b82a3c23e59fbac10149d110ad67950d24674792
[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-internal.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-internal.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
47 static gboolean is_usertype (MonoReflectionType *ref);
48 static MonoReflectionType *mono_reflection_type_resolve_user_types (MonoReflectionType *type);
49
50 typedef struct {
51         char *p;
52         char *buf;
53         char *end;
54 } SigBuffer;
55
56 #define TEXT_OFFSET 512
57 #define CLI_H_SIZE 136
58 #define FILE_ALIGN 512
59 #define VIRT_ALIGN 8192
60 #define START_TEXT_RVA  0x00002000
61
62 typedef struct {
63         MonoReflectionILGen *ilgen;
64         MonoReflectionType *rtype;
65         MonoArray *parameters;
66         MonoArray *generic_params;
67         MonoGenericContainer *generic_container;
68         MonoArray *pinfo;
69         MonoArray *opt_types;
70         guint32 attrs;
71         guint32 iattrs;
72         guint32 call_conv;
73         guint32 *table_idx; /* note: it's a pointer */
74         MonoArray *code;
75         MonoObject *type;
76         MonoString *name;
77         MonoBoolean init_locals;
78         MonoBoolean skip_visibility;
79         MonoArray *return_modreq;
80         MonoArray *return_modopt;
81         MonoArray *param_modreq;
82         MonoArray *param_modopt;
83         MonoArray *permissions;
84         MonoMethod *mhandle;
85         guint32 nrefs;
86         gpointer *refs;
87         /* for PInvoke */
88         int charset, extra_flags, native_cc;
89         MonoString *dll, *dllentry;
90 } ReflectionMethodBuilder;
91
92 typedef struct {
93         guint32 owner;
94         MonoReflectionGenericParam *gparam;
95 } GenericParamTableEntry;
96
97 const unsigned char table_sizes [MONO_TABLE_NUM] = {
98         MONO_MODULE_SIZE,
99         MONO_TYPEREF_SIZE,
100         MONO_TYPEDEF_SIZE,
101         0,
102         MONO_FIELD_SIZE,
103         0,
104         MONO_METHOD_SIZE,
105         0,
106         MONO_PARAM_SIZE,
107         MONO_INTERFACEIMPL_SIZE,
108         MONO_MEMBERREF_SIZE,    /* 0x0A */
109         MONO_CONSTANT_SIZE,
110         MONO_CUSTOM_ATTR_SIZE,
111         MONO_FIELD_MARSHAL_SIZE,
112         MONO_DECL_SECURITY_SIZE,
113         MONO_CLASS_LAYOUT_SIZE,
114         MONO_FIELD_LAYOUT_SIZE, /* 0x10 */
115         MONO_STAND_ALONE_SIGNATURE_SIZE,
116         MONO_EVENT_MAP_SIZE,
117         0,
118         MONO_EVENT_SIZE,
119         MONO_PROPERTY_MAP_SIZE,
120         0,
121         MONO_PROPERTY_SIZE,
122         MONO_METHOD_SEMA_SIZE,
123         MONO_METHODIMPL_SIZE,
124         MONO_MODULEREF_SIZE,    /* 0x1A */
125         MONO_TYPESPEC_SIZE,
126         MONO_IMPLMAP_SIZE,      
127         MONO_FIELD_RVA_SIZE,
128         0,
129         0,
130         MONO_ASSEMBLY_SIZE,     /* 0x20 */
131         MONO_ASSEMBLY_PROCESSOR_SIZE,
132         MONO_ASSEMBLYOS_SIZE,
133         MONO_ASSEMBLYREF_SIZE,
134         MONO_ASSEMBLYREFPROC_SIZE,
135         MONO_ASSEMBLYREFOS_SIZE,
136         MONO_FILE_SIZE,
137         MONO_EXP_TYPE_SIZE,
138         MONO_MANIFEST_SIZE,
139         MONO_NESTED_CLASS_SIZE,
140
141         MONO_GENERICPARAM_SIZE, /* 0x2A */
142         MONO_METHODSPEC_SIZE,
143         MONO_GENPARCONSTRAINT_SIZE
144
145 };
146
147 #ifndef DISABLE_REFLECTION_EMIT
148 static guint32 mono_image_get_methodref_token (MonoDynamicImage *assembly, MonoMethod *method, gboolean create_typespec);
149 static guint32 mono_image_get_methodbuilder_token (MonoDynamicImage *assembly, MonoReflectionMethodBuilder *mb, gboolean create_open_instance);
150 static guint32 mono_image_get_ctorbuilder_token (MonoDynamicImage *assembly, MonoReflectionCtorBuilder *cb);
151 static guint32 mono_image_get_sighelper_token (MonoDynamicImage *assembly, MonoReflectionSigHelper *helper);
152 static void    ensure_runtime_vtable (MonoClass *klass);
153 static gpointer resolve_object (MonoImage *image, MonoObject *obj, MonoClass **handle_class, MonoGenericContext *context);
154 static guint32 mono_image_get_methodref_token_for_methodbuilder (MonoDynamicImage *assembly, MonoReflectionMethodBuilder *method);
155 static guint32 encode_generic_method_sig (MonoDynamicImage *assembly, MonoGenericContext *context);
156 static gpointer register_assembly (MonoDomain *domain, MonoReflectionAssembly *res, MonoAssembly *assembly);
157 static void reflection_methodbuilder_from_method_builder (ReflectionMethodBuilder *rmb, MonoReflectionMethodBuilder *mb);
158 static void reflection_methodbuilder_from_ctor_builder (ReflectionMethodBuilder *rmb, MonoReflectionCtorBuilder *mb);
159 static guint32 create_generic_typespec (MonoDynamicImage *assembly, MonoReflectionTypeBuilder *tb);
160 #endif
161
162 static guint32 mono_image_typedef_or_ref (MonoDynamicImage *assembly, MonoType *type);
163 static guint32 mono_image_typedef_or_ref_full (MonoDynamicImage *assembly, MonoType *type, gboolean try_typespec);
164 static void    mono_image_get_generic_param_info (MonoReflectionGenericParam *gparam, guint32 owner, MonoDynamicImage *assembly);
165 static guint32 encode_marshal_blob (MonoDynamicImage *assembly, MonoReflectionMarshal *minfo);
166 static guint32 encode_constant (MonoDynamicImage *assembly, MonoObject *val, guint32 *ret_type);
167 static char*   type_get_qualified_name (MonoType *type, MonoAssembly *ass);
168 static void    encode_type (MonoDynamicImage *assembly, MonoType *type, SigBuffer *buf);
169 static void get_default_param_value_blobs (MonoMethod *method, char **blobs, guint32 *types);
170 static MonoReflectionType *mono_reflection_type_get_underlying_system_type (MonoReflectionType* t);
171 static MonoType* mono_reflection_get_type_with_rootimage (MonoImage *rootimage, MonoImage* image, MonoTypeNameParse *info, gboolean ignorecase, gboolean *type_resolve);
172 static MonoReflectionType* mono_reflection_type_resolve_user_types (MonoReflectionType *type);
173 static gboolean is_sre_array (MonoClass *class);
174 static gboolean is_sre_byref (MonoClass *class);
175 static gboolean is_sre_pointer (MonoClass *class);
176 static gboolean is_sre_type_builder (MonoClass *class);
177 static gboolean is_sre_method_builder (MonoClass *class);
178 static gboolean is_sre_ctor_builder (MonoClass *class);
179 static gboolean is_sre_field_builder (MonoClass *class);
180 static gboolean is_sr_mono_method (MonoClass *class);
181 static gboolean is_sr_mono_cmethod (MonoClass *class);
182 static gboolean is_sr_mono_generic_method (MonoClass *class);
183 static gboolean is_sr_mono_generic_cmethod (MonoClass *class);
184 static gboolean is_sr_mono_field (MonoClass *class);
185 static gboolean is_sr_mono_property (MonoClass *class);
186 static gboolean is_sre_method_on_tb_inst (MonoClass *class);
187 static gboolean is_sre_ctor_on_tb_inst (MonoClass *class);
188
189 static guint32 mono_image_get_methodspec_token (MonoDynamicImage *assembly, MonoMethod *method);
190 static guint32 mono_image_get_inflated_method_token (MonoDynamicImage *assembly, MonoMethod *m);
191 static MonoMethod * inflate_method (MonoReflectionType *type, MonoObject *obj);
192
193 static guint32 create_typespec (MonoDynamicImage *assembly, MonoType *type);
194 static void init_type_builder_generics (MonoObject *type);
195
196 #define RESOLVE_TYPE(type) do { type = (void*)mono_reflection_type_resolve_user_types ((MonoReflectionType*)type); } while (0)
197 #define RESOLVE_ARRAY_TYPE_ELEMENT(array, index) do {   \
198         MonoReflectionType *__type = mono_array_get (array, MonoReflectionType*, index);        \
199         __type = mono_reflection_type_resolve_user_types (__type);      \
200         mono_array_set (arr, MonoReflectionType*, index, __type);       \
201 } while (0)
202
203 #define mono_type_array_get_and_resolve(array, index) mono_reflection_type_get_handle ((MonoReflectionType*)mono_array_get (array, gpointer, index))
204
205 #define CHECK_ADD4_OVERFLOW_UN(a, b) ((guint32)(0xFFFFFFFFU) - (guint32)(b) < (guint32)(a))
206 #define CHECK_ADD8_OVERFLOW_UN(a, b) ((guint64)(0xFFFFFFFFFFFFFFFFUL) - (guint64)(b) < (guint64)(a))
207
208 #if SIZEOF_VOID_P == 4
209 #define CHECK_ADDP_OVERFLOW_UN(a,b) CHECK_ADD4_OVERFLOW_UN(a, b)
210 #else
211 #define CHECK_ADDP_OVERFLOW_UN(a,b) CHECK_ADD8_OVERFLOW_UN(a, b)
212 #endif
213
214 #define ADDP_IS_GREATER_OR_OVF(a, b, c) (((a) + (b) > (c)) || CHECK_ADDP_OVERFLOW_UN (a, b))
215 #define ADD_IS_GREATER_OR_OVF(a, b, c) (((a) + (b) > (c)) || CHECK_ADD4_OVERFLOW_UN (a, b))
216
217
218 void
219 mono_reflection_init (void)
220 {
221 }
222
223 static void
224 sigbuffer_init (SigBuffer *buf, int size)
225 {
226         buf->buf = g_malloc (size);
227         buf->p = buf->buf;
228         buf->end = buf->buf + size;
229 }
230
231 static void
232 sigbuffer_make_room (SigBuffer *buf, int size)
233 {
234         if (buf->end - buf->p < size) {
235                 int new_size = buf->end - buf->buf + size + 32;
236                 char *p = g_realloc (buf->buf, new_size);
237                 size = buf->p - buf->buf;
238                 buf->buf = p;
239                 buf->p = p + size;
240                 buf->end = buf->buf + new_size;
241         }
242 }
243
244 static void
245 sigbuffer_add_value (SigBuffer *buf, guint32 val)
246 {
247         sigbuffer_make_room (buf, 6);
248         mono_metadata_encode_value (val, buf->p, &buf->p);
249 }
250
251 static void
252 sigbuffer_add_byte (SigBuffer *buf, guint8 val)
253 {
254         sigbuffer_make_room (buf, 1);
255         buf->p [0] = val;
256         buf->p++;
257 }
258
259 static void
260 sigbuffer_add_mem (SigBuffer *buf, char *p, guint32 size)
261 {
262         sigbuffer_make_room (buf, size);
263         memcpy (buf->p, p, size);
264         buf->p += size;
265 }
266
267 static void
268 sigbuffer_free (SigBuffer *buf)
269 {
270         g_free (buf->buf);
271 }
272
273 #ifndef DISABLE_REFLECTION_EMIT
274 /**
275  * mp_g_alloc:
276  *
277  * Allocate memory from the @image mempool if it is non-NULL. Otherwise, allocate memory
278  * from the C heap.
279  */
280 static gpointer
281 image_g_malloc (MonoImage *image, guint size)
282 {
283         if (image)
284                 return mono_image_alloc (image, size);
285         else
286                 return g_malloc (size);
287 }
288 #endif /* !DISABLE_REFLECTION_EMIT */
289
290 /**
291  * image_g_alloc0:
292  *
293  * Allocate memory from the @image mempool if it is non-NULL. Otherwise, allocate memory
294  * from the C heap.
295  */
296 static gpointer
297 image_g_malloc0 (MonoImage *image, guint size)
298 {
299         if (image)
300                 return mono_image_alloc0 (image, size);
301         else
302                 return g_malloc0 (size);
303 }
304
305 #ifndef DISABLE_REFLECTION_EMIT
306 static char*
307 image_strdup (MonoImage *image, const char *s)
308 {
309         if (image)
310                 return mono_image_strdup (image, s);
311         else
312                 return g_strdup (s);
313 }
314 #endif
315
316 #define image_g_new(image,struct_type, n_structs)               \
317     ((struct_type *) image_g_malloc (image, ((gsize) sizeof (struct_type)) * ((gsize) (n_structs))))
318
319 #define image_g_new0(image,struct_type, n_structs)              \
320     ((struct_type *) image_g_malloc0 (image, ((gsize) sizeof (struct_type)) * ((gsize) (n_structs))))
321
322
323 static void
324 alloc_table (MonoDynamicTable *table, guint nrows)
325 {
326         table->rows = nrows;
327         g_assert (table->columns);
328         if (nrows + 1 >= table->alloc_rows) {
329                 while (nrows + 1 >= table->alloc_rows) {
330                         if (table->alloc_rows == 0)
331                                 table->alloc_rows = 16;
332                         else
333                                 table->alloc_rows *= 2;
334                 }
335
336                 table->values = g_renew (guint32, table->values, (table->alloc_rows) * table->columns);
337         }
338 }
339
340 static void
341 make_room_in_stream (MonoDynamicStream *stream, int size)
342 {
343         if (size <= stream->alloc_size)
344                 return;
345         
346         while (stream->alloc_size <= size) {
347                 if (stream->alloc_size < 4096)
348                         stream->alloc_size = 4096;
349                 else
350                         stream->alloc_size *= 2;
351         }
352         
353         stream->data = g_realloc (stream->data, stream->alloc_size);
354 }
355
356 static guint32
357 string_heap_insert (MonoDynamicStream *sh, const char *str)
358 {
359         guint32 idx;
360         guint32 len;
361         gpointer oldkey, oldval;
362
363         if (g_hash_table_lookup_extended (sh->hash, str, &oldkey, &oldval))
364                 return GPOINTER_TO_UINT (oldval);
365
366         len = strlen (str) + 1;
367         idx = sh->index;
368         
369         make_room_in_stream (sh, idx + len);
370
371         /*
372          * We strdup the string even if we already copy them in sh->data
373          * so that the string pointers in the hash remain valid even if
374          * we need to realloc sh->data. We may want to avoid that later.
375          */
376         g_hash_table_insert (sh->hash, g_strdup (str), GUINT_TO_POINTER (idx));
377         memcpy (sh->data + idx, str, len);
378         sh->index += len;
379         return idx;
380 }
381
382 static guint32
383 string_heap_insert_mstring (MonoDynamicStream *sh, MonoString *str)
384 {
385         char *name = mono_string_to_utf8 (str);
386         guint32 idx;
387         idx = string_heap_insert (sh, name);
388         g_free (name);
389         return idx;
390 }
391
392 #ifndef DISABLE_REFLECTION_EMIT
393 static void
394 string_heap_init (MonoDynamicStream *sh)
395 {
396         sh->index = 0;
397         sh->alloc_size = 4096;
398         sh->data = g_malloc (4096);
399         sh->hash = g_hash_table_new_full (g_str_hash, g_str_equal, g_free, NULL);
400         string_heap_insert (sh, "");
401 }
402 #endif
403
404 static guint32
405 mono_image_add_stream_data (MonoDynamicStream *stream, const char *data, guint32 len)
406 {
407         guint32 idx;
408         
409         make_room_in_stream (stream, stream->index + len);
410         memcpy (stream->data + stream->index, data, len);
411         idx = stream->index;
412         stream->index += len;
413         /* 
414          * align index? Not without adding an additional param that controls it since
415          * we may store a blob value in pieces.
416          */
417         return idx;
418 }
419
420 static guint32
421 mono_image_add_stream_zero (MonoDynamicStream *stream, guint32 len)
422 {
423         guint32 idx;
424         
425         make_room_in_stream (stream, stream->index + len);
426         memset (stream->data + stream->index, 0, len);
427         idx = stream->index;
428         stream->index += len;
429         return idx;
430 }
431
432 static void
433 stream_data_align (MonoDynamicStream *stream)
434 {
435         char buf [4] = {0};
436         guint32 count = stream->index % 4;
437
438         /* we assume the stream data will be aligned */
439         if (count)
440                 mono_image_add_stream_data (stream, buf, 4 - count);
441 }
442
443 #ifndef DISABLE_REFLECTION_EMIT
444 static int
445 mono_blob_entry_hash (const char* str)
446 {
447         guint len, h;
448         const char *end;
449         len = mono_metadata_decode_blob_size (str, &str);
450         if (len > 0) {
451                 end = str + len;
452                 h = *str;
453                 for (str += 1; str < end; str++)
454                         h = (h << 5) - h + *str;
455                 return h;
456         } else {
457                 return 0;
458         }
459 }
460
461 static gboolean
462 mono_blob_entry_equal (const char *str1, const char *str2) {
463         int len, len2;
464         const char *end1;
465         const char *end2;
466         len = mono_metadata_decode_blob_size (str1, &end1);
467         len2 = mono_metadata_decode_blob_size (str2, &end2);
468         if (len != len2)
469                 return 0;
470         return memcmp (end1, end2, len) == 0;
471 }
472 #endif
473 static guint32
474 add_to_blob_cached (MonoDynamicImage *assembly, char *b1, int s1, char *b2, int s2)
475 {
476         guint32 idx;
477         char *copy;
478         gpointer oldkey, oldval;
479
480         copy = g_malloc (s1+s2);
481         memcpy (copy, b1, s1);
482         memcpy (copy + s1, b2, s2);
483         if (g_hash_table_lookup_extended (assembly->blob_cache, copy, &oldkey, &oldval)) {
484                 g_free (copy);
485                 idx = GPOINTER_TO_UINT (oldval);
486         } else {
487                 idx = mono_image_add_stream_data (&assembly->blob, b1, s1);
488                 mono_image_add_stream_data (&assembly->blob, b2, s2);
489                 g_hash_table_insert (assembly->blob_cache, copy, GUINT_TO_POINTER (idx));
490         }
491         return idx;
492 }
493
494 static guint32
495 sigbuffer_add_to_blob_cached (MonoDynamicImage *assembly, SigBuffer *buf)
496 {
497         char blob_size [8];
498         char *b = blob_size;
499         guint32 size = buf->p - buf->buf;
500         /* store length */
501         g_assert (size <= (buf->end - buf->buf));
502         mono_metadata_encode_value (size, b, &b);
503         return add_to_blob_cached (assembly, blob_size, b-blob_size, buf->buf, size);
504 }
505
506 /*
507  * Copy len * nelem bytes from val to dest, swapping bytes to LE if necessary.
508  * dest may be misaligned.
509  */
510 static void
511 swap_with_size (char *dest, const char* val, int len, int nelem) {
512 #if G_BYTE_ORDER != G_LITTLE_ENDIAN
513         int elem;
514
515         for (elem = 0; elem < nelem; ++elem) {
516                 switch (len) {
517                 case 1:
518                         *dest = *val;
519                         break;
520                 case 2:
521                         dest [0] = val [1];
522                         dest [1] = val [0];
523                         break;
524                 case 4:
525                         dest [0] = val [3];
526                         dest [1] = val [2];
527                         dest [2] = val [1];
528                         dest [3] = val [0];
529                         break;
530                 case 8:
531                         dest [0] = val [7];
532                         dest [1] = val [6];
533                         dest [2] = val [5];
534                         dest [3] = val [4];
535                         dest [4] = val [3];
536                         dest [5] = val [2];
537                         dest [6] = val [1];
538                         dest [7] = val [0];
539                         break;
540                 default:
541                         g_assert_not_reached ();
542                 }
543                 dest += len;
544                 val += len;
545         }
546 #else
547         memcpy (dest, val, len * nelem);
548 #endif
549 }
550
551 static guint32
552 add_mono_string_to_blob_cached (MonoDynamicImage *assembly, MonoString *str)
553 {
554         char blob_size [64];
555         char *b = blob_size;
556         guint32 idx = 0, len;
557
558         len = str->length * 2;
559         mono_metadata_encode_value (len, b, &b);
560 #if G_BYTE_ORDER != G_LITTLE_ENDIAN
561         {
562                 char *swapped = g_malloc (2 * mono_string_length (str));
563                 const char *p = (const char*)mono_string_chars (str);
564
565                 swap_with_size (swapped, p, 2, mono_string_length (str));
566                 idx = add_to_blob_cached (assembly, blob_size, b-blob_size, swapped, len);
567                 g_free (swapped);
568         }
569 #else
570         idx = add_to_blob_cached (assembly, blob_size, b-blob_size, (char*)mono_string_chars (str), len);
571 #endif
572         return idx;
573 }
574
575 #ifndef DISABLE_REFLECTION_EMIT
576 static MonoClass *
577 default_class_from_mono_type (MonoType *type)
578 {
579         switch (type->type) {
580         case MONO_TYPE_OBJECT:
581                 return mono_defaults.object_class;
582         case MONO_TYPE_VOID:
583                 return mono_defaults.void_class;
584         case MONO_TYPE_BOOLEAN:
585                 return mono_defaults.boolean_class;
586         case MONO_TYPE_CHAR:
587                 return mono_defaults.char_class;
588         case MONO_TYPE_I1:
589                 return mono_defaults.sbyte_class;
590         case MONO_TYPE_U1:
591                 return mono_defaults.byte_class;
592         case MONO_TYPE_I2:
593                 return mono_defaults.int16_class;
594         case MONO_TYPE_U2:
595                 return mono_defaults.uint16_class;
596         case MONO_TYPE_I4:
597                 return mono_defaults.int32_class;
598         case MONO_TYPE_U4:
599                 return mono_defaults.uint32_class;
600         case MONO_TYPE_I:
601                 return mono_defaults.int_class;
602         case MONO_TYPE_U:
603                 return mono_defaults.uint_class;
604         case MONO_TYPE_I8:
605                 return mono_defaults.int64_class;
606         case MONO_TYPE_U8:
607                 return mono_defaults.uint64_class;
608         case MONO_TYPE_R4:
609                 return mono_defaults.single_class;
610         case MONO_TYPE_R8:
611                 return mono_defaults.double_class;
612         case MONO_TYPE_STRING:
613                 return mono_defaults.string_class;
614         default:
615                 g_warning ("default_class_from_mono_type: implement me 0x%02x\n", type->type);
616                 g_assert_not_reached ();
617         }
618         
619         return NULL;
620 }
621 #endif
622
623 /*
624  * mono_class_get_ref_info:
625  *
626  *   Return the type builder/generic param builder corresponding to KLASS, if it exists.
627  */
628 gpointer
629 mono_class_get_ref_info (MonoClass *klass)
630 {
631         if (klass->ref_info_handle == 0)
632                 return NULL;
633         else
634                 return mono_gchandle_get_target (klass->ref_info_handle);
635 }
636
637 void
638 mono_class_set_ref_info (MonoClass *klass, gpointer obj)
639 {
640         klass->ref_info_handle = mono_gchandle_new ((MonoObject*)obj, FALSE);
641         g_assert (klass->ref_info_handle != 0);
642 }
643
644 void
645 mono_class_free_ref_info (MonoClass *klass)
646 {
647         if (klass->ref_info_handle) {
648                 mono_gchandle_free (klass->ref_info_handle);
649                 klass->ref_info_handle = 0;
650         }
651 }
652
653 static void
654 encode_generic_class (MonoDynamicImage *assembly, MonoGenericClass *gclass, SigBuffer *buf)
655 {
656         int i;
657         MonoGenericInst *class_inst;
658         MonoClass *klass;
659
660         g_assert (gclass);
661
662         class_inst = gclass->context.class_inst;
663
664         sigbuffer_add_value (buf, MONO_TYPE_GENERICINST);
665         klass = gclass->container_class;
666         sigbuffer_add_value (buf, klass->byval_arg.type);
667         sigbuffer_add_value (buf, mono_image_typedef_or_ref_full (assembly, &klass->byval_arg, FALSE));
668
669         sigbuffer_add_value (buf, class_inst->type_argc);
670         for (i = 0; i < class_inst->type_argc; ++i)
671                 encode_type (assembly, class_inst->type_argv [i], buf);
672
673 }
674
675 static void
676 encode_type (MonoDynamicImage *assembly, MonoType *type, SigBuffer *buf)
677 {
678         if (!type) {
679                 g_assert_not_reached ();
680                 return;
681         }
682                 
683         if (type->byref)
684                 sigbuffer_add_value (buf, MONO_TYPE_BYREF);
685
686         switch (type->type){
687         case MONO_TYPE_VOID:
688         case MONO_TYPE_BOOLEAN:
689         case MONO_TYPE_CHAR:
690         case MONO_TYPE_I1:
691         case MONO_TYPE_U1:
692         case MONO_TYPE_I2:
693         case MONO_TYPE_U2:
694         case MONO_TYPE_I4:
695         case MONO_TYPE_U4:
696         case MONO_TYPE_I8:
697         case MONO_TYPE_U8:
698         case MONO_TYPE_R4:
699         case MONO_TYPE_R8:
700         case MONO_TYPE_I:
701         case MONO_TYPE_U:
702         case MONO_TYPE_STRING:
703         case MONO_TYPE_OBJECT:
704         case MONO_TYPE_TYPEDBYREF:
705                 sigbuffer_add_value (buf, type->type);
706                 break;
707         case MONO_TYPE_PTR:
708                 sigbuffer_add_value (buf, type->type);
709                 encode_type (assembly, type->data.type, buf);
710                 break;
711         case MONO_TYPE_SZARRAY:
712                 sigbuffer_add_value (buf, type->type);
713                 encode_type (assembly, &type->data.klass->byval_arg, buf);
714                 break;
715         case MONO_TYPE_VALUETYPE:
716         case MONO_TYPE_CLASS: {
717                 MonoClass *k = mono_class_from_mono_type (type);
718
719                 if (k->generic_container) {
720                         MonoGenericClass *gclass = mono_metadata_lookup_generic_class (k, k->generic_container->context.class_inst, TRUE);
721                         encode_generic_class (assembly, gclass, buf);
722                 } else {
723                         /*
724                          * Make sure we use the correct type.
725                          */
726                         sigbuffer_add_value (buf, k->byval_arg.type);
727                         /*
728                          * ensure only non-byref gets passed to mono_image_typedef_or_ref(),
729                          * otherwise two typerefs could point to the same type, leading to
730                          * verification errors.
731                          */
732                         sigbuffer_add_value (buf, mono_image_typedef_or_ref (assembly, &k->byval_arg));
733                 }
734                 break;
735         }
736         case MONO_TYPE_ARRAY:
737                 sigbuffer_add_value (buf, type->type);
738                 encode_type (assembly, &type->data.array->eklass->byval_arg, buf);
739                 sigbuffer_add_value (buf, type->data.array->rank);
740                 sigbuffer_add_value (buf, 0); /* FIXME: set to 0 for now */
741                 sigbuffer_add_value (buf, 0);
742                 break;
743         case MONO_TYPE_GENERICINST:
744                 encode_generic_class (assembly, type->data.generic_class, buf);
745                 break;
746         case MONO_TYPE_VAR:
747         case MONO_TYPE_MVAR:
748                 sigbuffer_add_value (buf, type->type);
749                 sigbuffer_add_value (buf, mono_type_get_generic_param_num (type));
750                 break;
751         default:
752                 g_error ("need to encode type %x", type->type);
753         }
754 }
755
756 static void
757 encode_reflection_type (MonoDynamicImage *assembly, MonoReflectionType *type, SigBuffer *buf)
758 {
759         if (!type) {
760                 sigbuffer_add_value (buf, MONO_TYPE_VOID);
761                 return;
762         }
763
764         encode_type (assembly, mono_reflection_type_get_handle (type), buf);
765 }
766
767 static void
768 encode_custom_modifiers (MonoDynamicImage *assembly, MonoArray *modreq, MonoArray *modopt, SigBuffer *buf)
769 {
770         int i;
771
772         if (modreq) {
773                 for (i = 0; i < mono_array_length (modreq); ++i) {
774                         MonoType *mod = mono_type_array_get_and_resolve (modreq, i);
775                         sigbuffer_add_byte (buf, MONO_TYPE_CMOD_REQD);
776                         sigbuffer_add_value (buf, mono_image_typedef_or_ref (assembly, mod));
777                 }
778         }
779         if (modopt) {
780                 for (i = 0; i < mono_array_length (modopt); ++i) {
781                         MonoType *mod = mono_type_array_get_and_resolve (modopt, i);
782                         sigbuffer_add_byte (buf, MONO_TYPE_CMOD_OPT);
783                         sigbuffer_add_value (buf, mono_image_typedef_or_ref (assembly, mod));
784                 }
785         }
786 }
787
788 #ifndef DISABLE_REFLECTION_EMIT
789 static guint32
790 method_encode_signature (MonoDynamicImage *assembly, MonoMethodSignature *sig)
791 {
792         SigBuffer buf;
793         int i;
794         guint32 nparams =  sig->param_count;
795         guint32 idx;
796
797         if (!assembly->save)
798                 return 0;
799
800         sigbuffer_init (&buf, 32);
801         /*
802          * FIXME: vararg, explicit_this, differenc call_conv values...
803          */
804         idx = sig->call_convention;
805         if (sig->hasthis)
806                 idx |= 0x20; /* hasthis */
807         if (sig->generic_param_count)
808                 idx |= 0x10; /* generic */
809         sigbuffer_add_byte (&buf, idx);
810         if (sig->generic_param_count)
811                 sigbuffer_add_value (&buf, sig->generic_param_count);
812         sigbuffer_add_value (&buf, nparams);
813         encode_type (assembly, sig->ret, &buf);
814         for (i = 0; i < nparams; ++i) {
815                 if (i == sig->sentinelpos)
816                         sigbuffer_add_byte (&buf, MONO_TYPE_SENTINEL);
817                 encode_type (assembly, sig->params [i], &buf);
818         }
819         idx = sigbuffer_add_to_blob_cached (assembly, &buf);
820         sigbuffer_free (&buf);
821         return idx;
822 }
823 #endif
824
825 static guint32
826 method_builder_encode_signature (MonoDynamicImage *assembly, ReflectionMethodBuilder *mb)
827 {
828         /*
829          * FIXME: reuse code from method_encode_signature().
830          */
831         SigBuffer buf;
832         int i;
833         guint32 nparams =  mb->parameters ? mono_array_length (mb->parameters): 0;
834         guint32 ngparams = mb->generic_params ? mono_array_length (mb->generic_params): 0;
835         guint32 notypes = mb->opt_types ? mono_array_length (mb->opt_types): 0;
836         guint32 idx;
837
838         sigbuffer_init (&buf, 32);
839         /* LAMESPEC: all the call conv spec is foobared */
840         idx = mb->call_conv & 0x60; /* has-this, explicit-this */
841         if (mb->call_conv & 2)
842                 idx |= 0x5; /* vararg */
843         if (!(mb->attrs & METHOD_ATTRIBUTE_STATIC))
844                 idx |= 0x20; /* hasthis */
845         if (ngparams)
846                 idx |= 0x10; /* generic */
847         sigbuffer_add_byte (&buf, idx);
848         if (ngparams)
849                 sigbuffer_add_value (&buf, ngparams);
850         sigbuffer_add_value (&buf, nparams + notypes);
851         encode_custom_modifiers (assembly, mb->return_modreq, mb->return_modopt, &buf);
852         encode_reflection_type (assembly, mb->rtype, &buf);
853         for (i = 0; i < nparams; ++i) {
854                 MonoArray *modreq = NULL;
855                 MonoArray *modopt = NULL;
856                 MonoReflectionType *pt;
857
858                 if (mb->param_modreq && (i < mono_array_length (mb->param_modreq)))
859                         modreq = mono_array_get (mb->param_modreq, MonoArray*, i);
860                 if (mb->param_modopt && (i < mono_array_length (mb->param_modopt)))
861                         modopt = mono_array_get (mb->param_modopt, MonoArray*, i);
862                 encode_custom_modifiers (assembly, modreq, modopt, &buf);
863                 pt = mono_array_get (mb->parameters, MonoReflectionType*, i);
864                 encode_reflection_type (assembly, pt, &buf);
865         }
866         if (notypes)
867                 sigbuffer_add_byte (&buf, MONO_TYPE_SENTINEL);
868         for (i = 0; i < notypes; ++i) {
869                 MonoReflectionType *pt;
870
871                 pt = mono_array_get (mb->opt_types, MonoReflectionType*, i);
872                 encode_reflection_type (assembly, pt, &buf);
873         }
874
875         idx = sigbuffer_add_to_blob_cached (assembly, &buf);
876         sigbuffer_free (&buf);
877         return idx;
878 }
879
880 static guint32
881 encode_locals (MonoDynamicImage *assembly, MonoReflectionILGen *ilgen)
882 {
883         MonoDynamicTable *table;
884         guint32 *values;
885         guint32 idx, sig_idx;
886         guint nl = mono_array_length (ilgen->locals);
887         SigBuffer buf;
888         int i;
889
890         sigbuffer_init (&buf, 32);
891         sigbuffer_add_value (&buf, 0x07);
892         sigbuffer_add_value (&buf, nl);
893         for (i = 0; i < nl; ++i) {
894                 MonoReflectionLocalBuilder *lb = mono_array_get (ilgen->locals, MonoReflectionLocalBuilder*, i);
895                 
896                 if (lb->is_pinned)
897                         sigbuffer_add_value (&buf, MONO_TYPE_PINNED);
898                 
899                 encode_reflection_type (assembly, (MonoReflectionType*)lb->type, &buf);
900         }
901         sig_idx = sigbuffer_add_to_blob_cached (assembly, &buf);
902         sigbuffer_free (&buf);
903
904         if (assembly->standalonesig_cache == NULL)
905                 assembly->standalonesig_cache = g_hash_table_new (NULL, NULL);
906         idx = GPOINTER_TO_UINT (g_hash_table_lookup (assembly->standalonesig_cache, GUINT_TO_POINTER (sig_idx)));
907         if (idx)
908                 return idx;
909
910         table = &assembly->tables [MONO_TABLE_STANDALONESIG];
911         idx = table->next_idx ++;
912         table->rows ++;
913         alloc_table (table, table->rows);
914         values = table->values + idx * MONO_STAND_ALONE_SIGNATURE_SIZE;
915
916         values [MONO_STAND_ALONE_SIGNATURE] = sig_idx;
917
918         g_hash_table_insert (assembly->standalonesig_cache, GUINT_TO_POINTER (sig_idx), GUINT_TO_POINTER (idx));
919
920         return idx;
921 }
922
923 static guint32
924 method_count_clauses (MonoReflectionILGen *ilgen)
925 {
926         guint32 num_clauses = 0;
927         int i;
928
929         MonoILExceptionInfo *ex_info;
930         for (i = 0; i < mono_array_length (ilgen->ex_handlers); ++i) {
931                 ex_info = (MonoILExceptionInfo*)mono_array_addr (ilgen->ex_handlers, MonoILExceptionInfo, i);
932                 if (ex_info->handlers)
933                         num_clauses += mono_array_length (ex_info->handlers);
934                 else
935                         num_clauses++;
936         }
937
938         return num_clauses;
939 }
940
941 #ifndef DISABLE_REFLECTION_EMIT
942 static MonoExceptionClause*
943 method_encode_clauses (MonoImage *image, MonoDynamicImage *assembly, MonoReflectionILGen *ilgen, guint32 num_clauses)
944 {
945         MonoExceptionClause *clauses;
946         MonoExceptionClause *clause;
947         MonoILExceptionInfo *ex_info;
948         MonoILExceptionBlock *ex_block;
949         guint32 finally_start;
950         int i, j, clause_index;;
951
952         clauses = image_g_new0 (image, MonoExceptionClause, num_clauses);
953
954         clause_index = 0;
955         for (i = mono_array_length (ilgen->ex_handlers) - 1; i >= 0; --i) {
956                 ex_info = (MonoILExceptionInfo*)mono_array_addr (ilgen->ex_handlers, MonoILExceptionInfo, i);
957                 finally_start = ex_info->start + ex_info->len;
958                 if (!ex_info->handlers)
959                         continue;
960                 for (j = 0; j < mono_array_length (ex_info->handlers); ++j) {
961                         ex_block = (MonoILExceptionBlock*)mono_array_addr (ex_info->handlers, MonoILExceptionBlock, j);
962                         clause = &(clauses [clause_index]);
963
964                         clause->flags = ex_block->type;
965                         clause->try_offset = ex_info->start;
966
967                         if (ex_block->type == MONO_EXCEPTION_CLAUSE_FINALLY)
968                                 clause->try_len = finally_start - ex_info->start;
969                         else
970                                 clause->try_len = ex_info->len;
971                         clause->handler_offset = ex_block->start;
972                         clause->handler_len = ex_block->len;
973                         if (ex_block->extype) {
974                                 clause->data.catch_class = mono_class_from_mono_type (mono_reflection_type_get_handle ((MonoReflectionType*)ex_block->extype));
975                         } else {
976                                 if (ex_block->type == MONO_EXCEPTION_CLAUSE_FILTER)
977                                         clause->data.filter_offset = ex_block->filter_offset;
978                                 else
979                                         clause->data.filter_offset = 0;
980                         }
981                         finally_start = ex_block->start + ex_block->len;
982
983                         clause_index ++;
984                 }
985         }
986
987         return clauses;
988 }
989 #endif /* !DISABLE_REFLECTION_EMIT */
990
991 static guint32
992 method_encode_code (MonoDynamicImage *assembly, ReflectionMethodBuilder *mb)
993 {
994         char flags = 0;
995         guint32 idx;
996         guint32 code_size;
997         gint32 max_stack, i;
998         gint32 num_locals = 0;
999         gint32 num_exception = 0;
1000         gint maybe_small;
1001         guint32 fat_flags;
1002         char fat_header [12];
1003         guint32 int_value;
1004         guint16 short_value;
1005         guint32 local_sig = 0;
1006         guint32 header_size = 12;
1007         MonoArray *code;
1008
1009         if ((mb->attrs & (METHOD_ATTRIBUTE_PINVOKE_IMPL | METHOD_ATTRIBUTE_ABSTRACT)) ||
1010                         (mb->iattrs & (METHOD_IMPL_ATTRIBUTE_INTERNAL_CALL | METHOD_IMPL_ATTRIBUTE_RUNTIME)))
1011                 return 0;
1012
1013         /*if (mb->name)
1014                 g_print ("Encode method %s\n", mono_string_to_utf8 (mb->name));*/
1015         if (mb->ilgen) {
1016                 code = mb->ilgen->code;
1017                 code_size = mb->ilgen->code_len;
1018                 max_stack = mb->ilgen->max_stack;
1019                 num_locals = mb->ilgen->locals ? mono_array_length (mb->ilgen->locals) : 0;
1020                 if (mb->ilgen->ex_handlers)
1021                         num_exception = method_count_clauses (mb->ilgen);
1022         } else {
1023                 code = mb->code;
1024                 if (code == NULL){
1025                         char *name = mono_string_to_utf8 (mb->name);
1026                         char *str = g_strdup_printf ("Method %s does not have any IL associated", name);
1027                         MonoException *exception = mono_get_exception_argument (NULL, "a method does not have any IL associated");
1028                         g_free (str);
1029                         g_free (name);
1030                         mono_raise_exception (exception);
1031                 }
1032
1033                 code_size = mono_array_length (code);
1034                 max_stack = 8; /* we probably need to run a verifier on the code... */
1035         }
1036
1037         stream_data_align (&assembly->code);
1038
1039         /* check for exceptions, maxstack, locals */
1040         maybe_small = (max_stack <= 8) && (!num_locals) && (!num_exception);
1041         if (maybe_small) {
1042                 if (code_size < 64 && !(code_size & 1)) {
1043                         flags = (code_size << 2) | 0x2;
1044                 } else if (code_size < 32 && (code_size & 1)) {
1045                         flags = (code_size << 2) | 0x6; /* LAMESPEC: see metadata.c */
1046                 } else {
1047                         goto fat_header;
1048                 }
1049                 idx = mono_image_add_stream_data (&assembly->code, &flags, 1);
1050                 /* add to the fixup todo list */
1051                 if (mb->ilgen && mb->ilgen->num_token_fixups)
1052                         mono_g_hash_table_insert (assembly->token_fixups, mb->ilgen, GUINT_TO_POINTER (idx + 1));
1053                 mono_image_add_stream_data (&assembly->code, mono_array_addr (code, char, 0), code_size);
1054                 return assembly->text_rva + idx;
1055         } 
1056 fat_header:
1057         if (num_locals)
1058                 local_sig = MONO_TOKEN_SIGNATURE | encode_locals (assembly, mb->ilgen);
1059         /* 
1060          * FIXME: need to set also the header size in fat_flags.
1061          * (and more sects and init locals flags)
1062          */
1063         fat_flags =  0x03;
1064         if (num_exception)
1065                 fat_flags |= METHOD_HEADER_MORE_SECTS;
1066         if (mb->init_locals)
1067                 fat_flags |= METHOD_HEADER_INIT_LOCALS;
1068         fat_header [0] = fat_flags;
1069         fat_header [1] = (header_size / 4 ) << 4;
1070         short_value = GUINT16_TO_LE (max_stack);
1071         memcpy (fat_header + 2, &short_value, 2);
1072         int_value = GUINT32_TO_LE (code_size);
1073         memcpy (fat_header + 4, &int_value, 4);
1074         int_value = GUINT32_TO_LE (local_sig);
1075         memcpy (fat_header + 8, &int_value, 4);
1076         idx = mono_image_add_stream_data (&assembly->code, fat_header, 12);
1077         /* add to the fixup todo list */
1078         if (mb->ilgen && mb->ilgen->num_token_fixups)
1079                 mono_g_hash_table_insert (assembly->token_fixups, mb->ilgen, GUINT_TO_POINTER (idx + 12));
1080         
1081         mono_image_add_stream_data (&assembly->code, mono_array_addr (code, char, 0), code_size);
1082         if (num_exception) {
1083                 unsigned char sheader [4];
1084                 MonoILExceptionInfo * ex_info;
1085                 MonoILExceptionBlock * ex_block;
1086                 int j;
1087
1088                 stream_data_align (&assembly->code);
1089                 /* always use fat format for now */
1090                 sheader [0] = METHOD_HEADER_SECTION_FAT_FORMAT | METHOD_HEADER_SECTION_EHTABLE;
1091                 num_exception *= 6 * sizeof (guint32);
1092                 num_exception += 4; /* include the size of the header */
1093                 sheader [1] = num_exception & 0xff;
1094                 sheader [2] = (num_exception >> 8) & 0xff;
1095                 sheader [3] = (num_exception >> 16) & 0xff;
1096                 mono_image_add_stream_data (&assembly->code, (char*)sheader, 4);
1097                 /* fat header, so we are already aligned */
1098                 /* reverse order */
1099                 for (i = mono_array_length (mb->ilgen->ex_handlers) - 1; i >= 0; --i) {
1100                         ex_info = (MonoILExceptionInfo *)mono_array_addr (mb->ilgen->ex_handlers, MonoILExceptionInfo, i);
1101                         if (ex_info->handlers) {
1102                                 int finally_start = ex_info->start + ex_info->len;
1103                                 for (j = 0; j < mono_array_length (ex_info->handlers); ++j) {
1104                                         guint32 val;
1105                                         ex_block = (MonoILExceptionBlock*)mono_array_addr (ex_info->handlers, MonoILExceptionBlock, j);
1106                                         /* the flags */
1107                                         val = GUINT32_TO_LE (ex_block->type);
1108                                         mono_image_add_stream_data (&assembly->code, (char*)&val, sizeof (guint32));
1109                                         /* try offset */
1110                                         val = GUINT32_TO_LE (ex_info->start);
1111                                         mono_image_add_stream_data (&assembly->code, (char*)&val, sizeof (guint32));
1112                                         /* need fault, too, probably */
1113                                         if (ex_block->type == MONO_EXCEPTION_CLAUSE_FINALLY)
1114                                                 val = GUINT32_TO_LE (finally_start - ex_info->start);
1115                                         else
1116                                                 val = GUINT32_TO_LE (ex_info->len);
1117                                         mono_image_add_stream_data (&assembly->code, (char*)&val, sizeof (guint32));
1118                                         /* handler offset */
1119                                         val = GUINT32_TO_LE (ex_block->start);
1120                                         mono_image_add_stream_data (&assembly->code, (char*)&val, sizeof (guint32));
1121                                         /* handler len */
1122                                         val = GUINT32_TO_LE (ex_block->len);
1123                                         mono_image_add_stream_data (&assembly->code, (char*)&val, sizeof (guint32));
1124                                         finally_start = ex_block->start + ex_block->len;
1125                                         if (ex_block->extype) {
1126                                                 val = mono_metadata_token_from_dor (mono_image_typedef_or_ref (assembly, mono_reflection_type_get_handle ((MonoReflectionType*)ex_block->extype)));
1127                                         } else {
1128                                                 if (ex_block->type == MONO_EXCEPTION_CLAUSE_FILTER)
1129                                                         val = ex_block->filter_offset;
1130                                                 else
1131                                                         val = 0;
1132                                         }
1133                                         val = GUINT32_TO_LE (val);
1134                                         mono_image_add_stream_data (&assembly->code, (char*)&val, sizeof (guint32));
1135                                         /*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", 
1136                                                         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);*/
1137                                 }
1138                         } else {
1139                                 g_error ("No clauses for ex info block %d", i);
1140                         }
1141                 }
1142         }
1143         return assembly->text_rva + idx;
1144 }
1145
1146 static guint32
1147 find_index_in_table (MonoDynamicImage *assembly, int table_idx, int col, guint32 token)
1148 {
1149         int i;
1150         MonoDynamicTable *table;
1151         guint32 *values;
1152         
1153         table = &assembly->tables [table_idx];
1154
1155         g_assert (col < table->columns);
1156
1157         values = table->values + table->columns;
1158         for (i = 1; i <= table->rows; ++i) {
1159                 if (values [col] == token)
1160                         return i;
1161                 values += table->columns;
1162         }
1163         return 0;
1164 }
1165
1166 /*
1167  * LOCKING: Acquires the loader lock. 
1168  */
1169 static MonoCustomAttrInfo*
1170 lookup_custom_attr (MonoImage *image, gpointer member)
1171 {
1172         MonoCustomAttrInfo* res;
1173
1174         res = mono_image_property_lookup (image, member, MONO_PROP_DYNAMIC_CATTR);
1175
1176         if (!res)
1177                 return NULL;
1178
1179         res = g_memdup (res, MONO_SIZEOF_CUSTOM_ATTR_INFO + sizeof (MonoCustomAttrEntry) * res->num_attrs);
1180         res->cached = 0;
1181         return res;
1182 }
1183
1184 static gboolean
1185 custom_attr_visible (MonoImage *image, MonoReflectionCustomAttr *cattr)
1186 {
1187         /* FIXME: Need to do more checks */
1188         if (cattr->ctor->method && (cattr->ctor->method->klass->image != image)) {
1189                 int visibility = cattr->ctor->method->klass->flags & TYPE_ATTRIBUTE_VISIBILITY_MASK;
1190
1191                 if ((visibility != TYPE_ATTRIBUTE_PUBLIC) && (visibility != TYPE_ATTRIBUTE_NESTED_PUBLIC))
1192                         return FALSE;
1193         }
1194
1195         return TRUE;
1196 }
1197
1198 static MonoCustomAttrInfo*
1199 mono_custom_attrs_from_builders (MonoImage *alloc_img, MonoImage *image, MonoArray *cattrs)
1200 {
1201         int i, index, count, not_visible;
1202         MonoCustomAttrInfo *ainfo;
1203         MonoReflectionCustomAttr *cattr;
1204
1205         if (!cattrs)
1206                 return NULL;
1207         /* FIXME: check in assembly the Run flag is set */
1208
1209         count = mono_array_length (cattrs);
1210
1211         /* Skip nonpublic attributes since MS.NET seems to do the same */
1212         /* FIXME: This needs to be done more globally */
1213         not_visible = 0;
1214         for (i = 0; i < count; ++i) {
1215                 cattr = (MonoReflectionCustomAttr*)mono_array_get (cattrs, gpointer, i);
1216                 if (!custom_attr_visible (image, cattr))
1217                         not_visible ++;
1218         }
1219         count -= not_visible;
1220
1221         ainfo = image_g_malloc0 (alloc_img, MONO_SIZEOF_CUSTOM_ATTR_INFO + sizeof (MonoCustomAttrEntry) * count);
1222
1223         ainfo->image = image;
1224         ainfo->num_attrs = count;
1225         ainfo->cached = alloc_img != NULL;
1226         index = 0;
1227         for (i = 0; i < count; ++i) {
1228                 cattr = (MonoReflectionCustomAttr*)mono_array_get (cattrs, gpointer, i);
1229                 if (custom_attr_visible (image, cattr)) {
1230                         unsigned char *saved = mono_image_alloc (image, mono_array_length (cattr->data));
1231                         memcpy (saved, mono_array_addr (cattr->data, char, 0), mono_array_length (cattr->data));
1232                         ainfo->attrs [index].ctor = cattr->ctor->method;
1233                         ainfo->attrs [index].data = saved;
1234                         ainfo->attrs [index].data_size = mono_array_length (cattr->data);
1235                         index ++;
1236                 }
1237         }
1238
1239         return ainfo;
1240 }
1241
1242 #ifndef DISABLE_REFLECTION_EMIT
1243 /*
1244  * LOCKING: Acquires the loader lock. 
1245  */
1246 static void
1247 mono_save_custom_attrs (MonoImage *image, void *obj, MonoArray *cattrs)
1248 {
1249         MonoCustomAttrInfo *ainfo, *tmp;
1250
1251         if (!cattrs || !mono_array_length (cattrs))
1252                 return;
1253
1254         ainfo = mono_custom_attrs_from_builders (image, image, cattrs);
1255
1256         mono_loader_lock ();
1257         tmp = mono_image_property_lookup (image, obj, MONO_PROP_DYNAMIC_CATTR);
1258         if (tmp)
1259                 mono_custom_attrs_free (tmp);
1260         mono_image_property_insert (image, obj, MONO_PROP_DYNAMIC_CATTR, ainfo);
1261         mono_loader_unlock ();
1262
1263 }
1264 #endif
1265
1266 void
1267 mono_custom_attrs_free (MonoCustomAttrInfo *ainfo)
1268 {
1269         if (!ainfo->cached)
1270                 g_free (ainfo);
1271 }
1272
1273 /*
1274  * idx is the table index of the object
1275  * type is one of MONO_CUSTOM_ATTR_*
1276  */
1277 static void
1278 mono_image_add_cattrs (MonoDynamicImage *assembly, guint32 idx, guint32 type, MonoArray *cattrs)
1279 {
1280         MonoDynamicTable *table;
1281         MonoReflectionCustomAttr *cattr;
1282         guint32 *values;
1283         guint32 count, i, token;
1284         char blob_size [6];
1285         char *p = blob_size;
1286         
1287         /* it is legal to pass a NULL cattrs: we avoid to use the if in a lot of places */
1288         if (!cattrs)
1289                 return;
1290         count = mono_array_length (cattrs);
1291         table = &assembly->tables [MONO_TABLE_CUSTOMATTRIBUTE];
1292         table->rows += count;
1293         alloc_table (table, table->rows);
1294         values = table->values + table->next_idx * MONO_CUSTOM_ATTR_SIZE;
1295         idx <<= MONO_CUSTOM_ATTR_BITS;
1296         idx |= type;
1297         for (i = 0; i < count; ++i) {
1298                 cattr = (MonoReflectionCustomAttr*)mono_array_get (cattrs, gpointer, i);
1299                 values [MONO_CUSTOM_ATTR_PARENT] = idx;
1300                 token = mono_image_create_token (assembly, (MonoObject*)cattr->ctor, FALSE, FALSE);
1301                 type = mono_metadata_token_index (token);
1302                 type <<= MONO_CUSTOM_ATTR_TYPE_BITS;
1303                 switch (mono_metadata_token_table (token)) {
1304                 case MONO_TABLE_METHOD:
1305                         type |= MONO_CUSTOM_ATTR_TYPE_METHODDEF;
1306                         /*
1307                          * fixup_cattrs () needs to fix this up. We can't use image->tokens, since it contains the old token for the
1308                          * method, not the one returned by mono_image_create_token ().
1309                          */
1310                         mono_g_hash_table_insert (assembly->remapped_tokens, GUINT_TO_POINTER (token), cattr->ctor);
1311                         break;
1312                 case MONO_TABLE_MEMBERREF:
1313                         type |= MONO_CUSTOM_ATTR_TYPE_MEMBERREF;
1314                         break;
1315                 default:
1316                         g_warning ("got wrong token in custom attr");
1317                         continue;
1318                 }
1319                 values [MONO_CUSTOM_ATTR_TYPE] = type;
1320                 p = blob_size;
1321                 mono_metadata_encode_value (mono_array_length (cattr->data), p, &p);
1322                 values [MONO_CUSTOM_ATTR_VALUE] = add_to_blob_cached (assembly, blob_size, p - blob_size,
1323                         mono_array_addr (cattr->data, char, 0), mono_array_length (cattr->data));
1324                 values += MONO_CUSTOM_ATTR_SIZE;
1325                 ++table->next_idx;
1326         }
1327 }
1328
1329 static void
1330 mono_image_add_decl_security (MonoDynamicImage *assembly, guint32 parent_token, MonoArray *permissions)
1331 {
1332         MonoDynamicTable *table;
1333         guint32 *values;
1334         guint32 count, i, idx;
1335         MonoReflectionPermissionSet *perm;
1336
1337         if (!permissions)
1338                 return;
1339
1340         count = mono_array_length (permissions);
1341         table = &assembly->tables [MONO_TABLE_DECLSECURITY];
1342         table->rows += count;
1343         alloc_table (table, table->rows);
1344
1345         for (i = 0; i < mono_array_length (permissions); ++i) {
1346                 perm = (MonoReflectionPermissionSet*)mono_array_addr (permissions, MonoReflectionPermissionSet, i);
1347
1348                 values = table->values + table->next_idx * MONO_DECL_SECURITY_SIZE;
1349
1350                 idx = mono_metadata_token_index (parent_token);
1351                 idx <<= MONO_HAS_DECL_SECURITY_BITS;
1352                 switch (mono_metadata_token_table (parent_token)) {
1353                 case MONO_TABLE_TYPEDEF:
1354                         idx |= MONO_HAS_DECL_SECURITY_TYPEDEF;
1355                         break;
1356                 case MONO_TABLE_METHOD:
1357                         idx |= MONO_HAS_DECL_SECURITY_METHODDEF;
1358                         break;
1359                 case MONO_TABLE_ASSEMBLY:
1360                         idx |= MONO_HAS_DECL_SECURITY_ASSEMBLY;
1361                         break;
1362                 default:
1363                         g_assert_not_reached ();
1364                 }
1365
1366                 values [MONO_DECL_SECURITY_ACTION] = perm->action;
1367                 values [MONO_DECL_SECURITY_PARENT] = idx;
1368                 values [MONO_DECL_SECURITY_PERMISSIONSET] = add_mono_string_to_blob_cached (assembly, perm->pset);
1369
1370                 ++table->next_idx;
1371         }
1372 }
1373
1374 /*
1375  * Fill in the MethodDef and ParamDef tables for a method.
1376  * This is used for both normal methods and constructors.
1377  */
1378 static void
1379 mono_image_basic_method (ReflectionMethodBuilder *mb, MonoDynamicImage *assembly)
1380 {
1381         MonoDynamicTable *table;
1382         guint32 *values;
1383         guint i, count;
1384
1385         /* room in this table is already allocated */
1386         table = &assembly->tables [MONO_TABLE_METHOD];
1387         *mb->table_idx = table->next_idx ++;
1388         g_hash_table_insert (assembly->method_to_table_idx, mb->mhandle, GUINT_TO_POINTER ((*mb->table_idx)));
1389         values = table->values + *mb->table_idx * MONO_METHOD_SIZE;
1390         values [MONO_METHOD_NAME] = string_heap_insert_mstring (&assembly->sheap, mb->name);
1391         values [MONO_METHOD_FLAGS] = mb->attrs;
1392         values [MONO_METHOD_IMPLFLAGS] = mb->iattrs;
1393         values [MONO_METHOD_SIGNATURE] = method_builder_encode_signature (assembly, mb);
1394         values [MONO_METHOD_RVA] = method_encode_code (assembly, mb);
1395         
1396         table = &assembly->tables [MONO_TABLE_PARAM];
1397         values [MONO_METHOD_PARAMLIST] = table->next_idx;
1398
1399         mono_image_add_decl_security (assembly, 
1400                 mono_metadata_make_token (MONO_TABLE_METHOD, *mb->table_idx), mb->permissions);
1401
1402         if (mb->pinfo) {
1403                 MonoDynamicTable *mtable;
1404                 guint32 *mvalues;
1405                 
1406                 mtable = &assembly->tables [MONO_TABLE_FIELDMARSHAL];
1407                 mvalues = mtable->values + mtable->next_idx * MONO_FIELD_MARSHAL_SIZE;
1408                 
1409                 count = 0;
1410                 for (i = 0; i < mono_array_length (mb->pinfo); ++i) {
1411                         if (mono_array_get (mb->pinfo, gpointer, i))
1412                                 count++;
1413                 }
1414                 table->rows += count;
1415                 alloc_table (table, table->rows);
1416                 values = table->values + table->next_idx * MONO_PARAM_SIZE;
1417                 for (i = 0; i < mono_array_length (mb->pinfo); ++i) {
1418                         MonoReflectionParamBuilder *pb;
1419                         if ((pb = mono_array_get (mb->pinfo, MonoReflectionParamBuilder*, i))) {
1420                                 values [MONO_PARAM_FLAGS] = pb->attrs;
1421                                 values [MONO_PARAM_SEQUENCE] = i;
1422                                 if (pb->name != NULL) {
1423                                         values [MONO_PARAM_NAME] = string_heap_insert_mstring (&assembly->sheap, pb->name);
1424                                 } else {
1425                                         values [MONO_PARAM_NAME] = 0;
1426                                 }
1427                                 values += MONO_PARAM_SIZE;
1428                                 if (pb->marshal_info) {
1429                                         mtable->rows++;
1430                                         alloc_table (mtable, mtable->rows);
1431                                         mvalues = mtable->values + mtable->rows * MONO_FIELD_MARSHAL_SIZE;
1432                                         mvalues [MONO_FIELD_MARSHAL_PARENT] = (table->next_idx << MONO_HAS_FIELD_MARSHAL_BITS) | MONO_HAS_FIELD_MARSHAL_PARAMDEF;
1433                                         mvalues [MONO_FIELD_MARSHAL_NATIVE_TYPE] = encode_marshal_blob (assembly, pb->marshal_info);
1434                                 }
1435                                 pb->table_idx = table->next_idx++;
1436                                 if (pb->attrs & PARAM_ATTRIBUTE_HAS_DEFAULT) {
1437                                         guint32 field_type = 0;
1438                                         mtable = &assembly->tables [MONO_TABLE_CONSTANT];
1439                                         mtable->rows ++;
1440                                         alloc_table (mtable, mtable->rows);
1441                                         mvalues = mtable->values + mtable->rows * MONO_CONSTANT_SIZE;
1442                                         mvalues [MONO_CONSTANT_PARENT] = MONO_HASCONSTANT_PARAM | (pb->table_idx << MONO_HASCONSTANT_BITS);
1443                                         mvalues [MONO_CONSTANT_VALUE] = encode_constant (assembly, pb->def_value, &field_type);
1444                                         mvalues [MONO_CONSTANT_TYPE] = field_type;
1445                                         mvalues [MONO_CONSTANT_PADDING] = 0;
1446                                 }
1447                         }
1448                 }
1449         }
1450 }
1451
1452 #ifndef DISABLE_REFLECTION_EMIT
1453 static void
1454 reflection_methodbuilder_from_method_builder (ReflectionMethodBuilder *rmb, MonoReflectionMethodBuilder *mb)
1455 {
1456         memset (rmb, 0, sizeof (ReflectionMethodBuilder));
1457
1458         rmb->ilgen = mb->ilgen;
1459         rmb->rtype = mono_reflection_type_resolve_user_types ((MonoReflectionType*)mb->rtype);
1460         rmb->parameters = mb->parameters;
1461         rmb->generic_params = mb->generic_params;
1462         rmb->generic_container = mb->generic_container;
1463         rmb->opt_types = NULL;
1464         rmb->pinfo = mb->pinfo;
1465         rmb->attrs = mb->attrs;
1466         rmb->iattrs = mb->iattrs;
1467         rmb->call_conv = mb->call_conv;
1468         rmb->code = mb->code;
1469         rmb->type = mb->type;
1470         rmb->name = mb->name;
1471         rmb->table_idx = &mb->table_idx;
1472         rmb->init_locals = mb->init_locals;
1473         rmb->skip_visibility = FALSE;
1474         rmb->return_modreq = mb->return_modreq;
1475         rmb->return_modopt = mb->return_modopt;
1476         rmb->param_modreq = mb->param_modreq;
1477         rmb->param_modopt = mb->param_modopt;
1478         rmb->permissions = mb->permissions;
1479         rmb->mhandle = mb->mhandle;
1480         rmb->nrefs = 0;
1481         rmb->refs = NULL;
1482
1483         if (mb->dll) {
1484                 rmb->charset = mb->charset;
1485                 rmb->extra_flags = mb->extra_flags;
1486                 rmb->native_cc = mb->native_cc;
1487                 rmb->dllentry = mb->dllentry;
1488                 rmb->dll = mb->dll;
1489         }
1490 }
1491
1492 static void
1493 reflection_methodbuilder_from_ctor_builder (ReflectionMethodBuilder *rmb, MonoReflectionCtorBuilder *mb)
1494 {
1495         const char *name = mb->attrs & METHOD_ATTRIBUTE_STATIC ? ".cctor": ".ctor";
1496
1497         memset (rmb, 0, sizeof (ReflectionMethodBuilder));
1498
1499         rmb->ilgen = mb->ilgen;
1500         rmb->rtype = mono_type_get_object (mono_domain_get (), &mono_defaults.void_class->byval_arg);
1501         rmb->parameters = mb->parameters;
1502         rmb->generic_params = NULL;
1503         rmb->generic_container = NULL;
1504         rmb->opt_types = NULL;
1505         rmb->pinfo = mb->pinfo;
1506         rmb->attrs = mb->attrs;
1507         rmb->iattrs = mb->iattrs;
1508         rmb->call_conv = mb->call_conv;
1509         rmb->code = NULL;
1510         rmb->type = mb->type;
1511         rmb->name = mono_string_new (mono_domain_get (), name);
1512         rmb->table_idx = &mb->table_idx;
1513         rmb->init_locals = mb->init_locals;
1514         rmb->skip_visibility = FALSE;
1515         rmb->return_modreq = NULL;
1516         rmb->return_modopt = NULL;
1517         rmb->param_modreq = mb->param_modreq;
1518         rmb->param_modopt = mb->param_modopt;
1519         rmb->permissions = mb->permissions;
1520         rmb->mhandle = mb->mhandle;
1521         rmb->nrefs = 0;
1522         rmb->refs = NULL;
1523 }
1524
1525 static void
1526 reflection_methodbuilder_from_dynamic_method (ReflectionMethodBuilder *rmb, MonoReflectionDynamicMethod *mb)
1527 {
1528         memset (rmb, 0, sizeof (ReflectionMethodBuilder));
1529
1530         rmb->ilgen = mb->ilgen;
1531         rmb->rtype = mb->rtype;
1532         rmb->parameters = mb->parameters;
1533         rmb->generic_params = NULL;
1534         rmb->generic_container = NULL;
1535         rmb->opt_types = NULL;
1536         rmb->pinfo = NULL;
1537         rmb->attrs = mb->attrs;
1538         rmb->iattrs = 0;
1539         rmb->call_conv = mb->call_conv;
1540         rmb->code = NULL;
1541         rmb->type = (MonoObject *) mb->owner;
1542         rmb->name = mb->name;
1543         rmb->table_idx = NULL;
1544         rmb->init_locals = mb->init_locals;
1545         rmb->skip_visibility = mb->skip_visibility;
1546         rmb->return_modreq = NULL;
1547         rmb->return_modopt = NULL;
1548         rmb->param_modreq = NULL;
1549         rmb->param_modopt = NULL;
1550         rmb->permissions = NULL;
1551         rmb->mhandle = mb->mhandle;
1552         rmb->nrefs = 0;
1553         rmb->refs = NULL;
1554 }       
1555 #endif
1556
1557 static void
1558 mono_image_add_methodimpl (MonoDynamicImage *assembly, MonoReflectionMethodBuilder *mb)
1559 {
1560         MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder *)mb->type;
1561         MonoDynamicTable *table;
1562         guint32 *values;
1563         guint32 tok;
1564         MonoReflectionMethod *m;
1565         int i;
1566
1567         if (!mb->override_methods)
1568                 return;
1569
1570         for (i = 0; i < mono_array_length (mb->override_methods); ++i) {
1571                 m = mono_array_get (mb->override_methods, MonoReflectionMethod*, i);
1572
1573                 table = &assembly->tables [MONO_TABLE_METHODIMPL];
1574                 table->rows ++;
1575                 alloc_table (table, table->rows);
1576                 values = table->values + table->rows * MONO_METHODIMPL_SIZE;
1577                 values [MONO_METHODIMPL_CLASS] = tb->table_idx;
1578                 values [MONO_METHODIMPL_BODY] = MONO_METHODDEFORREF_METHODDEF | (mb->table_idx << MONO_METHODDEFORREF_BITS);
1579
1580                 tok = mono_image_create_token (assembly, (MonoObject*)m, FALSE, FALSE);
1581                 switch (mono_metadata_token_table (tok)) {
1582                 case MONO_TABLE_MEMBERREF:
1583                         tok = (mono_metadata_token_index (tok) << MONO_METHODDEFORREF_BITS ) | MONO_METHODDEFORREF_METHODREF;
1584                         break;
1585                 case MONO_TABLE_METHOD:
1586                         tok = (mono_metadata_token_index (tok) << MONO_METHODDEFORREF_BITS ) | MONO_METHODDEFORREF_METHODDEF;
1587                         break;
1588                 default:
1589                         g_assert_not_reached ();
1590                 }
1591                 values [MONO_METHODIMPL_DECLARATION] = tok;
1592         }
1593 }
1594
1595 #ifndef DISABLE_REFLECTION_EMIT
1596 static void
1597 mono_image_get_method_info (MonoReflectionMethodBuilder *mb, MonoDynamicImage *assembly)
1598 {
1599         MonoDynamicTable *table;
1600         guint32 *values;
1601         ReflectionMethodBuilder rmb;
1602         int i;
1603
1604         reflection_methodbuilder_from_method_builder (&rmb, mb);
1605
1606         mono_image_basic_method (&rmb, assembly);
1607         mb->table_idx = *rmb.table_idx;
1608
1609         if (mb->dll) { /* It's a P/Invoke method */
1610                 guint32 moduleref;
1611                 /* map CharSet values to on-disk values */
1612                 int ncharset = (mb->charset ? (mb->charset - 1) * 2 : 0);
1613                 int extra_flags = mb->extra_flags;
1614                 table = &assembly->tables [MONO_TABLE_IMPLMAP];
1615                 table->rows ++;
1616                 alloc_table (table, table->rows);
1617                 values = table->values + table->rows * MONO_IMPLMAP_SIZE;
1618                 
1619                 values [MONO_IMPLMAP_FLAGS] = (mb->native_cc << 8) | ncharset | extra_flags;
1620                 values [MONO_IMPLMAP_MEMBER] = (mb->table_idx << 1) | 1; /* memberforwarded: method */
1621                 if (mb->dllentry)
1622                         values [MONO_IMPLMAP_NAME] = string_heap_insert_mstring (&assembly->sheap, mb->dllentry);
1623                 else
1624                         values [MONO_IMPLMAP_NAME] = string_heap_insert_mstring (&assembly->sheap, mb->name);
1625                 moduleref = string_heap_insert_mstring (&assembly->sheap, mb->dll);
1626                 if (!(values [MONO_IMPLMAP_SCOPE] = find_index_in_table (assembly, MONO_TABLE_MODULEREF, MONO_MODULEREF_NAME, moduleref))) {
1627                         table = &assembly->tables [MONO_TABLE_MODULEREF];
1628                         table->rows ++;
1629                         alloc_table (table, table->rows);
1630                         table->values [table->rows * MONO_MODULEREF_SIZE + MONO_MODULEREF_NAME] = moduleref;
1631                         values [MONO_IMPLMAP_SCOPE] = table->rows;
1632                 }
1633         }
1634
1635         if (mb->generic_params) {
1636                 table = &assembly->tables [MONO_TABLE_GENERICPARAM];
1637                 table->rows += mono_array_length (mb->generic_params);
1638                 alloc_table (table, table->rows);
1639                 for (i = 0; i < mono_array_length (mb->generic_params); ++i) {
1640                         guint32 owner = MONO_TYPEORMETHOD_METHOD | (mb->table_idx << MONO_TYPEORMETHOD_BITS);
1641
1642                         mono_image_get_generic_param_info (
1643                                 mono_array_get (mb->generic_params, gpointer, i), owner, assembly);
1644                 }
1645         }
1646
1647 }
1648
1649 static void
1650 mono_image_get_ctor_info (MonoDomain *domain, MonoReflectionCtorBuilder *mb, MonoDynamicImage *assembly)
1651 {
1652         ReflectionMethodBuilder rmb;
1653
1654         reflection_methodbuilder_from_ctor_builder (&rmb, mb);
1655
1656         mono_image_basic_method (&rmb, assembly);
1657         mb->table_idx = *rmb.table_idx;
1658 }
1659 #endif
1660
1661 static char*
1662 type_get_fully_qualified_name (MonoType *type)
1663 {
1664         return mono_type_get_name_full (type, MONO_TYPE_NAME_FORMAT_ASSEMBLY_QUALIFIED);
1665 }
1666
1667 static char*
1668 type_get_qualified_name (MonoType *type, MonoAssembly *ass) {
1669         MonoClass *klass;
1670         MonoAssembly *ta;
1671
1672         klass = mono_class_from_mono_type (type);
1673         if (!klass) 
1674                 return mono_type_get_name_full (type, MONO_TYPE_NAME_FORMAT_REFLECTION);
1675         ta = klass->image->assembly;
1676         if (assembly_is_dynamic (ta) || (ta == ass)) {
1677                 if (klass->generic_class || klass->generic_container)
1678                         /* For generic type definitions, we want T, while REFLECTION returns T<K> */
1679                         return mono_type_get_name_full (type, MONO_TYPE_NAME_FORMAT_FULL_NAME);
1680                 else
1681                         return mono_type_get_name_full (type, MONO_TYPE_NAME_FORMAT_REFLECTION);
1682         }
1683
1684         return mono_type_get_name_full (type, MONO_TYPE_NAME_FORMAT_ASSEMBLY_QUALIFIED);
1685 }
1686
1687 #ifndef DISABLE_REFLECTION_EMIT
1688 /*field_image is the image to which the eventual custom mods have been encoded against*/
1689 static guint32
1690 fieldref_encode_signature (MonoDynamicImage *assembly, MonoImage *field_image, MonoType *type)
1691 {
1692         SigBuffer buf;
1693         guint32 idx, i, token;
1694
1695         if (!assembly->save)
1696                 return 0;
1697
1698         sigbuffer_init (&buf, 32);
1699         
1700         sigbuffer_add_value (&buf, 0x06);
1701         /* encode custom attributes before the type */
1702         if (type->num_mods) {
1703                 for (i = 0; i < type->num_mods; ++i) {
1704                         if (field_image) {
1705                                 MonoError error;
1706                                 MonoClass *class = mono_class_get_checked (field_image, type->modifiers [i].token, &error);
1707                                 g_assert (mono_error_ok (&error)); /* FIXME don't swallow the error */
1708
1709                                 token = mono_image_typedef_or_ref (assembly, &class->byval_arg);
1710                         } else {
1711                                 token = type->modifiers [i].token;
1712                         }
1713
1714                         if (type->modifiers [i].required)
1715                                 sigbuffer_add_byte (&buf, MONO_TYPE_CMOD_REQD);
1716                         else
1717                                 sigbuffer_add_byte (&buf, MONO_TYPE_CMOD_OPT);
1718
1719                         sigbuffer_add_value (&buf, token);
1720                 }
1721         }
1722         encode_type (assembly, type, &buf);
1723         idx = sigbuffer_add_to_blob_cached (assembly, &buf);
1724         sigbuffer_free (&buf);
1725         return idx;
1726 }
1727 #endif
1728
1729 static guint32
1730 field_encode_signature (MonoDynamicImage *assembly, MonoReflectionFieldBuilder *fb)
1731 {
1732         SigBuffer buf;
1733         guint32 idx;
1734         guint32 typespec = 0;
1735         MonoType *type;
1736         MonoClass *class;
1737
1738         init_type_builder_generics (fb->type);
1739
1740         type = mono_reflection_type_get_handle ((MonoReflectionType*)fb->type);
1741         class = mono_class_from_mono_type (type);
1742
1743         sigbuffer_init (&buf, 32);
1744         
1745         sigbuffer_add_value (&buf, 0x06);
1746         encode_custom_modifiers (assembly, fb->modreq, fb->modopt, &buf);
1747         /* encode custom attributes before the type */
1748
1749         if (class->generic_container)
1750                 typespec = create_typespec (assembly, type);
1751
1752         if (typespec) {
1753                 MonoGenericClass *gclass;
1754                 gclass = mono_metadata_lookup_generic_class (class, class->generic_container->context.class_inst, TRUE);
1755                 encode_generic_class (assembly, gclass, &buf);
1756         } else {
1757                 encode_type (assembly, type, &buf);
1758         }
1759         idx = sigbuffer_add_to_blob_cached (assembly, &buf);
1760         sigbuffer_free (&buf);
1761         return idx;
1762 }
1763
1764 static guint32
1765 encode_constant (MonoDynamicImage *assembly, MonoObject *val, guint32 *ret_type) {
1766         char blob_size [64];
1767         char *b = blob_size;
1768         char *box_val;
1769         char* buf;
1770         guint32 idx = 0, len = 0, dummy = 0;
1771
1772         buf = g_malloc (64);
1773         if (!val) {
1774                 *ret_type = MONO_TYPE_CLASS;
1775                 len = 4;
1776                 box_val = (char*)&dummy;
1777         } else {
1778                 box_val = ((char*)val) + sizeof (MonoObject);
1779                 *ret_type = val->vtable->klass->byval_arg.type;
1780         }
1781 handle_enum:
1782         switch (*ret_type) {
1783         case MONO_TYPE_BOOLEAN:
1784         case MONO_TYPE_U1:
1785         case MONO_TYPE_I1:
1786                 len = 1;
1787                 break;
1788         case MONO_TYPE_CHAR:
1789         case MONO_TYPE_U2:
1790         case MONO_TYPE_I2:
1791                 len = 2;
1792                 break;
1793         case MONO_TYPE_U4:
1794         case MONO_TYPE_I4:
1795         case MONO_TYPE_R4:
1796                 len = 4;
1797                 break;
1798         case MONO_TYPE_U8:
1799         case MONO_TYPE_I8:
1800                 len = 8;
1801                 break;
1802         case MONO_TYPE_R8:
1803                 len = 8;
1804                 break;
1805         case MONO_TYPE_VALUETYPE: {
1806                 MonoClass *klass = val->vtable->klass;
1807                 
1808                 if (klass->enumtype) {
1809                         *ret_type = mono_class_enum_basetype (klass)->type;
1810                         goto handle_enum;
1811                 } else if (mono_is_corlib_image (klass->image) && strcmp (klass->name_space, "System") == 0 && strcmp (klass->name, "DateTime") == 0) {
1812                         len = 8;
1813                 } else 
1814                         g_error ("we can't encode valuetypes, we should have never reached this line");
1815                 break;
1816         }
1817         case MONO_TYPE_CLASS:
1818                 break;
1819         case MONO_TYPE_STRING: {
1820                 MonoString *str = (MonoString*)val;
1821                 /* there is no signature */
1822                 len = str->length * 2;
1823                 mono_metadata_encode_value (len, b, &b);
1824 #if G_BYTE_ORDER != G_LITTLE_ENDIAN
1825                 {
1826                         char *swapped = g_malloc (2 * mono_string_length (str));
1827                         const char *p = (const char*)mono_string_chars (str);
1828
1829                         swap_with_size (swapped, p, 2, mono_string_length (str));
1830                         idx = add_to_blob_cached (assembly, blob_size, b-blob_size, swapped, len);
1831                         g_free (swapped);
1832                 }
1833 #else
1834                 idx = add_to_blob_cached (assembly, blob_size, b-blob_size, (char*)mono_string_chars (str), len);
1835 #endif
1836
1837                 g_free (buf);
1838                 return idx;
1839         }
1840         case MONO_TYPE_GENERICINST:
1841                 *ret_type = val->vtable->klass->generic_class->container_class->byval_arg.type;
1842                 goto handle_enum;
1843         default:
1844                 g_error ("we don't encode constant type 0x%02x yet", *ret_type);
1845         }
1846
1847         /* there is no signature */
1848         mono_metadata_encode_value (len, b, &b);
1849 #if G_BYTE_ORDER != G_LITTLE_ENDIAN
1850         idx = mono_image_add_stream_data (&assembly->blob, blob_size, b-blob_size);
1851         swap_with_size (blob_size, box_val, len, 1);
1852         mono_image_add_stream_data (&assembly->blob, blob_size, len);
1853 #else
1854         idx = add_to_blob_cached (assembly, blob_size, b-blob_size, box_val, len);
1855 #endif
1856
1857         g_free (buf);
1858         return idx;
1859 }
1860
1861 static guint32
1862 encode_marshal_blob (MonoDynamicImage *assembly, MonoReflectionMarshal *minfo) {
1863         char *str;
1864         SigBuffer buf;
1865         guint32 idx, len;
1866
1867         sigbuffer_init (&buf, 32);
1868
1869         sigbuffer_add_value (&buf, minfo->type);
1870
1871         switch (minfo->type) {
1872         case MONO_NATIVE_BYVALTSTR:
1873         case MONO_NATIVE_BYVALARRAY:
1874                 sigbuffer_add_value (&buf, minfo->count);
1875                 break;
1876         case MONO_NATIVE_LPARRAY:
1877                 if (minfo->eltype || minfo->has_size) {
1878                         sigbuffer_add_value (&buf, minfo->eltype);
1879                         if (minfo->has_size) {
1880                                 sigbuffer_add_value (&buf, minfo->param_num != -1? minfo->param_num: 0);
1881                                 sigbuffer_add_value (&buf, minfo->count != -1? minfo->count: 0);
1882
1883                                 /* LAMESPEC: ElemMult is undocumented */
1884                                 sigbuffer_add_value (&buf, minfo->param_num != -1? 1: 0);
1885                         }
1886                 }
1887                 break;
1888         case MONO_NATIVE_SAFEARRAY:
1889                 if (minfo->eltype)
1890                         sigbuffer_add_value (&buf, minfo->eltype);
1891                 break;
1892         case MONO_NATIVE_CUSTOM:
1893                 if (minfo->guid) {
1894                         str = mono_string_to_utf8 (minfo->guid);
1895                         len = strlen (str);
1896                         sigbuffer_add_value (&buf, len);
1897                         sigbuffer_add_mem (&buf, str, len);
1898                         g_free (str);
1899                 } else {
1900                         sigbuffer_add_value (&buf, 0);
1901                 }
1902                 /* native type name */
1903                 sigbuffer_add_value (&buf, 0);
1904                 /* custom marshaler type name */
1905                 if (minfo->marshaltype || minfo->marshaltyperef) {
1906                         if (minfo->marshaltyperef)
1907                                 str = type_get_fully_qualified_name (mono_reflection_type_get_handle ((MonoReflectionType*)minfo->marshaltyperef));
1908                         else
1909                                 str = mono_string_to_utf8 (minfo->marshaltype);
1910                         len = strlen (str);
1911                         sigbuffer_add_value (&buf, len);
1912                         sigbuffer_add_mem (&buf, str, len);
1913                         g_free (str);
1914                 } else {
1915                         /* FIXME: Actually a bug, since this field is required.  Punting for now ... */
1916                         sigbuffer_add_value (&buf, 0);
1917                 }
1918                 if (minfo->mcookie) {
1919                         str = mono_string_to_utf8 (minfo->mcookie);
1920                         len = strlen (str);
1921                         sigbuffer_add_value (&buf, len);
1922                         sigbuffer_add_mem (&buf, str, len);
1923                         g_free (str);
1924                 } else {
1925                         sigbuffer_add_value (&buf, 0);
1926                 }
1927                 break;
1928         default:
1929                 break;
1930         }
1931         idx = sigbuffer_add_to_blob_cached (assembly, &buf);
1932         sigbuffer_free (&buf);
1933         return idx;
1934 }
1935
1936 static void
1937 mono_image_get_field_info (MonoReflectionFieldBuilder *fb, MonoDynamicImage *assembly)
1938 {
1939         MonoDynamicTable *table;
1940         guint32 *values;
1941
1942         /* maybe this fixup should be done in the C# code */
1943         if (fb->attrs & FIELD_ATTRIBUTE_LITERAL)
1944                 fb->attrs |= FIELD_ATTRIBUTE_HAS_DEFAULT;
1945         table = &assembly->tables [MONO_TABLE_FIELD];
1946         fb->table_idx = table->next_idx ++;
1947         g_hash_table_insert (assembly->field_to_table_idx, fb->handle, GUINT_TO_POINTER (fb->table_idx));
1948         values = table->values + fb->table_idx * MONO_FIELD_SIZE;
1949         values [MONO_FIELD_NAME] = string_heap_insert_mstring (&assembly->sheap, fb->name);
1950         values [MONO_FIELD_FLAGS] = fb->attrs;
1951         values [MONO_FIELD_SIGNATURE] = field_encode_signature (assembly, fb);
1952
1953         if (fb->offset != -1) {
1954                 table = &assembly->tables [MONO_TABLE_FIELDLAYOUT];
1955                 table->rows ++;
1956                 alloc_table (table, table->rows);
1957                 values = table->values + table->rows * MONO_FIELD_LAYOUT_SIZE;
1958                 values [MONO_FIELD_LAYOUT_FIELD] = fb->table_idx;
1959                 values [MONO_FIELD_LAYOUT_OFFSET] = fb->offset;
1960         }
1961         if (fb->attrs & FIELD_ATTRIBUTE_LITERAL) {
1962                 guint32 field_type = 0;
1963                 table = &assembly->tables [MONO_TABLE_CONSTANT];
1964                 table->rows ++;
1965                 alloc_table (table, table->rows);
1966                 values = table->values + table->rows * MONO_CONSTANT_SIZE;
1967                 values [MONO_CONSTANT_PARENT] = MONO_HASCONSTANT_FIEDDEF | (fb->table_idx << MONO_HASCONSTANT_BITS);
1968                 values [MONO_CONSTANT_VALUE] = encode_constant (assembly, fb->def_value, &field_type);
1969                 values [MONO_CONSTANT_TYPE] = field_type;
1970                 values [MONO_CONSTANT_PADDING] = 0;
1971         }
1972         if (fb->attrs & FIELD_ATTRIBUTE_HAS_FIELD_RVA) {
1973                 guint32 rva_idx;
1974                 table = &assembly->tables [MONO_TABLE_FIELDRVA];
1975                 table->rows ++;
1976                 alloc_table (table, table->rows);
1977                 values = table->values + table->rows * MONO_FIELD_RVA_SIZE;
1978                 values [MONO_FIELD_RVA_FIELD] = fb->table_idx;
1979                 /*
1980                  * We store it in the code section because it's simpler for now.
1981                  */
1982                 if (fb->rva_data) {
1983                         if (mono_array_length (fb->rva_data) >= 10)
1984                                 stream_data_align (&assembly->code);
1985                         rva_idx = mono_image_add_stream_data (&assembly->code, mono_array_addr (fb->rva_data, char, 0), mono_array_length (fb->rva_data));
1986                 } else
1987                         rva_idx = mono_image_add_stream_zero (&assembly->code, mono_class_value_size (fb->handle->parent, NULL));
1988                 values [MONO_FIELD_RVA_RVA] = rva_idx + assembly->text_rva;
1989         }
1990         if (fb->marshal_info) {
1991                 table = &assembly->tables [MONO_TABLE_FIELDMARSHAL];
1992                 table->rows ++;
1993                 alloc_table (table, table->rows);
1994                 values = table->values + table->rows * MONO_FIELD_MARSHAL_SIZE;
1995                 values [MONO_FIELD_MARSHAL_PARENT] = (fb->table_idx << MONO_HAS_FIELD_MARSHAL_BITS) | MONO_HAS_FIELD_MARSHAL_FIELDSREF;
1996                 values [MONO_FIELD_MARSHAL_NATIVE_TYPE] = encode_marshal_blob (assembly, fb->marshal_info);
1997         }
1998 }
1999
2000 static guint32
2001 property_encode_signature (MonoDynamicImage *assembly, MonoReflectionPropertyBuilder *fb)
2002 {
2003         SigBuffer buf;
2004         guint32 nparams = 0;
2005         MonoReflectionMethodBuilder *mb = fb->get_method;
2006         MonoReflectionMethodBuilder *smb = fb->set_method;
2007         guint32 idx, i;
2008
2009         if (mb && mb->parameters)
2010                 nparams = mono_array_length (mb->parameters);
2011         if (!mb && smb && smb->parameters)
2012                 nparams = mono_array_length (smb->parameters) - 1;
2013         sigbuffer_init (&buf, 32);
2014         if (fb->call_conv & 0x20)
2015                 sigbuffer_add_byte (&buf, 0x28);
2016         else
2017                 sigbuffer_add_byte (&buf, 0x08);
2018         sigbuffer_add_value (&buf, nparams);
2019         if (mb) {
2020                 encode_reflection_type (assembly, (MonoReflectionType*)mb->rtype, &buf);
2021                 for (i = 0; i < nparams; ++i) {
2022                         MonoReflectionType *pt = mono_array_get (mb->parameters, MonoReflectionType*, i);
2023                         encode_reflection_type (assembly, pt, &buf);
2024                 }
2025         } else if (smb && smb->parameters) {
2026                 /* the property type is the last param */
2027                 encode_reflection_type (assembly, mono_array_get (smb->parameters, MonoReflectionType*, nparams), &buf);
2028                 for (i = 0; i < nparams; ++i) {
2029                         MonoReflectionType *pt = mono_array_get (smb->parameters, MonoReflectionType*, i);
2030                         encode_reflection_type (assembly, pt, &buf);
2031                 }
2032         } else {
2033                 encode_reflection_type (assembly, (MonoReflectionType*)fb->type, &buf);
2034         }
2035
2036         idx = sigbuffer_add_to_blob_cached (assembly, &buf);
2037         sigbuffer_free (&buf);
2038         return idx;
2039 }
2040
2041 static void
2042 mono_image_get_property_info (MonoReflectionPropertyBuilder *pb, MonoDynamicImage *assembly)
2043 {
2044         MonoDynamicTable *table;
2045         guint32 *values;
2046         guint num_methods = 0;
2047         guint32 semaidx;
2048
2049         /* 
2050          * we need to set things in the following tables:
2051          * PROPERTYMAP (info already filled in _get_type_info ())
2052          * PROPERTY    (rows already preallocated in _get_type_info ())
2053          * METHOD      (method info already done with the generic method code)
2054          * METHODSEMANTICS
2055          * CONSTANT
2056          */
2057         table = &assembly->tables [MONO_TABLE_PROPERTY];
2058         pb->table_idx = table->next_idx ++;
2059         values = table->values + pb->table_idx * MONO_PROPERTY_SIZE;
2060         values [MONO_PROPERTY_NAME] = string_heap_insert_mstring (&assembly->sheap, pb->name);
2061         values [MONO_PROPERTY_FLAGS] = pb->attrs;
2062         values [MONO_PROPERTY_TYPE] = property_encode_signature (assembly, pb);
2063
2064         /* FIXME: we still don't handle 'other' methods */
2065         if (pb->get_method) num_methods ++;
2066         if (pb->set_method) num_methods ++;
2067
2068         table = &assembly->tables [MONO_TABLE_METHODSEMANTICS];
2069         table->rows += num_methods;
2070         alloc_table (table, table->rows);
2071
2072         if (pb->get_method) {
2073                 semaidx = table->next_idx ++;
2074                 values = table->values + semaidx * MONO_METHOD_SEMA_SIZE;
2075                 values [MONO_METHOD_SEMA_SEMANTICS] = METHOD_SEMANTIC_GETTER;
2076                 values [MONO_METHOD_SEMA_METHOD] = pb->get_method->table_idx;
2077                 values [MONO_METHOD_SEMA_ASSOCIATION] = (pb->table_idx << MONO_HAS_SEMANTICS_BITS) | MONO_HAS_SEMANTICS_PROPERTY;
2078         }
2079         if (pb->set_method) {
2080                 semaidx = table->next_idx ++;
2081                 values = table->values + semaidx * MONO_METHOD_SEMA_SIZE;
2082                 values [MONO_METHOD_SEMA_SEMANTICS] = METHOD_SEMANTIC_SETTER;
2083                 values [MONO_METHOD_SEMA_METHOD] = pb->set_method->table_idx;
2084                 values [MONO_METHOD_SEMA_ASSOCIATION] = (pb->table_idx << MONO_HAS_SEMANTICS_BITS) | MONO_HAS_SEMANTICS_PROPERTY;
2085         }
2086         if (pb->attrs & PROPERTY_ATTRIBUTE_HAS_DEFAULT) {
2087                 guint32 field_type = 0;
2088                 table = &assembly->tables [MONO_TABLE_CONSTANT];
2089                 table->rows ++;
2090                 alloc_table (table, table->rows);
2091                 values = table->values + table->rows * MONO_CONSTANT_SIZE;
2092                 values [MONO_CONSTANT_PARENT] = MONO_HASCONSTANT_PROPERTY | (pb->table_idx << MONO_HASCONSTANT_BITS);
2093                 values [MONO_CONSTANT_VALUE] = encode_constant (assembly, pb->def_value, &field_type);
2094                 values [MONO_CONSTANT_TYPE] = field_type;
2095                 values [MONO_CONSTANT_PADDING] = 0;
2096         }
2097 }
2098
2099 static void
2100 mono_image_get_event_info (MonoReflectionEventBuilder *eb, MonoDynamicImage *assembly)
2101 {
2102         MonoDynamicTable *table;
2103         guint32 *values;
2104         guint num_methods = 0;
2105         guint32 semaidx;
2106
2107         /* 
2108          * we need to set things in the following tables:
2109          * EVENTMAP (info already filled in _get_type_info ())
2110          * EVENT    (rows already preallocated in _get_type_info ())
2111          * METHOD      (method info already done with the generic method code)
2112          * METHODSEMANTICS
2113          */
2114         table = &assembly->tables [MONO_TABLE_EVENT];
2115         eb->table_idx = table->next_idx ++;
2116         values = table->values + eb->table_idx * MONO_EVENT_SIZE;
2117         values [MONO_EVENT_NAME] = string_heap_insert_mstring (&assembly->sheap, eb->name);
2118         values [MONO_EVENT_FLAGS] = eb->attrs;
2119         values [MONO_EVENT_TYPE] = mono_image_typedef_or_ref (assembly, mono_reflection_type_get_handle (eb->type));
2120
2121         /*
2122          * FIXME: we still don't handle 'other' methods 
2123          */
2124         if (eb->add_method) num_methods ++;
2125         if (eb->remove_method) num_methods ++;
2126         if (eb->raise_method) num_methods ++;
2127
2128         table = &assembly->tables [MONO_TABLE_METHODSEMANTICS];
2129         table->rows += num_methods;
2130         alloc_table (table, table->rows);
2131
2132         if (eb->add_method) {
2133                 semaidx = table->next_idx ++;
2134                 values = table->values + semaidx * MONO_METHOD_SEMA_SIZE;
2135                 values [MONO_METHOD_SEMA_SEMANTICS] = METHOD_SEMANTIC_ADD_ON;
2136                 values [MONO_METHOD_SEMA_METHOD] = eb->add_method->table_idx;
2137                 values [MONO_METHOD_SEMA_ASSOCIATION] = (eb->table_idx << MONO_HAS_SEMANTICS_BITS) | MONO_HAS_SEMANTICS_EVENT;
2138         }
2139         if (eb->remove_method) {
2140                 semaidx = table->next_idx ++;
2141                 values = table->values + semaidx * MONO_METHOD_SEMA_SIZE;
2142                 values [MONO_METHOD_SEMA_SEMANTICS] = METHOD_SEMANTIC_REMOVE_ON;
2143                 values [MONO_METHOD_SEMA_METHOD] = eb->remove_method->table_idx;
2144                 values [MONO_METHOD_SEMA_ASSOCIATION] = (eb->table_idx << MONO_HAS_SEMANTICS_BITS) | MONO_HAS_SEMANTICS_EVENT;
2145         }
2146         if (eb->raise_method) {
2147                 semaidx = table->next_idx ++;
2148                 values = table->values + semaidx * MONO_METHOD_SEMA_SIZE;
2149                 values [MONO_METHOD_SEMA_SEMANTICS] = METHOD_SEMANTIC_FIRE;
2150                 values [MONO_METHOD_SEMA_METHOD] = eb->raise_method->table_idx;
2151                 values [MONO_METHOD_SEMA_ASSOCIATION] = (eb->table_idx << MONO_HAS_SEMANTICS_BITS) | MONO_HAS_SEMANTICS_EVENT;
2152         }
2153 }
2154
2155 static void
2156 encode_constraints (MonoReflectionGenericParam *gparam, guint32 owner, MonoDynamicImage *assembly)
2157 {
2158         MonoDynamicTable *table;
2159         guint32 num_constraints, i;
2160         guint32 *values;
2161         guint32 table_idx;
2162
2163         table = &assembly->tables [MONO_TABLE_GENERICPARAMCONSTRAINT];
2164         num_constraints = gparam->iface_constraints ?
2165                 mono_array_length (gparam->iface_constraints) : 0;
2166         table->rows += num_constraints;
2167         if (gparam->base_type)
2168                 table->rows++;
2169         alloc_table (table, table->rows);
2170
2171         if (gparam->base_type) {
2172                 table_idx = table->next_idx ++;
2173                 values = table->values + table_idx * MONO_GENPARCONSTRAINT_SIZE;
2174
2175                 values [MONO_GENPARCONSTRAINT_GENERICPAR] = owner;
2176                 values [MONO_GENPARCONSTRAINT_CONSTRAINT] = mono_image_typedef_or_ref (
2177                         assembly, mono_reflection_type_get_handle (gparam->base_type));
2178         }
2179
2180         for (i = 0; i < num_constraints; i++) {
2181                 MonoReflectionType *constraint = mono_array_get (
2182                         gparam->iface_constraints, gpointer, i);
2183
2184                 table_idx = table->next_idx ++;
2185                 values = table->values + table_idx * MONO_GENPARCONSTRAINT_SIZE;
2186
2187                 values [MONO_GENPARCONSTRAINT_GENERICPAR] = owner;
2188                 values [MONO_GENPARCONSTRAINT_CONSTRAINT] = mono_image_typedef_or_ref (
2189                         assembly, mono_reflection_type_get_handle (constraint));
2190         }
2191 }
2192
2193 static void
2194 mono_image_get_generic_param_info (MonoReflectionGenericParam *gparam, guint32 owner, MonoDynamicImage *assembly)
2195 {
2196         GenericParamTableEntry *entry;
2197
2198         /*
2199          * The GenericParam table must be sorted according to the `owner' field.
2200          * We need to do this sorting prior to writing the GenericParamConstraint
2201          * table, since we have to use the final GenericParam table indices there
2202          * and they must also be sorted.
2203          */
2204
2205         entry = g_new0 (GenericParamTableEntry, 1);
2206         entry->owner = owner;
2207         /* FIXME: track where gen_params should be freed and remove the GC root as well */
2208         MONO_GC_REGISTER_ROOT_IF_MOVING (entry->gparam);
2209         entry->gparam = gparam;
2210         
2211         g_ptr_array_add (assembly->gen_params, entry);
2212 }
2213
2214 static void
2215 write_generic_param_entry (MonoDynamicImage *assembly, GenericParamTableEntry *entry)
2216 {
2217         MonoDynamicTable *table;
2218         MonoGenericParam *param;
2219         guint32 *values;
2220         guint32 table_idx;
2221
2222         table = &assembly->tables [MONO_TABLE_GENERICPARAM];
2223         table_idx = table->next_idx ++;
2224         values = table->values + table_idx * MONO_GENERICPARAM_SIZE;
2225
2226         param = mono_reflection_type_get_handle ((MonoReflectionType*)entry->gparam)->data.generic_param;
2227
2228         values [MONO_GENERICPARAM_OWNER] = entry->owner;
2229         values [MONO_GENERICPARAM_FLAGS] = entry->gparam->attrs;
2230         values [MONO_GENERICPARAM_NUMBER] = mono_generic_param_num (param);
2231         values [MONO_GENERICPARAM_NAME] = string_heap_insert (&assembly->sheap, mono_generic_param_info (param)->name);
2232
2233         mono_image_add_cattrs (assembly, table_idx, MONO_CUSTOM_ATTR_GENERICPAR, entry->gparam->cattrs);
2234
2235         encode_constraints (entry->gparam, table_idx, assembly);
2236 }
2237
2238 static guint32
2239 resolution_scope_from_image (MonoDynamicImage *assembly, MonoImage *image)
2240 {
2241         MonoDynamicTable *table;
2242         guint32 token;
2243         guint32 *values;
2244         guint32 cols [MONO_ASSEMBLY_SIZE];
2245         const char *pubkey;
2246         guint32 publen;
2247
2248         if ((token = GPOINTER_TO_UINT (g_hash_table_lookup (assembly->handleref, image))))
2249                 return token;
2250
2251         if (assembly_is_dynamic (image->assembly) && (image->assembly == assembly->image.assembly)) {
2252                 table = &assembly->tables [MONO_TABLE_MODULEREF];
2253                 token = table->next_idx ++;
2254                 table->rows ++;
2255                 alloc_table (table, table->rows);
2256                 values = table->values + token * MONO_MODULEREF_SIZE;
2257                 values [MONO_MODULEREF_NAME] = string_heap_insert (&assembly->sheap, image->module_name);
2258
2259                 token <<= MONO_RESOLUTION_SCOPE_BITS;
2260                 token |= MONO_RESOLUTION_SCOPE_MODULEREF;
2261                 g_hash_table_insert (assembly->handleref, image, GUINT_TO_POINTER (token));
2262
2263                 return token;
2264         }
2265         
2266         if (assembly_is_dynamic (image->assembly))
2267                 /* FIXME: */
2268                 memset (cols, 0, sizeof (cols));
2269         else {
2270                 /* image->assembly->image is the manifest module */
2271                 image = image->assembly->image;
2272                 mono_metadata_decode_row (&image->tables [MONO_TABLE_ASSEMBLY], 0, cols, MONO_ASSEMBLY_SIZE);
2273         }
2274
2275         table = &assembly->tables [MONO_TABLE_ASSEMBLYREF];
2276         token = table->next_idx ++;
2277         table->rows ++;
2278         alloc_table (table, table->rows);
2279         values = table->values + token * MONO_ASSEMBLYREF_SIZE;
2280         values [MONO_ASSEMBLYREF_NAME] = string_heap_insert (&assembly->sheap, image->assembly_name);
2281         values [MONO_ASSEMBLYREF_MAJOR_VERSION] = cols [MONO_ASSEMBLY_MAJOR_VERSION];
2282         values [MONO_ASSEMBLYREF_MINOR_VERSION] = cols [MONO_ASSEMBLY_MINOR_VERSION];
2283         values [MONO_ASSEMBLYREF_BUILD_NUMBER] = cols [MONO_ASSEMBLY_BUILD_NUMBER];
2284         values [MONO_ASSEMBLYREF_REV_NUMBER] = cols [MONO_ASSEMBLY_REV_NUMBER];
2285         values [MONO_ASSEMBLYREF_FLAGS] = 0;
2286         values [MONO_ASSEMBLYREF_CULTURE] = 0;
2287         values [MONO_ASSEMBLYREF_HASH_VALUE] = 0;
2288
2289         if (strcmp ("", image->assembly->aname.culture)) {
2290                 values [MONO_ASSEMBLYREF_CULTURE] = string_heap_insert (&assembly->sheap,
2291                                 image->assembly->aname.culture);
2292         }
2293
2294         if ((pubkey = mono_image_get_public_key (image, &publen))) {
2295                 guchar pubtoken [9];
2296                 pubtoken [0] = 8;
2297                 mono_digest_get_public_token (pubtoken + 1, (guchar*)pubkey, publen);
2298                 values [MONO_ASSEMBLYREF_PUBLIC_KEY] = mono_image_add_stream_data (&assembly->blob, (char*)pubtoken, 9);
2299         } else {
2300                 values [MONO_ASSEMBLYREF_PUBLIC_KEY] = 0;
2301         }
2302         token <<= MONO_RESOLUTION_SCOPE_BITS;
2303         token |= MONO_RESOLUTION_SCOPE_ASSEMBLYREF;
2304         g_hash_table_insert (assembly->handleref, image, GUINT_TO_POINTER (token));
2305         return token;
2306 }
2307
2308 static guint32
2309 create_typespec (MonoDynamicImage *assembly, MonoType *type)
2310 {
2311         MonoDynamicTable *table;
2312         guint32 *values;
2313         guint32 token;
2314         SigBuffer buf;
2315
2316         if ((token = GPOINTER_TO_UINT (g_hash_table_lookup (assembly->typespec, type))))
2317                 return token;
2318
2319         sigbuffer_init (&buf, 32);
2320         switch (type->type) {
2321         case MONO_TYPE_FNPTR:
2322         case MONO_TYPE_PTR:
2323         case MONO_TYPE_SZARRAY:
2324         case MONO_TYPE_ARRAY:
2325         case MONO_TYPE_VAR:
2326         case MONO_TYPE_MVAR:
2327         case MONO_TYPE_GENERICINST:
2328                 encode_type (assembly, type, &buf);
2329                 break;
2330         case MONO_TYPE_CLASS:
2331         case MONO_TYPE_VALUETYPE: {
2332                 MonoClass *k = mono_class_from_mono_type (type);
2333                 if (!k || !k->generic_container) {
2334                         sigbuffer_free (&buf);
2335                         return 0;
2336                 }
2337                 encode_type (assembly, type, &buf);
2338                 break;
2339         }
2340         default:
2341                 sigbuffer_free (&buf);
2342                 return 0;
2343         }
2344
2345         table = &assembly->tables [MONO_TABLE_TYPESPEC];
2346         if (assembly->save) {
2347                 token = sigbuffer_add_to_blob_cached (assembly, &buf);
2348                 alloc_table (table, table->rows + 1);
2349                 values = table->values + table->next_idx * MONO_TYPESPEC_SIZE;
2350                 values [MONO_TYPESPEC_SIGNATURE] = token;
2351         }
2352         sigbuffer_free (&buf);
2353
2354         token = MONO_TYPEDEFORREF_TYPESPEC | (table->next_idx << MONO_TYPEDEFORREF_BITS);
2355         g_hash_table_insert (assembly->typespec, type, GUINT_TO_POINTER(token));
2356         table->next_idx ++;
2357         return token;
2358 }
2359
2360 static guint32
2361 mono_image_typedef_or_ref_full (MonoDynamicImage *assembly, MonoType *type, gboolean try_typespec)
2362 {
2363         MonoDynamicTable *table;
2364         guint32 *values;
2365         guint32 token, scope, enclosing;
2366         MonoClass *klass;
2367
2368         /* if the type requires a typespec, we must try that first*/
2369         if (try_typespec && (token = create_typespec (assembly, type)))
2370                 return token;
2371         token = GPOINTER_TO_UINT (g_hash_table_lookup (assembly->typeref, type));
2372         if (token)
2373                 return token;
2374         klass = mono_class_from_mono_type (type);
2375         if (!klass)
2376                 klass = mono_class_from_mono_type (type);
2377
2378         /*
2379          * If it's in the same module and not a generic type parameter:
2380          */
2381         if ((klass->image == &assembly->image) && (type->type != MONO_TYPE_VAR) && 
2382                         (type->type != MONO_TYPE_MVAR)) {
2383                 MonoReflectionTypeBuilder *tb = mono_class_get_ref_info (klass);
2384                 token = MONO_TYPEDEFORREF_TYPEDEF | (tb->table_idx << MONO_TYPEDEFORREF_BITS);
2385                 mono_g_hash_table_insert (assembly->tokens, GUINT_TO_POINTER (token), mono_class_get_ref_info (klass));
2386                 return token;
2387         }
2388
2389         if (klass->nested_in) {
2390                 enclosing = mono_image_typedef_or_ref_full (assembly, &klass->nested_in->byval_arg, FALSE);
2391                 /* get the typeref idx of the enclosing type */
2392                 enclosing >>= MONO_TYPEDEFORREF_BITS;
2393                 scope = (enclosing << MONO_RESOLUTION_SCOPE_BITS) | MONO_RESOLUTION_SCOPE_TYPEREF;
2394         } else {
2395                 scope = resolution_scope_from_image (assembly, klass->image);
2396         }
2397         table = &assembly->tables [MONO_TABLE_TYPEREF];
2398         if (assembly->save) {
2399                 alloc_table (table, table->rows + 1);
2400                 values = table->values + table->next_idx * MONO_TYPEREF_SIZE;
2401                 values [MONO_TYPEREF_SCOPE] = scope;
2402                 values [MONO_TYPEREF_NAME] = string_heap_insert (&assembly->sheap, klass->name);
2403                 values [MONO_TYPEREF_NAMESPACE] = string_heap_insert (&assembly->sheap, klass->name_space);
2404         }
2405         token = MONO_TYPEDEFORREF_TYPEREF | (table->next_idx << MONO_TYPEDEFORREF_BITS); /* typeref */
2406         g_hash_table_insert (assembly->typeref, type, GUINT_TO_POINTER(token));
2407         table->next_idx ++;
2408         mono_g_hash_table_insert (assembly->tokens, GUINT_TO_POINTER (token), mono_class_get_ref_info (klass));
2409         return token;
2410 }
2411
2412 /*
2413  * Despite the name, we handle also TypeSpec (with the above helper).
2414  */
2415 static guint32
2416 mono_image_typedef_or_ref (MonoDynamicImage *assembly, MonoType *type)
2417 {
2418         return mono_image_typedef_or_ref_full (assembly, type, TRUE);
2419 }
2420
2421 #ifndef DISABLE_REFLECTION_EMIT
2422 static guint32
2423 mono_image_add_memberef_row (MonoDynamicImage *assembly, guint32 parent, const char *name, guint32 sig)
2424 {
2425         MonoDynamicTable *table;
2426         guint32 *values;
2427         guint32 token, pclass;
2428
2429         switch (parent & MONO_TYPEDEFORREF_MASK) {
2430         case MONO_TYPEDEFORREF_TYPEREF:
2431                 pclass = MONO_MEMBERREF_PARENT_TYPEREF;
2432                 break;
2433         case MONO_TYPEDEFORREF_TYPESPEC:
2434                 pclass = MONO_MEMBERREF_PARENT_TYPESPEC;
2435                 break;
2436         case MONO_TYPEDEFORREF_TYPEDEF:
2437                 pclass = MONO_MEMBERREF_PARENT_TYPEDEF;
2438                 break;
2439         default:
2440                 g_warning ("unknown typeref or def token 0x%08x for %s", parent, name);
2441                 return 0;
2442         }
2443         /* extract the index */
2444         parent >>= MONO_TYPEDEFORREF_BITS;
2445
2446         table = &assembly->tables [MONO_TABLE_MEMBERREF];
2447
2448         if (assembly->save) {
2449                 alloc_table (table, table->rows + 1);
2450                 values = table->values + table->next_idx * MONO_MEMBERREF_SIZE;
2451                 values [MONO_MEMBERREF_CLASS] = pclass | (parent << MONO_MEMBERREF_PARENT_BITS);
2452                 values [MONO_MEMBERREF_NAME] = string_heap_insert (&assembly->sheap, name);
2453                 values [MONO_MEMBERREF_SIGNATURE] = sig;
2454         }
2455
2456         token = MONO_TOKEN_MEMBER_REF | table->next_idx;
2457         table->next_idx ++;
2458
2459         return token;
2460 }
2461
2462 /*
2463  * Insert a memberef row into the metadata: the token that point to the memberref
2464  * is returned. Caching is done in the caller (mono_image_get_methodref_token() or
2465  * mono_image_get_fieldref_token()).
2466  * The sig param is an index to an already built signature.
2467  */
2468 static guint32
2469 mono_image_get_memberref_token (MonoDynamicImage *assembly, MonoType *type, const char *name, guint32 sig)
2470 {
2471         guint32 parent = mono_image_typedef_or_ref (assembly, type);
2472         return mono_image_add_memberef_row (assembly, parent, name, sig);
2473 }
2474
2475
2476 static guint32
2477 mono_image_get_methodref_token (MonoDynamicImage *assembly, MonoMethod *method, gboolean create_typespec)
2478 {
2479         guint32 token;
2480         MonoMethodSignature *sig;
2481         
2482         create_typespec = create_typespec && method->is_generic && method->klass->image != &assembly->image;
2483
2484         if (create_typespec) {
2485                 token = GPOINTER_TO_UINT (g_hash_table_lookup (assembly->handleref, GUINT_TO_POINTER (GPOINTER_TO_UINT (method) + 1)));
2486                 if (token)
2487                         return token;
2488         } 
2489
2490         token = GPOINTER_TO_UINT (g_hash_table_lookup (assembly->handleref, method));
2491         if (token && !create_typespec)
2492                 return token;
2493
2494         g_assert (!method->is_inflated);
2495         if (!token) {
2496                 /*
2497                  * A methodref signature can't contain an unmanaged calling convention.
2498                  */
2499                 sig = mono_metadata_signature_dup (mono_method_signature (method));
2500                 if ((sig->call_convention != MONO_CALL_DEFAULT) && (sig->call_convention != MONO_CALL_VARARG))
2501                         sig->call_convention = MONO_CALL_DEFAULT;
2502                 token = mono_image_get_memberref_token (assembly, &method->klass->byval_arg,
2503                         method->name,  method_encode_signature (assembly, sig));
2504                 g_free (sig);
2505                 g_hash_table_insert (assembly->handleref, method, GUINT_TO_POINTER(token));
2506         }
2507
2508         if (create_typespec) {
2509                 MonoDynamicTable *table = &assembly->tables [MONO_TABLE_METHODSPEC];
2510                 g_assert (mono_metadata_token_table (token) == MONO_TABLE_MEMBERREF);
2511                 token = (mono_metadata_token_index (token) << MONO_METHODDEFORREF_BITS) | MONO_METHODDEFORREF_METHODREF;
2512
2513                 if (assembly->save) {
2514                         guint32 *values;
2515
2516                         alloc_table (table, table->rows + 1);
2517                         values = table->values + table->next_idx * MONO_METHODSPEC_SIZE;
2518                         values [MONO_METHODSPEC_METHOD] = token;
2519                         values [MONO_METHODSPEC_SIGNATURE] = encode_generic_method_sig (assembly, &mono_method_get_generic_container (method)->context);
2520                 }
2521
2522                 token = MONO_TOKEN_METHOD_SPEC | table->next_idx;
2523                 table->next_idx ++;
2524                 /*methodspec and memberef tokens are diferent, */
2525                 g_hash_table_insert (assembly->handleref, GUINT_TO_POINTER (GPOINTER_TO_UINT (method) + 1), GUINT_TO_POINTER (token));
2526                 return token;
2527         }
2528         return token;
2529 }
2530
2531 static guint32
2532 mono_image_get_methodref_token_for_methodbuilder (MonoDynamicImage *assembly, MonoReflectionMethodBuilder *method)
2533 {
2534         guint32 token, parent, sig;
2535         ReflectionMethodBuilder rmb;
2536         char *name;
2537         MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder *)method->type;
2538         
2539         token = GPOINTER_TO_UINT (g_hash_table_lookup (assembly->handleref, method));
2540         if (token)
2541                 return token;
2542
2543         name = mono_string_to_utf8 (method->name);
2544         reflection_methodbuilder_from_method_builder (&rmb, method);
2545
2546         /*
2547          * A methodref signature can't contain an unmanaged calling convention.
2548          * Since some flags are encoded as part of call_conv, we need to check against it.
2549         */
2550         if ((rmb.call_conv & ~0x60) != MONO_CALL_DEFAULT && (rmb.call_conv & ~0x60) != MONO_CALL_VARARG)
2551                 rmb.call_conv = (rmb.call_conv & 0x60) | MONO_CALL_DEFAULT;
2552
2553         sig = method_builder_encode_signature (assembly, &rmb);
2554
2555         if (tb->generic_params)
2556                 parent = create_generic_typespec (assembly, tb);
2557         else
2558                 parent = mono_image_typedef_or_ref (assembly, mono_reflection_type_get_handle ((MonoReflectionType*)rmb.type));
2559
2560         token = mono_image_add_memberef_row (assembly, parent, name, sig);
2561
2562         g_free (name);
2563         g_hash_table_insert (assembly->handleref, method, GUINT_TO_POINTER(token));
2564         return token;
2565 }
2566
2567 static guint32
2568 mono_image_get_varargs_method_token (MonoDynamicImage *assembly, guint32 original,
2569                                      const gchar *name, guint32 sig)
2570 {
2571         MonoDynamicTable *table;
2572         guint32 token;
2573         guint32 *values;
2574         
2575         table = &assembly->tables [MONO_TABLE_MEMBERREF];
2576
2577         if (assembly->save) {
2578                 alloc_table (table, table->rows + 1);
2579                 values = table->values + table->next_idx * MONO_MEMBERREF_SIZE;
2580                 values [MONO_MEMBERREF_CLASS] = original;
2581                 values [MONO_MEMBERREF_NAME] = string_heap_insert (&assembly->sheap, name);
2582                 values [MONO_MEMBERREF_SIGNATURE] = sig;
2583         }
2584
2585         token = MONO_TOKEN_MEMBER_REF | table->next_idx;
2586         table->next_idx ++;
2587
2588         return token;
2589 }
2590
2591 static guint32
2592 encode_generic_method_definition_sig (MonoDynamicImage *assembly, MonoReflectionMethodBuilder *mb)
2593 {
2594         SigBuffer buf;
2595         int i;
2596         guint32 nparams = mono_array_length (mb->generic_params);
2597         guint32 idx;
2598
2599         if (!assembly->save)
2600                 return 0;
2601
2602         sigbuffer_init (&buf, 32);
2603
2604         sigbuffer_add_value (&buf, 0xa);
2605         sigbuffer_add_value (&buf, nparams);
2606
2607         for (i = 0; i < nparams; i++) {
2608                 sigbuffer_add_value (&buf, MONO_TYPE_MVAR);
2609                 sigbuffer_add_value (&buf, i);
2610         }
2611
2612         idx = sigbuffer_add_to_blob_cached (assembly, &buf);
2613         sigbuffer_free (&buf);
2614         return idx;
2615 }
2616
2617 static guint32
2618 mono_image_get_methodspec_token_for_generic_method_definition (MonoDynamicImage *assembly, MonoReflectionMethodBuilder *mb)
2619 {
2620         MonoDynamicTable *table;
2621         guint32 *values;
2622         guint32 token, mtoken = 0;
2623
2624         token = GPOINTER_TO_UINT (mono_g_hash_table_lookup (assembly->methodspec, mb));
2625         if (token)
2626                 return token;
2627
2628         table = &assembly->tables [MONO_TABLE_METHODSPEC];
2629
2630         mtoken = mono_image_get_methodref_token_for_methodbuilder (assembly, mb);
2631         switch (mono_metadata_token_table (mtoken)) {
2632         case MONO_TABLE_MEMBERREF:
2633                 mtoken = (mono_metadata_token_index (mtoken) << MONO_METHODDEFORREF_BITS) | MONO_METHODDEFORREF_METHODREF;
2634                 break;
2635         case MONO_TABLE_METHOD:
2636                 mtoken = (mono_metadata_token_index (mtoken) << MONO_METHODDEFORREF_BITS) | MONO_METHODDEFORREF_METHODDEF;
2637                 break;
2638         default:
2639                 g_assert_not_reached ();
2640         }
2641
2642         if (assembly->save) {
2643                 alloc_table (table, table->rows + 1);
2644                 values = table->values + table->next_idx * MONO_METHODSPEC_SIZE;
2645                 values [MONO_METHODSPEC_METHOD] = mtoken;
2646                 values [MONO_METHODSPEC_SIGNATURE] = encode_generic_method_definition_sig (assembly, mb);
2647         }
2648
2649         token = MONO_TOKEN_METHOD_SPEC | table->next_idx;
2650         table->next_idx ++;
2651
2652         mono_g_hash_table_insert (assembly->methodspec, mb, GUINT_TO_POINTER(token));
2653         return token;
2654 }
2655
2656 static guint32
2657 mono_image_get_methodbuilder_token (MonoDynamicImage *assembly, MonoReflectionMethodBuilder *mb, gboolean create_methodspec)
2658 {
2659         guint32 token;
2660
2661         if (mb->generic_params && create_methodspec) 
2662                 return mono_image_get_methodspec_token_for_generic_method_definition (assembly, mb);
2663
2664         token = GPOINTER_TO_UINT (mono_g_hash_table_lookup (assembly->handleref_managed, mb));
2665         if (token)
2666                 return token;
2667
2668         token = mono_image_get_methodref_token_for_methodbuilder (assembly, mb);
2669         mono_g_hash_table_insert (assembly->handleref_managed, mb, GUINT_TO_POINTER(token));
2670         return token;
2671 }
2672
2673 static guint32
2674 mono_image_get_ctorbuilder_token (MonoDynamicImage *assembly, MonoReflectionCtorBuilder *mb)
2675 {
2676         guint32 token, parent, sig;
2677         ReflectionMethodBuilder rmb;
2678         char *name;
2679         MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder *)mb->type;
2680         
2681         token = GPOINTER_TO_UINT (mono_g_hash_table_lookup (assembly->handleref_managed, mb));
2682         if (token)
2683                 return token;
2684
2685         reflection_methodbuilder_from_ctor_builder (&rmb, mb);
2686
2687         if (tb->generic_params)
2688                 parent = create_generic_typespec (assembly, tb);
2689         else
2690                 parent = mono_image_typedef_or_ref (assembly, mono_reflection_type_get_handle ((MonoReflectionType*)tb));
2691         
2692         name = mono_string_to_utf8 (rmb.name);
2693         sig = method_builder_encode_signature (assembly, &rmb);
2694
2695         token = mono_image_add_memberef_row (assembly, parent, name, sig);
2696
2697         g_free (name);
2698         mono_g_hash_table_insert (assembly->handleref_managed, mb, GUINT_TO_POINTER(token));
2699         return token;
2700 }
2701 #endif
2702
2703 static gboolean
2704 is_field_on_inst (MonoClassField *field)
2705 {
2706         return (field->parent->generic_class && field->parent->generic_class->is_dynamic && ((MonoDynamicGenericClass*)field->parent->generic_class)->fields);
2707 }
2708
2709 /*
2710  * If FIELD is a field of a MonoDynamicGenericClass, return its non-inflated type.
2711  */
2712 static MonoType*
2713 get_field_on_inst_generic_type (MonoClassField *field)
2714 {
2715         MonoClass *class, *gtd;
2716         MonoDynamicGenericClass *dgclass;
2717         int field_index;
2718
2719         g_assert (is_field_on_inst (field));
2720
2721         dgclass = (MonoDynamicGenericClass*)field->parent->generic_class;
2722
2723         if (field >= dgclass->fields && field - dgclass->fields < dgclass->count_fields) {
2724                 field_index = field - dgclass->fields;
2725                 return dgclass->field_generic_types [field_index];              
2726         }
2727
2728         class = field->parent;
2729         gtd = class->generic_class->container_class;
2730
2731         if (field >= class->fields && field - class->fields < class->field.count) {
2732                 field_index = field - class->fields;
2733                 return gtd->fields [field_index].type;
2734         }
2735
2736         g_assert_not_reached ();
2737         return 0;
2738 }
2739
2740 #ifndef DISABLE_REFLECTION_EMIT
2741 static guint32
2742 mono_image_get_fieldref_token (MonoDynamicImage *assembly, MonoObject *f, MonoClassField *field)
2743 {
2744         MonoType *type;
2745         guint32 token;
2746
2747         g_assert (field);
2748         g_assert (field->parent);
2749
2750         token = GPOINTER_TO_UINT (mono_g_hash_table_lookup (assembly->handleref_managed, f));
2751         if (token)
2752                 return token;
2753
2754         if (field->parent->generic_class && field->parent->generic_class->container_class && field->parent->generic_class->container_class->fields) {
2755                 int index = field - field->parent->fields;
2756                 type = mono_field_get_type (&field->parent->generic_class->container_class->fields [index]);
2757         } else {
2758                 if (is_field_on_inst (field))
2759                         type = get_field_on_inst_generic_type (field);
2760                 else
2761                         type = mono_field_get_type (field);
2762         }
2763         token = mono_image_get_memberref_token (assembly, &field->parent->byval_arg,
2764                                                                                         mono_field_get_name (field),
2765                                                                                         fieldref_encode_signature (assembly, field->parent->image, type));
2766         mono_g_hash_table_insert (assembly->handleref_managed, f, GUINT_TO_POINTER(token));
2767         return token;
2768 }
2769
2770 static guint32
2771 mono_image_get_field_on_inst_token (MonoDynamicImage *assembly, MonoReflectionFieldOnTypeBuilderInst *f)
2772 {
2773         guint32 token;
2774         MonoClass *klass;
2775         MonoGenericClass *gclass;
2776         MonoType *type;
2777         char *name;
2778
2779         token = GPOINTER_TO_UINT (mono_g_hash_table_lookup (assembly->handleref_managed, f));
2780         if (token)
2781                 return token;
2782         if (is_sre_field_builder (mono_object_class (f->fb))) {
2783                 MonoReflectionFieldBuilder *fb = (MonoReflectionFieldBuilder *)f->fb;
2784                 type = mono_reflection_type_get_handle ((MonoReflectionType*)f->inst);
2785                 klass = mono_class_from_mono_type (type);
2786                 gclass = type->data.generic_class;
2787                 g_assert (gclass->is_dynamic);
2788
2789                 name = mono_string_to_utf8 (fb->name);
2790                 token = mono_image_get_memberref_token (assembly, &klass->byval_arg, name, 
2791                                                                                                 field_encode_signature (assembly, fb));
2792                 g_free (name);          
2793         } else if (is_sr_mono_field (mono_object_class (f->fb))) {
2794                 guint32 sig;
2795                 MonoClassField *field = ((MonoReflectionField *)f->fb)->field;
2796
2797                 type = mono_reflection_type_get_handle ((MonoReflectionType*)f->inst);
2798                 klass = mono_class_from_mono_type (type);
2799
2800                 sig = fieldref_encode_signature (assembly, field->parent->image, field->type);
2801                 token = mono_image_get_memberref_token (assembly, &klass->byval_arg, field->name, sig);
2802         } else {
2803                 char *name = mono_type_get_full_name (mono_object_class (f->fb));
2804                 g_error ("mono_image_get_field_on_inst_token: don't know how to handle %s", name);
2805         }
2806
2807         mono_g_hash_table_insert (assembly->handleref_managed, f, GUINT_TO_POINTER (token));
2808         return token;
2809 }
2810
2811 static guint32
2812 mono_image_get_ctor_on_inst_token (MonoDynamicImage *assembly, MonoReflectionCtorOnTypeBuilderInst *c, gboolean create_methodspec)
2813 {
2814         guint32 sig, token;
2815         MonoClass *klass;
2816         MonoGenericClass *gclass;
2817         MonoType *type;
2818
2819         /* A ctor cannot be a generic method, so we can ignore create_methodspec */
2820
2821         token = GPOINTER_TO_UINT (mono_g_hash_table_lookup (assembly->handleref_managed, c));
2822         if (token)
2823                 return token;
2824
2825         if (is_sre_ctor_builder (mono_object_class (c->cb))) {
2826                 MonoReflectionCtorBuilder *cb = (MonoReflectionCtorBuilder *)c->cb;
2827                 ReflectionMethodBuilder rmb;
2828                 char *name;
2829
2830                 type = mono_reflection_type_get_handle ((MonoReflectionType*)c->inst);
2831                 klass = mono_class_from_mono_type (type);
2832
2833                 gclass = type->data.generic_class;
2834                 g_assert (gclass->is_dynamic);
2835
2836                 reflection_methodbuilder_from_ctor_builder (&rmb, cb);
2837
2838                 name = mono_string_to_utf8 (rmb.name);
2839
2840                 sig = method_builder_encode_signature (assembly, &rmb);
2841
2842                 token = mono_image_get_memberref_token (assembly, &klass->byval_arg, name, sig);
2843                 g_free (name);
2844         } else if (is_sr_mono_cmethod (mono_object_class (c->cb))) {
2845                 MonoMethod *mm = ((MonoReflectionMethod *)c->cb)->method;
2846
2847                 type = mono_reflection_type_get_handle ((MonoReflectionType*)c->inst);
2848                 klass = mono_class_from_mono_type (type);
2849
2850                 sig = method_encode_signature (assembly, mono_method_signature (mm));
2851                 token = mono_image_get_memberref_token (assembly, &klass->byval_arg, mm->name, sig);
2852         } else {
2853                 char *name = mono_type_get_full_name (mono_object_class (c->cb));
2854                 g_error ("mono_image_get_method_on_inst_token: don't know how to handle %s", name);
2855         }
2856
2857
2858         mono_g_hash_table_insert (assembly->handleref_managed, c, GUINT_TO_POINTER (token));
2859         return token;
2860 }
2861
2862 static MonoMethod*
2863 mono_reflection_method_on_tb_inst_get_handle (MonoReflectionMethodOnTypeBuilderInst *m)
2864 {
2865         MonoError error;
2866         MonoClass *klass;
2867         MonoGenericContext tmp_context;
2868         MonoType **type_argv;
2869         MonoGenericInst *ginst;
2870         MonoMethod *method, *inflated;
2871         int count, i;
2872
2873         init_type_builder_generics ((MonoObject*)m->inst);
2874
2875         method = inflate_method (m->inst, (MonoObject*)m->mb);
2876
2877         klass = method->klass;
2878
2879         if (m->method_args == NULL)
2880                 return method;
2881
2882         if (method->is_inflated)
2883                 method = ((MonoMethodInflated *) method)->declaring;
2884
2885         count = mono_array_length (m->method_args);
2886
2887         type_argv = g_new0 (MonoType *, count);
2888         for (i = 0; i < count; i++) {
2889                 MonoReflectionType *garg = mono_array_get (m->method_args, gpointer, i);
2890                 type_argv [i] = mono_reflection_type_get_handle (garg);
2891         }
2892         ginst = mono_metadata_get_generic_inst (count, type_argv);
2893         g_free (type_argv);
2894
2895         tmp_context.class_inst = klass->generic_class ? klass->generic_class->context.class_inst : NULL;
2896         tmp_context.method_inst = ginst;
2897
2898         inflated = mono_class_inflate_generic_method_checked (method, &tmp_context, &error);
2899         g_assert (mono_error_ok (&error)); /* FIXME don't swallow the error */
2900         return inflated;
2901 }
2902
2903 static guint32
2904 mono_image_get_method_on_inst_token (MonoDynamicImage *assembly, MonoReflectionMethodOnTypeBuilderInst *m, gboolean create_methodspec)
2905 {
2906         guint32 sig, token = 0;
2907         MonoType *type;
2908         MonoClass *klass;
2909
2910         if (m->method_args) {
2911                 MonoMethod *inflated;
2912
2913                 inflated = mono_reflection_method_on_tb_inst_get_handle (m);
2914                 if (create_methodspec)
2915                         token = mono_image_get_methodspec_token (assembly, inflated);
2916                 else
2917                         token = mono_image_get_inflated_method_token (assembly, inflated);
2918                 return token;
2919         }
2920
2921         token = GPOINTER_TO_UINT (mono_g_hash_table_lookup (assembly->handleref_managed, m));
2922         if (token)
2923                 return token;
2924
2925         if (is_sre_method_builder (mono_object_class (m->mb))) {
2926                 MonoReflectionMethodBuilder *mb = (MonoReflectionMethodBuilder *)m->mb;
2927                 MonoGenericClass *gclass;
2928                 ReflectionMethodBuilder rmb;
2929                 char *name;
2930
2931                 type = mono_reflection_type_get_handle ((MonoReflectionType*)m->inst);
2932                 klass = mono_class_from_mono_type (type);
2933                 gclass = type->data.generic_class;
2934                 g_assert (gclass->is_dynamic);
2935
2936                 reflection_methodbuilder_from_method_builder (&rmb, mb);
2937
2938                 name = mono_string_to_utf8 (rmb.name);
2939
2940                 sig = method_builder_encode_signature (assembly, &rmb);
2941
2942                 token = mono_image_get_memberref_token (assembly, &klass->byval_arg, name, sig);
2943                 g_free (name);          
2944         } else if (is_sr_mono_method (mono_object_class (m->mb))) {
2945                 MonoMethod *mm = ((MonoReflectionMethod *)m->mb)->method;
2946
2947                 type = mono_reflection_type_get_handle ((MonoReflectionType*)m->inst);
2948                 klass = mono_class_from_mono_type (type);
2949
2950                 sig = method_encode_signature (assembly, mono_method_signature (mm));
2951                 token = mono_image_get_memberref_token (assembly, &klass->byval_arg, mm->name, sig);
2952         } else {
2953                 char *name = mono_type_get_full_name (mono_object_class (m->mb));
2954                 g_error ("mono_image_get_method_on_inst_token: don't know how to handle %s", name);
2955         }
2956
2957         mono_g_hash_table_insert (assembly->handleref_managed, m, GUINT_TO_POINTER (token));
2958         return token;
2959 }
2960
2961 static guint32
2962 encode_generic_method_sig (MonoDynamicImage *assembly, MonoGenericContext *context)
2963 {
2964         SigBuffer buf;
2965         int i;
2966         guint32 nparams = context->method_inst->type_argc;
2967         guint32 idx;
2968
2969         if (!assembly->save)
2970                 return 0;
2971
2972         sigbuffer_init (&buf, 32);
2973         /*
2974          * FIXME: vararg, explicit_this, differenc call_conv values...
2975          */
2976         sigbuffer_add_value (&buf, 0xa); /* FIXME FIXME FIXME */
2977         sigbuffer_add_value (&buf, nparams);
2978
2979         for (i = 0; i < nparams; i++)
2980                 encode_type (assembly, context->method_inst->type_argv [i], &buf);
2981
2982         idx = sigbuffer_add_to_blob_cached (assembly, &buf);
2983         sigbuffer_free (&buf);
2984         return idx;
2985 }
2986
2987 static guint32
2988 method_encode_methodspec (MonoDynamicImage *assembly, MonoMethod *method)
2989 {
2990         MonoDynamicTable *table;
2991         guint32 *values;
2992         guint32 token, mtoken = 0, sig;
2993         MonoMethodInflated *imethod;
2994         MonoMethod *declaring;
2995
2996         table = &assembly->tables [MONO_TABLE_METHODSPEC];
2997
2998         g_assert (method->is_inflated);
2999         imethod = (MonoMethodInflated *) method;
3000         declaring = imethod->declaring;
3001
3002         sig = method_encode_signature (assembly, mono_method_signature (declaring));
3003         mtoken = mono_image_get_memberref_token (assembly, &method->klass->byval_arg, declaring->name, sig);
3004
3005         if (!mono_method_signature (declaring)->generic_param_count)
3006                 return mtoken;
3007
3008         switch (mono_metadata_token_table (mtoken)) {
3009         case MONO_TABLE_MEMBERREF:
3010                 mtoken = (mono_metadata_token_index (mtoken) << MONO_METHODDEFORREF_BITS) | MONO_METHODDEFORREF_METHODREF;
3011                 break;
3012         case MONO_TABLE_METHOD:
3013                 mtoken = (mono_metadata_token_index (mtoken) << MONO_METHODDEFORREF_BITS) | MONO_METHODDEFORREF_METHODDEF;
3014                 break;
3015         default:
3016                 g_assert_not_reached ();
3017         }
3018
3019         sig = encode_generic_method_sig (assembly, mono_method_get_context (method));
3020
3021         if (assembly->save) {
3022                 alloc_table (table, table->rows + 1);
3023                 values = table->values + table->next_idx * MONO_METHODSPEC_SIZE;
3024                 values [MONO_METHODSPEC_METHOD] = mtoken;
3025                 values [MONO_METHODSPEC_SIGNATURE] = sig;
3026         }
3027
3028         token = MONO_TOKEN_METHOD_SPEC | table->next_idx;
3029         table->next_idx ++;
3030
3031         return token;
3032 }
3033
3034 static guint32
3035 mono_image_get_methodspec_token (MonoDynamicImage *assembly, MonoMethod *method)
3036 {
3037         MonoMethodInflated *imethod;
3038         guint32 token;
3039         
3040         token = GPOINTER_TO_UINT (g_hash_table_lookup (assembly->handleref, method));
3041         if (token)
3042                 return token;
3043
3044         g_assert (method->is_inflated);
3045         imethod = (MonoMethodInflated *) method;
3046
3047         if (mono_method_signature (imethod->declaring)->generic_param_count) {
3048                 token = method_encode_methodspec (assembly, method);
3049         } else {
3050                 guint32 sig = method_encode_signature (
3051                         assembly, mono_method_signature (imethod->declaring));
3052                 token = mono_image_get_memberref_token (
3053                         assembly, &method->klass->byval_arg, method->name, sig);
3054         }
3055
3056         g_hash_table_insert (assembly->handleref, method, GUINT_TO_POINTER(token));
3057         return token;
3058 }
3059
3060 static guint32
3061 mono_image_get_inflated_method_token (MonoDynamicImage *assembly, MonoMethod *m)
3062 {
3063         MonoMethodInflated *imethod = (MonoMethodInflated *) m;
3064         guint32 sig, token;
3065
3066         sig = method_encode_signature (assembly, mono_method_signature (imethod->declaring));
3067         token = mono_image_get_memberref_token (
3068                 assembly, &m->klass->byval_arg, m->name, sig);
3069
3070         return token;
3071 }
3072
3073 static guint32
3074 create_generic_typespec (MonoDynamicImage *assembly, MonoReflectionTypeBuilder *tb)
3075 {
3076         MonoDynamicTable *table;
3077         MonoClass *klass;
3078         MonoType *type;
3079         guint32 *values;
3080         guint32 token;
3081         SigBuffer buf;
3082         int count, i;
3083
3084         /*
3085          * We're creating a TypeSpec for the TypeBuilder of a generic type declaration,
3086          * ie. what we'd normally use as the generic type in a TypeSpec signature.
3087          * Because of this, we must not insert it into the `typeref' hash table.
3088          */
3089         type = mono_reflection_type_get_handle ((MonoReflectionType*)tb);
3090         token = GPOINTER_TO_UINT (g_hash_table_lookup (assembly->typespec, type));
3091         if (token)
3092                 return token;
3093
3094         sigbuffer_init (&buf, 32);
3095
3096         g_assert (tb->generic_params);
3097         klass = mono_class_from_mono_type (type);
3098
3099         if (tb->generic_container)
3100                 mono_reflection_create_generic_class (tb);
3101
3102         sigbuffer_add_value (&buf, MONO_TYPE_GENERICINST);
3103         g_assert (klass->generic_container);
3104         sigbuffer_add_value (&buf, klass->byval_arg.type);
3105         sigbuffer_add_value (&buf, mono_image_typedef_or_ref_full (assembly, &klass->byval_arg, FALSE));
3106
3107         count = mono_array_length (tb->generic_params);
3108         sigbuffer_add_value (&buf, count);
3109         for (i = 0; i < count; i++) {
3110                 MonoReflectionGenericParam *gparam;
3111
3112                 gparam = mono_array_get (tb->generic_params, MonoReflectionGenericParam *, i);
3113
3114                 encode_type (assembly, mono_reflection_type_get_handle ((MonoReflectionType*)gparam), &buf);
3115         }
3116
3117         table = &assembly->tables [MONO_TABLE_TYPESPEC];
3118
3119         if (assembly->save) {
3120                 token = sigbuffer_add_to_blob_cached (assembly, &buf);
3121                 alloc_table (table, table->rows + 1);
3122                 values = table->values + table->next_idx * MONO_TYPESPEC_SIZE;
3123                 values [MONO_TYPESPEC_SIGNATURE] = token;
3124         }
3125         sigbuffer_free (&buf);
3126
3127         token = MONO_TYPEDEFORREF_TYPESPEC | (table->next_idx << MONO_TYPEDEFORREF_BITS);
3128         g_hash_table_insert (assembly->typespec, type, GUINT_TO_POINTER(token));
3129         table->next_idx ++;
3130         return token;
3131 }
3132
3133 /*
3134  * Return a copy of TYPE, adding the custom modifiers in MODREQ and MODOPT.
3135  */
3136 static MonoType*
3137 add_custom_modifiers (MonoDynamicImage *assembly, MonoType *type, MonoArray *modreq, MonoArray *modopt)
3138 {
3139         int i, count, len, pos;
3140         MonoType *t;
3141
3142         count = 0;
3143         if (modreq)
3144                 count += mono_array_length (modreq);
3145         if (modopt)
3146                 count += mono_array_length (modopt);
3147
3148         if (count == 0)
3149                 return mono_metadata_type_dup (NULL, type);
3150
3151         len = MONO_SIZEOF_TYPE + ((gint32)count) * sizeof (MonoCustomMod);
3152         t = g_malloc (len);
3153         memcpy (t, type, MONO_SIZEOF_TYPE);
3154
3155         t->num_mods = count;
3156         pos = 0;
3157         if (modreq) {
3158                 for (i = 0; i < mono_array_length (modreq); ++i) {
3159                         MonoType *mod = mono_type_array_get_and_resolve (modreq, i);
3160                         t->modifiers [pos].required = 1;
3161                         t->modifiers [pos].token = mono_image_typedef_or_ref (assembly, mod);
3162                         pos ++;
3163                 }
3164         }
3165         if (modopt) {
3166                 for (i = 0; i < mono_array_length (modopt); ++i) {
3167                         MonoType *mod = mono_type_array_get_and_resolve (modopt, i);
3168                         t->modifiers [pos].required = 0;
3169                         t->modifiers [pos].token = mono_image_typedef_or_ref (assembly, mod);
3170                         pos ++;
3171                 }
3172         }
3173
3174         return t;
3175 }
3176
3177 static void
3178 init_type_builder_generics (MonoObject *type)
3179 {
3180         MonoReflectionTypeBuilder *tb;
3181
3182         if (!is_sre_type_builder(mono_object_class (type)))
3183                 return;
3184         tb = (MonoReflectionTypeBuilder *)type;
3185
3186         if (tb && tb->generic_container)
3187                 mono_reflection_create_generic_class (tb);
3188 }
3189
3190 static guint32
3191 mono_image_get_generic_field_token (MonoDynamicImage *assembly, MonoReflectionFieldBuilder *fb)
3192 {
3193         MonoDynamicTable *table;
3194         MonoType *custom = NULL, *type;
3195         guint32 *values;
3196         guint32 token, pclass, parent, sig;
3197         gchar *name;
3198
3199         token = GPOINTER_TO_UINT (mono_g_hash_table_lookup (assembly->handleref_managed, fb));
3200         if (token)
3201                 return token;
3202
3203         /* FIXME: is this call necessary? */
3204         mono_class_from_mono_type (mono_reflection_type_get_handle (fb->typeb));
3205         name = mono_string_to_utf8 (fb->name);
3206
3207         /*FIXME this is one more layer of ugliness due how types are created.*/
3208         init_type_builder_generics (fb->type);
3209
3210         /* fb->type does not include the custom modifiers */
3211         /* FIXME: We should do this in one place when a fieldbuilder is created */
3212         type = mono_reflection_type_get_handle ((MonoReflectionType*)fb->type);
3213         if (fb->modreq || fb->modopt)
3214                 type = custom = add_custom_modifiers (assembly, type, fb->modreq, fb->modopt);
3215
3216         sig = fieldref_encode_signature (assembly, NULL, type);
3217         g_free (custom);
3218
3219         parent = create_generic_typespec (assembly, (MonoReflectionTypeBuilder *) fb->typeb);
3220         g_assert ((parent & MONO_TYPEDEFORREF_MASK) == MONO_TYPEDEFORREF_TYPESPEC);
3221         
3222         pclass = MONO_MEMBERREF_PARENT_TYPESPEC;
3223         parent >>= MONO_TYPEDEFORREF_BITS;
3224
3225         table = &assembly->tables [MONO_TABLE_MEMBERREF];
3226
3227         if (assembly->save) {
3228                 alloc_table (table, table->rows + 1);
3229                 values = table->values + table->next_idx * MONO_MEMBERREF_SIZE;
3230                 values [MONO_MEMBERREF_CLASS] = pclass | (parent << MONO_MEMBERREF_PARENT_BITS);
3231                 values [MONO_MEMBERREF_NAME] = string_heap_insert (&assembly->sheap, name);
3232                 values [MONO_MEMBERREF_SIGNATURE] = sig;
3233         }
3234
3235         token = MONO_TOKEN_MEMBER_REF | table->next_idx;
3236         table->next_idx ++;
3237         mono_g_hash_table_insert (assembly->handleref_managed, fb, GUINT_TO_POINTER(token));
3238         g_free (name);
3239         return token;
3240 }
3241
3242 static guint32
3243 mono_reflection_encode_sighelper (MonoDynamicImage *assembly, MonoReflectionSigHelper *helper)
3244 {
3245         SigBuffer buf;
3246         guint32 nargs;
3247         guint32 i, idx;
3248
3249         if (!assembly->save)
3250                 return 0;
3251
3252         /* FIXME: this means SignatureHelper.SignatureHelpType.HELPER_METHOD */
3253         g_assert (helper->type == 2);
3254
3255         if (helper->arguments)
3256                 nargs = mono_array_length (helper->arguments);
3257         else
3258                 nargs = 0;
3259
3260         sigbuffer_init (&buf, 32);
3261
3262         /* Encode calling convention */
3263         /* Change Any to Standard */
3264         if ((helper->call_conv & 0x03) == 0x03)
3265                 helper->call_conv = 0x01;
3266         /* explicit_this implies has_this */
3267         if (helper->call_conv & 0x40)
3268                 helper->call_conv &= 0x20;
3269
3270         if (helper->call_conv == 0) { /* Unmanaged */
3271                 idx = helper->unmanaged_call_conv - 1;
3272         } else {
3273                 /* Managed */
3274                 idx = helper->call_conv & 0x60; /* has_this + explicit_this */
3275                 if (helper->call_conv & 0x02) /* varargs */
3276                         idx += 0x05;
3277         }
3278
3279         sigbuffer_add_byte (&buf, idx);
3280         sigbuffer_add_value (&buf, nargs);
3281         encode_reflection_type (assembly, helper->return_type, &buf);
3282         for (i = 0; i < nargs; ++i) {
3283                 MonoArray *modreqs = NULL;
3284                 MonoArray *modopts = NULL;
3285                 MonoReflectionType *pt;
3286
3287                 if (helper->modreqs && (i < mono_array_length (helper->modreqs)))
3288                         modreqs = mono_array_get (helper->modreqs, MonoArray*, i);
3289                 if (helper->modopts && (i < mono_array_length (helper->modopts)))
3290                         modopts = mono_array_get (helper->modopts, MonoArray*, i);
3291
3292                 encode_custom_modifiers (assembly, modreqs, modopts, &buf);
3293                 pt = mono_array_get (helper->arguments, MonoReflectionType*, i);
3294                 encode_reflection_type (assembly, pt, &buf);
3295         }
3296         idx = sigbuffer_add_to_blob_cached (assembly, &buf);
3297         sigbuffer_free (&buf);
3298
3299         return idx;
3300 }
3301
3302 static guint32 
3303 mono_image_get_sighelper_token (MonoDynamicImage *assembly, MonoReflectionSigHelper *helper)
3304 {
3305         guint32 idx;
3306         MonoDynamicTable *table;
3307         guint32 *values;
3308
3309         table = &assembly->tables [MONO_TABLE_STANDALONESIG];
3310         idx = table->next_idx ++;
3311         table->rows ++;
3312         alloc_table (table, table->rows);
3313         values = table->values + idx * MONO_STAND_ALONE_SIGNATURE_SIZE;
3314
3315         values [MONO_STAND_ALONE_SIGNATURE] =
3316                 mono_reflection_encode_sighelper (assembly, helper);
3317
3318         return idx;
3319 }
3320
3321 static int
3322 reflection_cc_to_file (int call_conv) {
3323         switch (call_conv & 0x3) {
3324         case 0:
3325         case 1: return MONO_CALL_DEFAULT;
3326         case 2: return MONO_CALL_VARARG;
3327         default:
3328                 g_assert_not_reached ();
3329         }
3330         return 0;
3331 }
3332 #endif /* !DISABLE_REFLECTION_EMIT */
3333
3334 typedef struct {
3335         MonoType *parent;
3336         MonoMethodSignature *sig;
3337         char *name;
3338         guint32 token;
3339 } ArrayMethod;
3340
3341 #ifndef DISABLE_REFLECTION_EMIT
3342 static guint32
3343 mono_image_get_array_token (MonoDynamicImage *assembly, MonoReflectionArrayMethod *m)
3344 {
3345         guint32 nparams, i;
3346         GList *tmp;
3347         char *name;
3348         MonoMethodSignature *sig;
3349         ArrayMethod *am;
3350         MonoType *mtype;
3351
3352         name = mono_string_to_utf8 (m->name);
3353         nparams = mono_array_length (m->parameters);
3354         sig = g_malloc0 (MONO_SIZEOF_METHOD_SIGNATURE + sizeof (MonoType*) * nparams);
3355         sig->hasthis = 1;
3356         sig->sentinelpos = -1;
3357         sig->call_convention = reflection_cc_to_file (m->call_conv);
3358         sig->param_count = nparams;
3359         sig->ret = m->ret ? mono_reflection_type_get_handle (m->ret): &mono_defaults.void_class->byval_arg;
3360         mtype = mono_reflection_type_get_handle (m->parent);
3361         for (i = 0; i < nparams; ++i)
3362                 sig->params [i] = mono_type_array_get_and_resolve (m->parameters, i);
3363
3364         for (tmp = assembly->array_methods; tmp; tmp = tmp->next) {
3365                 am = tmp->data;
3366                 if (strcmp (name, am->name) == 0 && 
3367                                 mono_metadata_type_equal (am->parent, mtype) &&
3368                                 mono_metadata_signature_equal (am->sig, sig)) {
3369                         g_free (name);
3370                         g_free (sig);
3371                         m->table_idx = am->token & 0xffffff;
3372                         return am->token;
3373                 }
3374         }
3375         am = g_new0 (ArrayMethod, 1);
3376         am->name = name;
3377         am->sig = sig;
3378         am->parent = mtype;
3379         am->token = mono_image_get_memberref_token (assembly, am->parent, name,
3380                 method_encode_signature (assembly, sig));
3381         assembly->array_methods = g_list_prepend (assembly->array_methods, am);
3382         m->table_idx = am->token & 0xffffff;
3383         return am->token;
3384 }
3385
3386 /*
3387  * Insert into the metadata tables all the info about the TypeBuilder tb.
3388  * Data in the tables is inserted in a predefined order, since some tables need to be sorted.
3389  */
3390 static void
3391 mono_image_get_type_info (MonoDomain *domain, MonoReflectionTypeBuilder *tb, MonoDynamicImage *assembly)
3392 {
3393         MonoDynamicTable *table;
3394         guint *values;
3395         int i, is_object = 0, is_system = 0;
3396         char *n;
3397
3398         table = &assembly->tables [MONO_TABLE_TYPEDEF];
3399         values = table->values + tb->table_idx * MONO_TYPEDEF_SIZE;
3400         values [MONO_TYPEDEF_FLAGS] = tb->attrs;
3401         n = mono_string_to_utf8 (tb->name);
3402         if (strcmp (n, "Object") == 0)
3403                 is_object++;
3404         values [MONO_TYPEDEF_NAME] = string_heap_insert (&assembly->sheap, n);
3405         g_free (n);
3406         n = mono_string_to_utf8 (tb->nspace);
3407         if (strcmp (n, "System") == 0)
3408                 is_system++;
3409         values [MONO_TYPEDEF_NAMESPACE] = string_heap_insert (&assembly->sheap, n);
3410         g_free (n);
3411         if (tb->parent && !(is_system && is_object) && 
3412                         !(tb->attrs & TYPE_ATTRIBUTE_INTERFACE)) { /* interfaces don't have a parent */
3413                 values [MONO_TYPEDEF_EXTENDS] = mono_image_typedef_or_ref (assembly, mono_reflection_type_get_handle ((MonoReflectionType*)tb->parent));
3414         } else {
3415                 values [MONO_TYPEDEF_EXTENDS] = 0;
3416         }
3417         values [MONO_TYPEDEF_FIELD_LIST] = assembly->tables [MONO_TABLE_FIELD].next_idx;
3418         values [MONO_TYPEDEF_METHOD_LIST] = assembly->tables [MONO_TABLE_METHOD].next_idx;
3419
3420         /*
3421          * if we have explicitlayout or sequentiallayouts, output data in the
3422          * ClassLayout table.
3423          */
3424         if (((tb->attrs & TYPE_ATTRIBUTE_LAYOUT_MASK) != TYPE_ATTRIBUTE_AUTO_LAYOUT) &&
3425                         ((tb->class_size > 0) || (tb->packing_size > 0))) {
3426                 table = &assembly->tables [MONO_TABLE_CLASSLAYOUT];
3427                 table->rows++;
3428                 alloc_table (table, table->rows);
3429                 values = table->values + table->rows * MONO_CLASS_LAYOUT_SIZE;
3430                 values [MONO_CLASS_LAYOUT_PARENT] = tb->table_idx;
3431                 values [MONO_CLASS_LAYOUT_CLASS_SIZE] = tb->class_size;
3432                 values [MONO_CLASS_LAYOUT_PACKING_SIZE] = tb->packing_size;
3433         }
3434
3435         /* handle interfaces */
3436         if (tb->interfaces) {
3437                 table = &assembly->tables [MONO_TABLE_INTERFACEIMPL];
3438                 i = table->rows;
3439                 table->rows += mono_array_length (tb->interfaces);
3440                 alloc_table (table, table->rows);
3441                 values = table->values + (i + 1) * MONO_INTERFACEIMPL_SIZE;
3442                 for (i = 0; i < mono_array_length (tb->interfaces); ++i) {
3443                         MonoReflectionType* iface = (MonoReflectionType*) mono_array_get (tb->interfaces, gpointer, i);
3444                         values [MONO_INTERFACEIMPL_CLASS] = tb->table_idx;
3445                         values [MONO_INTERFACEIMPL_INTERFACE] = mono_image_typedef_or_ref (assembly, mono_reflection_type_get_handle (iface));
3446                         values += MONO_INTERFACEIMPL_SIZE;
3447                 }
3448         }
3449
3450         /* handle fields */
3451         if (tb->fields) {
3452                 table = &assembly->tables [MONO_TABLE_FIELD];
3453                 table->rows += tb->num_fields;
3454                 alloc_table (table, table->rows);
3455                 for (i = 0; i < tb->num_fields; ++i)
3456                         mono_image_get_field_info (
3457                                 mono_array_get (tb->fields, MonoReflectionFieldBuilder*, i), assembly);
3458         }
3459
3460         /* handle constructors */
3461         if (tb->ctors) {
3462                 table = &assembly->tables [MONO_TABLE_METHOD];
3463                 table->rows += mono_array_length (tb->ctors);
3464                 alloc_table (table, table->rows);
3465                 for (i = 0; i < mono_array_length (tb->ctors); ++i)
3466                         mono_image_get_ctor_info (domain,
3467                                 mono_array_get (tb->ctors, MonoReflectionCtorBuilder*, i), assembly);
3468         }
3469
3470         /* handle methods */
3471         if (tb->methods) {
3472                 table = &assembly->tables [MONO_TABLE_METHOD];
3473                 table->rows += tb->num_methods;
3474                 alloc_table (table, table->rows);
3475                 for (i = 0; i < tb->num_methods; ++i)
3476                         mono_image_get_method_info (
3477                                 mono_array_get (tb->methods, MonoReflectionMethodBuilder*, i), assembly);
3478         }
3479
3480         /* Do the same with properties etc.. */
3481         if (tb->events && mono_array_length (tb->events)) {
3482                 table = &assembly->tables [MONO_TABLE_EVENT];
3483                 table->rows += mono_array_length (tb->events);
3484                 alloc_table (table, table->rows);
3485                 table = &assembly->tables [MONO_TABLE_EVENTMAP];
3486                 table->rows ++;
3487                 alloc_table (table, table->rows);
3488                 values = table->values + table->rows * MONO_EVENT_MAP_SIZE;
3489                 values [MONO_EVENT_MAP_PARENT] = tb->table_idx;
3490                 values [MONO_EVENT_MAP_EVENTLIST] = assembly->tables [MONO_TABLE_EVENT].next_idx;
3491                 for (i = 0; i < mono_array_length (tb->events); ++i)
3492                         mono_image_get_event_info (
3493                                 mono_array_get (tb->events, MonoReflectionEventBuilder*, i), assembly);
3494         }
3495         if (tb->properties && mono_array_length (tb->properties)) {
3496                 table = &assembly->tables [MONO_TABLE_PROPERTY];
3497                 table->rows += mono_array_length (tb->properties);
3498                 alloc_table (table, table->rows);
3499                 table = &assembly->tables [MONO_TABLE_PROPERTYMAP];
3500                 table->rows ++;
3501                 alloc_table (table, table->rows);
3502                 values = table->values + table->rows * MONO_PROPERTY_MAP_SIZE;
3503                 values [MONO_PROPERTY_MAP_PARENT] = tb->table_idx;
3504                 values [MONO_PROPERTY_MAP_PROPERTY_LIST] = assembly->tables [MONO_TABLE_PROPERTY].next_idx;
3505                 for (i = 0; i < mono_array_length (tb->properties); ++i)
3506                         mono_image_get_property_info (
3507                                 mono_array_get (tb->properties, MonoReflectionPropertyBuilder*, i), assembly);
3508         }
3509
3510         /* handle generic parameters */
3511         if (tb->generic_params) {
3512                 table = &assembly->tables [MONO_TABLE_GENERICPARAM];
3513                 table->rows += mono_array_length (tb->generic_params);
3514                 alloc_table (table, table->rows);
3515                 for (i = 0; i < mono_array_length (tb->generic_params); ++i) {
3516                         guint32 owner = MONO_TYPEORMETHOD_TYPE | (tb->table_idx << MONO_TYPEORMETHOD_BITS);
3517
3518                         mono_image_get_generic_param_info (
3519                                 mono_array_get (tb->generic_params, MonoReflectionGenericParam*, i), owner, assembly);
3520                 }
3521         }
3522
3523         mono_image_add_decl_security (assembly, 
3524                 mono_metadata_make_token (MONO_TABLE_TYPEDEF, tb->table_idx), tb->permissions);
3525
3526         if (tb->subtypes) {
3527                 MonoDynamicTable *ntable;
3528                 
3529                 ntable = &assembly->tables [MONO_TABLE_NESTEDCLASS];
3530                 ntable->rows += mono_array_length (tb->subtypes);
3531                 alloc_table (ntable, ntable->rows);
3532                 values = ntable->values + ntable->next_idx * MONO_NESTED_CLASS_SIZE;
3533
3534                 for (i = 0; i < mono_array_length (tb->subtypes); ++i) {
3535                         MonoReflectionTypeBuilder *subtype = mono_array_get (tb->subtypes, MonoReflectionTypeBuilder*, i);
3536
3537                         values [MONO_NESTED_CLASS_NESTED] = subtype->table_idx;
3538                         values [MONO_NESTED_CLASS_ENCLOSING] = tb->table_idx;
3539                         /*g_print ("nesting %s (%d) in %s (%d) (rows %d/%d)\n",
3540                                 mono_string_to_utf8 (subtype->name), subtype->table_idx,
3541                                 mono_string_to_utf8 (tb->name), tb->table_idx,
3542                                 ntable->next_idx, ntable->rows);*/
3543                         values += MONO_NESTED_CLASS_SIZE;
3544                         ntable->next_idx++;
3545                 }
3546         }
3547 }
3548 #endif
3549
3550 static void
3551 collect_types (MonoPtrArray *types, MonoReflectionTypeBuilder *type)
3552 {
3553         int i;
3554
3555         mono_ptr_array_append (*types, type);
3556
3557         if (!type->subtypes)
3558                 return;
3559
3560         for (i = 0; i < mono_array_length (type->subtypes); ++i) {
3561                 MonoReflectionTypeBuilder *subtype = mono_array_get (type->subtypes, MonoReflectionTypeBuilder*, i);
3562                 collect_types (types, subtype);
3563         }
3564 }
3565
3566 static gint
3567 compare_types_by_table_idx (MonoReflectionTypeBuilder **type1, MonoReflectionTypeBuilder **type2)
3568 {
3569         if ((*type1)->table_idx < (*type2)->table_idx)
3570                 return -1;
3571         else
3572                 if ((*type1)->table_idx > (*type2)->table_idx)
3573                         return 1;
3574         else
3575                 return 0;
3576 }
3577
3578 static void
3579 params_add_cattrs (MonoDynamicImage *assembly, MonoArray *pinfo) {
3580         int i;
3581
3582         if (!pinfo)
3583                 return;
3584         for (i = 0; i < mono_array_length (pinfo); ++i) {
3585                 MonoReflectionParamBuilder *pb;
3586                 pb = mono_array_get (pinfo, MonoReflectionParamBuilder *, i);
3587                 if (!pb)
3588                         continue;
3589                 mono_image_add_cattrs (assembly, pb->table_idx, MONO_CUSTOM_ATTR_PARAMDEF, pb->cattrs);
3590         }
3591 }
3592
3593 static void
3594 type_add_cattrs (MonoDynamicImage *assembly, MonoReflectionTypeBuilder *tb) {
3595         int i;
3596         
3597         mono_image_add_cattrs (assembly, tb->table_idx, MONO_CUSTOM_ATTR_TYPEDEF, tb->cattrs);
3598         if (tb->fields) {
3599                 for (i = 0; i < tb->num_fields; ++i) {
3600                         MonoReflectionFieldBuilder* fb;
3601                         fb = mono_array_get (tb->fields, MonoReflectionFieldBuilder*, i);
3602                         mono_image_add_cattrs (assembly, fb->table_idx, MONO_CUSTOM_ATTR_FIELDDEF, fb->cattrs);
3603                 }
3604         }
3605         if (tb->events) {
3606                 for (i = 0; i < mono_array_length (tb->events); ++i) {
3607                         MonoReflectionEventBuilder* eb;
3608                         eb = mono_array_get (tb->events, MonoReflectionEventBuilder*, i);
3609                         mono_image_add_cattrs (assembly, eb->table_idx, MONO_CUSTOM_ATTR_EVENT, eb->cattrs);
3610                 }
3611         }
3612         if (tb->properties) {
3613                 for (i = 0; i < mono_array_length (tb->properties); ++i) {
3614                         MonoReflectionPropertyBuilder* pb;
3615                         pb = mono_array_get (tb->properties, MonoReflectionPropertyBuilder*, i);
3616                         mono_image_add_cattrs (assembly, pb->table_idx, MONO_CUSTOM_ATTR_PROPERTY, pb->cattrs);
3617                 }
3618         }
3619         if (tb->ctors) {
3620                 for (i = 0; i < mono_array_length (tb->ctors); ++i) {
3621                         MonoReflectionCtorBuilder* cb;
3622                         cb = mono_array_get (tb->ctors, MonoReflectionCtorBuilder*, i);
3623                         mono_image_add_cattrs (assembly, cb->table_idx, MONO_CUSTOM_ATTR_METHODDEF, cb->cattrs);
3624                         params_add_cattrs (assembly, cb->pinfo);
3625                 }
3626         }
3627
3628         if (tb->methods) {
3629                 for (i = 0; i < tb->num_methods; ++i) {
3630                         MonoReflectionMethodBuilder* mb;
3631                         mb = mono_array_get (tb->methods, MonoReflectionMethodBuilder*, i);
3632                         mono_image_add_cattrs (assembly, mb->table_idx, MONO_CUSTOM_ATTR_METHODDEF, mb->cattrs);
3633                         params_add_cattrs (assembly, mb->pinfo);
3634                 }
3635         }
3636
3637         if (tb->subtypes) {
3638                 for (i = 0; i < mono_array_length (tb->subtypes); ++i)
3639                         type_add_cattrs (assembly, mono_array_get (tb->subtypes, MonoReflectionTypeBuilder*, i));
3640         }
3641 }
3642
3643 static void
3644 module_add_cattrs (MonoDynamicImage *assembly, MonoReflectionModuleBuilder *moduleb)
3645 {
3646         int i;
3647         
3648         mono_image_add_cattrs (assembly, moduleb->table_idx, MONO_CUSTOM_ATTR_MODULE, moduleb->cattrs);
3649
3650         if (moduleb->global_methods) {
3651                 for (i = 0; i < mono_array_length (moduleb->global_methods); ++i) {
3652                         MonoReflectionMethodBuilder* mb = mono_array_get (moduleb->global_methods, MonoReflectionMethodBuilder*, i);
3653                         mono_image_add_cattrs (assembly, mb->table_idx, MONO_CUSTOM_ATTR_METHODDEF, mb->cattrs);
3654                         params_add_cattrs (assembly, mb->pinfo);
3655                 }
3656         }
3657
3658         if (moduleb->global_fields) {
3659                 for (i = 0; i < mono_array_length (moduleb->global_fields); ++i) {
3660                         MonoReflectionFieldBuilder *fb = mono_array_get (moduleb->global_fields, MonoReflectionFieldBuilder*, i);
3661                         mono_image_add_cattrs (assembly, fb->table_idx, MONO_CUSTOM_ATTR_FIELDDEF, fb->cattrs);
3662                 }
3663         }
3664         
3665         if (moduleb->types) {
3666                 for (i = 0; i < moduleb->num_types; ++i)
3667                         type_add_cattrs (assembly, mono_array_get (moduleb->types, MonoReflectionTypeBuilder*, i));
3668         }
3669 }
3670
3671 static void
3672 mono_image_fill_file_table (MonoDomain *domain, MonoReflectionModule *module, MonoDynamicImage *assembly)
3673 {
3674         MonoDynamicTable *table;
3675         guint32 *values;
3676         char blob_size [6];
3677         guchar hash [20];
3678         char *b = blob_size;
3679         char *dir, *path;
3680
3681         table = &assembly->tables [MONO_TABLE_FILE];
3682         table->rows++;
3683         alloc_table (table, table->rows);
3684         values = table->values + table->next_idx * MONO_FILE_SIZE;
3685         values [MONO_FILE_FLAGS] = FILE_CONTAINS_METADATA;
3686         values [MONO_FILE_NAME] = string_heap_insert (&assembly->sheap, module->image->module_name);
3687         if (image_is_dynamic (module->image)) {
3688                 /* This depends on the fact that the main module is emitted last */
3689                 dir = mono_string_to_utf8 (((MonoReflectionModuleBuilder*)module)->assemblyb->dir);
3690                 path = g_strdup_printf ("%s%c%s", dir, G_DIR_SEPARATOR, module->image->module_name);
3691         } else {
3692                 dir = NULL;
3693                 path = g_strdup (module->image->name);
3694         }
3695         mono_sha1_get_digest_from_file (path, hash);
3696         g_free (dir);
3697         g_free (path);
3698         mono_metadata_encode_value (20, b, &b);
3699         values [MONO_FILE_HASH_VALUE] = mono_image_add_stream_data (&assembly->blob, blob_size, b-blob_size);
3700         mono_image_add_stream_data (&assembly->blob, (char*)hash, 20);
3701         table->next_idx ++;
3702 }
3703
3704 static void
3705 mono_image_fill_module_table (MonoDomain *domain, MonoReflectionModuleBuilder *mb, MonoDynamicImage *assembly)
3706 {
3707         MonoDynamicTable *table;
3708         int i;
3709
3710         table = &assembly->tables [MONO_TABLE_MODULE];
3711         mb->table_idx = table->next_idx ++;
3712         table->values [mb->table_idx * MONO_MODULE_SIZE + MONO_MODULE_NAME] = string_heap_insert_mstring (&assembly->sheap, mb->module.name);
3713         i = mono_image_add_stream_data (&assembly->guid, mono_array_addr (mb->guid, char, 0), 16);
3714         i /= 16;
3715         ++i;
3716         table->values [mb->table_idx * MONO_MODULE_SIZE + MONO_MODULE_GENERATION] = 0;
3717         table->values [mb->table_idx * MONO_MODULE_SIZE + MONO_MODULE_MVID] = i;
3718         table->values [mb->table_idx * MONO_MODULE_SIZE + MONO_MODULE_ENC] = 0;
3719         table->values [mb->table_idx * MONO_MODULE_SIZE + MONO_MODULE_ENCBASE] = 0;
3720 }
3721
3722 static guint32
3723 mono_image_fill_export_table_from_class (MonoDomain *domain, MonoClass *klass,
3724         guint32 module_index, guint32 parent_index, MonoDynamicImage *assembly)
3725 {
3726         MonoDynamicTable *table;
3727         guint32 *values;
3728         guint32 visib, res;
3729
3730         visib = klass->flags & TYPE_ATTRIBUTE_VISIBILITY_MASK;
3731         if (! ((visib & TYPE_ATTRIBUTE_PUBLIC) || (visib & TYPE_ATTRIBUTE_NESTED_PUBLIC)))
3732                 return 0;
3733
3734         table = &assembly->tables [MONO_TABLE_EXPORTEDTYPE];
3735         table->rows++;
3736         alloc_table (table, table->rows);
3737         values = table->values + table->next_idx * MONO_EXP_TYPE_SIZE;
3738
3739         values [MONO_EXP_TYPE_FLAGS] = klass->flags;
3740         values [MONO_EXP_TYPE_TYPEDEF] = klass->type_token;
3741         if (klass->nested_in)
3742                 values [MONO_EXP_TYPE_IMPLEMENTATION] = (parent_index << MONO_IMPLEMENTATION_BITS) + MONO_IMPLEMENTATION_EXP_TYPE;
3743         else
3744                 values [MONO_EXP_TYPE_IMPLEMENTATION] = (module_index << MONO_IMPLEMENTATION_BITS) + MONO_IMPLEMENTATION_FILE;
3745         values [MONO_EXP_TYPE_NAME] = string_heap_insert (&assembly->sheap, klass->name);
3746         values [MONO_EXP_TYPE_NAMESPACE] = string_heap_insert (&assembly->sheap, klass->name_space);
3747
3748         res = table->next_idx;
3749
3750         table->next_idx ++;
3751
3752         /* Emit nested types */
3753         if (klass->ext && klass->ext->nested_classes) {
3754                 GList *tmp;
3755
3756                 for (tmp = klass->ext->nested_classes; tmp; tmp = tmp->next)
3757                         mono_image_fill_export_table_from_class (domain, tmp->data, module_index, table->next_idx - 1, assembly);
3758         }
3759
3760         return res;
3761 }
3762
3763 static void
3764 mono_image_fill_export_table (MonoDomain *domain, MonoReflectionTypeBuilder *tb,
3765         guint32 module_index, guint32 parent_index, MonoDynamicImage *assembly)
3766 {
3767         MonoClass *klass;
3768         guint32 idx, i;
3769
3770         klass = mono_class_from_mono_type (mono_reflection_type_get_handle ((MonoReflectionType*)tb));
3771
3772         klass->type_token = mono_metadata_make_token (MONO_TABLE_TYPEDEF, tb->table_idx);
3773
3774         idx = mono_image_fill_export_table_from_class (domain, klass, module_index, 
3775                                                                                                    parent_index, assembly);
3776
3777         /* 
3778          * Emit nested types
3779          * We need to do this ourselves since klass->nested_classes is not set up.
3780          */
3781         if (tb->subtypes) {
3782                 for (i = 0; i < mono_array_length (tb->subtypes); ++i)
3783                         mono_image_fill_export_table (domain, mono_array_get (tb->subtypes, MonoReflectionTypeBuilder*, i), module_index, idx, assembly);
3784         }
3785 }
3786
3787 static void
3788 mono_image_fill_export_table_from_module (MonoDomain *domain, MonoReflectionModule *module,
3789         guint32 module_index, MonoDynamicImage *assembly)
3790 {
3791         MonoImage *image = module->image;
3792         MonoTableInfo  *t;
3793         guint32 i;
3794
3795         t = &image->tables [MONO_TABLE_TYPEDEF];
3796
3797         for (i = 0; i < t->rows; ++i) {
3798                 MonoError error;
3799                 MonoClass *klass = mono_class_get_checked (image, mono_metadata_make_token (MONO_TABLE_TYPEDEF, i + 1), &error);
3800                 g_assert (mono_error_ok (&error)); /* FIXME don't swallow the error */
3801
3802                 if (klass->flags & TYPE_ATTRIBUTE_PUBLIC)
3803                         mono_image_fill_export_table_from_class (domain, klass, module_index, 0, assembly);
3804         }
3805 }
3806
3807 static void
3808 add_exported_type (MonoReflectionAssemblyBuilder *assemblyb, MonoDynamicImage *assembly, MonoClass *klass, guint32 parent_index)
3809 {
3810         MonoDynamicTable *table;
3811         guint32 *values;
3812         guint32 scope, scope_idx, impl, current_idx;
3813         gboolean forwarder = TRUE;
3814         gpointer iter = NULL;
3815         MonoClass *nested;
3816
3817         if (klass->nested_in) {
3818                 impl = (parent_index << MONO_IMPLEMENTATION_BITS) + MONO_IMPLEMENTATION_EXP_TYPE;
3819                 forwarder = FALSE;
3820         } else {
3821                 scope = resolution_scope_from_image (assembly, klass->image);
3822                 g_assert ((scope & MONO_RESOLUTION_SCOPE_MASK) == MONO_RESOLUTION_SCOPE_ASSEMBLYREF);
3823                 scope_idx = scope >> MONO_RESOLUTION_SCOPE_BITS;
3824                 impl = (scope_idx << MONO_IMPLEMENTATION_BITS) + MONO_IMPLEMENTATION_ASSEMBLYREF;
3825         }
3826
3827         table = &assembly->tables [MONO_TABLE_EXPORTEDTYPE];
3828
3829         table->rows++;
3830         alloc_table (table, table->rows);
3831         current_idx = table->next_idx;
3832         values = table->values + current_idx * MONO_EXP_TYPE_SIZE;
3833
3834         values [MONO_EXP_TYPE_FLAGS] = forwarder ? TYPE_ATTRIBUTE_FORWARDER : 0;
3835         values [MONO_EXP_TYPE_TYPEDEF] = 0;
3836         values [MONO_EXP_TYPE_IMPLEMENTATION] = impl;
3837         values [MONO_EXP_TYPE_NAME] = string_heap_insert (&assembly->sheap, klass->name);
3838         values [MONO_EXP_TYPE_NAMESPACE] = string_heap_insert (&assembly->sheap, klass->name_space);
3839
3840         table->next_idx++;
3841
3842         while ((nested = mono_class_get_nested_types (klass, &iter)))
3843                 add_exported_type (assemblyb, assembly, nested, current_idx);
3844 }
3845
3846 static void
3847 mono_image_fill_export_table_from_type_forwarders (MonoReflectionAssemblyBuilder *assemblyb, MonoDynamicImage *assembly)
3848 {
3849         MonoClass *klass;
3850         int i;
3851
3852         if (!assemblyb->type_forwarders)
3853                 return;
3854
3855         for (i = 0; i < mono_array_length (assemblyb->type_forwarders); ++i) {
3856                 MonoReflectionType *t = mono_array_get (assemblyb->type_forwarders, MonoReflectionType *, i);
3857                 MonoType *type;
3858                 if (!t)
3859                         continue;
3860
3861                 type = mono_reflection_type_get_handle (t);
3862                 g_assert (type);
3863
3864                 klass = mono_class_from_mono_type (type);
3865
3866                 add_exported_type (assemblyb, assembly, klass, 0);
3867         }
3868 }
3869
3870 #define align_pointer(base,p)\
3871         do {\
3872                 guint32 __diff = (unsigned char*)(p)-(unsigned char*)(base);\
3873                 if (__diff & 3)\
3874                         (p) += 4 - (__diff & 3);\
3875         } while (0)
3876
3877 static int
3878 compare_constants (const void *a, const void *b)
3879 {
3880         const guint32 *a_values = a;
3881         const guint32 *b_values = b;
3882         return a_values [MONO_CONSTANT_PARENT] - b_values [MONO_CONSTANT_PARENT];
3883 }
3884
3885 static int
3886 compare_semantics (const void *a, const void *b)
3887 {
3888         const guint32 *a_values = a;
3889         const guint32 *b_values = b;
3890         int assoc = a_values [MONO_METHOD_SEMA_ASSOCIATION] - b_values [MONO_METHOD_SEMA_ASSOCIATION];
3891         if (assoc)
3892                 return assoc;
3893         return a_values [MONO_METHOD_SEMA_SEMANTICS] - b_values [MONO_METHOD_SEMA_SEMANTICS];
3894 }
3895
3896 static int
3897 compare_custom_attrs (const void *a, const void *b)
3898 {
3899         const guint32 *a_values = a;
3900         const guint32 *b_values = b;
3901
3902         return a_values [MONO_CUSTOM_ATTR_PARENT] - b_values [MONO_CUSTOM_ATTR_PARENT];
3903 }
3904
3905 static int
3906 compare_field_marshal (const void *a, const void *b)
3907 {
3908         const guint32 *a_values = a;
3909         const guint32 *b_values = b;
3910
3911         return a_values [MONO_FIELD_MARSHAL_PARENT] - b_values [MONO_FIELD_MARSHAL_PARENT];
3912 }
3913
3914 static int
3915 compare_nested (const void *a, const void *b)
3916 {
3917         const guint32 *a_values = a;
3918         const guint32 *b_values = b;
3919
3920         return a_values [MONO_NESTED_CLASS_NESTED] - b_values [MONO_NESTED_CLASS_NESTED];
3921 }
3922
3923 static int
3924 compare_genericparam (const void *a, const void *b)
3925 {
3926         const GenericParamTableEntry **a_entry = (const GenericParamTableEntry **) a;
3927         const GenericParamTableEntry **b_entry = (const GenericParamTableEntry **) b;
3928
3929         if ((*b_entry)->owner == (*a_entry)->owner)
3930                 return 
3931                         mono_type_get_generic_param_num (mono_reflection_type_get_handle ((MonoReflectionType*)(*a_entry)->gparam)) -
3932                         mono_type_get_generic_param_num (mono_reflection_type_get_handle ((MonoReflectionType*)(*b_entry)->gparam));
3933         else
3934                 return (*a_entry)->owner - (*b_entry)->owner;
3935 }
3936
3937 static int
3938 compare_declsecurity_attrs (const void *a, const void *b)
3939 {
3940         const guint32 *a_values = a;
3941         const guint32 *b_values = b;
3942
3943         return a_values [MONO_DECL_SECURITY_PARENT] - b_values [MONO_DECL_SECURITY_PARENT];
3944 }
3945
3946 static int
3947 compare_interface_impl (const void *a, const void *b)
3948 {
3949         const guint32 *a_values = a;
3950         const guint32 *b_values = b;
3951
3952         int klass = a_values [MONO_INTERFACEIMPL_CLASS] - b_values [MONO_INTERFACEIMPL_CLASS];
3953         if (klass)
3954                 return klass;
3955
3956         return a_values [MONO_INTERFACEIMPL_INTERFACE] - b_values [MONO_INTERFACEIMPL_INTERFACE];
3957 }
3958
3959 static void
3960 pad_heap (MonoDynamicStream *sh)
3961 {
3962         if (sh->index & 3) {
3963                 int sz = 4 - (sh->index & 3);
3964                 memset (sh->data + sh->index, 0, sz);
3965                 sh->index += sz;
3966         }
3967 }
3968
3969 struct StreamDesc {
3970         const char *name;
3971         MonoDynamicStream *stream;
3972 };
3973
3974 /*
3975  * build_compressed_metadata() fills in the blob of data that represents the 
3976  * raw metadata as it will be saved in the PE file. The five streams are output 
3977  * and the metadata tables are comnpressed from the guint32 array representation, 
3978  * to the compressed on-disk format.
3979  */
3980 static void
3981 build_compressed_metadata (MonoDynamicImage *assembly)
3982 {
3983         MonoDynamicTable *table;
3984         int i;
3985         guint64 valid_mask = 0;
3986         guint64 sorted_mask;
3987         guint32 heapt_size = 0;
3988         guint32 meta_size = 256; /* allow for header and other stuff */
3989         guint32 table_offset;
3990         guint32 ntables = 0;
3991         guint64 *int64val;
3992         guint32 *int32val;
3993         guint16 *int16val;
3994         MonoImage *meta;
3995         unsigned char *p;
3996         struct StreamDesc stream_desc [5];
3997
3998         qsort (assembly->gen_params->pdata, assembly->gen_params->len, sizeof (gpointer), compare_genericparam);
3999         for (i = 0; i < assembly->gen_params->len; i++){
4000                 GenericParamTableEntry *entry = g_ptr_array_index (assembly->gen_params, i);
4001                 write_generic_param_entry (assembly, entry);
4002         }
4003
4004         stream_desc [0].name  = "#~";
4005         stream_desc [0].stream = &assembly->tstream;
4006         stream_desc [1].name  = "#Strings";
4007         stream_desc [1].stream = &assembly->sheap;
4008         stream_desc [2].name  = "#US";
4009         stream_desc [2].stream = &assembly->us;
4010         stream_desc [3].name  = "#Blob";
4011         stream_desc [3].stream = &assembly->blob;
4012         stream_desc [4].name  = "#GUID";
4013         stream_desc [4].stream = &assembly->guid;
4014         
4015         /* tables that are sorted */
4016         sorted_mask = ((guint64)1 << MONO_TABLE_CONSTANT) | ((guint64)1 << MONO_TABLE_FIELDMARSHAL)
4017                 | ((guint64)1 << MONO_TABLE_METHODSEMANTICS) | ((guint64)1 << MONO_TABLE_CLASSLAYOUT)
4018                 | ((guint64)1 << MONO_TABLE_FIELDLAYOUT) | ((guint64)1 << MONO_TABLE_FIELDRVA)
4019                 | ((guint64)1 << MONO_TABLE_IMPLMAP) | ((guint64)1 << MONO_TABLE_NESTEDCLASS)
4020                 | ((guint64)1 << MONO_TABLE_METHODIMPL) | ((guint64)1 << MONO_TABLE_CUSTOMATTRIBUTE)
4021                 | ((guint64)1 << MONO_TABLE_DECLSECURITY) | ((guint64)1 << MONO_TABLE_GENERICPARAM)
4022                 | ((guint64)1 << MONO_TABLE_INTERFACEIMPL);
4023         
4024         /* Compute table sizes */
4025         /* the MonoImage has already been created in mono_image_basic_init() */
4026         meta = &assembly->image;
4027
4028         /* sizes should be multiple of 4 */
4029         pad_heap (&assembly->blob);
4030         pad_heap (&assembly->guid);
4031         pad_heap (&assembly->sheap);
4032         pad_heap (&assembly->us);
4033
4034         /* Setup the info used by compute_sizes () */
4035         meta->idx_blob_wide = assembly->blob.index >= 65536 ? 1 : 0;
4036         meta->idx_guid_wide = assembly->guid.index >= 65536 ? 1 : 0;
4037         meta->idx_string_wide = assembly->sheap.index >= 65536 ? 1 : 0;
4038
4039         meta_size += assembly->blob.index;
4040         meta_size += assembly->guid.index;
4041         meta_size += assembly->sheap.index;
4042         meta_size += assembly->us.index;
4043
4044         for (i=0; i < MONO_TABLE_NUM; ++i)
4045                 meta->tables [i].rows = assembly->tables [i].rows;
4046         
4047         for (i = 0; i < MONO_TABLE_NUM; i++){
4048                 if (meta->tables [i].rows == 0)
4049                         continue;
4050                 valid_mask |= (guint64)1 << i;
4051                 ntables ++;
4052                 meta->tables [i].row_size = mono_metadata_compute_size (
4053                         meta, i, &meta->tables [i].size_bitfield);
4054                 heapt_size += meta->tables [i].row_size * meta->tables [i].rows;
4055         }
4056         heapt_size += 24; /* #~ header size */
4057         heapt_size += ntables * 4;
4058         /* make multiple of 4 */
4059         heapt_size += 3;
4060         heapt_size &= ~3;
4061         meta_size += heapt_size;
4062         meta->raw_metadata = g_malloc0 (meta_size);
4063         p = (unsigned char*)meta->raw_metadata;
4064         /* the metadata signature */
4065         *p++ = 'B'; *p++ = 'S'; *p++ = 'J'; *p++ = 'B';
4066         /* version numbers and 4 bytes reserved */
4067         int16val = (guint16*)p;
4068         *int16val++ = GUINT16_TO_LE (meta->md_version_major);
4069         *int16val = GUINT16_TO_LE (meta->md_version_minor);
4070         p += 8;
4071         /* version string */
4072         int32val = (guint32*)p;
4073         *int32val = GUINT32_TO_LE ((strlen (meta->version) + 3) & (~3)); /* needs to be multiple of 4 */
4074         p += 4;
4075         memcpy (p, meta->version, strlen (meta->version));
4076         p += GUINT32_FROM_LE (*int32val);
4077         align_pointer (meta->raw_metadata, p);
4078         int16val = (guint16*)p;
4079         *int16val++ = GUINT16_TO_LE (0); /* flags must be 0 */
4080         *int16val = GUINT16_TO_LE (5); /* number of streams */
4081         p += 4;
4082
4083         /*
4084          * write the stream info.
4085          */
4086         table_offset = (p - (unsigned char*)meta->raw_metadata) + 5 * 8 + 40; /* room needed for stream headers */
4087         table_offset += 3; table_offset &= ~3;
4088
4089         assembly->tstream.index = heapt_size;
4090         for (i = 0; i < 5; ++i) {
4091                 int32val = (guint32*)p;
4092                 stream_desc [i].stream->offset = table_offset;
4093                 *int32val++ = GUINT32_TO_LE (table_offset);
4094                 *int32val = GUINT32_TO_LE (stream_desc [i].stream->index);
4095                 table_offset += GUINT32_FROM_LE (*int32val);
4096                 table_offset += 3; table_offset &= ~3;
4097                 p += 8;
4098                 strcpy ((char*)p, stream_desc [i].name);
4099                 p += strlen (stream_desc [i].name) + 1;
4100                 align_pointer (meta->raw_metadata, p);
4101         }
4102         /* 
4103          * now copy the data, the table stream header and contents goes first.
4104          */
4105         g_assert ((p - (unsigned char*)meta->raw_metadata) < assembly->tstream.offset);
4106         p = (guchar*)meta->raw_metadata + assembly->tstream.offset;
4107         int32val = (guint32*)p;
4108         *int32val = GUINT32_TO_LE (0); /* reserved */
4109         p += 4;
4110
4111         *p++ = 2; /* version */
4112         *p++ = 0;
4113
4114         if (meta->idx_string_wide)
4115                 *p |= 0x01;
4116         if (meta->idx_guid_wide)
4117                 *p |= 0x02;
4118         if (meta->idx_blob_wide)
4119                 *p |= 0x04;
4120         ++p;
4121         *p++ = 1; /* reserved */
4122         int64val = (guint64*)p;
4123         *int64val++ = GUINT64_TO_LE (valid_mask);
4124         *int64val++ = GUINT64_TO_LE (valid_mask & sorted_mask); /* bitvector of sorted tables  */
4125         p += 16;
4126         int32val = (guint32*)p;
4127         for (i = 0; i < MONO_TABLE_NUM; i++){
4128                 if (meta->tables [i].rows == 0)
4129                         continue;
4130                 *int32val++ = GUINT32_TO_LE (meta->tables [i].rows);
4131         }
4132         p = (unsigned char*)int32val;
4133
4134         /* sort the tables that still need sorting */
4135         table = &assembly->tables [MONO_TABLE_CONSTANT];
4136         if (table->rows)
4137                 qsort (table->values + MONO_CONSTANT_SIZE, table->rows, sizeof (guint32) * MONO_CONSTANT_SIZE, compare_constants);
4138         table = &assembly->tables [MONO_TABLE_METHODSEMANTICS];
4139         if (table->rows)
4140                 qsort (table->values + MONO_METHOD_SEMA_SIZE, table->rows, sizeof (guint32) * MONO_METHOD_SEMA_SIZE, compare_semantics);
4141         table = &assembly->tables [MONO_TABLE_CUSTOMATTRIBUTE];
4142         if (table->rows)
4143                 qsort (table->values + MONO_CUSTOM_ATTR_SIZE, table->rows, sizeof (guint32) * MONO_CUSTOM_ATTR_SIZE, compare_custom_attrs);
4144         table = &assembly->tables [MONO_TABLE_FIELDMARSHAL];
4145         if (table->rows)
4146                 qsort (table->values + MONO_FIELD_MARSHAL_SIZE, table->rows, sizeof (guint32) * MONO_FIELD_MARSHAL_SIZE, compare_field_marshal);
4147         table = &assembly->tables [MONO_TABLE_NESTEDCLASS];
4148         if (table->rows)
4149                 qsort (table->values + MONO_NESTED_CLASS_SIZE, table->rows, sizeof (guint32) * MONO_NESTED_CLASS_SIZE, compare_nested);
4150         /* Section 21.11 DeclSecurity in Partition II doesn't specify this to be sorted by MS implementation requires it */
4151         table = &assembly->tables [MONO_TABLE_DECLSECURITY];
4152         if (table->rows)
4153                 qsort (table->values + MONO_DECL_SECURITY_SIZE, table->rows, sizeof (guint32) * MONO_DECL_SECURITY_SIZE, compare_declsecurity_attrs);
4154         table = &assembly->tables [MONO_TABLE_INTERFACEIMPL];
4155         if (table->rows)
4156                 qsort (table->values + MONO_INTERFACEIMPL_SIZE, table->rows, sizeof (guint32) * MONO_INTERFACEIMPL_SIZE, compare_interface_impl);
4157
4158         /* compress the tables */
4159         for (i = 0; i < MONO_TABLE_NUM; i++){
4160                 int row, col;
4161                 guint32 *values;
4162                 guint32 bitfield = meta->tables [i].size_bitfield;
4163                 if (!meta->tables [i].rows)
4164                         continue;
4165                 if (assembly->tables [i].columns != mono_metadata_table_count (bitfield))
4166                         g_error ("col count mismatch in %d: %d %d", i, assembly->tables [i].columns, mono_metadata_table_count (bitfield));
4167                 meta->tables [i].base = (char*)p;
4168                 for (row = 1; row <= meta->tables [i].rows; ++row) {
4169                         values = assembly->tables [i].values + row * assembly->tables [i].columns;
4170                         for (col = 0; col < assembly->tables [i].columns; ++col) {
4171                                 switch (mono_metadata_table_size (bitfield, col)) {
4172                                 case 1:
4173                                         *p++ = values [col];
4174                                         break;
4175                                 case 2:
4176                                         *p++ = values [col] & 0xff;
4177                                         *p++ = (values [col] >> 8) & 0xff;
4178                                         break;
4179                                 case 4:
4180                                         *p++ = values [col] & 0xff;
4181                                         *p++ = (values [col] >> 8) & 0xff;
4182                                         *p++ = (values [col] >> 16) & 0xff;
4183                                         *p++ = (values [col] >> 24) & 0xff;
4184                                         break;
4185                                 default:
4186                                         g_assert_not_reached ();
4187                                 }
4188                         }
4189                 }
4190                 g_assert ((p - (const unsigned char*)meta->tables [i].base) == (meta->tables [i].rows * meta->tables [i].row_size));
4191         }
4192         
4193         g_assert (assembly->guid.offset + assembly->guid.index < meta_size);
4194         memcpy (meta->raw_metadata + assembly->sheap.offset, assembly->sheap.data, assembly->sheap.index);
4195         memcpy (meta->raw_metadata + assembly->us.offset, assembly->us.data, assembly->us.index);
4196         memcpy (meta->raw_metadata + assembly->blob.offset, assembly->blob.data, assembly->blob.index);
4197         memcpy (meta->raw_metadata + assembly->guid.offset, assembly->guid.data, assembly->guid.index);
4198
4199         assembly->meta_size = assembly->guid.offset + assembly->guid.index;
4200 }
4201
4202 /*
4203  * Some tables in metadata need to be sorted according to some criteria, but
4204  * when methods and fields are first created with reflection, they may be assigned a token
4205  * that doesn't correspond to the final token they will get assigned after the sorting.
4206  * ILGenerator.cs keeps a fixup table that maps the position of tokens in the IL code stream
4207  * with the reflection objects that represent them. Once all the tables are set up, the 
4208  * reflection objects will contains the correct table index. fixup_method() will fixup the
4209  * tokens for the method with ILGenerator @ilgen.
4210  */
4211 static void
4212 fixup_method (MonoReflectionILGen *ilgen, gpointer value, MonoDynamicImage *assembly)
4213 {
4214         guint32 code_idx = GPOINTER_TO_UINT (value);
4215         MonoReflectionILTokenInfo *iltoken;
4216         MonoReflectionFieldBuilder *field;
4217         MonoReflectionCtorBuilder *ctor;
4218         MonoReflectionMethodBuilder *method;
4219         MonoReflectionTypeBuilder *tb;
4220         MonoReflectionArrayMethod *am;
4221         guint32 i, idx = 0;
4222         unsigned char *target;
4223
4224         for (i = 0; i < ilgen->num_token_fixups; ++i) {
4225                 iltoken = (MonoReflectionILTokenInfo *)mono_array_addr_with_size (ilgen->token_fixups, sizeof (MonoReflectionILTokenInfo), i);
4226                 target = (guchar*)assembly->code.data + code_idx + iltoken->code_pos;
4227                 switch (target [3]) {
4228                 case MONO_TABLE_FIELD:
4229                         if (!strcmp (iltoken->member->vtable->klass->name, "FieldBuilder")) {
4230                                 field = (MonoReflectionFieldBuilder *)iltoken->member;
4231                                 idx = field->table_idx;
4232                         } else if (!strcmp (iltoken->member->vtable->klass->name, "MonoField")) {
4233                                 MonoClassField *f = ((MonoReflectionField*)iltoken->member)->field;
4234                                 idx = GPOINTER_TO_UINT (g_hash_table_lookup (assembly->field_to_table_idx, f));
4235                         } else {
4236                                 g_assert_not_reached ();
4237                         }
4238                         break;
4239                 case MONO_TABLE_METHOD:
4240                         if (!strcmp (iltoken->member->vtable->klass->name, "MethodBuilder")) {
4241                                 method = (MonoReflectionMethodBuilder *)iltoken->member;
4242                                 idx = method->table_idx;
4243                         } else if (!strcmp (iltoken->member->vtable->klass->name, "ConstructorBuilder")) {
4244                                 ctor = (MonoReflectionCtorBuilder *)iltoken->member;
4245                                 idx = ctor->table_idx;
4246                         } else if (!strcmp (iltoken->member->vtable->klass->name, "MonoMethod") || 
4247                                            !strcmp (iltoken->member->vtable->klass->name, "MonoCMethod")) {
4248                                 MonoMethod *m = ((MonoReflectionMethod*)iltoken->member)->method;
4249                                 idx = GPOINTER_TO_UINT (g_hash_table_lookup (assembly->method_to_table_idx, m));
4250                         } else {
4251                                 g_assert_not_reached ();
4252                         }
4253                         break;
4254                 case MONO_TABLE_TYPEDEF:
4255                         if (strcmp (iltoken->member->vtable->klass->name, "TypeBuilder"))
4256                                 g_assert_not_reached ();
4257                         tb = (MonoReflectionTypeBuilder *)iltoken->member;
4258                         idx = tb->table_idx;
4259                         break;
4260                 case MONO_TABLE_MEMBERREF:
4261                         if (!strcmp (iltoken->member->vtable->klass->name, "MonoArrayMethod")) {
4262                                 am = (MonoReflectionArrayMethod*)iltoken->member;
4263                                 idx = am->table_idx;
4264                         } else if (!strcmp (iltoken->member->vtable->klass->name, "MonoMethod") ||
4265                                    !strcmp (iltoken->member->vtable->klass->name, "MonoCMethod") ||
4266                                    !strcmp (iltoken->member->vtable->klass->name, "MonoGenericMethod") ||
4267                                    !strcmp (iltoken->member->vtable->klass->name, "MonoGenericCMethod")) {
4268                                 MonoMethod *m = ((MonoReflectionMethod*)iltoken->member)->method;
4269                                 g_assert (m->klass->generic_class || m->klass->generic_container);
4270                                 continue;
4271                         } else if (!strcmp (iltoken->member->vtable->klass->name, "FieldBuilder")) {
4272                                 continue;
4273                         } else if (!strcmp (iltoken->member->vtable->klass->name, "MonoField")) {
4274                                 MonoClassField *f = ((MonoReflectionField*)iltoken->member)->field;
4275                                 g_assert (is_field_on_inst (f));
4276                                 continue;
4277                         } else if (!strcmp (iltoken->member->vtable->klass->name, "MethodBuilder") ||
4278                                         !strcmp (iltoken->member->vtable->klass->name, "ConstructorBuilder")) {
4279                                 continue;
4280                         } else if (!strcmp (iltoken->member->vtable->klass->name, "FieldOnTypeBuilderInst")) {
4281                                 continue;
4282                         } else if (!strcmp (iltoken->member->vtable->klass->name, "MethodOnTypeBuilderInst")) {
4283                                 continue;
4284                         } else if (!strcmp (iltoken->member->vtable->klass->name, "ConstructorOnTypeBuilderInst")) {
4285                                 continue;
4286                         } else {
4287                                 g_assert_not_reached ();
4288                         }
4289                         break;
4290                 case MONO_TABLE_METHODSPEC:
4291                         if (!strcmp (iltoken->member->vtable->klass->name, "MonoGenericMethod")) {
4292                                 MonoMethod *m = ((MonoReflectionMethod*)iltoken->member)->method;
4293                                 g_assert (mono_method_signature (m)->generic_param_count);
4294                                 continue;
4295                         } else if (!strcmp (iltoken->member->vtable->klass->name, "MethodBuilder")) {
4296                                 continue;
4297                         } else if (!strcmp (iltoken->member->vtable->klass->name, "MethodOnTypeBuilderInst")) {
4298                                 continue;
4299                         } else {
4300                                 g_assert_not_reached ();
4301                         }
4302                         break;
4303                 default:
4304                         g_error ("got unexpected table 0x%02x in fixup", target [3]);
4305                 }
4306                 target [0] = idx & 0xff;
4307                 target [1] = (idx >> 8) & 0xff;
4308                 target [2] = (idx >> 16) & 0xff;
4309         }
4310 }
4311
4312 /*
4313  * fixup_cattrs:
4314  *
4315  *   The CUSTOM_ATTRIBUTE table might contain METHODDEF tokens whose final
4316  * value is not known when the table is emitted.
4317  */
4318 static void
4319 fixup_cattrs (MonoDynamicImage *assembly)
4320 {
4321         MonoDynamicTable *table;
4322         guint32 *values;
4323         guint32 type, i, idx, token;
4324         MonoObject *ctor;
4325
4326         table = &assembly->tables [MONO_TABLE_CUSTOMATTRIBUTE];
4327
4328         for (i = 0; i < table->rows; ++i) {
4329                 values = table->values + ((i + 1) * MONO_CUSTOM_ATTR_SIZE);
4330
4331                 type = values [MONO_CUSTOM_ATTR_TYPE];
4332                 if ((type & MONO_CUSTOM_ATTR_TYPE_MASK) == MONO_CUSTOM_ATTR_TYPE_METHODDEF) {
4333                         idx = type >> MONO_CUSTOM_ATTR_TYPE_BITS;
4334                         token = mono_metadata_make_token (MONO_TABLE_METHOD, idx);
4335                         ctor = mono_g_hash_table_lookup (assembly->remapped_tokens, GUINT_TO_POINTER (token));
4336                         g_assert (ctor);
4337
4338                         if (!strcmp (ctor->vtable->klass->name, "MonoCMethod")) {
4339                                 MonoMethod *m = ((MonoReflectionMethod*)ctor)->method;
4340                                 idx = GPOINTER_TO_UINT (g_hash_table_lookup (assembly->method_to_table_idx, m));
4341                                 values [MONO_CUSTOM_ATTR_TYPE] = (idx << MONO_CUSTOM_ATTR_TYPE_BITS) | MONO_CUSTOM_ATTR_TYPE_METHODDEF;
4342                         } else if (!strcmp (ctor->vtable->klass->name, "ConstructorBuilder")) {
4343                                 MonoMethod *m = ((MonoReflectionCtorBuilder*)ctor)->mhandle;
4344                                 idx = GPOINTER_TO_UINT (g_hash_table_lookup (assembly->method_to_table_idx, m));
4345                                 values [MONO_CUSTOM_ATTR_TYPE] = (idx << MONO_CUSTOM_ATTR_TYPE_BITS) | MONO_CUSTOM_ATTR_TYPE_METHODDEF;
4346                         }
4347                 }
4348         }
4349 }
4350
4351 static void
4352 assembly_add_resource_manifest (MonoReflectionModuleBuilder *mb, MonoDynamicImage *assembly, MonoReflectionResource *rsrc, guint32 implementation)
4353 {
4354         MonoDynamicTable *table;
4355         guint32 *values;
4356
4357         table = &assembly->tables [MONO_TABLE_MANIFESTRESOURCE];
4358         table->rows++;
4359         alloc_table (table, table->rows);
4360         values = table->values + table->next_idx * MONO_MANIFEST_SIZE;
4361         values [MONO_MANIFEST_OFFSET] = rsrc->offset;
4362         values [MONO_MANIFEST_FLAGS] = rsrc->attrs;
4363         values [MONO_MANIFEST_NAME] = string_heap_insert_mstring (&assembly->sheap, rsrc->name);
4364         values [MONO_MANIFEST_IMPLEMENTATION] = implementation;
4365         table->next_idx++;
4366 }
4367
4368 static void
4369 assembly_add_resource (MonoReflectionModuleBuilder *mb, MonoDynamicImage *assembly, MonoReflectionResource *rsrc)
4370 {
4371         MonoDynamicTable *table;
4372         guint32 *values;
4373         char blob_size [6];
4374         guchar hash [20];
4375         char *b = blob_size;
4376         char *name, *sname;
4377         guint32 idx, offset;
4378
4379         if (rsrc->filename) {
4380                 name = mono_string_to_utf8 (rsrc->filename);
4381                 sname = g_path_get_basename (name);
4382         
4383                 table = &assembly->tables [MONO_TABLE_FILE];
4384                 table->rows++;
4385                 alloc_table (table, table->rows);
4386                 values = table->values + table->next_idx * MONO_FILE_SIZE;
4387                 values [MONO_FILE_FLAGS] = FILE_CONTAINS_NO_METADATA;
4388                 values [MONO_FILE_NAME] = string_heap_insert (&assembly->sheap, sname);
4389                 g_free (sname);
4390
4391                 mono_sha1_get_digest_from_file (name, hash);
4392                 mono_metadata_encode_value (20, b, &b);
4393                 values [MONO_FILE_HASH_VALUE] = mono_image_add_stream_data (&assembly->blob, blob_size, b-blob_size);
4394                 mono_image_add_stream_data (&assembly->blob, (char*)hash, 20);
4395                 g_free (name);
4396                 idx = table->next_idx++;
4397                 rsrc->offset = 0;
4398                 idx = MONO_IMPLEMENTATION_FILE | (idx << MONO_IMPLEMENTATION_BITS);
4399         } else {
4400                 char sizebuf [4];
4401                 char *data;
4402                 guint len;
4403                 if (rsrc->data) {
4404                         data = mono_array_addr (rsrc->data, char, 0);
4405                         len = mono_array_length (rsrc->data);
4406                 } else {
4407                         data = NULL;
4408                         len = 0;
4409                 }
4410                 offset = len;
4411                 sizebuf [0] = offset; sizebuf [1] = offset >> 8;
4412                 sizebuf [2] = offset >> 16; sizebuf [3] = offset >> 24;
4413                 rsrc->offset = mono_image_add_stream_data (&assembly->resources, sizebuf, 4);
4414                 mono_image_add_stream_data (&assembly->resources, data, len);
4415
4416                 if (!mb->is_main)
4417                         /* 
4418                          * The entry should be emitted into the MANIFESTRESOURCE table of 
4419                          * the main module, but that needs to reference the FILE table
4420                          * which isn't emitted yet.
4421                          */
4422                         return;
4423                 else
4424                         idx = 0;
4425         }
4426
4427         assembly_add_resource_manifest (mb, assembly, rsrc, idx);
4428 }
4429
4430 static void
4431 set_version_from_string (MonoString *version, guint32 *values)
4432 {
4433         gchar *ver, *p, *str;
4434         guint32 i;
4435         
4436         values [MONO_ASSEMBLY_MAJOR_VERSION] = 0;
4437         values [MONO_ASSEMBLY_MINOR_VERSION] = 0;
4438         values [MONO_ASSEMBLY_REV_NUMBER] = 0;
4439         values [MONO_ASSEMBLY_BUILD_NUMBER] = 0;
4440         if (!version)
4441                 return;
4442         ver = str = mono_string_to_utf8 (version);
4443         for (i = 0; i < 4; ++i) {
4444                 values [MONO_ASSEMBLY_MAJOR_VERSION + i] = strtol (ver, &p, 10);
4445                 switch (*p) {
4446                 case '.':
4447                         p++;
4448                         break;
4449                 case '*':
4450                         /* handle Revision and Build */
4451                         p++;
4452                         break;
4453                 }
4454                 ver = p;
4455         }
4456         g_free (str);
4457 }
4458
4459 static guint32
4460 load_public_key (MonoArray *pkey, MonoDynamicImage *assembly) {
4461         gsize len;
4462         guint32 token = 0;
4463         char blob_size [6];
4464         char *b = blob_size;
4465
4466         if (!pkey)
4467                 return token;
4468
4469         len = mono_array_length (pkey);
4470         mono_metadata_encode_value (len, b, &b);
4471         token = mono_image_add_stream_data (&assembly->blob, blob_size, b - blob_size);
4472         mono_image_add_stream_data (&assembly->blob, mono_array_addr (pkey, char, 0), len);
4473
4474         assembly->public_key = g_malloc (len);
4475         memcpy (assembly->public_key, mono_array_addr (pkey, char, 0), len);
4476         assembly->public_key_len = len;
4477
4478         /* Special case: check for ECMA key (16 bytes) */
4479         if ((len == MONO_ECMA_KEY_LENGTH) && mono_is_ecma_key (mono_array_addr (pkey, char, 0), len)) {
4480                 /* In this case we must reserve 128 bytes (1024 bits) for the signature */
4481                 assembly->strong_name_size = MONO_DEFAULT_PUBLIC_KEY_LENGTH;
4482         } else if (len >= MONO_PUBLIC_KEY_HEADER_LENGTH + MONO_MINIMUM_PUBLIC_KEY_LENGTH) {
4483                 /* minimum key size (in 2.0) is 384 bits */
4484                 assembly->strong_name_size = len - MONO_PUBLIC_KEY_HEADER_LENGTH;
4485         } else {
4486                 /* FIXME - verifier */
4487                 g_warning ("Invalid public key length: %d bits (total: %d)", (int)MONO_PUBLIC_KEY_BIT_SIZE (len), (int)len);
4488                 assembly->strong_name_size = MONO_DEFAULT_PUBLIC_KEY_LENGTH; /* to be safe */
4489         }
4490         assembly->strong_name = g_malloc0 (assembly->strong_name_size);
4491
4492         return token;
4493 }
4494
4495 static void
4496 mono_image_emit_manifest (MonoReflectionModuleBuilder *moduleb)
4497 {
4498         MonoDynamicTable *table;
4499         MonoDynamicImage *assembly;
4500         MonoReflectionAssemblyBuilder *assemblyb;
4501         MonoDomain *domain;
4502         guint32 *values;
4503         int i;
4504         guint32 module_index;
4505
4506         assemblyb = moduleb->assemblyb;
4507         assembly = moduleb->dynamic_image;
4508         domain = mono_object_domain (assemblyb);
4509
4510         /* Emit ASSEMBLY table */
4511         table = &assembly->tables [MONO_TABLE_ASSEMBLY];
4512         alloc_table (table, 1);
4513         values = table->values + MONO_ASSEMBLY_SIZE;
4514         values [MONO_ASSEMBLY_HASH_ALG] = assemblyb->algid? assemblyb->algid: ASSEMBLY_HASH_SHA1;
4515         values [MONO_ASSEMBLY_NAME] = string_heap_insert_mstring (&assembly->sheap, assemblyb->name);
4516         if (assemblyb->culture) {
4517                 values [MONO_ASSEMBLY_CULTURE] = string_heap_insert_mstring (&assembly->sheap, assemblyb->culture);
4518         } else {
4519                 values [MONO_ASSEMBLY_CULTURE] = string_heap_insert (&assembly->sheap, "");
4520         }
4521         values [MONO_ASSEMBLY_PUBLIC_KEY] = load_public_key (assemblyb->public_key, assembly);
4522         values [MONO_ASSEMBLY_FLAGS] = assemblyb->flags;
4523         set_version_from_string (assemblyb->version, values);
4524
4525         /* Emit FILE + EXPORTED_TYPE table */
4526         module_index = 0;
4527         for (i = 0; i < mono_array_length (assemblyb->modules); ++i) {
4528                 int j;
4529                 MonoReflectionModuleBuilder *file_module = 
4530                         mono_array_get (assemblyb->modules, MonoReflectionModuleBuilder*, i);
4531                 if (file_module != moduleb) {
4532                         mono_image_fill_file_table (domain, (MonoReflectionModule*)file_module, assembly);
4533                         module_index ++;
4534                         if (file_module->types) {
4535                                 for (j = 0; j < file_module->num_types; ++j) {
4536                                         MonoReflectionTypeBuilder *tb = mono_array_get (file_module->types, MonoReflectionTypeBuilder*, j);
4537                                         mono_image_fill_export_table (domain, tb, module_index, 0, assembly);
4538                                 }
4539                         }
4540                 }
4541         }
4542         if (assemblyb->loaded_modules) {
4543                 for (i = 0; i < mono_array_length (assemblyb->loaded_modules); ++i) {
4544                         MonoReflectionModule *file_module = 
4545                                 mono_array_get (assemblyb->loaded_modules, MonoReflectionModule*, i);
4546                         mono_image_fill_file_table (domain, file_module, assembly);
4547                         module_index ++;
4548                         mono_image_fill_export_table_from_module (domain, file_module, module_index, assembly);
4549                 }
4550         }
4551         if (assemblyb->type_forwarders)
4552                 mono_image_fill_export_table_from_type_forwarders (assemblyb, assembly);
4553
4554         /* Emit MANIFESTRESOURCE table */
4555         module_index = 0;
4556         for (i = 0; i < mono_array_length (assemblyb->modules); ++i) {
4557                 int j;
4558                 MonoReflectionModuleBuilder *file_module = 
4559                         mono_array_get (assemblyb->modules, MonoReflectionModuleBuilder*, i);
4560                 /* The table for the main module is emitted later */
4561                 if (file_module != moduleb) {
4562                         module_index ++;
4563                         if (file_module->resources) {
4564                                 int len = mono_array_length (file_module->resources);
4565                                 for (j = 0; j < len; ++j) {
4566                                         MonoReflectionResource* res = (MonoReflectionResource*)mono_array_addr (file_module->resources, MonoReflectionResource, j);
4567                                         assembly_add_resource_manifest (file_module, assembly, res, MONO_IMPLEMENTATION_FILE | (module_index << MONO_IMPLEMENTATION_BITS));
4568                                 }
4569                         }
4570                 }
4571         }               
4572 }
4573
4574 #ifndef DISABLE_REFLECTION_EMIT_SAVE
4575
4576 /*
4577  * mono_image_build_metadata() will fill the info in all the needed metadata tables
4578  * for the modulebuilder @moduleb.
4579  * At the end of the process, method and field tokens are fixed up and the 
4580  * on-disk compressed metadata representation is created.
4581  */
4582 void
4583 mono_image_build_metadata (MonoReflectionModuleBuilder *moduleb)
4584 {
4585         MonoDynamicTable *table;
4586         MonoDynamicImage *assembly;
4587         MonoReflectionAssemblyBuilder *assemblyb;
4588         MonoDomain *domain;
4589         MonoPtrArray types;
4590         guint32 *values;
4591         int i, j;
4592
4593         assemblyb = moduleb->assemblyb;
4594         assembly = moduleb->dynamic_image;
4595         domain = mono_object_domain (assemblyb);
4596
4597         if (assembly->text_rva)
4598                 return;
4599
4600         assembly->text_rva = START_TEXT_RVA;
4601
4602         if (moduleb->is_main) {
4603                 mono_image_emit_manifest (moduleb);
4604         }
4605
4606         table = &assembly->tables [MONO_TABLE_TYPEDEF];
4607         table->rows = 1; /* .<Module> */
4608         table->next_idx++;
4609         alloc_table (table, table->rows);
4610         /*
4611          * Set the first entry.
4612          */
4613         values = table->values + table->columns;
4614         values [MONO_TYPEDEF_FLAGS] = 0;
4615         values [MONO_TYPEDEF_NAME] = string_heap_insert (&assembly->sheap, "<Module>") ;
4616         values [MONO_TYPEDEF_NAMESPACE] = string_heap_insert (&assembly->sheap, "") ;
4617         values [MONO_TYPEDEF_EXTENDS] = 0;
4618         values [MONO_TYPEDEF_FIELD_LIST] = 1;
4619         values [MONO_TYPEDEF_METHOD_LIST] = 1;
4620
4621         /* 
4622          * handle global methods 
4623          * FIXME: test what to do when global methods are defined in multiple modules.
4624          */
4625         if (moduleb->global_methods) {
4626                 table = &assembly->tables [MONO_TABLE_METHOD];
4627                 table->rows += mono_array_length (moduleb->global_methods);
4628                 alloc_table (table, table->rows);
4629                 for (i = 0; i < mono_array_length (moduleb->global_methods); ++i)
4630                         mono_image_get_method_info (
4631                                 mono_array_get (moduleb->global_methods, MonoReflectionMethodBuilder*, i), assembly);
4632         }
4633         if (moduleb->global_fields) {
4634                 table = &assembly->tables [MONO_TABLE_FIELD];
4635                 table->rows += mono_array_length (moduleb->global_fields);
4636                 alloc_table (table, table->rows);
4637                 for (i = 0; i < mono_array_length (moduleb->global_fields); ++i)
4638                         mono_image_get_field_info (
4639                                 mono_array_get (moduleb->global_fields, MonoReflectionFieldBuilder*, i), assembly);
4640         }
4641
4642         table = &assembly->tables [MONO_TABLE_MODULE];
4643         alloc_table (table, 1);
4644         mono_image_fill_module_table (domain, moduleb, assembly);
4645
4646         /* Collect all types into a list sorted by their table_idx */
4647         mono_ptr_array_init (types, moduleb->num_types);
4648
4649         if (moduleb->types)
4650                 for (i = 0; i < moduleb->num_types; ++i) {
4651                         MonoReflectionTypeBuilder *type = mono_array_get (moduleb->types, MonoReflectionTypeBuilder*, i);
4652                         collect_types (&types, type);
4653                 }
4654
4655         mono_ptr_array_sort (types, (gpointer)compare_types_by_table_idx);
4656         table = &assembly->tables [MONO_TABLE_TYPEDEF];
4657         table->rows += mono_ptr_array_size (types);
4658         alloc_table (table, table->rows);
4659
4660         /*
4661          * Emit type names + namespaces at one place inside the string heap,
4662          * so load_class_names () needs to touch fewer pages.
4663          */
4664         for (i = 0; i < mono_ptr_array_size (types); ++i) {
4665                 MonoReflectionTypeBuilder *tb = mono_ptr_array_get (types, i);
4666                 string_heap_insert_mstring (&assembly->sheap, tb->nspace);
4667         }
4668         for (i = 0; i < mono_ptr_array_size (types); ++i) {
4669                 MonoReflectionTypeBuilder *tb = mono_ptr_array_get (types, i);
4670                 string_heap_insert_mstring (&assembly->sheap, tb->name);
4671         }
4672
4673         for (i = 0; i < mono_ptr_array_size (types); ++i) {
4674                 MonoReflectionTypeBuilder *type = mono_ptr_array_get (types, i);
4675                 mono_image_get_type_info (domain, type, assembly);
4676         }
4677
4678         /* 
4679          * table->rows is already set above and in mono_image_fill_module_table.
4680          */
4681         /* add all the custom attributes at the end, once all the indexes are stable */
4682         mono_image_add_cattrs (assembly, 1, MONO_CUSTOM_ATTR_ASSEMBLY, assemblyb->cattrs);
4683
4684         /* CAS assembly permissions */
4685         if (assemblyb->permissions_minimum)
4686                 mono_image_add_decl_security (assembly, mono_metadata_make_token (MONO_TABLE_ASSEMBLY, 1), assemblyb->permissions_minimum);
4687         if (assemblyb->permissions_optional)
4688                 mono_image_add_decl_security (assembly, mono_metadata_make_token (MONO_TABLE_ASSEMBLY, 1), assemblyb->permissions_optional);
4689         if (assemblyb->permissions_refused)
4690                 mono_image_add_decl_security (assembly, mono_metadata_make_token (MONO_TABLE_ASSEMBLY, 1), assemblyb->permissions_refused);
4691
4692         module_add_cattrs (assembly, moduleb);
4693
4694         /* fixup tokens */
4695         mono_g_hash_table_foreach (assembly->token_fixups, (GHFunc)fixup_method, assembly);
4696
4697         /* Create the MethodImpl table.  We do this after emitting all methods so we already know
4698          * the final tokens and don't need another fixup pass. */
4699
4700         if (moduleb->global_methods) {
4701                 for (i = 0; i < mono_array_length (moduleb->global_methods); ++i) {
4702                         MonoReflectionMethodBuilder *mb = mono_array_get (
4703                                 moduleb->global_methods, MonoReflectionMethodBuilder*, i);
4704                         mono_image_add_methodimpl (assembly, mb);
4705                 }
4706         }
4707
4708         for (i = 0; i < mono_ptr_array_size (types); ++i) {
4709                 MonoReflectionTypeBuilder *type = mono_ptr_array_get (types, i);
4710                 if (type->methods) {
4711                         for (j = 0; j < type->num_methods; ++j) {
4712                                 MonoReflectionMethodBuilder *mb = mono_array_get (
4713                                         type->methods, MonoReflectionMethodBuilder*, j);
4714
4715                                 mono_image_add_methodimpl (assembly, mb);
4716                         }
4717                 }
4718         }
4719
4720         mono_ptr_array_destroy (types);
4721
4722         fixup_cattrs (assembly);
4723 }
4724
4725 #else /* DISABLE_REFLECTION_EMIT_SAVE */
4726
4727 void
4728 mono_image_build_metadata (MonoReflectionModuleBuilder *moduleb)
4729 {
4730         g_error ("This mono runtime was configured with --enable-minimal=reflection_emit_save, so saving of dynamic assemblies is not supported.");
4731 }
4732
4733 #endif /* DISABLE_REFLECTION_EMIT_SAVE */
4734
4735
4736 typedef struct {
4737         guint32 import_lookup_table;
4738         guint32 timestamp;
4739         guint32 forwarder;
4740         guint32 name_rva;
4741         guint32 import_address_table_rva;
4742 } MonoIDT;
4743
4744 typedef struct {
4745         guint32 name_rva;
4746         guint32 flags;
4747 } MonoILT;
4748
4749 #ifndef DISABLE_REFLECTION_EMIT
4750
4751 /*
4752  * mono_image_insert_string:
4753  * @module: module builder object
4754  * @str: a string
4755  *
4756  * Insert @str into the user string stream of @module.
4757  */
4758 guint32
4759 mono_image_insert_string (MonoReflectionModuleBuilder *module, MonoString *str)
4760 {
4761         MonoDynamicImage *assembly;
4762         guint32 idx;
4763         char buf [16];
4764         char *b = buf;
4765         
4766         if (!module->dynamic_image)
4767                 mono_image_module_basic_init (module);
4768
4769         assembly = module->dynamic_image;
4770         
4771         if (assembly->save) {
4772                 mono_metadata_encode_value (1 | (str->length * 2), b, &b);
4773                 idx = mono_image_add_stream_data (&assembly->us, buf, b-buf);
4774 #if G_BYTE_ORDER != G_LITTLE_ENDIAN
4775         {
4776                 char *swapped = g_malloc (2 * mono_string_length (str));
4777                 const char *p = (const char*)mono_string_chars (str);
4778
4779                 swap_with_size (swapped, p, 2, mono_string_length (str));
4780                 mono_image_add_stream_data (&assembly->us, swapped, str->length * 2);
4781                 g_free (swapped);
4782         }
4783 #else
4784                 mono_image_add_stream_data (&assembly->us, (const char*)mono_string_chars (str), str->length * 2);
4785 #endif
4786                 mono_image_add_stream_data (&assembly->us, "", 1);
4787         } else {
4788                 idx = assembly->us.index ++;
4789         }
4790
4791         mono_g_hash_table_insert (assembly->tokens, GUINT_TO_POINTER (MONO_TOKEN_STRING | idx), str);
4792
4793         return MONO_TOKEN_STRING | idx;
4794 }
4795
4796 guint32
4797 mono_image_create_method_token (MonoDynamicImage *assembly, MonoObject *obj, MonoArray *opt_param_types)
4798 {
4799         MonoClass *klass;
4800         guint32 token = 0;
4801         MonoMethodSignature *sig;
4802
4803         klass = obj->vtable->klass;
4804         if (strcmp (klass->name, "MonoMethod") == 0 || strcmp (klass->name, "MonoCMethod") == 0) {
4805                 MonoMethod *method = ((MonoReflectionMethod *)obj)->method;
4806                 MonoMethodSignature *old;
4807                 guint32 sig_token, parent;
4808                 int nargs, i;
4809
4810                 g_assert (opt_param_types && (mono_method_signature (method)->sentinelpos >= 0));
4811
4812                 nargs = mono_array_length (opt_param_types);
4813                 old = mono_method_signature (method);
4814                 sig = mono_metadata_signature_alloc ( &assembly->image, old->param_count + nargs);
4815
4816                 sig->hasthis = old->hasthis;
4817                 sig->explicit_this = old->explicit_this;
4818                 sig->call_convention = old->call_convention;
4819                 sig->generic_param_count = old->generic_param_count;
4820                 sig->param_count = old->param_count + nargs;
4821                 sig->sentinelpos = old->param_count;
4822                 sig->ret = old->ret;
4823
4824                 for (i = 0; i < old->param_count; i++)
4825                         sig->params [i] = old->params [i];
4826
4827                 for (i = 0; i < nargs; i++) {
4828                         MonoReflectionType *rt = mono_array_get (opt_param_types, MonoReflectionType *, i);
4829                         sig->params [old->param_count + i] = mono_reflection_type_get_handle (rt);
4830                 }
4831
4832                 parent = mono_image_typedef_or_ref (assembly, &method->klass->byval_arg);
4833                 g_assert ((parent & MONO_TYPEDEFORREF_MASK) == MONO_MEMBERREF_PARENT_TYPEREF);
4834                 parent >>= MONO_TYPEDEFORREF_BITS;
4835
4836                 parent <<= MONO_MEMBERREF_PARENT_BITS;
4837                 parent |= MONO_MEMBERREF_PARENT_TYPEREF;
4838
4839                 sig_token = method_encode_signature (assembly, sig);
4840                 token = mono_image_get_varargs_method_token (assembly, parent, method->name, sig_token);
4841         } else if (strcmp (klass->name, "MethodBuilder") == 0) {
4842                 MonoReflectionMethodBuilder *mb = (MonoReflectionMethodBuilder *)obj;
4843                 ReflectionMethodBuilder rmb;
4844                 guint32 parent, sig_token;
4845                 int nopt_args, nparams, ngparams, i;
4846                 char *name;
4847
4848                 reflection_methodbuilder_from_method_builder (&rmb, mb);
4849                 rmb.opt_types = opt_param_types;
4850                 nopt_args = mono_array_length (opt_param_types);
4851
4852                 nparams = rmb.parameters ? mono_array_length (rmb.parameters): 0;
4853                 ngparams = rmb.generic_params ? mono_array_length (rmb.generic_params): 0;
4854                 sig = mono_metadata_signature_alloc (&assembly->image, nparams + nopt_args);
4855
4856                 sig->hasthis = !(rmb.attrs & METHOD_ATTRIBUTE_STATIC);
4857                 sig->explicit_this = (rmb.call_conv & 0x40) == 0x40;
4858                 sig->call_convention = rmb.call_conv;
4859                 sig->generic_param_count = ngparams;
4860                 sig->param_count = nparams + nopt_args;
4861                 sig->sentinelpos = nparams;
4862                 sig->ret = mono_reflection_type_get_handle (rmb.rtype);
4863
4864                 for (i = 0; i < nparams; i++) {
4865                         MonoReflectionType *rt = mono_array_get (rmb.parameters, MonoReflectionType *, i);
4866                         sig->params [i] = mono_reflection_type_get_handle (rt);
4867                 }
4868
4869                 for (i = 0; i < nopt_args; i++) {
4870                         MonoReflectionType *rt = mono_array_get (opt_param_types, MonoReflectionType *, i);
4871                         sig->params [nparams + i] = mono_reflection_type_get_handle (rt);
4872                 }
4873
4874                 sig_token = method_builder_encode_signature (assembly, &rmb);
4875
4876                 parent = mono_image_create_token (assembly, obj, TRUE, TRUE);
4877                 g_assert (mono_metadata_token_table (parent) == MONO_TABLE_METHOD);
4878
4879                 parent = mono_metadata_token_index (parent) << MONO_MEMBERREF_PARENT_BITS;
4880                 parent |= MONO_MEMBERREF_PARENT_METHODDEF;
4881
4882                 name = mono_string_to_utf8 (rmb.name);
4883                 token = mono_image_get_varargs_method_token (
4884                         assembly, parent, name, sig_token);
4885                 g_free (name);
4886         } else {
4887                 g_error ("requested method token for %s\n", klass->name);
4888         }
4889
4890         g_hash_table_insert (assembly->vararg_aux_hash, GUINT_TO_POINTER (token), sig);
4891         mono_g_hash_table_insert (assembly->tokens, GUINT_TO_POINTER (token), obj);
4892         return token;
4893 }
4894
4895 /*
4896  * mono_image_create_token:
4897  * @assembly: a dynamic assembly
4898  * @obj:
4899  * @register_token: Whenever to register the token in the assembly->tokens hash. 
4900  *
4901  * Get a token to insert in the IL code stream for the given MemberInfo.
4902  * The metadata emission routines need to pass FALSE as REGISTER_TOKEN, since by that time, 
4903  * the table_idx-es were recomputed, so registering the token would overwrite an existing 
4904  * entry.
4905  */
4906 guint32
4907 mono_image_create_token (MonoDynamicImage *assembly, MonoObject *obj, 
4908                                                  gboolean create_open_instance, gboolean register_token)
4909 {
4910         MonoClass *klass;
4911         guint32 token = 0;
4912
4913         klass = obj->vtable->klass;
4914
4915         /* Check for user defined reflection objects */
4916         /* TypeDelegator is the only corlib type which doesn't look like a MonoReflectionType */
4917         if (klass->image != mono_defaults.corlib || (strcmp (klass->name, "TypeDelegator") == 0))
4918                 mono_raise_exception (mono_get_exception_not_supported ("User defined subclasses of System.Type are not yet supported")); \
4919
4920         if (strcmp (klass->name, "MethodBuilder") == 0) {
4921                 MonoReflectionMethodBuilder *mb = (MonoReflectionMethodBuilder *)obj;
4922                 MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder*)mb->type;
4923
4924                 if (tb->module->dynamic_image == assembly && !tb->generic_params && !mb->generic_params)
4925                         token = mb->table_idx | MONO_TOKEN_METHOD_DEF;
4926                 else
4927                         token = mono_image_get_methodbuilder_token (assembly, mb, create_open_instance);
4928                 /*g_print ("got token 0x%08x for %s\n", token, mono_string_to_utf8 (mb->name));*/
4929         } else if (strcmp (klass->name, "ConstructorBuilder") == 0) {
4930                 MonoReflectionCtorBuilder *mb = (MonoReflectionCtorBuilder *)obj;
4931                 MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder*)mb->type;
4932
4933                 if (tb->module->dynamic_image == assembly && !tb->generic_params)
4934                         token = mb->table_idx | MONO_TOKEN_METHOD_DEF;
4935                 else
4936                         token = mono_image_get_ctorbuilder_token (assembly, mb);
4937                 /*g_print ("got token 0x%08x for %s\n", token, mono_string_to_utf8 (mb->name));*/
4938         } else if (strcmp (klass->name, "FieldBuilder") == 0) {
4939                 MonoReflectionFieldBuilder *fb = (MonoReflectionFieldBuilder *)obj;
4940                 MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder *)fb->typeb;
4941                 if (tb->generic_params) {
4942                         token = mono_image_get_generic_field_token (assembly, fb);
4943                 } else {
4944                         if (tb->module->dynamic_image == assembly) {
4945                                 token = fb->table_idx | MONO_TOKEN_FIELD_DEF;
4946                         } else {
4947                                 token = mono_image_get_fieldref_token (assembly, (MonoObject*)fb, fb->handle);
4948                         }
4949                 }
4950         } else if (strcmp (klass->name, "TypeBuilder") == 0) {
4951                 MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder *)obj;
4952                 if (create_open_instance && tb->generic_params) {
4953                         MonoType *type;
4954                         init_type_builder_generics (obj);
4955                         type = mono_reflection_type_get_handle ((MonoReflectionType *)obj);
4956                         token = mono_image_typedef_or_ref_full (assembly, type, TRUE);
4957                         token = mono_metadata_token_from_dor (token);
4958                 } else if (tb->module->dynamic_image == assembly) {
4959                         token = tb->table_idx | MONO_TOKEN_TYPE_DEF;
4960                 } else {
4961                         MonoType *type;
4962                         type = mono_reflection_type_get_handle ((MonoReflectionType *)obj);
4963                         token = mono_metadata_token_from_dor (mono_image_typedef_or_ref (assembly, type));
4964                 }
4965         } else if (strcmp (klass->name, "MonoType") == 0) {
4966                 MonoType *type = mono_reflection_type_get_handle ((MonoReflectionType *)obj);
4967                 MonoClass *mc = mono_class_from_mono_type (type);
4968                 token = mono_metadata_token_from_dor (
4969                         mono_image_typedef_or_ref_full (assembly, type, mc->generic_container == NULL || create_open_instance));
4970         } else if (strcmp (klass->name, "GenericTypeParameterBuilder") == 0) {
4971                 MonoType *type = mono_reflection_type_get_handle ((MonoReflectionType *)obj);
4972                 token = mono_metadata_token_from_dor (
4973                         mono_image_typedef_or_ref (assembly, type));
4974         } else if (strcmp (klass->name, "MonoGenericClass") == 0) {
4975                 MonoType *type = mono_reflection_type_get_handle ((MonoReflectionType *)obj);
4976                 token = mono_metadata_token_from_dor (
4977                         mono_image_typedef_or_ref (assembly, type));
4978         } else if (strcmp (klass->name, "MonoCMethod") == 0 ||
4979                    strcmp (klass->name, "MonoMethod") == 0 ||
4980                    strcmp (klass->name, "MonoGenericMethod") == 0 ||
4981                    strcmp (klass->name, "MonoGenericCMethod") == 0) {
4982                 MonoReflectionMethod *m = (MonoReflectionMethod *)obj;
4983                 if (m->method->is_inflated) {
4984                         if (create_open_instance)
4985                                 token = mono_image_get_methodspec_token (assembly, m->method);
4986                         else
4987                                 token = mono_image_get_inflated_method_token (assembly, m->method);
4988                 } else if ((m->method->klass->image == &assembly->image) &&
4989                          !m->method->klass->generic_class) {
4990                         static guint32 method_table_idx = 0xffffff;
4991                         if (m->method->klass->wastypebuilder) {
4992                                 /* we use the same token as the one that was assigned
4993                                  * to the Methodbuilder.
4994                                  * FIXME: do the equivalent for Fields.
4995                                  */
4996                                 token = m->method->token;
4997                         } else {
4998                                 /*
4999                                  * Each token should have a unique index, but the indexes are
5000                                  * assigned by managed code, so we don't know about them. An
5001                                  * easy solution is to count backwards...
5002                                  */
5003                                 method_table_idx --;
5004                                 token = MONO_TOKEN_METHOD_DEF | method_table_idx;
5005                         }
5006                 } else {
5007                         token = mono_image_get_methodref_token (assembly, m->method, create_open_instance);
5008                 }
5009                 /*g_print ("got token 0x%08x for %s\n", token, m->method->name);*/
5010         } else if (strcmp (klass->name, "MonoField") == 0) {
5011                 MonoReflectionField *f = (MonoReflectionField *)obj;
5012                 if ((f->field->parent->image == &assembly->image) && !is_field_on_inst (f->field)) {
5013                         static guint32 field_table_idx = 0xffffff;
5014                         field_table_idx --;
5015                         token = MONO_TOKEN_FIELD_DEF | field_table_idx;
5016                 } else {
5017                         token = mono_image_get_fieldref_token (assembly, (MonoObject*)f, f->field);
5018                 }
5019                 /*g_print ("got token 0x%08x for %s\n", token, f->field->name);*/
5020         } else if (strcmp (klass->name, "MonoArrayMethod") == 0) {
5021                 MonoReflectionArrayMethod *m = (MonoReflectionArrayMethod *)obj;
5022                 token = mono_image_get_array_token (assembly, m);
5023         } else if (strcmp (klass->name, "SignatureHelper") == 0) {
5024                 MonoReflectionSigHelper *s = (MonoReflectionSigHelper*)obj;
5025                 token = MONO_TOKEN_SIGNATURE | mono_image_get_sighelper_token (assembly, s);
5026         } else if (strcmp (klass->name, "EnumBuilder") == 0) {
5027                 MonoType *type = mono_reflection_type_get_handle ((MonoReflectionType *)obj);
5028                 token = mono_metadata_token_from_dor (
5029                         mono_image_typedef_or_ref (assembly, type));
5030         } else if (strcmp (klass->name, "FieldOnTypeBuilderInst") == 0) {
5031                 MonoReflectionFieldOnTypeBuilderInst *f = (MonoReflectionFieldOnTypeBuilderInst*)obj;
5032                 token = mono_image_get_field_on_inst_token (assembly, f);
5033         } else if (strcmp (klass->name, "ConstructorOnTypeBuilderInst") == 0) {
5034                 MonoReflectionCtorOnTypeBuilderInst *c = (MonoReflectionCtorOnTypeBuilderInst*)obj;
5035                 token = mono_image_get_ctor_on_inst_token (assembly, c, create_open_instance);
5036         } else if (strcmp (klass->name, "MethodOnTypeBuilderInst") == 0) {
5037                 MonoReflectionMethodOnTypeBuilderInst *m = (MonoReflectionMethodOnTypeBuilderInst*)obj;
5038                 token = mono_image_get_method_on_inst_token (assembly, m, create_open_instance);
5039         } else if (is_sre_array (klass) || is_sre_byref (klass) || is_sre_pointer (klass)) {
5040                 MonoReflectionType *type = (MonoReflectionType *)obj;
5041                 token = mono_metadata_token_from_dor (
5042                                 mono_image_typedef_or_ref (assembly, mono_reflection_type_get_handle (type)));
5043         } else {
5044                 g_error ("requested token for %s\n", klass->name);
5045         }
5046
5047         if (register_token)
5048                 mono_image_register_token (assembly, token, obj);
5049
5050         return token;
5051 }
5052
5053 /*
5054  * mono_image_register_token:
5055  *
5056  *   Register the TOKEN->OBJ mapping in the mapping table in ASSEMBLY. This is required for
5057  * the Module.ResolveXXXToken () methods to work.
5058  */
5059 void
5060 mono_image_register_token (MonoDynamicImage *assembly, guint32 token, MonoObject *obj)
5061 {
5062         MonoObject *prev = mono_g_hash_table_lookup (assembly->tokens, GUINT_TO_POINTER (token));
5063         if (prev) {
5064                 /* There could be multiple MethodInfo objects with the same token */
5065                 //g_assert (prev == obj);
5066         } else {
5067                 mono_g_hash_table_insert (assembly->tokens, GUINT_TO_POINTER (token), obj);
5068         }
5069 }
5070
5071 static MonoDynamicImage*
5072 create_dynamic_mono_image (MonoDynamicAssembly *assembly, char *assembly_name, char *module_name)
5073 {
5074         static const guchar entrycode [16] = {0xff, 0x25, 0};
5075         MonoDynamicImage *image;
5076         int i;
5077
5078         const char *version;
5079
5080         if (!strcmp (mono_get_runtime_info ()->framework_version, "2.1"))
5081                 version = "v2.0.50727"; /* HACK: SL 2 enforces the .net 2 metadata version */
5082         else
5083                 version = mono_get_runtime_info ()->runtime_version;
5084
5085 #if HAVE_BOEHM_GC
5086         /* The MonoGHashTable's need GC tracking */
5087         image = GC_MALLOC (sizeof (MonoDynamicImage));
5088 #else
5089         image = g_new0 (MonoDynamicImage, 1);
5090 #endif
5091
5092         mono_profiler_module_event (&image->image, MONO_PROFILE_START_LOAD);
5093         
5094         /*g_print ("created image %p\n", image);*/
5095         /* keep in sync with image.c */
5096         image->image.name = assembly_name;
5097         image->image.assembly_name = image->image.name; /* they may be different */
5098         image->image.module_name = module_name;
5099         image->image.version = g_strdup (version);
5100         image->image.md_version_major = 1;
5101         image->image.md_version_minor = 1;
5102         image->image.dynamic = TRUE;
5103
5104         image->image.references = g_new0 (MonoAssembly*, 1);
5105         image->image.references [0] = NULL;
5106
5107         mono_image_init (&image->image);
5108
5109         image->token_fixups = mono_g_hash_table_new_type ((GHashFunc)mono_object_hash, NULL, MONO_HASH_KEY_GC);
5110         image->method_to_table_idx = g_hash_table_new (NULL, NULL);
5111         image->field_to_table_idx = g_hash_table_new (NULL, NULL);
5112         image->method_aux_hash = g_hash_table_new (NULL, NULL);
5113         image->vararg_aux_hash = g_hash_table_new (NULL, NULL);
5114         image->handleref = g_hash_table_new (NULL, NULL);
5115         image->handleref_managed = mono_g_hash_table_new_type ((GHashFunc)mono_object_hash, NULL, MONO_HASH_KEY_GC);
5116         image->tokens = mono_g_hash_table_new_type (NULL, NULL, MONO_HASH_VALUE_GC);
5117         image->generic_def_objects = mono_g_hash_table_new_type (NULL, NULL, MONO_HASH_VALUE_GC);
5118         image->methodspec = mono_g_hash_table_new_type ((GHashFunc)mono_object_hash, NULL, MONO_HASH_KEY_GC);
5119         image->typespec = g_hash_table_new ((GHashFunc)mono_metadata_type_hash, (GCompareFunc)mono_metadata_type_equal);
5120         image->typeref = g_hash_table_new ((GHashFunc)mono_metadata_type_hash, (GCompareFunc)mono_metadata_type_equal);
5121         image->blob_cache = g_hash_table_new ((GHashFunc)mono_blob_entry_hash, (GCompareFunc)mono_blob_entry_equal);
5122         image->gen_params = g_ptr_array_new ();
5123         image->remapped_tokens = mono_g_hash_table_new_type (NULL, NULL, MONO_HASH_VALUE_GC);
5124
5125         /*g_print ("string heap create for image %p (%s)\n", image, module_name);*/
5126         string_heap_init (&image->sheap);
5127         mono_image_add_stream_data (&image->us, "", 1);
5128         add_to_blob_cached (image, (char*) "", 1, NULL, 0);
5129         /* import tables... */
5130         mono_image_add_stream_data (&image->code, (char*)entrycode, sizeof (entrycode));
5131         image->iat_offset = mono_image_add_stream_zero (&image->code, 8); /* two IAT entries */
5132         image->idt_offset = mono_image_add_stream_zero (&image->code, 2 * sizeof (MonoIDT)); /* two IDT entries */
5133         image->imp_names_offset = mono_image_add_stream_zero (&image->code, 2); /* flags for name entry */
5134         mono_image_add_stream_data (&image->code, "_CorExeMain", 12);
5135         mono_image_add_stream_data (&image->code, "mscoree.dll", 12);
5136         image->ilt_offset = mono_image_add_stream_zero (&image->code, 8); /* two ILT entries */
5137         stream_data_align (&image->code);
5138
5139         image->cli_header_offset = mono_image_add_stream_zero (&image->code, sizeof (MonoCLIHeader));
5140
5141         for (i=0; i < MONO_TABLE_NUM; ++i) {
5142                 image->tables [i].next_idx = 1;
5143                 image->tables [i].columns = table_sizes [i];
5144         }
5145
5146         image->image.assembly = (MonoAssembly*)assembly;
5147         image->run = assembly->run;
5148         image->save = assembly->save;
5149         image->pe_kind = 0x1; /* ILOnly */
5150         image->machine = 0x14c; /* I386 */
5151         
5152         mono_profiler_module_loaded (&image->image, MONO_PROFILE_OK);
5153
5154         return image;
5155 }
5156 #endif
5157
5158 static void
5159 free_blob_cache_entry (gpointer key, gpointer val, gpointer user_data)
5160 {
5161         g_free (key);
5162 }
5163
5164 static void
5165 release_hashtable (MonoGHashTable **hash)
5166 {
5167         if (*hash) {
5168                 mono_g_hash_table_destroy (*hash);
5169                 *hash = NULL;
5170         }
5171 }
5172
5173 void
5174 mono_dynamic_image_release_gc_roots (MonoDynamicImage *image)
5175 {
5176         release_hashtable (&image->token_fixups);
5177         release_hashtable (&image->handleref_managed);
5178         release_hashtable (&image->tokens);
5179         release_hashtable (&image->remapped_tokens);
5180         release_hashtable (&image->generic_def_objects);
5181         release_hashtable (&image->methodspec);
5182 }
5183
5184 void
5185 mono_dynamic_image_free (MonoDynamicImage *image)
5186 {
5187         MonoDynamicImage *di = image;
5188         GList *list;
5189         int i;
5190
5191         if (di->methodspec)
5192                 mono_g_hash_table_destroy (di->methodspec);
5193         if (di->typespec)
5194                 g_hash_table_destroy (di->typespec);
5195         if (di->typeref)
5196                 g_hash_table_destroy (di->typeref);
5197         if (di->handleref)
5198                 g_hash_table_destroy (di->handleref);
5199         if (di->handleref_managed)
5200                 mono_g_hash_table_destroy (di->handleref_managed);
5201         if (di->tokens)
5202                 mono_g_hash_table_destroy (di->tokens);
5203         if (di->remapped_tokens)
5204                 mono_g_hash_table_destroy (di->remapped_tokens);
5205         if (di->generic_def_objects)
5206                 mono_g_hash_table_destroy (di->generic_def_objects);
5207         if (di->blob_cache) {
5208                 g_hash_table_foreach (di->blob_cache, free_blob_cache_entry, NULL);
5209                 g_hash_table_destroy (di->blob_cache);
5210         }
5211         if (di->standalonesig_cache)
5212                 g_hash_table_destroy (di->standalonesig_cache);
5213         for (list = di->array_methods; list; list = list->next) {
5214                 ArrayMethod *am = (ArrayMethod *)list->data;
5215                 g_free (am->sig);
5216                 g_free (am->name);
5217                 g_free (am);
5218         }
5219         g_list_free (di->array_methods);
5220         if (di->gen_params) {
5221                 for (i = 0; i < di->gen_params->len; i++) {
5222                         GenericParamTableEntry *entry = g_ptr_array_index (di->gen_params, i);
5223                         mono_gc_deregister_root ((char*) &entry->gparam);
5224                         g_free (entry);
5225                 }
5226                 g_ptr_array_free (di->gen_params, TRUE);
5227         }
5228         if (di->token_fixups)
5229                 mono_g_hash_table_destroy (di->token_fixups);
5230         if (di->method_to_table_idx)
5231                 g_hash_table_destroy (di->method_to_table_idx);
5232         if (di->field_to_table_idx)
5233                 g_hash_table_destroy (di->field_to_table_idx);
5234         if (di->method_aux_hash)
5235                 g_hash_table_destroy (di->method_aux_hash);
5236         if (di->vararg_aux_hash)
5237                 g_hash_table_destroy (di->vararg_aux_hash);
5238         g_free (di->strong_name);
5239         g_free (di->win32_res);
5240         if (di->public_key)
5241                 g_free (di->public_key);
5242
5243         /*g_print ("string heap destroy for image %p\n", di);*/
5244         mono_dynamic_stream_reset (&di->sheap);
5245         mono_dynamic_stream_reset (&di->code);
5246         mono_dynamic_stream_reset (&di->resources);
5247         mono_dynamic_stream_reset (&di->us);
5248         mono_dynamic_stream_reset (&di->blob);
5249         mono_dynamic_stream_reset (&di->tstream);
5250         mono_dynamic_stream_reset (&di->guid);
5251         for (i = 0; i < MONO_TABLE_NUM; ++i) {
5252                 g_free (di->tables [i].values);
5253         }
5254 }       
5255
5256 void
5257 mono_dynamic_image_free_image (MonoDynamicImage *image)
5258 {
5259         /* See create_dynamic_mono_image () */
5260 #if HAVE_BOEHM_GC
5261         /* Allocated using GC_MALLOC */
5262 #else
5263         g_free (image);
5264 #endif
5265 }
5266
5267 #ifndef DISABLE_REFLECTION_EMIT
5268
5269 /*
5270  * mono_image_basic_init:
5271  * @assembly: an assembly builder object
5272  *
5273  * Create the MonoImage that represents the assembly builder and setup some
5274  * of the helper hash table and the basic metadata streams.
5275  */
5276 void
5277 mono_image_basic_init (MonoReflectionAssemblyBuilder *assemblyb)
5278 {
5279         MonoDynamicAssembly *assembly;
5280         MonoDynamicImage *image;
5281         MonoDomain *domain = mono_object_domain (assemblyb);
5282         
5283         if (assemblyb->dynamic_assembly)
5284                 return;
5285
5286 #if HAVE_BOEHM_GC
5287         /* assembly->assembly.image might be GC allocated */
5288         assembly = assemblyb->dynamic_assembly = GC_MALLOC (sizeof (MonoDynamicAssembly));
5289 #else
5290         assembly = assemblyb->dynamic_assembly = g_new0 (MonoDynamicAssembly, 1);
5291 #endif
5292
5293         mono_profiler_assembly_event (&assembly->assembly, MONO_PROFILE_START_LOAD);
5294         
5295         assembly->assembly.ref_count = 1;
5296         assembly->assembly.dynamic = TRUE;
5297         assembly->assembly.corlib_internal = assemblyb->corlib_internal;
5298         assemblyb->assembly.assembly = (MonoAssembly*)assembly;
5299         assembly->assembly.basedir = mono_string_to_utf8 (assemblyb->dir);
5300         if (assemblyb->culture)
5301                 assembly->assembly.aname.culture = mono_string_to_utf8 (assemblyb->culture);
5302         else
5303                 assembly->assembly.aname.culture = g_strdup ("");
5304
5305         if (assemblyb->version) {
5306                         char *vstr = mono_string_to_utf8 (assemblyb->version);
5307                         char **version = g_strsplit (vstr, ".", 4);
5308                         char **parts = version;
5309                         assembly->assembly.aname.major = atoi (*parts++);
5310                         assembly->assembly.aname.minor = atoi (*parts++);
5311                         assembly->assembly.aname.build = *parts != NULL ? atoi (*parts++) : 0;
5312                         assembly->assembly.aname.revision = *parts != NULL ? atoi (*parts) : 0;
5313
5314                         g_strfreev (version);
5315                         g_free (vstr);
5316         } else {
5317                         assembly->assembly.aname.major = 0;
5318                         assembly->assembly.aname.minor = 0;
5319                         assembly->assembly.aname.build = 0;
5320                         assembly->assembly.aname.revision = 0;
5321         }
5322
5323         assembly->run = assemblyb->access != 2;
5324         assembly->save = assemblyb->access != 1;
5325         assembly->domain = domain;
5326
5327         image = create_dynamic_mono_image (assembly, mono_string_to_utf8 (assemblyb->name), g_strdup ("RefEmit_YouForgotToDefineAModule"));
5328         image->initial_image = TRUE;
5329         assembly->assembly.aname.name = image->image.name;
5330         assembly->assembly.image = &image->image;
5331         if (assemblyb->pktoken && assemblyb->pktoken->max_length) {
5332                 /* -1 to correct for the trailing NULL byte */
5333                 if (assemblyb->pktoken->max_length != MONO_PUBLIC_KEY_TOKEN_LENGTH - 1) {
5334                         g_error ("Public key token length invalid for assembly %s: %i", assembly->assembly.aname.name, assemblyb->pktoken->max_length);
5335                 }
5336                 memcpy (&assembly->assembly.aname.public_key_token, mono_array_addr (assemblyb->pktoken, guint8, 0), assemblyb->pktoken->max_length);           
5337         }
5338
5339         mono_domain_assemblies_lock (domain);
5340         domain->domain_assemblies = g_slist_append (domain->domain_assemblies, assembly);
5341         mono_domain_assemblies_unlock (domain);
5342
5343         register_assembly (mono_object_domain (assemblyb), &assemblyb->assembly, &assembly->assembly);
5344         
5345         mono_profiler_assembly_loaded (&assembly->assembly, MONO_PROFILE_OK);
5346         
5347         mono_assembly_invoke_load_hook ((MonoAssembly*)assembly);
5348 }
5349
5350 #endif /* !DISABLE_REFLECTION_EMIT */
5351
5352 #ifndef DISABLE_REFLECTION_EMIT_SAVE
5353
5354 static int
5355 calc_section_size (MonoDynamicImage *assembly)
5356 {
5357         int nsections = 0;
5358
5359         /* alignment constraints */
5360         mono_image_add_stream_zero (&assembly->code, 4 - (assembly->code.index % 4));
5361         g_assert ((assembly->code.index % 4) == 0);
5362         assembly->meta_size += 3;
5363         assembly->meta_size &= ~3;
5364         mono_image_add_stream_zero (&assembly->resources, 4 - (assembly->resources.index % 4));
5365         g_assert ((assembly->resources.index % 4) == 0);
5366
5367         assembly->sections [MONO_SECTION_TEXT].size = assembly->meta_size + assembly->code.index + assembly->resources.index + assembly->strong_name_size;
5368         assembly->sections [MONO_SECTION_TEXT].attrs = SECT_FLAGS_HAS_CODE | SECT_FLAGS_MEM_EXECUTE | SECT_FLAGS_MEM_READ;
5369         nsections++;
5370
5371         if (assembly->win32_res) {
5372                 guint32 res_size = (assembly->win32_res_size + 3) & ~3;
5373
5374                 assembly->sections [MONO_SECTION_RSRC].size = res_size;
5375                 assembly->sections [MONO_SECTION_RSRC].attrs = SECT_FLAGS_HAS_INITIALIZED_DATA | SECT_FLAGS_MEM_READ;
5376                 nsections++;
5377         }
5378
5379         assembly->sections [MONO_SECTION_RELOC].size = 12;
5380         assembly->sections [MONO_SECTION_RELOC].attrs = SECT_FLAGS_MEM_READ | SECT_FLAGS_MEM_DISCARDABLE | SECT_FLAGS_HAS_INITIALIZED_DATA;
5381         nsections++;
5382
5383         return nsections;
5384 }
5385
5386 typedef struct {
5387         guint32 id;
5388         guint32 offset;
5389         GSList *children;
5390         MonoReflectionWin32Resource *win32_res; /* Only for leaf nodes */
5391 } ResTreeNode;
5392
5393 static int
5394 resource_tree_compare_by_id (gconstpointer a, gconstpointer b)
5395 {
5396         ResTreeNode *t1 = (ResTreeNode*)a;
5397         ResTreeNode *t2 = (ResTreeNode*)b;
5398
5399         return t1->id - t2->id;
5400 }
5401
5402 /*
5403  * resource_tree_create:
5404  *
5405  *  Organize the resources into a resource tree.
5406  */
5407 static ResTreeNode *
5408 resource_tree_create (MonoArray *win32_resources)
5409 {
5410         ResTreeNode *tree, *res_node, *type_node, *lang_node;
5411         GSList *l;
5412         int i;
5413
5414         tree = g_new0 (ResTreeNode, 1);
5415         
5416         for (i = 0; i < mono_array_length (win32_resources); ++i) {
5417                 MonoReflectionWin32Resource *win32_res =
5418                         (MonoReflectionWin32Resource*)mono_array_addr (win32_resources, MonoReflectionWin32Resource, i);
5419
5420                 /* Create node */
5421
5422                 /* FIXME: BUG: this stores managed references in unmanaged memory */
5423                 lang_node = g_new0 (ResTreeNode, 1);
5424                 lang_node->id = win32_res->lang_id;
5425                 lang_node->win32_res = win32_res;
5426
5427                 /* Create type node if neccesary */
5428                 type_node = NULL;
5429                 for (l = tree->children; l; l = l->next)
5430                         if (((ResTreeNode*)(l->data))->id == win32_res->res_type) {
5431                                 type_node = (ResTreeNode*)l->data;
5432                                 break;
5433                         }
5434
5435                 if (!type_node) {
5436                         type_node = g_new0 (ResTreeNode, 1);
5437                         type_node->id = win32_res->res_type;
5438
5439                         /* 
5440                          * The resource types have to be sorted otherwise
5441                          * Windows Explorer can't display the version information.
5442                          */
5443                         tree->children = g_slist_insert_sorted (tree->children, 
5444                                 type_node, resource_tree_compare_by_id);
5445                 }
5446
5447                 /* Create res node if neccesary */
5448                 res_node = NULL;
5449                 for (l = type_node->children; l; l = l->next)
5450                         if (((ResTreeNode*)(l->data))->id == win32_res->res_id) {
5451                                 res_node = (ResTreeNode*)l->data;
5452                                 break;
5453                         }
5454
5455                 if (!res_node) {
5456                         res_node = g_new0 (ResTreeNode, 1);
5457                         res_node->id = win32_res->res_id;
5458                         type_node->children = g_slist_append (type_node->children, res_node);
5459                 }
5460
5461                 res_node->children = g_slist_append (res_node->children, lang_node);
5462         }
5463
5464         return tree;
5465 }
5466
5467 /*
5468  * resource_tree_encode:
5469  * 
5470  *   Encode the resource tree into the format used in the PE file.
5471  */
5472 static void
5473 resource_tree_encode (ResTreeNode *node, char *begin, char *p, char **endbuf)
5474 {
5475         char *entries;
5476         MonoPEResourceDir dir;
5477         MonoPEResourceDirEntry dir_entry;
5478         MonoPEResourceDataEntry data_entry;
5479         GSList *l;
5480         guint32 res_id_entries;
5481
5482         /*
5483          * For the format of the resource directory, see the article
5484          * "An In-Depth Look into the Win32 Portable Executable File Format" by
5485          * Matt Pietrek
5486          */
5487
5488         memset (&dir, 0, sizeof (dir));
5489         memset (&dir_entry, 0, sizeof (dir_entry));
5490         memset (&data_entry, 0, sizeof (data_entry));
5491
5492         g_assert (sizeof (dir) == 16);
5493         g_assert (sizeof (dir_entry) == 8);
5494         g_assert (sizeof (data_entry) == 16);
5495
5496         node->offset = p - begin;
5497
5498         /* IMAGE_RESOURCE_DIRECTORY */
5499         res_id_entries = g_slist_length (node->children);
5500         dir.res_id_entries = GUINT16_TO_LE (res_id_entries);
5501
5502         memcpy (p, &dir, sizeof (dir));
5503         p += sizeof (dir);
5504
5505         /* Reserve space for entries */
5506         entries = p;
5507         p += sizeof (dir_entry) * res_id_entries;
5508
5509         /* Write children */
5510         for (l = node->children; l; l = l->next) {
5511                 ResTreeNode *child = (ResTreeNode*)l->data;
5512
5513                 if (child->win32_res) {
5514                         guint32 size;
5515
5516                         child->offset = p - begin;
5517
5518                         /* IMAGE_RESOURCE_DATA_ENTRY */
5519                         data_entry.rde_data_offset = GUINT32_TO_LE (p - begin + sizeof (data_entry));
5520                         size = mono_array_length (child->win32_res->res_data);
5521                         data_entry.rde_size = GUINT32_TO_LE (size);
5522
5523                         memcpy (p, &data_entry, sizeof (data_entry));
5524                         p += sizeof (data_entry);
5525
5526                         memcpy (p, mono_array_addr (child->win32_res->res_data, char, 0), size);
5527                         p += size;
5528                 } else {
5529                         resource_tree_encode (child, begin, p, &p);
5530                 }
5531         }
5532
5533         /* IMAGE_RESOURCE_ENTRY */
5534         for (l = node->children; l; l = l->next) {
5535                 ResTreeNode *child = (ResTreeNode*)l->data;
5536
5537                 MONO_PE_RES_DIR_ENTRY_SET_NAME (dir_entry, FALSE, child->id);
5538                 MONO_PE_RES_DIR_ENTRY_SET_DIR (dir_entry, !child->win32_res, child->offset);
5539
5540                 memcpy (entries, &dir_entry, sizeof (dir_entry));
5541                 entries += sizeof (dir_entry);
5542         }
5543
5544         *endbuf = p;
5545 }
5546
5547 static void
5548 resource_tree_free (ResTreeNode * node)
5549 {
5550         GSList * list;
5551         for (list = node->children; list; list = list->next)
5552                 resource_tree_free ((ResTreeNode*)list->data);
5553         g_slist_free(node->children);
5554         g_free (node);
5555 }
5556
5557 static void
5558 assembly_add_win32_resources (MonoDynamicImage *assembly, MonoReflectionAssemblyBuilder *assemblyb)
5559 {
5560         char *buf;
5561         char *p;
5562         guint32 size, i;
5563         MonoReflectionWin32Resource *win32_res;
5564         ResTreeNode *tree;
5565
5566         if (!assemblyb->win32_resources)
5567                 return;
5568
5569         /*
5570          * Resources are stored in a three level tree inside the PE file.
5571          * - level one contains a node for each type of resource
5572          * - level two contains a node for each resource
5573          * - level three contains a node for each instance of a resource for a
5574          *   specific language.
5575          */
5576
5577         tree = resource_tree_create (assemblyb->win32_resources);
5578
5579         /* Estimate the size of the encoded tree */
5580         size = 0;
5581         for (i = 0; i < mono_array_length (assemblyb->win32_resources); ++i) {
5582                 win32_res = (MonoReflectionWin32Resource*)mono_array_addr (assemblyb->win32_resources, MonoReflectionWin32Resource, i);
5583                 size += mono_array_length (win32_res->res_data);
5584         }
5585         /* Directory structure */
5586         size += mono_array_length (assemblyb->win32_resources) * 256;
5587         p = buf = g_malloc (size);
5588
5589         resource_tree_encode (tree, p, p, &p);
5590
5591         g_assert (p - buf <= size);
5592
5593         assembly->win32_res = g_malloc (p - buf);
5594         assembly->win32_res_size = p - buf;
5595         memcpy (assembly->win32_res, buf, p - buf);
5596
5597         g_free (buf);
5598         resource_tree_free (tree);
5599 }
5600
5601 static void
5602 fixup_resource_directory (char *res_section, char *p, guint32 rva)
5603 {
5604         MonoPEResourceDir *dir = (MonoPEResourceDir*)p;
5605         int i;
5606
5607         p += sizeof (MonoPEResourceDir);
5608         for (i = 0; i < GUINT16_FROM_LE (dir->res_named_entries) + GUINT16_FROM_LE (dir->res_id_entries); ++i) {
5609                 MonoPEResourceDirEntry *dir_entry = (MonoPEResourceDirEntry*)p;
5610                 char *child = res_section + MONO_PE_RES_DIR_ENTRY_DIR_OFFSET (*dir_entry);
5611                 if (MONO_PE_RES_DIR_ENTRY_IS_DIR (*dir_entry)) {
5612                         fixup_resource_directory (res_section, child, rva);
5613                 } else {
5614                         MonoPEResourceDataEntry *data_entry = (MonoPEResourceDataEntry*)child;
5615                         data_entry->rde_data_offset = GUINT32_TO_LE (GUINT32_FROM_LE (data_entry->rde_data_offset) + rva);
5616                 }
5617
5618                 p += sizeof (MonoPEResourceDirEntry);
5619         }
5620 }
5621
5622 static void
5623 checked_write_file (HANDLE f, gconstpointer buffer, guint32 numbytes)
5624 {
5625         guint32 dummy;
5626         if (!WriteFile (f, buffer, numbytes, &dummy, NULL))
5627                 g_error ("WriteFile returned %d\n", GetLastError ());
5628 }
5629
5630 /*
5631  * mono_image_create_pefile:
5632  * @mb: a module builder object
5633  * 
5634  * This function creates the PE-COFF header, the image sections, the CLI header  * etc. all the data is written in
5635  * assembly->pefile where it can be easily retrieved later in chunks.
5636  */
5637 void
5638 mono_image_create_pefile (MonoReflectionModuleBuilder *mb, HANDLE file)
5639 {
5640         MonoMSDOSHeader *msdos;
5641         MonoDotNetHeader *header;
5642         MonoSectionTable *section;
5643         MonoCLIHeader *cli_header;
5644         guint32 size, image_size, virtual_base, text_offset;
5645         guint32 header_start, section_start, file_offset, virtual_offset;
5646         MonoDynamicImage *assembly;
5647         MonoReflectionAssemblyBuilder *assemblyb;
5648         MonoDynamicStream pefile_stream = {0};
5649         MonoDynamicStream *pefile = &pefile_stream;
5650         int i, nsections;
5651         guint32 *rva, value;
5652         guchar *p;
5653         static const unsigned char msheader[] = {
5654                 0x4d, 0x5a, 0x90, 0x00, 0x03, 0x00, 0x00, 0x00,  0x04, 0x00, 0x00, 0x00, 0xff, 0xff, 0x00, 0x00,
5655                 0xb8, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,  0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
5656                 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
5657                 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,  0x00, 0x00, 0x00, 0x00, 0x80, 0x00, 0x00, 0x00,
5658                 0x0e, 0x1f, 0xba, 0x0e, 0x00, 0xb4, 0x09, 0xcd,  0x21, 0xb8, 0x01, 0x4c, 0xcd, 0x21, 0x54, 0x68,
5659                 0x69, 0x73, 0x20, 0x70, 0x72, 0x6f, 0x67, 0x72,  0x61, 0x6d, 0x20, 0x63, 0x61, 0x6e, 0x6e, 0x6f,
5660                 0x74, 0x20, 0x62, 0x65, 0x20, 0x72, 0x75, 0x6e,  0x20, 0x69, 0x6e, 0x20, 0x44, 0x4f, 0x53, 0x20,
5661                 0x6d, 0x6f, 0x64, 0x65, 0x2e, 0x0d, 0x0d, 0x0a,  0x24, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
5662         };
5663
5664         assemblyb = mb->assemblyb;
5665
5666         mono_image_basic_init (assemblyb);
5667         assembly = mb->dynamic_image;
5668
5669         assembly->pe_kind = assemblyb->pe_kind;
5670         assembly->machine = assemblyb->machine;
5671         ((MonoDynamicImage*)assemblyb->dynamic_assembly->assembly.image)->pe_kind = assemblyb->pe_kind;
5672         ((MonoDynamicImage*)assemblyb->dynamic_assembly->assembly.image)->machine = assemblyb->machine;
5673         
5674         mono_image_build_metadata (mb);
5675
5676         if (mb->is_main && assemblyb->resources) {
5677                 int len = mono_array_length (assemblyb->resources);
5678                 for (i = 0; i < len; ++i)
5679                         assembly_add_resource (mb, assembly, (MonoReflectionResource*)mono_array_addr (assemblyb->resources, MonoReflectionResource, i));
5680         }
5681
5682         if (mb->resources) {
5683                 int len = mono_array_length (mb->resources);
5684                 for (i = 0; i < len; ++i)
5685                         assembly_add_resource (mb, assembly, (MonoReflectionResource*)mono_array_addr (mb->resources, MonoReflectionResource, i));
5686         }
5687
5688         build_compressed_metadata (assembly);
5689
5690         if (mb->is_main)
5691                 assembly_add_win32_resources (assembly, assemblyb);
5692
5693         nsections = calc_section_size (assembly);
5694         
5695         /* The DOS header and stub */
5696         g_assert (sizeof (MonoMSDOSHeader) == sizeof (msheader));
5697         mono_image_add_stream_data (pefile, (char*)msheader, sizeof (msheader));
5698
5699         /* the dotnet header */
5700         header_start = mono_image_add_stream_zero (pefile, sizeof (MonoDotNetHeader));
5701
5702         /* the section tables */
5703         section_start = mono_image_add_stream_zero (pefile, sizeof (MonoSectionTable) * nsections);
5704
5705         file_offset = section_start + sizeof (MonoSectionTable) * nsections;
5706         virtual_offset = VIRT_ALIGN;
5707         image_size = 0;
5708
5709         for (i = 0; i < MONO_SECTION_MAX; ++i) {
5710                 if (!assembly->sections [i].size)
5711                         continue;
5712                 /* align offsets */
5713                 file_offset += FILE_ALIGN - 1;
5714                 file_offset &= ~(FILE_ALIGN - 1);
5715                 virtual_offset += VIRT_ALIGN - 1;
5716                 virtual_offset &= ~(VIRT_ALIGN - 1);
5717
5718                 assembly->sections [i].offset = file_offset;
5719                 assembly->sections [i].rva = virtual_offset;
5720
5721                 file_offset += assembly->sections [i].size;
5722                 virtual_offset += assembly->sections [i].size;
5723                 image_size += (assembly->sections [i].size + VIRT_ALIGN - 1) & ~(VIRT_ALIGN - 1);
5724         }
5725
5726         file_offset += FILE_ALIGN - 1;
5727         file_offset &= ~(FILE_ALIGN - 1);
5728
5729         image_size += section_start + sizeof (MonoSectionTable) * nsections;
5730
5731         /* back-patch info */
5732         msdos = (MonoMSDOSHeader*)pefile->data;
5733         msdos->pe_offset = GUINT32_FROM_LE (sizeof (MonoMSDOSHeader));
5734
5735         header = (MonoDotNetHeader*)(pefile->data + header_start);
5736         header->pesig [0] = 'P';
5737         header->pesig [1] = 'E';
5738         
5739         header->coff.coff_machine = GUINT16_FROM_LE (assemblyb->machine);
5740         header->coff.coff_sections = GUINT16_FROM_LE (nsections);
5741         header->coff.coff_time = GUINT32_FROM_LE (time (NULL));
5742         header->coff.coff_opt_header_size = GUINT16_FROM_LE (sizeof (MonoDotNetHeader) - sizeof (MonoCOFFHeader) - 4);
5743         if (assemblyb->pekind == 1) {
5744                 /* it's a dll */
5745                 header->coff.coff_attributes = GUINT16_FROM_LE (0x210e);
5746         } else {
5747                 /* it's an exe */
5748                 header->coff.coff_attributes = GUINT16_FROM_LE (0x010e);
5749         }
5750
5751         virtual_base = 0x400000; /* FIXME: 0x10000000 if a DLL */
5752
5753         header->pe.pe_magic = GUINT16_FROM_LE (0x10B);
5754         header->pe.pe_major = 6;
5755         header->pe.pe_minor = 0;
5756         size = assembly->sections [MONO_SECTION_TEXT].size;
5757         size += FILE_ALIGN - 1;
5758         size &= ~(FILE_ALIGN - 1);
5759         header->pe.pe_code_size = GUINT32_FROM_LE(size);
5760         size = assembly->sections [MONO_SECTION_RSRC].size;
5761         size += FILE_ALIGN - 1;
5762         size &= ~(FILE_ALIGN - 1);
5763         header->pe.pe_data_size = GUINT32_FROM_LE(size);
5764         g_assert (START_TEXT_RVA == assembly->sections [MONO_SECTION_TEXT].rva);
5765         header->pe.pe_rva_code_base = GUINT32_FROM_LE (assembly->sections [MONO_SECTION_TEXT].rva);
5766         header->pe.pe_rva_data_base = GUINT32_FROM_LE (assembly->sections [MONO_SECTION_RSRC].rva);
5767         /* pe_rva_entry_point always at the beginning of the text section */
5768         header->pe.pe_rva_entry_point = GUINT32_FROM_LE (assembly->sections [MONO_SECTION_TEXT].rva);
5769
5770         header->nt.pe_image_base = GUINT32_FROM_LE (virtual_base);
5771         header->nt.pe_section_align = GUINT32_FROM_LE (VIRT_ALIGN);
5772         header->nt.pe_file_alignment = GUINT32_FROM_LE (FILE_ALIGN);
5773         header->nt.pe_os_major = GUINT16_FROM_LE (4);
5774         header->nt.pe_os_minor = GUINT16_FROM_LE (0);
5775         header->nt.pe_subsys_major = GUINT16_FROM_LE (4);
5776         size = section_start;
5777         size += FILE_ALIGN - 1;
5778         size &= ~(FILE_ALIGN - 1);
5779         header->nt.pe_header_size = GUINT32_FROM_LE (size);
5780         size = image_size;
5781         size += VIRT_ALIGN - 1;
5782         size &= ~(VIRT_ALIGN - 1);
5783         header->nt.pe_image_size = GUINT32_FROM_LE (size);
5784
5785         /*
5786         // Translate the PEFileKind value to the value expected by the Windows loader
5787         */
5788         {
5789                 short kind;
5790
5791                 /*
5792                 // PEFileKinds.Dll == 1
5793                 // PEFileKinds.ConsoleApplication == 2
5794                 // PEFileKinds.WindowApplication == 3
5795                 //
5796                 // need to get:
5797                 //     IMAGE_SUBSYSTEM_WINDOWS_GUI 2 // Image runs in the Windows GUI subsystem.
5798                 //     IMAGE_SUBSYSTEM_WINDOWS_CUI 3 // Image runs in the Windows character subsystem.
5799                 */
5800                 if (assemblyb->pekind == 3)
5801                         kind = 2;
5802                 else
5803                         kind = 3;
5804                 
5805                 header->nt.pe_subsys_required = GUINT16_FROM_LE (kind);
5806         }    
5807         header->nt.pe_stack_reserve = GUINT32_FROM_LE (0x00100000);
5808         header->nt.pe_stack_commit = GUINT32_FROM_LE (0x00001000);
5809         header->nt.pe_heap_reserve = GUINT32_FROM_LE (0x00100000);
5810         header->nt.pe_heap_commit = GUINT32_FROM_LE (0x00001000);
5811         header->nt.pe_loader_flags = GUINT32_FROM_LE (0);
5812         header->nt.pe_data_dir_count = GUINT32_FROM_LE (16);
5813
5814         /* fill data directory entries */
5815
5816         header->datadir.pe_resource_table.size = GUINT32_FROM_LE (assembly->sections [MONO_SECTION_RSRC].size);
5817         header->datadir.pe_resource_table.rva = GUINT32_FROM_LE (assembly->sections [MONO_SECTION_RSRC].rva);
5818
5819         header->datadir.pe_reloc_table.size = GUINT32_FROM_LE (assembly->sections [MONO_SECTION_RELOC].size);
5820         header->datadir.pe_reloc_table.rva = GUINT32_FROM_LE (assembly->sections [MONO_SECTION_RELOC].rva);
5821
5822         header->datadir.pe_cli_header.size = GUINT32_FROM_LE (72);
5823         header->datadir.pe_cli_header.rva = GUINT32_FROM_LE (assembly->text_rva + assembly->cli_header_offset);
5824         header->datadir.pe_iat.size = GUINT32_FROM_LE (8);
5825         header->datadir.pe_iat.rva = GUINT32_FROM_LE (assembly->text_rva + assembly->iat_offset);
5826         /* patch entrypoint name */
5827         if (assemblyb->pekind == 1)
5828                 memcpy (assembly->code.data + assembly->imp_names_offset + 2, "_CorDllMain", 12);
5829         else
5830                 memcpy (assembly->code.data + assembly->imp_names_offset + 2, "_CorExeMain", 12);
5831         /* patch imported function RVA name */
5832         rva = (guint32*)(assembly->code.data + assembly->iat_offset);
5833         *rva = GUINT32_FROM_LE (assembly->text_rva + assembly->imp_names_offset);
5834
5835         /* the import table */
5836         header->datadir.pe_import_table.size = GUINT32_FROM_LE (79); /* FIXME: magic number? */
5837         header->datadir.pe_import_table.rva = GUINT32_FROM_LE (assembly->text_rva + assembly->idt_offset);
5838         /* patch imported dll RVA name and other entries in the dir */
5839         rva = (guint32*)(assembly->code.data + assembly->idt_offset + G_STRUCT_OFFSET (MonoIDT, name_rva));
5840         *rva = GUINT32_FROM_LE (assembly->text_rva + assembly->imp_names_offset + 14); /* 14 is hint+strlen+1 of func name */
5841         rva = (guint32*)(assembly->code.data + assembly->idt_offset + G_STRUCT_OFFSET (MonoIDT, import_address_table_rva));
5842         *rva = GUINT32_FROM_LE (assembly->text_rva + assembly->iat_offset);
5843         rva = (guint32*)(assembly->code.data + assembly->idt_offset + G_STRUCT_OFFSET (MonoIDT, import_lookup_table));
5844         *rva = GUINT32_FROM_LE (assembly->text_rva + assembly->ilt_offset);
5845
5846         p = (guchar*)(assembly->code.data + assembly->ilt_offset);
5847         value = (assembly->text_rva + assembly->imp_names_offset);
5848         *p++ = (value) & 0xff;
5849         *p++ = (value >> 8) & (0xff);
5850         *p++ = (value >> 16) & (0xff);
5851         *p++ = (value >> 24) & (0xff);
5852
5853         /* the CLI header info */
5854         cli_header = (MonoCLIHeader*)(assembly->code.data + assembly->cli_header_offset);
5855         cli_header->ch_size = GUINT32_FROM_LE (72);
5856         cli_header->ch_runtime_major = GUINT16_FROM_LE (2);
5857         cli_header->ch_runtime_minor = GUINT16_FROM_LE (5);
5858         cli_header->ch_flags = GUINT32_FROM_LE (assemblyb->pe_kind);
5859         if (assemblyb->entry_point) {
5860                 guint32 table_idx = 0;
5861                 if (!strcmp (assemblyb->entry_point->object.vtable->klass->name, "MethodBuilder")) {
5862                         MonoReflectionMethodBuilder *methodb = (MonoReflectionMethodBuilder*)assemblyb->entry_point;
5863                         table_idx = methodb->table_idx;
5864                 } else {
5865                         table_idx = GPOINTER_TO_UINT (g_hash_table_lookup (assembly->method_to_table_idx, assemblyb->entry_point->method));
5866                 }
5867                 cli_header->ch_entry_point = GUINT32_FROM_LE (table_idx | MONO_TOKEN_METHOD_DEF);
5868         } else {
5869                 cli_header->ch_entry_point = GUINT32_FROM_LE (0);
5870         }
5871         /* The embedded managed resources */
5872         text_offset = assembly->text_rva + assembly->code.index;
5873         cli_header->ch_resources.rva = GUINT32_FROM_LE (text_offset);
5874         cli_header->ch_resources.size = GUINT32_FROM_LE (assembly->resources.index);
5875         text_offset += assembly->resources.index;
5876         cli_header->ch_metadata.rva = GUINT32_FROM_LE (text_offset);
5877         cli_header->ch_metadata.size = GUINT32_FROM_LE (assembly->meta_size);
5878         text_offset += assembly->meta_size;
5879         if (assembly->strong_name_size) {
5880                 cli_header->ch_strong_name.rva = GUINT32_FROM_LE (text_offset);
5881                 cli_header->ch_strong_name.size = GUINT32_FROM_LE (assembly->strong_name_size);
5882                 text_offset += assembly->strong_name_size;
5883         }
5884
5885         /* write the section tables and section content */
5886         section = (MonoSectionTable*)(pefile->data + section_start);
5887         for (i = 0; i < MONO_SECTION_MAX; ++i) {
5888                 static const char section_names [][7] = {
5889                         ".text", ".rsrc", ".reloc"
5890                 };
5891                 if (!assembly->sections [i].size)
5892                         continue;
5893                 strcpy (section->st_name, section_names [i]);
5894                 /*g_print ("output section %s (%d), size: %d\n", section->st_name, i, assembly->sections [i].size);*/
5895                 section->st_virtual_address = GUINT32_FROM_LE (assembly->sections [i].rva);
5896                 section->st_virtual_size = GUINT32_FROM_LE (assembly->sections [i].size);
5897                 section->st_raw_data_size = GUINT32_FROM_LE (GUINT32_TO_LE (section->st_virtual_size) + (FILE_ALIGN - 1));
5898                 section->st_raw_data_size &= GUINT32_FROM_LE (~(FILE_ALIGN - 1));
5899                 section->st_raw_data_ptr = GUINT32_FROM_LE (assembly->sections [i].offset);
5900                 section->st_flags = GUINT32_FROM_LE (assembly->sections [i].attrs);
5901                 section ++;
5902         }
5903         
5904         checked_write_file (file, pefile->data, pefile->index);
5905         
5906         mono_dynamic_stream_reset (pefile);
5907         
5908         for (i = 0; i < MONO_SECTION_MAX; ++i) {
5909                 if (!assembly->sections [i].size)
5910                         continue;
5911                 
5912                 if (SetFilePointer (file, assembly->sections [i].offset, NULL, FILE_BEGIN) == INVALID_SET_FILE_POINTER)
5913                         g_error ("SetFilePointer returned %d\n", GetLastError ());
5914                 
5915                 switch (i) {
5916                 case MONO_SECTION_TEXT:
5917                         /* patch entry point */
5918                         p = (guchar*)(assembly->code.data + 2);
5919                         value = (virtual_base + assembly->text_rva + assembly->iat_offset);
5920                         *p++ = (value) & 0xff;
5921                         *p++ = (value >> 8) & 0xff;
5922                         *p++ = (value >> 16) & 0xff;
5923                         *p++ = (value >> 24) & 0xff;
5924                 
5925                         checked_write_file (file, assembly->code.data, assembly->code.index);
5926                         checked_write_file (file, assembly->resources.data, assembly->resources.index);
5927                         checked_write_file (file, assembly->image.raw_metadata, assembly->meta_size);
5928                         checked_write_file (file, assembly->strong_name, assembly->strong_name_size);
5929                                 
5930
5931                         g_free (assembly->image.raw_metadata);
5932                         break;
5933                 case MONO_SECTION_RELOC: {
5934                         struct {
5935                                 guint32 page_rva;
5936                                 guint32 block_size;
5937                                 guint16 type_and_offset;
5938                                 guint16 term;
5939                         } reloc;
5940                         
5941                         g_assert (sizeof (reloc) == 12);
5942                         
5943                         reloc.page_rva = GUINT32_FROM_LE (assembly->text_rva);
5944                         reloc.block_size = GUINT32_FROM_LE (12);
5945                         
5946                         /* 
5947                          * the entrypoint is always at the start of the text section 
5948                          * 3 is IMAGE_REL_BASED_HIGHLOW
5949                          * 2 is patch_size_rva - text_rva
5950                          */
5951                         reloc.type_and_offset = GUINT16_FROM_LE ((3 << 12) + (2));
5952                         reloc.term = 0;
5953                         
5954                         checked_write_file (file, &reloc, sizeof (reloc));
5955                         
5956                         break;
5957                 }
5958                 case MONO_SECTION_RSRC:
5959                         if (assembly->win32_res) {
5960
5961                                 /* Fixup the offsets in the IMAGE_RESOURCE_DATA_ENTRY structures */
5962                                 fixup_resource_directory (assembly->win32_res, assembly->win32_res, assembly->sections [i].rva);
5963                                 checked_write_file (file, assembly->win32_res, assembly->win32_res_size);
5964                         }
5965                         break;
5966                 default:
5967                         g_assert_not_reached ();
5968                 }
5969         }
5970         
5971         /* check that the file is properly padded */
5972         if (SetFilePointer (file, file_offset, NULL, FILE_BEGIN) == INVALID_SET_FILE_POINTER)
5973                 g_error ("SetFilePointer returned %d\n", GetLastError ());
5974         if (! SetEndOfFile (file))
5975                 g_error ("SetEndOfFile returned %d\n", GetLastError ());
5976         
5977         mono_dynamic_stream_reset (&assembly->code);
5978         mono_dynamic_stream_reset (&assembly->us);
5979         mono_dynamic_stream_reset (&assembly->blob);
5980         mono_dynamic_stream_reset (&assembly->guid);
5981         mono_dynamic_stream_reset (&assembly->sheap);
5982
5983         g_hash_table_foreach (assembly->blob_cache, (GHFunc)g_free, NULL);
5984         g_hash_table_destroy (assembly->blob_cache);
5985         assembly->blob_cache = NULL;
5986 }
5987
5988 #else /* DISABLE_REFLECTION_EMIT_SAVE */
5989
5990 void
5991 mono_image_create_pefile (MonoReflectionModuleBuilder *mb, HANDLE file)
5992 {
5993         g_assert_not_reached ();
5994 }
5995
5996 #endif /* DISABLE_REFLECTION_EMIT_SAVE */
5997
5998 #ifndef DISABLE_REFLECTION_EMIT
5999
6000 MonoReflectionModule *
6001 mono_image_load_module_dynamic (MonoReflectionAssemblyBuilder *ab, MonoString *fileName)
6002 {
6003         char *name;
6004         MonoImage *image;
6005         MonoImageOpenStatus status;
6006         MonoDynamicAssembly *assembly;
6007         guint32 module_count;
6008         MonoImage **new_modules;
6009         gboolean *new_modules_loaded;
6010         
6011         name = mono_string_to_utf8 (fileName);
6012
6013         image = mono_image_open (name, &status);
6014         if (!image) {
6015                 MonoException *exc;
6016                 if (status == MONO_IMAGE_ERROR_ERRNO)
6017                         exc = mono_get_exception_file_not_found (fileName);
6018                 else
6019                         exc = mono_get_exception_bad_image_format (name);
6020                 g_free (name);
6021                 mono_raise_exception (exc);
6022         }
6023
6024         g_free (name);
6025
6026         assembly = ab->dynamic_assembly;
6027         image->assembly = (MonoAssembly*)assembly;
6028
6029         module_count = image->assembly->image->module_count;
6030         new_modules = g_new0 (MonoImage *, module_count + 1);
6031         new_modules_loaded = g_new0 (gboolean, module_count + 1);
6032
6033         if (image->assembly->image->modules)
6034                 memcpy (new_modules, image->assembly->image->modules, module_count * sizeof (MonoImage *));
6035         if (image->assembly->image->modules_loaded)
6036                 memcpy (new_modules_loaded, image->assembly->image->modules_loaded, module_count * sizeof (gboolean));
6037         new_modules [module_count] = image;
6038         new_modules_loaded [module_count] = TRUE;
6039         mono_image_addref (image);
6040
6041         g_free (image->assembly->image->modules);
6042         image->assembly->image->modules = new_modules;
6043         image->assembly->image->modules_loaded = new_modules_loaded;
6044         image->assembly->image->module_count ++;
6045
6046         mono_assembly_load_references (image, &status);
6047         if (status) {
6048                 mono_image_close (image);
6049                 mono_raise_exception (mono_get_exception_file_not_found (fileName));
6050         }
6051
6052         return mono_module_get_object (mono_domain_get (), image);
6053 }
6054
6055 #endif /* DISABLE_REFLECTION_EMIT */
6056
6057 /*
6058  * We need to return always the same object for MethodInfo, FieldInfo etc..
6059  * but we need to consider the reflected type.
6060  * type uses a different hash, since it uses custom hash/equal functions.
6061  */
6062
6063 typedef struct {
6064         gpointer item;
6065         MonoClass *refclass;
6066 } ReflectedEntry;
6067
6068 static gboolean
6069 reflected_equal (gconstpointer a, gconstpointer b) {
6070         const ReflectedEntry *ea = a;
6071         const ReflectedEntry *eb = b;
6072
6073         return (ea->item == eb->item) && (ea->refclass == eb->refclass);
6074 }
6075
6076 static guint
6077 reflected_hash (gconstpointer a) {
6078         const ReflectedEntry *ea = a;
6079         return mono_aligned_addr_hash (ea->item);
6080 }
6081
6082 #define CHECK_OBJECT(t,p,k)     \
6083         do {    \
6084                 t _obj; \
6085                 ReflectedEntry e;       \
6086                 e.item = (p);   \
6087                 e.refclass = (k);       \
6088                 mono_domain_lock (domain);      \
6089                 if (!domain->refobject_hash)    \
6090                         domain->refobject_hash = mono_g_hash_table_new_type (reflected_hash, reflected_equal, MONO_HASH_VALUE_GC);      \
6091                 if ((_obj = mono_g_hash_table_lookup (domain->refobject_hash, &e))) {   \
6092                         mono_domain_unlock (domain);    \
6093                         return _obj;    \
6094                 }       \
6095         mono_domain_unlock (domain); \
6096         } while (0)
6097
6098 #ifdef HAVE_BOEHM_GC
6099 /* ReflectedEntry doesn't need to be GC tracked */
6100 #define ALLOC_REFENTRY g_new0 (ReflectedEntry, 1)
6101 #define FREE_REFENTRY(entry) g_free ((entry))
6102 #define REFENTRY_REQUIRES_CLEANUP
6103 #else
6104 #define ALLOC_REFENTRY mono_mempool_alloc (domain->mp, sizeof (ReflectedEntry))
6105 /* FIXME: */
6106 #define FREE_REFENTRY(entry)
6107 #endif
6108
6109 #define CACHE_OBJECT(t,p,o,k)   \
6110         do {    \
6111                 t _obj; \
6112         ReflectedEntry pe; \
6113         pe.item = (p); \
6114         pe.refclass = (k); \
6115         mono_domain_lock (domain); \
6116                 if (!domain->refobject_hash)    \
6117                         domain->refobject_hash = mono_g_hash_table_new_type (reflected_hash, reflected_equal, MONO_HASH_VALUE_GC);      \
6118         _obj = mono_g_hash_table_lookup (domain->refobject_hash, &pe); \
6119         if (!_obj) { \
6120                     ReflectedEntry *e = ALLOC_REFENTRY;         \
6121                     e->item = (p);      \
6122                     e->refclass = (k);  \
6123                     mono_g_hash_table_insert (domain->refobject_hash, e,o);     \
6124             _obj = o; \
6125         } \
6126                 mono_domain_unlock (domain);    \
6127         return _obj; \
6128         } while (0)
6129
6130 static void
6131 clear_cached_object (MonoDomain *domain, gpointer o, MonoClass *klass)
6132 {
6133         mono_domain_lock (domain);
6134         if (domain->refobject_hash) {
6135         ReflectedEntry pe;
6136                 gpointer orig_pe, orig_value;
6137
6138                 pe.item = o;
6139                 pe.refclass = klass;
6140                 if (mono_g_hash_table_lookup_extended (domain->refobject_hash, &pe, &orig_pe, &orig_value)) {
6141                         mono_g_hash_table_remove (domain->refobject_hash, &pe);
6142                         FREE_REFENTRY (orig_pe);
6143                 }
6144         }
6145         mono_domain_unlock (domain);
6146 }
6147
6148 #ifdef REFENTRY_REQUIRES_CLEANUP
6149 static void
6150 cleanup_refobject_hash (gpointer key, gpointer value, gpointer user_data)
6151 {
6152         FREE_REFENTRY (key);
6153 }
6154 #endif
6155
6156 void
6157 mono_reflection_cleanup_domain (MonoDomain *domain)
6158 {
6159         if (domain->refobject_hash) {
6160 /*let's avoid scanning the whole hashtable if not needed*/
6161 #ifdef REFENTRY_REQUIRES_CLEANUP
6162                 mono_g_hash_table_foreach (domain->refobject_hash, cleanup_refobject_hash, NULL);
6163 #endif
6164                 mono_g_hash_table_destroy (domain->refobject_hash);
6165                 domain->refobject_hash = NULL;
6166         }
6167 }
6168
6169 #ifndef DISABLE_REFLECTION_EMIT
6170 static gpointer
6171 register_assembly (MonoDomain *domain, MonoReflectionAssembly *res, MonoAssembly *assembly)
6172 {
6173         CACHE_OBJECT (MonoReflectionAssembly *, assembly, res, NULL);
6174 }
6175
6176 static gpointer
6177 register_module (MonoDomain *domain, MonoReflectionModuleBuilder *res, MonoDynamicImage *module)
6178 {
6179         CACHE_OBJECT (MonoReflectionModuleBuilder *, module, res, NULL);
6180 }
6181
6182 void
6183 mono_image_module_basic_init (MonoReflectionModuleBuilder *moduleb)
6184 {
6185         MonoDynamicImage *image = moduleb->dynamic_image;
6186         MonoReflectionAssemblyBuilder *ab = moduleb->assemblyb;
6187         if (!image) {
6188                 MonoError error;
6189                 int module_count;
6190                 MonoImage **new_modules;
6191                 MonoImage *ass;
6192                 char *name, *fqname;
6193                 /*
6194                  * FIXME: we already created an image in mono_image_basic_init (), but
6195                  * we don't know which module it belongs to, since that is only 
6196                  * determined at assembly save time.
6197                  */
6198                 /*image = (MonoDynamicImage*)ab->dynamic_assembly->assembly.image; */
6199                 name = mono_string_to_utf8 (ab->name);
6200                 fqname = mono_string_to_utf8_checked (moduleb->module.fqname, &error);
6201                 if (!mono_error_ok (&error)) {
6202                         g_free (name);
6203                         mono_error_raise_exception (&error);
6204                 }
6205                 image = create_dynamic_mono_image (ab->dynamic_assembly, name, fqname);
6206
6207                 moduleb->module.image = &image->image;
6208                 moduleb->dynamic_image = image;
6209                 register_module (mono_object_domain (moduleb), moduleb, image);
6210
6211                 /* register the module with the assembly */
6212                 ass = ab->dynamic_assembly->assembly.image;
6213                 module_count = ass->module_count;
6214                 new_modules = g_new0 (MonoImage *, module_count + 1);
6215
6216                 if (ass->modules)
6217                         memcpy (new_modules, ass->modules, module_count * sizeof (MonoImage *));
6218                 new_modules [module_count] = &image->image;
6219                 mono_image_addref (&image->image);
6220
6221                 g_free (ass->modules);
6222                 ass->modules = new_modules;
6223                 ass->module_count ++;
6224         }
6225 }
6226
6227 void
6228 mono_image_set_wrappers_type (MonoReflectionModuleBuilder *moduleb, MonoReflectionType *type)
6229 {
6230         MonoDynamicImage *image = moduleb->dynamic_image;
6231
6232         g_assert (type->type);
6233         image->wrappers_type = mono_class_from_mono_type (type->type);
6234 }
6235
6236 #endif
6237
6238 /*
6239  * mono_assembly_get_object:
6240  * @domain: an app domain
6241  * @assembly: an assembly
6242  *
6243  * Return an System.Reflection.Assembly object representing the MonoAssembly @assembly.
6244  */
6245 MonoReflectionAssembly*
6246 mono_assembly_get_object (MonoDomain *domain, MonoAssembly *assembly)
6247 {
6248         static MonoClass *assembly_type;
6249         MonoReflectionAssembly *res;
6250         
6251         CHECK_OBJECT (MonoReflectionAssembly *, assembly, NULL);
6252         if (!assembly_type) {
6253                 MonoClass *class = mono_class_from_name (mono_defaults.corlib, "System.Reflection", "MonoAssembly");
6254                 if (class == NULL)
6255                         class = mono_class_from_name (mono_defaults.corlib, "System.Reflection", "Assembly");
6256                 g_assert (class);
6257                 assembly_type = class;
6258         }
6259         res = (MonoReflectionAssembly *)mono_object_new (domain, assembly_type);
6260         res->assembly = assembly;
6261
6262         CACHE_OBJECT (MonoReflectionAssembly *, assembly, res, NULL);
6263 }
6264
6265
6266
6267 MonoReflectionModule*   
6268 mono_module_get_object   (MonoDomain *domain, MonoImage *image)
6269 {
6270         static MonoClass *module_type;
6271         MonoReflectionModule *res;
6272         char* basename;
6273         
6274         CHECK_OBJECT (MonoReflectionModule *, image, NULL);
6275         if (!module_type) {
6276                 MonoClass *class = mono_class_from_name (mono_defaults.corlib, "System.Reflection", "MonoModule");
6277                 if (class == NULL)
6278                         class = mono_class_from_name (mono_defaults.corlib, "System.Reflection", "Module");
6279                 g_assert (class);
6280                 module_type = class;
6281         }
6282         res = (MonoReflectionModule *)mono_object_new (domain, module_type);
6283
6284         res->image = image;
6285         MONO_OBJECT_SETREF (res, assembly, (MonoReflectionAssembly *) mono_assembly_get_object(domain, image->assembly));
6286
6287         MONO_OBJECT_SETREF (res, fqname, mono_string_new (domain, image->name));
6288         basename = g_path_get_basename (image->name);
6289         MONO_OBJECT_SETREF (res, name, mono_string_new (domain, basename));
6290         MONO_OBJECT_SETREF (res, scopename, mono_string_new (domain, image->module_name));
6291         
6292         g_free (basename);
6293
6294         if (image->assembly->image == image) {
6295                 res->token = mono_metadata_make_token (MONO_TABLE_MODULE, 1);
6296         } else {
6297                 int i;
6298                 res->token = 0;
6299                 if (image->assembly->image->modules) {
6300                         for (i = 0; i < image->assembly->image->module_count; i++) {
6301                                 if (image->assembly->image->modules [i] == image)
6302                                         res->token = mono_metadata_make_token (MONO_TABLE_MODULEREF, i + 1);
6303                         }
6304                         g_assert (res->token);
6305                 }
6306         }
6307
6308         CACHE_OBJECT (MonoReflectionModule *, image, res, NULL);
6309 }
6310
6311 MonoReflectionModule*   
6312 mono_module_file_get_object (MonoDomain *domain, MonoImage *image, int table_index)
6313 {
6314         static MonoClass *module_type;
6315         MonoReflectionModule *res;
6316         MonoTableInfo *table;
6317         guint32 cols [MONO_FILE_SIZE];
6318         const char *name;
6319         guint32 i, name_idx;
6320         const char *val;
6321         
6322         if (!module_type) {
6323                 MonoClass *class = mono_class_from_name (mono_defaults.corlib, "System.Reflection", "MonoModule");
6324                 if (class == NULL)
6325                         class = mono_class_from_name (mono_defaults.corlib, "System.Reflection", "Module");
6326                 g_assert (class);
6327                 module_type = class;
6328         }
6329         res = (MonoReflectionModule *)mono_object_new (domain, module_type);
6330
6331         table = &image->tables [MONO_TABLE_FILE];
6332         g_assert (table_index < table->rows);
6333         mono_metadata_decode_row (table, table_index, cols, MONO_FILE_SIZE);
6334
6335         res->image = NULL;
6336         MONO_OBJECT_SETREF (res, assembly, (MonoReflectionAssembly *) mono_assembly_get_object(domain, image->assembly));
6337         name = mono_metadata_string_heap (image, cols [MONO_FILE_NAME]);
6338
6339         /* Check whenever the row has a corresponding row in the moduleref table */
6340         table = &image->tables [MONO_TABLE_MODULEREF];
6341         for (i = 0; i < table->rows; ++i) {
6342                 name_idx = mono_metadata_decode_row_col (table, i, MONO_MODULEREF_NAME);
6343                 val = mono_metadata_string_heap (image, name_idx);
6344                 if (strcmp (val, name) == 0)
6345                         res->image = image->modules [i];
6346         }
6347
6348         MONO_OBJECT_SETREF (res, fqname, mono_string_new (domain, name));
6349         MONO_OBJECT_SETREF (res, name, mono_string_new (domain, name));
6350         MONO_OBJECT_SETREF (res, scopename, mono_string_new (domain, name));
6351         res->is_resource = cols [MONO_FILE_FLAGS] && FILE_CONTAINS_NO_METADATA;
6352         res->token = mono_metadata_make_token (MONO_TABLE_FILE, table_index + 1);
6353
6354         return res;
6355 }
6356
6357 static gboolean
6358 verify_safe_for_managed_space (MonoType *type)
6359 {
6360         switch (type->type) {
6361 #ifdef DEBUG_HARDER
6362         case MONO_TYPE_ARRAY:
6363                 return verify_safe_for_managed_space (&type->data.array->eklass->byval_arg);
6364         case MONO_TYPE_PTR:
6365                 return verify_safe_for_managed_space (type->data.type);
6366         case MONO_TYPE_SZARRAY:
6367                 return verify_safe_for_managed_space (&type->data.klass->byval_arg);
6368         case MONO_TYPE_GENERICINST: {
6369                 MonoGenericInst *inst = type->data.generic_class->inst;
6370                 int i;
6371                 if (!inst->is_open)
6372                         break;
6373                 for (i = 0; i < inst->type_argc; ++i)
6374                         if (!verify_safe_for_managed_space (inst->type_argv [i]))
6375                                 return FALSE;
6376                 return TRUE;
6377         }
6378 #endif
6379         case MONO_TYPE_VAR:
6380         case MONO_TYPE_MVAR:
6381                 return TRUE;
6382         default:
6383                 return TRUE;
6384         }
6385 }
6386
6387 static MonoType*
6388 mono_type_normalize (MonoType *type)
6389 {
6390         int i;
6391         MonoGenericClass *gclass;
6392         MonoGenericInst *ginst;
6393         MonoClass *gtd;
6394         MonoGenericContainer *gcontainer;
6395         MonoType **argv = NULL;
6396         gboolean is_denorm_gtd = TRUE, requires_rebind = FALSE;
6397
6398         if (type->type != MONO_TYPE_GENERICINST)
6399                 return type;
6400
6401         gclass = type->data.generic_class;
6402         ginst = gclass->context.class_inst;
6403         if (!ginst->is_open)
6404                 return type;
6405
6406         gtd = gclass->container_class;
6407         gcontainer = gtd->generic_container;
6408         argv = g_newa (MonoType*, ginst->type_argc);
6409
6410         for (i = 0; i < ginst->type_argc; ++i) {
6411                 MonoType *t = ginst->type_argv [i], *norm;
6412                 if (t->type != MONO_TYPE_VAR || t->data.generic_param->num != i || t->data.generic_param->owner != gcontainer)
6413                         is_denorm_gtd = FALSE;
6414                 norm = mono_type_normalize (t);
6415                 argv [i] = norm;
6416                 if (norm != t)
6417                         requires_rebind = TRUE;
6418         }
6419
6420         if (is_denorm_gtd)
6421                 return type->byref == gtd->byval_arg.byref ? &gtd->byval_arg : &gtd->this_arg;
6422
6423         if (requires_rebind) {
6424                 MonoClass *klass = mono_class_bind_generic_parameters (gtd, ginst->type_argc, argv, gclass->is_dynamic);
6425                 return type->byref == klass->byval_arg.byref ? &klass->byval_arg : &klass->this_arg;
6426         }
6427
6428         return type;
6429 }
6430 /*
6431  * mono_type_get_object:
6432  * @domain: an app domain
6433  * @type: a type
6434  *
6435  * Return an System.MonoType object representing the type @type.
6436  */
6437 MonoReflectionType*
6438 mono_type_get_object (MonoDomain *domain, MonoType *type)
6439 {
6440         MonoType *norm_type;
6441         MonoReflectionType *res;
6442         MonoClass *klass = mono_class_from_mono_type (type);
6443
6444         /*we must avoid using @type as it might have come
6445          * from a mono_metadata_type_dup and the caller
6446          * expects that is can be freed.
6447          * Using the right type from 
6448          */
6449         type = klass->byval_arg.byref == type->byref ? &klass->byval_arg : &klass->this_arg;
6450
6451         /* void is very common */
6452         if (type->type == MONO_TYPE_VOID && domain->typeof_void)
6453                 return (MonoReflectionType*)domain->typeof_void;
6454
6455         /*
6456          * If the vtable of the given class was already created, we can use
6457          * the MonoType from there and avoid all locking and hash table lookups.
6458          * 
6459          * We cannot do this for TypeBuilders as mono_reflection_create_runtime_class expects
6460          * that the resulting object is different.   
6461          */
6462         if (type == &klass->byval_arg && !image_is_dynamic (klass->image)) {
6463                 MonoVTable *vtable = mono_class_try_get_vtable (domain, klass);
6464                 if (vtable && vtable->type)
6465                         return vtable->type;
6466         }
6467
6468         mono_loader_lock (); /*FIXME mono_class_init and mono_class_vtable acquire it*/
6469         mono_domain_lock (domain);
6470         if (!domain->type_hash)
6471                 domain->type_hash = mono_g_hash_table_new_type ((GHashFunc)mono_metadata_type_hash, 
6472                                 (GCompareFunc)mono_metadata_type_equal, MONO_HASH_VALUE_GC);
6473         if ((res = mono_g_hash_table_lookup (domain->type_hash, type))) {
6474                 mono_domain_unlock (domain);
6475                 mono_loader_unlock ();
6476                 return res;
6477         }
6478
6479         /*Types must be normalized so a generic instance of the GTD get's the same inner type.
6480          * For example in: Foo<A,B>; Bar<A> : Foo<A, Bar<A>>
6481          * The second Bar will be encoded a generic instance of Bar with <A> as parameter.
6482          * On all other places, Bar<A> will be encoded as the GTD itself. This is an implementation
6483          * artifact of how generics are encoded and should be transparent to managed code so we
6484          * need to weed out this diference when retrieving managed System.Type objects.
6485          */
6486         norm_type = mono_type_normalize (type);
6487         if (norm_type != type) {
6488                 res = mono_type_get_object (domain, norm_type);
6489                 mono_g_hash_table_insert (domain->type_hash, type, res);
6490                 mono_domain_unlock (domain);
6491                 mono_loader_unlock ();
6492                 return res;
6493         }
6494
6495         /* This MonoGenericClass hack is no longer necessary. Let's leave it here until we finish with the 2-stage type-builder setup.*/
6496         if ((type->type == MONO_TYPE_GENERICINST) && type->data.generic_class->is_dynamic && !type->data.generic_class->container_class->wastypebuilder)
6497                 g_assert (0);
6498
6499         if (!verify_safe_for_managed_space (type)) {
6500                 mono_domain_unlock (domain);
6501                 mono_loader_unlock ();
6502                 mono_raise_exception (mono_get_exception_invalid_operation ("This type cannot be propagated to managed space"));
6503         }
6504
6505         if (mono_class_get_ref_info (klass) && !klass->wastypebuilder) {
6506                 gboolean is_type_done = TRUE;
6507                 /* Generic parameters have reflection_info set but they are not finished together with their enclosing type.
6508                  * We must ensure that once a type is finished we don't return a GenericTypeParameterBuilder.
6509                  * We can't simply close the types as this will interfere with other parts of the generics machinery.
6510                 */
6511                 if (klass->byval_arg.type == MONO_TYPE_MVAR || klass->byval_arg.type == MONO_TYPE_VAR) {
6512                         MonoGenericParam *gparam = klass->byval_arg.data.generic_param;
6513
6514                         if (gparam->owner && gparam->owner->is_method) {
6515                                 MonoMethod *method = gparam->owner->owner.method;
6516                                 if (method && mono_class_get_generic_type_definition (method->klass)->wastypebuilder)
6517                                         is_type_done = FALSE;
6518                         } else if (gparam->owner && !gparam->owner->is_method) {
6519                                 MonoClass *klass = gparam->owner->owner.klass;
6520                                 if (klass && mono_class_get_generic_type_definition (klass)->wastypebuilder)
6521                                         is_type_done = FALSE;
6522                         }
6523                 } 
6524
6525                 /* g_assert_not_reached (); */
6526                 /* should this be considered an error condition? */
6527                 if (is_type_done && !type->byref) {
6528                         mono_domain_unlock (domain);
6529                         mono_loader_unlock ();
6530                         return mono_class_get_ref_info (klass);
6531                 }
6532         }
6533         /* This is stored in vtables/JITted code so it has to be pinned */
6534         res = (MonoReflectionType *)mono_object_new_pinned (domain, mono_defaults.monotype_class);
6535         res->type = type;
6536         mono_g_hash_table_insert (domain->type_hash, type, res);
6537
6538         if (type->type == MONO_TYPE_VOID)
6539                 domain->typeof_void = (MonoObject*)res;
6540
6541         mono_domain_unlock (domain);
6542         mono_loader_unlock ();
6543         return res;
6544 }
6545
6546 /*
6547  * mono_method_get_object:
6548  * @domain: an app domain
6549  * @method: a method
6550  * @refclass: the reflected type (can be NULL)
6551  *
6552  * Return an System.Reflection.MonoMethod object representing the method @method.
6553  */
6554 MonoReflectionMethod*
6555 mono_method_get_object (MonoDomain *domain, MonoMethod *method, MonoClass *refclass)
6556 {
6557         /*
6558          * We use the same C representation for methods and constructors, but the type 
6559          * name in C# is different.
6560          */
6561         static MonoClass *System_Reflection_MonoMethod = NULL;
6562         static MonoClass *System_Reflection_MonoCMethod = NULL;
6563         static MonoClass *System_Reflection_MonoGenericMethod = NULL;
6564         static MonoClass *System_Reflection_MonoGenericCMethod = NULL;
6565         MonoClass *klass;
6566         MonoReflectionMethod *ret;
6567
6568         if (method->is_inflated) {
6569                 MonoReflectionGenericMethod *gret;
6570
6571                 refclass = method->klass;
6572                 CHECK_OBJECT (MonoReflectionMethod *, method, refclass);
6573                 if ((*method->name == '.') && (!strcmp (method->name, ".ctor") || !strcmp (method->name, ".cctor"))) {
6574                         if (!System_Reflection_MonoGenericCMethod)
6575                                 System_Reflection_MonoGenericCMethod = mono_class_from_name (mono_defaults.corlib, "System.Reflection", "MonoGenericCMethod");
6576                         klass = System_Reflection_MonoGenericCMethod;
6577                 } else {
6578                         if (!System_Reflection_MonoGenericMethod)
6579                                 System_Reflection_MonoGenericMethod = mono_class_from_name (mono_defaults.corlib, "System.Reflection", "MonoGenericMethod");
6580                         klass = System_Reflection_MonoGenericMethod;
6581                 }
6582                 gret = (MonoReflectionGenericMethod*)mono_object_new (domain, klass);
6583                 gret->method.method = method;
6584                 MONO_OBJECT_SETREF (gret, method.name, mono_string_new (domain, method->name));
6585                 MONO_OBJECT_SETREF (gret, method.reftype, mono_type_get_object (domain, &refclass->byval_arg));
6586                 CACHE_OBJECT (MonoReflectionMethod *, method, (MonoReflectionMethod*)gret, refclass);
6587         }
6588
6589         if (!refclass)
6590                 refclass = method->klass;
6591
6592         CHECK_OBJECT (MonoReflectionMethod *, method, refclass);
6593         if (*method->name == '.' && (strcmp (method->name, ".ctor") == 0 || strcmp (method->name, ".cctor") == 0)) {
6594                 if (!System_Reflection_MonoCMethod)
6595                         System_Reflection_MonoCMethod = mono_class_from_name (mono_defaults.corlib, "System.Reflection", "MonoCMethod");
6596                 klass = System_Reflection_MonoCMethod;
6597         }
6598         else {
6599                 if (!System_Reflection_MonoMethod)
6600                         System_Reflection_MonoMethod = mono_class_from_name (mono_defaults.corlib, "System.Reflection", "MonoMethod");
6601                 klass = System_Reflection_MonoMethod;
6602         }
6603         ret = (MonoReflectionMethod*)mono_object_new (domain, klass);
6604         ret->method = method;
6605         MONO_OBJECT_SETREF (ret, reftype, mono_type_get_object (domain, &refclass->byval_arg));
6606         CACHE_OBJECT (MonoReflectionMethod *, method, ret, refclass);
6607 }
6608
6609 /*
6610  * mono_method_clear_object:
6611  *
6612  *   Clear the cached reflection objects for the dynamic method METHOD.
6613  */
6614 void
6615 mono_method_clear_object (MonoDomain *domain, MonoMethod *method)
6616 {
6617         MonoClass *klass;
6618         g_assert (method_is_dynamic (method));
6619
6620         klass = method->klass;
6621         while (klass) {
6622                 clear_cached_object (domain, method, klass);
6623                 klass = klass->parent;
6624         }
6625         /* Added by mono_param_get_objects () */
6626         clear_cached_object (domain, &(method->signature), NULL);
6627         klass = method->klass;
6628         while (klass) {
6629                 clear_cached_object (domain, &(method->signature), klass);
6630                 klass = klass->parent;
6631         }
6632 }
6633
6634 /*
6635  * mono_field_get_object:
6636  * @domain: an app domain
6637  * @klass: a type
6638  * @field: a field
6639  *
6640  * Return an System.Reflection.MonoField object representing the field @field
6641  * in class @klass.
6642  */
6643 MonoReflectionField*
6644 mono_field_get_object (MonoDomain *domain, MonoClass *klass, MonoClassField *field)
6645 {
6646         MonoReflectionField *res;
6647         static MonoClass *monofield_klass;
6648
6649         CHECK_OBJECT (MonoReflectionField *, field, klass);
6650         if (!monofield_klass)
6651                 monofield_klass = mono_class_from_name (mono_defaults.corlib, "System.Reflection", "MonoField");
6652         res = (MonoReflectionField *)mono_object_new (domain, monofield_klass);
6653         res->klass = klass;
6654         res->field = field;
6655         MONO_OBJECT_SETREF (res, name, mono_string_new (domain, mono_field_get_name (field)));
6656
6657         if (is_field_on_inst (field)) {
6658                 res->attrs = get_field_on_inst_generic_type (field)->attrs;
6659                 MONO_OBJECT_SETREF (res, type, mono_type_get_object (domain, field->type));
6660         } else {
6661                 if (field->type)
6662                         MONO_OBJECT_SETREF (res, type, mono_type_get_object (domain, field->type));
6663                 res->attrs = mono_field_get_flags (field);
6664         }
6665         CACHE_OBJECT (MonoReflectionField *, field, res, klass);
6666 }
6667
6668 /*
6669  * mono_property_get_object:
6670  * @domain: an app domain
6671  * @klass: a type
6672  * @property: a property
6673  *
6674  * Return an System.Reflection.MonoProperty object representing the property @property
6675  * in class @klass.
6676  */
6677 MonoReflectionProperty*
6678 mono_property_get_object (MonoDomain *domain, MonoClass *klass, MonoProperty *property)
6679 {
6680         MonoReflectionProperty *res;
6681         static MonoClass *monoproperty_klass;
6682
6683         CHECK_OBJECT (MonoReflectionProperty *, property, klass);
6684         if (!monoproperty_klass)
6685                 monoproperty_klass = mono_class_from_name (mono_defaults.corlib, "System.Reflection", "MonoProperty");
6686         res = (MonoReflectionProperty *)mono_object_new (domain, monoproperty_klass);
6687         res->klass = klass;
6688         res->property = property;
6689         CACHE_OBJECT (MonoReflectionProperty *, property, res, klass);
6690 }
6691
6692 /*
6693  * mono_event_get_object:
6694  * @domain: an app domain
6695  * @klass: a type
6696  * @event: a event
6697  *
6698  * Return an System.Reflection.MonoEvent object representing the event @event
6699  * in class @klass.
6700  */
6701 MonoReflectionEvent*
6702 mono_event_get_object (MonoDomain *domain, MonoClass *klass, MonoEvent *event)
6703 {
6704         MonoReflectionEvent *res;
6705         MonoReflectionMonoEvent *mono_event;
6706         static MonoClass *monoevent_klass;
6707
6708         CHECK_OBJECT (MonoReflectionEvent *, event, klass);
6709         if (!monoevent_klass)
6710                 monoevent_klass = mono_class_from_name (mono_defaults.corlib, "System.Reflection", "MonoEvent");
6711         mono_event = (MonoReflectionMonoEvent *)mono_object_new (domain, monoevent_klass);
6712         mono_event->klass = klass;
6713         mono_event->event = event;
6714         res = (MonoReflectionEvent*)mono_event;
6715         CACHE_OBJECT (MonoReflectionEvent *, event, res, klass);
6716 }
6717
6718 /**
6719  * mono_get_reflection_missing_object:
6720  * @domain: Domain where the object lives
6721  *
6722  * Returns the System.Reflection.Missing.Value singleton object
6723  * (of type System.Reflection.Missing).
6724  *
6725  * Used as the value for ParameterInfo.DefaultValue when Optional
6726  * is present
6727  */
6728 static MonoObject *
6729 mono_get_reflection_missing_object (MonoDomain *domain)
6730 {
6731         MonoObject *obj;
6732         static MonoClassField *missing_value_field = NULL;
6733         
6734         if (!missing_value_field) {
6735                 MonoClass *missing_klass;
6736                 missing_klass = mono_class_from_name (mono_defaults.corlib, "System.Reflection", "Missing");
6737                 mono_class_init (missing_klass);
6738                 missing_value_field = mono_class_get_field_from_name (missing_klass, "Value");
6739                 g_assert (missing_value_field);
6740         }
6741         obj = mono_field_get_value_object (domain, missing_value_field, NULL); 
6742         g_assert (obj);
6743         return obj;
6744 }
6745
6746 static MonoObject*
6747 get_dbnull (MonoDomain *domain, MonoObject **dbnull)
6748 {
6749         if (!*dbnull)
6750                 *dbnull = mono_get_dbnull_object (domain);
6751         return *dbnull;
6752 }
6753
6754 static MonoObject*
6755 get_reflection_missing (MonoDomain *domain, MonoObject **reflection_missing)
6756 {
6757         if (!*reflection_missing)
6758                 *reflection_missing = mono_get_reflection_missing_object (domain);
6759         return *reflection_missing;
6760 }
6761
6762 /*
6763  * mono_param_get_objects:
6764  * @domain: an app domain
6765  * @method: a method
6766  *
6767  * Return an System.Reflection.ParameterInfo array object representing the parameters
6768  * in the method @method.
6769  */
6770 MonoArray*
6771 mono_param_get_objects_internal (MonoDomain *domain, MonoMethod *method, MonoClass *refclass)
6772 {
6773         static MonoClass *System_Reflection_ParameterInfo;
6774         static MonoClass *System_Reflection_ParameterInfo_array;
6775         MonoError error;
6776         MonoArray *res = NULL;
6777         MonoReflectionMethod *member = NULL;
6778         MonoReflectionParameter *param = NULL;
6779         char **names, **blobs = NULL;
6780         guint32 *types = NULL;
6781         MonoType *type = NULL;
6782         MonoObject *dbnull = NULL;
6783         MonoObject *missing = NULL;
6784         MonoMarshalSpec **mspecs;
6785         MonoMethodSignature *sig;
6786         MonoVTable *pinfo_vtable;
6787         int i;
6788
6789         if (!System_Reflection_ParameterInfo_array) {
6790                 MonoClass *klass;
6791
6792                 klass = mono_class_from_name (mono_defaults.corlib, "System.Reflection", "MonoParameterInfo");
6793                 if (!klass)
6794                         klass = mono_class_from_name (mono_defaults.corlib, "System.Reflection", "ParameterInfo");
6795
6796                 mono_memory_barrier ();
6797                 System_Reflection_ParameterInfo = klass; 
6798
6799         
6800                 klass = mono_array_class_get (klass, 1);
6801                 mono_memory_barrier ();
6802                 System_Reflection_ParameterInfo_array = klass;
6803         }
6804
6805         sig = mono_method_signature_checked (method, &error);
6806         if (!mono_error_ok (&error))
6807                 mono_error_raise_exception (&error);
6808
6809         if (!sig->param_count)
6810                 return mono_array_new_specific (mono_class_vtable (domain, System_Reflection_ParameterInfo_array), 0);
6811
6812         /* Note: the cache is based on the address of the signature into the method
6813          * since we already cache MethodInfos with the method as keys.
6814          */
6815         CHECK_OBJECT (MonoArray*, &(method->signature), refclass);
6816
6817         member = mono_method_get_object (domain, method, refclass);
6818         names = g_new (char *, sig->param_count);
6819         mono_method_get_param_names (method, (const char **) names);
6820
6821         mspecs = g_new (MonoMarshalSpec*, sig->param_count + 1);
6822         mono_method_get_marshal_info (method, mspecs);
6823
6824         res = mono_array_new_specific (mono_class_vtable (domain, System_Reflection_ParameterInfo_array), sig->param_count);
6825         pinfo_vtable = mono_class_vtable (domain, System_Reflection_ParameterInfo);
6826         for (i = 0; i < sig->param_count; ++i) {
6827                 param = (MonoReflectionParameter *)mono_object_new_specific (pinfo_vtable);
6828                 MONO_OBJECT_SETREF (param, ClassImpl, mono_type_get_object (domain, sig->params [i]));
6829                 MONO_OBJECT_SETREF (param, MemberImpl, (MonoObject*)member);
6830                 MONO_OBJECT_SETREF (param, NameImpl, mono_string_new (domain, names [i]));
6831                 param->PositionImpl = i;
6832                 param->AttrsImpl = sig->params [i]->attrs;
6833
6834                 if (!(param->AttrsImpl & PARAM_ATTRIBUTE_HAS_DEFAULT)) {
6835                         if (param->AttrsImpl & PARAM_ATTRIBUTE_OPTIONAL)
6836                                 MONO_OBJECT_SETREF (param, DefaultValueImpl, get_reflection_missing (domain, &missing));
6837                         else
6838                                 MONO_OBJECT_SETREF (param, DefaultValueImpl, get_dbnull (domain, &dbnull));
6839                 } else {
6840
6841                         if (!blobs) {
6842                                 blobs = g_new0 (char *, sig->param_count);
6843                                 types = g_new0 (guint32, sig->param_count);
6844                                 get_default_param_value_blobs (method, blobs, types); 
6845                         }
6846
6847                         /* Build MonoType for the type from the Constant Table */
6848                         if (!type)
6849                                 type = g_new0 (MonoType, 1);
6850                         type->type = types [i];
6851                         type->data.klass = NULL;
6852                         if (types [i] == MONO_TYPE_CLASS)
6853                                 type->data.klass = mono_defaults.object_class;
6854                         else if ((sig->params [i]->type == MONO_TYPE_VALUETYPE) && sig->params [i]->data.klass->enumtype) {
6855                                 /* For enums, types [i] contains the base type */
6856
6857                                         type->type = MONO_TYPE_VALUETYPE;
6858                                         type->data.klass = mono_class_from_mono_type (sig->params [i]);
6859                         } else
6860                                 type->data.klass = mono_class_from_mono_type (type);
6861
6862                         MONO_OBJECT_SETREF (param, DefaultValueImpl, mono_get_object_from_blob (domain, type, blobs [i]));
6863
6864                         /* Type in the Constant table is MONO_TYPE_CLASS for nulls */
6865                         if (types [i] != MONO_TYPE_CLASS && !param->DefaultValueImpl) {
6866                                 if (param->AttrsImpl & PARAM_ATTRIBUTE_OPTIONAL)
6867                                         MONO_OBJECT_SETREF (param, DefaultValueImpl, get_reflection_missing (domain, &missing));
6868                                 else
6869                                         MONO_OBJECT_SETREF (param, DefaultValueImpl, get_dbnull (domain, &dbnull));
6870                         }
6871                         
6872                 }
6873
6874                 if (mspecs [i + 1])
6875                         MONO_OBJECT_SETREF (param, MarshalAsImpl, (MonoObject*)mono_reflection_marshal_as_attribute_from_marshal_spec (domain, method->klass, mspecs [i + 1]));
6876                 
6877                 mono_array_setref (res, i, param);
6878         }
6879         g_free (names);
6880         g_free (blobs);
6881         g_free (types);
6882         g_free (type);
6883
6884         for (i = mono_method_signature (method)->param_count; i >= 0; i--)
6885                 if (mspecs [i])
6886                         mono_metadata_free_marshal_spec (mspecs [i]);
6887         g_free (mspecs);
6888         
6889         CACHE_OBJECT (MonoArray *, &(method->signature), res, refclass);
6890 }
6891
6892 MonoArray*
6893 mono_param_get_objects (MonoDomain *domain, MonoMethod *method)
6894 {
6895         return mono_param_get_objects_internal (domain, method, NULL);
6896 }
6897
6898 /*
6899  * mono_method_body_get_object:
6900  * @domain: an app domain
6901  * @method: a method
6902  *
6903  * Return an System.Reflection.MethodBody object representing the method @method.
6904  */
6905 MonoReflectionMethodBody*
6906 mono_method_body_get_object (MonoDomain *domain, MonoMethod *method)
6907 {
6908         static MonoClass *System_Reflection_MethodBody = NULL;
6909         static MonoClass *System_Reflection_LocalVariableInfo = NULL;
6910         static MonoClass *System_Reflection_ExceptionHandlingClause = NULL;
6911         MonoReflectionMethodBody *ret;
6912         MonoMethodHeader *header;
6913         MonoImage *image;
6914         guint32 method_rva, local_var_sig_token;
6915     char *ptr;
6916         unsigned char format, flags;
6917         int i;
6918
6919         /* for compatibility with .net */
6920     if (method_is_dynamic (method))
6921         mono_raise_exception (mono_get_exception_invalid_operation (NULL));
6922
6923         if (!System_Reflection_MethodBody)
6924                 System_Reflection_MethodBody = mono_class_from_name (mono_defaults.corlib, "System.Reflection", "MethodBody");
6925         if (!System_Reflection_LocalVariableInfo)
6926                 System_Reflection_LocalVariableInfo = mono_class_from_name (mono_defaults.corlib, "System.Reflection", "LocalVariableInfo");
6927         if (!System_Reflection_ExceptionHandlingClause)
6928                 System_Reflection_ExceptionHandlingClause = mono_class_from_name (mono_defaults.corlib, "System.Reflection", "ExceptionHandlingClause");
6929
6930         CHECK_OBJECT (MonoReflectionMethodBody *, method, NULL);
6931
6932         if ((method->flags & METHOD_ATTRIBUTE_PINVOKE_IMPL) ||
6933                 (method->flags & METHOD_ATTRIBUTE_ABSTRACT) ||
6934             (method->iflags & METHOD_IMPL_ATTRIBUTE_INTERNAL_CALL) ||
6935             (method->iflags & METHOD_IMPL_ATTRIBUTE_RUNTIME))
6936                 return NULL;
6937
6938         image = method->klass->image;
6939         header = mono_method_get_header (method);
6940
6941         if (!image_is_dynamic (image)) {
6942                 /* Obtain local vars signature token */
6943                 method_rva = mono_metadata_decode_row_col (&image->tables [MONO_TABLE_METHOD], mono_metadata_token_index (method->token) - 1, MONO_METHOD_RVA);
6944                 ptr = mono_image_rva_map (image, method_rva);
6945                 flags = *(const unsigned char *) ptr;
6946                 format = flags & METHOD_HEADER_FORMAT_MASK;
6947                 switch (format){
6948                 case METHOD_HEADER_TINY_FORMAT:
6949                         local_var_sig_token = 0;
6950                         break;
6951                 case METHOD_HEADER_FAT_FORMAT:
6952                         ptr += 2;
6953                         ptr += 2;
6954                         ptr += 4;
6955                         local_var_sig_token = read32 (ptr);
6956                         break;
6957                 default:
6958                         g_assert_not_reached ();
6959                 }
6960         } else
6961                 local_var_sig_token = 0; //FIXME
6962
6963         ret = (MonoReflectionMethodBody*)mono_object_new (domain, System_Reflection_MethodBody);
6964
6965         ret->init_locals = header->init_locals;
6966         ret->max_stack = header->max_stack;
6967         ret->local_var_sig_token = local_var_sig_token;
6968         MONO_OBJECT_SETREF (ret, il, mono_array_new_cached (domain, mono_defaults.byte_class, header->code_size));
6969         memcpy (mono_array_addr (ret->il, guint8, 0), header->code, header->code_size);
6970
6971         /* Locals */
6972         MONO_OBJECT_SETREF (ret, locals, mono_array_new_cached (domain, System_Reflection_LocalVariableInfo, header->num_locals));
6973         for (i = 0; i < header->num_locals; ++i) {
6974                 MonoReflectionLocalVariableInfo *info = (MonoReflectionLocalVariableInfo*)mono_object_new (domain, System_Reflection_LocalVariableInfo);
6975                 MONO_OBJECT_SETREF (info, local_type, mono_type_get_object (domain, header->locals [i]));
6976                 info->is_pinned = header->locals [i]->pinned;
6977                 info->local_index = i;
6978                 mono_array_setref (ret->locals, i, info);
6979         }
6980
6981         /* Exceptions */
6982         MONO_OBJECT_SETREF (ret, clauses, mono_array_new_cached (domain, System_Reflection_ExceptionHandlingClause, header->num_clauses));
6983         for (i = 0; i < header->num_clauses; ++i) {
6984                 MonoReflectionExceptionHandlingClause *info = (MonoReflectionExceptionHandlingClause*)mono_object_new (domain, System_Reflection_ExceptionHandlingClause);
6985                 MonoExceptionClause *clause = &header->clauses [i];
6986
6987                 info->flags = clause->flags;
6988                 info->try_offset = clause->try_offset;
6989                 info->try_length = clause->try_len;
6990                 info->handler_offset = clause->handler_offset;
6991                 info->handler_length = clause->handler_len;
6992                 if (clause->flags == MONO_EXCEPTION_CLAUSE_FILTER)
6993                         info->filter_offset = clause->data.filter_offset;
6994                 else if (clause->data.catch_class)
6995                         MONO_OBJECT_SETREF (info, catch_type, mono_type_get_object (mono_domain_get (), &clause->data.catch_class->byval_arg));
6996
6997                 mono_array_setref (ret->clauses, i, info);
6998         }
6999
7000         mono_metadata_free_mh (header);
7001         CACHE_OBJECT (MonoReflectionMethodBody *, method, ret, NULL);
7002         return ret;
7003 }
7004
7005 /**
7006  * mono_get_dbnull_object:
7007  * @domain: Domain where the object lives
7008  *
7009  * Returns the System.DBNull.Value singleton object
7010  *
7011  * Used as the value for ParameterInfo.DefaultValue 
7012  */
7013 MonoObject *
7014 mono_get_dbnull_object (MonoDomain *domain)
7015 {
7016         MonoObject *obj;
7017         static MonoClassField *dbnull_value_field = NULL;
7018         
7019         if (!dbnull_value_field) {
7020                 MonoClass *dbnull_klass;
7021                 dbnull_klass = mono_class_from_name (mono_defaults.corlib, "System", "DBNull");
7022                 mono_class_init (dbnull_klass);
7023                 dbnull_value_field = mono_class_get_field_from_name (dbnull_klass, "Value");
7024                 g_assert (dbnull_value_field);
7025         }
7026         obj = mono_field_get_value_object (domain, dbnull_value_field, NULL); 
7027         g_assert (obj);
7028         return obj;
7029 }
7030
7031 static void
7032 get_default_param_value_blobs (MonoMethod *method, char **blobs, guint32 *types)
7033 {
7034         guint32 param_index, i, lastp, crow = 0;
7035         guint32 param_cols [MONO_PARAM_SIZE], const_cols [MONO_CONSTANT_SIZE];
7036         gint32 idx;
7037
7038         MonoClass *klass = method->klass;
7039         MonoImage *image = klass->image;
7040         MonoMethodSignature *methodsig = mono_method_signature (method);
7041
7042         MonoTableInfo *constt;
7043         MonoTableInfo *methodt;
7044         MonoTableInfo *paramt;
7045
7046         if (!methodsig->param_count)
7047                 return;
7048
7049         mono_class_init (klass);
7050
7051         if (image_is_dynamic (klass->image)) {
7052                 MonoReflectionMethodAux *aux;
7053                 if (method->is_inflated)
7054                         method = ((MonoMethodInflated*)method)->declaring;
7055                 aux = g_hash_table_lookup (((MonoDynamicImage*)method->klass->image)->method_aux_hash, method);
7056                 if (aux && aux->param_defaults) {
7057                         memcpy (blobs, &(aux->param_defaults [1]), methodsig->param_count * sizeof (char*));
7058                         memcpy (types, &(aux->param_default_types [1]), methodsig->param_count * sizeof (guint32));
7059                 }
7060                 return;
7061         }
7062
7063         methodt = &klass->image->tables [MONO_TABLE_METHOD];
7064         paramt = &klass->image->tables [MONO_TABLE_PARAM];
7065         constt = &image->tables [MONO_TABLE_CONSTANT];
7066
7067         idx = mono_method_get_index (method) - 1;
7068         g_assert (idx != -1);
7069
7070         param_index = mono_metadata_decode_row_col (methodt, idx, MONO_METHOD_PARAMLIST);
7071         if (idx + 1 < methodt->rows)
7072                 lastp = mono_metadata_decode_row_col (methodt, idx + 1, MONO_METHOD_PARAMLIST);
7073         else
7074                 lastp = paramt->rows + 1;
7075
7076         for (i = param_index; i < lastp; ++i) {
7077                 guint32 paramseq;
7078
7079                 mono_metadata_decode_row (paramt, i - 1, param_cols, MONO_PARAM_SIZE);
7080                 paramseq = param_cols [MONO_PARAM_SEQUENCE];
7081
7082                 if (!(param_cols [MONO_PARAM_FLAGS] & PARAM_ATTRIBUTE_HAS_DEFAULT))
7083                         continue;
7084
7085                 crow = mono_metadata_get_constant_index (image, MONO_TOKEN_PARAM_DEF | i, crow + 1);
7086                 if (!crow) {
7087                         continue;
7088                 }
7089         
7090                 mono_metadata_decode_row (constt, crow - 1, const_cols, MONO_CONSTANT_SIZE);
7091                 blobs [paramseq - 1] = (gpointer) mono_metadata_blob_heap (image, const_cols [MONO_CONSTANT_VALUE]);
7092                 types [paramseq - 1] = const_cols [MONO_CONSTANT_TYPE];
7093         }
7094
7095         return;
7096 }
7097
7098 MonoObject *
7099 mono_get_object_from_blob (MonoDomain *domain, MonoType *type, const char *blob)
7100 {
7101         void *retval;
7102         MonoClass *klass;
7103         MonoObject *object;
7104         MonoType *basetype = type;
7105
7106         if (!blob)
7107                 return NULL;
7108         
7109         klass = mono_class_from_mono_type (type);
7110         if (klass->valuetype) {
7111                 object = mono_object_new (domain, klass);
7112                 retval = ((gchar *) object + sizeof (MonoObject));
7113                 if (klass->enumtype)
7114                         basetype = mono_class_enum_basetype (klass);
7115         } else {
7116                 retval = &object;
7117         }
7118                         
7119         if (!mono_get_constant_value_from_blob (domain, basetype->type,  blob, retval))
7120                 return object;
7121         else
7122                 return NULL;
7123 }
7124
7125 static int
7126 assembly_name_to_aname (MonoAssemblyName *assembly, char *p) {
7127         int found_sep;
7128         char *s;
7129         gboolean quoted = FALSE;
7130
7131         memset (assembly, 0, sizeof (MonoAssemblyName));
7132         assembly->culture = "";
7133         memset (assembly->public_key_token, 0, MONO_PUBLIC_KEY_TOKEN_LENGTH);
7134
7135         if (*p == '"') {
7136                 quoted = TRUE;
7137                 p++;
7138         }
7139         assembly->name = p;
7140         while (*p && (isalnum (*p) || *p == '.' || *p == '-' || *p == '_' || *p == '$' || *p == '@' || g_ascii_isspace (*p)))
7141                 p++;
7142         if (quoted) {
7143                 if (*p != '"')
7144                         return 1;
7145                 *p = 0;
7146                 p++;
7147         }
7148         if (*p != ',')
7149                 return 1;
7150         *p = 0;
7151         /* Remove trailing whitespace */
7152         s = p - 1;
7153         while (*s && g_ascii_isspace (*s))
7154                 *s-- = 0;
7155         p ++;
7156         while (g_ascii_isspace (*p))
7157                 p++;
7158         while (*p) {
7159                 if (*p == 'V' && g_ascii_strncasecmp (p, "Version=", 8) == 0) {
7160                         p += 8;
7161                         assembly->major = strtoul (p, &s, 10);
7162                         if (s == p || *s != '.')
7163                                 return 1;
7164                         p = ++s;
7165                         assembly->minor = strtoul (p, &s, 10);
7166                         if (s == p || *s != '.')
7167                                 return 1;
7168                         p = ++s;
7169                         assembly->build = strtoul (p, &s, 10);
7170                         if (s == p || *s != '.')
7171                                 return 1;
7172                         p = ++s;
7173                         assembly->revision = strtoul (p, &s, 10);
7174                         if (s == p)
7175                                 return 1;
7176                         p = s;
7177                 } else if (*p == 'C' && g_ascii_strncasecmp (p, "Culture=", 8) == 0) {
7178                         p += 8;
7179                         if (g_ascii_strncasecmp (p, "neutral", 7) == 0) {
7180                                 assembly->culture = "";
7181                                 p += 7;
7182                         } else {
7183                                 assembly->culture = p;
7184                                 while (*p && *p != ',') {
7185                                         p++;
7186                                 }
7187                         }
7188                 } else if (*p == 'P' && g_ascii_strncasecmp (p, "PublicKeyToken=", 15) == 0) {
7189                         p += 15;
7190                         if (strncmp (p, "null", 4) == 0) {
7191                                 p += 4;
7192                         } else {
7193                                 int len;
7194                                 gchar *start = p;
7195                                 while (*p && *p != ',') {
7196                                         p++;
7197                                 }
7198                                 len = (p - start + 1);
7199                                 if (len > MONO_PUBLIC_KEY_TOKEN_LENGTH)
7200                                         len = MONO_PUBLIC_KEY_TOKEN_LENGTH;
7201                                 g_strlcpy ((char*)assembly->public_key_token, start, len);
7202                         }
7203                 } else {
7204                         while (*p && *p != ',')
7205                                 p++;
7206                 }
7207                 found_sep = 0;
7208                 while (g_ascii_isspace (*p) || *p == ',') {
7209                         *p++ = 0;
7210                         found_sep = 1;
7211                         continue;
7212                 }
7213                 /* failed */
7214                 if (!found_sep)
7215                         return 1;
7216         }
7217
7218         return 0;
7219 }
7220
7221 /*
7222  * mono_reflection_parse_type:
7223  * @name: type name
7224  *
7225  * Parse a type name as accepted by the GetType () method and output the info
7226  * extracted in the info structure.
7227  * the name param will be mangled, so, make a copy before passing it to this function.
7228  * The fields in info will be valid until the memory pointed to by name is valid.
7229  *
7230  * See also mono_type_get_name () below.
7231  *
7232  * Returns: 0 on parse error.
7233  */
7234 static int
7235 _mono_reflection_parse_type (char *name, char **endptr, gboolean is_recursed,
7236                              MonoTypeNameParse *info)
7237 {
7238         char *start, *p, *w, *last_point, *startn;
7239         int in_modifiers = 0;
7240         int isbyref = 0, rank = 0;
7241
7242         start = p = w = name;
7243
7244         //FIXME could we just zero the whole struct? memset (&info, 0, sizeof (MonoTypeNameParse))
7245         memset (&info->assembly, 0, sizeof (MonoAssemblyName));
7246         info->name = info->name_space = NULL;
7247         info->nested = NULL;
7248         info->modifiers = NULL;
7249         info->type_arguments = NULL;
7250
7251         /* last_point separates the namespace from the name */
7252         last_point = NULL;
7253         /* Skips spaces */
7254         while (*p == ' ') p++, start++, w++, name++;
7255
7256         while (*p) {
7257                 switch (*p) {
7258                 case '+':
7259                         *p = 0; /* NULL terminate the name */
7260                         startn = p + 1;
7261                         info->nested = g_list_append (info->nested, startn);
7262                         /* we have parsed the nesting namespace + name */
7263                         if (info->name)
7264                                 break;
7265                         if (last_point) {
7266                                 info->name_space = start;
7267                                 *last_point = 0;
7268                                 info->name = last_point + 1;
7269                         } else {
7270                                 info->name_space = (char *)"";
7271                                 info->name = start;
7272                         }
7273                         break;
7274                 case '.':
7275                         last_point = p;
7276                         break;
7277                 case '\\':
7278                         ++p;
7279                         break;
7280                 case '&':
7281                 case '*':
7282                 case '[':
7283                 case ',':
7284                 case ']':
7285                         in_modifiers = 1;
7286                         break;
7287                 default:
7288                         break;
7289                 }
7290                 if (in_modifiers)
7291                         break;
7292                 // *w++ = *p++;
7293                 p++;
7294         }
7295         
7296         if (!info->name) {
7297                 if (last_point) {
7298                         info->name_space = start;
7299                         *last_point = 0;
7300                         info->name = last_point + 1;
7301                 } else {
7302                         info->name_space = (char *)"";
7303                         info->name = start;
7304                 }
7305         }
7306         while (*p) {
7307                 switch (*p) {
7308                 case '&':
7309                         if (isbyref) /* only one level allowed by the spec */
7310                                 return 0;
7311                         isbyref = 1;
7312                         info->modifiers = g_list_append (info->modifiers, GUINT_TO_POINTER (0));
7313                         *p++ = 0;
7314                         break;
7315                 case '*':
7316                         info->modifiers = g_list_append (info->modifiers, GUINT_TO_POINTER (-1));
7317                         *p++ = 0;
7318                         break;
7319                 case '[':
7320                         //Decide if it's an array of a generic argument list
7321                         *p++ = 0;
7322
7323                         if (!*p) //XXX test
7324                                 return 0;
7325                         if (*p  == ',' || *p == '*' || *p == ']') { //array
7326                                 rank = 1;
7327                                 while (*p) {
7328                                         if (*p == ']')
7329                                                 break;
7330                                         if (*p == ',')
7331                                                 rank++;
7332                                         else if (*p == '*') /* '*' means unknown lower bound */
7333                                                 info->modifiers = g_list_append (info->modifiers, GUINT_TO_POINTER (-2));
7334                                         else
7335                                                 return 0;
7336                                         ++p;
7337                                 }
7338                                 if (*p++ != ']')
7339                                         return 0;
7340                                 info->modifiers = g_list_append (info->modifiers, GUINT_TO_POINTER (rank));
7341                         } else {
7342                                 if (rank) /* generic args after array spec*/ //XXX test
7343                                         return 0;
7344                                 info->type_arguments = g_ptr_array_new ();
7345                                 while (*p) {
7346                                         MonoTypeNameParse *subinfo = g_new0 (MonoTypeNameParse, 1);
7347                                         gboolean fqname = FALSE;
7348
7349                                         g_ptr_array_add (info->type_arguments, subinfo);
7350
7351                                         while (*p == ' ') p++;
7352                                         if (*p == '[') {
7353                                                 p++;
7354                                                 fqname = TRUE;
7355                                         }
7356
7357                                         if (!_mono_reflection_parse_type (p, &p, TRUE, subinfo))
7358                                                 return 0;
7359
7360                                         /*MS is lenient on [] delimited parameters that aren't fqn - and F# uses them.*/
7361                                         if (fqname && (*p != ']')) {
7362                                                 char *aname;
7363
7364                                                 if (*p != ',')
7365                                                         return 0;
7366                                                 *p++ = 0;
7367
7368                                                 aname = p;
7369                                                 while (*p && (*p != ']'))
7370                                                         p++;
7371
7372                                                 if (*p != ']')
7373                                                         return 0;
7374
7375                                                 *p++ = 0;
7376                                                 while (*aname) {
7377                                                         if (g_ascii_isspace (*aname)) {
7378                                                                 ++aname;
7379                                                                 continue;
7380                                                         }
7381                                                         break;
7382                                                 }
7383                                                 if (!*aname ||
7384                                                     !assembly_name_to_aname (&subinfo->assembly, aname))
7385                                                         return 0;
7386                                         } else if (fqname && (*p == ']')) {
7387                                                 *p++ = 0;
7388                                         }
7389                                         if (*p == ']') {
7390                                                 *p++ = 0;
7391                                                 break;
7392                                         } else if (!*p) {
7393                                                 return 0;
7394                                         }
7395                                         *p++ = 0;
7396                                 }
7397                         }
7398                         break;
7399                 case ']':
7400                         if (is_recursed)
7401                                 goto end;
7402                         return 0;
7403                 case ',':
7404                         if (is_recursed)
7405                                 goto end;
7406                         *p++ = 0;
7407                         while (*p) {
7408                                 if (g_ascii_isspace (*p)) {
7409                                         ++p;
7410                                         continue;
7411                                 }
7412                                 break;
7413                         }
7414                         if (!*p)
7415                                 return 0; /* missing assembly name */
7416                         if (!assembly_name_to_aname (&info->assembly, p))
7417                                 return 0;
7418                         break;
7419                 default:
7420                         return 0;
7421                 }
7422                 if (info->assembly.name)
7423                         break;
7424         }
7425         // *w = 0; /* terminate class name */
7426  end:
7427         if (!info->name || !*info->name)
7428                 return 0;
7429         if (endptr)
7430                 *endptr = p;
7431         /* add other consistency checks */
7432         return 1;
7433 }
7434
7435 int
7436 mono_reflection_parse_type (char *name, MonoTypeNameParse *info)
7437 {
7438         return _mono_reflection_parse_type (name, NULL, FALSE, info);
7439 }
7440
7441 static MonoType*
7442 _mono_reflection_get_type_from_info (MonoTypeNameParse *info, MonoImage *image, gboolean ignorecase)
7443 {
7444         gboolean type_resolve = FALSE;
7445         MonoType *type;
7446         MonoImage *rootimage = image;
7447
7448         if (info->assembly.name) {
7449                 MonoAssembly *assembly = mono_assembly_loaded (&info->assembly);
7450                 if (!assembly && image && image->assembly && mono_assembly_names_equal (&info->assembly, &image->assembly->aname))
7451                         /* 
7452                          * This could happen in the AOT compiler case when the search hook is not
7453                          * installed.
7454                          */
7455                         assembly = image->assembly;
7456                 if (!assembly) {
7457                         /* then we must load the assembly ourselve - see #60439 */
7458                         assembly = mono_assembly_load (&info->assembly, image->assembly->basedir, NULL);
7459                         if (!assembly)
7460                                 return NULL;
7461                 }
7462                 image = assembly->image;
7463         } else if (!image) {
7464                 image = mono_defaults.corlib;
7465         }
7466
7467         type = mono_reflection_get_type_with_rootimage (rootimage, image, info, ignorecase, &type_resolve);
7468         if (type == NULL && !info->assembly.name && image != mono_defaults.corlib) {
7469                 image = mono_defaults.corlib;
7470                 type = mono_reflection_get_type_with_rootimage (rootimage, image, info, ignorecase, &type_resolve);
7471         }
7472
7473         return type;
7474 }
7475
7476 static MonoType*
7477 mono_reflection_get_type_internal (MonoImage *rootimage, MonoImage* image, MonoTypeNameParse *info, gboolean ignorecase)
7478 {
7479         MonoClass *klass;
7480         GList *mod;
7481         int modval;
7482         gboolean bounded = FALSE;
7483         
7484         if (!image)
7485                 image = mono_defaults.corlib;
7486
7487         if (ignorecase) {
7488                 MonoError error;
7489                 klass = mono_class_from_name_case_checked (image, info->name_space, info->name, &error);
7490                 g_assert (mono_error_ok (&error)); /* FIXME Don't swallow the error */
7491         } else {
7492                 klass = mono_class_from_name (image, info->name_space, info->name);
7493         }
7494         if (!klass)
7495                 return NULL;
7496         for (mod = info->nested; mod; mod = mod->next) {
7497                 gpointer iter = NULL;
7498                 MonoClass *parent;
7499
7500                 parent = klass;
7501                 mono_class_init (parent);
7502
7503                 while ((klass = mono_class_get_nested_types (parent, &iter))) {
7504                         char *lastp;
7505                         char *nested_name, *nested_nspace;
7506                         gboolean match = TRUE;
7507
7508                         lastp = strrchr (mod->data, '.');
7509                         if (lastp) {
7510                                 /* Nested classes can have namespaces */
7511                                 int nspace_len;
7512
7513                                 nested_name = g_strdup (lastp + 1);
7514                                 nspace_len = lastp - (char*)mod->data;
7515                                 nested_nspace = g_malloc (nspace_len + 1);
7516                                 memcpy (nested_nspace, mod->data, nspace_len);
7517                                 nested_nspace [nspace_len] = '\0';
7518
7519                         } else {
7520                                 nested_name = mod->data;
7521                                 nested_nspace = NULL;
7522                         }
7523
7524                         if (nested_nspace) {
7525                                 if (ignorecase) {
7526                                         if (!(klass->name_space && mono_utf8_strcasecmp (klass->name_space, nested_nspace) == 0))
7527                                                 match = FALSE;
7528                                 } else {
7529                                         if (!(klass->name_space && strcmp (klass->name_space, nested_nspace) == 0))
7530                                                 match = FALSE;
7531                                 }
7532                         }
7533                         if (match) {
7534                                 if (ignorecase) {
7535                                         if (mono_utf8_strcasecmp (klass->name, nested_name) != 0)
7536                                                 match = FALSE;
7537                                 } else {
7538                                         if (strcmp (klass->name, nested_name) != 0)
7539                                                 match = FALSE;
7540                                 }
7541                         }
7542                         if (lastp) {
7543                                 g_free (nested_name);
7544                                 g_free (nested_nspace);
7545                         }
7546                         if (match)
7547                                 break;
7548                 }
7549
7550                 if (!klass)
7551                         break;
7552         }
7553         if (!klass)
7554                 return NULL;
7555
7556         if (info->type_arguments) {
7557                 MonoType **type_args = g_new0 (MonoType *, info->type_arguments->len);
7558                 MonoReflectionType *the_type;
7559                 MonoType *instance;
7560                 int i;
7561
7562                 for (i = 0; i < info->type_arguments->len; i++) {
7563                         MonoTypeNameParse *subinfo = g_ptr_array_index (info->type_arguments, i);
7564
7565                         type_args [i] = _mono_reflection_get_type_from_info (subinfo, rootimage, ignorecase);
7566                         if (!type_args [i]) {
7567                                 g_free (type_args);
7568                                 return NULL;
7569                         }
7570                 }
7571
7572                 the_type = mono_type_get_object (mono_domain_get (), &klass->byval_arg);
7573
7574                 instance = mono_reflection_bind_generic_parameters (
7575                         the_type, info->type_arguments->len, type_args);
7576
7577                 g_free (type_args);
7578                 if (!instance)
7579                         return NULL;
7580
7581                 klass = mono_class_from_mono_type (instance);
7582         }
7583
7584         for (mod = info->modifiers; mod; mod = mod->next) {
7585                 modval = GPOINTER_TO_UINT (mod->data);
7586                 if (!modval) { /* byref: must be last modifier */
7587                         return &klass->this_arg;
7588                 } else if (modval == -1) {
7589                         klass = mono_ptr_class_get (&klass->byval_arg);
7590                 } else if (modval == -2) {
7591                         bounded = TRUE;
7592                 } else { /* array rank */
7593                         klass = mono_bounded_array_class_get (klass, modval, bounded);
7594                 }
7595         }
7596
7597         return &klass->byval_arg;
7598 }
7599
7600 /*
7601  * mono_reflection_get_type:
7602  * @image: a metadata context
7603  * @info: type description structure
7604  * @ignorecase: flag for case-insensitive string compares
7605  * @type_resolve: whenever type resolve was already tried
7606  *
7607  * Build a MonoType from the type description in @info.
7608  * 
7609  */
7610
7611 MonoType*
7612 mono_reflection_get_type (MonoImage* image, MonoTypeNameParse *info, gboolean ignorecase, gboolean *type_resolve) {
7613         return mono_reflection_get_type_with_rootimage(image, image, info, ignorecase, type_resolve);
7614 }
7615
7616 static MonoType*
7617 mono_reflection_get_type_internal_dynamic (MonoImage *rootimage, MonoAssembly *assembly, MonoTypeNameParse *info, gboolean ignorecase)
7618 {
7619         MonoReflectionAssemblyBuilder *abuilder;
7620         MonoType *type;
7621         int i;
7622
7623         g_assert (assembly_is_dynamic (assembly));
7624         abuilder = (MonoReflectionAssemblyBuilder*)mono_assembly_get_object (((MonoDynamicAssembly*)assembly)->domain, assembly);
7625
7626         /* Enumerate all modules */
7627
7628         type = NULL;
7629         if (abuilder->modules) {
7630                 for (i = 0; i < mono_array_length (abuilder->modules); ++i) {
7631                         MonoReflectionModuleBuilder *mb = mono_array_get (abuilder->modules, MonoReflectionModuleBuilder*, i);
7632                         type = mono_reflection_get_type_internal (rootimage, &mb->dynamic_image->image, info, ignorecase);
7633                         if (type)
7634                                 break;
7635                 }
7636         }
7637
7638         if (!type && abuilder->loaded_modules) {
7639                 for (i = 0; i < mono_array_length (abuilder->loaded_modules); ++i) {
7640                         MonoReflectionModule *mod = mono_array_get (abuilder->loaded_modules, MonoReflectionModule*, i);
7641                         type = mono_reflection_get_type_internal (rootimage, mod->image, info, ignorecase);
7642                         if (type)
7643                                 break;
7644                 }
7645         }
7646
7647         return type;
7648 }
7649         
7650 MonoType*
7651 mono_reflection_get_type_with_rootimage (MonoImage *rootimage, MonoImage* image, MonoTypeNameParse *info, gboolean ignorecase, gboolean *type_resolve)
7652 {
7653         MonoType *type;
7654         MonoReflectionAssembly *assembly;
7655         GString *fullName;
7656         GList *mod;
7657
7658         if (image && image_is_dynamic (image))
7659                 type = mono_reflection_get_type_internal_dynamic (rootimage, image->assembly, info, ignorecase);
7660         else
7661                 type = mono_reflection_get_type_internal (rootimage, image, info, ignorecase);
7662         if (type)
7663                 return type;
7664         if (!mono_domain_has_type_resolve (mono_domain_get ()))
7665                 return NULL;
7666
7667         if (type_resolve) {
7668                 if (*type_resolve) 
7669                         return NULL;
7670                 else
7671                         *type_resolve = TRUE;
7672         }
7673         
7674         /* Reconstruct the type name */
7675         fullName = g_string_new ("");
7676         if (info->name_space && (info->name_space [0] != '\0'))
7677                 g_string_printf (fullName, "%s.%s", info->name_space, info->name);
7678         else
7679                 g_string_printf (fullName, "%s", info->name);
7680         for (mod = info->nested; mod; mod = mod->next)
7681                 g_string_append_printf (fullName, "+%s", (char*)mod->data);
7682
7683         assembly = mono_domain_try_type_resolve ( mono_domain_get (), fullName->str, NULL);
7684         if (assembly) {
7685                 if (assembly_is_dynamic (assembly->assembly))
7686                         type = mono_reflection_get_type_internal_dynamic (rootimage, assembly->assembly, info, ignorecase);
7687                 else
7688                         type = mono_reflection_get_type_internal (rootimage, assembly->assembly->image, 
7689                                                                                                           info, ignorecase);
7690         }
7691         g_string_free (fullName, TRUE);
7692         return type;
7693 }
7694
7695 void
7696 mono_reflection_free_type_info (MonoTypeNameParse *info)
7697 {
7698         g_list_free (info->modifiers);
7699         g_list_free (info->nested);
7700
7701         if (info->type_arguments) {
7702                 int i;
7703
7704                 for (i = 0; i < info->type_arguments->len; i++) {
7705                         MonoTypeNameParse *subinfo = g_ptr_array_index (info->type_arguments, i);
7706
7707                         mono_reflection_free_type_info (subinfo);
7708                         /*We free the subinfo since it is allocated by _mono_reflection_parse_type*/
7709                         g_free (subinfo);
7710                 }
7711
7712                 g_ptr_array_free (info->type_arguments, TRUE);
7713         }
7714 }
7715
7716 /*
7717  * mono_reflection_type_from_name:
7718  * @name: type name.
7719  * @image: a metadata context (can be NULL).
7720  *
7721  * Retrieves a MonoType from its @name. If the name is not fully qualified,
7722  * it defaults to get the type from @image or, if @image is NULL or loading
7723  * from it fails, uses corlib.
7724  * 
7725  */
7726 MonoType*
7727 mono_reflection_type_from_name (char *name, MonoImage *image)
7728 {
7729         MonoType *type = NULL;
7730         MonoTypeNameParse info;
7731         char *tmp;
7732
7733         /* Make a copy since parse_type modifies its argument */
7734         tmp = g_strdup (name);
7735         
7736         /*g_print ("requested type %s\n", str);*/
7737         if (mono_reflection_parse_type (tmp, &info)) {
7738                 type = _mono_reflection_get_type_from_info (&info, image, FALSE);
7739         }
7740
7741         g_free (tmp);
7742         mono_reflection_free_type_info (&info);
7743         return type;
7744 }
7745
7746 /*
7747  * mono_reflection_get_token:
7748  *
7749  *   Return the metadata token of OBJ which should be an object
7750  * representing a metadata element.
7751  */
7752 guint32
7753 mono_reflection_get_token (MonoObject *obj)
7754 {
7755         MonoClass *klass;
7756         guint32 token = 0;
7757
7758         klass = obj->vtable->klass;
7759
7760         if (strcmp (klass->name, "MethodBuilder") == 0) {
7761                 MonoReflectionMethodBuilder *mb = (MonoReflectionMethodBuilder *)obj;
7762
7763                 token = mb->table_idx | MONO_TOKEN_METHOD_DEF;
7764         } else if (strcmp (klass->name, "ConstructorBuilder") == 0) {
7765                 MonoReflectionCtorBuilder *mb = (MonoReflectionCtorBuilder *)obj;
7766
7767                 token = mb->table_idx | MONO_TOKEN_METHOD_DEF;
7768         } else if (strcmp (klass->name, "FieldBuilder") == 0) {
7769                 MonoReflectionFieldBuilder *fb = (MonoReflectionFieldBuilder *)obj;
7770
7771                 token = fb->table_idx | MONO_TOKEN_FIELD_DEF;
7772         } else if (strcmp (klass->name, "TypeBuilder") == 0) {
7773                 MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder *)obj;
7774                 token = tb->table_idx | MONO_TOKEN_TYPE_DEF;
7775         } else if (strcmp (klass->name, "MonoType") == 0) {
7776                 MonoType *type = mono_reflection_type_get_handle ((MonoReflectionType*)obj);
7777                 MonoClass *mc = mono_class_from_mono_type (type);
7778                 if (!mono_class_init (mc))
7779                         mono_raise_exception (mono_class_get_exception_for_failure (mc));
7780
7781                 token = mc->type_token;
7782         } else if (strcmp (klass->name, "MonoCMethod") == 0 ||
7783                    strcmp (klass->name, "MonoMethod") == 0 ||
7784                    strcmp (klass->name, "MonoGenericMethod") == 0 ||
7785                    strcmp (klass->name, "MonoGenericCMethod") == 0) {
7786                 MonoReflectionMethod *m = (MonoReflectionMethod *)obj;
7787                 if (m->method->is_inflated) {
7788                         MonoMethodInflated *inflated = (MonoMethodInflated *) m->method;
7789                         return inflated->declaring->token;
7790                 } else {
7791                         token = m->method->token;
7792                 }
7793         } else if (strcmp (klass->name, "MonoField") == 0) {
7794                 MonoReflectionField *f = (MonoReflectionField*)obj;
7795
7796                 if (is_field_on_inst (f->field)) {
7797                         MonoDynamicGenericClass *dgclass = (MonoDynamicGenericClass*)f->field->parent->generic_class;
7798
7799                         if (f->field >= dgclass->fields && f->field < dgclass->fields + dgclass->count_fields) {
7800                                 int field_index = f->field - dgclass->fields;
7801                                 MonoObject *obj;
7802
7803                                 g_assert (field_index >= 0 && field_index < dgclass->count_fields);
7804                                 obj = dgclass->field_objects [field_index];
7805                                 return mono_reflection_get_token (obj);
7806                         }
7807                 }
7808                 token = mono_class_get_field_token (f->field);
7809         } else if (strcmp (klass->name, "MonoProperty") == 0) {
7810                 MonoReflectionProperty *p = (MonoReflectionProperty*)obj;
7811
7812                 token = mono_class_get_property_token (p->property);
7813         } else if (strcmp (klass->name, "MonoEvent") == 0) {
7814                 MonoReflectionMonoEvent *p = (MonoReflectionMonoEvent*)obj;
7815
7816                 token = mono_class_get_event_token (p->event);
7817         } else if (strcmp (klass->name, "ParameterInfo") == 0 || strcmp (klass->name, "MonoParameterInfo") == 0) {
7818                 MonoReflectionParameter *p = (MonoReflectionParameter*)obj;
7819                 MonoClass *member_class = mono_object_class (p->MemberImpl);
7820                 g_assert (mono_class_is_reflection_method_or_constructor (member_class));
7821
7822                 token = mono_method_get_param_token (((MonoReflectionMethod*)p->MemberImpl)->method, p->PositionImpl);
7823         } else if (strcmp (klass->name, "Module") == 0 || strcmp (klass->name, "MonoModule") == 0) {
7824                 MonoReflectionModule *m = (MonoReflectionModule*)obj;
7825
7826                 token = m->token;
7827         } else if (strcmp (klass->name, "Assembly") == 0 || strcmp (klass->name, "MonoAssembly") == 0) {
7828                 token = mono_metadata_make_token (MONO_TABLE_ASSEMBLY, 1);
7829         } else {
7830                 gchar *msg = g_strdup_printf ("MetadataToken is not supported for type '%s.%s'", klass->name_space, klass->name);
7831                 MonoException *ex = mono_get_exception_not_implemented (msg);
7832                 g_free (msg);
7833                 mono_raise_exception (ex);
7834         }
7835
7836         return token;
7837 }
7838
7839 static MonoClass*
7840 load_cattr_enum_type (MonoImage *image, const char *p, const char **end, MonoError *error)
7841 {
7842         char *n;
7843         MonoType *t;
7844         int slen = mono_metadata_decode_value (p, &p);
7845
7846         mono_error_init (error);
7847
7848         n = g_memdup (p, slen + 1);
7849         n [slen] = 0;
7850         t = mono_reflection_type_from_name (n, image);
7851         if (!t) {
7852                 /* FIXME the error should come from mono_reflection_type_from_name as it will have type/assembly names split */
7853                 /* We don't free n, it's consumed by mono_error */
7854                 mono_error_set_type_load_name (error, n, NULL, "Could not load enum type %s while decoding custom attribute", n);
7855                 return NULL;
7856         }
7857         g_free (n);
7858         p += slen;
7859         *end = p;
7860         return mono_class_from_mono_type (t);
7861 }
7862
7863 static void*
7864 load_cattr_value (MonoImage *image, MonoType *t, const char *p, const char **end, MonoError *error)
7865 {
7866         int slen, type = t->type;
7867         MonoClass *tklass = t->data.klass;
7868
7869         mono_error_init (error);
7870
7871 handle_enum:
7872         switch (type) {
7873         case MONO_TYPE_U1:
7874         case MONO_TYPE_I1:
7875         case MONO_TYPE_BOOLEAN: {
7876                 MonoBoolean *bval = g_malloc (sizeof (MonoBoolean));
7877                 *bval = *p;
7878                 *end = p + 1;
7879                 return bval;
7880         }
7881         case MONO_TYPE_CHAR:
7882         case MONO_TYPE_U2:
7883         case MONO_TYPE_I2: {
7884                 guint16 *val = g_malloc (sizeof (guint16));
7885                 *val = read16 (p);
7886                 *end = p + 2;
7887                 return val;
7888         }
7889 #if SIZEOF_VOID_P == 4
7890         case MONO_TYPE_U:
7891         case MONO_TYPE_I:
7892 #endif
7893         case MONO_TYPE_R4:
7894         case MONO_TYPE_U4:
7895         case MONO_TYPE_I4: {
7896                 guint32 *val = g_malloc (sizeof (guint32));
7897                 *val = read32 (p);
7898                 *end = p + 4;
7899                 return val;
7900         }
7901 #if SIZEOF_VOID_P == 8
7902         case MONO_TYPE_U: /* error out instead? this should probably not happen */
7903         case MONO_TYPE_I:
7904 #endif
7905         case MONO_TYPE_U8:
7906         case MONO_TYPE_I8: {
7907                 guint64 *val = g_malloc (sizeof (guint64));
7908                 *val = read64 (p);
7909                 *end = p + 8;
7910                 return val;
7911         }
7912         case MONO_TYPE_R8: {
7913                 double *val = g_malloc (sizeof (double));
7914                 readr8 (p, val);
7915                 *end = p + 8;
7916                 return val;
7917         }
7918         case MONO_TYPE_VALUETYPE:
7919                 if (t->data.klass->enumtype) {
7920                         type = mono_class_enum_basetype (t->data.klass)->type;
7921                         goto handle_enum;
7922                 } else {
7923                         MonoClass *k =  t->data.klass;
7924                         
7925                         if (mono_is_corlib_image (k->image) && strcmp (k->name_space, "System") == 0 && strcmp (k->name, "DateTime") == 0){
7926                                 guint64 *val = g_malloc (sizeof (guint64));
7927                                 *val = read64 (p);
7928                                 *end = p + 8;
7929                                 return val;
7930                         }
7931                 }
7932                 g_error ("generic valutype %s not handled in custom attr value decoding", t->data.klass->name);
7933                 break;
7934                 
7935         case MONO_TYPE_STRING:
7936                 if (*p == (char)0xFF) {
7937                         *end = p + 1;
7938                         return NULL;
7939                 }
7940                 slen = mono_metadata_decode_value (p, &p);
7941                 *end = p + slen;
7942                 return mono_string_new_len (mono_domain_get (), p, slen);
7943         case MONO_TYPE_CLASS: {
7944                 char *n;
7945                 MonoType *t;
7946                 if (*p == (char)0xFF) {
7947                         *end = p + 1;
7948                         return NULL;
7949                 }
7950 handle_type:
7951                 slen = mono_metadata_decode_value (p, &p);
7952                 n = g_memdup (p, slen + 1);
7953                 n [slen] = 0;
7954                 t = mono_reflection_type_from_name (n, image);
7955                 if (!t) {
7956                         /* FIXME the error should come from mono_reflection_type_from_name as it will have type/assembly names split */
7957                         /* We don't free n, it's consumed by mono_error */
7958                         mono_error_set_type_load_name (error, n, NULL, "Could not load type %s while decoding custom attribute", n);
7959                         return NULL;
7960                 }
7961                 g_free (n);
7962                 *end = p + slen;
7963                 return mono_type_get_object (mono_domain_get (), t);
7964         }
7965         case MONO_TYPE_OBJECT: {
7966                 char subt = *p++;
7967                 MonoObject *obj;
7968                 MonoClass *subc = NULL;
7969                 void *val;
7970
7971                 if (subt == 0x50) {
7972                         goto handle_type;
7973                 } else if (subt == 0x0E) {
7974                         type = MONO_TYPE_STRING;
7975                         goto handle_enum;
7976                 } else if (subt == 0x1D) {
7977                         MonoType simple_type = {{0}};
7978                         int etype = *p;
7979                         p ++;
7980
7981                         type = MONO_TYPE_SZARRAY;
7982                         if (etype == 0x50) {
7983                                 tklass = mono_defaults.systemtype_class;
7984                         } else if (etype == 0x55) {
7985                                 tklass = load_cattr_enum_type (image, p, &p, error);
7986                                 if (!mono_error_ok (error))
7987                                         return NULL;
7988                         } else {
7989                                 if (etype == 0x51)
7990                                         /* See Partition II, Appendix B3 */
7991                                         etype = MONO_TYPE_OBJECT;
7992                                 simple_type.type = etype;
7993                                 tklass = mono_class_from_mono_type (&simple_type);
7994                         }
7995                         goto handle_enum;
7996                 } else if (subt == 0x55) {
7997                         char *n;
7998                         MonoType *t;
7999                         slen = mono_metadata_decode_value (p, &p);
8000                         n = g_memdup (p, slen + 1);
8001                         n [slen] = 0;
8002                         t = mono_reflection_type_from_name (n, image);
8003                         if (!t) {
8004                                 /* FIXME the error should come from mono_reflection_type_from_name as it will have type/assembly names split */
8005                                 /* We don't free n, it's consumed by mono_error */
8006                                 mono_error_set_type_load_name (error, n, NULL, "Could not load type %s while decoding custom attribute", n);
8007                                 return NULL;
8008                         }
8009                         g_free (n);
8010                         p += slen;
8011                         subc = mono_class_from_mono_type (t);
8012                 } else if (subt >= MONO_TYPE_BOOLEAN && subt <= MONO_TYPE_R8) {
8013                         MonoType simple_type = {{0}};
8014                         simple_type.type = subt;
8015                         subc = mono_class_from_mono_type (&simple_type);
8016                 } else {
8017                         g_error ("Unknown type 0x%02x for object type encoding in custom attr", subt);
8018                 }
8019                 val = load_cattr_value (image, &subc->byval_arg, p, end, error);
8020                 obj = NULL;
8021                 if (mono_error_ok (error)) {
8022                         obj = mono_object_new (mono_domain_get (), subc);
8023                         g_assert (!subc->has_references);
8024                         mono_gc_memmove_atomic ((char*)obj + sizeof (MonoObject), val, mono_class_value_size (subc, NULL));
8025                 }
8026
8027                 g_free (val);
8028                 return obj;
8029         }
8030         case MONO_TYPE_SZARRAY: {
8031                 MonoArray *arr;
8032                 guint32 i, alen, basetype;
8033                 alen = read32 (p);
8034                 p += 4;
8035                 if (alen == 0xffffffff) {
8036                         *end = p;
8037                         return NULL;
8038                 }
8039                 arr = mono_array_new (mono_domain_get(), tklass, alen);
8040                 basetype = tklass->byval_arg.type;
8041                 if (basetype == MONO_TYPE_VALUETYPE && tklass->enumtype)
8042                         basetype = mono_class_enum_basetype (tklass)->type;
8043                 switch (basetype)
8044                 {
8045                         case MONO_TYPE_U1:
8046                         case MONO_TYPE_I1:
8047                         case MONO_TYPE_BOOLEAN:
8048                                 for (i = 0; i < alen; i++) {
8049                                         MonoBoolean val = *p++;
8050                                         mono_array_set (arr, MonoBoolean, i, val);
8051                                 }
8052                                 break;
8053                         case MONO_TYPE_CHAR:
8054                         case MONO_TYPE_U2:
8055                         case MONO_TYPE_I2:
8056                                 for (i = 0; i < alen; i++) {
8057                                         guint16 val = read16 (p);
8058                                         mono_array_set (arr, guint16, i, val);
8059                                         p += 2;
8060                                 }
8061                                 break;
8062                         case MONO_TYPE_R4:
8063                         case MONO_TYPE_U4:
8064                         case MONO_TYPE_I4:
8065                                 for (i = 0; i < alen; i++) {
8066                                         guint32 val = read32 (p);
8067                                         mono_array_set (arr, guint32, i, val);
8068                                         p += 4;
8069                                 }
8070                                 break;
8071                         case MONO_TYPE_R8:
8072                                 for (i = 0; i < alen; i++) {
8073                                         double val;
8074                                         readr8 (p, &val);
8075                                         mono_array_set (arr, double, i, val);
8076                                         p += 8;
8077                                 }
8078                                 break;
8079                         case MONO_TYPE_U8:
8080                         case MONO_TYPE_I8:
8081                                 for (i = 0; i < alen; i++) {
8082                                         guint64 val = read64 (p);
8083                                         mono_array_set (arr, guint64, i, val);
8084                                         p += 8;
8085                                 }
8086                                 break;
8087                         case MONO_TYPE_CLASS:
8088                         case MONO_TYPE_OBJECT:
8089                         case MONO_TYPE_STRING:
8090                         case MONO_TYPE_SZARRAY:
8091                                 for (i = 0; i < alen; i++) {
8092                                         MonoObject *item = load_cattr_value (image, &tklass->byval_arg, p, &p, error);
8093                                         if (!mono_error_ok (error))
8094                                                 return NULL;
8095                                         mono_array_setref (arr, i, item);
8096                                 }
8097                                 break;
8098                         default:
8099                                 g_error ("Type 0x%02x not handled in custom attr array decoding", basetype);
8100                 }
8101                 *end=p;
8102                 return arr;
8103         }
8104         default:
8105                 g_error ("Type 0x%02x not handled in custom attr value decoding", type);
8106         }
8107         return NULL;
8108 }
8109
8110 static MonoObject*
8111 create_cattr_typed_arg (MonoType *t, MonoObject *val)
8112 {
8113         static MonoClass *klass;
8114         static MonoMethod *ctor;
8115         MonoObject *retval;
8116         void *params [2], *unboxed;
8117
8118         if (!klass)
8119                 klass = mono_class_from_name (mono_defaults.corlib, "System.Reflection", "CustomAttributeTypedArgument");
8120         if (!ctor)
8121                 ctor = mono_class_get_method_from_name (klass, ".ctor", 2);
8122         
8123         params [0] = mono_type_get_object (mono_domain_get (), t);
8124         params [1] = val;
8125         retval = mono_object_new (mono_domain_get (), klass);
8126         unboxed = mono_object_unbox (retval);
8127         mono_runtime_invoke (ctor, unboxed, params, NULL);
8128
8129         return retval;
8130 }
8131
8132 static MonoObject*
8133 create_cattr_named_arg (void *minfo, MonoObject *typedarg)
8134 {
8135         static MonoClass *klass;
8136         static MonoMethod *ctor;
8137         MonoObject *retval;
8138         void *unboxed, *params [2];
8139
8140         if (!klass)
8141                 klass = mono_class_from_name (mono_defaults.corlib, "System.Reflection", "CustomAttributeNamedArgument");
8142         if (!ctor)
8143                 ctor = mono_class_get_method_from_name (klass, ".ctor", 2);
8144
8145         params [0] = minfo;
8146         params [1] = typedarg;
8147         retval = mono_object_new (mono_domain_get (), klass);
8148         unboxed = mono_object_unbox (retval);
8149         mono_runtime_invoke (ctor, unboxed, params, NULL);
8150
8151         return retval;
8152 }
8153
8154 static gboolean
8155 type_is_reference (MonoType *type)
8156 {
8157         switch (type->type) {
8158         case MONO_TYPE_BOOLEAN:
8159         case MONO_TYPE_CHAR:
8160         case MONO_TYPE_U:
8161         case MONO_TYPE_I:
8162         case MONO_TYPE_U1:
8163         case MONO_TYPE_I1:
8164         case MONO_TYPE_U2:
8165         case MONO_TYPE_I2:
8166         case MONO_TYPE_U4:
8167         case MONO_TYPE_I4:
8168         case MONO_TYPE_U8:
8169         case MONO_TYPE_I8:
8170         case MONO_TYPE_R8:
8171         case MONO_TYPE_R4:
8172         case MONO_TYPE_VALUETYPE:
8173                 return FALSE;
8174         default:
8175                 return TRUE;
8176         }
8177 }
8178
8179 static void
8180 free_param_data (MonoMethodSignature *sig, void **params) {
8181         int i;
8182         for (i = 0; i < sig->param_count; ++i) {
8183                 if (!type_is_reference (sig->params [i]))
8184                         g_free (params [i]);
8185         }
8186 }
8187
8188 /*
8189  * Find the field index in the metadata FieldDef table.
8190  */
8191 static guint32
8192 find_field_index (MonoClass *klass, MonoClassField *field) {
8193         int i;
8194
8195         for (i = 0; i < klass->field.count; ++i) {
8196                 if (field == &klass->fields [i])
8197                         return klass->field.first + 1 + i;
8198         }
8199         return 0;
8200 }
8201
8202 /*
8203  * Find the property index in the metadata Property table.
8204  */
8205 static guint32
8206 find_property_index (MonoClass *klass, MonoProperty *property) {
8207         int i;
8208
8209         for (i = 0; i < klass->ext->property.count; ++i) {
8210                 if (property == &klass->ext->properties [i])
8211                         return klass->ext->property.first + 1 + i;
8212         }
8213         return 0;
8214 }
8215
8216 /*
8217  * Find the event index in the metadata Event table.
8218  */
8219 static guint32
8220 find_event_index (MonoClass *klass, MonoEvent *event) {
8221         int i;
8222
8223         for (i = 0; i < klass->ext->event.count; ++i) {
8224                 if (event == &klass->ext->events [i])
8225                         return klass->ext->event.first + 1 + i;
8226         }
8227         return 0;
8228 }
8229
8230 static MonoObject*
8231 create_custom_attr (MonoImage *image, MonoMethod *method, const guchar *data, guint32 len, MonoError *error)
8232 {
8233         const char *p = (const char*)data;
8234         const char *named;
8235         guint32 i, j, num_named;
8236         MonoObject *attr;
8237         void *params_buf [32];
8238         void **params = NULL;
8239         MonoMethodSignature *sig;
8240         MonoObject *exc = NULL;
8241
8242         mono_error_init (error);
8243
8244         mono_class_init (method->klass);
8245
8246         if (!mono_verifier_verify_cattr_content (image, method, data, len, NULL)) {
8247                 mono_error_set_generic_error (error, "System.Reflection", "CustomAttributeFormatException", "Binary format of the specified custom attribute was invalid.");
8248                 return NULL;
8249         }
8250
8251         if (len == 0) {
8252                 attr = mono_object_new (mono_domain_get (), method->klass);
8253                 mono_runtime_invoke (method, attr, NULL, NULL);
8254                 return attr;
8255         }
8256
8257         if (len < 2 || read16 (p) != 0x0001) /* Prolog */
8258                 return NULL;
8259
8260         /*g_print ("got attr %s\n", method->klass->name);*/
8261
8262         sig = mono_method_signature (method);
8263         if (sig->param_count < 32) {
8264                 params = params_buf;
8265                 memset (params, 0, sizeof (void*) * sig->param_count);
8266         } else {
8267                 /* Allocate using GC so it gets GC tracking */
8268                 params = mono_gc_alloc_fixed (sig->param_count * sizeof (void*), NULL);
8269         }
8270
8271         /* skip prolog */
8272         p += 2;
8273         for (i = 0; i < mono_method_signature (method)->param_count; ++i) {
8274                 params [i] = load_cattr_value (image, mono_method_signature (method)->params [i], p, &p, error);
8275                 if (!mono_error_ok (error))
8276                         goto fail;
8277         }
8278
8279         named = p;
8280         attr = mono_object_new (mono_domain_get (), method->klass);
8281
8282         mono_runtime_invoke (method, attr, params, &exc);
8283         if (exc)
8284                 goto fail;
8285         num_named = read16 (named);
8286         named += 2;
8287         for (j = 0; j < num_named; j++) {
8288                 gint name_len;
8289                 char *name, named_type, data_type;
8290                 named_type = *named++;
8291                 data_type = *named++; /* type of data */
8292                 if (data_type == MONO_TYPE_SZARRAY)
8293                         data_type = *named++;
8294                 if (data_type == MONO_TYPE_ENUM) {
8295                         gint type_len;
8296                         char *type_name;
8297                         type_len = mono_metadata_decode_blob_size (named, &named);
8298                         type_name = g_malloc (type_len + 1);
8299                         memcpy (type_name, named, type_len);
8300                         type_name [type_len] = 0;
8301                         named += type_len;
8302                         /* FIXME: lookup the type and check type consistency */
8303                         g_free (type_name);
8304                 }
8305                 name_len = mono_metadata_decode_blob_size (named, &named);
8306                 name = g_malloc (name_len + 1);
8307                 memcpy (name, named, name_len);
8308                 name [name_len] = 0;
8309                 named += name_len;
8310                 if (named_type == 0x53) {
8311                         MonoClassField *field;
8312                         void *val;
8313
8314                         /* how this fail is a blackbox */
8315                         field = mono_class_get_field_from_name (mono_object_class (attr), name);
8316                         if (!field) {
8317                                 mono_error_set_generic_error (error, "System.Reflection", "CustomAttributeFormatException", "Could not find a field with name %s", name);
8318                                 g_free (name);
8319                                 goto fail;
8320                         }
8321
8322                         val = load_cattr_value (image, field->type, named, &named, error);
8323                         if (!mono_error_ok (error)) {
8324                                 g_free (name);
8325                                 if (!type_is_reference (field->type))
8326                                         g_free (val);
8327                                 goto fail;
8328                         }
8329
8330                         mono_field_set_value (attr, field, val);
8331                         if (!type_is_reference (field->type))
8332                                 g_free (val);
8333                 } else if (named_type == 0x54) {
8334                         MonoProperty *prop;
8335                         void *pparams [1];
8336                         MonoType *prop_type;
8337
8338                         prop = mono_class_get_property_from_name (mono_object_class (attr), name);
8339
8340                         if (!prop) {
8341                                 mono_error_set_generic_error (error, "System.Reflection", "CustomAttributeFormatException", "Could not find a property with name %s", name);
8342                                 g_free (name);
8343                                 goto fail;
8344                         }
8345
8346                         if (!prop->set) {
8347                                 mono_error_set_generic_error (error, "System.Reflection", "CustomAttributeFormatException", "Could not find the setter for %s", name);
8348                                 g_free (name);
8349                                 goto fail;
8350                         }
8351
8352                         /* can we have more that 1 arg in a custom attr named property? */
8353                         prop_type = prop->get? mono_method_signature (prop->get)->ret :
8354                              mono_method_signature (prop->set)->params [mono_method_signature (prop->set)->param_count - 1];
8355
8356                         pparams [0] = load_cattr_value (image, prop_type, named, &named, error);
8357                         if (!mono_error_ok (error)) {
8358                                 g_free (name);
8359                                 if (!type_is_reference (prop_type))
8360                                         g_free (pparams [0]);
8361                                 goto fail;
8362                         }
8363
8364
8365                         mono_property_set_value (prop, attr, pparams, NULL);
8366                         if (!type_is_reference (prop_type))
8367                                 g_free (pparams [0]);
8368                 }
8369                 g_free (name);
8370         }
8371
8372         free_param_data (method->signature, params);
8373         if (params != params_buf)
8374                 mono_gc_free_fixed (params);
8375
8376         return attr;
8377
8378 fail:
8379         free_param_data (method->signature, params);
8380         if (params != params_buf)
8381                 mono_gc_free_fixed (params);
8382         if (exc)
8383                 mono_raise_exception ((MonoException*)exc);
8384         return NULL;
8385 }
8386         
8387 /*
8388  * mono_reflection_create_custom_attr_data_args:
8389  *
8390  *   Create an array of typed and named arguments from the cattr blob given by DATA.
8391  * TYPED_ARGS and NAMED_ARGS will contain the objects representing the arguments,
8392  * NAMED_ARG_INFO will contain information about the named arguments.
8393  */
8394 void
8395 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)
8396 {
8397         MonoArray *typedargs, *namedargs;
8398         MonoClass *attrklass;
8399         MonoDomain *domain;
8400         const char *p = (const char*)data;
8401         const char *named;
8402         guint32 i, j, num_named;
8403         CattrNamedArg *arginfo = NULL;
8404
8405         *typed_args = NULL;
8406         *named_args = NULL;
8407         *named_arg_info = NULL;
8408
8409         mono_error_init (error);
8410
8411         if (!mono_verifier_verify_cattr_content (image, method, data, len, NULL)) {
8412                 mono_error_set_generic_error (error, "System.Reflection", "CustomAttributeFormatException", "Binary format of the specified custom attribute was invalid.");
8413                 return;
8414         }
8415
8416         mono_class_init (method->klass);
8417         
8418         domain = mono_domain_get ();
8419
8420         if (len < 2 || read16 (p) != 0x0001) /* Prolog */
8421                 return;
8422
8423         typedargs = mono_array_new (domain, mono_get_object_class (), mono_method_signature (method)->param_count);
8424         
8425         /* skip prolog */
8426         p += 2;
8427         for (i = 0; i < mono_method_signature (method)->param_count; ++i) {
8428                 MonoObject *obj;
8429                 void *val;
8430
8431                 val = load_cattr_value (image, mono_method_signature (method)->params [i], p, &p, error);
8432                 if (!mono_error_ok (error)) {
8433                         if (!type_is_reference (mono_method_signature (method)->params [i]))
8434                                 g_free (val);
8435                         return;
8436                 }
8437
8438                 obj = type_is_reference (mono_method_signature (method)->params [i]) ? 
8439                         val : mono_value_box (domain, mono_class_from_mono_type (mono_method_signature (method)->params [i]), val);
8440                 mono_array_setref (typedargs, i, obj);
8441
8442                 if (!type_is_reference (mono_method_signature (method)->params [i]))
8443                         g_free (val);
8444         }
8445
8446         named = p;
8447         num_named = read16 (named);
8448         namedargs = mono_array_new (domain, mono_get_object_class (), num_named);
8449         named += 2;
8450         attrklass = method->klass;
8451
8452         arginfo = g_new0 (CattrNamedArg, num_named);
8453         *named_arg_info = arginfo;
8454
8455         for (j = 0; j < num_named; j++) {
8456                 gint name_len;
8457                 char *name, named_type, data_type;
8458                 named_type = *named++;
8459                 data_type = *named++; /* type of data */
8460                 if (data_type == MONO_TYPE_SZARRAY)
8461                         data_type = *named++;
8462                 if (data_type == MONO_TYPE_ENUM) {
8463                         gint type_len;
8464                         char *type_name;
8465                         type_len = mono_metadata_decode_blob_size (named, &named);
8466                         if (ADDP_IS_GREATER_OR_OVF ((const guchar*)named, type_len, data + len))
8467                                 goto fail;
8468
8469                         type_name = g_malloc (type_len + 1);
8470                         memcpy (type_name, named, type_len);
8471                         type_name [type_len] = 0;
8472                         named += type_len;
8473                         /* FIXME: lookup the type and check type consistency */
8474                         g_free (type_name);
8475                 }
8476                 name_len = mono_metadata_decode_blob_size (named, &named);
8477                 if (ADDP_IS_GREATER_OR_OVF ((const guchar*)named, name_len, data + len))
8478                         goto fail;
8479                 name = g_malloc (name_len + 1);
8480                 memcpy (name, named, name_len);
8481                 name [name_len] = 0;
8482                 named += name_len;
8483                 if (named_type == 0x53) {
8484                         MonoObject *obj;
8485                         MonoClassField *field = mono_class_get_field_from_name (attrklass, name);
8486                         void *val;
8487
8488                         if (!field) {
8489                                 g_free (name);
8490                                 goto fail;
8491                         }
8492
8493                         arginfo [j].type = field->type;
8494                         arginfo [j].field = field;
8495
8496                         val = load_cattr_value (image, field->type, named, &named, error);
8497                         if (!mono_error_ok (error)) {
8498                                 if (!type_is_reference (field->type))
8499                                         g_free (val);
8500                                 g_free (name);
8501                                 return;
8502                         }
8503
8504                         obj = type_is_reference (field->type) ? val : mono_value_box (domain, mono_class_from_mono_type (field->type), val);
8505                         mono_array_setref (namedargs, j, obj);
8506                         if (!type_is_reference (field->type))
8507                                 g_free (val);
8508                 } else if (named_type == 0x54) {
8509                         MonoObject *obj;
8510                         MonoType *prop_type;
8511                         MonoProperty *prop = mono_class_get_property_from_name (attrklass, name);
8512                         void *val;
8513
8514                         if (!prop || !prop->set) {
8515                                 g_free (name);
8516                                 goto fail;
8517                         }
8518
8519                         prop_type = prop->get? mono_method_signature (prop->get)->ret :
8520                              mono_method_signature (prop->set)->params [mono_method_signature (prop->set)->param_count - 1];
8521
8522                         arginfo [j].type = prop_type;
8523                         arginfo [j].prop = prop;
8524
8525                         val = load_cattr_value (image, prop_type, named, &named, error);
8526                         if (!mono_error_ok (error)) {
8527                                 if (!type_is_reference (prop_type))
8528                                         g_free (val);
8529                                 g_free (name);
8530                                 return;
8531                         }
8532
8533                         obj = type_is_reference (prop_type) ? val : mono_value_box (domain, mono_class_from_mono_type (prop_type), val);
8534                         mono_array_setref (namedargs, j, obj);
8535                         if (!type_is_reference (prop_type))
8536                                 g_free (val);
8537                 }
8538                 g_free (name);
8539         }
8540
8541         *typed_args = typedargs;
8542         *named_args = namedargs;
8543         return;
8544 fail:
8545         mono_error_set_generic_error (error, "System.Reflection", "CustomAttributeFormatException", "Binary format of the specified custom attribute was invalid.");
8546         g_free (arginfo);
8547         *named_arg_info = NULL;
8548 }
8549
8550 void
8551 mono_reflection_resolve_custom_attribute_data (MonoReflectionMethod *ref_method, MonoReflectionAssembly *assembly, gpointer data, guint32 len, MonoArray **ctor_args, MonoArray **named_args)
8552 {
8553         MonoDomain *domain;
8554         MonoArray *typedargs, *namedargs;
8555         MonoImage *image;
8556         MonoMethod *method;
8557         CattrNamedArg *arginfo = NULL;
8558         MonoError error;
8559         int i;
8560
8561         *ctor_args = NULL;
8562         *named_args = NULL;
8563
8564         if (len == 0)
8565                 return;
8566
8567         image = assembly->assembly->image;
8568         method = ref_method->method;
8569         domain = mono_object_domain (ref_method);
8570
8571         if (!mono_class_init (method->klass))
8572                 mono_raise_exception (mono_class_get_exception_for_failure (method->klass));
8573
8574         mono_reflection_create_custom_attr_data_args (image, method, data, len, &typedargs, &namedargs, &arginfo, &error);
8575         if (!mono_error_ok (&error))
8576                 mono_error_raise_exception (&error);
8577         if (mono_loader_get_last_error ())
8578                 mono_raise_exception (mono_loader_error_prepare_exception (mono_loader_get_last_error ()));
8579
8580         if (!typedargs || !namedargs) {
8581                 g_free (arginfo);
8582                 return;
8583         }
8584
8585         for (i = 0; i < mono_method_signature (method)->param_count; ++i) {
8586                 MonoObject *obj = mono_array_get (typedargs, MonoObject*, i);
8587                 MonoObject *typedarg;
8588
8589                 typedarg = create_cattr_typed_arg (mono_method_signature (method)->params [i], obj);
8590                 mono_array_setref (typedargs, i, typedarg);
8591         }
8592
8593         for (i = 0; i < mono_array_length (namedargs); ++i) {
8594                 MonoObject *obj = mono_array_get (namedargs, MonoObject*, i);
8595                 MonoObject *typedarg, *namedarg, *minfo;
8596
8597                 if (arginfo [i].prop)
8598                         minfo = (MonoObject*)mono_property_get_object (domain, NULL, arginfo [i].prop);
8599                 else
8600                         minfo = (MonoObject*)mono_field_get_object (domain, NULL, arginfo [i].field);
8601
8602                 typedarg = create_cattr_typed_arg (arginfo [i].type, obj);
8603                 namedarg = create_cattr_named_arg (minfo, typedarg);
8604
8605                 mono_array_setref (namedargs, i, namedarg);
8606         }
8607
8608         *ctor_args = typedargs;
8609         *named_args = namedargs;
8610         g_free (arginfo);
8611 }
8612
8613 static MonoObject*
8614 create_custom_attr_data (MonoImage *image, MonoCustomAttrEntry *cattr)
8615 {
8616         static MonoMethod *ctor;
8617         MonoDomain *domain;
8618         MonoObject *attr;
8619         void *params [4];
8620
8621         g_assert (image->assembly);
8622
8623         if (!ctor)
8624                 ctor = mono_class_get_method_from_name (mono_defaults.customattribute_data_class, ".ctor", 4);
8625
8626         domain = mono_domain_get ();
8627         attr = mono_object_new (domain, mono_defaults.customattribute_data_class);
8628         params [0] = mono_method_get_object (domain, cattr->ctor, NULL);
8629         params [1] = mono_assembly_get_object (domain, image->assembly);
8630         params [2] = (gpointer)&cattr->data;
8631         params [3] = &cattr->data_size;
8632         mono_runtime_invoke (ctor, attr, params, NULL);
8633         return attr;
8634 }
8635
8636 static MonoArray*
8637 mono_custom_attrs_construct_by_type (MonoCustomAttrInfo *cinfo, MonoClass *attr_klass, MonoError *error)
8638 {
8639         MonoArray *result;
8640         MonoObject *attr;
8641         int i, n;
8642
8643         mono_error_init (error);
8644
8645         n = 0;
8646         for (i = 0; i < cinfo->num_attrs; ++i) {
8647                 if (!attr_klass || mono_class_is_assignable_from (attr_klass, cinfo->attrs [i].ctor->klass))
8648                         n ++;
8649         }
8650
8651         result = mono_array_new_cached (mono_domain_get (), mono_defaults.attribute_class, n);
8652         n = 0;
8653         for (i = 0; i < cinfo->num_attrs; ++i) {
8654                 if (!cinfo->attrs [i].ctor)
8655                         /* The cattr type is not finished yet */
8656                         /* We should include the type name but cinfo doesn't contain it */
8657                         mono_raise_exception (mono_get_exception_type_load (NULL, NULL));
8658                 if (!attr_klass || mono_class_is_assignable_from (attr_klass, cinfo->attrs [i].ctor->klass)) {
8659                         attr = create_custom_attr (cinfo->image, cinfo->attrs [i].ctor, cinfo->attrs [i].data, cinfo->attrs [i].data_size, error);
8660                         if (!mono_error_ok (error))
8661                                 return result;
8662                         mono_array_setref (result, n, attr);
8663                         n ++;
8664                 }
8665         }
8666         return result;
8667 }
8668
8669 MonoArray*
8670 mono_custom_attrs_construct (MonoCustomAttrInfo *cinfo)
8671 {
8672         MonoError error;
8673         MonoArray *result = mono_custom_attrs_construct_by_type (cinfo, NULL, &error);
8674         g_assert (mono_error_ok (&error)); /*FIXME proper error handling*/
8675
8676         return result;
8677 }
8678
8679 static MonoArray*
8680 mono_custom_attrs_data_construct (MonoCustomAttrInfo *cinfo)
8681 {
8682         MonoArray *result;
8683         MonoObject *attr;
8684         int i;
8685         
8686         result = mono_array_new (mono_domain_get (), mono_defaults.customattribute_data_class, cinfo->num_attrs);
8687         for (i = 0; i < cinfo->num_attrs; ++i) {
8688                 attr = create_custom_attr_data (cinfo->image, &cinfo->attrs [i]);
8689                 mono_array_setref (result, i, attr);
8690         }
8691         return result;
8692 }
8693
8694 /**
8695  * mono_custom_attrs_from_index:
8696  *
8697  * Returns: NULL if no attributes are found or if a loading error occurs.
8698  */
8699 MonoCustomAttrInfo*
8700 mono_custom_attrs_from_index (MonoImage *image, guint32 idx)
8701 {
8702         guint32 mtoken, i, len;
8703         guint32 cols [MONO_CUSTOM_ATTR_SIZE];
8704         MonoTableInfo *ca;
8705         MonoCustomAttrInfo *ainfo;
8706         GList *tmp, *list = NULL;
8707         const char *data;
8708
8709         ca = &image->tables [MONO_TABLE_CUSTOMATTRIBUTE];
8710
8711         i = mono_metadata_custom_attrs_from_index (image, idx);
8712         if (!i)
8713                 return NULL;
8714         i --;
8715         while (i < ca->rows) {
8716                 if (mono_metadata_decode_row_col (ca, i, MONO_CUSTOM_ATTR_PARENT) != idx)
8717                         break;
8718                 list = g_list_prepend (list, GUINT_TO_POINTER (i));
8719                 ++i;
8720         }
8721         len = g_list_length (list);
8722         if (!len)
8723                 return NULL;
8724         ainfo = g_malloc0 (MONO_SIZEOF_CUSTOM_ATTR_INFO + sizeof (MonoCustomAttrEntry) * len);
8725         ainfo->num_attrs = len;
8726         ainfo->image = image;
8727         for (i = 0, tmp = list; i < len; ++i, tmp = tmp->next) {
8728                 mono_metadata_decode_row (ca, GPOINTER_TO_UINT (tmp->data), cols, MONO_CUSTOM_ATTR_SIZE);
8729                 mtoken = cols [MONO_CUSTOM_ATTR_TYPE] >> MONO_CUSTOM_ATTR_TYPE_BITS;
8730                 switch (cols [MONO_CUSTOM_ATTR_TYPE] & MONO_CUSTOM_ATTR_TYPE_MASK) {
8731                 case MONO_CUSTOM_ATTR_TYPE_METHODDEF:
8732                         mtoken |= MONO_TOKEN_METHOD_DEF;
8733                         break;
8734                 case MONO_CUSTOM_ATTR_TYPE_MEMBERREF:
8735                         mtoken |= MONO_TOKEN_MEMBER_REF;
8736                         break;
8737                 default:
8738                         g_error ("Unknown table for custom attr type %08x", cols [MONO_CUSTOM_ATTR_TYPE]);
8739                         break;
8740                 }
8741                 ainfo->attrs [i].ctor = mono_get_method (image, mtoken, NULL);
8742                 if (!ainfo->attrs [i].ctor) {
8743                         g_warning ("Can't find custom attr constructor image: %s mtoken: 0x%08x", image->name, mtoken);
8744                         g_list_free (list);
8745                         g_free (ainfo);
8746                         return NULL;
8747                 }
8748
8749                 if (!mono_verifier_verify_cattr_blob (image, cols [MONO_CUSTOM_ATTR_VALUE], NULL)) {
8750                         /*FIXME raising an exception here doesn't make any sense*/
8751                         g_warning ("Invalid custom attribute blob on image %s for index %x", image->name, idx);
8752                         g_list_free (list);
8753                         g_free (ainfo);
8754                         return NULL;
8755                 }
8756                 data = mono_metadata_blob_heap (image, cols [MONO_CUSTOM_ATTR_VALUE]);
8757                 ainfo->attrs [i].data_size = mono_metadata_decode_value (data, &data);
8758                 ainfo->attrs [i].data = (guchar*)data;
8759         }
8760         g_list_free (list);
8761
8762         return ainfo;
8763 }
8764
8765 MonoCustomAttrInfo*
8766 mono_custom_attrs_from_method (MonoMethod *method)
8767 {
8768         guint32 idx;
8769
8770         /*
8771          * An instantiated method has the same cattrs as the generic method definition.
8772          *
8773          * LAMESPEC: The .NET SRE throws an exception for instantiations of generic method builders
8774          *           Note that this stanza is not necessary for non-SRE types, but it's a micro-optimization
8775          */
8776         if (method->is_inflated)
8777                 method = ((MonoMethodInflated *) method)->declaring;
8778         
8779         if (method_is_dynamic (method) || image_is_dynamic (method->klass->image))
8780                 return lookup_custom_attr (method->klass->image, method);
8781
8782         if (!method->token)
8783                 /* Synthetic methods */
8784                 return NULL;
8785
8786         idx = mono_method_get_index (method);
8787         idx <<= MONO_CUSTOM_ATTR_BITS;
8788         idx |= MONO_CUSTOM_ATTR_METHODDEF;
8789         return mono_custom_attrs_from_index (method->klass->image, idx);
8790 }
8791
8792 MonoCustomAttrInfo*
8793 mono_custom_attrs_from_class (MonoClass *klass)
8794 {
8795         guint32 idx;
8796
8797         if (klass->generic_class)
8798                 klass = klass->generic_class->container_class;
8799
8800         if (image_is_dynamic (klass->image))
8801                 return lookup_custom_attr (klass->image, klass);
8802
8803         if (klass->byval_arg.type == MONO_TYPE_VAR || klass->byval_arg.type == MONO_TYPE_MVAR) {
8804                 idx = mono_metadata_token_index (klass->sizes.generic_param_token);
8805                 idx <<= MONO_CUSTOM_ATTR_BITS;
8806                 idx |= MONO_CUSTOM_ATTR_GENERICPAR;
8807         } else {
8808                 idx = mono_metadata_token_index (klass->type_token);
8809                 idx <<= MONO_CUSTOM_ATTR_BITS;
8810                 idx |= MONO_CUSTOM_ATTR_TYPEDEF;
8811         }
8812         return mono_custom_attrs_from_index (klass->image, idx);
8813 }
8814
8815 MonoCustomAttrInfo*
8816 mono_custom_attrs_from_assembly (MonoAssembly *assembly)
8817 {
8818         guint32 idx;
8819         
8820         if (image_is_dynamic (assembly->image))
8821                 return lookup_custom_attr (assembly->image, assembly);
8822         idx = 1; /* there is only one assembly */
8823         idx <<= MONO_CUSTOM_ATTR_BITS;
8824         idx |= MONO_CUSTOM_ATTR_ASSEMBLY;
8825         return mono_custom_attrs_from_index (assembly->image, idx);
8826 }
8827
8828 static MonoCustomAttrInfo*
8829 mono_custom_attrs_from_module (MonoImage *image)
8830 {
8831         guint32 idx;
8832         
8833         if (image_is_dynamic (image))
8834                 return lookup_custom_attr (image, image);
8835         idx = 1; /* there is only one module */
8836         idx <<= MONO_CUSTOM_ATTR_BITS;
8837         idx |= MONO_CUSTOM_ATTR_MODULE;
8838         return mono_custom_attrs_from_index (image, idx);
8839 }
8840
8841 MonoCustomAttrInfo*
8842 mono_custom_attrs_from_property (MonoClass *klass, MonoProperty *property)
8843 {
8844         guint32 idx;
8845         
8846         if (image_is_dynamic (klass->image)) {
8847                 property = mono_metadata_get_corresponding_property_from_generic_type_definition (property);
8848                 return lookup_custom_attr (klass->image, property);
8849         }
8850         idx = find_property_index (klass, property);
8851         idx <<= MONO_CUSTOM_ATTR_BITS;
8852         idx |= MONO_CUSTOM_ATTR_PROPERTY;
8853         return mono_custom_attrs_from_index (klass->image, idx);
8854 }
8855
8856 MonoCustomAttrInfo*
8857 mono_custom_attrs_from_event (MonoClass *klass, MonoEvent *event)
8858 {
8859         guint32 idx;
8860         
8861         if (image_is_dynamic (klass->image)) {
8862                 event = mono_metadata_get_corresponding_event_from_generic_type_definition (event);
8863                 return lookup_custom_attr (klass->image, event);
8864         }
8865         idx = find_event_index (klass, event);
8866         idx <<= MONO_CUSTOM_ATTR_BITS;
8867         idx |= MONO_CUSTOM_ATTR_EVENT;
8868         return mono_custom_attrs_from_index (klass->image, idx);
8869 }
8870
8871 MonoCustomAttrInfo*
8872 mono_custom_attrs_from_field (MonoClass *klass, MonoClassField *field)
8873 {
8874         guint32 idx;
8875         if (image_is_dynamic (klass->image)) {
8876                 field = mono_metadata_get_corresponding_field_from_generic_type_definition (field);
8877                 return lookup_custom_attr (klass->image, field);
8878         }
8879         idx = find_field_index (klass, field);
8880         idx <<= MONO_CUSTOM_ATTR_BITS;
8881         idx |= MONO_CUSTOM_ATTR_FIELDDEF;
8882         return mono_custom_attrs_from_index (klass->image, idx);
8883 }
8884
8885 /**
8886  * mono_custom_attrs_from_param:
8887  * @method: handle to the method that we want to retrieve custom parameter information from
8888  * @param: parameter number, where zero represent the return value, and one is the first parameter in the method
8889  *
8890  * The result must be released with mono_custom_attrs_free().
8891  *
8892  * Returns: the custom attribute object for the specified parameter, or NULL if there are none.
8893  */
8894 MonoCustomAttrInfo*
8895 mono_custom_attrs_from_param (MonoMethod *method, guint32 param)
8896 {
8897         MonoTableInfo *ca;
8898         guint32 i, idx, method_index;
8899         guint32 param_list, param_last, param_pos, found;
8900         MonoImage *image;
8901         MonoReflectionMethodAux *aux;
8902
8903         /*
8904          * An instantiated method has the same cattrs as the generic method definition.
8905          *
8906          * LAMESPEC: The .NET SRE throws an exception for instantiations of generic method builders
8907          *           Note that this stanza is not necessary for non-SRE types, but it's a micro-optimization
8908          */
8909         if (method->is_inflated)
8910                 method = ((MonoMethodInflated *) method)->declaring;
8911
8912         if (image_is_dynamic (method->klass->image)) {
8913                 MonoCustomAttrInfo *res, *ainfo;
8914                 int size;
8915
8916                 aux = g_hash_table_lookup (((MonoDynamicImage*)method->klass->image)->method_aux_hash, method);
8917                 if (!aux || !aux->param_cattr)
8918                         return NULL;
8919
8920                 /* Need to copy since it will be freed later */
8921                 ainfo = aux->param_cattr [param];
8922                 if (!ainfo)
8923                         return NULL;
8924                 size = MONO_SIZEOF_CUSTOM_ATTR_INFO + sizeof (MonoCustomAttrEntry) * ainfo->num_attrs;
8925                 res = g_malloc0 (size);
8926                 memcpy (res, ainfo, size);
8927                 return res;
8928         }
8929
8930         image = method->klass->image;
8931         method_index = mono_method_get_index (method);
8932         if (!method_index)
8933                 return NULL;
8934         ca = &image->tables [MONO_TABLE_METHOD];
8935
8936         param_list = mono_metadata_decode_row_col (ca, method_index - 1, MONO_METHOD_PARAMLIST);
8937         if (method_index == ca->rows) {
8938                 ca = &image->tables [MONO_TABLE_PARAM];
8939                 param_last = ca->rows + 1;
8940         } else {
8941                 param_last = mono_metadata_decode_row_col (ca, method_index, MONO_METHOD_PARAMLIST);
8942                 ca = &image->tables [MONO_TABLE_PARAM];
8943         }
8944         found = FALSE;
8945         for (i = param_list; i < param_last; ++i) {
8946                 param_pos = mono_metadata_decode_row_col (ca, i - 1, MONO_PARAM_SEQUENCE);
8947                 if (param_pos == param) {
8948                         found = TRUE;
8949                         break;
8950                 }
8951         }
8952         if (!found)
8953                 return NULL;
8954         idx = i;
8955         idx <<= MONO_CUSTOM_ATTR_BITS;
8956         idx |= MONO_CUSTOM_ATTR_PARAMDEF;
8957         return mono_custom_attrs_from_index (image, idx);
8958 }
8959
8960 gboolean
8961 mono_custom_attrs_has_attr (MonoCustomAttrInfo *ainfo, MonoClass *attr_klass)
8962 {
8963         int i;
8964         MonoClass *klass;
8965         for (i = 0; i < ainfo->num_attrs; ++i) {
8966                 klass = ainfo->attrs [i].ctor->klass;
8967                 if (mono_class_has_parent (klass, attr_klass) || (MONO_CLASS_IS_INTERFACE (attr_klass) && mono_class_is_assignable_from (attr_klass, klass)))
8968                         return TRUE;
8969         }
8970         return FALSE;
8971 }
8972
8973 MonoObject*
8974 mono_custom_attrs_get_attr (MonoCustomAttrInfo *ainfo, MonoClass *attr_klass)
8975 {
8976         MonoError error;
8977         MonoObject *res = mono_custom_attrs_get_attr_checked (ainfo, attr_klass, &error);
8978         g_assert (mono_error_ok (&error)); /*FIXME proper error handling*/
8979         return res;
8980 }
8981
8982 MonoObject*
8983 mono_custom_attrs_get_attr_checked (MonoCustomAttrInfo *ainfo, MonoClass *attr_klass, MonoError *error)
8984 {
8985         int i, attr_index;
8986         MonoClass *klass;
8987         MonoArray *attrs;
8988
8989         mono_error_init (error);
8990
8991         attr_index = -1;
8992         for (i = 0; i < ainfo->num_attrs; ++i) {
8993                 klass = ainfo->attrs [i].ctor->klass;
8994                 if (mono_class_has_parent (klass, attr_klass)) {
8995                         attr_index = i;
8996                         break;
8997                 }
8998         }
8999         if (attr_index == -1)
9000                 return NULL;
9001
9002         attrs = mono_custom_attrs_construct_by_type (ainfo, NULL, error);
9003         if (!mono_error_ok (error))
9004                 return NULL;
9005         return mono_array_get (attrs, MonoObject*, attr_index);
9006 }
9007
9008 /*
9009  * mono_reflection_get_custom_attrs_info:
9010  * @obj: a reflection object handle
9011  *
9012  * Return the custom attribute info for attributes defined for the
9013  * reflection handle @obj. The objects.
9014  *
9015  * FIXME this function leaks like a sieve for SRE objects.
9016  */
9017 MonoCustomAttrInfo*
9018 mono_reflection_get_custom_attrs_info (MonoObject *obj)
9019 {
9020         MonoClass *klass;
9021         MonoCustomAttrInfo *cinfo = NULL;
9022         
9023         klass = obj->vtable->klass;
9024         if (klass == mono_defaults.monotype_class) {
9025                 MonoType *type = mono_reflection_type_get_handle ((MonoReflectionType *)obj);
9026                 klass = mono_class_from_mono_type (type);
9027                 /*We cannot mono_class_init the class from which we'll load the custom attributes since this must work with broken types.*/
9028                 cinfo = mono_custom_attrs_from_class (klass);
9029         } else if (strcmp ("Assembly", klass->name) == 0 || strcmp ("MonoAssembly", klass->name) == 0) {
9030                 MonoReflectionAssembly *rassembly = (MonoReflectionAssembly*)obj;
9031                 cinfo = mono_custom_attrs_from_assembly (rassembly->assembly);
9032         } else if (strcmp ("Module", klass->name) == 0 || strcmp ("MonoModule", klass->name) == 0) {
9033                 MonoReflectionModule *module = (MonoReflectionModule*)obj;
9034                 cinfo = mono_custom_attrs_from_module (module->image);
9035         } else if (strcmp ("MonoProperty", klass->name) == 0) {
9036                 MonoReflectionProperty *rprop = (MonoReflectionProperty*)obj;
9037                 cinfo = mono_custom_attrs_from_property (rprop->property->parent, rprop->property);
9038         } else if (strcmp ("MonoEvent", klass->name) == 0) {
9039                 MonoReflectionMonoEvent *revent = (MonoReflectionMonoEvent*)obj;
9040                 cinfo = mono_custom_attrs_from_event (revent->event->parent, revent->event);
9041         } else if (strcmp ("MonoField", klass->name) == 0) {
9042                 MonoReflectionField *rfield = (MonoReflectionField*)obj;
9043                 cinfo = mono_custom_attrs_from_field (rfield->field->parent, rfield->field);
9044         } else if ((strcmp ("MonoMethod", klass->name) == 0) || (strcmp ("MonoCMethod", klass->name) == 0)) {
9045                 MonoReflectionMethod *rmethod = (MonoReflectionMethod*)obj;
9046                 cinfo = mono_custom_attrs_from_method (rmethod->method);
9047         } else if ((strcmp ("MonoGenericMethod", klass->name) == 0) || (strcmp ("MonoGenericCMethod", klass->name) == 0)) {
9048                 MonoReflectionMethod *rmethod = (MonoReflectionMethod*)obj;
9049                 cinfo = mono_custom_attrs_from_method (rmethod->method);
9050         } else if (strcmp ("ParameterInfo", klass->name) == 0 || strcmp ("MonoParameterInfo", klass->name) == 0) {
9051                 MonoReflectionParameter *param = (MonoReflectionParameter*)obj;
9052                 MonoClass *member_class = mono_object_class (param->MemberImpl);
9053                 if (mono_class_is_reflection_method_or_constructor (member_class)) {
9054                         MonoReflectionMethod *rmethod = (MonoReflectionMethod*)param->MemberImpl;
9055                         cinfo = mono_custom_attrs_from_param (rmethod->method, param->PositionImpl + 1);
9056                 } else if (is_sr_mono_property (member_class)) {
9057                         MonoReflectionProperty *prop = (MonoReflectionProperty *)param->MemberImpl;
9058                         MonoMethod *method;
9059                         if (!(method = prop->property->get))
9060                                 method = prop->property->set;
9061                         g_assert (method);
9062
9063                         cinfo = mono_custom_attrs_from_param (method, param->PositionImpl + 1);
9064                 } 
9065 #ifndef DISABLE_REFLECTION_EMIT
9066                 else if (is_sre_method_on_tb_inst (member_class)) {/*XXX This is a workaround for Compiler Context*/
9067                         MonoMethod *method = mono_reflection_method_on_tb_inst_get_handle ((MonoReflectionMethodOnTypeBuilderInst*)param->MemberImpl);
9068                         cinfo = mono_custom_attrs_from_param (method, param->PositionImpl + 1);
9069                 } else if (is_sre_ctor_on_tb_inst (member_class)) { /*XX This is a workaround for Compiler Context*/
9070                         MonoReflectionCtorOnTypeBuilderInst *c = (MonoReflectionCtorOnTypeBuilderInst*)param->MemberImpl;
9071                         MonoMethod *method = NULL;
9072                         if (is_sre_ctor_builder (mono_object_class (c->cb)))
9073                                 method = ((MonoReflectionCtorBuilder *)c->cb)->mhandle;
9074                         else if (is_sr_mono_cmethod (mono_object_class (c->cb)))
9075                                 method = ((MonoReflectionMethod *)c->cb)->method;
9076                         else
9077                                 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));
9078
9079                         cinfo = mono_custom_attrs_from_param (method, param->PositionImpl + 1);
9080                 } 
9081 #endif
9082                 else {
9083                         char *type_name = mono_type_get_full_name (member_class);
9084                         char *msg = g_strdup_printf ("Custom attributes on a ParamInfo with member %s are not supported", type_name);
9085                         MonoException *ex = mono_get_exception_not_supported  (msg);
9086                         g_free (type_name);
9087                         g_free (msg);
9088                         mono_raise_exception (ex);
9089                 }
9090         } else if (strcmp ("AssemblyBuilder", klass->name) == 0) {
9091                 MonoReflectionAssemblyBuilder *assemblyb = (MonoReflectionAssemblyBuilder*)obj;
9092                 cinfo = mono_custom_attrs_from_builders (NULL, assemblyb->assembly.assembly->image, assemblyb->cattrs);
9093         } else if (strcmp ("TypeBuilder", klass->name) == 0) {
9094                 MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder*)obj;
9095                 cinfo = mono_custom_attrs_from_builders (NULL, &tb->module->dynamic_image->image, tb->cattrs);
9096         } else if (strcmp ("ModuleBuilder", klass->name) == 0) {
9097                 MonoReflectionModuleBuilder *mb = (MonoReflectionModuleBuilder*)obj;
9098                 cinfo = mono_custom_attrs_from_builders (NULL, &mb->dynamic_image->image, mb->cattrs);
9099         } else if (strcmp ("ConstructorBuilder", klass->name) == 0) {
9100                 MonoReflectionCtorBuilder *cb = (MonoReflectionCtorBuilder*)obj;
9101                 cinfo = mono_custom_attrs_from_builders (NULL, cb->mhandle->klass->image, cb->cattrs);
9102         } else if (strcmp ("MethodBuilder", klass->name) == 0) {
9103                 MonoReflectionMethodBuilder *mb = (MonoReflectionMethodBuilder*)obj;
9104                 cinfo = mono_custom_attrs_from_builders (NULL, mb->mhandle->klass->image, mb->cattrs);
9105         } else if (strcmp ("FieldBuilder", klass->name) == 0) {
9106                 MonoReflectionFieldBuilder *fb = (MonoReflectionFieldBuilder*)obj;
9107                 cinfo = mono_custom_attrs_from_builders (NULL, &((MonoReflectionTypeBuilder*)fb->typeb)->module->dynamic_image->image, fb->cattrs);
9108         } else if (strcmp ("MonoGenericClass", klass->name) == 0) {
9109                 MonoReflectionGenericClass *gclass = (MonoReflectionGenericClass*)obj;
9110                 cinfo = mono_reflection_get_custom_attrs_info ((MonoObject*)gclass->generic_type);
9111         } else { /* handle other types here... */
9112                 g_error ("get custom attrs not yet supported for %s", klass->name);
9113         }
9114
9115         return cinfo;
9116 }
9117
9118 /*
9119  * mono_reflection_get_custom_attrs_by_type:
9120  * @obj: a reflection object handle
9121  *
9122  * Return an array with all the custom attributes defined of the
9123  * reflection handle @obj. If @attr_klass is non-NULL, only custom attributes 
9124  * of that type are returned. The objects are fully build. Return NULL if a loading error
9125  * occurs.
9126  */
9127 MonoArray*
9128 mono_reflection_get_custom_attrs_by_type (MonoObject *obj, MonoClass *attr_klass, MonoError *error)
9129 {
9130         MonoArray *result;
9131         MonoCustomAttrInfo *cinfo;
9132
9133         mono_error_init (error);
9134
9135         cinfo = mono_reflection_get_custom_attrs_info (obj);
9136         if (cinfo) {
9137                 result = mono_custom_attrs_construct_by_type (cinfo, attr_klass, error);
9138                 if (!cinfo->cached)
9139                         mono_custom_attrs_free (cinfo);
9140         } else {
9141                 /* FIXME add MonoError to mono_reflection_get_custom_attrs_info */
9142                 if (mono_loader_get_last_error ())
9143                         return NULL;
9144                 result = mono_array_new_cached (mono_domain_get (), mono_defaults.attribute_class, 0);
9145         }
9146
9147         return result;
9148 }
9149
9150 /*
9151  * mono_reflection_get_custom_attrs:
9152  * @obj: a reflection object handle
9153  *
9154  * Return an array with all the custom attributes defined of the
9155  * reflection handle @obj. The objects are fully build. Return NULL if a loading error
9156  * occurs.
9157  */
9158 MonoArray*
9159 mono_reflection_get_custom_attrs (MonoObject *obj)
9160 {
9161         MonoError error;
9162
9163         return mono_reflection_get_custom_attrs_by_type (obj, NULL, &error);
9164 }
9165
9166 /*
9167  * mono_reflection_get_custom_attrs_data:
9168  * @obj: a reflection obj handle
9169  *
9170  * Returns an array of System.Reflection.CustomAttributeData,
9171  * which include information about attributes reflected on
9172  * types loaded using the Reflection Only methods
9173  */
9174 MonoArray*
9175 mono_reflection_get_custom_attrs_data (MonoObject *obj)
9176 {
9177         MonoArray *result;
9178         MonoCustomAttrInfo *cinfo;
9179
9180         cinfo = mono_reflection_get_custom_attrs_info (obj);
9181         if (cinfo) {
9182                 result = mono_custom_attrs_data_construct (cinfo);
9183                 if (!cinfo->cached)
9184                         mono_custom_attrs_free (cinfo);
9185         } else
9186                 result = mono_array_new (mono_domain_get (), mono_defaults.customattribute_data_class, 0);
9187
9188         return result;
9189 }
9190
9191 static MonoReflectionType*
9192 mono_reflection_type_get_underlying_system_type (MonoReflectionType* t)
9193 {
9194         static MonoMethod *method_get_underlying_system_type = NULL;
9195         MonoMethod *usertype_method;
9196
9197         if (!method_get_underlying_system_type)
9198                 method_get_underlying_system_type = mono_class_get_method_from_name (mono_defaults.systemtype_class, "get_UnderlyingSystemType", 0);
9199         usertype_method = mono_object_get_virtual_method ((MonoObject *) t, method_get_underlying_system_type);
9200         return (MonoReflectionType *) mono_runtime_invoke (usertype_method, t, NULL, NULL);
9201 }
9202
9203
9204 static gboolean
9205 is_corlib_type (MonoClass *class)
9206 {
9207         return class->image == mono_defaults.corlib;
9208 }
9209
9210 #define check_corlib_type_cached(_class, _namespace, _name) do { \
9211         static MonoClass *cached_class; \
9212         if (cached_class) \
9213                 return cached_class == _class; \
9214         if (is_corlib_type (_class) && !strcmp (_name, _class->name) && !strcmp (_namespace, _class->name_space)) { \
9215                 cached_class = _class; \
9216                 return TRUE; \
9217         } \
9218         return FALSE; \
9219 } while (0) \
9220
9221
9222 #ifndef DISABLE_REFLECTION_EMIT
9223 static gboolean
9224 is_sre_array (MonoClass *class)
9225 {
9226         check_corlib_type_cached (class, "System.Reflection.Emit", "ArrayType");
9227 }
9228
9229 static gboolean
9230 is_sre_byref (MonoClass *class)
9231 {
9232         check_corlib_type_cached (class, "System.Reflection.Emit", "ByRefType");
9233 }
9234
9235 static gboolean
9236 is_sre_pointer (MonoClass *class)
9237 {
9238         check_corlib_type_cached (class, "System.Reflection.Emit", "PointerType");
9239 }
9240
9241 static gboolean
9242 is_sre_generic_instance (MonoClass *class)
9243 {
9244         check_corlib_type_cached (class, "System.Reflection", "MonoGenericClass");
9245 }
9246
9247 static gboolean
9248 is_sre_type_builder (MonoClass *class)
9249 {
9250         check_corlib_type_cached (class, "System.Reflection.Emit", "TypeBuilder");
9251 }
9252
9253 static gboolean
9254 is_sre_method_builder (MonoClass *class)
9255 {
9256         check_corlib_type_cached (class, "System.Reflection.Emit", "MethodBuilder");
9257 }
9258
9259 static gboolean
9260 is_sre_ctor_builder (MonoClass *class)
9261 {
9262         check_corlib_type_cached (class, "System.Reflection.Emit", "ConstructorBuilder");
9263 }
9264
9265 static gboolean
9266 is_sre_field_builder (MonoClass *class)
9267 {
9268         check_corlib_type_cached (class, "System.Reflection.Emit", "FieldBuilder");
9269 }
9270
9271 static gboolean
9272 is_sre_method_on_tb_inst (MonoClass *class)
9273 {
9274         check_corlib_type_cached (class, "System.Reflection.Emit", "MethodOnTypeBuilderInst");
9275 }
9276
9277 static gboolean
9278 is_sre_ctor_on_tb_inst (MonoClass *class)
9279 {
9280         check_corlib_type_cached (class, "System.Reflection.Emit", "ConstructorOnTypeBuilderInst");
9281 }
9282
9283 MonoType*
9284 mono_reflection_type_get_handle (MonoReflectionType* ref)
9285 {
9286         MonoClass *class;
9287         if (!ref)
9288                 return NULL;
9289         if (ref->type)
9290                 return ref->type;
9291
9292         if (is_usertype (ref)) {
9293                 ref = mono_reflection_type_get_underlying_system_type (ref);
9294                 if (ref == NULL || is_usertype (ref))
9295                         return NULL;
9296                 if (ref->type)
9297                         return ref->type;
9298         }
9299
9300         class = mono_object_class (ref);
9301
9302         if (is_sre_array (class)) {
9303                 MonoType *res;
9304                 MonoReflectionArrayType *sre_array = (MonoReflectionArrayType*)ref;
9305                 MonoType *base = mono_reflection_type_get_handle (sre_array->element_type);
9306                 g_assert (base);
9307                 if (sre_array->rank == 0) //single dimentional array
9308                         res = &mono_array_class_get (mono_class_from_mono_type (base), 1)->byval_arg;
9309                 else
9310                         res = &mono_bounded_array_class_get (mono_class_from_mono_type (base), sre_array->rank, TRUE)->byval_arg;
9311                 sre_array->type.type = res;
9312                 return res;
9313         } else if (is_sre_byref (class)) {
9314                 MonoType *res;
9315                 MonoReflectionDerivedType *sre_byref = (MonoReflectionDerivedType*)ref;
9316                 MonoType *base = mono_reflection_type_get_handle (sre_byref->element_type);
9317                 g_assert (base);
9318                 res = &mono_class_from_mono_type (base)->this_arg;
9319                 sre_byref->type.type = res;
9320                 return res;
9321         } else if (is_sre_pointer (class)) {
9322                 MonoType *res;
9323                 MonoReflectionDerivedType *sre_pointer = (MonoReflectionDerivedType*)ref;
9324                 MonoType *base = mono_reflection_type_get_handle (sre_pointer->element_type);
9325                 g_assert (base);
9326                 res = &mono_ptr_class_get (base)->byval_arg;
9327                 sre_pointer->type.type = res;
9328                 return res;
9329         } else if (is_sre_generic_instance (class)) {
9330                 MonoType *res, **types;
9331                 MonoReflectionGenericClass *gclass = (MonoReflectionGenericClass*)ref;
9332                 int i, count;
9333
9334                 count = mono_array_length (gclass->type_arguments);
9335                 types = g_new0 (MonoType*, count);
9336                 for (i = 0; i < count; ++i) {
9337                         MonoReflectionType *t = mono_array_get (gclass->type_arguments, gpointer, i);
9338                         types [i] = mono_reflection_type_get_handle (t);
9339                         if (!types[i]) {
9340                                 g_free (types);
9341                                 return NULL;
9342                         }
9343                 }
9344
9345                 res = mono_reflection_bind_generic_parameters (gclass->generic_type, count, types);
9346                 g_free (types);
9347                 g_assert (res);
9348                 gclass->type.type = res;
9349                 return res;
9350         }
9351
9352         g_error ("Cannot handle corlib user type %s", mono_type_full_name (&mono_object_class(ref)->byval_arg));
9353         return NULL;
9354 }
9355
9356
9357
9358 void
9359 mono_reflection_create_unmanaged_type (MonoReflectionType *type)
9360 {
9361         mono_reflection_type_get_handle (type);
9362 }
9363
9364 void
9365 mono_reflection_register_with_runtime (MonoReflectionType *type)
9366 {
9367         MonoType *res = mono_reflection_type_get_handle (type);
9368         MonoDomain *domain = mono_object_domain ((MonoObject*)type);
9369         MonoClass *class;
9370
9371         if (!res)
9372                 mono_raise_exception (mono_get_exception_argument (NULL, "Invalid generic instantiation, one or more arguments are not proper user types"));
9373
9374         class = mono_class_from_mono_type (res);
9375
9376         mono_loader_lock (); /*same locking as mono_type_get_object*/
9377         mono_domain_lock (domain);
9378
9379         if (!image_is_dynamic (class->image)) {
9380                 mono_class_setup_supertypes (class);
9381         } else {
9382                 if (!domain->type_hash)
9383                         domain->type_hash = mono_g_hash_table_new_type ((GHashFunc)mono_metadata_type_hash, 
9384                                         (GCompareFunc)mono_metadata_type_equal, MONO_HASH_VALUE_GC);
9385                 mono_g_hash_table_insert (domain->type_hash, res, type);
9386         }
9387         mono_domain_unlock (domain);
9388         mono_loader_unlock ();
9389 }
9390
9391 /**
9392  * LOCKING: Assumes the loader lock is held.
9393  */
9394 static MonoMethodSignature*
9395 parameters_to_signature (MonoImage *image, MonoArray *parameters) {
9396         MonoMethodSignature *sig;
9397         int count, i;
9398
9399         count = parameters? mono_array_length (parameters): 0;
9400
9401         sig = image_g_malloc0 (image, MONO_SIZEOF_METHOD_SIGNATURE + sizeof (MonoType*) * count);
9402         sig->param_count = count;
9403         sig->sentinelpos = -1; /* FIXME */
9404         for (i = 0; i < count; ++i)
9405                 sig->params [i] = mono_type_array_get_and_resolve (parameters, i);
9406         return sig;
9407 }
9408
9409 /**
9410  * LOCKING: Assumes the loader lock is held.
9411  */
9412 static MonoMethodSignature*
9413 ctor_builder_to_signature (MonoImage *image, MonoReflectionCtorBuilder *ctor) {
9414         MonoMethodSignature *sig;
9415
9416         sig = parameters_to_signature (image, ctor->parameters);
9417         sig->hasthis = ctor->attrs & METHOD_ATTRIBUTE_STATIC? 0: 1;
9418         sig->ret = &mono_defaults.void_class->byval_arg;
9419         return sig;
9420 }
9421
9422 /**
9423  * LOCKING: Assumes the loader lock is held.
9424  */
9425 static MonoMethodSignature*
9426 method_builder_to_signature (MonoImage *image, MonoReflectionMethodBuilder *method) {
9427         MonoMethodSignature *sig;
9428
9429         sig = parameters_to_signature (image, method->parameters);
9430         sig->hasthis = method->attrs & METHOD_ATTRIBUTE_STATIC? 0: 1;
9431         sig->ret = method->rtype? mono_reflection_type_get_handle ((MonoReflectionType*)method->rtype): &mono_defaults.void_class->byval_arg;
9432         sig->generic_param_count = method->generic_params ? mono_array_length (method->generic_params) : 0;
9433         return sig;
9434 }
9435
9436 static MonoMethodSignature*
9437 dynamic_method_to_signature (MonoReflectionDynamicMethod *method) {
9438         MonoMethodSignature *sig;
9439
9440         sig = parameters_to_signature (NULL, method->parameters);
9441         sig->hasthis = method->attrs & METHOD_ATTRIBUTE_STATIC? 0: 1;
9442         sig->ret = method->rtype? mono_reflection_type_get_handle (method->rtype): &mono_defaults.void_class->byval_arg;
9443         sig->generic_param_count = 0;
9444         return sig;
9445 }
9446
9447 static void
9448 get_prop_name_and_type (MonoObject *prop, char **name, MonoType **type)
9449 {
9450         MonoClass *klass = mono_object_class (prop);
9451         if (strcmp (klass->name, "PropertyBuilder") == 0) {
9452                 MonoReflectionPropertyBuilder *pb = (MonoReflectionPropertyBuilder *)prop;
9453                 *name = mono_string_to_utf8 (pb->name);
9454                 *type = mono_reflection_type_get_handle ((MonoReflectionType*)pb->type);
9455         } else {
9456                 MonoReflectionProperty *p = (MonoReflectionProperty *)prop;
9457                 *name = g_strdup (p->property->name);
9458                 if (p->property->get)
9459                         *type = mono_method_signature (p->property->get)->ret;
9460                 else
9461                         *type = mono_method_signature (p->property->set)->params [mono_method_signature (p->property->set)->param_count - 1];
9462         }
9463 }
9464
9465 static void
9466 get_field_name_and_type (MonoObject *field, char **name, MonoType **type)
9467 {
9468         MonoClass *klass = mono_object_class (field);
9469         if (strcmp (klass->name, "FieldBuilder") == 0) {
9470                 MonoReflectionFieldBuilder *fb = (MonoReflectionFieldBuilder *)field;
9471                 *name = mono_string_to_utf8 (fb->name);
9472                 *type = mono_reflection_type_get_handle ((MonoReflectionType*)fb->type);
9473         } else {
9474                 MonoReflectionField *f = (MonoReflectionField *)field;
9475                 *name = g_strdup (mono_field_get_name (f->field));
9476                 *type = f->field->type;
9477         }
9478 }
9479
9480 #else /* DISABLE_REFLECTION_EMIT */
9481
9482 void
9483 mono_reflection_register_with_runtime (MonoReflectionType *type)
9484 {
9485         /* This is empty */
9486 }
9487
9488 static gboolean
9489 is_sre_type_builder (MonoClass *class)
9490 {
9491         return FALSE;
9492 }
9493
9494 static gboolean
9495 is_sre_generic_instance (MonoClass *class)
9496 {
9497         return FALSE;
9498 }
9499
9500 static void
9501 init_type_builder_generics (MonoObject *type)
9502 {
9503 }
9504
9505 #endif /* !DISABLE_REFLECTION_EMIT */
9506
9507
9508 static gboolean
9509 is_sr_mono_field (MonoClass *class)
9510 {
9511         check_corlib_type_cached (class, "System.Reflection", "MonoField");
9512 }
9513
9514 static gboolean
9515 is_sr_mono_property (MonoClass *class)
9516 {
9517         check_corlib_type_cached (class, "System.Reflection", "MonoProperty");
9518 }
9519
9520 static gboolean
9521 is_sr_mono_method (MonoClass *class)
9522 {
9523         check_corlib_type_cached (class, "System.Reflection", "MonoMethod");
9524 }
9525
9526 static gboolean
9527 is_sr_mono_cmethod (MonoClass *class)
9528 {
9529         check_corlib_type_cached (class, "System.Reflection", "MonoCMethod");
9530 }
9531
9532 static gboolean
9533 is_sr_mono_generic_method (MonoClass *class)
9534 {
9535         check_corlib_type_cached (class, "System.Reflection", "MonoGenericMethod");
9536 }
9537
9538 static gboolean
9539 is_sr_mono_generic_cmethod (MonoClass *class)
9540 {
9541         check_corlib_type_cached (class, "System.Reflection", "MonoGenericCMethod");
9542 }
9543
9544 gboolean
9545 mono_class_is_reflection_method_or_constructor (MonoClass *class)
9546 {
9547         return is_sr_mono_method (class) || is_sr_mono_cmethod (class) || is_sr_mono_generic_method (class) || is_sr_mono_generic_cmethod (class);
9548 }
9549
9550 static gboolean
9551 is_usertype (MonoReflectionType *ref)
9552 {
9553         MonoClass *class = mono_object_class (ref);
9554         return class->image != mono_defaults.corlib || strcmp ("TypeDelegator", class->name) == 0;
9555 }
9556
9557 static MonoReflectionType*
9558 mono_reflection_type_resolve_user_types (MonoReflectionType *type)
9559 {
9560         if (!type || type->type)
9561                 return type;
9562
9563         if (is_usertype (type)) {
9564                 type = mono_reflection_type_get_underlying_system_type (type);
9565                 if (is_usertype (type))
9566                         mono_raise_exception (mono_get_exception_not_supported ("User defined subclasses of System.Type are not yet supported22"));
9567         }
9568
9569         return type;
9570 }
9571 /*
9572  * Encode a value in a custom attribute stream of bytes.
9573  * The value to encode is either supplied as an object in argument val
9574  * (valuetypes are boxed), or as a pointer to the data in the
9575  * argument argval.
9576  * @type represents the type of the value
9577  * @buffer is the start of the buffer
9578  * @p the current position in the buffer
9579  * @buflen contains the size of the buffer and is used to return the new buffer size
9580  * if this needs to be realloced.
9581  * @retbuffer and @retp return the start and the position of the buffer
9582  */
9583 static void
9584 encode_cattr_value (MonoAssembly *assembly, char *buffer, char *p, char **retbuffer, char **retp, guint32 *buflen, MonoType *type, MonoObject *arg, char *argval)
9585 {
9586         MonoTypeEnum simple_type;
9587         
9588         if ((p-buffer) + 10 >= *buflen) {
9589                 char *newbuf;
9590                 *buflen *= 2;
9591                 newbuf = g_realloc (buffer, *buflen);
9592                 p = newbuf + (p-buffer);
9593                 buffer = newbuf;
9594         }
9595         if (!argval)
9596                 argval = ((char*)arg + sizeof (MonoObject));
9597         simple_type = type->type;
9598 handle_enum:
9599         switch (simple_type) {
9600         case MONO_TYPE_BOOLEAN:
9601         case MONO_TYPE_U1:
9602         case MONO_TYPE_I1:
9603                 *p++ = *argval;
9604                 break;
9605         case MONO_TYPE_CHAR:
9606         case MONO_TYPE_U2:
9607         case MONO_TYPE_I2:
9608                 swap_with_size (p, argval, 2, 1);
9609                 p += 2;
9610                 break;
9611         case MONO_TYPE_U4:
9612         case MONO_TYPE_I4:
9613         case MONO_TYPE_R4:
9614                 swap_with_size (p, argval, 4, 1);
9615                 p += 4;
9616                 break;
9617         case MONO_TYPE_R8:
9618                 swap_with_size (p, argval, 8, 1);
9619                 p += 8;
9620                 break;
9621         case MONO_TYPE_U8:
9622         case MONO_TYPE_I8:
9623                 swap_with_size (p, argval, 8, 1);
9624                 p += 8;
9625                 break;
9626         case MONO_TYPE_VALUETYPE:
9627                 if (type->data.klass->enumtype) {
9628                         simple_type = mono_class_enum_basetype (type->data.klass)->type;
9629                         goto handle_enum;
9630                 } else {
9631                         g_warning ("generic valutype %s not handled in custom attr value decoding", type->data.klass->name);
9632                 }
9633                 break;
9634         case MONO_TYPE_STRING: {
9635                 char *str;
9636                 guint32 slen;
9637                 if (!arg) {
9638                         *p++ = 0xFF;
9639                         break;
9640                 }
9641                 str = mono_string_to_utf8 ((MonoString*)arg);
9642                 slen = strlen (str);
9643                 if ((p-buffer) + 10 + slen >= *buflen) {
9644                         char *newbuf;
9645                         *buflen *= 2;
9646                         *buflen += slen;
9647                         newbuf = g_realloc (buffer, *buflen);
9648                         p = newbuf + (p-buffer);
9649                         buffer = newbuf;
9650                 }
9651                 mono_metadata_encode_value (slen, p, &p);
9652                 memcpy (p, str, slen);
9653                 p += slen;
9654                 g_free (str);
9655                 break;
9656         }
9657         case MONO_TYPE_CLASS: {
9658                 char *str;
9659                 guint32 slen;
9660                 if (!arg) {
9661                         *p++ = 0xFF;
9662                         break;
9663                 }
9664 handle_type:
9665                 str = type_get_qualified_name (mono_reflection_type_get_handle ((MonoReflectionType*)arg), NULL);
9666                 slen = strlen (str);
9667                 if ((p-buffer) + 10 + slen >= *buflen) {
9668                         char *newbuf;
9669                         *buflen *= 2;
9670                         *buflen += slen;
9671                         newbuf = g_realloc (buffer, *buflen);
9672                         p = newbuf + (p-buffer);
9673                         buffer = newbuf;
9674                 }
9675                 mono_metadata_encode_value (slen, p, &p);
9676                 memcpy (p, str, slen);
9677                 p += slen;
9678                 g_free (str);
9679                 break;
9680         }
9681         case MONO_TYPE_SZARRAY: {
9682                 int len, i;
9683                 MonoClass *eclass, *arg_eclass;
9684
9685                 if (!arg) {
9686                         *p++ = 0xff; *p++ = 0xff; *p++ = 0xff; *p++ = 0xff;
9687                         break;
9688                 }
9689                 len = mono_array_length ((MonoArray*)arg);
9690                 *p++ = len & 0xff;
9691                 *p++ = (len >> 8) & 0xff;
9692                 *p++ = (len >> 16) & 0xff;
9693                 *p++ = (len >> 24) & 0xff;
9694                 *retp = p;
9695                 *retbuffer = buffer;
9696                 eclass = type->data.klass;
9697                 arg_eclass = mono_object_class (arg)->element_class;
9698
9699                 if (!eclass) {
9700                         /* Happens when we are called from the MONO_TYPE_OBJECT case below */
9701                         eclass = mono_defaults.object_class;
9702                 }
9703                 if (eclass == mono_defaults.object_class && arg_eclass->valuetype) {
9704                         char *elptr = mono_array_addr ((MonoArray*)arg, char, 0);
9705                         int elsize = mono_class_array_element_size (arg_eclass);
9706                         for (i = 0; i < len; ++i) {
9707                                 encode_cattr_value (assembly, buffer, p, &buffer, &p, buflen, &arg_eclass->byval_arg, NULL, elptr);
9708                                 elptr += elsize;
9709                         }
9710                 } else if (eclass->valuetype && arg_eclass->valuetype) {
9711                         char *elptr = mono_array_addr ((MonoArray*)arg, char, 0);
9712                         int elsize = mono_class_array_element_size (eclass);
9713                         for (i = 0; i < len; ++i) {
9714                                 encode_cattr_value (assembly, buffer, p, &buffer, &p, buflen, &eclass->byval_arg, NULL, elptr);
9715                                 elptr += elsize;
9716                         }
9717                 } else {
9718                         for (i = 0; i < len; ++i) {
9719                                 encode_cattr_value (assembly, buffer, p, &buffer, &p, buflen, &eclass->byval_arg, mono_array_get ((MonoArray*)arg, MonoObject*, i), NULL);
9720                         }
9721                 }
9722                 break;
9723         }
9724         case MONO_TYPE_OBJECT: {
9725                 MonoClass *klass;
9726                 char *str;
9727                 guint32 slen;
9728
9729                 /*
9730                  * The parameter type is 'object' but the type of the actual
9731                  * argument is not. So we have to add type information to the blob
9732                  * too. This is completely undocumented in the spec.
9733                  */
9734
9735                 if (arg == NULL) {
9736                         *p++ = MONO_TYPE_STRING;        // It's same hack as MS uses
9737                         *p++ = 0xFF;
9738                         break;
9739                 }
9740                 
9741                 klass = mono_object_class (arg);
9742
9743                 if (mono_object_isinst (arg, mono_defaults.systemtype_class)) {
9744                         *p++ = 0x50;
9745                         goto handle_type;
9746                 } else if (klass->enumtype) {
9747                         *p++ = 0x55;
9748                 } else if (klass == mono_defaults.string_class) {
9749                         simple_type = MONO_TYPE_STRING;
9750                         *p++ = 0x0E;
9751                         goto handle_enum;
9752                 } else if (klass->rank == 1) {
9753                         *p++ = 0x1D;
9754                         if (klass->element_class->byval_arg.type == MONO_TYPE_OBJECT)
9755                                 /* See Partition II, Appendix B3 */
9756                                 *p++ = 0x51;
9757                         else
9758                                 *p++ = klass->element_class->byval_arg.type;
9759                         encode_cattr_value (assembly, buffer, p, &buffer, &p, buflen, &klass->byval_arg, arg, NULL);
9760                         break;
9761                 } else if (klass->byval_arg.type >= MONO_TYPE_BOOLEAN && klass->byval_arg.type <= MONO_TYPE_R8) {
9762                         *p++ = simple_type = klass->byval_arg.type;
9763                         goto handle_enum;
9764                 } else {
9765                         g_error ("unhandled type in custom attr");
9766                 }
9767                 str = type_get_qualified_name (mono_class_get_type(klass), NULL);
9768                 slen = strlen (str);
9769                 if ((p-buffer) + 10 + slen >= *buflen) {
9770                         char *newbuf;
9771                         *buflen *= 2;
9772                         *buflen += slen;
9773                         newbuf = g_realloc (buffer, *buflen);
9774                         p = newbuf + (p-buffer);
9775                         buffer = newbuf;
9776                 }
9777                 mono_metadata_encode_value (slen, p, &p);
9778                 memcpy (p, str, slen);
9779                 p += slen;
9780                 g_free (str);
9781                 simple_type = mono_class_enum_basetype (klass)->type;
9782                 goto handle_enum;
9783         }
9784         default:
9785                 g_error ("type 0x%02x not yet supported in custom attr encoder", simple_type);
9786         }
9787         *retp = p;
9788         *retbuffer = buffer;
9789 }
9790
9791 static void
9792 encode_field_or_prop_type (MonoType *type, char *p, char **retp)
9793 {
9794         if (type->type == MONO_TYPE_VALUETYPE && type->data.klass->enumtype) {
9795                 char *str = type_get_qualified_name (type, NULL);
9796                 int slen = strlen (str);
9797
9798                 *p++ = 0x55;
9799                 /*
9800                  * This seems to be optional...
9801                  * *p++ = 0x80;
9802                  */
9803                 mono_metadata_encode_value (slen, p, &p);
9804                 memcpy (p, str, slen);
9805                 p += slen;
9806                 g_free (str);
9807         } else if (type->type == MONO_TYPE_OBJECT) {
9808                 *p++ = 0x51;
9809         } else if (type->type == MONO_TYPE_CLASS) {
9810                 /* it should be a type: encode_cattr_value () has the check */
9811                 *p++ = 0x50;
9812         } else {
9813                 mono_metadata_encode_value (type->type, p, &p);
9814                 if (type->type == MONO_TYPE_SZARRAY)
9815                         /* See the examples in Partition VI, Annex B */
9816                         encode_field_or_prop_type (&type->data.klass->byval_arg, p, &p);
9817         }
9818
9819         *retp = p;
9820 }
9821
9822 #ifndef DISABLE_REFLECTION_EMIT
9823 static void
9824 encode_named_val (MonoReflectionAssembly *assembly, char *buffer, char *p, char **retbuffer, char **retp, guint32 *buflen, MonoType *type, char *name, MonoObject *value)
9825 {
9826         int len;
9827         /* Preallocate a large enough buffer */
9828         if (type->type == MONO_TYPE_VALUETYPE && type->data.klass->enumtype) {
9829                 char *str = type_get_qualified_name (type, NULL);
9830                 len = strlen (str);
9831                 g_free (str);
9832         } else if (type->type == MONO_TYPE_SZARRAY && type->data.klass->enumtype) {
9833                 char *str = type_get_qualified_name (&type->data.klass->byval_arg, NULL);
9834                 len = strlen (str);
9835                 g_free (str);
9836         } else {
9837                 len = 0;
9838         }
9839         len += strlen (name);
9840
9841         if ((p-buffer) + 20 + len >= *buflen) {
9842                 char *newbuf;
9843                 *buflen *= 2;
9844                 *buflen += len;
9845                 newbuf = g_realloc (buffer, *buflen);
9846                 p = newbuf + (p-buffer);
9847                 buffer = newbuf;
9848         }
9849
9850         encode_field_or_prop_type (type, p, &p);
9851
9852         len = strlen (name);
9853         mono_metadata_encode_value (len, p, &p);
9854         memcpy (p, name, len);
9855         p += len;
9856         encode_cattr_value (assembly->assembly, buffer, p, &buffer, &p, buflen, type, value, NULL);
9857         *retp = p;
9858         *retbuffer = buffer;
9859 }
9860
9861 /*
9862  * mono_reflection_get_custom_attrs_blob:
9863  * @ctor: custom attribute constructor
9864  * @ctorArgs: arguments o the constructor
9865  * @properties:
9866  * @propValues:
9867  * @fields:
9868  * @fieldValues:
9869  * 
9870  * Creates the blob of data that needs to be saved in the metadata and that represents
9871  * the custom attributed described by @ctor, @ctorArgs etc.
9872  * Returns: a Byte array representing the blob of data.
9873  */
9874 MonoArray*
9875 mono_reflection_get_custom_attrs_blob (MonoReflectionAssembly *assembly, MonoObject *ctor, MonoArray *ctorArgs, MonoArray *properties, MonoArray *propValues, MonoArray *fields, MonoArray* fieldValues) 
9876 {
9877         MonoArray *result;
9878         MonoMethodSignature *sig;
9879         MonoObject *arg;
9880         char *buffer, *p;
9881         guint32 buflen, i;
9882
9883         if (strcmp (ctor->vtable->klass->name, "MonoCMethod")) {
9884                 /* sig is freed later so allocate it in the heap */
9885                 sig = ctor_builder_to_signature (NULL, (MonoReflectionCtorBuilder*)ctor);
9886         } else {
9887                 sig = mono_method_signature (((MonoReflectionMethod*)ctor)->method);
9888         }
9889
9890         g_assert (mono_array_length (ctorArgs) == sig->param_count);
9891         buflen = 256;
9892         p = buffer = g_malloc (buflen);
9893         /* write the prolog */
9894         *p++ = 1;
9895         *p++ = 0;
9896         for (i = 0; i < sig->param_count; ++i) {
9897                 arg = mono_array_get (ctorArgs, MonoObject*, i);
9898                 encode_cattr_value (assembly->assembly, buffer, p, &buffer, &p, &buflen, sig->params [i], arg, NULL);
9899         }
9900         i = 0;
9901         if (properties)
9902                 i += mono_array_length (properties);
9903         if (fields)
9904                 i += mono_array_length (fields);
9905         *p++ = i & 0xff;
9906         *p++ = (i >> 8) & 0xff;
9907         if (properties) {
9908                 MonoObject *prop;
9909                 for (i = 0; i < mono_array_length (properties); ++i) {
9910                         MonoType *ptype;
9911                         char *pname;
9912
9913                         prop = mono_array_get (properties, gpointer, i);
9914                         get_prop_name_and_type (prop, &pname, &ptype);
9915                         *p++ = 0x54; /* PROPERTY signature */
9916                         encode_named_val (assembly, buffer, p, &buffer, &p, &buflen, ptype, pname, (MonoObject*)mono_array_get (propValues, gpointer, i));
9917                         g_free (pname);
9918                 }
9919         }
9920
9921         if (fields) {
9922                 MonoObject *field;
9923                 for (i = 0; i < mono_array_length (fields); ++i) {
9924                         MonoType *ftype;
9925                         char *fname;
9926
9927                         field = mono_array_get (fields, gpointer, i);
9928                         get_field_name_and_type (field, &fname, &ftype);
9929                         *p++ = 0x53; /* FIELD signature */
9930                         encode_named_val (assembly, buffer, p, &buffer, &p, &buflen, ftype, fname, (MonoObject*)mono_array_get (fieldValues, gpointer, i));
9931                         g_free (fname);
9932                 }
9933         }
9934
9935         g_assert (p - buffer <= buflen);
9936         buflen = p - buffer;
9937         result = mono_array_new (mono_domain_get (), mono_defaults.byte_class, buflen);
9938         p = mono_array_addr (result, char, 0);
9939         memcpy (p, buffer, buflen);
9940         g_free (buffer);
9941         if (strcmp (ctor->vtable->klass->name, "MonoCMethod"))
9942                 g_free (sig);
9943         return result;
9944 }
9945
9946 /*
9947  * mono_reflection_setup_internal_class:
9948  * @tb: a TypeBuilder object
9949  *
9950  * Creates a MonoClass that represents the TypeBuilder.
9951  * This is a trick that lets us simplify a lot of reflection code
9952  * (and will allow us to support Build and Run assemblies easier).
9953  */
9954 void
9955 mono_reflection_setup_internal_class (MonoReflectionTypeBuilder *tb)
9956 {
9957         MonoError error;
9958         MonoClass *klass, *parent;
9959
9960         RESOLVE_TYPE (tb->parent);
9961
9962         mono_loader_lock ();
9963
9964         if (tb->parent) {
9965                 /* check so we can compile corlib correctly */
9966                 if (strcmp (mono_object_class (tb->parent)->name, "TypeBuilder") == 0) {
9967                         /* mono_class_setup_mono_type () guaranteess type->data.klass is valid */
9968                         parent = mono_reflection_type_get_handle ((MonoReflectionType*)tb->parent)->data.klass;
9969                 } else {
9970                         parent = mono_class_from_mono_type (mono_reflection_type_get_handle ((MonoReflectionType*)tb->parent));
9971                 }
9972         } else {
9973                 parent = NULL;
9974         }
9975         
9976         /* the type has already being created: it means we just have to change the parent */
9977         if (tb->type.type) {
9978                 klass = mono_class_from_mono_type (tb->type.type);
9979                 klass->parent = NULL;
9980                 /* fool mono_class_setup_parent */
9981                 klass->supertypes = NULL;
9982                 mono_class_setup_parent (klass, parent);
9983                 mono_class_setup_mono_type (klass);
9984                 mono_loader_unlock ();
9985                 return;
9986         }
9987
9988         klass = mono_image_alloc0 (&tb->module->dynamic_image->image, sizeof (MonoClass));
9989
9990         klass->image = &tb->module->dynamic_image->image;
9991
9992         klass->inited = 1; /* we lie to the runtime */
9993         klass->name = mono_string_to_utf8_image (klass->image, tb->name, &error);
9994         if (!mono_error_ok (&error))
9995                 goto failure;
9996         klass->name_space = mono_string_to_utf8_image (klass->image, tb->nspace, &error);
9997         if (!mono_error_ok (&error))
9998                 goto failure;
9999         klass->type_token = MONO_TOKEN_TYPE_DEF | tb->table_idx;
10000         klass->flags = tb->attrs;
10001         
10002         mono_profiler_class_event (klass, MONO_PROFILE_START_LOAD);
10003
10004         klass->element_class = klass;
10005
10006         if (mono_class_get_ref_info (klass) == NULL) {
10007
10008                 mono_class_set_ref_info (klass, tb);
10009
10010                 /* Put into cache so mono_class_get_checked () will find it.
10011                 Skip nested types as those should not be available on the global scope. */
10012                 if (!tb->nesting_type)
10013                         mono_image_add_to_name_cache (klass->image, klass->name_space, klass->name, tb->table_idx);
10014
10015                 /*
10016                 We must register all types as we cannot rely on the name_cache hashtable since we find the class
10017                 by performing a mono_class_get which does the full resolution.
10018
10019                 Working around this semantics would require us to write a lot of code for no clear advantage.
10020                 */
10021                 mono_image_append_class_to_reflection_info_set (klass);
10022         } else {
10023                 g_assert (mono_class_get_ref_info (klass) == tb);
10024         }
10025
10026         mono_g_hash_table_insert (tb->module->dynamic_image->tokens,
10027                 GUINT_TO_POINTER (MONO_TOKEN_TYPE_DEF | tb->table_idx), tb);
10028
10029         if (parent != NULL) {
10030                 mono_class_setup_parent (klass, parent);
10031         } else if (strcmp (klass->name, "Object") == 0 && strcmp (klass->name_space, "System") == 0) {
10032                 const char *old_n = klass->name;
10033                 /* trick to get relative numbering right when compiling corlib */
10034                 klass->name = "BuildingObject";
10035                 mono_class_setup_parent (klass, mono_defaults.object_class);
10036                 klass->name = old_n;
10037         }
10038
10039         if ((!strcmp (klass->name, "ValueType") && !strcmp (klass->name_space, "System")) ||
10040                         (!strcmp (klass->name, "Object") && !strcmp (klass->name_space, "System")) ||
10041                         (!strcmp (klass->name, "Enum") && !strcmp (klass->name_space, "System"))) {
10042                 klass->instance_size = sizeof (MonoObject);
10043                 klass->size_inited = 1;
10044                 mono_class_setup_vtable_general (klass, NULL, 0, NULL);
10045         }
10046
10047         mono_class_setup_mono_type (klass);
10048
10049         mono_class_setup_supertypes (klass);
10050
10051         /*
10052          * FIXME: handle interfaces.
10053          */
10054
10055         tb->type.type = &klass->byval_arg;
10056
10057         if (tb->nesting_type) {
10058                 g_assert (tb->nesting_type->type);
10059                 klass->nested_in = mono_class_from_mono_type (mono_reflection_type_get_handle (tb->nesting_type));
10060         }
10061
10062         /*g_print ("setup %s as %s (%p)\n", klass->name, ((MonoObject*)tb)->vtable->klass->name, tb);*/
10063
10064         mono_profiler_class_loaded (klass, MONO_PROFILE_OK);
10065         
10066         mono_loader_unlock ();
10067         return;
10068
10069 failure:
10070         mono_loader_unlock ();
10071         mono_error_raise_exception (&error);
10072 }
10073
10074 /*
10075  * mono_reflection_setup_generic_class:
10076  * @tb: a TypeBuilder object
10077  *
10078  * Setup the generic class before adding the first generic parameter.
10079  */
10080 void
10081 mono_reflection_setup_generic_class (MonoReflectionTypeBuilder *tb)
10082 {
10083 }
10084
10085 /*
10086  * mono_reflection_create_generic_class:
10087  * @tb: a TypeBuilder object
10088  *
10089  * Creates the generic class after all generic parameters have been added.
10090  */
10091 void
10092 mono_reflection_create_generic_class (MonoReflectionTypeBuilder *tb)
10093 {
10094         MonoClass *klass;
10095         int count, i;
10096
10097         klass = mono_class_from_mono_type (tb->type.type);
10098
10099         count = tb->generic_params ? mono_array_length (tb->generic_params) : 0;
10100
10101         if (klass->generic_container || (count == 0))
10102                 return;
10103
10104         g_assert (tb->generic_container && (tb->generic_container->owner.klass == klass));
10105
10106         klass->generic_container = mono_image_alloc0 (klass->image, sizeof (MonoGenericContainer));
10107
10108         klass->generic_container->owner.klass = klass;
10109         klass->generic_container->type_argc = count;
10110         klass->generic_container->type_params = mono_image_alloc0 (klass->image, sizeof (MonoGenericParamFull) * count);
10111
10112         klass->is_generic = 1;
10113
10114         for (i = 0; i < count; i++) {
10115                 MonoReflectionGenericParam *gparam = mono_array_get (tb->generic_params, gpointer, i);
10116                 MonoGenericParamFull *param = (MonoGenericParamFull *) mono_reflection_type_get_handle ((MonoReflectionType*)gparam)->data.generic_param;
10117                 klass->generic_container->type_params [i] = *param;
10118                 /*Make sure we are a diferent type instance */
10119                 klass->generic_container->type_params [i].param.owner = klass->generic_container;
10120                 klass->generic_container->type_params [i].info.pklass = NULL;
10121                 klass->generic_container->type_params [i].info.flags = gparam->attrs;
10122
10123                 g_assert (klass->generic_container->type_params [i].param.owner);
10124         }
10125
10126         klass->generic_container->context.class_inst = mono_get_shared_generic_inst (klass->generic_container);
10127 }
10128
10129 /*
10130  * mono_reflection_create_internal_class:
10131  * @tb: a TypeBuilder object
10132  *
10133  * Actually create the MonoClass that is associated with the TypeBuilder.
10134  */
10135 void
10136 mono_reflection_create_internal_class (MonoReflectionTypeBuilder *tb)
10137 {
10138         MonoClass *klass;
10139
10140         klass = mono_class_from_mono_type (tb->type.type);
10141
10142         mono_loader_lock ();
10143         if (klass->enumtype && mono_class_enum_basetype (klass) == NULL) {
10144                 MonoReflectionFieldBuilder *fb;
10145                 MonoClass *ec;
10146                 MonoType *enum_basetype;
10147
10148                 g_assert (tb->fields != NULL);
10149                 g_assert (mono_array_length (tb->fields) >= 1);
10150
10151                 fb = mono_array_get (tb->fields, MonoReflectionFieldBuilder*, 0);
10152
10153                 if (!mono_type_is_valid_enum_basetype (mono_reflection_type_get_handle ((MonoReflectionType*)fb->type))) {
10154                         mono_loader_unlock ();
10155                         return;
10156                 }
10157
10158                 enum_basetype = mono_reflection_type_get_handle ((MonoReflectionType*)fb->type);
10159                 klass->element_class = mono_class_from_mono_type (enum_basetype);
10160                 if (!klass->element_class)
10161                         klass->element_class = mono_class_from_mono_type (enum_basetype);
10162
10163                 /*
10164                  * get the element_class from the current corlib.
10165                  */
10166                 ec = default_class_from_mono_type (enum_basetype);
10167                 klass->instance_size = ec->instance_size;
10168                 klass->size_inited = 1;
10169                 /* 
10170                  * this is almost safe to do with enums and it's needed to be able
10171                  * to create objects of the enum type (for use in SetConstant).
10172                  */
10173                 /* FIXME: Does this mean enums can't have method overrides ? */
10174                 mono_class_setup_vtable_general (klass, NULL, 0, NULL);
10175         }
10176         mono_loader_unlock ();
10177 }
10178
10179 static MonoMarshalSpec*
10180 mono_marshal_spec_from_builder (MonoImage *image, MonoAssembly *assembly,
10181                                                                 MonoReflectionMarshal *minfo)
10182 {
10183         MonoMarshalSpec *res;
10184
10185         res = image_g_new0 (image, MonoMarshalSpec, 1);
10186         res->native = minfo->type;
10187
10188         switch (minfo->type) {
10189         case MONO_NATIVE_LPARRAY:
10190                 res->data.array_data.elem_type = minfo->eltype;
10191                 if (minfo->has_size) {
10192                         res->data.array_data.param_num = minfo->param_num;
10193                         res->data.array_data.num_elem = minfo->count;
10194                         res->data.array_data.elem_mult = minfo->param_num == -1 ? 0 : 1;
10195                 }
10196                 else {
10197                         res->data.array_data.param_num = -1;
10198                         res->data.array_data.num_elem = -1;
10199                         res->data.array_data.elem_mult = -1;
10200                 }
10201                 break;
10202
10203         case MONO_NATIVE_BYVALTSTR:
10204         case MONO_NATIVE_BYVALARRAY:
10205                 res->data.array_data.num_elem = minfo->count;
10206                 break;
10207
10208         case MONO_NATIVE_CUSTOM:
10209                 if (minfo->marshaltyperef)
10210                         res->data.custom_data.custom_name =
10211                                 type_get_fully_qualified_name (mono_reflection_type_get_handle ((MonoReflectionType*)minfo->marshaltyperef));
10212                 if (minfo->mcookie)
10213                         res->data.custom_data.cookie = mono_string_to_utf8 (minfo->mcookie);
10214                 break;
10215
10216         default:
10217                 break;
10218         }
10219
10220         return res;
10221 }
10222 #endif /* !DISABLE_REFLECTION_EMIT */
10223
10224 MonoReflectionMarshalAsAttribute*
10225 mono_reflection_marshal_as_attribute_from_marshal_spec (MonoDomain *domain, MonoClass *klass,
10226                                                                                    MonoMarshalSpec *spec)
10227 {
10228         static MonoClass *System_Reflection_Emit_MarshalAsAttribute;
10229         MonoReflectionMarshalAsAttribute *minfo;
10230         MonoType *mtype;
10231
10232         if (!System_Reflection_Emit_MarshalAsAttribute) {
10233                 System_Reflection_Emit_MarshalAsAttribute = mono_class_from_name (
10234                    mono_defaults.corlib, "System.Runtime.InteropServices", "MarshalAsAttribute");
10235                 g_assert (System_Reflection_Emit_MarshalAsAttribute);
10236         }
10237
10238         minfo = (MonoReflectionMarshalAsAttribute*)mono_object_new (domain, System_Reflection_Emit_MarshalAsAttribute);
10239         minfo->utype = spec->native;
10240
10241         switch (minfo->utype) {
10242         case MONO_NATIVE_LPARRAY:
10243                 minfo->array_subtype = spec->data.array_data.elem_type;
10244                 minfo->size_const = spec->data.array_data.num_elem;
10245                 if (spec->data.array_data.param_num != -1)
10246                         minfo->size_param_index = spec->data.array_data.param_num;
10247                 break;
10248
10249         case MONO_NATIVE_BYVALTSTR:
10250         case MONO_NATIVE_BYVALARRAY:
10251                 minfo->size_const = spec->data.array_data.num_elem;
10252                 break;
10253
10254         case MONO_NATIVE_CUSTOM:
10255                 if (spec->data.custom_data.custom_name) {
10256                         mtype = mono_reflection_type_from_name (spec->data.custom_data.custom_name, klass->image);
10257                         if (mtype)
10258                                 MONO_OBJECT_SETREF (minfo, marshal_type_ref, mono_type_get_object (domain, mtype));
10259
10260                         MONO_OBJECT_SETREF (minfo, marshal_type, mono_string_new (domain, spec->data.custom_data.custom_name));
10261                 }
10262                 if (spec->data.custom_data.cookie)
10263                         MONO_OBJECT_SETREF (minfo, marshal_cookie, mono_string_new (domain, spec->data.custom_data.cookie));
10264                 break;
10265
10266         default:
10267                 break;
10268         }
10269
10270         return minfo;
10271 }
10272
10273 #ifndef DISABLE_REFLECTION_EMIT
10274 static MonoMethod*
10275 reflection_methodbuilder_to_mono_method (MonoClass *klass,
10276                                          ReflectionMethodBuilder *rmb,
10277                                          MonoMethodSignature *sig)
10278 {
10279         MonoError error;
10280         MonoMethod *m;
10281         MonoMethodWrapper *wrapperm;
10282         MonoMarshalSpec **specs;
10283         MonoReflectionMethodAux *method_aux;
10284         MonoImage *image;
10285         gboolean dynamic;
10286         int i;
10287
10288         mono_error_init (&error);
10289         /*
10290          * Methods created using a MethodBuilder should have their memory allocated
10291          * inside the image mempool, while dynamic methods should have their memory
10292          * malloc'd.
10293          */
10294         dynamic = rmb->refs != NULL;
10295         image = dynamic ? NULL : klass->image;
10296
10297         if (!dynamic)
10298                 g_assert (!klass->generic_class);
10299
10300         mono_loader_lock ();
10301
10302         if ((rmb->attrs & METHOD_ATTRIBUTE_PINVOKE_IMPL) ||
10303                         (rmb->iattrs & METHOD_IMPL_ATTRIBUTE_INTERNAL_CALL))
10304                 m = (MonoMethod *)image_g_new0 (image, MonoMethodPInvoke, 1);
10305         else
10306                 m = (MonoMethod *)image_g_new0 (image, MonoMethodWrapper, 1);
10307
10308         wrapperm = (MonoMethodWrapper*)m;
10309
10310         m->dynamic = dynamic;
10311         m->slot = -1;
10312         m->flags = rmb->attrs;
10313         m->iflags = rmb->iattrs;
10314         m->name = mono_string_to_utf8_image_ignore (image, rmb->name);
10315         m->klass = klass;
10316         m->signature = sig;
10317         m->sre_method = TRUE;
10318         m->skip_visibility = rmb->skip_visibility;
10319         if (rmb->table_idx)
10320                 m->token = MONO_TOKEN_METHOD_DEF | (*rmb->table_idx);
10321
10322         if (m->iflags & METHOD_IMPL_ATTRIBUTE_INTERNAL_CALL) {
10323                 if (klass == mono_defaults.string_class && !strcmp (m->name, ".ctor"))
10324                         m->string_ctor = 1;
10325
10326                 m->signature->pinvoke = 1;
10327         } else if (m->flags & METHOD_ATTRIBUTE_PINVOKE_IMPL) {
10328                 m->signature->pinvoke = 1;
10329
10330                 method_aux = image_g_new0 (image, MonoReflectionMethodAux, 1);
10331
10332                 method_aux->dllentry = rmb->dllentry ? mono_string_to_utf8_image (image, rmb->dllentry, &error) : image_strdup (image, m->name);
10333                 g_assert (mono_error_ok (&error));
10334                 method_aux->dll = mono_string_to_utf8_image (image, rmb->dll, &error);
10335                 g_assert (mono_error_ok (&error));
10336                 
10337                 ((MonoMethodPInvoke*)m)->piflags = (rmb->native_cc << 8) | (rmb->charset ? (rmb->charset - 1) * 2 : 0) | rmb->extra_flags;
10338
10339                 if (image_is_dynamic (klass->image))
10340                         g_hash_table_insert (((MonoDynamicImage*)klass->image)->method_aux_hash, m, method_aux);
10341
10342                 mono_loader_unlock ();
10343
10344                 return m;
10345         } else if (!(m->flags & METHOD_ATTRIBUTE_ABSTRACT) &&
10346                            !(m->iflags & METHOD_IMPL_ATTRIBUTE_RUNTIME)) {
10347                 MonoMethodHeader *header;
10348                 guint32 code_size;
10349                 gint32 max_stack, i;
10350                 gint32 num_locals = 0;
10351                 gint32 num_clauses = 0;
10352                 guint8 *code;
10353
10354                 if (rmb->ilgen) {
10355                         code = mono_array_addr (rmb->ilgen->code, guint8, 0);
10356                         code_size = rmb->ilgen->code_len;
10357                         max_stack = rmb->ilgen->max_stack;
10358                         num_locals = rmb->ilgen->locals ? mono_array_length (rmb->ilgen->locals) : 0;
10359                         if (rmb->ilgen->ex_handlers)
10360                                 num_clauses = method_count_clauses (rmb->ilgen);
10361                 } else {
10362                         if (rmb->code) {
10363                                 code = mono_array_addr (rmb->code, guint8, 0);
10364                                 code_size = mono_array_length (rmb->code);
10365                                 /* we probably need to run a verifier on the code... */
10366                                 max_stack = 8; 
10367                         }
10368                         else {
10369                                 code = NULL;
10370                                 code_size = 0;
10371                                 max_stack = 8;
10372                         }
10373                 }
10374
10375                 header = image_g_malloc0 (image, MONO_SIZEOF_METHOD_HEADER + num_locals * sizeof (MonoType*));
10376                 header->code_size = code_size;
10377                 header->code = image_g_malloc (image, code_size);
10378                 memcpy ((char*)header->code, code, code_size);
10379                 header->max_stack = max_stack;
10380                 header->init_locals = rmb->init_locals;
10381                 header->num_locals = num_locals;
10382
10383                 for (i = 0; i < num_locals; ++i) {
10384                         MonoReflectionLocalBuilder *lb = 
10385                                 mono_array_get (rmb->ilgen->locals, MonoReflectionLocalBuilder*, i);
10386
10387                         header->locals [i] = image_g_new0 (image, MonoType, 1);
10388                         memcpy (header->locals [i], mono_reflection_type_get_handle ((MonoReflectionType*)lb->type), MONO_SIZEOF_TYPE);
10389                 }
10390
10391                 header->num_clauses = num_clauses;
10392                 if (num_clauses) {
10393                         header->clauses = method_encode_clauses (image, (MonoDynamicImage*)klass->image,
10394                                  rmb->ilgen, num_clauses);
10395                 }
10396
10397                 wrapperm->header = header;
10398         }
10399
10400         if (rmb->generic_params) {
10401                 int count = mono_array_length (rmb->generic_params);
10402                 MonoGenericContainer *container = rmb->generic_container;
10403
10404                 g_assert (container);
10405
10406                 container->type_argc = count;
10407                 container->type_params = image_g_new0 (image, MonoGenericParamFull, count);
10408                 container->owner.method = m;
10409
10410                 m->is_generic = TRUE;
10411                 mono_method_set_generic_container (m, container);
10412
10413                 for (i = 0; i < count; i++) {
10414                         MonoReflectionGenericParam *gp =
10415                                 mono_array_get (rmb->generic_params, MonoReflectionGenericParam*, i);
10416                         MonoGenericParamFull *param = (MonoGenericParamFull *) mono_reflection_type_get_handle ((MonoReflectionType*)gp)->data.generic_param;
10417                         container->type_params [i] = *param;
10418                 }
10419
10420                 /*
10421                  * The method signature might have pointers to generic parameters that belong to other methods.
10422                  * This is a valid SRE case, but the resulting method signature must be encoded using the proper
10423                  * generic parameters.
10424                  */
10425                 for (i = 0; i < m->signature->param_count; ++i) {
10426                         MonoType *t = m->signature->params [i];
10427                         if (t->type == MONO_TYPE_MVAR) {
10428                                 MonoGenericParam *gparam =  t->data.generic_param;
10429                                 if (gparam->num < count) {
10430                                         m->signature->params [i] = mono_metadata_type_dup (image, m->signature->params [i]);
10431                                         m->signature->params [i]->data.generic_param = mono_generic_container_get_param (container, gparam->num);
10432                                 }
10433
10434                         }
10435                 }
10436
10437                 if (klass->generic_container) {
10438                         container->parent = klass->generic_container;
10439                         container->context.class_inst = klass->generic_container->context.class_inst;
10440                 }
10441                 container->context.method_inst = mono_get_shared_generic_inst (container);
10442         }
10443
10444         if (rmb->refs) {
10445                 MonoMethodWrapper *mw = (MonoMethodWrapper*)m;
10446                 int i;
10447                 void **data;
10448
10449                 m->wrapper_type = MONO_WRAPPER_DYNAMIC_METHOD;
10450
10451                 mw->method_data = data = image_g_new (image, gpointer, rmb->nrefs + 1);
10452                 data [0] = GUINT_TO_POINTER (rmb->nrefs);
10453                 for (i = 0; i < rmb->nrefs; ++i)
10454                         data [i + 1] = rmb->refs [i];
10455         }
10456
10457         method_aux = NULL;
10458
10459         /* Parameter info */
10460         if (rmb->pinfo) {
10461                 if (!method_aux)
10462                         method_aux = image_g_new0 (image, MonoReflectionMethodAux, 1);
10463                 method_aux->param_names = image_g_new0 (image, char *, mono_method_signature (m)->param_count + 1);
10464                 for (i = 0; i <= m->signature->param_count; ++i) {
10465                         MonoReflectionParamBuilder *pb;
10466                         if ((pb = mono_array_get (rmb->pinfo, MonoReflectionParamBuilder*, i))) {
10467                                 if ((i > 0) && (pb->attrs)) {
10468                                         /* Make a copy since it might point to a shared type structure */
10469                                         m->signature->params [i - 1] = mono_metadata_type_dup (klass->image, m->signature->params [i - 1]);
10470                                         m->signature->params [i - 1]->attrs = pb->attrs;
10471                                 }
10472
10473                                 if (pb->attrs & PARAM_ATTRIBUTE_HAS_DEFAULT) {
10474                                         MonoDynamicImage *assembly;
10475                                         guint32 idx, def_type, len;
10476                                         char *p;
10477                                         const char *p2;
10478
10479                                         if (!method_aux->param_defaults) {
10480                                                 method_aux->param_defaults = image_g_new0 (image, guint8*, m->signature->param_count + 1);
10481                                                 method_aux->param_default_types = image_g_new0 (image, guint32, m->signature->param_count + 1);
10482                                         }
10483                                         assembly = (MonoDynamicImage*)klass->image;
10484                                         idx = encode_constant (assembly, pb->def_value, &def_type);
10485                                         /* Copy the data from the blob since it might get realloc-ed */
10486                                         p = assembly->blob.data + idx;
10487                                         len = mono_metadata_decode_blob_size (p, &p2);
10488                                         len += p2 - p;
10489                                         method_aux->param_defaults [i] = image_g_malloc (image, len);
10490                                         method_aux->param_default_types [i] = def_type;
10491                                         memcpy ((gpointer)method_aux->param_defaults [i], p, len);
10492                                 }
10493
10494                                 if (pb->name) {
10495                                         method_aux->param_names [i] = mono_string_to_utf8_image (image, pb->name, &error);
10496                                         g_assert (mono_error_ok (&error));
10497                                 }
10498                                 if (pb->cattrs) {
10499                                         if (!method_aux->param_cattr)
10500                                                 method_aux->param_cattr = image_g_new0 (image, MonoCustomAttrInfo*, m->signature->param_count + 1);
10501                                         method_aux->param_cattr [i] = mono_custom_attrs_from_builders (image, klass->image, pb->cattrs);
10502                                 }
10503                         }
10504                 }
10505         }
10506
10507         /* Parameter marshalling */
10508         specs = NULL;
10509         if (rmb->pinfo)         
10510                 for (i = 0; i < mono_array_length (rmb->pinfo); ++i) {
10511                         MonoReflectionParamBuilder *pb;
10512                         if ((pb = mono_array_get (rmb->pinfo, MonoReflectionParamBuilder*, i))) {
10513                                 if (pb->marshal_info) {
10514                                         if (specs == NULL)
10515                                                 specs = image_g_new0 (image, MonoMarshalSpec*, sig->param_count + 1);
10516                                         specs [pb->position] = 
10517                                                 mono_marshal_spec_from_builder (image, klass->image->assembly, pb->marshal_info);
10518                                 }
10519                         }
10520                 }
10521         if (specs != NULL) {
10522                 if (!method_aux)
10523                         method_aux = image_g_new0 (image, MonoReflectionMethodAux, 1);
10524                 method_aux->param_marshall = specs;
10525         }
10526
10527         if (image_is_dynamic (klass->image) && method_aux)
10528                 g_hash_table_insert (((MonoDynamicImage*)klass->image)->method_aux_hash, m, method_aux);
10529
10530         mono_loader_unlock ();
10531
10532         return m;
10533 }       
10534
10535 static MonoMethod*
10536 ctorbuilder_to_mono_method (MonoClass *klass, MonoReflectionCtorBuilder* mb)
10537 {
10538         ReflectionMethodBuilder rmb;
10539         MonoMethodSignature *sig;
10540
10541         mono_loader_lock ();
10542         sig = ctor_builder_to_signature (klass->image, mb);
10543         mono_loader_unlock ();
10544
10545         reflection_methodbuilder_from_ctor_builder (&rmb, mb);
10546
10547         mb->mhandle = reflection_methodbuilder_to_mono_method (klass, &rmb, sig);
10548         mono_save_custom_attrs (klass->image, mb->mhandle, mb->cattrs);
10549
10550         /* If we are in a generic class, we might be called multiple times from inflate_method */
10551         if (!((MonoDynamicImage*)(MonoDynamicImage*)klass->image)->save && !klass->generic_container) {
10552                 /* ilgen is no longer needed */
10553                 mb->ilgen = NULL;
10554         }
10555
10556         return mb->mhandle;
10557 }
10558
10559 static MonoMethod*
10560 methodbuilder_to_mono_method (MonoClass *klass, MonoReflectionMethodBuilder* mb)
10561 {
10562         ReflectionMethodBuilder rmb;
10563         MonoMethodSignature *sig;
10564
10565         mono_loader_lock ();
10566         sig = method_builder_to_signature (klass->image, mb);
10567         mono_loader_unlock ();
10568
10569         reflection_methodbuilder_from_method_builder (&rmb, mb);
10570
10571         mb->mhandle = reflection_methodbuilder_to_mono_method (klass, &rmb, sig);
10572         mono_save_custom_attrs (klass->image, mb->mhandle, mb->cattrs);
10573
10574         /* If we are in a generic class, we might be called multiple times from inflate_method */
10575         if (!((MonoDynamicImage*)(MonoDynamicImage*)klass->image)->save && !klass->generic_container) {
10576                 /* ilgen is no longer needed */
10577                 mb->ilgen = NULL;
10578         }
10579         return mb->mhandle;
10580 }
10581
10582 static MonoClassField*
10583 fieldbuilder_to_mono_class_field (MonoClass *klass, MonoReflectionFieldBuilder* fb)
10584 {
10585         MonoClassField *field;
10586         MonoType *custom;
10587         MonoError error;
10588
10589         field = g_new0 (MonoClassField, 1);
10590
10591         field->name = mono_string_to_utf8_image (klass->image, fb->name, &error);
10592         g_assert (mono_error_ok (&error));
10593         if (fb->attrs || fb->modreq || fb->modopt) {
10594                 field->type = mono_metadata_type_dup (NULL, mono_reflection_type_get_handle ((MonoReflectionType*)fb->type));
10595                 field->type->attrs = fb->attrs;
10596
10597                 g_assert (image_is_dynamic (klass->image));
10598                 custom = add_custom_modifiers ((MonoDynamicImage*)klass->image, field->type, fb->modreq, fb->modopt);
10599                 g_free (field->type);
10600                 field->type = mono_metadata_type_dup (klass->image, custom);
10601                 g_free (custom);
10602         } else {
10603                 field->type = mono_reflection_type_get_handle ((MonoReflectionType*)fb->type);
10604         }
10605         if (fb->offset != -1)
10606                 field->offset = fb->offset;
10607         field->parent = klass;
10608         mono_save_custom_attrs (klass->image, field, fb->cattrs);
10609
10610         // FIXME: Can't store fb->def_value/RVA, is it needed for field_on_insts ?
10611
10612         return field;
10613 }
10614 #endif
10615
10616 MonoType*
10617 mono_reflection_bind_generic_parameters (MonoReflectionType *type, int type_argc, MonoType **types)
10618 {
10619         MonoClass *klass;
10620         MonoReflectionTypeBuilder *tb = NULL;
10621         gboolean is_dynamic = FALSE;
10622         MonoClass *geninst;
10623
10624         mono_loader_lock ();
10625
10626         if (is_sre_type_builder (mono_object_class (type))) {
10627                 tb = (MonoReflectionTypeBuilder *) type;
10628
10629                 is_dynamic = TRUE;
10630         } else if (is_sre_generic_instance (mono_object_class (type))) {
10631                 MonoReflectionGenericClass *rgi = (MonoReflectionGenericClass *) type;
10632                 MonoReflectionType *gtd = rgi->generic_type;
10633
10634                 if (is_sre_type_builder (mono_object_class (gtd))) {
10635                         tb = (MonoReflectionTypeBuilder *)gtd;
10636                         is_dynamic = TRUE;
10637                 }
10638         }
10639
10640         /* FIXME: fix the CreateGenericParameters protocol to avoid the two stage setup of TypeBuilders */
10641         if (tb && tb->generic_container)
10642                 mono_reflection_create_generic_class (tb);
10643
10644         klass = mono_class_from_mono_type (mono_reflection_type_get_handle (type));
10645         if (!klass->generic_container) {
10646                 mono_loader_unlock ();
10647                 return NULL;
10648         }
10649
10650         if (klass->wastypebuilder) {
10651                 tb = (MonoReflectionTypeBuilder *) mono_class_get_ref_info (klass);
10652
10653                 is_dynamic = TRUE;
10654         }
10655
10656         mono_loader_unlock ();
10657
10658         geninst = mono_class_bind_generic_parameters (klass, type_argc, types, is_dynamic);
10659
10660         return &geninst->byval_arg;
10661 }
10662
10663 MonoClass*
10664 mono_class_bind_generic_parameters (MonoClass *klass, int type_argc, MonoType **types, gboolean is_dynamic)
10665 {
10666         MonoGenericClass *gclass;
10667         MonoGenericInst *inst;
10668
10669         g_assert (klass->generic_container);
10670
10671         inst = mono_metadata_get_generic_inst (type_argc, types);
10672         gclass = mono_metadata_lookup_generic_class (klass, inst, is_dynamic);
10673
10674         return mono_generic_class_get_class (gclass);
10675 }
10676
10677 MonoReflectionMethod*
10678 mono_reflection_bind_generic_method_parameters (MonoReflectionMethod *rmethod, MonoArray *types)
10679 {
10680         MonoError error;
10681         MonoClass *klass;
10682         MonoMethod *method, *inflated;
10683         MonoMethodInflated *imethod;
10684         MonoGenericContext tmp_context;
10685         MonoGenericInst *ginst;
10686         MonoType **type_argv;
10687         int count, i;
10688
10689         /*FIXME but this no longer should happen*/
10690         if (!strcmp (rmethod->object.vtable->klass->name, "MethodBuilder")) {
10691 #ifndef DISABLE_REFLECTION_EMIT
10692                 MonoReflectionMethodBuilder *mb = NULL;
10693                 MonoReflectionTypeBuilder *tb;
10694                 MonoClass *klass;
10695
10696                 mb = (MonoReflectionMethodBuilder *) rmethod;
10697                 tb = (MonoReflectionTypeBuilder *) mb->type;
10698                 klass = mono_class_from_mono_type (mono_reflection_type_get_handle ((MonoReflectionType*)tb));
10699
10700                 method = methodbuilder_to_mono_method (klass, mb);
10701 #else
10702                 g_assert_not_reached ();
10703                 method = NULL;
10704 #endif
10705         } else {
10706                 method = rmethod->method;
10707         }
10708
10709         klass = method->klass;
10710
10711         if (method->is_inflated)
10712                 method = ((MonoMethodInflated *) method)->declaring;
10713
10714         count = mono_method_signature (method)->generic_param_count;
10715         if (count != mono_array_length (types))
10716                 return NULL;
10717
10718         type_argv = g_new0 (MonoType *, count);
10719         for (i = 0; i < count; i++) {
10720                 MonoReflectionType *garg = mono_array_get (types, gpointer, i);
10721                 type_argv [i] = mono_reflection_type_get_handle (garg);
10722         }
10723         ginst = mono_metadata_get_generic_inst (count, type_argv);
10724         g_free (type_argv);
10725
10726         tmp_context.class_inst = klass->generic_class ? klass->generic_class->context.class_inst : NULL;
10727         tmp_context.method_inst = ginst;
10728
10729         inflated = mono_class_inflate_generic_method_checked (method, &tmp_context, &error);
10730         g_assert (mono_error_ok (&error)); /* FIXME don't swallow the error */
10731         imethod = (MonoMethodInflated *) inflated;
10732
10733         /*FIXME but I think this is no longer necessary*/
10734         if (image_is_dynamic (method->klass->image)) {
10735                 MonoDynamicImage *image = (MonoDynamicImage*)method->klass->image;
10736                 /*
10737                  * This table maps metadata structures representing inflated methods/fields
10738                  * to the reflection objects representing their generic definitions.
10739                  */
10740                 mono_image_lock ((MonoImage*)image);
10741                 mono_g_hash_table_insert (image->generic_def_objects, imethod, rmethod);
10742                 mono_image_unlock ((MonoImage*)image);
10743         }
10744
10745         if (!mono_verifier_is_method_valid_generic_instantiation (inflated))
10746                 mono_raise_exception (mono_get_exception_argument ("typeArguments", "Invalid generic arguments"));
10747         
10748         return mono_method_get_object (mono_object_domain (rmethod), inflated, NULL);
10749 }
10750
10751 #ifndef DISABLE_REFLECTION_EMIT
10752
10753 static MonoMethod *
10754 inflate_mono_method (MonoClass *klass, MonoMethod *method, MonoObject *obj)
10755 {
10756         MonoMethodInflated *imethod;
10757         MonoGenericContext *context;
10758         int i;
10759
10760         /*
10761          * With generic code sharing the klass might not be inflated.
10762          * This can happen because classes inflated with their own
10763          * type arguments are "normalized" to the uninflated class.
10764          */
10765         if (!klass->generic_class)
10766                 return method;
10767
10768         context = mono_class_get_context (klass);
10769
10770         if (klass->method.count && klass->methods) {
10771                 /* Find the already created inflated method */
10772                 for (i = 0; i < klass->method.count; ++i) {
10773                         g_assert (klass->methods [i]->is_inflated);
10774                         if (((MonoMethodInflated*)klass->methods [i])->declaring == method)
10775                                 break;
10776                 }
10777                 g_assert (i < klass->method.count);
10778                 imethod = (MonoMethodInflated*)klass->methods [i];
10779         } else {
10780                 MonoError error;
10781                 imethod = (MonoMethodInflated *) mono_class_inflate_generic_method_full_checked (method, klass, context, &error);
10782                 g_assert (mono_error_ok (&error)); /* FIXME don't swallow the error */
10783         }
10784
10785         if (method->is_generic && image_is_dynamic (method->klass->image)) {
10786                 MonoDynamicImage *image = (MonoDynamicImage*)method->klass->image;
10787
10788                 mono_image_lock ((MonoImage*)image);
10789                 mono_g_hash_table_insert (image->generic_def_objects, imethod, obj);
10790                 mono_image_unlock ((MonoImage*)image);
10791         }
10792         return (MonoMethod *) imethod;
10793 }
10794
10795 static MonoMethod *
10796 inflate_method (MonoReflectionType *type, MonoObject *obj)
10797 {
10798         MonoMethod *method;
10799         MonoClass *gklass;
10800
10801         MonoClass *type_class = mono_object_class (type);
10802
10803         if (is_sre_generic_instance (type_class)) {
10804                 MonoReflectionGenericClass *mgc = (MonoReflectionGenericClass*)type;
10805                 gklass = mono_class_from_mono_type (mono_reflection_type_get_handle ((MonoReflectionType*)mgc->generic_type));
10806         } else if (is_sre_type_builder (type_class)) {
10807                 gklass = mono_class_from_mono_type (mono_reflection_type_get_handle (type));
10808         } else if (type->type) {
10809                 gklass = mono_class_from_mono_type (type->type);
10810                 gklass = mono_class_get_generic_type_definition (gklass);
10811         } else {
10812                 g_error ("Can't handle type %s", mono_type_get_full_name (mono_object_class (type)));
10813         }
10814
10815         if (!strcmp (obj->vtable->klass->name, "MethodBuilder"))
10816                 if (((MonoReflectionMethodBuilder*)obj)->mhandle)
10817                         method = ((MonoReflectionMethodBuilder*)obj)->mhandle;
10818                 else
10819                         method = methodbuilder_to_mono_method (gklass, (MonoReflectionMethodBuilder *) obj);
10820         else if (!strcmp (obj->vtable->klass->name, "ConstructorBuilder"))
10821                 method = ctorbuilder_to_mono_method (gklass, (MonoReflectionCtorBuilder *) obj);
10822         else if (!strcmp (obj->vtable->klass->name, "MonoMethod") || !strcmp (obj->vtable->klass->name, "MonoCMethod"))
10823                 method = ((MonoReflectionMethod *) obj)->method;
10824         else {
10825                 method = NULL; /* prevent compiler warning */
10826                 g_error ("can't handle type %s", obj->vtable->klass->name);
10827         }
10828
10829         return inflate_mono_method (mono_class_from_mono_type (mono_reflection_type_get_handle ((MonoReflectionType*)type)), method, obj);
10830 }
10831
10832 /*TODO avoid saving custom attrs for generic classes as it's enough to have them on the generic type definition.*/
10833 void
10834 mono_reflection_generic_class_initialize (MonoReflectionGenericClass *type, MonoArray *fields)
10835 {
10836         MonoGenericClass *gclass;
10837         MonoDynamicGenericClass *dgclass;
10838         MonoClass *klass, *gklass;
10839         MonoType *gtype;
10840         int i;
10841
10842         gtype = mono_reflection_type_get_handle ((MonoReflectionType*)type);
10843         klass = mono_class_from_mono_type (gtype);
10844         g_assert (gtype->type == MONO_TYPE_GENERICINST);
10845         gclass = gtype->data.generic_class;
10846
10847         if (!gclass->is_dynamic)
10848                 return;
10849
10850         dgclass = (MonoDynamicGenericClass *) gclass;
10851
10852         if (dgclass->initialized)
10853                 return;
10854
10855         gklass = gclass->container_class;
10856         mono_class_init (gklass);
10857
10858         dgclass->count_fields = fields ? mono_array_length (fields) : 0;
10859
10860         dgclass->fields = mono_image_set_new0 (gclass->owner, MonoClassField, dgclass->count_fields);
10861         dgclass->field_objects = mono_image_set_new0 (gclass->owner, MonoObject*, dgclass->count_fields);
10862         dgclass->field_generic_types = mono_image_set_new0 (gclass->owner, MonoType*, dgclass->count_fields);
10863
10864         for (i = 0; i < dgclass->count_fields; i++) {
10865                 MonoObject *obj = mono_array_get (fields, gpointer, i);
10866                 MonoClassField *field, *inflated_field = NULL;
10867
10868                 if (!strcmp (obj->vtable->klass->name, "FieldBuilder"))
10869                         inflated_field = field = fieldbuilder_to_mono_class_field (klass, (MonoReflectionFieldBuilder *) obj);
10870                 else if (!strcmp (obj->vtable->klass->name, "MonoField"))
10871                         field = ((MonoReflectionField *) obj)->field;
10872                 else {
10873                         field = NULL; /* prevent compiler warning */
10874                         g_assert_not_reached ();
10875                 }
10876
10877                 dgclass->fields [i] = *field;
10878                 dgclass->fields [i].parent = klass;
10879                 dgclass->fields [i].type = mono_class_inflate_generic_type (
10880                         field->type, mono_generic_class_get_context ((MonoGenericClass *) dgclass));
10881                 dgclass->field_generic_types [i] = field->type;
10882                 MONO_GC_REGISTER_ROOT_IF_MOVING (dgclass->field_objects [i]);
10883                 dgclass->field_objects [i] = obj;
10884
10885                 if (inflated_field) {
10886                         g_free (inflated_field);
10887                 } else {
10888                         dgclass->fields [i].name = mono_image_set_strdup (gclass->owner, dgclass->fields [i].name);
10889                 }
10890         }
10891
10892         dgclass->initialized = TRUE;
10893 }
10894
10895 void
10896 mono_reflection_free_dynamic_generic_class (MonoGenericClass *gclass)
10897 {
10898         MonoDynamicGenericClass *dgclass;
10899         int i;
10900
10901         g_assert (gclass->is_dynamic);
10902
10903         dgclass = (MonoDynamicGenericClass *)gclass;
10904
10905         for (i = 0; i < dgclass->count_fields; ++i) {
10906                 MonoClassField *field = dgclass->fields + i;
10907                 mono_metadata_free_type (field->type);
10908                 MONO_GC_UNREGISTER_ROOT_IF_MOVING (dgclass->field_objects [i]);
10909         }
10910 }
10911
10912 static void
10913 fix_partial_generic_class (MonoClass *klass)
10914 {
10915         MonoClass *gklass = klass->generic_class->container_class;
10916         MonoDynamicGenericClass *dgclass;
10917         int i;
10918
10919         if (klass->wastypebuilder)
10920                 return;
10921
10922         dgclass = (MonoDynamicGenericClass *)  klass->generic_class;
10923         if (klass->parent != gklass->parent) {
10924                 MonoError error;
10925                 MonoType *parent_type = mono_class_inflate_generic_type_checked (&gklass->parent->byval_arg, &klass->generic_class->context, &error);
10926                 if (mono_error_ok (&error)) {
10927                         MonoClass *parent = mono_class_from_mono_type (parent_type);
10928                         mono_metadata_free_type (parent_type);
10929                         if (parent != klass->parent) {
10930                                 /*fool mono_class_setup_parent*/
10931                                 klass->supertypes = NULL;
10932                                 mono_class_setup_parent (klass, parent);
10933                         }
10934                 } else {
10935                         mono_class_set_failure (klass, MONO_EXCEPTION_TYPE_LOAD, NULL);
10936                         mono_error_cleanup (&error);
10937                         if (gklass->wastypebuilder)
10938                                 klass->wastypebuilder = TRUE;
10939                         return;
10940                 }
10941         }
10942
10943         if (!dgclass->initialized)
10944                 return;
10945
10946         if (klass->method.count != gklass->method.count) {
10947                 klass->method.count = gklass->method.count;
10948                 klass->methods = mono_image_alloc (klass->image, sizeof (MonoMethod*) * (klass->method.count + 1));
10949
10950                 for (i = 0; i < klass->method.count; i++) {
10951                         MonoError error;
10952                         klass->methods [i] = mono_class_inflate_generic_method_full_checked (
10953                                 gklass->methods [i], klass, mono_class_get_context (klass), &error);
10954                         g_assert (mono_error_ok (&error)); /* FIXME don't swallow the error */
10955                 }
10956         }
10957
10958         if (klass->interface_count && klass->interface_count != gklass->interface_count) {
10959                 klass->interface_count = gklass->interface_count;
10960                 klass->interfaces = mono_image_alloc (klass->image, sizeof (MonoClass*) * gklass->interface_count);
10961                 klass->interfaces_packed = NULL; /*make setup_interface_offsets happy*/
10962
10963                 for (i = 0; i < gklass->interface_count; ++i) {
10964                         MonoType *iface_type = mono_class_inflate_generic_type (&gklass->interfaces [i]->byval_arg, mono_class_get_context (klass));
10965                         klass->interfaces [i] = mono_class_from_mono_type (iface_type);
10966                         mono_metadata_free_type (iface_type);
10967
10968                         ensure_runtime_vtable (klass->interfaces [i]);
10969                 }
10970                 klass->interfaces_inited = 1;
10971         }
10972
10973         if (klass->field.count != gklass->field.count) {
10974                 klass->field.count = gklass->field.count;
10975                 klass->fields = image_g_new0 (klass->image, MonoClassField, klass->field.count);
10976
10977                 for (i = 0; i < klass->field.count; i++) {
10978                         klass->fields [i] = gklass->fields [i];
10979                         klass->fields [i].parent = klass;
10980                         klass->fields [i].type = mono_class_inflate_generic_type (gklass->fields [i].type, mono_class_get_context (klass));
10981                 }
10982         }
10983
10984         /*We can only finish with this klass once it's parent has as well*/
10985         if (gklass->wastypebuilder)
10986                 klass->wastypebuilder = TRUE;
10987         return;
10988 }
10989
10990 static void
10991 ensure_generic_class_runtime_vtable (MonoClass *klass)
10992 {
10993         MonoClass *gklass = klass->generic_class->container_class;
10994
10995         ensure_runtime_vtable (gklass); 
10996
10997         fix_partial_generic_class (klass);
10998 }
10999
11000 static void
11001 ensure_runtime_vtable (MonoClass *klass)
11002 {
11003         MonoReflectionTypeBuilder *tb = mono_class_get_ref_info (klass);
11004         int i, num, j;
11005
11006         if (!image_is_dynamic (klass->image) || (!tb && !klass->generic_class) || klass->wastypebuilder)
11007                 return;
11008         if (klass->parent)
11009                 ensure_runtime_vtable (klass->parent);
11010
11011         if (tb) {
11012                 num = tb->ctors? mono_array_length (tb->ctors): 0;
11013                 num += tb->num_methods;
11014                 klass->method.count = num;
11015                 klass->methods = mono_image_alloc (klass->image, sizeof (MonoMethod*) * num);
11016                 num = tb->ctors? mono_array_length (tb->ctors): 0;
11017                 for (i = 0; i < num; ++i)
11018                         klass->methods [i] = ctorbuilder_to_mono_method (klass, mono_array_get (tb->ctors, MonoReflectionCtorBuilder*, i));
11019                 num = tb->num_methods;
11020                 j = i;
11021                 for (i = 0; i < num; ++i)
11022                         klass->methods [j++] = methodbuilder_to_mono_method (klass, mono_array_get (tb->methods, MonoReflectionMethodBuilder*, i));
11023         
11024                 if (tb->interfaces) {
11025                         klass->interface_count = mono_array_length (tb->interfaces);
11026                         klass->interfaces = mono_image_alloc (klass->image, sizeof (MonoClass*) * klass->interface_count);
11027                         for (i = 0; i < klass->interface_count; ++i) {
11028                                 MonoType *iface = mono_type_array_get_and_resolve (tb->interfaces, i);
11029                                 klass->interfaces [i] = mono_class_from_mono_type (iface);
11030                                 ensure_runtime_vtable (klass->interfaces [i]);
11031                         }
11032                         klass->interfaces_inited = 1;
11033                 }
11034         } else if (klass->generic_class){
11035                 ensure_generic_class_runtime_vtable (klass);
11036         }
11037
11038         if (klass->flags & TYPE_ATTRIBUTE_INTERFACE) {
11039                 int slot_num = 0;
11040                 for (i = 0; i < klass->method.count; ++i) {
11041                         MonoMethod *im = klass->methods [i];
11042                         if (!(im->flags & METHOD_ATTRIBUTE_STATIC))
11043                                 im->slot = slot_num++;
11044                 }
11045                 
11046                 klass->interfaces_packed = NULL; /*make setup_interface_offsets happy*/
11047                 mono_class_setup_interface_offsets (klass);
11048                 mono_class_setup_interface_id (klass);
11049         }
11050
11051         /*
11052          * The generic vtable is needed even if image->run is not set since some
11053          * runtime code like ves_icall_Type_GetMethodsByName depends on 
11054          * method->slot being defined.
11055          */
11056
11057         /* 
11058          * tb->methods could not be freed since it is used for determining 
11059          * overrides during dynamic vtable construction.
11060          */
11061 }
11062
11063 static MonoMethod*
11064 mono_reflection_method_get_handle (MonoObject *method)
11065 {
11066         MonoClass *class = mono_object_class (method);
11067         if (is_sr_mono_method (class) || is_sr_mono_generic_method (class)) {
11068                 MonoReflectionMethod *sr_method = (MonoReflectionMethod*)method;
11069                 return sr_method->method;
11070         }
11071         if (is_sre_method_builder (class)) {
11072                 MonoReflectionMethodBuilder *mb = (MonoReflectionMethodBuilder*)method;
11073                 return mb->mhandle;
11074         }
11075         if (is_sre_method_on_tb_inst (class)) {
11076                 MonoReflectionMethodOnTypeBuilderInst *m = (MonoReflectionMethodOnTypeBuilderInst*)method;
11077                 MonoMethod *result;
11078                 /*FIXME move this to a proper method and unify with resolve_object*/
11079                 if (m->method_args) {
11080                         result = mono_reflection_method_on_tb_inst_get_handle (m);
11081                 } else {
11082                         MonoType *type = mono_reflection_type_get_handle ((MonoReflectionType*)m->inst);
11083                         MonoClass *inflated_klass = mono_class_from_mono_type (type);
11084                         MonoMethod *mono_method;
11085
11086                         if (is_sre_method_builder (mono_object_class (m->mb)))
11087                                 mono_method = ((MonoReflectionMethodBuilder *)m->mb)->mhandle;
11088                         else if (is_sr_mono_method (mono_object_class (m->mb)))
11089                                 mono_method = ((MonoReflectionMethod *)m->mb)->method;
11090                         else
11091                                 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)));
11092
11093                         result = inflate_mono_method (inflated_klass, mono_method, (MonoObject*)m->mb);
11094                 }
11095                 return result;
11096         }
11097
11098         g_error ("Can't handle methods of type %s:%s", class->name_space, class->name);
11099         return NULL;
11100 }
11101
11102 void
11103 mono_reflection_get_dynamic_overrides (MonoClass *klass, MonoMethod ***overrides, int *num_overrides)
11104 {
11105         MonoReflectionTypeBuilder *tb;
11106         int i, j, onum;
11107         MonoReflectionMethod *m;
11108
11109         *overrides = NULL;
11110         *num_overrides = 0;
11111
11112         g_assert (image_is_dynamic (klass->image));
11113
11114         if (!mono_class_get_ref_info (klass))
11115                 return;
11116
11117         g_assert (strcmp (((MonoObject*)mono_class_get_ref_info (klass))->vtable->klass->name, "TypeBuilder") == 0);
11118
11119         tb = (MonoReflectionTypeBuilder*)mono_class_get_ref_info (klass);
11120
11121         onum = 0;
11122         if (tb->methods) {
11123                 for (i = 0; i < tb->num_methods; ++i) {
11124                         MonoReflectionMethodBuilder *mb = 
11125                                 mono_array_get (tb->methods, MonoReflectionMethodBuilder*, i);
11126                         if (mb->override_methods)
11127                                 onum += mono_array_length (mb->override_methods);
11128                 }
11129         }
11130
11131         if (onum) {
11132                 *overrides = g_new0 (MonoMethod*, onum * 2);
11133
11134                 onum = 0;
11135                 for (i = 0; i < tb->num_methods; ++i) {
11136                         MonoReflectionMethodBuilder *mb = 
11137                                 mono_array_get (tb->methods, MonoReflectionMethodBuilder*, i);
11138                         if (mb->override_methods) {
11139                                 for (j = 0; j < mono_array_length (mb->override_methods); ++j) {
11140                                         m = mono_array_get (mb->override_methods, MonoReflectionMethod*, j);
11141
11142                                         (*overrides) [onum * 2] = mono_reflection_method_get_handle ((MonoObject*)m);
11143                                         (*overrides) [onum * 2 + 1] = mb->mhandle;
11144
11145                                         g_assert (mb->mhandle);
11146
11147                                         onum ++;
11148                                 }
11149                         }
11150                 }
11151         }
11152
11153         *num_overrides = onum;
11154 }
11155
11156 static void
11157 typebuilder_setup_fields (MonoClass *klass, MonoError *error)
11158 {
11159         MonoReflectionTypeBuilder *tb = mono_class_get_ref_info (klass);
11160         MonoReflectionFieldBuilder *fb;
11161         MonoClassField *field;
11162         MonoImage *image = klass->image;
11163         const char *p, *p2;
11164         int i;
11165         guint32 len, idx, real_size = 0;
11166
11167         klass->field.count = tb->num_fields;
11168         klass->field.first = 0;
11169
11170         mono_error_init (error);
11171
11172         if (tb->class_size) {
11173                 if ((tb->packing_size & 0xffffff00) != 0) {
11174                         char *err_msg = g_strdup_printf ("Could not load struct '%s' with packing size %d >= 256", klass->name, tb->packing_size);
11175                         mono_class_set_failure (klass, MONO_EXCEPTION_TYPE_LOAD, err_msg);
11176                         return;
11177                 }
11178                 klass->packing_size = tb->packing_size;
11179                 real_size = klass->instance_size + tb->class_size;
11180         }
11181
11182         if (!klass->field.count) {
11183                 klass->instance_size = MAX (klass->instance_size, real_size);
11184                 return;
11185         }
11186         
11187         klass->fields = image_g_new0 (image, MonoClassField, klass->field.count);
11188         mono_class_alloc_ext (klass);
11189         klass->ext->field_def_values = image_g_new0 (image, MonoFieldDefaultValue, klass->field.count);
11190         /*
11191         This is, guess what, a hack.
11192         The issue is that the runtime doesn't know how to setup the fields of a typebuider and crash.
11193         On the static path no field class is resolved, only types are built. This is the right thing to do
11194         but we suck.
11195         Setting size_inited is harmless because we're doing the same job as mono_class_setup_fields anyway.
11196         */
11197         klass->size_inited = 1;
11198
11199         for (i = 0; i < klass->field.count; ++i) {
11200                 MonoArray *rva_data;
11201                 fb = mono_array_get (tb->fields, gpointer, i);
11202                 field = &klass->fields [i];
11203                 field->name = mono_string_to_utf8_image (image, fb->name, error);
11204                 if (!mono_error_ok (error))
11205                         return;
11206                 if (fb->attrs) {
11207                         field->type = mono_metadata_type_dup (klass->image, mono_reflection_type_get_handle ((MonoReflectionType*)fb->type));
11208                         field->type->attrs = fb->attrs;
11209                 } else {
11210                         field->type = mono_reflection_type_get_handle ((MonoReflectionType*)fb->type);
11211                 }
11212
11213                 if ((fb->attrs & FIELD_ATTRIBUTE_HAS_FIELD_RVA) && (rva_data = fb->rva_data)) {
11214                         char *base = mono_array_addr (rva_data, char, 0);
11215                         size_t size = mono_array_length (rva_data);
11216                         char *data = mono_image_alloc (klass->image, size);
11217                         memcpy (data, base, size);
11218                         klass->ext->field_def_values [i].data = data;
11219                 }
11220                 if (fb->offset != -1)
11221                         field->offset = fb->offset;
11222                 field->parent = klass;
11223                 fb->handle = field;
11224                 mono_save_custom_attrs (klass->image, field, fb->cattrs);
11225
11226                 if (klass->enumtype && !(field->type->attrs & FIELD_ATTRIBUTE_STATIC)) {
11227                         klass->cast_class = klass->element_class = mono_class_from_mono_type (field->type);
11228                 }
11229                 if (fb->def_value) {
11230                         MonoDynamicImage *assembly = (MonoDynamicImage*)klass->image;
11231                         field->type->attrs |= FIELD_ATTRIBUTE_HAS_DEFAULT;
11232                         idx = encode_constant (assembly, fb->def_value, &klass->ext->field_def_values [i].def_type);
11233                         /* Copy the data from the blob since it might get realloc-ed */
11234                         p = assembly->blob.data + idx;
11235                         len = mono_metadata_decode_blob_size (p, &p2);
11236                         len += p2 - p;
11237                         klass->ext->field_def_values [i].data = mono_image_alloc (image, len);
11238                         memcpy ((gpointer)klass->ext->field_def_values [i].data, p, len);
11239                 }
11240         }
11241
11242         klass->instance_size = MAX (klass->instance_size, real_size);
11243         mono_class_layout_fields (klass);
11244 }
11245
11246 static void
11247 typebuilder_setup_properties (MonoClass *klass, MonoError *error)
11248 {
11249         MonoReflectionTypeBuilder *tb = mono_class_get_ref_info (klass);
11250         MonoReflectionPropertyBuilder *pb;
11251         MonoImage *image = klass->image;
11252         MonoProperty *properties;
11253         int i;
11254
11255         mono_error_init (error);
11256
11257         if (!klass->ext)
11258                 klass->ext = image_g_new0 (image, MonoClassExt, 1);
11259
11260         klass->ext->property.count = tb->properties ? mono_array_length (tb->properties) : 0;
11261         klass->ext->property.first = 0;
11262
11263         properties = image_g_new0 (image, MonoProperty, klass->ext->property.count);
11264         klass->ext->properties = properties;
11265         for (i = 0; i < klass->ext->property.count; ++i) {
11266                 pb = mono_array_get (tb->properties, MonoReflectionPropertyBuilder*, i);
11267                 properties [i].parent = klass;
11268                 properties [i].attrs = pb->attrs;
11269                 properties [i].name = mono_string_to_utf8_image (image, pb->name, error);
11270                 if (!mono_error_ok (error))
11271                         return;
11272                 if (pb->get_method)
11273                         properties [i].get = pb->get_method->mhandle;
11274                 if (pb->set_method)
11275                         properties [i].set = pb->set_method->mhandle;
11276
11277                 mono_save_custom_attrs (klass->image, &properties [i], pb->cattrs);
11278                 if (pb->def_value) {
11279                         guint32 len, idx;
11280                         const char *p, *p2;
11281                         MonoDynamicImage *assembly = (MonoDynamicImage*)klass->image;
11282                         if (!klass->ext->prop_def_values)
11283                                 klass->ext->prop_def_values = image_g_new0 (image, MonoFieldDefaultValue, klass->ext->property.count);
11284                         properties [i].attrs |= PROPERTY_ATTRIBUTE_HAS_DEFAULT;
11285                         idx = encode_constant (assembly, pb->def_value, &klass->ext->prop_def_values [i].def_type);
11286                         /* Copy the data from the blob since it might get realloc-ed */
11287                         p = assembly->blob.data + idx;
11288                         len = mono_metadata_decode_blob_size (p, &p2);
11289                         len += p2 - p;
11290                         klass->ext->prop_def_values [i].data = mono_image_alloc (image, len);
11291                         memcpy ((gpointer)klass->ext->prop_def_values [i].data, p, len);
11292                 }
11293         }
11294 }
11295
11296 MonoReflectionEvent *
11297 mono_reflection_event_builder_get_event_info (MonoReflectionTypeBuilder *tb, MonoReflectionEventBuilder *eb)
11298 {
11299         MonoEvent *event = g_new0 (MonoEvent, 1);
11300         MonoClass *klass;
11301
11302         klass = mono_class_from_mono_type (mono_reflection_type_get_handle ((MonoReflectionType*)tb));
11303
11304         event->parent = klass;
11305         event->attrs = eb->attrs;
11306         event->name = mono_string_to_utf8 (eb->name);
11307         if (eb->add_method)
11308                 event->add = eb->add_method->mhandle;
11309         if (eb->remove_method)
11310                 event->remove = eb->remove_method->mhandle;
11311         if (eb->raise_method)
11312                 event->raise = eb->raise_method->mhandle;
11313
11314 #ifndef MONO_SMALL_CONFIG
11315         if (eb->other_methods) {
11316                 int j;
11317                 event->other = g_new0 (MonoMethod*, mono_array_length (eb->other_methods) + 1);
11318                 for (j = 0; j < mono_array_length (eb->other_methods); ++j) {
11319                         MonoReflectionMethodBuilder *mb = 
11320                                 mono_array_get (eb->other_methods,
11321                                                 MonoReflectionMethodBuilder*, j);
11322                         event->other [j] = mb->mhandle;
11323                 }
11324         }
11325 #endif
11326
11327         return mono_event_get_object (mono_object_domain (tb), klass, event);
11328 }
11329
11330 static void
11331 typebuilder_setup_events (MonoClass *klass, MonoError *error)
11332 {
11333         MonoReflectionTypeBuilder *tb = mono_class_get_ref_info (klass);
11334         MonoReflectionEventBuilder *eb;
11335         MonoImage *image = klass->image;
11336         MonoEvent *events;
11337         int i;
11338
11339         mono_error_init (error);
11340
11341         if (!klass->ext)
11342                 klass->ext = image_g_new0 (image, MonoClassExt, 1);
11343
11344         klass->ext->event.count = tb->events ? mono_array_length (tb->events) : 0;
11345         klass->ext->event.first = 0;
11346
11347         events = image_g_new0 (image, MonoEvent, klass->ext->event.count);
11348         klass->ext->events = events;
11349         for (i = 0; i < klass->ext->event.count; ++i) {
11350                 eb = mono_array_get (tb->events, MonoReflectionEventBuilder*, i);
11351                 events [i].parent = klass;
11352                 events [i].attrs = eb->attrs;
11353                 events [i].name = mono_string_to_utf8_image (image, eb->name, error);
11354                 if (!mono_error_ok (error))
11355                         return;
11356                 if (eb->add_method)
11357                         events [i].add = eb->add_method->mhandle;
11358                 if (eb->remove_method)
11359                         events [i].remove = eb->remove_method->mhandle;
11360                 if (eb->raise_method)
11361                         events [i].raise = eb->raise_method->mhandle;
11362
11363 #ifndef MONO_SMALL_CONFIG
11364                 if (eb->other_methods) {
11365                         int j;
11366                         events [i].other = image_g_new0 (image, MonoMethod*, mono_array_length (eb->other_methods) + 1);
11367                         for (j = 0; j < mono_array_length (eb->other_methods); ++j) {
11368                                 MonoReflectionMethodBuilder *mb = 
11369                                         mono_array_get (eb->other_methods,
11370                                                                         MonoReflectionMethodBuilder*, j);
11371                                 events [i].other [j] = mb->mhandle;
11372                         }
11373                 }
11374 #endif
11375                 mono_save_custom_attrs (klass->image, &events [i], eb->cattrs);
11376         }
11377 }
11378
11379 static gboolean
11380 remove_instantiations_of_and_ensure_contents (gpointer key,
11381                                                   gpointer value,
11382                                                   gpointer user_data)
11383 {
11384         MonoType *type = (MonoType*)key;
11385         MonoClass *klass = (MonoClass*)user_data;
11386
11387         if ((type->type == MONO_TYPE_GENERICINST) && (type->data.generic_class->container_class == klass)) {
11388                 fix_partial_generic_class (mono_class_from_mono_type (type)); //Ensure it's safe to use it.
11389                 return TRUE;
11390         } else
11391                 return FALSE;
11392 }
11393
11394 static void
11395 check_array_for_usertypes (MonoArray *arr)
11396 {
11397         int i;
11398
11399         if (!arr)
11400                 return;
11401
11402         for (i = 0; i < mono_array_length (arr); ++i)
11403                 RESOLVE_ARRAY_TYPE_ELEMENT (arr, i);
11404 }
11405
11406 MonoReflectionType*
11407 mono_reflection_create_runtime_class (MonoReflectionTypeBuilder *tb)
11408 {
11409         MonoError error;
11410         MonoClass *klass;
11411         MonoDomain* domain;
11412         MonoReflectionType* res;
11413         int i, j;
11414
11415         domain = mono_object_domain (tb);
11416         klass = mono_class_from_mono_type (tb->type.type);
11417
11418         /*
11419          * Check for user defined Type subclasses.
11420          */
11421         RESOLVE_TYPE (tb->parent);
11422         check_array_for_usertypes (tb->interfaces);
11423         if (tb->fields) {
11424                 for (i = 0; i < mono_array_length (tb->fields); ++i) {
11425                         MonoReflectionFieldBuilder *fb = mono_array_get (tb->fields, gpointer, i);
11426                         if (fb) {
11427                                 RESOLVE_TYPE (fb->type);
11428                                 check_array_for_usertypes (fb->modreq);
11429                                 check_array_for_usertypes (fb->modopt);
11430                                 if (fb->marshal_info && fb->marshal_info->marshaltyperef)
11431                                         RESOLVE_TYPE (fb->marshal_info->marshaltyperef);
11432                         }
11433                 }
11434         }
11435         if (tb->methods) {
11436                 for (i = 0; i < mono_array_length (tb->methods); ++i) {
11437                         MonoReflectionMethodBuilder *mb = mono_array_get (tb->methods, gpointer, i);
11438                         if (mb) {
11439                                 RESOLVE_TYPE (mb->rtype);
11440                                 check_array_for_usertypes (mb->return_modreq);
11441                                 check_array_for_usertypes (mb->return_modopt);
11442                                 check_array_for_usertypes (mb->parameters);
11443                                 if (mb->param_modreq)
11444                                         for (j = 0; j < mono_array_length (mb->param_modreq); ++j)
11445                                                 check_array_for_usertypes (mono_array_get (mb->param_modreq, MonoArray*, j));
11446                                 if (mb->param_modopt)
11447                                         for (j = 0; j < mono_array_length (mb->param_modopt); ++j)
11448                                                 check_array_for_usertypes (mono_array_get (mb->param_modopt, MonoArray*, j));
11449                         }
11450                 }
11451         }
11452         if (tb->ctors) {
11453                 for (i = 0; i < mono_array_length (tb->ctors); ++i) {
11454                         MonoReflectionCtorBuilder *mb = mono_array_get (tb->ctors, gpointer, i);
11455                         if (mb) {
11456                                 check_array_for_usertypes (mb->parameters);
11457                                 if (mb->param_modreq)
11458                                         for (j = 0; j < mono_array_length (mb->param_modreq); ++j)
11459                                                 check_array_for_usertypes (mono_array_get (mb->param_modreq, MonoArray*, j));
11460                                 if (mb->param_modopt)
11461                                         for (j = 0; j < mono_array_length (mb->param_modopt); ++j)
11462                                                 check_array_for_usertypes (mono_array_get (mb->param_modopt, MonoArray*, j));
11463                         }
11464                 }
11465         }
11466
11467         mono_save_custom_attrs (klass->image, klass, tb->cattrs);
11468
11469         /* 
11470          * we need to lock the domain because the lock will be taken inside
11471          * So, we need to keep the locking order correct.
11472          */
11473         mono_loader_lock ();
11474         mono_domain_lock (domain);
11475         if (klass->wastypebuilder) {
11476                 mono_domain_unlock (domain);
11477                 mono_loader_unlock ();
11478                 return mono_type_get_object (mono_object_domain (tb), &klass->byval_arg);
11479         }
11480         /*
11481          * Fields to set in klass:
11482          * the various flags: delegate/unicode/contextbound etc.
11483          */
11484         klass->flags = tb->attrs;
11485         klass->has_cctor = 1;
11486         klass->has_finalize = 1;
11487         klass->has_finalize_inited = 1;
11488
11489         mono_class_setup_parent (klass, klass->parent);
11490         /* fool mono_class_setup_supertypes */
11491         klass->supertypes = NULL;
11492         mono_class_setup_supertypes (klass);
11493         mono_class_setup_mono_type (klass);
11494
11495 #if 0
11496         if (!((MonoDynamicImage*)klass->image)->run) {
11497                 if (klass->generic_container) {
11498                         /* FIXME: The code below can't handle generic classes */
11499                         klass->wastypebuilder = TRUE;
11500                         mono_loader_unlock ();
11501                         mono_domain_unlock (domain);
11502                         return mono_type_get_object (mono_object_domain (tb), &klass->byval_arg);
11503                 }
11504         }
11505 #endif
11506
11507         /* enums are done right away */
11508         if (!klass->enumtype)
11509                 ensure_runtime_vtable (klass);
11510
11511         if (tb->subtypes) {
11512                 for (i = 0; i < mono_array_length (tb->subtypes); ++i) {
11513                         MonoReflectionTypeBuilder *subtb = mono_array_get (tb->subtypes, MonoReflectionTypeBuilder*, i);
11514                         mono_class_alloc_ext (klass);
11515                         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)));
11516                 }
11517         }
11518
11519         klass->nested_classes_inited = TRUE;
11520
11521         /* fields and object layout */
11522         if (klass->parent) {
11523                 if (!klass->parent->size_inited)
11524                         mono_class_init (klass->parent);
11525                 klass->instance_size = klass->parent->instance_size;
11526                 klass->sizes.class_size = 0;
11527                 klass->min_align = klass->parent->min_align;
11528                 /* if the type has no fields we won't call the field_setup
11529                  * routine which sets up klass->has_references.
11530                  */
11531                 klass->has_references |= klass->parent->has_references;
11532         } else {
11533                 klass->instance_size = sizeof (MonoObject);
11534                 klass->min_align = 1;
11535         }
11536
11537         /* FIXME: handle packing_size and instance_size */
11538         typebuilder_setup_fields (klass, &error);
11539         if (!mono_error_ok (&error))
11540                 goto failure;
11541         typebuilder_setup_properties (klass, &error);
11542         if (!mono_error_ok (&error))
11543                 goto failure;
11544
11545         typebuilder_setup_events (klass, &error);
11546         if (!mono_error_ok (&error))
11547                 goto failure;
11548
11549         klass->wastypebuilder = TRUE;
11550
11551         /* 
11552          * If we are a generic TypeBuilder, there might be instantiations in the type cache
11553          * which have type System.Reflection.MonoGenericClass, but after the type is created, 
11554          * we want to return normal System.MonoType objects, so clear these out from the cache.
11555          *
11556          * Together with this we must ensure the contents of all instances to match the created type.
11557          */
11558         if (domain->type_hash && klass->generic_container)
11559                 mono_g_hash_table_foreach_remove (domain->type_hash, remove_instantiations_of_and_ensure_contents, klass);
11560
11561         mono_domain_unlock (domain);
11562         mono_loader_unlock ();
11563
11564         if (klass->enumtype && !mono_class_is_valid_enum (klass)) {
11565                 mono_class_set_failure (klass, MONO_EXCEPTION_TYPE_LOAD, NULL);
11566                 mono_raise_exception (mono_get_exception_type_load (tb->name, NULL));
11567         }
11568
11569         res = mono_type_get_object (mono_object_domain (tb), &klass->byval_arg);
11570         g_assert (res != (MonoReflectionType*)tb);
11571
11572         return res;
11573
11574 failure:
11575         mono_class_set_failure (klass, MONO_EXCEPTION_TYPE_LOAD, NULL);
11576         klass->wastypebuilder = TRUE;
11577         mono_domain_unlock (domain);
11578         mono_loader_unlock ();
11579         mono_error_raise_exception (&error);
11580         return NULL;
11581 }
11582
11583 void
11584 mono_reflection_initialize_generic_parameter (MonoReflectionGenericParam *gparam)
11585 {
11586         MonoGenericParamFull *param;
11587         MonoImage *image;
11588         MonoClass *pklass;
11589         MonoError error;
11590
11591         image = &gparam->tbuilder->module->dynamic_image->image;
11592
11593         param = mono_image_new0 (image, MonoGenericParamFull, 1);
11594
11595         param->info.name = mono_string_to_utf8_image (image, gparam->name, &error);
11596         g_assert (mono_error_ok (&error));
11597         param->param.num = gparam->index;
11598
11599         if (gparam->mbuilder) {
11600                 if (!gparam->mbuilder->generic_container) {
11601                         MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder *)gparam->mbuilder->type;
11602                         MonoClass *klass = mono_class_from_mono_type (mono_reflection_type_get_handle ((MonoReflectionType*)tb));
11603                         gparam->mbuilder->generic_container = mono_image_alloc0 (klass->image, sizeof (MonoGenericContainer));
11604                         gparam->mbuilder->generic_container->is_method = TRUE;
11605                         /* 
11606                          * Cannot set owner.method, since the MonoMethod is not created yet.
11607                          * Set the image field instead, so type_in_image () works.
11608                          */
11609                         gparam->mbuilder->generic_container->image = klass->image;
11610                 }
11611                 param->param.owner = gparam->mbuilder->generic_container;
11612         } else if (gparam->tbuilder) {
11613                 if (!gparam->tbuilder->generic_container) {
11614                         MonoClass *klass = mono_class_from_mono_type (mono_reflection_type_get_handle ((MonoReflectionType*)gparam->tbuilder));
11615                         gparam->tbuilder->generic_container = mono_image_alloc0 (klass->image, sizeof (MonoGenericContainer));
11616                         gparam->tbuilder->generic_container->owner.klass = klass;
11617                 }
11618                 param->param.owner = gparam->tbuilder->generic_container;
11619         }
11620
11621         pklass = mono_class_from_generic_parameter ((MonoGenericParam *) param, image, gparam->mbuilder != NULL);
11622
11623         gparam->type.type = &pklass->byval_arg;
11624
11625         mono_class_set_ref_info (pklass, gparam);
11626         mono_image_append_class_to_reflection_info_set (pklass);
11627 }
11628
11629 MonoArray *
11630 mono_reflection_sighelper_get_signature_local (MonoReflectionSigHelper *sig)
11631 {
11632         MonoReflectionModuleBuilder *module = sig->module;
11633         MonoDynamicImage *assembly = module != NULL ? module->dynamic_image : NULL;
11634         guint32 na = sig->arguments ? mono_array_length (sig->arguments) : 0;
11635         guint32 buflen, i;
11636         MonoArray *result;
11637         SigBuffer buf;
11638
11639         check_array_for_usertypes (sig->arguments);
11640
11641         sigbuffer_init (&buf, 32);
11642
11643         sigbuffer_add_value (&buf, 0x07);
11644         sigbuffer_add_value (&buf, na);
11645         if (assembly != NULL){
11646                 for (i = 0; i < na; ++i) {
11647                         MonoReflectionType *type = mono_array_get (sig->arguments, MonoReflectionType*, i);
11648                         encode_reflection_type (assembly, type, &buf);
11649                 }
11650         }
11651
11652         buflen = buf.p - buf.buf;
11653         result = mono_array_new (mono_domain_get (), mono_defaults.byte_class, buflen);
11654         memcpy (mono_array_addr (result, char, 0), buf.buf, buflen);
11655         sigbuffer_free (&buf);
11656
11657         return result;
11658 }
11659
11660 MonoArray *
11661 mono_reflection_sighelper_get_signature_field (MonoReflectionSigHelper *sig)
11662 {
11663         MonoDynamicImage *assembly = sig->module->dynamic_image;
11664         guint32 na = sig->arguments ? mono_array_length (sig->arguments) : 0;
11665         guint32 buflen, i;
11666         MonoArray *result;
11667         SigBuffer buf;
11668
11669         check_array_for_usertypes (sig->arguments);
11670
11671         sigbuffer_init (&buf, 32);
11672
11673         sigbuffer_add_value (&buf, 0x06);
11674         for (i = 0; i < na; ++i) {
11675                 MonoReflectionType *type = mono_array_get (sig->arguments, MonoReflectionType*, i);
11676                 encode_reflection_type (assembly, type, &buf);
11677         }
11678
11679         buflen = buf.p - buf.buf;
11680         result = mono_array_new (mono_domain_get (), mono_defaults.byte_class, buflen);
11681         memcpy (mono_array_addr (result, char, 0), buf.buf, buflen);
11682         sigbuffer_free (&buf);
11683
11684         return result;
11685 }
11686
11687 typedef struct {
11688         MonoMethod *handle;
11689         MonoDomain *domain;
11690 } DynamicMethodReleaseData;
11691
11692 /*
11693  * The runtime automatically clean up those after finalization.
11694 */      
11695 static MonoReferenceQueue *dynamic_method_queue;
11696
11697 static void
11698 free_dynamic_method (void *dynamic_method)
11699 {
11700         DynamicMethodReleaseData *data = dynamic_method;
11701
11702         mono_runtime_free_method (data->domain, data->handle);
11703         g_free (data);
11704 }
11705
11706 void 
11707 mono_reflection_create_dynamic_method (MonoReflectionDynamicMethod *mb)
11708 {
11709         MonoReferenceQueue *queue;
11710         MonoMethod *handle;
11711         DynamicMethodReleaseData *release_data;
11712         ReflectionMethodBuilder rmb;
11713         MonoMethodSignature *sig;
11714         MonoClass *klass;
11715         GSList *l;
11716         int i;
11717
11718         if (mono_runtime_is_shutting_down ())
11719                 mono_raise_exception (mono_get_exception_invalid_operation (""));
11720
11721         if (!(queue = dynamic_method_queue)) {
11722                 mono_loader_lock ();
11723                 if (!(queue = dynamic_method_queue))
11724                         queue = dynamic_method_queue = mono_gc_reference_queue_new (free_dynamic_method);
11725                 mono_loader_unlock ();
11726         }
11727
11728         sig = dynamic_method_to_signature (mb);
11729
11730         reflection_methodbuilder_from_dynamic_method (&rmb, mb);
11731
11732         /*
11733          * Resolve references.
11734          */
11735         /* 
11736          * Every second entry in the refs array is reserved for storing handle_class,
11737          * which is needed by the ldtoken implementation in the JIT.
11738          */
11739         rmb.nrefs = mb->nrefs;
11740         rmb.refs = g_new0 (gpointer, mb->nrefs + 1);
11741         for (i = 0; i < mb->nrefs; i += 2) {
11742                 MonoClass *handle_class;
11743                 gpointer ref;
11744                 MonoObject *obj = mono_array_get (mb->refs, MonoObject*, i);
11745
11746                 if (strcmp (obj->vtable->klass->name, "DynamicMethod") == 0) {
11747                         MonoReflectionDynamicMethod *method = (MonoReflectionDynamicMethod*)obj;
11748                         /*
11749                          * The referenced DynamicMethod should already be created by the managed
11750                          * code, except in the case of circular references. In that case, we store
11751                          * method in the refs array, and fix it up later when the referenced 
11752                          * DynamicMethod is created.
11753                          */
11754                         if (method->mhandle) {
11755                                 ref = method->mhandle;
11756                         } else {
11757                                 /* FIXME: GC object stored in unmanaged memory */
11758                                 ref = method;
11759
11760                                 /* FIXME: GC object stored in unmanaged memory */
11761                                 method->referenced_by = g_slist_append (method->referenced_by, mb);
11762                         }
11763                         handle_class = mono_defaults.methodhandle_class;
11764                 } else {
11765                         MonoException *ex = NULL;
11766                         ref = resolve_object (mb->module->image, obj, &handle_class, NULL);
11767                         if (!ref)
11768                                 ex = mono_get_exception_type_load (NULL, NULL);
11769                         else if (mono_security_core_clr_enabled ())
11770                                 ex = mono_security_core_clr_ensure_dynamic_method_resolved_object (ref, handle_class);
11771
11772                         if (ex) {
11773                                 g_free (rmb.refs);
11774                                 mono_raise_exception (ex);
11775                                 return;
11776                         }
11777                 }
11778
11779                 rmb.refs [i] = ref; /* FIXME: GC object stored in unmanaged memory (change also resolve_object() signature) */
11780                 rmb.refs [i + 1] = handle_class;
11781         }               
11782
11783         klass = mb->owner ? mono_class_from_mono_type (mono_reflection_type_get_handle ((MonoReflectionType*)mb->owner)) : mono_defaults.object_class;
11784
11785         mb->mhandle = handle = reflection_methodbuilder_to_mono_method (klass, &rmb, sig);
11786         release_data = g_new (DynamicMethodReleaseData, 1);
11787         release_data->handle = handle;
11788         release_data->domain = mono_object_get_domain ((MonoObject*)mb);
11789         if (!mono_gc_reference_queue_add (queue, (MonoObject*)mb, release_data))
11790                 g_free (release_data);
11791
11792         /* Fix up refs entries pointing at us */
11793         for (l = mb->referenced_by; l; l = l->next) {
11794                 MonoReflectionDynamicMethod *method = (MonoReflectionDynamicMethod*)l->data;
11795                 MonoMethodWrapper *wrapper = (MonoMethodWrapper*)method->mhandle;
11796                 gpointer *data;
11797                 
11798                 g_assert (method->mhandle);
11799
11800                 data = (gpointer*)wrapper->method_data;
11801                 for (i = 0; i < GPOINTER_TO_UINT (data [0]); i += 2) {
11802                         if ((data [i + 1] == mb) && (data [i + 1 + 1] == mono_defaults.methodhandle_class))
11803                                 data [i + 1] = mb->mhandle;
11804                 }
11805         }
11806         g_slist_free (mb->referenced_by);
11807
11808         g_free (rmb.refs);
11809
11810         /* ilgen is no longer needed */
11811         mb->ilgen = NULL;
11812 }
11813
11814 #endif /* DISABLE_REFLECTION_EMIT */
11815
11816 /**
11817  * 
11818  * mono_reflection_is_valid_dynamic_token:
11819  * 
11820  * Returns TRUE if token is valid.
11821  * 
11822  */
11823 gboolean
11824 mono_reflection_is_valid_dynamic_token (MonoDynamicImage *image, guint32 token)
11825 {
11826         return mono_g_hash_table_lookup (image->tokens, GUINT_TO_POINTER (token)) != NULL;
11827 }
11828
11829 MonoMethodSignature *
11830 mono_reflection_lookup_signature (MonoImage *image, MonoMethod *method, guint32 token, MonoError *error)
11831 {
11832         MonoMethodSignature *sig;
11833         g_assert (image_is_dynamic (image));
11834
11835         mono_error_init (error);
11836
11837         sig = g_hash_table_lookup (((MonoDynamicImage*)image)->vararg_aux_hash, GUINT_TO_POINTER (token));
11838         if (sig)
11839                 return sig;
11840
11841         return mono_method_signature_checked (method, error);
11842 }
11843
11844 #ifndef DISABLE_REFLECTION_EMIT
11845
11846 /**
11847  * mono_reflection_lookup_dynamic_token:
11848  *
11849  * Finish the Builder object pointed to by TOKEN and return the corresponding
11850  * runtime structure. If HANDLE_CLASS is not NULL, it is set to the class required by 
11851  * mono_ldtoken. If valid_token is TRUE, assert if it is not found in the token->object
11852  * mapping table.
11853  *
11854  * LOCKING: Take the loader lock
11855  */
11856 gpointer
11857 mono_reflection_lookup_dynamic_token (MonoImage *image, guint32 token, gboolean valid_token, MonoClass **handle_class, MonoGenericContext *context)
11858 {
11859         MonoDynamicImage *assembly = (MonoDynamicImage*)image;
11860         MonoObject *obj;
11861         MonoClass *klass;
11862
11863         mono_loader_lock ();
11864         obj = mono_g_hash_table_lookup (assembly->tokens, GUINT_TO_POINTER (token));
11865         mono_loader_unlock ();
11866         if (!obj) {
11867                 if (valid_token)
11868                         g_error ("Could not find required dynamic token 0x%08x", token);
11869                 else
11870                         return NULL;
11871         }
11872
11873         if (!handle_class)
11874                 handle_class = &klass;
11875         return resolve_object (image, obj, handle_class, context);
11876 }
11877
11878 /*
11879  * ensure_complete_type:
11880  *
11881  *   Ensure that KLASS is completed if it is a dynamic type, or references
11882  * dynamic types.
11883  */
11884 static void
11885 ensure_complete_type (MonoClass *klass)
11886 {
11887         if (image_is_dynamic (klass->image) && !klass->wastypebuilder && mono_class_get_ref_info (klass)) {
11888                 MonoReflectionTypeBuilder *tb = mono_class_get_ref_info (klass);
11889
11890                 mono_domain_try_type_resolve (mono_domain_get (), NULL, (MonoObject*)tb);
11891
11892                 // Asserting here could break a lot of code
11893                 //g_assert (klass->wastypebuilder);
11894         }
11895
11896         if (klass->generic_class) {
11897                 MonoGenericInst *inst = klass->generic_class->context.class_inst;
11898                 int i;
11899
11900                 for (i = 0; i < inst->type_argc; ++i) {
11901                         ensure_complete_type (mono_class_from_mono_type (inst->type_argv [i]));
11902                 }
11903         }
11904 }
11905
11906 static gpointer
11907 resolve_object (MonoImage *image, MonoObject *obj, MonoClass **handle_class, MonoGenericContext *context)
11908 {
11909         gpointer result = NULL;
11910
11911         if (strcmp (obj->vtable->klass->name, "String") == 0) {
11912                 result = mono_string_intern ((MonoString*)obj);
11913                 *handle_class = mono_defaults.string_class;
11914                 g_assert (result);
11915         } else if (strcmp (obj->vtable->klass->name, "MonoType") == 0) {
11916                 MonoType *type = mono_reflection_type_get_handle ((MonoReflectionType*)obj);
11917                 MonoClass *mc = mono_class_from_mono_type (type);
11918                 if (!mono_class_init (mc))
11919                         mono_raise_exception (mono_class_get_exception_for_failure (mc));
11920
11921                 if (context) {
11922                         MonoType *inflated = mono_class_inflate_generic_type (type, context);
11923                         result = mono_class_from_mono_type (inflated);
11924                         mono_metadata_free_type (inflated);
11925                 } else {
11926                         result = mono_class_from_mono_type (type);
11927                 }
11928                 *handle_class = mono_defaults.typehandle_class;
11929                 g_assert (result);
11930         } else if (strcmp (obj->vtable->klass->name, "MonoMethod") == 0 ||
11931                    strcmp (obj->vtable->klass->name, "MonoCMethod") == 0 ||
11932                    strcmp (obj->vtable->klass->name, "MonoGenericCMethod") == 0 ||
11933                    strcmp (obj->vtable->klass->name, "MonoGenericMethod") == 0) {
11934                 result = ((MonoReflectionMethod*)obj)->method;
11935                 if (context) {
11936                         MonoError error;
11937                         result = mono_class_inflate_generic_method_checked (result, context, &error);
11938                         g_assert (mono_error_ok (&error)); /* FIXME don't swallow the error */
11939                 }
11940                 *handle_class = mono_defaults.methodhandle_class;
11941                 g_assert (result);
11942         } else if (strcmp (obj->vtable->klass->name, "MethodBuilder") == 0) {
11943                 MonoReflectionMethodBuilder *mb = (MonoReflectionMethodBuilder*)obj;
11944                 result = mb->mhandle;
11945                 if (!result) {
11946                         /* Type is not yet created */
11947                         MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder*)mb->type;
11948
11949                         mono_domain_try_type_resolve (mono_domain_get (), NULL, (MonoObject*)tb);
11950
11951                         /*
11952                          * Hopefully this has been filled in by calling CreateType() on the
11953                          * TypeBuilder.
11954                          */
11955                         /*
11956                          * TODO: This won't work if the application finishes another 
11957                          * TypeBuilder instance instead of this one.
11958                          */
11959                         result = mb->mhandle;
11960                 }
11961                 if (context) {
11962                         MonoError error;
11963                         result = mono_class_inflate_generic_method_checked (result, context, &error);
11964                         g_assert (mono_error_ok (&error)); /* FIXME don't swallow the error */
11965                 }
11966                 *handle_class = mono_defaults.methodhandle_class;
11967         } else if (strcmp (obj->vtable->klass->name, "ConstructorBuilder") == 0) {
11968                 MonoReflectionCtorBuilder *cb = (MonoReflectionCtorBuilder*)obj;
11969
11970                 result = cb->mhandle;
11971                 if (!result) {
11972                         MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder*)cb->type;
11973
11974                         mono_domain_try_type_resolve (mono_domain_get (), NULL, (MonoObject*)tb);
11975                         result = cb->mhandle;
11976                 }
11977                 if (context) {
11978                         MonoError error;
11979                         result = mono_class_inflate_generic_method_checked (result, context, &error);
11980                         g_assert (mono_error_ok (&error)); /* FIXME don't swallow the error */
11981                 }
11982                 *handle_class = mono_defaults.methodhandle_class;
11983         } else if (strcmp (obj->vtable->klass->name, "MonoField") == 0) {
11984                 MonoClassField *field = ((MonoReflectionField*)obj)->field;
11985
11986                 ensure_complete_type (field->parent);
11987                 if (context) {
11988                         MonoType *inflated = mono_class_inflate_generic_type (&field->parent->byval_arg, context);
11989                         MonoClass *class = mono_class_from_mono_type (inflated);
11990                         MonoClassField *inflated_field;
11991                         gpointer iter = NULL;
11992                         mono_metadata_free_type (inflated);
11993                         while ((inflated_field = mono_class_get_fields (class, &iter))) {
11994                                 if (!strcmp (field->name, inflated_field->name))
11995                                         break;
11996                         }
11997                         g_assert (inflated_field && !strcmp (field->name, inflated_field->name));
11998                         result = inflated_field;
11999                 } else {
12000                         result = field;
12001                 }
12002                 *handle_class = mono_defaults.fieldhandle_class;
12003                 g_assert (result);
12004         } else if (strcmp (obj->vtable->klass->name, "FieldBuilder") == 0) {
12005                 MonoReflectionFieldBuilder *fb = (MonoReflectionFieldBuilder*)obj;
12006                 result = fb->handle;
12007
12008                 if (!result) {
12009                         MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder*)fb->typeb;
12010
12011                         mono_domain_try_type_resolve (mono_domain_get (), NULL, (MonoObject*)tb);
12012                         result = fb->handle;
12013                 }
12014
12015                 if (fb->handle && fb->handle->parent->generic_container) {
12016                         MonoClass *klass = fb->handle->parent;
12017                         MonoType *type = mono_class_inflate_generic_type (&klass->byval_arg, context);
12018                         MonoClass *inflated = mono_class_from_mono_type (type);
12019
12020                         result = mono_class_get_field_from_name (inflated, mono_field_get_name (fb->handle));
12021                         g_assert (result);
12022                         mono_metadata_free_type (type);
12023                 }
12024                 *handle_class = mono_defaults.fieldhandle_class;
12025         } else if (strcmp (obj->vtable->klass->name, "TypeBuilder") == 0) {
12026                 MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder*)obj;
12027                 MonoType *type = mono_reflection_type_get_handle ((MonoReflectionType*)tb); 
12028                 MonoClass *klass;
12029
12030                 klass = type->data.klass;
12031                 if (klass->wastypebuilder) {
12032                         /* Already created */
12033                         result = klass;
12034                 }
12035                 else {
12036                         mono_domain_try_type_resolve (mono_domain_get (), NULL, (MonoObject*)tb);
12037                         result = type->data.klass;
12038                         g_assert (result);
12039                 }
12040                 *handle_class = mono_defaults.typehandle_class;
12041         } else if (strcmp (obj->vtable->klass->name, "SignatureHelper") == 0) {
12042                 MonoReflectionSigHelper *helper = (MonoReflectionSigHelper*)obj;
12043                 MonoMethodSignature *sig;
12044                 int nargs, i;
12045
12046                 if (helper->arguments)
12047                         nargs = mono_array_length (helper->arguments);
12048                 else
12049                         nargs = 0;
12050
12051                 sig = mono_metadata_signature_alloc (image, nargs);
12052                 sig->explicit_this = helper->call_conv & 64 ? 1 : 0;
12053                 sig->hasthis = helper->call_conv & 32 ? 1 : 0;
12054
12055                 if (helper->unmanaged_call_conv) { /* unmanaged */
12056                         sig->call_convention = helper->unmanaged_call_conv - 1;
12057                         sig->pinvoke = TRUE;
12058                 } else if (helper->call_conv & 0x02) {
12059                         sig->call_convention = MONO_CALL_VARARG;
12060                 } else {
12061                         sig->call_convention = MONO_CALL_DEFAULT;
12062                 }
12063
12064                 sig->param_count = nargs;
12065                 /* TODO: Copy type ? */
12066                 sig->ret = helper->return_type->type;
12067                 for (i = 0; i < nargs; ++i)
12068                         sig->params [i] = mono_type_array_get_and_resolve (helper->arguments, i);
12069
12070                 result = sig;
12071                 *handle_class = NULL;
12072         } else if (strcmp (obj->vtable->klass->name, "DynamicMethod") == 0) {
12073                 MonoReflectionDynamicMethod *method = (MonoReflectionDynamicMethod*)obj;
12074                 /* Already created by the managed code */
12075                 g_assert (method->mhandle);
12076                 result = method->mhandle;
12077                 *handle_class = mono_defaults.methodhandle_class;
12078         } else if (strcmp (obj->vtable->klass->name, "GenericTypeParameterBuilder") == 0) {
12079                 MonoType *type = mono_reflection_type_get_handle ((MonoReflectionType*)obj);
12080                 type = mono_class_inflate_generic_type (type, context);
12081                 result = mono_class_from_mono_type (type);
12082                 *handle_class = mono_defaults.typehandle_class;
12083                 g_assert (result);
12084                 mono_metadata_free_type (type);
12085         } else if (strcmp (obj->vtable->klass->name, "MonoGenericClass") == 0) {
12086                 MonoType *type = mono_reflection_type_get_handle ((MonoReflectionType*)obj);
12087                 type = mono_class_inflate_generic_type (type, context);
12088                 result = mono_class_from_mono_type (type);
12089                 *handle_class = mono_defaults.typehandle_class;
12090                 g_assert (result);
12091                 mono_metadata_free_type (type);
12092         } else if (strcmp (obj->vtable->klass->name, "FieldOnTypeBuilderInst") == 0) {
12093                 MonoReflectionFieldOnTypeBuilderInst *f = (MonoReflectionFieldOnTypeBuilderInst*)obj;
12094                 MonoClass *inflated;
12095                 MonoType *type;
12096                 MonoClassField *field;
12097
12098                 if (is_sre_field_builder (mono_object_class (f->fb)))
12099                         field = ((MonoReflectionFieldBuilder*)f->fb)->handle;
12100                 else if (is_sr_mono_field (mono_object_class (f->fb)))
12101                         field = ((MonoReflectionField*)f->fb)->field;
12102                 else
12103                         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)));
12104
12105                 type = mono_class_inflate_generic_type (mono_reflection_type_get_handle ((MonoReflectionType*)f->inst), context);
12106                 inflated = mono_class_from_mono_type (type);
12107
12108                 result = field = mono_class_get_field_from_name (inflated, mono_field_get_name (field));
12109                 ensure_complete_type (field->parent);
12110                 g_assert (result);
12111                 mono_metadata_free_type (type);
12112                 *handle_class = mono_defaults.fieldhandle_class;
12113         } else if (strcmp (obj->vtable->klass->name, "ConstructorOnTypeBuilderInst") == 0) {
12114                 MonoReflectionCtorOnTypeBuilderInst *c = (MonoReflectionCtorOnTypeBuilderInst*)obj;
12115                 MonoType *type = mono_class_inflate_generic_type (mono_reflection_type_get_handle ((MonoReflectionType*)c->inst), context);
12116                 MonoClass *inflated_klass = mono_class_from_mono_type (type);
12117                 MonoMethod *method;
12118
12119                 if (is_sre_ctor_builder (mono_object_class (c->cb)))
12120                         method = ((MonoReflectionCtorBuilder *)c->cb)->mhandle;
12121                 else if (is_sr_mono_cmethod (mono_object_class (c->cb)))
12122                         method = ((MonoReflectionMethod *)c->cb)->method;
12123                 else
12124                         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)));
12125
12126                 result = inflate_mono_method (inflated_klass, method, (MonoObject*)c->cb);
12127                 *handle_class = mono_defaults.methodhandle_class;
12128                 mono_metadata_free_type (type);
12129         } else if (strcmp (obj->vtable->klass->name, "MethodOnTypeBuilderInst") == 0) {
12130                 MonoReflectionMethodOnTypeBuilderInst *m = (MonoReflectionMethodOnTypeBuilderInst*)obj;
12131                 if (m->method_args) {
12132                         result = mono_reflection_method_on_tb_inst_get_handle (m);
12133                         if (context) {
12134                                 MonoError error;
12135                                 result = mono_class_inflate_generic_method_checked (result, context, &error);
12136                                 g_assert (mono_error_ok (&error)); /* FIXME don't swallow the error */
12137                         }
12138                 } else {
12139                         MonoType *type = mono_class_inflate_generic_type (mono_reflection_type_get_handle ((MonoReflectionType*)m->inst), context);
12140                         MonoClass *inflated_klass = mono_class_from_mono_type (type);
12141                         MonoMethod *method;
12142
12143                         if (is_sre_method_builder (mono_object_class (m->mb)))
12144                                 method = ((MonoReflectionMethodBuilder *)m->mb)->mhandle;
12145                         else if (is_sr_mono_method (mono_object_class (m->mb)))
12146                                 method = ((MonoReflectionMethod *)m->mb)->method;
12147                         else
12148                                 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)));
12149
12150                         result = inflate_mono_method (inflated_klass, method, (MonoObject*)m->mb);
12151                         mono_metadata_free_type (type);
12152                 }
12153                 *handle_class = mono_defaults.methodhandle_class;
12154         } else if (strcmp (obj->vtable->klass->name, "MonoArrayMethod") == 0) {
12155                 MonoReflectionArrayMethod *m = (MonoReflectionArrayMethod*)obj;
12156                 MonoType *mtype;
12157                 MonoClass *klass;
12158                 MonoMethod *method;
12159                 gpointer iter;
12160                 char *name;
12161
12162                 mtype = mono_reflection_type_get_handle (m->parent);
12163                 klass = mono_class_from_mono_type (mtype);
12164
12165                 /* Find the method */
12166
12167                 name = mono_string_to_utf8 (m->name);
12168                 iter = NULL;
12169                 while ((method = mono_class_get_methods (klass, &iter))) {
12170                         if (!strcmp (method->name, name))
12171                                 break;
12172                 }
12173                 g_free (name);
12174
12175                 // FIXME:
12176                 g_assert (method);
12177                 // FIXME: Check parameters/return value etc. match
12178
12179                 result = method;
12180                 *handle_class = mono_defaults.methodhandle_class;
12181         } else if (is_sre_array (mono_object_get_class(obj)) ||
12182                                 is_sre_byref (mono_object_get_class(obj)) ||
12183                                 is_sre_pointer (mono_object_get_class(obj))) {
12184                 MonoReflectionType *ref_type = (MonoReflectionType *)obj;
12185                 MonoType *type = mono_reflection_type_get_handle (ref_type);
12186
12187                 if (context) {
12188                         MonoType *inflated = mono_class_inflate_generic_type (type, context);
12189                         result = mono_class_from_mono_type (inflated);
12190                         mono_metadata_free_type (inflated);
12191                 } else {
12192                         result = mono_class_from_mono_type (type);
12193                 }
12194                 *handle_class = mono_defaults.typehandle_class;
12195         } else {
12196                 g_print ("%s\n", obj->vtable->klass->name);
12197                 g_assert_not_reached ();
12198         }
12199         return result;
12200 }
12201
12202 #else /* DISABLE_REFLECTION_EMIT */
12203
12204 MonoArray*
12205 mono_reflection_get_custom_attrs_blob (MonoReflectionAssembly *assembly, MonoObject *ctor, MonoArray *ctorArgs, MonoArray *properties, MonoArray *propValues, MonoArray *fields, MonoArray* fieldValues) 
12206 {
12207         g_assert_not_reached ();
12208         return NULL;
12209 }
12210
12211 void
12212 mono_reflection_setup_internal_class (MonoReflectionTypeBuilder *tb)
12213 {
12214         g_assert_not_reached ();
12215 }
12216
12217 void
12218 mono_reflection_setup_generic_class (MonoReflectionTypeBuilder *tb)
12219 {
12220         g_assert_not_reached ();
12221 }
12222
12223 void
12224 mono_reflection_create_generic_class (MonoReflectionTypeBuilder *tb)
12225 {
12226         g_assert_not_reached ();
12227 }
12228
12229 void
12230 mono_reflection_create_internal_class (MonoReflectionTypeBuilder *tb)
12231 {
12232         g_assert_not_reached ();
12233 }
12234
12235 void
12236 mono_image_basic_init (MonoReflectionAssemblyBuilder *assemblyb)
12237 {
12238         g_error ("This mono runtime was configured with --enable-minimal=reflection_emit, so System.Reflection.Emit is not supported.");
12239 }
12240
12241 void
12242 mono_image_module_basic_init (MonoReflectionModuleBuilder *moduleb)
12243 {
12244         g_assert_not_reached ();
12245 }
12246
12247 void
12248 mono_image_set_wrappers_type (MonoReflectionModuleBuilder *moduleb, MonoReflectionType *type)
12249 {
12250         g_assert_not_reached ();
12251 }
12252
12253 MonoReflectionModule *
12254 mono_image_load_module_dynamic (MonoReflectionAssemblyBuilder *ab, MonoString *fileName)
12255 {
12256         g_assert_not_reached ();
12257         return NULL;
12258 }
12259
12260 guint32
12261 mono_image_insert_string (MonoReflectionModuleBuilder *module, MonoString *str)
12262 {
12263         g_assert_not_reached ();
12264         return 0;
12265 }
12266
12267 guint32
12268 mono_image_create_method_token (MonoDynamicImage *assembly, MonoObject *obj, MonoArray *opt_param_types)
12269 {
12270         g_assert_not_reached ();
12271         return 0;
12272 }
12273
12274 guint32
12275 mono_image_create_token (MonoDynamicImage *assembly, MonoObject *obj, 
12276                                                  gboolean create_open_instance, gboolean register_token)
12277 {
12278         g_assert_not_reached ();
12279         return 0;
12280 }
12281
12282 void
12283 mono_image_register_token (MonoDynamicImage *assembly, guint32 token, MonoObject *obj)
12284 {
12285 }
12286
12287 void
12288 mono_reflection_generic_class_initialize (MonoReflectionGenericClass *type, MonoArray *fields)
12289 {
12290         g_assert_not_reached ();
12291 }
12292
12293 void
12294 mono_reflection_get_dynamic_overrides (MonoClass *klass, MonoMethod ***overrides, int *num_overrides)
12295 {
12296         *overrides = NULL;
12297         *num_overrides = 0;
12298 }
12299
12300 MonoReflectionEvent *
12301 mono_reflection_event_builder_get_event_info (MonoReflectionTypeBuilder *tb, MonoReflectionEventBuilder *eb)
12302 {
12303         g_assert_not_reached ();
12304         return NULL;
12305 }
12306
12307 MonoReflectionType*
12308 mono_reflection_create_runtime_class (MonoReflectionTypeBuilder *tb)
12309 {
12310         g_assert_not_reached ();
12311         return NULL;
12312 }
12313
12314 void
12315 mono_reflection_initialize_generic_parameter (MonoReflectionGenericParam *gparam)
12316 {
12317         g_assert_not_reached ();
12318 }
12319
12320 MonoArray *
12321 mono_reflection_sighelper_get_signature_local (MonoReflectionSigHelper *sig)
12322 {
12323         g_assert_not_reached ();
12324         return NULL;
12325 }
12326
12327 MonoArray *
12328 mono_reflection_sighelper_get_signature_field (MonoReflectionSigHelper *sig)
12329 {
12330         g_assert_not_reached ();
12331         return NULL;
12332 }
12333
12334 void 
12335 mono_reflection_create_dynamic_method (MonoReflectionDynamicMethod *mb)
12336 {
12337 }
12338
12339 gpointer
12340 mono_reflection_lookup_dynamic_token (MonoImage *image, guint32 token, gboolean valid_token, MonoClass **handle_class, MonoGenericContext *context)
12341 {
12342         return NULL;
12343 }
12344
12345 MonoType*
12346 mono_reflection_type_get_handle (MonoReflectionType* ref)
12347 {
12348         if (!ref)
12349                 return NULL;
12350         return ref->type;
12351 }
12352
12353 void
12354 mono_reflection_free_dynamic_generic_class (MonoGenericClass *gclass)
12355 {
12356         g_assert_not_reached ();
12357 }
12358
12359 #endif /* DISABLE_REFLECTION_EMIT */
12360
12361 /* SECURITY_ACTION_* are defined in mono/metadata/tabledefs.h */
12362 const static guint32 declsec_flags_map[] = {
12363         0x00000000,                                     /* empty */
12364         MONO_DECLSEC_FLAG_REQUEST,                      /* SECURITY_ACTION_REQUEST                      (x01) */
12365         MONO_DECLSEC_FLAG_DEMAND,                       /* SECURITY_ACTION_DEMAND                       (x02) */
12366         MONO_DECLSEC_FLAG_ASSERT,                       /* SECURITY_ACTION_ASSERT                       (x03) */
12367         MONO_DECLSEC_FLAG_DENY,                         /* SECURITY_ACTION_DENY                         (x04) */
12368         MONO_DECLSEC_FLAG_PERMITONLY,                   /* SECURITY_ACTION_PERMITONLY                   (x05) */
12369         MONO_DECLSEC_FLAG_LINKDEMAND,                   /* SECURITY_ACTION_LINKDEMAND                   (x06) */
12370         MONO_DECLSEC_FLAG_INHERITANCEDEMAND,            /* SECURITY_ACTION_INHERITANCEDEMAND            (x07) */
12371         MONO_DECLSEC_FLAG_REQUEST_MINIMUM,              /* SECURITY_ACTION_REQUEST_MINIMUM              (x08) */
12372         MONO_DECLSEC_FLAG_REQUEST_OPTIONAL,             /* SECURITY_ACTION_REQUEST_OPTIONAL             (x09) */
12373         MONO_DECLSEC_FLAG_REQUEST_REFUSE,               /* SECURITY_ACTION_REQUEST_REFUSE               (x0A) */
12374         MONO_DECLSEC_FLAG_PREJIT_GRANT,                 /* SECURITY_ACTION_PREJIT_GRANT                 (x0B) */
12375         MONO_DECLSEC_FLAG_PREJIT_DENY,                  /* SECURITY_ACTION_PREJIT_DENY                  (x0C) */
12376         MONO_DECLSEC_FLAG_NONCAS_DEMAND,                /* SECURITY_ACTION_NONCAS_DEMAND                (x0D) */
12377         MONO_DECLSEC_FLAG_NONCAS_LINKDEMAND,            /* SECURITY_ACTION_NONCAS_LINKDEMAND            (x0E) */
12378         MONO_DECLSEC_FLAG_NONCAS_INHERITANCEDEMAND,     /* SECURITY_ACTION_NONCAS_INHERITANCEDEMAND     (x0F) */
12379         MONO_DECLSEC_FLAG_LINKDEMAND_CHOICE,            /* SECURITY_ACTION_LINKDEMAND_CHOICE            (x10) */
12380         MONO_DECLSEC_FLAG_INHERITANCEDEMAND_CHOICE,     /* SECURITY_ACTION_INHERITANCEDEMAND_CHOICE     (x11) */
12381         MONO_DECLSEC_FLAG_DEMAND_CHOICE,                /* SECURITY_ACTION_DEMAND_CHOICE                (x12) */
12382 };
12383
12384 /*
12385  * Returns flags that includes all available security action associated to the handle.
12386  * @token: metadata token (either for a class or a method)
12387  * @image: image where resides the metadata.
12388  */
12389 static guint32
12390 mono_declsec_get_flags (MonoImage *image, guint32 token)
12391 {
12392         int index = mono_metadata_declsec_from_index (image, token);
12393         MonoTableInfo *t = &image->tables [MONO_TABLE_DECLSECURITY];
12394         guint32 result = 0;
12395         guint32 action;
12396         int i;
12397
12398         /* HasSecurity can be present for other, not specially encoded, attributes,
12399            e.g. SuppressUnmanagedCodeSecurityAttribute */
12400         if (index < 0)
12401                 return 0;
12402
12403         for (i = index; i < t->rows; i++) {
12404                 guint32 cols [MONO_DECL_SECURITY_SIZE];
12405
12406                 mono_metadata_decode_row (t, i, cols, MONO_DECL_SECURITY_SIZE);
12407                 if (cols [MONO_DECL_SECURITY_PARENT] != token)
12408                         break;
12409
12410                 action = cols [MONO_DECL_SECURITY_ACTION];
12411                 if ((action >= MONO_DECLSEC_ACTION_MIN) && (action <= MONO_DECLSEC_ACTION_MAX)) {
12412                         result |= declsec_flags_map [action];
12413                 } else {
12414                         g_assert_not_reached ();
12415                 }
12416         }
12417         return result;
12418 }
12419
12420 /*
12421  * Get the security actions (in the form of flags) associated with the specified method.
12422  *
12423  * @method: The method for which we want the declarative security flags.
12424  * Return the declarative security flags for the method (only).
12425  *
12426  * Note: To keep MonoMethod size down we do not cache the declarative security flags
12427  *       (except for the stack modifiers which are kept in the MonoJitInfo structure)
12428  */
12429 guint32
12430 mono_declsec_flags_from_method (MonoMethod *method)
12431 {
12432         if (method->flags & METHOD_ATTRIBUTE_HAS_SECURITY) {
12433                 /* FIXME: No cache (for the moment) */
12434                 guint32 idx = mono_method_get_index (method);
12435                 idx <<= MONO_HAS_DECL_SECURITY_BITS;
12436                 idx |= MONO_HAS_DECL_SECURITY_METHODDEF;
12437                 return mono_declsec_get_flags (method->klass->image, idx);
12438         }
12439         return 0;
12440 }
12441
12442 /*
12443  * Get the security actions (in the form of flags) associated with the specified class.
12444  *
12445  * @klass: The class for which we want the declarative security flags.
12446  * Return the declarative security flags for the class.
12447  *
12448  * Note: We cache the flags inside the MonoClass structure as this will get 
12449  *       called very often (at least for each method).
12450  */
12451 guint32
12452 mono_declsec_flags_from_class (MonoClass *klass)
12453 {
12454         if (klass->flags & TYPE_ATTRIBUTE_HAS_SECURITY) {
12455                 if (!klass->ext || !klass->ext->declsec_flags) {
12456                         guint32 idx;
12457
12458                         idx = mono_metadata_token_index (klass->type_token);
12459                         idx <<= MONO_HAS_DECL_SECURITY_BITS;
12460                         idx |= MONO_HAS_DECL_SECURITY_TYPEDEF;
12461                         mono_loader_lock ();
12462                         mono_class_alloc_ext (klass);
12463                         mono_loader_unlock ();
12464                         /* we cache the flags on classes */
12465                         klass->ext->declsec_flags = mono_declsec_get_flags (klass->image, idx);
12466                 }
12467                 return klass->ext->declsec_flags;
12468         }
12469         return 0;
12470 }
12471
12472 /*
12473  * Get the security actions (in the form of flags) associated with the specified assembly.
12474  *
12475  * @assembly: The assembly for which we want the declarative security flags.
12476  * Return the declarative security flags for the assembly.
12477  */
12478 guint32
12479 mono_declsec_flags_from_assembly (MonoAssembly *assembly)
12480 {
12481         guint32 idx = 1; /* there is only one assembly */
12482         idx <<= MONO_HAS_DECL_SECURITY_BITS;
12483         idx |= MONO_HAS_DECL_SECURITY_ASSEMBLY;
12484         return mono_declsec_get_flags (assembly->image, idx);
12485 }
12486
12487
12488 /*
12489  * Fill actions for the specific index (which may either be an encoded class token or
12490  * an encoded method token) from the metadata image.
12491  * Returns TRUE if some actions requiring code generation are present, FALSE otherwise.
12492  */
12493 static MonoBoolean
12494 fill_actions_from_index (MonoImage *image, guint32 token, MonoDeclSecurityActions* actions,
12495         guint32 id_std, guint32 id_noncas, guint32 id_choice)
12496 {
12497         MonoBoolean result = FALSE;
12498         MonoTableInfo *t;
12499         guint32 cols [MONO_DECL_SECURITY_SIZE];
12500         int index = mono_metadata_declsec_from_index (image, token);
12501         int i;
12502
12503         t  = &image->tables [MONO_TABLE_DECLSECURITY];
12504         for (i = index; i < t->rows; i++) {
12505                 mono_metadata_decode_row (t, i, cols, MONO_DECL_SECURITY_SIZE);
12506
12507                 if (cols [MONO_DECL_SECURITY_PARENT] != token)
12508                         return result;
12509
12510                 /* if present only replace (class) permissions with method permissions */
12511                 /* if empty accept either class or method permissions */
12512                 if (cols [MONO_DECL_SECURITY_ACTION] == id_std) {
12513                         if (!actions->demand.blob) {
12514                                 const char *blob = mono_metadata_blob_heap (image, cols [MONO_DECL_SECURITY_PERMISSIONSET]);
12515                                 actions->demand.index = cols [MONO_DECL_SECURITY_PERMISSIONSET];
12516                                 actions->demand.blob = (char*) (blob + 2);
12517                                 actions->demand.size = mono_metadata_decode_blob_size (blob, &blob);
12518                                 result = TRUE;
12519                         }
12520                 } else if (cols [MONO_DECL_SECURITY_ACTION] == id_noncas) {
12521                         if (!actions->noncasdemand.blob) {
12522                                 const char *blob = mono_metadata_blob_heap (image, cols [MONO_DECL_SECURITY_PERMISSIONSET]);
12523                                 actions->noncasdemand.index = cols [MONO_DECL_SECURITY_PERMISSIONSET];
12524                                 actions->noncasdemand.blob = (char*) (blob + 2);
12525                                 actions->noncasdemand.size = mono_metadata_decode_blob_size (blob, &blob);
12526                                 result = TRUE;
12527                         }
12528                 } else if (cols [MONO_DECL_SECURITY_ACTION] == id_choice) {
12529                         if (!actions->demandchoice.blob) {
12530                                 const char *blob = mono_metadata_blob_heap (image, cols [MONO_DECL_SECURITY_PERMISSIONSET]);
12531                                 actions->demandchoice.index = cols [MONO_DECL_SECURITY_PERMISSIONSET];
12532                                 actions->demandchoice.blob = (char*) (blob + 2);
12533                                 actions->demandchoice.size = mono_metadata_decode_blob_size (blob, &blob);
12534                                 result = TRUE;
12535                         }
12536                 }
12537         }
12538
12539         return result;
12540 }
12541
12542 static MonoBoolean
12543 mono_declsec_get_class_demands_params (MonoClass *klass, MonoDeclSecurityActions* demands, 
12544         guint32 id_std, guint32 id_noncas, guint32 id_choice)
12545 {
12546         guint32 idx = mono_metadata_token_index (klass->type_token);
12547         idx <<= MONO_HAS_DECL_SECURITY_BITS;
12548         idx |= MONO_HAS_DECL_SECURITY_TYPEDEF;
12549         return fill_actions_from_index (klass->image, idx, demands, id_std, id_noncas, id_choice);
12550 }
12551
12552 static MonoBoolean
12553 mono_declsec_get_method_demands_params (MonoMethod *method, MonoDeclSecurityActions* demands, 
12554         guint32 id_std, guint32 id_noncas, guint32 id_choice)
12555 {
12556         guint32 idx = mono_method_get_index (method);
12557         idx <<= MONO_HAS_DECL_SECURITY_BITS;
12558         idx |= MONO_HAS_DECL_SECURITY_METHODDEF;
12559         return fill_actions_from_index (method->klass->image, idx, demands, id_std, id_noncas, id_choice);
12560 }
12561
12562 /*
12563  * Collect all actions (that requires to generate code in mini) assigned for
12564  * the specified method.
12565  * Note: Don't use the content of actions if the function return FALSE.
12566  */
12567 MonoBoolean
12568 mono_declsec_get_demands (MonoMethod *method, MonoDeclSecurityActions* demands)
12569 {
12570         guint32 mask = MONO_DECLSEC_FLAG_DEMAND | MONO_DECLSEC_FLAG_NONCAS_DEMAND | 
12571                 MONO_DECLSEC_FLAG_DEMAND_CHOICE;
12572         MonoBoolean result = FALSE;
12573         guint32 flags;
12574
12575         /* quick exit if no declarative security is present in the metadata */
12576         if (!method->klass->image->tables [MONO_TABLE_DECLSECURITY].rows)
12577                 return FALSE;
12578
12579         /* we want the original as the wrapper is "free" of the security informations */
12580         if (method->wrapper_type == MONO_WRAPPER_MANAGED_TO_NATIVE || method->wrapper_type == MONO_WRAPPER_MANAGED_TO_MANAGED) {
12581                 method = mono_marshal_method_from_wrapper (method);
12582                 if (!method)
12583                         return FALSE;
12584         }
12585
12586         /* First we look for method-level attributes */
12587         if (method->flags & METHOD_ATTRIBUTE_HAS_SECURITY) {
12588                 mono_class_init (method->klass);
12589                 memset (demands, 0, sizeof (MonoDeclSecurityActions));
12590
12591                 result = mono_declsec_get_method_demands_params (method, demands, 
12592                         SECURITY_ACTION_DEMAND, SECURITY_ACTION_NONCASDEMAND, SECURITY_ACTION_DEMANDCHOICE);
12593         }
12594
12595         /* Here we use (or create) the class declarative cache to look for demands */
12596         flags = mono_declsec_flags_from_class (method->klass);
12597         if (flags & mask) {
12598                 if (!result) {
12599                         mono_class_init (method->klass);
12600                         memset (demands, 0, sizeof (MonoDeclSecurityActions));
12601                 }
12602                 result |= mono_declsec_get_class_demands_params (method->klass, demands, 
12603                         SECURITY_ACTION_DEMAND, SECURITY_ACTION_NONCASDEMAND, SECURITY_ACTION_DEMANDCHOICE);
12604         }
12605
12606         /* The boolean return value is used as a shortcut in case nothing needs to
12607            be generated (e.g. LinkDemand[Choice] and InheritanceDemand[Choice]) */
12608         return result;
12609 }
12610
12611
12612 /*
12613  * Collect all Link actions: LinkDemand, NonCasLinkDemand and LinkDemandChoice (2.0).
12614  *
12615  * Note: Don't use the content of actions if the function return FALSE.
12616  */
12617 MonoBoolean
12618 mono_declsec_get_linkdemands (MonoMethod *method, MonoDeclSecurityActions* klass, MonoDeclSecurityActions *cmethod)
12619 {
12620         MonoBoolean result = FALSE;
12621         guint32 flags;
12622
12623         /* quick exit if no declarative security is present in the metadata */
12624         if (!method->klass->image->tables [MONO_TABLE_DECLSECURITY].rows)
12625                 return FALSE;
12626
12627         /* we want the original as the wrapper is "free" of the security informations */
12628         if (method->wrapper_type == MONO_WRAPPER_MANAGED_TO_NATIVE || method->wrapper_type == MONO_WRAPPER_MANAGED_TO_MANAGED) {
12629                 method = mono_marshal_method_from_wrapper (method);
12630                 if (!method)
12631                         return FALSE;
12632         }
12633
12634         /* results are independant - zeroize both */
12635         memset (cmethod, 0, sizeof (MonoDeclSecurityActions));
12636         memset (klass, 0, sizeof (MonoDeclSecurityActions));
12637
12638         /* First we look for method-level attributes */
12639         if (method->flags & METHOD_ATTRIBUTE_HAS_SECURITY) {
12640                 mono_class_init (method->klass);
12641
12642                 result = mono_declsec_get_method_demands_params (method, cmethod, 
12643                         SECURITY_ACTION_LINKDEMAND, SECURITY_ACTION_NONCASLINKDEMAND, SECURITY_ACTION_LINKDEMANDCHOICE);
12644         }
12645
12646         /* Here we use (or create) the class declarative cache to look for demands */
12647         flags = mono_declsec_flags_from_class (method->klass);
12648         if (flags & (MONO_DECLSEC_FLAG_LINKDEMAND | MONO_DECLSEC_FLAG_NONCAS_LINKDEMAND | MONO_DECLSEC_FLAG_LINKDEMAND_CHOICE)) {
12649                 mono_class_init (method->klass);
12650
12651                 result |= mono_declsec_get_class_demands_params (method->klass, klass, 
12652                         SECURITY_ACTION_LINKDEMAND, SECURITY_ACTION_NONCASLINKDEMAND, SECURITY_ACTION_LINKDEMANDCHOICE);
12653         }
12654
12655         return result;
12656 }
12657
12658 /*
12659  * Collect all Inherit actions: InheritanceDemand, NonCasInheritanceDemand and InheritanceDemandChoice (2.0).
12660  *
12661  * @klass       The inherited class - this is the class that provides the security check (attributes)
12662  * @demans      
12663  * return TRUE if inheritance demands (any kind) are present, FALSE otherwise.
12664  * 
12665  * Note: Don't use the content of actions if the function return FALSE.
12666  */
12667 MonoBoolean
12668 mono_declsec_get_inheritdemands_class (MonoClass *klass, MonoDeclSecurityActions* demands)
12669 {
12670         MonoBoolean result = FALSE;
12671         guint32 flags;
12672
12673         /* quick exit if no declarative security is present in the metadata */
12674         if (!klass->image->tables [MONO_TABLE_DECLSECURITY].rows)
12675                 return FALSE;
12676
12677         /* Here we use (or create) the class declarative cache to look for demands */
12678         flags = mono_declsec_flags_from_class (klass);
12679         if (flags & (MONO_DECLSEC_FLAG_INHERITANCEDEMAND | MONO_DECLSEC_FLAG_NONCAS_INHERITANCEDEMAND | MONO_DECLSEC_FLAG_INHERITANCEDEMAND_CHOICE)) {
12680                 mono_class_init (klass);
12681                 memset (demands, 0, sizeof (MonoDeclSecurityActions));
12682
12683                 result |= mono_declsec_get_class_demands_params (klass, demands, 
12684                         SECURITY_ACTION_INHERITDEMAND, SECURITY_ACTION_NONCASINHERITANCE, SECURITY_ACTION_INHERITDEMANDCHOICE);
12685         }
12686
12687         return result;
12688 }
12689
12690 /*
12691  * Collect all Inherit actions: InheritanceDemand, NonCasInheritanceDemand and InheritanceDemandChoice (2.0).
12692  *
12693  * Note: Don't use the content of actions if the function return FALSE.
12694  */
12695 MonoBoolean
12696 mono_declsec_get_inheritdemands_method (MonoMethod *method, MonoDeclSecurityActions* demands)
12697 {
12698         /* quick exit if no declarative security is present in the metadata */
12699         if (!method->klass->image->tables [MONO_TABLE_DECLSECURITY].rows)
12700                 return FALSE;
12701
12702         /* we want the original as the wrapper is "free" of the security informations */
12703         if (method->wrapper_type == MONO_WRAPPER_MANAGED_TO_NATIVE || method->wrapper_type == MONO_WRAPPER_MANAGED_TO_MANAGED) {
12704                 method = mono_marshal_method_from_wrapper (method);
12705                 if (!method)
12706                         return FALSE;
12707         }
12708
12709         if (method->flags & METHOD_ATTRIBUTE_HAS_SECURITY) {
12710                 mono_class_init (method->klass);
12711                 memset (demands, 0, sizeof (MonoDeclSecurityActions));
12712
12713                 return mono_declsec_get_method_demands_params (method, demands, 
12714                         SECURITY_ACTION_INHERITDEMAND, SECURITY_ACTION_NONCASINHERITANCE, SECURITY_ACTION_INHERITDEMANDCHOICE);
12715         }
12716         return FALSE;
12717 }
12718
12719
12720 static MonoBoolean
12721 get_declsec_action (MonoImage *image, guint32 token, guint32 action, MonoDeclSecurityEntry *entry)
12722 {
12723         guint32 cols [MONO_DECL_SECURITY_SIZE];
12724         MonoTableInfo *t;
12725         int i;
12726
12727         int index = mono_metadata_declsec_from_index (image, token);
12728         if (index == -1)
12729                 return FALSE;
12730
12731         t =  &image->tables [MONO_TABLE_DECLSECURITY];
12732         for (i = index; i < t->rows; i++) {
12733                 mono_metadata_decode_row (t, i, cols, MONO_DECL_SECURITY_SIZE);
12734
12735                 /* shortcut - index are ordered */
12736                 if (token != cols [MONO_DECL_SECURITY_PARENT])
12737                         return FALSE;
12738
12739                 if (cols [MONO_DECL_SECURITY_ACTION] == action) {
12740                         const char *metadata = mono_metadata_blob_heap (image, cols [MONO_DECL_SECURITY_PERMISSIONSET]);
12741                         entry->blob = (char*) (metadata + 2);
12742                         entry->size = mono_metadata_decode_blob_size (metadata, &metadata);
12743                         return TRUE;
12744                 }
12745         }
12746
12747         return FALSE;
12748 }
12749
12750 MonoBoolean
12751 mono_declsec_get_method_action (MonoMethod *method, guint32 action, MonoDeclSecurityEntry *entry)
12752 {
12753         if (method->flags & METHOD_ATTRIBUTE_HAS_SECURITY) {
12754                 guint32 idx = mono_method_get_index (method);
12755                 idx <<= MONO_HAS_DECL_SECURITY_BITS;
12756                 idx |= MONO_HAS_DECL_SECURITY_METHODDEF;
12757                 return get_declsec_action (method->klass->image, idx, action, entry);
12758         }
12759         return FALSE;
12760 }
12761
12762 MonoBoolean
12763 mono_declsec_get_class_action (MonoClass *klass, guint32 action, MonoDeclSecurityEntry *entry)
12764 {
12765         /* use cache */
12766         guint32 flags = mono_declsec_flags_from_class (klass);
12767         if (declsec_flags_map [action] & flags) {
12768                 guint32 idx = mono_metadata_token_index (klass->type_token);
12769                 idx <<= MONO_HAS_DECL_SECURITY_BITS;
12770                 idx |= MONO_HAS_DECL_SECURITY_TYPEDEF;
12771                 return get_declsec_action (klass->image, idx, action, entry);
12772         }
12773         return FALSE;
12774 }
12775
12776 MonoBoolean
12777 mono_declsec_get_assembly_action (MonoAssembly *assembly, guint32 action, MonoDeclSecurityEntry *entry)
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
12783         return get_declsec_action (assembly->image, idx, action, entry);
12784 }
12785
12786 gboolean
12787 mono_reflection_call_is_assignable_to (MonoClass *klass, MonoClass *oklass)
12788 {
12789         MonoObject *res, *exc;
12790         void *params [1];
12791         static MonoClass *System_Reflection_Emit_TypeBuilder = NULL;
12792         static MonoMethod *method = NULL;
12793
12794         if (!System_Reflection_Emit_TypeBuilder) {
12795                 System_Reflection_Emit_TypeBuilder = mono_class_from_name (mono_defaults.corlib, "System.Reflection.Emit", "TypeBuilder");
12796                 g_assert (System_Reflection_Emit_TypeBuilder);
12797         }
12798         if (method == NULL) {
12799                 method = mono_class_get_method_from_name (System_Reflection_Emit_TypeBuilder, "IsAssignableTo", 1);
12800                 g_assert (method);
12801         }
12802
12803         /* 
12804          * The result of mono_type_get_object () might be a System.MonoType but we
12805          * need a TypeBuilder so use mono_class_get_ref_info (klass).
12806          */
12807         g_assert (mono_class_get_ref_info (klass));
12808         g_assert (!strcmp (((MonoObject*)(mono_class_get_ref_info (klass)))->vtable->klass->name, "TypeBuilder"));
12809
12810         params [0] = mono_type_get_object (mono_domain_get (), &oklass->byval_arg);
12811
12812         res = mono_runtime_invoke (method, (MonoObject*)(mono_class_get_ref_info (klass)), params, &exc);
12813         if (exc)
12814                 return FALSE;
12815         else
12816                 return *(MonoBoolean*)mono_object_unbox (res);
12817 }
12818
12819 /**
12820  * mono_reflection_type_get_type:
12821  * @reftype: the System.Type object
12822  *
12823  * Returns the MonoType* associated with the C# System.Type object @reftype.
12824  */
12825 MonoType*
12826 mono_reflection_type_get_type (MonoReflectionType *reftype)
12827 {
12828         g_assert (reftype);
12829
12830         return mono_reflection_type_get_handle (reftype);
12831 }
12832
12833 /**
12834  * mono_reflection_assembly_get_assembly:
12835  * @refassembly: the System.Reflection.Assembly object
12836  *
12837  * Returns the MonoAssembly* associated with the C# System.Reflection.Assembly object @refassembly.
12838  */
12839 MonoAssembly*
12840 mono_reflection_assembly_get_assembly (MonoReflectionAssembly *refassembly)
12841 {
12842         g_assert (refassembly);
12843
12844         return refassembly->assembly;
12845 }
12846