88bb0d38d14c3725dc689c36759433fdd06ef317
[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.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 (ta->dynamic || (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                                 MonoClass *class = mono_class_get (field_image, type->modifiers [i].token);
1706                                 g_assert (class);
1707                                 token = mono_image_typedef_or_ref (assembly, &class->byval_arg);
1708                         } else {
1709                                 token = type->modifiers [i].token;
1710                         }
1711
1712                         if (type->modifiers [i].required)
1713                                 sigbuffer_add_byte (&buf, MONO_TYPE_CMOD_REQD);
1714                         else
1715                                 sigbuffer_add_byte (&buf, MONO_TYPE_CMOD_OPT);
1716
1717                         sigbuffer_add_value (&buf, token);
1718                 }
1719         }
1720         encode_type (assembly, type, &buf);
1721         idx = sigbuffer_add_to_blob_cached (assembly, &buf);
1722         sigbuffer_free (&buf);
1723         return idx;
1724 }
1725 #endif
1726
1727 static guint32
1728 field_encode_signature (MonoDynamicImage *assembly, MonoReflectionFieldBuilder *fb)
1729 {
1730         SigBuffer buf;
1731         guint32 idx;
1732         guint32 typespec = 0;
1733         MonoType *type;
1734         MonoClass *class;
1735
1736         init_type_builder_generics (fb->type);
1737
1738         type = mono_reflection_type_get_handle ((MonoReflectionType*)fb->type);
1739         class = mono_class_from_mono_type (type);
1740
1741         sigbuffer_init (&buf, 32);
1742         
1743         sigbuffer_add_value (&buf, 0x06);
1744         encode_custom_modifiers (assembly, fb->modreq, fb->modopt, &buf);
1745         /* encode custom attributes before the type */
1746
1747         if (class->generic_container)
1748                 typespec = create_typespec (assembly, type);
1749
1750         if (typespec) {
1751                 MonoGenericClass *gclass;
1752                 gclass = mono_metadata_lookup_generic_class (class, class->generic_container->context.class_inst, TRUE);
1753                 encode_generic_class (assembly, gclass, &buf);
1754         } else {
1755                 encode_type (assembly, type, &buf);
1756         }
1757         idx = sigbuffer_add_to_blob_cached (assembly, &buf);
1758         sigbuffer_free (&buf);
1759         return idx;
1760 }
1761
1762 static guint32
1763 encode_constant (MonoDynamicImage *assembly, MonoObject *val, guint32 *ret_type) {
1764         char blob_size [64];
1765         char *b = blob_size;
1766         char *p, *box_val;
1767         char* buf;
1768         guint32 idx = 0, len = 0, dummy = 0;
1769
1770         p = buf = g_malloc (64);
1771         if (!val) {
1772                 *ret_type = MONO_TYPE_CLASS;
1773                 len = 4;
1774                 box_val = (char*)&dummy;
1775         } else {
1776                 box_val = ((char*)val) + sizeof (MonoObject);
1777                 *ret_type = val->vtable->klass->byval_arg.type;
1778         }
1779 handle_enum:
1780         switch (*ret_type) {
1781         case MONO_TYPE_BOOLEAN:
1782         case MONO_TYPE_U1:
1783         case MONO_TYPE_I1:
1784                 len = 1;
1785                 break;
1786         case MONO_TYPE_CHAR:
1787         case MONO_TYPE_U2:
1788         case MONO_TYPE_I2:
1789                 len = 2;
1790                 break;
1791         case MONO_TYPE_U4:
1792         case MONO_TYPE_I4:
1793         case MONO_TYPE_R4:
1794                 len = 4;
1795                 break;
1796         case MONO_TYPE_U8:
1797         case MONO_TYPE_I8:
1798                 len = 8;
1799                 break;
1800         case MONO_TYPE_R8:
1801                 len = 8;
1802                 break;
1803         case MONO_TYPE_VALUETYPE: {
1804                 MonoClass *klass = val->vtable->klass;
1805                 
1806                 if (klass->enumtype) {
1807                         *ret_type = mono_class_enum_basetype (klass)->type;
1808                         goto handle_enum;
1809                 } else if (mono_is_corlib_image (klass->image) && strcmp (klass->name_space, "System") == 0 && strcmp (klass->name, "DateTime") == 0) {
1810                         len = 8;
1811                 } else 
1812                         g_error ("we can't encode valuetypes, we should have never reached this line");
1813                 break;
1814         }
1815         case MONO_TYPE_CLASS:
1816                 break;
1817         case MONO_TYPE_STRING: {
1818                 MonoString *str = (MonoString*)val;
1819                 /* there is no signature */
1820                 len = str->length * 2;
1821                 mono_metadata_encode_value (len, b, &b);
1822 #if G_BYTE_ORDER != G_LITTLE_ENDIAN
1823                 {
1824                         char *swapped = g_malloc (2 * mono_string_length (str));
1825                         const char *p = (const char*)mono_string_chars (str);
1826
1827                         swap_with_size (swapped, p, 2, mono_string_length (str));
1828                         idx = add_to_blob_cached (assembly, blob_size, b-blob_size, swapped, len);
1829                         g_free (swapped);
1830                 }
1831 #else
1832                 idx = add_to_blob_cached (assembly, blob_size, b-blob_size, (char*)mono_string_chars (str), len);
1833 #endif
1834
1835                 g_free (buf);
1836                 return idx;
1837         }
1838         case MONO_TYPE_GENERICINST:
1839                 *ret_type = val->vtable->klass->generic_class->container_class->byval_arg.type;
1840                 goto handle_enum;
1841         default:
1842                 g_error ("we don't encode constant type 0x%02x yet", *ret_type);
1843         }
1844
1845         /* there is no signature */
1846         mono_metadata_encode_value (len, b, &b);
1847 #if G_BYTE_ORDER != G_LITTLE_ENDIAN
1848         idx = mono_image_add_stream_data (&assembly->blob, blob_size, b-blob_size);
1849         swap_with_size (blob_size, box_val, len, 1);
1850         mono_image_add_stream_data (&assembly->blob, blob_size, len);
1851 #else
1852         idx = add_to_blob_cached (assembly, blob_size, b-blob_size, box_val, len);
1853 #endif
1854
1855         g_free (buf);
1856         return idx;
1857 }
1858
1859 static guint32
1860 encode_marshal_blob (MonoDynamicImage *assembly, MonoReflectionMarshal *minfo) {
1861         char *str;
1862         SigBuffer buf;
1863         guint32 idx, len;
1864
1865         sigbuffer_init (&buf, 32);
1866
1867         sigbuffer_add_value (&buf, minfo->type);
1868
1869         switch (minfo->type) {
1870         case MONO_NATIVE_BYVALTSTR:
1871         case MONO_NATIVE_BYVALARRAY:
1872                 sigbuffer_add_value (&buf, minfo->count);
1873                 break;
1874         case MONO_NATIVE_LPARRAY:
1875                 if (minfo->eltype || minfo->has_size) {
1876                         sigbuffer_add_value (&buf, minfo->eltype);
1877                         if (minfo->has_size) {
1878                                 sigbuffer_add_value (&buf, minfo->param_num != -1? minfo->param_num: 0);
1879                                 sigbuffer_add_value (&buf, minfo->count != -1? minfo->count: 0);
1880
1881                                 /* LAMESPEC: ElemMult is undocumented */
1882                                 sigbuffer_add_value (&buf, minfo->param_num != -1? 1: 0);
1883                         }
1884                 }
1885                 break;
1886         case MONO_NATIVE_SAFEARRAY:
1887                 if (minfo->eltype)
1888                         sigbuffer_add_value (&buf, minfo->eltype);
1889                 break;
1890         case MONO_NATIVE_CUSTOM:
1891                 if (minfo->guid) {
1892                         str = mono_string_to_utf8 (minfo->guid);
1893                         len = strlen (str);
1894                         sigbuffer_add_value (&buf, len);
1895                         sigbuffer_add_mem (&buf, str, len);
1896                         g_free (str);
1897                 } else {
1898                         sigbuffer_add_value (&buf, 0);
1899                 }
1900                 /* native type name */
1901                 sigbuffer_add_value (&buf, 0);
1902                 /* custom marshaler type name */
1903                 if (minfo->marshaltype || minfo->marshaltyperef) {
1904                         if (minfo->marshaltyperef)
1905                                 str = type_get_fully_qualified_name (mono_reflection_type_get_handle ((MonoReflectionType*)minfo->marshaltyperef));
1906                         else
1907                                 str = mono_string_to_utf8 (minfo->marshaltype);
1908                         len = strlen (str);
1909                         sigbuffer_add_value (&buf, len);
1910                         sigbuffer_add_mem (&buf, str, len);
1911                         g_free (str);
1912                 } else {
1913                         /* FIXME: Actually a bug, since this field is required.  Punting for now ... */
1914                         sigbuffer_add_value (&buf, 0);
1915                 }
1916                 if (minfo->mcookie) {
1917                         str = mono_string_to_utf8 (minfo->mcookie);
1918                         len = strlen (str);
1919                         sigbuffer_add_value (&buf, len);
1920                         sigbuffer_add_mem (&buf, str, len);
1921                         g_free (str);
1922                 } else {
1923                         sigbuffer_add_value (&buf, 0);
1924                 }
1925                 break;
1926         default:
1927                 break;
1928         }
1929         idx = sigbuffer_add_to_blob_cached (assembly, &buf);
1930         sigbuffer_free (&buf);
1931         return idx;
1932 }
1933
1934 static void
1935 mono_image_get_field_info (MonoReflectionFieldBuilder *fb, MonoDynamicImage *assembly)
1936 {
1937         MonoDynamicTable *table;
1938         guint32 *values;
1939
1940         /* maybe this fixup should be done in the C# code */
1941         if (fb->attrs & FIELD_ATTRIBUTE_LITERAL)
1942                 fb->attrs |= FIELD_ATTRIBUTE_HAS_DEFAULT;
1943         table = &assembly->tables [MONO_TABLE_FIELD];
1944         fb->table_idx = table->next_idx ++;
1945         g_hash_table_insert (assembly->field_to_table_idx, fb->handle, GUINT_TO_POINTER (fb->table_idx));
1946         values = table->values + fb->table_idx * MONO_FIELD_SIZE;
1947         values [MONO_FIELD_NAME] = string_heap_insert_mstring (&assembly->sheap, fb->name);
1948         values [MONO_FIELD_FLAGS] = fb->attrs;
1949         values [MONO_FIELD_SIGNATURE] = field_encode_signature (assembly, fb);
1950
1951         if (fb->offset != -1) {
1952                 table = &assembly->tables [MONO_TABLE_FIELDLAYOUT];
1953                 table->rows ++;
1954                 alloc_table (table, table->rows);
1955                 values = table->values + table->rows * MONO_FIELD_LAYOUT_SIZE;
1956                 values [MONO_FIELD_LAYOUT_FIELD] = fb->table_idx;
1957                 values [MONO_FIELD_LAYOUT_OFFSET] = fb->offset;
1958         }
1959         if (fb->attrs & FIELD_ATTRIBUTE_LITERAL) {
1960                 guint32 field_type = 0;
1961                 table = &assembly->tables [MONO_TABLE_CONSTANT];
1962                 table->rows ++;
1963                 alloc_table (table, table->rows);
1964                 values = table->values + table->rows * MONO_CONSTANT_SIZE;
1965                 values [MONO_CONSTANT_PARENT] = MONO_HASCONSTANT_FIEDDEF | (fb->table_idx << MONO_HASCONSTANT_BITS);
1966                 values [MONO_CONSTANT_VALUE] = encode_constant (assembly, fb->def_value, &field_type);
1967                 values [MONO_CONSTANT_TYPE] = field_type;
1968                 values [MONO_CONSTANT_PADDING] = 0;
1969         }
1970         if (fb->attrs & FIELD_ATTRIBUTE_HAS_FIELD_RVA) {
1971                 guint32 rva_idx;
1972                 table = &assembly->tables [MONO_TABLE_FIELDRVA];
1973                 table->rows ++;
1974                 alloc_table (table, table->rows);
1975                 values = table->values + table->rows * MONO_FIELD_RVA_SIZE;
1976                 values [MONO_FIELD_RVA_FIELD] = fb->table_idx;
1977                 /*
1978                  * We store it in the code section because it's simpler for now.
1979                  */
1980                 if (fb->rva_data) {
1981                         if (mono_array_length (fb->rva_data) >= 10)
1982                                 stream_data_align (&assembly->code);
1983                         rva_idx = mono_image_add_stream_data (&assembly->code, mono_array_addr (fb->rva_data, char, 0), mono_array_length (fb->rva_data));
1984                 } else
1985                         rva_idx = mono_image_add_stream_zero (&assembly->code, mono_class_value_size (fb->handle->parent, NULL));
1986                 values [MONO_FIELD_RVA_RVA] = rva_idx + assembly->text_rva;
1987         }
1988         if (fb->marshal_info) {
1989                 table = &assembly->tables [MONO_TABLE_FIELDMARSHAL];
1990                 table->rows ++;
1991                 alloc_table (table, table->rows);
1992                 values = table->values + table->rows * MONO_FIELD_MARSHAL_SIZE;
1993                 values [MONO_FIELD_MARSHAL_PARENT] = (fb->table_idx << MONO_HAS_FIELD_MARSHAL_BITS) | MONO_HAS_FIELD_MARSHAL_FIELDSREF;
1994                 values [MONO_FIELD_MARSHAL_NATIVE_TYPE] = encode_marshal_blob (assembly, fb->marshal_info);
1995         }
1996 }
1997
1998 static guint32
1999 property_encode_signature (MonoDynamicImage *assembly, MonoReflectionPropertyBuilder *fb)
2000 {
2001         SigBuffer buf;
2002         guint32 nparams = 0;
2003         MonoReflectionMethodBuilder *mb = fb->get_method;
2004         MonoReflectionMethodBuilder *smb = fb->set_method;
2005         guint32 idx, i;
2006
2007         if (mb && mb->parameters)
2008                 nparams = mono_array_length (mb->parameters);
2009         if (!mb && smb && smb->parameters)
2010                 nparams = mono_array_length (smb->parameters) - 1;
2011         sigbuffer_init (&buf, 32);
2012         if (fb->call_conv & 0x20)
2013                 sigbuffer_add_byte (&buf, 0x28);
2014         else
2015                 sigbuffer_add_byte (&buf, 0x08);
2016         sigbuffer_add_value (&buf, nparams);
2017         if (mb) {
2018                 encode_reflection_type (assembly, (MonoReflectionType*)mb->rtype, &buf);
2019                 for (i = 0; i < nparams; ++i) {
2020                         MonoReflectionType *pt = mono_array_get (mb->parameters, MonoReflectionType*, i);
2021                         encode_reflection_type (assembly, pt, &buf);
2022                 }
2023         } else if (smb && smb->parameters) {
2024                 /* the property type is the last param */
2025                 encode_reflection_type (assembly, mono_array_get (smb->parameters, MonoReflectionType*, nparams), &buf);
2026                 for (i = 0; i < nparams; ++i) {
2027                         MonoReflectionType *pt = mono_array_get (smb->parameters, MonoReflectionType*, i);
2028                         encode_reflection_type (assembly, pt, &buf);
2029                 }
2030         } else {
2031                 encode_reflection_type (assembly, (MonoReflectionType*)fb->type, &buf);
2032         }
2033
2034         idx = sigbuffer_add_to_blob_cached (assembly, &buf);
2035         sigbuffer_free (&buf);
2036         return idx;
2037 }
2038
2039 static void
2040 mono_image_get_property_info (MonoReflectionPropertyBuilder *pb, MonoDynamicImage *assembly)
2041 {
2042         MonoDynamicTable *table;
2043         guint32 *values;
2044         guint num_methods = 0;
2045         guint32 semaidx;
2046
2047         /* 
2048          * we need to set things in the following tables:
2049          * PROPERTYMAP (info already filled in _get_type_info ())
2050          * PROPERTY    (rows already preallocated in _get_type_info ())
2051          * METHOD      (method info already done with the generic method code)
2052          * METHODSEMANTICS
2053          * CONSTANT
2054          */
2055         table = &assembly->tables [MONO_TABLE_PROPERTY];
2056         pb->table_idx = table->next_idx ++;
2057         values = table->values + pb->table_idx * MONO_PROPERTY_SIZE;
2058         values [MONO_PROPERTY_NAME] = string_heap_insert_mstring (&assembly->sheap, pb->name);
2059         values [MONO_PROPERTY_FLAGS] = pb->attrs;
2060         values [MONO_PROPERTY_TYPE] = property_encode_signature (assembly, pb);
2061
2062         /* FIXME: we still don't handle 'other' methods */
2063         if (pb->get_method) num_methods ++;
2064         if (pb->set_method) num_methods ++;
2065
2066         table = &assembly->tables [MONO_TABLE_METHODSEMANTICS];
2067         table->rows += num_methods;
2068         alloc_table (table, table->rows);
2069
2070         if (pb->get_method) {
2071                 semaidx = table->next_idx ++;
2072                 values = table->values + semaidx * MONO_METHOD_SEMA_SIZE;
2073                 values [MONO_METHOD_SEMA_SEMANTICS] = METHOD_SEMANTIC_GETTER;
2074                 values [MONO_METHOD_SEMA_METHOD] = pb->get_method->table_idx;
2075                 values [MONO_METHOD_SEMA_ASSOCIATION] = (pb->table_idx << MONO_HAS_SEMANTICS_BITS) | MONO_HAS_SEMANTICS_PROPERTY;
2076         }
2077         if (pb->set_method) {
2078                 semaidx = table->next_idx ++;
2079                 values = table->values + semaidx * MONO_METHOD_SEMA_SIZE;
2080                 values [MONO_METHOD_SEMA_SEMANTICS] = METHOD_SEMANTIC_SETTER;
2081                 values [MONO_METHOD_SEMA_METHOD] = pb->set_method->table_idx;
2082                 values [MONO_METHOD_SEMA_ASSOCIATION] = (pb->table_idx << MONO_HAS_SEMANTICS_BITS) | MONO_HAS_SEMANTICS_PROPERTY;
2083         }
2084         if (pb->attrs & PROPERTY_ATTRIBUTE_HAS_DEFAULT) {
2085                 guint32 field_type = 0;
2086                 table = &assembly->tables [MONO_TABLE_CONSTANT];
2087                 table->rows ++;
2088                 alloc_table (table, table->rows);
2089                 values = table->values + table->rows * MONO_CONSTANT_SIZE;
2090                 values [MONO_CONSTANT_PARENT] = MONO_HASCONSTANT_PROPERTY | (pb->table_idx << MONO_HASCONSTANT_BITS);
2091                 values [MONO_CONSTANT_VALUE] = encode_constant (assembly, pb->def_value, &field_type);
2092                 values [MONO_CONSTANT_TYPE] = field_type;
2093                 values [MONO_CONSTANT_PADDING] = 0;
2094         }
2095 }
2096
2097 static void
2098 mono_image_get_event_info (MonoReflectionEventBuilder *eb, MonoDynamicImage *assembly)
2099 {
2100         MonoDynamicTable *table;
2101         guint32 *values;
2102         guint num_methods = 0;
2103         guint32 semaidx;
2104
2105         /* 
2106          * we need to set things in the following tables:
2107          * EVENTMAP (info already filled in _get_type_info ())
2108          * EVENT    (rows already preallocated in _get_type_info ())
2109          * METHOD      (method info already done with the generic method code)
2110          * METHODSEMANTICS
2111          */
2112         table = &assembly->tables [MONO_TABLE_EVENT];
2113         eb->table_idx = table->next_idx ++;
2114         values = table->values + eb->table_idx * MONO_EVENT_SIZE;
2115         values [MONO_EVENT_NAME] = string_heap_insert_mstring (&assembly->sheap, eb->name);
2116         values [MONO_EVENT_FLAGS] = eb->attrs;
2117         values [MONO_EVENT_TYPE] = mono_image_typedef_or_ref (assembly, mono_reflection_type_get_handle (eb->type));
2118
2119         /*
2120          * FIXME: we still don't handle 'other' methods 
2121          */
2122         if (eb->add_method) num_methods ++;
2123         if (eb->remove_method) num_methods ++;
2124         if (eb->raise_method) num_methods ++;
2125
2126         table = &assembly->tables [MONO_TABLE_METHODSEMANTICS];
2127         table->rows += num_methods;
2128         alloc_table (table, table->rows);
2129
2130         if (eb->add_method) {
2131                 semaidx = table->next_idx ++;
2132                 values = table->values + semaidx * MONO_METHOD_SEMA_SIZE;
2133                 values [MONO_METHOD_SEMA_SEMANTICS] = METHOD_SEMANTIC_ADD_ON;
2134                 values [MONO_METHOD_SEMA_METHOD] = eb->add_method->table_idx;
2135                 values [MONO_METHOD_SEMA_ASSOCIATION] = (eb->table_idx << MONO_HAS_SEMANTICS_BITS) | MONO_HAS_SEMANTICS_EVENT;
2136         }
2137         if (eb->remove_method) {
2138                 semaidx = table->next_idx ++;
2139                 values = table->values + semaidx * MONO_METHOD_SEMA_SIZE;
2140                 values [MONO_METHOD_SEMA_SEMANTICS] = METHOD_SEMANTIC_REMOVE_ON;
2141                 values [MONO_METHOD_SEMA_METHOD] = eb->remove_method->table_idx;
2142                 values [MONO_METHOD_SEMA_ASSOCIATION] = (eb->table_idx << MONO_HAS_SEMANTICS_BITS) | MONO_HAS_SEMANTICS_EVENT;
2143         }
2144         if (eb->raise_method) {
2145                 semaidx = table->next_idx ++;
2146                 values = table->values + semaidx * MONO_METHOD_SEMA_SIZE;
2147                 values [MONO_METHOD_SEMA_SEMANTICS] = METHOD_SEMANTIC_FIRE;
2148                 values [MONO_METHOD_SEMA_METHOD] = eb->raise_method->table_idx;
2149                 values [MONO_METHOD_SEMA_ASSOCIATION] = (eb->table_idx << MONO_HAS_SEMANTICS_BITS) | MONO_HAS_SEMANTICS_EVENT;
2150         }
2151 }
2152
2153 static void
2154 encode_constraints (MonoReflectionGenericParam *gparam, guint32 owner, MonoDynamicImage *assembly)
2155 {
2156         MonoDynamicTable *table;
2157         guint32 num_constraints, i;
2158         guint32 *values;
2159         guint32 table_idx;
2160
2161         table = &assembly->tables [MONO_TABLE_GENERICPARAMCONSTRAINT];
2162         num_constraints = gparam->iface_constraints ?
2163                 mono_array_length (gparam->iface_constraints) : 0;
2164         table->rows += num_constraints;
2165         if (gparam->base_type)
2166                 table->rows++;
2167         alloc_table (table, table->rows);
2168
2169         if (gparam->base_type) {
2170                 table_idx = table->next_idx ++;
2171                 values = table->values + table_idx * MONO_GENPARCONSTRAINT_SIZE;
2172
2173                 values [MONO_GENPARCONSTRAINT_GENERICPAR] = owner;
2174                 values [MONO_GENPARCONSTRAINT_CONSTRAINT] = mono_image_typedef_or_ref (
2175                         assembly, mono_reflection_type_get_handle (gparam->base_type));
2176         }
2177
2178         for (i = 0; i < num_constraints; i++) {
2179                 MonoReflectionType *constraint = mono_array_get (
2180                         gparam->iface_constraints, gpointer, i);
2181
2182                 table_idx = table->next_idx ++;
2183                 values = table->values + table_idx * MONO_GENPARCONSTRAINT_SIZE;
2184
2185                 values [MONO_GENPARCONSTRAINT_GENERICPAR] = owner;
2186                 values [MONO_GENPARCONSTRAINT_CONSTRAINT] = mono_image_typedef_or_ref (
2187                         assembly, mono_reflection_type_get_handle (constraint));
2188         }
2189 }
2190
2191 static void
2192 mono_image_get_generic_param_info (MonoReflectionGenericParam *gparam, guint32 owner, MonoDynamicImage *assembly)
2193 {
2194         GenericParamTableEntry *entry;
2195
2196         /*
2197          * The GenericParam table must be sorted according to the `owner' field.
2198          * We need to do this sorting prior to writing the GenericParamConstraint
2199          * table, since we have to use the final GenericParam table indices there
2200          * and they must also be sorted.
2201          */
2202
2203         entry = g_new0 (GenericParamTableEntry, 1);
2204         entry->owner = owner;
2205         /* FIXME: track where gen_params should be freed and remove the GC root as well */
2206         MONO_GC_REGISTER_ROOT_IF_MOVING (entry->gparam);
2207         entry->gparam = gparam;
2208         
2209         g_ptr_array_add (assembly->gen_params, entry);
2210 }
2211
2212 static void
2213 write_generic_param_entry (MonoDynamicImage *assembly, GenericParamTableEntry *entry)
2214 {
2215         MonoDynamicTable *table;
2216         MonoGenericParam *param;
2217         guint32 *values;
2218         guint32 table_idx;
2219
2220         table = &assembly->tables [MONO_TABLE_GENERICPARAM];
2221         table_idx = table->next_idx ++;
2222         values = table->values + table_idx * MONO_GENERICPARAM_SIZE;
2223
2224         param = mono_reflection_type_get_handle ((MonoReflectionType*)entry->gparam)->data.generic_param;
2225
2226         values [MONO_GENERICPARAM_OWNER] = entry->owner;
2227         values [MONO_GENERICPARAM_FLAGS] = entry->gparam->attrs;
2228         values [MONO_GENERICPARAM_NUMBER] = mono_generic_param_num (param);
2229         values [MONO_GENERICPARAM_NAME] = string_heap_insert (&assembly->sheap, mono_generic_param_info (param)->name);
2230
2231         mono_image_add_cattrs (assembly, table_idx, MONO_CUSTOM_ATTR_GENERICPAR, entry->gparam->cattrs);
2232
2233         encode_constraints (entry->gparam, table_idx, assembly);
2234 }
2235
2236 static guint32
2237 resolution_scope_from_image (MonoDynamicImage *assembly, MonoImage *image)
2238 {
2239         MonoDynamicTable *table;
2240         guint32 token;
2241         guint32 *values;
2242         guint32 cols [MONO_ASSEMBLY_SIZE];
2243         const char *pubkey;
2244         guint32 publen;
2245
2246         if ((token = GPOINTER_TO_UINT (g_hash_table_lookup (assembly->handleref, image))))
2247                 return token;
2248
2249         if (image->assembly->dynamic && (image->assembly == assembly->image.assembly)) {
2250                 table = &assembly->tables [MONO_TABLE_MODULEREF];
2251                 token = table->next_idx ++;
2252                 table->rows ++;
2253                 alloc_table (table, table->rows);
2254                 values = table->values + token * MONO_MODULEREF_SIZE;
2255                 values [MONO_MODULEREF_NAME] = string_heap_insert (&assembly->sheap, image->module_name);
2256
2257                 token <<= MONO_RESOLTION_SCOPE_BITS;
2258                 token |= MONO_RESOLTION_SCOPE_MODULEREF;
2259                 g_hash_table_insert (assembly->handleref, image, GUINT_TO_POINTER (token));
2260
2261                 return token;
2262         }
2263         
2264         if (image->assembly->dynamic)
2265                 /* FIXME: */
2266                 memset (cols, 0, sizeof (cols));
2267         else {
2268                 /* image->assembly->image is the manifest module */
2269                 image = image->assembly->image;
2270                 mono_metadata_decode_row (&image->tables [MONO_TABLE_ASSEMBLY], 0, cols, MONO_ASSEMBLY_SIZE);
2271         }
2272
2273         table = &assembly->tables [MONO_TABLE_ASSEMBLYREF];
2274         token = table->next_idx ++;
2275         table->rows ++;
2276         alloc_table (table, table->rows);
2277         values = table->values + token * MONO_ASSEMBLYREF_SIZE;
2278         values [MONO_ASSEMBLYREF_NAME] = string_heap_insert (&assembly->sheap, image->assembly_name);
2279         values [MONO_ASSEMBLYREF_MAJOR_VERSION] = cols [MONO_ASSEMBLY_MAJOR_VERSION];
2280         values [MONO_ASSEMBLYREF_MINOR_VERSION] = cols [MONO_ASSEMBLY_MINOR_VERSION];
2281         values [MONO_ASSEMBLYREF_BUILD_NUMBER] = cols [MONO_ASSEMBLY_BUILD_NUMBER];
2282         values [MONO_ASSEMBLYREF_REV_NUMBER] = cols [MONO_ASSEMBLY_REV_NUMBER];
2283         values [MONO_ASSEMBLYREF_FLAGS] = 0;
2284         values [MONO_ASSEMBLYREF_CULTURE] = 0;
2285         values [MONO_ASSEMBLYREF_HASH_VALUE] = 0;
2286
2287         if (strcmp ("", image->assembly->aname.culture)) {
2288                 values [MONO_ASSEMBLYREF_CULTURE] = string_heap_insert (&assembly->sheap,
2289                                 image->assembly->aname.culture);
2290         }
2291
2292         if ((pubkey = mono_image_get_public_key (image, &publen))) {
2293                 guchar pubtoken [9];
2294                 pubtoken [0] = 8;
2295                 mono_digest_get_public_token (pubtoken + 1, (guchar*)pubkey, publen);
2296                 values [MONO_ASSEMBLYREF_PUBLIC_KEY] = mono_image_add_stream_data (&assembly->blob, (char*)pubtoken, 9);
2297         } else {
2298                 values [MONO_ASSEMBLYREF_PUBLIC_KEY] = 0;
2299         }
2300         token <<= MONO_RESOLTION_SCOPE_BITS;
2301         token |= MONO_RESOLTION_SCOPE_ASSEMBLYREF;
2302         g_hash_table_insert (assembly->handleref, image, GUINT_TO_POINTER (token));
2303         return token;
2304 }
2305
2306 static guint32
2307 create_typespec (MonoDynamicImage *assembly, MonoType *type)
2308 {
2309         MonoDynamicTable *table;
2310         guint32 *values;
2311         guint32 token;
2312         SigBuffer buf;
2313
2314         if ((token = GPOINTER_TO_UINT (g_hash_table_lookup (assembly->typespec, type))))
2315                 return token;
2316
2317         sigbuffer_init (&buf, 32);
2318         switch (type->type) {
2319         case MONO_TYPE_FNPTR:
2320         case MONO_TYPE_PTR:
2321         case MONO_TYPE_SZARRAY:
2322         case MONO_TYPE_ARRAY:
2323         case MONO_TYPE_VAR:
2324         case MONO_TYPE_MVAR:
2325         case MONO_TYPE_GENERICINST:
2326                 encode_type (assembly, type, &buf);
2327                 break;
2328         case MONO_TYPE_CLASS:
2329         case MONO_TYPE_VALUETYPE: {
2330                 MonoClass *k = mono_class_from_mono_type (type);
2331                 if (!k || !k->generic_container) {
2332                         sigbuffer_free (&buf);
2333                         return 0;
2334                 }
2335                 encode_type (assembly, type, &buf);
2336                 break;
2337         }
2338         default:
2339                 sigbuffer_free (&buf);
2340                 return 0;
2341         }
2342
2343         table = &assembly->tables [MONO_TABLE_TYPESPEC];
2344         if (assembly->save) {
2345                 token = sigbuffer_add_to_blob_cached (assembly, &buf);
2346                 alloc_table (table, table->rows + 1);
2347                 values = table->values + table->next_idx * MONO_TYPESPEC_SIZE;
2348                 values [MONO_TYPESPEC_SIGNATURE] = token;
2349         }
2350         sigbuffer_free (&buf);
2351
2352         token = MONO_TYPEDEFORREF_TYPESPEC | (table->next_idx << MONO_TYPEDEFORREF_BITS);
2353         g_hash_table_insert (assembly->typespec, type, GUINT_TO_POINTER(token));
2354         table->next_idx ++;
2355         return token;
2356 }
2357
2358 static guint32
2359 mono_image_typedef_or_ref_full (MonoDynamicImage *assembly, MonoType *type, gboolean try_typespec)
2360 {
2361         MonoDynamicTable *table;
2362         guint32 *values;
2363         guint32 token, scope, enclosing;
2364         MonoClass *klass;
2365
2366         /* if the type requires a typespec, we must try that first*/
2367         if (try_typespec && (token = create_typespec (assembly, type)))
2368                 return token;
2369         token = GPOINTER_TO_UINT (g_hash_table_lookup (assembly->typeref, type));
2370         if (token)
2371                 return token;
2372         klass = mono_class_from_mono_type (type);
2373         if (!klass)
2374                 klass = mono_class_from_mono_type (type);
2375
2376         /*
2377          * If it's in the same module and not a generic type parameter:
2378          */
2379         if ((klass->image == &assembly->image) && (type->type != MONO_TYPE_VAR) && 
2380                         (type->type != MONO_TYPE_MVAR)) {
2381                 MonoReflectionTypeBuilder *tb = mono_class_get_ref_info (klass);
2382                 token = MONO_TYPEDEFORREF_TYPEDEF | (tb->table_idx << MONO_TYPEDEFORREF_BITS);
2383                 mono_g_hash_table_insert (assembly->tokens, GUINT_TO_POINTER (token), mono_class_get_ref_info (klass));
2384                 return token;
2385         }
2386
2387         if (klass->nested_in) {
2388                 enclosing = mono_image_typedef_or_ref_full (assembly, &klass->nested_in->byval_arg, FALSE);
2389                 /* get the typeref idx of the enclosing type */
2390                 enclosing >>= MONO_TYPEDEFORREF_BITS;
2391                 scope = (enclosing << MONO_RESOLTION_SCOPE_BITS) | MONO_RESOLTION_SCOPE_TYPEREF;
2392         } else {
2393                 scope = resolution_scope_from_image (assembly, klass->image);
2394         }
2395         table = &assembly->tables [MONO_TABLE_TYPEREF];
2396         if (assembly->save) {
2397                 alloc_table (table, table->rows + 1);
2398                 values = table->values + table->next_idx * MONO_TYPEREF_SIZE;
2399                 values [MONO_TYPEREF_SCOPE] = scope;
2400                 values [MONO_TYPEREF_NAME] = string_heap_insert (&assembly->sheap, klass->name);
2401                 values [MONO_TYPEREF_NAMESPACE] = string_heap_insert (&assembly->sheap, klass->name_space);
2402         }
2403         token = MONO_TYPEDEFORREF_TYPEREF | (table->next_idx << MONO_TYPEDEFORREF_BITS); /* typeref */
2404         g_hash_table_insert (assembly->typeref, type, GUINT_TO_POINTER(token));
2405         table->next_idx ++;
2406         mono_g_hash_table_insert (assembly->tokens, GUINT_TO_POINTER (token), mono_class_get_ref_info (klass));
2407         return token;
2408 }
2409
2410 /*
2411  * Despite the name, we handle also TypeSpec (with the above helper).
2412  */
2413 static guint32
2414 mono_image_typedef_or_ref (MonoDynamicImage *assembly, MonoType *type)
2415 {
2416         return mono_image_typedef_or_ref_full (assembly, type, TRUE);
2417 }
2418
2419 #ifndef DISABLE_REFLECTION_EMIT
2420 static guint32
2421 mono_image_add_memberef_row (MonoDynamicImage *assembly, guint32 parent, const char *name, guint32 sig)
2422 {
2423         MonoDynamicTable *table;
2424         guint32 *values;
2425         guint32 token, pclass;
2426
2427         switch (parent & MONO_TYPEDEFORREF_MASK) {
2428         case MONO_TYPEDEFORREF_TYPEREF:
2429                 pclass = MONO_MEMBERREF_PARENT_TYPEREF;
2430                 break;
2431         case MONO_TYPEDEFORREF_TYPESPEC:
2432                 pclass = MONO_MEMBERREF_PARENT_TYPESPEC;
2433                 break;
2434         case MONO_TYPEDEFORREF_TYPEDEF:
2435                 pclass = MONO_MEMBERREF_PARENT_TYPEDEF;
2436                 break;
2437         default:
2438                 g_warning ("unknown typeref or def token 0x%08x for %s", parent, name);
2439                 return 0;
2440         }
2441         /* extract the index */
2442         parent >>= MONO_TYPEDEFORREF_BITS;
2443
2444         table = &assembly->tables [MONO_TABLE_MEMBERREF];
2445
2446         if (assembly->save) {
2447                 alloc_table (table, table->rows + 1);
2448                 values = table->values + table->next_idx * MONO_MEMBERREF_SIZE;
2449                 values [MONO_MEMBERREF_CLASS] = pclass | (parent << MONO_MEMBERREF_PARENT_BITS);
2450                 values [MONO_MEMBERREF_NAME] = string_heap_insert (&assembly->sheap, name);
2451                 values [MONO_MEMBERREF_SIGNATURE] = sig;
2452         }
2453
2454         token = MONO_TOKEN_MEMBER_REF | table->next_idx;
2455         table->next_idx ++;
2456
2457         return token;
2458 }
2459
2460 /*
2461  * Insert a memberef row into the metadata: the token that point to the memberref
2462  * is returned. Caching is done in the caller (mono_image_get_methodref_token() or
2463  * mono_image_get_fieldref_token()).
2464  * The sig param is an index to an already built signature.
2465  */
2466 static guint32
2467 mono_image_get_memberref_token (MonoDynamicImage *assembly, MonoType *type, const char *name, guint32 sig)
2468 {
2469         guint32 parent = mono_image_typedef_or_ref (assembly, type);
2470         return mono_image_add_memberef_row (assembly, parent, name, sig);
2471 }
2472
2473
2474 static guint32
2475 mono_image_get_methodref_token (MonoDynamicImage *assembly, MonoMethod *method, gboolean create_typespec)
2476 {
2477         guint32 token;
2478         MonoMethodSignature *sig;
2479         
2480         create_typespec = create_typespec && method->is_generic && method->klass->image != &assembly->image;
2481
2482         if (create_typespec) {
2483                 token = GPOINTER_TO_UINT (g_hash_table_lookup (assembly->handleref, GUINT_TO_POINTER (GPOINTER_TO_UINT (method) + 1)));
2484                 if (token)
2485                         return token;
2486         } 
2487
2488         token = GPOINTER_TO_UINT (g_hash_table_lookup (assembly->handleref, method));
2489         if (token && !create_typespec)
2490                 return token;
2491
2492         g_assert (!method->is_inflated);
2493         if (!token) {
2494                 /*
2495                  * A methodref signature can't contain an unmanaged calling convention.
2496                  */
2497                 sig = mono_metadata_signature_dup (mono_method_signature (method));
2498                 if ((sig->call_convention != MONO_CALL_DEFAULT) && (sig->call_convention != MONO_CALL_VARARG))
2499                         sig->call_convention = MONO_CALL_DEFAULT;
2500                 token = mono_image_get_memberref_token (assembly, &method->klass->byval_arg,
2501                         method->name,  method_encode_signature (assembly, sig));
2502                 g_free (sig);
2503                 g_hash_table_insert (assembly->handleref, method, GUINT_TO_POINTER(token));
2504         }
2505
2506         if (create_typespec) {
2507                 MonoDynamicTable *table = &assembly->tables [MONO_TABLE_METHODSPEC];
2508                 g_assert (mono_metadata_token_table (token) == MONO_TABLE_MEMBERREF);
2509                 token = (mono_metadata_token_index (token) << MONO_METHODDEFORREF_BITS) | MONO_METHODDEFORREF_METHODREF;
2510
2511                 if (assembly->save) {
2512                         guint32 *values;
2513
2514                         alloc_table (table, table->rows + 1);
2515                         values = table->values + table->next_idx * MONO_METHODSPEC_SIZE;
2516                         values [MONO_METHODSPEC_METHOD] = token;
2517                         values [MONO_METHODSPEC_SIGNATURE] = encode_generic_method_sig (assembly, &mono_method_get_generic_container (method)->context);
2518                 }
2519
2520                 token = MONO_TOKEN_METHOD_SPEC | table->next_idx;
2521                 table->next_idx ++;
2522                 /*methodspec and memberef tokens are diferent, */
2523                 g_hash_table_insert (assembly->handleref, GUINT_TO_POINTER (GPOINTER_TO_UINT (method) + 1), GUINT_TO_POINTER (token));
2524                 return token;
2525         }
2526         return token;
2527 }
2528
2529 static guint32
2530 mono_image_get_methodref_token_for_methodbuilder (MonoDynamicImage *assembly, MonoReflectionMethodBuilder *method)
2531 {
2532         guint32 token, parent, sig;
2533         ReflectionMethodBuilder rmb;
2534         char *name;
2535         MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder *)method->type;
2536         
2537         token = GPOINTER_TO_UINT (g_hash_table_lookup (assembly->handleref, method));
2538         if (token)
2539                 return token;
2540
2541         name = mono_string_to_utf8 (method->name);
2542         reflection_methodbuilder_from_method_builder (&rmb, method);
2543
2544         /*
2545          * A methodref signature can't contain an unmanaged calling convention.
2546          * Since some flags are encoded as part of call_conv, we need to check against it.
2547         */
2548         if ((rmb.call_conv & ~0x60) != MONO_CALL_DEFAULT && (rmb.call_conv & ~0x60) != MONO_CALL_VARARG)
2549                 rmb.call_conv = (rmb.call_conv & 0x60) | MONO_CALL_DEFAULT;
2550
2551         sig = method_builder_encode_signature (assembly, &rmb);
2552
2553         if (tb->generic_params)
2554                 parent = create_generic_typespec (assembly, tb);
2555         else
2556                 parent = mono_image_typedef_or_ref (assembly, mono_reflection_type_get_handle ((MonoReflectionType*)rmb.type));
2557
2558         token = mono_image_add_memberef_row (assembly, parent, name, sig);
2559
2560         g_free (name);
2561         g_hash_table_insert (assembly->handleref, method, GUINT_TO_POINTER(token));
2562         return token;
2563 }
2564
2565 static guint32
2566 mono_image_get_varargs_method_token (MonoDynamicImage *assembly, guint32 original,
2567                                      const gchar *name, guint32 sig)
2568 {
2569         MonoDynamicTable *table;
2570         guint32 token;
2571         guint32 *values;
2572         
2573         table = &assembly->tables [MONO_TABLE_MEMBERREF];
2574
2575         if (assembly->save) {
2576                 alloc_table (table, table->rows + 1);
2577                 values = table->values + table->next_idx * MONO_MEMBERREF_SIZE;
2578                 values [MONO_MEMBERREF_CLASS] = original;
2579                 values [MONO_MEMBERREF_NAME] = string_heap_insert (&assembly->sheap, name);
2580                 values [MONO_MEMBERREF_SIGNATURE] = sig;
2581         }
2582
2583         token = MONO_TOKEN_MEMBER_REF | table->next_idx;
2584         table->next_idx ++;
2585
2586         return token;
2587 }
2588
2589 static guint32
2590 encode_generic_method_definition_sig (MonoDynamicImage *assembly, MonoReflectionMethodBuilder *mb)
2591 {
2592         SigBuffer buf;
2593         int i;
2594         guint32 nparams = mono_array_length (mb->generic_params);
2595         guint32 idx;
2596
2597         if (!assembly->save)
2598                 return 0;
2599
2600         sigbuffer_init (&buf, 32);
2601
2602         sigbuffer_add_value (&buf, 0xa);
2603         sigbuffer_add_value (&buf, nparams);
2604
2605         for (i = 0; i < nparams; i++) {
2606                 sigbuffer_add_value (&buf, MONO_TYPE_MVAR);
2607                 sigbuffer_add_value (&buf, i);
2608         }
2609
2610         idx = sigbuffer_add_to_blob_cached (assembly, &buf);
2611         sigbuffer_free (&buf);
2612         return idx;
2613 }
2614
2615 static guint32
2616 mono_image_get_methodspec_token_for_generic_method_definition (MonoDynamicImage *assembly, MonoReflectionMethodBuilder *mb)
2617 {
2618         MonoDynamicTable *table;
2619         guint32 *values;
2620         guint32 token, mtoken = 0;
2621
2622         token = GPOINTER_TO_UINT (mono_g_hash_table_lookup (assembly->methodspec, mb));
2623         if (token)
2624                 return token;
2625
2626         table = &assembly->tables [MONO_TABLE_METHODSPEC];
2627
2628         mtoken = mono_image_get_methodref_token_for_methodbuilder (assembly, mb);
2629         switch (mono_metadata_token_table (mtoken)) {
2630         case MONO_TABLE_MEMBERREF:
2631                 mtoken = (mono_metadata_token_index (mtoken) << MONO_METHODDEFORREF_BITS) | MONO_METHODDEFORREF_METHODREF;
2632                 break;
2633         case MONO_TABLE_METHOD:
2634                 mtoken = (mono_metadata_token_index (mtoken) << MONO_METHODDEFORREF_BITS) | MONO_METHODDEFORREF_METHODDEF;
2635                 break;
2636         default:
2637                 g_assert_not_reached ();
2638         }
2639
2640         if (assembly->save) {
2641                 alloc_table (table, table->rows + 1);
2642                 values = table->values + table->next_idx * MONO_METHODSPEC_SIZE;
2643                 values [MONO_METHODSPEC_METHOD] = mtoken;
2644                 values [MONO_METHODSPEC_SIGNATURE] = encode_generic_method_definition_sig (assembly, mb);
2645         }
2646
2647         token = MONO_TOKEN_METHOD_SPEC | table->next_idx;
2648         table->next_idx ++;
2649
2650         mono_g_hash_table_insert (assembly->methodspec, mb, GUINT_TO_POINTER(token));
2651         return token;
2652 }
2653
2654 static guint32
2655 mono_image_get_methodbuilder_token (MonoDynamicImage *assembly, MonoReflectionMethodBuilder *mb, gboolean create_methodspec)
2656 {
2657         guint32 token;
2658
2659         if (mb->generic_params && create_methodspec) 
2660                 return mono_image_get_methodspec_token_for_generic_method_definition (assembly, mb);
2661
2662         token = GPOINTER_TO_UINT (mono_g_hash_table_lookup (assembly->handleref_managed, mb));
2663         if (token)
2664                 return token;
2665
2666         token = mono_image_get_methodref_token_for_methodbuilder (assembly, mb);
2667         mono_g_hash_table_insert (assembly->handleref_managed, mb, GUINT_TO_POINTER(token));
2668         return token;
2669 }
2670
2671 static guint32
2672 mono_image_get_ctorbuilder_token (MonoDynamicImage *assembly, MonoReflectionCtorBuilder *mb)
2673 {
2674         guint32 token, parent, sig;
2675         ReflectionMethodBuilder rmb;
2676         char *name;
2677         MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder *)mb->type;
2678         
2679         token = GPOINTER_TO_UINT (mono_g_hash_table_lookup (assembly->handleref_managed, mb));
2680         if (token)
2681                 return token;
2682
2683         reflection_methodbuilder_from_ctor_builder (&rmb, mb);
2684
2685         if (tb->generic_params)
2686                 parent = create_generic_typespec (assembly, tb);
2687         else
2688                 parent = mono_image_typedef_or_ref (assembly, mono_reflection_type_get_handle ((MonoReflectionType*)tb));
2689         
2690         name = mono_string_to_utf8 (rmb.name);
2691         sig = method_builder_encode_signature (assembly, &rmb);
2692
2693         token = mono_image_add_memberef_row (assembly, parent, name, sig);
2694
2695         g_free (name);
2696         mono_g_hash_table_insert (assembly->handleref_managed, mb, GUINT_TO_POINTER(token));
2697         return token;
2698 }
2699 #endif
2700
2701 static gboolean
2702 is_field_on_inst (MonoClassField *field)
2703 {
2704         return (field->parent->generic_class && field->parent->generic_class->is_dynamic && ((MonoDynamicGenericClass*)field->parent->generic_class)->fields);
2705 }
2706
2707 /*
2708  * If FIELD is a field of a MonoDynamicGenericClass, return its non-inflated type.
2709  */
2710 static MonoType*
2711 get_field_on_inst_generic_type (MonoClassField *field)
2712 {
2713         MonoClass *class, *gtd;
2714         MonoDynamicGenericClass *dgclass;
2715         int field_index;
2716
2717         g_assert (is_field_on_inst (field));
2718
2719         dgclass = (MonoDynamicGenericClass*)field->parent->generic_class;
2720
2721         if (field >= dgclass->fields && field - dgclass->fields < dgclass->count_fields) {
2722                 field_index = field - dgclass->fields;
2723                 return dgclass->field_generic_types [field_index];              
2724         }
2725
2726         class = field->parent;
2727         gtd = class->generic_class->container_class;
2728
2729         if (field >= class->fields && field - class->fields < class->field.count) {
2730                 field_index = field - class->fields;
2731                 return gtd->fields [field_index].type;
2732         }
2733
2734         g_assert_not_reached ();
2735         return 0;
2736 }
2737
2738 #ifndef DISABLE_REFLECTION_EMIT
2739 static guint32
2740 mono_image_get_fieldref_token (MonoDynamicImage *assembly, MonoObject *f, MonoClassField *field)
2741 {
2742         MonoType *type;
2743         guint32 token;
2744
2745         g_assert (field);
2746         g_assert (field->parent);
2747
2748         token = GPOINTER_TO_UINT (mono_g_hash_table_lookup (assembly->handleref_managed, f));
2749         if (token)
2750                 return token;
2751
2752         if (field->parent->generic_class && field->parent->generic_class->container_class && field->parent->generic_class->container_class->fields) {
2753                 int index = field - field->parent->fields;
2754                 type = mono_field_get_type (&field->parent->generic_class->container_class->fields [index]);
2755         } else {
2756                 if (is_field_on_inst (field))
2757                         type = get_field_on_inst_generic_type (field);
2758                 else
2759                         type = mono_field_get_type (field);
2760         }
2761         token = mono_image_get_memberref_token (assembly, &field->parent->byval_arg,
2762                                                                                         mono_field_get_name (field),
2763                                                                                         fieldref_encode_signature (assembly, field->parent->image, type));
2764         mono_g_hash_table_insert (assembly->handleref_managed, f, GUINT_TO_POINTER(token));
2765         return token;
2766 }
2767
2768 static guint32
2769 mono_image_get_field_on_inst_token (MonoDynamicImage *assembly, MonoReflectionFieldOnTypeBuilderInst *f)
2770 {
2771         guint32 token;
2772         MonoClass *klass;
2773         MonoGenericClass *gclass;
2774         MonoDynamicGenericClass *dgclass;
2775         MonoType *type;
2776         char *name;
2777
2778         token = GPOINTER_TO_UINT (mono_g_hash_table_lookup (assembly->handleref_managed, f));
2779         if (token)
2780                 return token;
2781         if (is_sre_field_builder (mono_object_class (f->fb))) {
2782                 MonoReflectionFieldBuilder *fb = (MonoReflectionFieldBuilder *)f->fb;
2783                 type = mono_reflection_type_get_handle ((MonoReflectionType*)f->inst);
2784                 klass = mono_class_from_mono_type (type);
2785                 gclass = type->data.generic_class;
2786                 g_assert (gclass->is_dynamic);
2787                 dgclass = (MonoDynamicGenericClass *) gclass;
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                 MonoDynamicGenericClass *dgclass;
2828                 ReflectionMethodBuilder rmb;
2829                 char *name;
2830
2831                 type = mono_reflection_type_get_handle ((MonoReflectionType*)c->inst);
2832                 klass = mono_class_from_mono_type (type);
2833
2834                 gclass = type->data.generic_class;
2835                 g_assert (gclass->is_dynamic);
2836                 dgclass = (MonoDynamicGenericClass *) gclass;
2837
2838                 reflection_methodbuilder_from_ctor_builder (&rmb, cb);
2839
2840                 name = mono_string_to_utf8 (rmb.name);
2841
2842                 sig = method_builder_encode_signature (assembly, &rmb);
2843
2844                 token = mono_image_get_memberref_token (assembly, &klass->byval_arg, name, sig);
2845                 g_free (name);
2846         } else if (is_sr_mono_cmethod (mono_object_class (c->cb))) {
2847                 MonoMethod *mm = ((MonoReflectionMethod *)c->cb)->method;
2848
2849                 type = mono_reflection_type_get_handle ((MonoReflectionType*)c->inst);
2850                 klass = mono_class_from_mono_type (type);
2851
2852                 sig = method_encode_signature (assembly, mono_method_signature (mm));
2853                 token = mono_image_get_memberref_token (assembly, &klass->byval_arg, mm->name, sig);
2854         } else {
2855                 char *name = mono_type_get_full_name (mono_object_class (c->cb));
2856                 g_error ("mono_image_get_method_on_inst_token: don't know how to handle %s", name);
2857         }
2858
2859
2860         mono_g_hash_table_insert (assembly->handleref_managed, c, GUINT_TO_POINTER (token));
2861         return token;
2862 }
2863
2864 static MonoMethod*
2865 mono_reflection_method_on_tb_inst_get_handle (MonoReflectionMethodOnTypeBuilderInst *m)
2866 {
2867         MonoClass *klass;
2868         MonoGenericContext tmp_context;
2869         MonoType **type_argv;
2870         MonoGenericInst *ginst;
2871         MonoMethod *method, *inflated;
2872         int count, i;
2873
2874         init_type_builder_generics ((MonoObject*)m->inst);
2875
2876         method = inflate_method (m->inst, (MonoObject*)m->mb);
2877
2878         klass = method->klass;
2879
2880         if (m->method_args == NULL)
2881                 return method;
2882
2883         if (method->is_inflated)
2884                 method = ((MonoMethodInflated *) method)->declaring;
2885
2886         count = mono_array_length (m->method_args);
2887
2888         type_argv = g_new0 (MonoType *, count);
2889         for (i = 0; i < count; i++) {
2890                 MonoReflectionType *garg = mono_array_get (m->method_args, gpointer, i);
2891                 type_argv [i] = mono_reflection_type_get_handle (garg);
2892         }
2893         ginst = mono_metadata_get_generic_inst (count, type_argv);
2894         g_free (type_argv);
2895
2896         tmp_context.class_inst = klass->generic_class ? klass->generic_class->context.class_inst : NULL;
2897         tmp_context.method_inst = ginst;
2898
2899         inflated = mono_class_inflate_generic_method (method, &tmp_context);
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         MonoClass *klass;
3195         MonoType *custom = NULL, *type;
3196         guint32 *values;
3197         guint32 token, pclass, parent, sig;
3198         gchar *name;
3199
3200         token = GPOINTER_TO_UINT (mono_g_hash_table_lookup (assembly->handleref_managed, fb));
3201         if (token)
3202                 return token;
3203
3204         klass = 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 size;
3248         guint32 i, idx;
3249
3250         if (!assembly->save)
3251                 return 0;
3252
3253         /* FIXME: this means SignatureHelper.SignatureHelpType.HELPER_METHOD */
3254         g_assert (helper->type == 2);
3255
3256         if (helper->arguments)
3257                 nargs = mono_array_length (helper->arguments);
3258         else
3259                 nargs = 0;
3260
3261         size = 10 + (nargs * 10);
3262         
3263         sigbuffer_init (&buf, 32);
3264
3265         /* Encode calling convention */
3266         /* Change Any to Standard */
3267         if ((helper->call_conv & 0x03) == 0x03)
3268                 helper->call_conv = 0x01;
3269         /* explicit_this implies has_this */
3270         if (helper->call_conv & 0x40)
3271                 helper->call_conv &= 0x20;
3272
3273         if (helper->call_conv == 0) { /* Unmanaged */
3274                 idx = helper->unmanaged_call_conv - 1;
3275         } else {
3276                 /* Managed */
3277                 idx = helper->call_conv & 0x60; /* has_this + explicit_this */
3278                 if (helper->call_conv & 0x02) /* varargs */
3279                         idx += 0x05;
3280         }
3281
3282         sigbuffer_add_byte (&buf, idx);
3283         sigbuffer_add_value (&buf, nargs);
3284         encode_reflection_type (assembly, helper->return_type, &buf);
3285         for (i = 0; i < nargs; ++i) {
3286                 MonoArray *modreqs = NULL;
3287                 MonoArray *modopts = NULL;
3288                 MonoReflectionType *pt;
3289
3290                 if (helper->modreqs && (i < mono_array_length (helper->modreqs)))
3291                         modreqs = mono_array_get (helper->modreqs, MonoArray*, i);
3292                 if (helper->modopts && (i < mono_array_length (helper->modopts)))
3293                         modopts = mono_array_get (helper->modopts, MonoArray*, i);
3294
3295                 encode_custom_modifiers (assembly, modreqs, modopts, &buf);
3296                 pt = mono_array_get (helper->arguments, MonoReflectionType*, i);
3297                 encode_reflection_type (assembly, pt, &buf);
3298         }
3299         idx = sigbuffer_add_to_blob_cached (assembly, &buf);
3300         sigbuffer_free (&buf);
3301
3302         return idx;
3303 }
3304
3305 static guint32 
3306 mono_image_get_sighelper_token (MonoDynamicImage *assembly, MonoReflectionSigHelper *helper)
3307 {
3308         guint32 idx;
3309         MonoDynamicTable *table;
3310         guint32 *values;
3311
3312         table = &assembly->tables [MONO_TABLE_STANDALONESIG];
3313         idx = table->next_idx ++;
3314         table->rows ++;
3315         alloc_table (table, table->rows);
3316         values = table->values + idx * MONO_STAND_ALONE_SIGNATURE_SIZE;
3317
3318         values [MONO_STAND_ALONE_SIGNATURE] =
3319                 mono_reflection_encode_sighelper (assembly, helper);
3320
3321         return idx;
3322 }
3323
3324 static int
3325 reflection_cc_to_file (int call_conv) {
3326         switch (call_conv & 0x3) {
3327         case 0:
3328         case 1: return MONO_CALL_DEFAULT;
3329         case 2: return MONO_CALL_VARARG;
3330         default:
3331                 g_assert_not_reached ();
3332         }
3333         return 0;
3334 }
3335 #endif /* !DISABLE_REFLECTION_EMIT */
3336
3337 typedef struct {
3338         MonoType *parent;
3339         MonoMethodSignature *sig;
3340         char *name;
3341         guint32 token;
3342 } ArrayMethod;
3343
3344 #ifndef DISABLE_REFLECTION_EMIT
3345 static guint32
3346 mono_image_get_array_token (MonoDynamicImage *assembly, MonoReflectionArrayMethod *m)
3347 {
3348         guint32 nparams, i;
3349         GList *tmp;
3350         char *name;
3351         MonoMethodSignature *sig;
3352         ArrayMethod *am;
3353         MonoType *mtype;
3354
3355         name = mono_string_to_utf8 (m->name);
3356         nparams = mono_array_length (m->parameters);
3357         sig = g_malloc0 (MONO_SIZEOF_METHOD_SIGNATURE + sizeof (MonoType*) * nparams);
3358         sig->hasthis = 1;
3359         sig->sentinelpos = -1;
3360         sig->call_convention = reflection_cc_to_file (m->call_conv);
3361         sig->param_count = nparams;
3362         sig->ret = m->ret ? mono_reflection_type_get_handle (m->ret): &mono_defaults.void_class->byval_arg;
3363         mtype = mono_reflection_type_get_handle (m->parent);
3364         for (i = 0; i < nparams; ++i)
3365                 sig->params [i] = mono_type_array_get_and_resolve (m->parameters, i);
3366
3367         for (tmp = assembly->array_methods; tmp; tmp = tmp->next) {
3368                 am = tmp->data;
3369                 if (strcmp (name, am->name) == 0 && 
3370                                 mono_metadata_type_equal (am->parent, mtype) &&
3371                                 mono_metadata_signature_equal (am->sig, sig)) {
3372                         g_free (name);
3373                         g_free (sig);
3374                         m->table_idx = am->token & 0xffffff;
3375                         return am->token;
3376                 }
3377         }
3378         am = g_new0 (ArrayMethod, 1);
3379         am->name = name;
3380         am->sig = sig;
3381         am->parent = mtype;
3382         am->token = mono_image_get_memberref_token (assembly, am->parent, name,
3383                 method_encode_signature (assembly, sig));
3384         assembly->array_methods = g_list_prepend (assembly->array_methods, am);
3385         m->table_idx = am->token & 0xffffff;
3386         return am->token;
3387 }
3388
3389 /*
3390  * Insert into the metadata tables all the info about the TypeBuilder tb.
3391  * Data in the tables is inserted in a predefined order, since some tables need to be sorted.
3392  */
3393 static void
3394 mono_image_get_type_info (MonoDomain *domain, MonoReflectionTypeBuilder *tb, MonoDynamicImage *assembly)
3395 {
3396         MonoDynamicTable *table;
3397         guint *values;
3398         int i, is_object = 0, is_system = 0;
3399         char *n;
3400
3401         table = &assembly->tables [MONO_TABLE_TYPEDEF];
3402         values = table->values + tb->table_idx * MONO_TYPEDEF_SIZE;
3403         values [MONO_TYPEDEF_FLAGS] = tb->attrs;
3404         n = mono_string_to_utf8 (tb->name);
3405         if (strcmp (n, "Object") == 0)
3406                 is_object++;
3407         values [MONO_TYPEDEF_NAME] = string_heap_insert (&assembly->sheap, n);
3408         g_free (n);
3409         n = mono_string_to_utf8 (tb->nspace);
3410         if (strcmp (n, "System") == 0)
3411                 is_system++;
3412         values [MONO_TYPEDEF_NAMESPACE] = string_heap_insert (&assembly->sheap, n);
3413         g_free (n);
3414         if (tb->parent && !(is_system && is_object) && 
3415                         !(tb->attrs & TYPE_ATTRIBUTE_INTERFACE)) { /* interfaces don't have a parent */
3416                 values [MONO_TYPEDEF_EXTENDS] = mono_image_typedef_or_ref (assembly, mono_reflection_type_get_handle ((MonoReflectionType*)tb->parent));
3417         } else {
3418                 values [MONO_TYPEDEF_EXTENDS] = 0;
3419         }
3420         values [MONO_TYPEDEF_FIELD_LIST] = assembly->tables [MONO_TABLE_FIELD].next_idx;
3421         values [MONO_TYPEDEF_METHOD_LIST] = assembly->tables [MONO_TABLE_METHOD].next_idx;
3422
3423         /*
3424          * if we have explicitlayout or sequentiallayouts, output data in the
3425          * ClassLayout table.
3426          */
3427         if (((tb->attrs & TYPE_ATTRIBUTE_LAYOUT_MASK) != TYPE_ATTRIBUTE_AUTO_LAYOUT) &&
3428                         ((tb->class_size > 0) || (tb->packing_size > 0))) {
3429                 table = &assembly->tables [MONO_TABLE_CLASSLAYOUT];
3430                 table->rows++;
3431                 alloc_table (table, table->rows);
3432                 values = table->values + table->rows * MONO_CLASS_LAYOUT_SIZE;
3433                 values [MONO_CLASS_LAYOUT_PARENT] = tb->table_idx;
3434                 values [MONO_CLASS_LAYOUT_CLASS_SIZE] = tb->class_size;
3435                 values [MONO_CLASS_LAYOUT_PACKING_SIZE] = tb->packing_size;
3436         }
3437
3438         /* handle interfaces */
3439         if (tb->interfaces) {
3440                 table = &assembly->tables [MONO_TABLE_INTERFACEIMPL];
3441                 i = table->rows;
3442                 table->rows += mono_array_length (tb->interfaces);
3443                 alloc_table (table, table->rows);
3444                 values = table->values + (i + 1) * MONO_INTERFACEIMPL_SIZE;
3445                 for (i = 0; i < mono_array_length (tb->interfaces); ++i) {
3446                         MonoReflectionType* iface = (MonoReflectionType*) mono_array_get (tb->interfaces, gpointer, i);
3447                         values [MONO_INTERFACEIMPL_CLASS] = tb->table_idx;
3448                         values [MONO_INTERFACEIMPL_INTERFACE] = mono_image_typedef_or_ref (assembly, mono_reflection_type_get_handle (iface));
3449                         values += MONO_INTERFACEIMPL_SIZE;
3450                 }
3451         }
3452
3453         /* handle fields */
3454         if (tb->fields) {
3455                 table = &assembly->tables [MONO_TABLE_FIELD];
3456                 table->rows += tb->num_fields;
3457                 alloc_table (table, table->rows);
3458                 for (i = 0; i < tb->num_fields; ++i)
3459                         mono_image_get_field_info (
3460                                 mono_array_get (tb->fields, MonoReflectionFieldBuilder*, i), assembly);
3461         }
3462
3463         /* handle constructors */
3464         if (tb->ctors) {
3465                 table = &assembly->tables [MONO_TABLE_METHOD];
3466                 table->rows += mono_array_length (tb->ctors);
3467                 alloc_table (table, table->rows);
3468                 for (i = 0; i < mono_array_length (tb->ctors); ++i)
3469                         mono_image_get_ctor_info (domain,
3470                                 mono_array_get (tb->ctors, MonoReflectionCtorBuilder*, i), assembly);
3471         }
3472
3473         /* handle methods */
3474         if (tb->methods) {
3475                 table = &assembly->tables [MONO_TABLE_METHOD];
3476                 table->rows += tb->num_methods;
3477                 alloc_table (table, table->rows);
3478                 for (i = 0; i < tb->num_methods; ++i)
3479                         mono_image_get_method_info (
3480                                 mono_array_get (tb->methods, MonoReflectionMethodBuilder*, i), assembly);
3481         }
3482
3483         /* Do the same with properties etc.. */
3484         if (tb->events && mono_array_length (tb->events)) {
3485                 table = &assembly->tables [MONO_TABLE_EVENT];
3486                 table->rows += mono_array_length (tb->events);
3487                 alloc_table (table, table->rows);
3488                 table = &assembly->tables [MONO_TABLE_EVENTMAP];
3489                 table->rows ++;
3490                 alloc_table (table, table->rows);
3491                 values = table->values + table->rows * MONO_EVENT_MAP_SIZE;
3492                 values [MONO_EVENT_MAP_PARENT] = tb->table_idx;
3493                 values [MONO_EVENT_MAP_EVENTLIST] = assembly->tables [MONO_TABLE_EVENT].next_idx;
3494                 for (i = 0; i < mono_array_length (tb->events); ++i)
3495                         mono_image_get_event_info (
3496                                 mono_array_get (tb->events, MonoReflectionEventBuilder*, i), assembly);
3497         }
3498         if (tb->properties && mono_array_length (tb->properties)) {
3499                 table = &assembly->tables [MONO_TABLE_PROPERTY];
3500                 table->rows += mono_array_length (tb->properties);
3501                 alloc_table (table, table->rows);
3502                 table = &assembly->tables [MONO_TABLE_PROPERTYMAP];
3503                 table->rows ++;
3504                 alloc_table (table, table->rows);
3505                 values = table->values + table->rows * MONO_PROPERTY_MAP_SIZE;
3506                 values [MONO_PROPERTY_MAP_PARENT] = tb->table_idx;
3507                 values [MONO_PROPERTY_MAP_PROPERTY_LIST] = assembly->tables [MONO_TABLE_PROPERTY].next_idx;
3508                 for (i = 0; i < mono_array_length (tb->properties); ++i)
3509                         mono_image_get_property_info (
3510                                 mono_array_get (tb->properties, MonoReflectionPropertyBuilder*, i), assembly);
3511         }
3512
3513         /* handle generic parameters */
3514         if (tb->generic_params) {
3515                 table = &assembly->tables [MONO_TABLE_GENERICPARAM];
3516                 table->rows += mono_array_length (tb->generic_params);
3517                 alloc_table (table, table->rows);
3518                 for (i = 0; i < mono_array_length (tb->generic_params); ++i) {
3519                         guint32 owner = MONO_TYPEORMETHOD_TYPE | (tb->table_idx << MONO_TYPEORMETHOD_BITS);
3520
3521                         mono_image_get_generic_param_info (
3522                                 mono_array_get (tb->generic_params, MonoReflectionGenericParam*, i), owner, assembly);
3523                 }
3524         }
3525
3526         mono_image_add_decl_security (assembly, 
3527                 mono_metadata_make_token (MONO_TABLE_TYPEDEF, tb->table_idx), tb->permissions);
3528
3529         if (tb->subtypes) {
3530                 MonoDynamicTable *ntable;
3531                 
3532                 ntable = &assembly->tables [MONO_TABLE_NESTEDCLASS];
3533                 ntable->rows += mono_array_length (tb->subtypes);
3534                 alloc_table (ntable, ntable->rows);
3535                 values = ntable->values + ntable->next_idx * MONO_NESTED_CLASS_SIZE;
3536
3537                 for (i = 0; i < mono_array_length (tb->subtypes); ++i) {
3538                         MonoReflectionTypeBuilder *subtype = mono_array_get (tb->subtypes, MonoReflectionTypeBuilder*, i);
3539
3540                         values [MONO_NESTED_CLASS_NESTED] = subtype->table_idx;
3541                         values [MONO_NESTED_CLASS_ENCLOSING] = tb->table_idx;
3542                         /*g_print ("nesting %s (%d) in %s (%d) (rows %d/%d)\n",
3543                                 mono_string_to_utf8 (subtype->name), subtype->table_idx,
3544                                 mono_string_to_utf8 (tb->name), tb->table_idx,
3545                                 ntable->next_idx, ntable->rows);*/
3546                         values += MONO_NESTED_CLASS_SIZE;
3547                         ntable->next_idx++;
3548                 }
3549         }
3550 }
3551 #endif
3552
3553 static void
3554 collect_types (MonoPtrArray *types, MonoReflectionTypeBuilder *type)
3555 {
3556         int i;
3557
3558         mono_ptr_array_append (*types, type);
3559
3560         if (!type->subtypes)
3561                 return;
3562
3563         for (i = 0; i < mono_array_length (type->subtypes); ++i) {
3564                 MonoReflectionTypeBuilder *subtype = mono_array_get (type->subtypes, MonoReflectionTypeBuilder*, i);
3565                 collect_types (types, subtype);
3566         }
3567 }
3568
3569 static gint
3570 compare_types_by_table_idx (MonoReflectionTypeBuilder **type1, MonoReflectionTypeBuilder **type2)
3571 {
3572         if ((*type1)->table_idx < (*type2)->table_idx)
3573                 return -1;
3574         else
3575                 if ((*type1)->table_idx > (*type2)->table_idx)
3576                         return 1;
3577         else
3578                 return 0;
3579 }
3580
3581 static void
3582 params_add_cattrs (MonoDynamicImage *assembly, MonoArray *pinfo) {
3583         int i;
3584
3585         if (!pinfo)
3586                 return;
3587         for (i = 0; i < mono_array_length (pinfo); ++i) {
3588                 MonoReflectionParamBuilder *pb;
3589                 pb = mono_array_get (pinfo, MonoReflectionParamBuilder *, i);
3590                 if (!pb)
3591                         continue;
3592                 mono_image_add_cattrs (assembly, pb->table_idx, MONO_CUSTOM_ATTR_PARAMDEF, pb->cattrs);
3593         }
3594 }
3595
3596 static void
3597 type_add_cattrs (MonoDynamicImage *assembly, MonoReflectionTypeBuilder *tb) {
3598         int i;
3599         
3600         mono_image_add_cattrs (assembly, tb->table_idx, MONO_CUSTOM_ATTR_TYPEDEF, tb->cattrs);
3601         if (tb->fields) {
3602                 for (i = 0; i < tb->num_fields; ++i) {
3603                         MonoReflectionFieldBuilder* fb;
3604                         fb = mono_array_get (tb->fields, MonoReflectionFieldBuilder*, i);
3605                         mono_image_add_cattrs (assembly, fb->table_idx, MONO_CUSTOM_ATTR_FIELDDEF, fb->cattrs);
3606                 }
3607         }
3608         if (tb->events) {
3609                 for (i = 0; i < mono_array_length (tb->events); ++i) {
3610                         MonoReflectionEventBuilder* eb;
3611                         eb = mono_array_get (tb->events, MonoReflectionEventBuilder*, i);
3612                         mono_image_add_cattrs (assembly, eb->table_idx, MONO_CUSTOM_ATTR_EVENT, eb->cattrs);
3613                 }
3614         }
3615         if (tb->properties) {
3616                 for (i = 0; i < mono_array_length (tb->properties); ++i) {
3617                         MonoReflectionPropertyBuilder* pb;
3618                         pb = mono_array_get (tb->properties, MonoReflectionPropertyBuilder*, i);
3619                         mono_image_add_cattrs (assembly, pb->table_idx, MONO_CUSTOM_ATTR_PROPERTY, pb->cattrs);
3620                 }
3621         }
3622         if (tb->ctors) {
3623                 for (i = 0; i < mono_array_length (tb->ctors); ++i) {
3624                         MonoReflectionCtorBuilder* cb;
3625                         cb = mono_array_get (tb->ctors, MonoReflectionCtorBuilder*, i);
3626                         mono_image_add_cattrs (assembly, cb->table_idx, MONO_CUSTOM_ATTR_METHODDEF, cb->cattrs);
3627                         params_add_cattrs (assembly, cb->pinfo);
3628                 }
3629         }
3630
3631         if (tb->methods) {
3632                 for (i = 0; i < tb->num_methods; ++i) {
3633                         MonoReflectionMethodBuilder* mb;
3634                         mb = mono_array_get (tb->methods, MonoReflectionMethodBuilder*, i);
3635                         mono_image_add_cattrs (assembly, mb->table_idx, MONO_CUSTOM_ATTR_METHODDEF, mb->cattrs);
3636                         params_add_cattrs (assembly, mb->pinfo);
3637                 }
3638         }
3639
3640         if (tb->subtypes) {
3641                 for (i = 0; i < mono_array_length (tb->subtypes); ++i)
3642                         type_add_cattrs (assembly, mono_array_get (tb->subtypes, MonoReflectionTypeBuilder*, i));
3643         }
3644 }
3645
3646 static void
3647 module_add_cattrs (MonoDynamicImage *assembly, MonoReflectionModuleBuilder *moduleb)
3648 {
3649         int i;
3650         
3651         mono_image_add_cattrs (assembly, moduleb->table_idx, MONO_CUSTOM_ATTR_MODULE, moduleb->cattrs);
3652
3653         if (moduleb->global_methods) {
3654                 for (i = 0; i < mono_array_length (moduleb->global_methods); ++i) {
3655                         MonoReflectionMethodBuilder* mb = mono_array_get (moduleb->global_methods, MonoReflectionMethodBuilder*, i);
3656                         mono_image_add_cattrs (assembly, mb->table_idx, MONO_CUSTOM_ATTR_METHODDEF, mb->cattrs);
3657                         params_add_cattrs (assembly, mb->pinfo);
3658                 }
3659         }
3660
3661         if (moduleb->global_fields) {
3662                 for (i = 0; i < mono_array_length (moduleb->global_fields); ++i) {
3663                         MonoReflectionFieldBuilder *fb = mono_array_get (moduleb->global_fields, MonoReflectionFieldBuilder*, i);
3664                         mono_image_add_cattrs (assembly, fb->table_idx, MONO_CUSTOM_ATTR_FIELDDEF, fb->cattrs);
3665                 }
3666         }
3667         
3668         if (moduleb->types) {
3669                 for (i = 0; i < moduleb->num_types; ++i)
3670                         type_add_cattrs (assembly, mono_array_get (moduleb->types, MonoReflectionTypeBuilder*, i));
3671         }
3672 }
3673
3674 static void
3675 mono_image_fill_file_table (MonoDomain *domain, MonoReflectionModule *module, MonoDynamicImage *assembly)
3676 {
3677         MonoDynamicTable *table;
3678         guint32 *values;
3679         char blob_size [6];
3680         guchar hash [20];
3681         char *b = blob_size;
3682         char *dir, *path;
3683
3684         table = &assembly->tables [MONO_TABLE_FILE];
3685         table->rows++;
3686         alloc_table (table, table->rows);
3687         values = table->values + table->next_idx * MONO_FILE_SIZE;
3688         values [MONO_FILE_FLAGS] = FILE_CONTAINS_METADATA;
3689         values [MONO_FILE_NAME] = string_heap_insert (&assembly->sheap, module->image->module_name);
3690         if (module->image->dynamic) {
3691                 /* This depends on the fact that the main module is emitted last */
3692                 dir = mono_string_to_utf8 (((MonoReflectionModuleBuilder*)module)->assemblyb->dir);
3693                 path = g_strdup_printf ("%s%c%s", dir, G_DIR_SEPARATOR, module->image->module_name);
3694         } else {
3695                 dir = NULL;
3696                 path = g_strdup (module->image->name);
3697         }
3698         mono_sha1_get_digest_from_file (path, hash);
3699         g_free (dir);
3700         g_free (path);
3701         mono_metadata_encode_value (20, b, &b);
3702         values [MONO_FILE_HASH_VALUE] = mono_image_add_stream_data (&assembly->blob, blob_size, b-blob_size);
3703         mono_image_add_stream_data (&assembly->blob, (char*)hash, 20);
3704         table->next_idx ++;
3705 }
3706
3707 static void
3708 mono_image_fill_module_table (MonoDomain *domain, MonoReflectionModuleBuilder *mb, MonoDynamicImage *assembly)
3709 {
3710         MonoDynamicTable *table;
3711         int i;
3712
3713         table = &assembly->tables [MONO_TABLE_MODULE];
3714         mb->table_idx = table->next_idx ++;
3715         table->values [mb->table_idx * MONO_MODULE_SIZE + MONO_MODULE_NAME] = string_heap_insert_mstring (&assembly->sheap, mb->module.name);
3716         i = mono_image_add_stream_data (&assembly->guid, mono_array_addr (mb->guid, char, 0), 16);
3717         i /= 16;
3718         ++i;
3719         table->values [mb->table_idx * MONO_MODULE_SIZE + MONO_MODULE_GENERATION] = 0;
3720         table->values [mb->table_idx * MONO_MODULE_SIZE + MONO_MODULE_MVID] = i;
3721         table->values [mb->table_idx * MONO_MODULE_SIZE + MONO_MODULE_ENC] = 0;
3722         table->values [mb->table_idx * MONO_MODULE_SIZE + MONO_MODULE_ENCBASE] = 0;
3723 }
3724
3725 static guint32
3726 mono_image_fill_export_table_from_class (MonoDomain *domain, MonoClass *klass,
3727         guint32 module_index, guint32 parent_index, MonoDynamicImage *assembly)
3728 {
3729         MonoDynamicTable *table;
3730         guint32 *values;
3731         guint32 visib, res;
3732
3733         visib = klass->flags & TYPE_ATTRIBUTE_VISIBILITY_MASK;
3734         if (! ((visib & TYPE_ATTRIBUTE_PUBLIC) || (visib & TYPE_ATTRIBUTE_NESTED_PUBLIC)))
3735                 return 0;
3736
3737         table = &assembly->tables [MONO_TABLE_EXPORTEDTYPE];
3738         table->rows++;
3739         alloc_table (table, table->rows);
3740         values = table->values + table->next_idx * MONO_EXP_TYPE_SIZE;
3741
3742         values [MONO_EXP_TYPE_FLAGS] = klass->flags;
3743         values [MONO_EXP_TYPE_TYPEDEF] = klass->type_token;
3744         if (klass->nested_in)
3745                 values [MONO_EXP_TYPE_IMPLEMENTATION] = (parent_index << MONO_IMPLEMENTATION_BITS) + MONO_IMPLEMENTATION_EXP_TYPE;
3746         else
3747                 values [MONO_EXP_TYPE_IMPLEMENTATION] = (module_index << MONO_IMPLEMENTATION_BITS) + MONO_IMPLEMENTATION_FILE;
3748         values [MONO_EXP_TYPE_NAME] = string_heap_insert (&assembly->sheap, klass->name);
3749         values [MONO_EXP_TYPE_NAMESPACE] = string_heap_insert (&assembly->sheap, klass->name_space);
3750
3751         res = table->next_idx;
3752
3753         table->next_idx ++;
3754
3755         /* Emit nested types */
3756         if (klass->ext && klass->ext->nested_classes) {
3757                 GList *tmp;
3758
3759                 for (tmp = klass->ext->nested_classes; tmp; tmp = tmp->next)
3760                         mono_image_fill_export_table_from_class (domain, tmp->data, module_index, table->next_idx - 1, assembly);
3761         }
3762
3763         return res;
3764 }
3765
3766 static void
3767 mono_image_fill_export_table (MonoDomain *domain, MonoReflectionTypeBuilder *tb,
3768         guint32 module_index, guint32 parent_index, MonoDynamicImage *assembly)
3769 {
3770         MonoClass *klass;
3771         guint32 idx, i;
3772
3773         klass = mono_class_from_mono_type (mono_reflection_type_get_handle ((MonoReflectionType*)tb));
3774
3775         klass->type_token = mono_metadata_make_token (MONO_TABLE_TYPEDEF, tb->table_idx);
3776
3777         idx = mono_image_fill_export_table_from_class (domain, klass, module_index, 
3778                                                                                                    parent_index, assembly);
3779
3780         /* 
3781          * Emit nested types
3782          * We need to do this ourselves since klass->nested_classes is not set up.
3783          */
3784         if (tb->subtypes) {
3785                 for (i = 0; i < mono_array_length (tb->subtypes); ++i)
3786                         mono_image_fill_export_table (domain, mono_array_get (tb->subtypes, MonoReflectionTypeBuilder*, i), module_index, idx, assembly);
3787         }
3788 }
3789
3790 static void
3791 mono_image_fill_export_table_from_module (MonoDomain *domain, MonoReflectionModule *module,
3792         guint32 module_index, MonoDynamicImage *assembly)
3793 {
3794         MonoImage *image = module->image;
3795         MonoTableInfo  *t;
3796         guint32 i;
3797
3798         t = &image->tables [MONO_TABLE_TYPEDEF];
3799
3800         for (i = 0; i < t->rows; ++i) {
3801                 MonoClass *klass = mono_class_get (image, mono_metadata_make_token (MONO_TABLE_TYPEDEF, i + 1));
3802
3803                 if (klass->flags & TYPE_ATTRIBUTE_PUBLIC)
3804                         mono_image_fill_export_table_from_class (domain, klass, module_index, 0, assembly);
3805         }
3806 }
3807
3808 static void
3809 add_exported_type (MonoReflectionAssemblyBuilder *assemblyb, MonoDynamicImage *assembly, MonoClass *klass, guint32 parent_index)
3810 {
3811         MonoDynamicTable *table;
3812         guint32 *values;
3813         guint32 scope, scope_idx, impl, current_idx;
3814         gboolean forwarder = TRUE;
3815         gpointer iter = NULL;
3816         MonoClass *nested;
3817
3818         if (klass->nested_in) {
3819                 impl = (parent_index << MONO_IMPLEMENTATION_BITS) + MONO_IMPLEMENTATION_EXP_TYPE;
3820                 forwarder = FALSE;
3821         } else {
3822                 scope = resolution_scope_from_image (assembly, klass->image);
3823                 g_assert ((scope & MONO_RESOLTION_SCOPE_MASK) == MONO_RESOLTION_SCOPE_ASSEMBLYREF);
3824                 scope_idx = scope >> MONO_RESOLTION_SCOPE_BITS;
3825                 impl = (scope_idx << MONO_IMPLEMENTATION_BITS) + MONO_IMPLEMENTATION_ASSEMBLYREF;
3826         }
3827
3828         table = &assembly->tables [MONO_TABLE_EXPORTEDTYPE];
3829
3830         table->rows++;
3831         alloc_table (table, table->rows);
3832         current_idx = table->next_idx;
3833         values = table->values + current_idx * MONO_EXP_TYPE_SIZE;
3834
3835         values [MONO_EXP_TYPE_FLAGS] = forwarder ? TYPE_ATTRIBUTE_FORWARDER : 0;
3836         values [MONO_EXP_TYPE_TYPEDEF] = 0;
3837         values [MONO_EXP_TYPE_IMPLEMENTATION] = impl;
3838         values [MONO_EXP_TYPE_NAME] = string_heap_insert (&assembly->sheap, klass->name);
3839         values [MONO_EXP_TYPE_NAMESPACE] = string_heap_insert (&assembly->sheap, klass->name_space);
3840
3841         table->next_idx++;
3842
3843         while ((nested = mono_class_get_nested_types (klass, &iter)))
3844                 add_exported_type (assemblyb, assembly, nested, current_idx);
3845 }
3846
3847 static void
3848 mono_image_fill_export_table_from_type_forwarders (MonoReflectionAssemblyBuilder *assemblyb, MonoDynamicImage *assembly)
3849 {
3850         MonoClass *klass;
3851         int i;
3852
3853         if (!assemblyb->type_forwarders)
3854                 return;
3855
3856         for (i = 0; i < mono_array_length (assemblyb->type_forwarders); ++i) {
3857                 MonoReflectionType *t = mono_array_get (assemblyb->type_forwarders, MonoReflectionType *, i);
3858                 MonoType *type;
3859                 if (!t)
3860                         continue;
3861
3862                 type = mono_reflection_type_get_handle (t);
3863                 g_assert (type);
3864
3865                 klass = mono_class_from_mono_type (type);
3866
3867                 add_exported_type (assemblyb, assembly, klass, 0);
3868         }
3869 }
3870
3871 #define align_pointer(base,p)\
3872         do {\
3873                 guint32 __diff = (unsigned char*)(p)-(unsigned char*)(base);\
3874                 if (__diff & 3)\
3875                         (p) += 4 - (__diff & 3);\
3876         } while (0)
3877
3878 static int
3879 compare_constants (const void *a, const void *b)
3880 {
3881         const guint32 *a_values = a;
3882         const guint32 *b_values = b;
3883         return a_values [MONO_CONSTANT_PARENT] - b_values [MONO_CONSTANT_PARENT];
3884 }
3885
3886 static int
3887 compare_semantics (const void *a, const void *b)
3888 {
3889         const guint32 *a_values = a;
3890         const guint32 *b_values = b;
3891         int assoc = a_values [MONO_METHOD_SEMA_ASSOCIATION] - b_values [MONO_METHOD_SEMA_ASSOCIATION];
3892         if (assoc)
3893                 return assoc;
3894         return a_values [MONO_METHOD_SEMA_SEMANTICS] - b_values [MONO_METHOD_SEMA_SEMANTICS];
3895 }
3896
3897 static int
3898 compare_custom_attrs (const void *a, const void *b)
3899 {
3900         const guint32 *a_values = a;
3901         const guint32 *b_values = b;
3902
3903         return a_values [MONO_CUSTOM_ATTR_PARENT] - b_values [MONO_CUSTOM_ATTR_PARENT];
3904 }
3905
3906 static int
3907 compare_field_marshal (const void *a, const void *b)
3908 {
3909         const guint32 *a_values = a;
3910         const guint32 *b_values = b;
3911
3912         return a_values [MONO_FIELD_MARSHAL_PARENT] - b_values [MONO_FIELD_MARSHAL_PARENT];
3913 }
3914
3915 static int
3916 compare_nested (const void *a, const void *b)
3917 {
3918         const guint32 *a_values = a;
3919         const guint32 *b_values = b;
3920
3921         return a_values [MONO_NESTED_CLASS_NESTED] - b_values [MONO_NESTED_CLASS_NESTED];
3922 }
3923
3924 static int
3925 compare_genericparam (const void *a, const void *b)
3926 {
3927         const GenericParamTableEntry **a_entry = (const GenericParamTableEntry **) a;
3928         const GenericParamTableEntry **b_entry = (const GenericParamTableEntry **) b;
3929
3930         if ((*b_entry)->owner == (*a_entry)->owner)
3931                 return 
3932                         mono_type_get_generic_param_num (mono_reflection_type_get_handle ((MonoReflectionType*)(*a_entry)->gparam)) -
3933                         mono_type_get_generic_param_num (mono_reflection_type_get_handle ((MonoReflectionType*)(*b_entry)->gparam));
3934         else
3935                 return (*a_entry)->owner - (*b_entry)->owner;
3936 }
3937
3938 static int
3939 compare_declsecurity_attrs (const void *a, const void *b)
3940 {
3941         const guint32 *a_values = a;
3942         const guint32 *b_values = b;
3943
3944         return a_values [MONO_DECL_SECURITY_PARENT] - b_values [MONO_DECL_SECURITY_PARENT];
3945 }
3946
3947 static int
3948 compare_interface_impl (const void *a, const void *b)
3949 {
3950         const guint32 *a_values = a;
3951         const guint32 *b_values = b;
3952
3953         int klass = a_values [MONO_INTERFACEIMPL_CLASS] - b_values [MONO_INTERFACEIMPL_CLASS];
3954         if (klass)
3955                 return klass;
3956
3957         return a_values [MONO_INTERFACEIMPL_INTERFACE] - b_values [MONO_INTERFACEIMPL_INTERFACE];
3958 }
3959
3960 static void
3961 pad_heap (MonoDynamicStream *sh)
3962 {
3963         if (sh->index & 3) {
3964                 int sz = 4 - (sh->index & 3);
3965                 memset (sh->data + sh->index, 0, sz);
3966                 sh->index += sz;
3967         }
3968 }
3969
3970 struct StreamDesc {
3971         const char *name;
3972         MonoDynamicStream *stream;
3973 };
3974
3975 /*
3976  * build_compressed_metadata() fills in the blob of data that represents the 
3977  * raw metadata as it will be saved in the PE file. The five streams are output 
3978  * and the metadata tables are comnpressed from the guint32 array representation, 
3979  * to the compressed on-disk format.
3980  */
3981 static void
3982 build_compressed_metadata (MonoDynamicImage *assembly)
3983 {
3984         MonoDynamicTable *table;
3985         int i;
3986         guint64 valid_mask = 0;
3987         guint64 sorted_mask;
3988         guint32 heapt_size = 0;
3989         guint32 meta_size = 256; /* allow for header and other stuff */
3990         guint32 table_offset;
3991         guint32 ntables = 0;
3992         guint64 *int64val;
3993         guint32 *int32val;
3994         guint16 *int16val;
3995         MonoImage *meta;
3996         unsigned char *p;
3997         struct StreamDesc stream_desc [5];
3998
3999         qsort (assembly->gen_params->pdata, assembly->gen_params->len, sizeof (gpointer), compare_genericparam);
4000         for (i = 0; i < assembly->gen_params->len; i++){
4001                 GenericParamTableEntry *entry = g_ptr_array_index (assembly->gen_params, i);
4002                 write_generic_param_entry (assembly, entry);
4003         }
4004
4005         stream_desc [0].name  = "#~";
4006         stream_desc [0].stream = &assembly->tstream;
4007         stream_desc [1].name  = "#Strings";
4008         stream_desc [1].stream = &assembly->sheap;
4009         stream_desc [2].name  = "#US";
4010         stream_desc [2].stream = &assembly->us;
4011         stream_desc [3].name  = "#Blob";
4012         stream_desc [3].stream = &assembly->blob;
4013         stream_desc [4].name  = "#GUID";
4014         stream_desc [4].stream = &assembly->guid;
4015         
4016         /* tables that are sorted */
4017         sorted_mask = ((guint64)1 << MONO_TABLE_CONSTANT) | ((guint64)1 << MONO_TABLE_FIELDMARSHAL)
4018                 | ((guint64)1 << MONO_TABLE_METHODSEMANTICS) | ((guint64)1 << MONO_TABLE_CLASSLAYOUT)
4019                 | ((guint64)1 << MONO_TABLE_FIELDLAYOUT) | ((guint64)1 << MONO_TABLE_FIELDRVA)
4020                 | ((guint64)1 << MONO_TABLE_IMPLMAP) | ((guint64)1 << MONO_TABLE_NESTEDCLASS)
4021                 | ((guint64)1 << MONO_TABLE_METHODIMPL) | ((guint64)1 << MONO_TABLE_CUSTOMATTRIBUTE)
4022                 | ((guint64)1 << MONO_TABLE_DECLSECURITY) | ((guint64)1 << MONO_TABLE_GENERICPARAM)
4023                 | ((guint64)1 << MONO_TABLE_INTERFACEIMPL);
4024         
4025         /* Compute table sizes */
4026         /* the MonoImage has already been created in mono_image_basic_init() */
4027         meta = &assembly->image;
4028
4029         /* sizes should be multiple of 4 */
4030         pad_heap (&assembly->blob);
4031         pad_heap (&assembly->guid);
4032         pad_heap (&assembly->sheap);
4033         pad_heap (&assembly->us);
4034
4035         /* Setup the info used by compute_sizes () */
4036         meta->idx_blob_wide = assembly->blob.index >= 65536 ? 1 : 0;
4037         meta->idx_guid_wide = assembly->guid.index >= 65536 ? 1 : 0;
4038         meta->idx_string_wide = assembly->sheap.index >= 65536 ? 1 : 0;
4039
4040         meta_size += assembly->blob.index;
4041         meta_size += assembly->guid.index;
4042         meta_size += assembly->sheap.index;
4043         meta_size += assembly->us.index;
4044
4045         for (i=0; i < MONO_TABLE_NUM; ++i)
4046                 meta->tables [i].rows = assembly->tables [i].rows;
4047         
4048         for (i = 0; i < MONO_TABLE_NUM; i++){
4049                 if (meta->tables [i].rows == 0)
4050                         continue;
4051                 valid_mask |= (guint64)1 << i;
4052                 ntables ++;
4053                 meta->tables [i].row_size = mono_metadata_compute_size (
4054                         meta, i, &meta->tables [i].size_bitfield);
4055                 heapt_size += meta->tables [i].row_size * meta->tables [i].rows;
4056         }
4057         heapt_size += 24; /* #~ header size */
4058         heapt_size += ntables * 4;
4059         /* make multiple of 4 */
4060         heapt_size += 3;
4061         heapt_size &= ~3;
4062         meta_size += heapt_size;
4063         meta->raw_metadata = g_malloc0 (meta_size);
4064         p = (unsigned char*)meta->raw_metadata;
4065         /* the metadata signature */
4066         *p++ = 'B'; *p++ = 'S'; *p++ = 'J'; *p++ = 'B';
4067         /* version numbers and 4 bytes reserved */
4068         int16val = (guint16*)p;
4069         *int16val++ = GUINT16_TO_LE (meta->md_version_major);
4070         *int16val = GUINT16_TO_LE (meta->md_version_minor);
4071         p += 8;
4072         /* version string */
4073         int32val = (guint32*)p;
4074         *int32val = GUINT32_TO_LE ((strlen (meta->version) + 3) & (~3)); /* needs to be multiple of 4 */
4075         p += 4;
4076         memcpy (p, meta->version, strlen (meta->version));
4077         p += GUINT32_FROM_LE (*int32val);
4078         align_pointer (meta->raw_metadata, p);
4079         int16val = (guint16*)p;
4080         *int16val++ = GUINT16_TO_LE (0); /* flags must be 0 */
4081         *int16val = GUINT16_TO_LE (5); /* number of streams */
4082         p += 4;
4083
4084         /*
4085          * write the stream info.
4086          */
4087         table_offset = (p - (unsigned char*)meta->raw_metadata) + 5 * 8 + 40; /* room needed for stream headers */
4088         table_offset += 3; table_offset &= ~3;
4089
4090         assembly->tstream.index = heapt_size;
4091         for (i = 0; i < 5; ++i) {
4092                 int32val = (guint32*)p;
4093                 stream_desc [i].stream->offset = table_offset;
4094                 *int32val++ = GUINT32_TO_LE (table_offset);
4095                 *int32val = GUINT32_TO_LE (stream_desc [i].stream->index);
4096                 table_offset += GUINT32_FROM_LE (*int32val);
4097                 table_offset += 3; table_offset &= ~3;
4098                 p += 8;
4099                 strcpy ((char*)p, stream_desc [i].name);
4100                 p += strlen (stream_desc [i].name) + 1;
4101                 align_pointer (meta->raw_metadata, p);
4102         }
4103         /* 
4104          * now copy the data, the table stream header and contents goes first.
4105          */
4106         g_assert ((p - (unsigned char*)meta->raw_metadata) < assembly->tstream.offset);
4107         p = (guchar*)meta->raw_metadata + assembly->tstream.offset;
4108         int32val = (guint32*)p;
4109         *int32val = GUINT32_TO_LE (0); /* reserved */
4110         p += 4;
4111
4112         *p++ = 2; /* version */
4113         *p++ = 0;
4114
4115         if (meta->idx_string_wide)
4116                 *p |= 0x01;
4117         if (meta->idx_guid_wide)
4118                 *p |= 0x02;
4119         if (meta->idx_blob_wide)
4120                 *p |= 0x04;
4121         ++p;
4122         *p++ = 1; /* reserved */
4123         int64val = (guint64*)p;
4124         *int64val++ = GUINT64_TO_LE (valid_mask);
4125         *int64val++ = GUINT64_TO_LE (valid_mask & sorted_mask); /* bitvector of sorted tables  */
4126         p += 16;
4127         int32val = (guint32*)p;
4128         for (i = 0; i < MONO_TABLE_NUM; i++){
4129                 if (meta->tables [i].rows == 0)
4130                         continue;
4131                 *int32val++ = GUINT32_TO_LE (meta->tables [i].rows);
4132         }
4133         p = (unsigned char*)int32val;
4134
4135         /* sort the tables that still need sorting */
4136         table = &assembly->tables [MONO_TABLE_CONSTANT];
4137         if (table->rows)
4138                 qsort (table->values + MONO_CONSTANT_SIZE, table->rows, sizeof (guint32) * MONO_CONSTANT_SIZE, compare_constants);
4139         table = &assembly->tables [MONO_TABLE_METHODSEMANTICS];
4140         if (table->rows)
4141                 qsort (table->values + MONO_METHOD_SEMA_SIZE, table->rows, sizeof (guint32) * MONO_METHOD_SEMA_SIZE, compare_semantics);
4142         table = &assembly->tables [MONO_TABLE_CUSTOMATTRIBUTE];
4143         if (table->rows)
4144                 qsort (table->values + MONO_CUSTOM_ATTR_SIZE, table->rows, sizeof (guint32) * MONO_CUSTOM_ATTR_SIZE, compare_custom_attrs);
4145         table = &assembly->tables [MONO_TABLE_FIELDMARSHAL];
4146         if (table->rows)
4147                 qsort (table->values + MONO_FIELD_MARSHAL_SIZE, table->rows, sizeof (guint32) * MONO_FIELD_MARSHAL_SIZE, compare_field_marshal);
4148         table = &assembly->tables [MONO_TABLE_NESTEDCLASS];
4149         if (table->rows)
4150                 qsort (table->values + MONO_NESTED_CLASS_SIZE, table->rows, sizeof (guint32) * MONO_NESTED_CLASS_SIZE, compare_nested);
4151         /* Section 21.11 DeclSecurity in Partition II doesn't specify this to be sorted by MS implementation requires it */
4152         table = &assembly->tables [MONO_TABLE_DECLSECURITY];
4153         if (table->rows)
4154                 qsort (table->values + MONO_DECL_SECURITY_SIZE, table->rows, sizeof (guint32) * MONO_DECL_SECURITY_SIZE, compare_declsecurity_attrs);
4155         table = &assembly->tables [MONO_TABLE_INTERFACEIMPL];
4156         if (table->rows)
4157                 qsort (table->values + MONO_INTERFACEIMPL_SIZE, table->rows, sizeof (guint32) * MONO_INTERFACEIMPL_SIZE, compare_interface_impl);
4158
4159         /* compress the tables */
4160         for (i = 0; i < MONO_TABLE_NUM; i++){
4161                 int row, col;
4162                 guint32 *values;
4163                 guint32 bitfield = meta->tables [i].size_bitfield;
4164                 if (!meta->tables [i].rows)
4165                         continue;
4166                 if (assembly->tables [i].columns != mono_metadata_table_count (bitfield))
4167                         g_error ("col count mismatch in %d: %d %d", i, assembly->tables [i].columns, mono_metadata_table_count (bitfield));
4168                 meta->tables [i].base = (char*)p;
4169                 for (row = 1; row <= meta->tables [i].rows; ++row) {
4170                         values = assembly->tables [i].values + row * assembly->tables [i].columns;
4171                         for (col = 0; col < assembly->tables [i].columns; ++col) {
4172                                 switch (mono_metadata_table_size (bitfield, col)) {
4173                                 case 1:
4174                                         *p++ = values [col];
4175                                         break;
4176                                 case 2:
4177                                         *p++ = values [col] & 0xff;
4178                                         *p++ = (values [col] >> 8) & 0xff;
4179                                         break;
4180                                 case 4:
4181                                         *p++ = values [col] & 0xff;
4182                                         *p++ = (values [col] >> 8) & 0xff;
4183                                         *p++ = (values [col] >> 16) & 0xff;
4184                                         *p++ = (values [col] >> 24) & 0xff;
4185                                         break;
4186                                 default:
4187                                         g_assert_not_reached ();
4188                                 }
4189                         }
4190                 }
4191                 g_assert ((p - (const unsigned char*)meta->tables [i].base) == (meta->tables [i].rows * meta->tables [i].row_size));
4192         }
4193         
4194         g_assert (assembly->guid.offset + assembly->guid.index < meta_size);
4195         memcpy (meta->raw_metadata + assembly->sheap.offset, assembly->sheap.data, assembly->sheap.index);
4196         memcpy (meta->raw_metadata + assembly->us.offset, assembly->us.data, assembly->us.index);
4197         memcpy (meta->raw_metadata + assembly->blob.offset, assembly->blob.data, assembly->blob.index);
4198         memcpy (meta->raw_metadata + assembly->guid.offset, assembly->guid.data, assembly->guid.index);
4199
4200         assembly->meta_size = assembly->guid.offset + assembly->guid.index;
4201 }
4202
4203 /*
4204  * Some tables in metadata need to be sorted according to some criteria, but
4205  * when methods and fields are first created with reflection, they may be assigned a token
4206  * that doesn't correspond to the final token they will get assigned after the sorting.
4207  * ILGenerator.cs keeps a fixup table that maps the position of tokens in the IL code stream
4208  * with the reflection objects that represent them. Once all the tables are set up, the 
4209  * reflection objects will contains the correct table index. fixup_method() will fixup the
4210  * tokens for the method with ILGenerator @ilgen.
4211  */
4212 static void
4213 fixup_method (MonoReflectionILGen *ilgen, gpointer value, MonoDynamicImage *assembly)
4214 {
4215         guint32 code_idx = GPOINTER_TO_UINT (value);
4216         MonoReflectionILTokenInfo *iltoken;
4217         MonoReflectionFieldBuilder *field;
4218         MonoReflectionCtorBuilder *ctor;
4219         MonoReflectionMethodBuilder *method;
4220         MonoReflectionTypeBuilder *tb;
4221         MonoReflectionArrayMethod *am;
4222         guint32 i, idx = 0;
4223         unsigned char *target;
4224
4225         for (i = 0; i < ilgen->num_token_fixups; ++i) {
4226                 iltoken = (MonoReflectionILTokenInfo *)mono_array_addr_with_size (ilgen->token_fixups, sizeof (MonoReflectionILTokenInfo), i);
4227                 target = (guchar*)assembly->code.data + code_idx + iltoken->code_pos;
4228                 switch (target [3]) {
4229                 case MONO_TABLE_FIELD:
4230                         if (!strcmp (iltoken->member->vtable->klass->name, "FieldBuilder")) {
4231                                 field = (MonoReflectionFieldBuilder *)iltoken->member;
4232                                 idx = field->table_idx;
4233                         } else if (!strcmp (iltoken->member->vtable->klass->name, "MonoField")) {
4234                                 MonoClassField *f = ((MonoReflectionField*)iltoken->member)->field;
4235                                 idx = GPOINTER_TO_UINT (g_hash_table_lookup (assembly->field_to_table_idx, f));
4236                         } else {
4237                                 g_assert_not_reached ();
4238                         }
4239                         break;
4240                 case MONO_TABLE_METHOD:
4241                         if (!strcmp (iltoken->member->vtable->klass->name, "MethodBuilder")) {
4242                                 method = (MonoReflectionMethodBuilder *)iltoken->member;
4243                                 idx = method->table_idx;
4244                         } else if (!strcmp (iltoken->member->vtable->klass->name, "ConstructorBuilder")) {
4245                                 ctor = (MonoReflectionCtorBuilder *)iltoken->member;
4246                                 idx = ctor->table_idx;
4247                         } else if (!strcmp (iltoken->member->vtable->klass->name, "MonoMethod") || 
4248                                            !strcmp (iltoken->member->vtable->klass->name, "MonoCMethod")) {
4249                                 MonoMethod *m = ((MonoReflectionMethod*)iltoken->member)->method;
4250                                 idx = GPOINTER_TO_UINT (g_hash_table_lookup (assembly->method_to_table_idx, m));
4251                         } else {
4252                                 g_assert_not_reached ();
4253                         }
4254                         break;
4255                 case MONO_TABLE_TYPEDEF:
4256                         if (strcmp (iltoken->member->vtable->klass->name, "TypeBuilder"))
4257                                 g_assert_not_reached ();
4258                         tb = (MonoReflectionTypeBuilder *)iltoken->member;
4259                         idx = tb->table_idx;
4260                         break;
4261                 case MONO_TABLE_MEMBERREF:
4262                         if (!strcmp (iltoken->member->vtable->klass->name, "MonoArrayMethod")) {
4263                                 am = (MonoReflectionArrayMethod*)iltoken->member;
4264                                 idx = am->table_idx;
4265                         } else if (!strcmp (iltoken->member->vtable->klass->name, "MonoMethod") ||
4266                                    !strcmp (iltoken->member->vtable->klass->name, "MonoCMethod") ||
4267                                    !strcmp (iltoken->member->vtable->klass->name, "MonoGenericMethod") ||
4268                                    !strcmp (iltoken->member->vtable->klass->name, "MonoGenericCMethod")) {
4269                                 MonoMethod *m = ((MonoReflectionMethod*)iltoken->member)->method;
4270                                 g_assert (m->klass->generic_class || m->klass->generic_container);
4271                                 continue;
4272                         } else if (!strcmp (iltoken->member->vtable->klass->name, "FieldBuilder")) {
4273                                 continue;
4274                         } else if (!strcmp (iltoken->member->vtable->klass->name, "MonoField")) {
4275                                 MonoClassField *f = ((MonoReflectionField*)iltoken->member)->field;
4276                                 g_assert (is_field_on_inst (f));
4277                                 continue;
4278                         } else if (!strcmp (iltoken->member->vtable->klass->name, "MethodBuilder") ||
4279                                         !strcmp (iltoken->member->vtable->klass->name, "ConstructorBuilder")) {
4280                                 continue;
4281                         } else if (!strcmp (iltoken->member->vtable->klass->name, "FieldOnTypeBuilderInst")) {
4282                                 continue;
4283                         } else if (!strcmp (iltoken->member->vtable->klass->name, "MethodOnTypeBuilderInst")) {
4284                                 continue;
4285                         } else if (!strcmp (iltoken->member->vtable->klass->name, "ConstructorOnTypeBuilderInst")) {
4286                                 continue;
4287                         } else {
4288                                 g_assert_not_reached ();
4289                         }
4290                         break;
4291                 case MONO_TABLE_METHODSPEC:
4292                         if (!strcmp (iltoken->member->vtable->klass->name, "MonoGenericMethod")) {
4293                                 MonoMethod *m = ((MonoReflectionMethod*)iltoken->member)->method;
4294                                 g_assert (mono_method_signature (m)->generic_param_count);
4295                                 continue;
4296                         } else if (!strcmp (iltoken->member->vtable->klass->name, "MethodBuilder")) {
4297                                 continue;
4298                         } else if (!strcmp (iltoken->member->vtable->klass->name, "MethodOnTypeBuilderInst")) {
4299                                 continue;
4300                         } else {
4301                                 g_assert_not_reached ();
4302                         }
4303                         break;
4304                 default:
4305                         g_error ("got unexpected table 0x%02x in fixup", target [3]);
4306                 }
4307                 target [0] = idx & 0xff;
4308                 target [1] = (idx >> 8) & 0xff;
4309                 target [2] = (idx >> 16) & 0xff;
4310         }
4311 }
4312
4313 /*
4314  * fixup_cattrs:
4315  *
4316  *   The CUSTOM_ATTRIBUTE table might contain METHODDEF tokens whose final
4317  * value is not known when the table is emitted.
4318  */
4319 static void
4320 fixup_cattrs (MonoDynamicImage *assembly)
4321 {
4322         MonoDynamicTable *table;
4323         guint32 *values;
4324         guint32 type, i, idx, token;
4325         MonoObject *ctor;
4326
4327         table = &assembly->tables [MONO_TABLE_CUSTOMATTRIBUTE];
4328
4329         for (i = 0; i < table->rows; ++i) {
4330                 values = table->values + ((i + 1) * MONO_CUSTOM_ATTR_SIZE);
4331
4332                 type = values [MONO_CUSTOM_ATTR_TYPE];
4333                 if ((type & MONO_CUSTOM_ATTR_TYPE_MASK) == MONO_CUSTOM_ATTR_TYPE_METHODDEF) {
4334                         idx = type >> MONO_CUSTOM_ATTR_TYPE_BITS;
4335                         token = mono_metadata_make_token (MONO_TABLE_METHOD, idx);
4336                         ctor = mono_g_hash_table_lookup (assembly->remapped_tokens, GUINT_TO_POINTER (token));
4337                         g_assert (ctor);
4338
4339                         if (!strcmp (ctor->vtable->klass->name, "MonoCMethod")) {
4340                                 MonoMethod *m = ((MonoReflectionMethod*)ctor)->method;
4341                                 idx = GPOINTER_TO_UINT (g_hash_table_lookup (assembly->method_to_table_idx, m));
4342                                 values [MONO_CUSTOM_ATTR_TYPE] = (idx << MONO_CUSTOM_ATTR_TYPE_BITS) | MONO_CUSTOM_ATTR_TYPE_METHODDEF;
4343                         } else if (!strcmp (ctor->vtable->klass->name, "ConstructorBuilder")) {
4344                                 MonoMethod *m = ((MonoReflectionCtorBuilder*)ctor)->mhandle;
4345                                 idx = GPOINTER_TO_UINT (g_hash_table_lookup (assembly->method_to_table_idx, m));
4346                                 values [MONO_CUSTOM_ATTR_TYPE] = (idx << MONO_CUSTOM_ATTR_TYPE_BITS) | MONO_CUSTOM_ATTR_TYPE_METHODDEF;
4347                         }
4348                 }
4349         }
4350 }
4351
4352 static void
4353 assembly_add_resource_manifest (MonoReflectionModuleBuilder *mb, MonoDynamicImage *assembly, MonoReflectionResource *rsrc, guint32 implementation)
4354 {
4355         MonoDynamicTable *table;
4356         guint32 *values;
4357
4358         table = &assembly->tables [MONO_TABLE_MANIFESTRESOURCE];
4359         table->rows++;
4360         alloc_table (table, table->rows);
4361         values = table->values + table->next_idx * MONO_MANIFEST_SIZE;
4362         values [MONO_MANIFEST_OFFSET] = rsrc->offset;
4363         values [MONO_MANIFEST_FLAGS] = rsrc->attrs;
4364         values [MONO_MANIFEST_NAME] = string_heap_insert_mstring (&assembly->sheap, rsrc->name);
4365         values [MONO_MANIFEST_IMPLEMENTATION] = implementation;
4366         table->next_idx++;
4367 }
4368
4369 static void
4370 assembly_add_resource (MonoReflectionModuleBuilder *mb, MonoDynamicImage *assembly, MonoReflectionResource *rsrc)
4371 {
4372         MonoDynamicTable *table;
4373         guint32 *values;
4374         char blob_size [6];
4375         guchar hash [20];
4376         char *b = blob_size;
4377         char *name, *sname;
4378         guint32 idx, offset;
4379
4380         if (rsrc->filename) {
4381                 name = mono_string_to_utf8 (rsrc->filename);
4382                 sname = g_path_get_basename (name);
4383         
4384                 table = &assembly->tables [MONO_TABLE_FILE];
4385                 table->rows++;
4386                 alloc_table (table, table->rows);
4387                 values = table->values + table->next_idx * MONO_FILE_SIZE;
4388                 values [MONO_FILE_FLAGS] = FILE_CONTAINS_NO_METADATA;
4389                 values [MONO_FILE_NAME] = string_heap_insert (&assembly->sheap, sname);
4390                 g_free (sname);
4391
4392                 mono_sha1_get_digest_from_file (name, hash);
4393                 mono_metadata_encode_value (20, b, &b);
4394                 values [MONO_FILE_HASH_VALUE] = mono_image_add_stream_data (&assembly->blob, blob_size, b-blob_size);
4395                 mono_image_add_stream_data (&assembly->blob, (char*)hash, 20);
4396                 g_free (name);
4397                 idx = table->next_idx++;
4398                 rsrc->offset = 0;
4399                 idx = MONO_IMPLEMENTATION_FILE | (idx << MONO_IMPLEMENTATION_BITS);
4400         } else {
4401                 char sizebuf [4];
4402                 char *data;
4403                 guint len;
4404                 if (rsrc->data) {
4405                         data = mono_array_addr (rsrc->data, char, 0);
4406                         len = mono_array_length (rsrc->data);
4407                 } else {
4408                         data = NULL;
4409                         len = 0;
4410                 }
4411                 offset = len;
4412                 sizebuf [0] = offset; sizebuf [1] = offset >> 8;
4413                 sizebuf [2] = offset >> 16; sizebuf [3] = offset >> 24;
4414                 rsrc->offset = mono_image_add_stream_data (&assembly->resources, sizebuf, 4);
4415                 mono_image_add_stream_data (&assembly->resources, data, len);
4416
4417                 if (!mb->is_main)
4418                         /* 
4419                          * The entry should be emitted into the MANIFESTRESOURCE table of 
4420                          * the main module, but that needs to reference the FILE table
4421                          * which isn't emitted yet.
4422                          */
4423                         return;
4424                 else
4425                         idx = 0;
4426         }
4427
4428         assembly_add_resource_manifest (mb, assembly, rsrc, idx);
4429 }
4430
4431 static void
4432 set_version_from_string (MonoString *version, guint32 *values)
4433 {
4434         gchar *ver, *p, *str;
4435         guint32 i;
4436         
4437         values [MONO_ASSEMBLY_MAJOR_VERSION] = 0;
4438         values [MONO_ASSEMBLY_MINOR_VERSION] = 0;
4439         values [MONO_ASSEMBLY_REV_NUMBER] = 0;
4440         values [MONO_ASSEMBLY_BUILD_NUMBER] = 0;
4441         if (!version)
4442                 return;
4443         ver = str = mono_string_to_utf8 (version);
4444         for (i = 0; i < 4; ++i) {
4445                 values [MONO_ASSEMBLY_MAJOR_VERSION + i] = strtol (ver, &p, 10);
4446                 switch (*p) {
4447                 case '.':
4448                         p++;
4449                         break;
4450                 case '*':
4451                         /* handle Revision and Build */
4452                         p++;
4453                         break;
4454                 }
4455                 ver = p;
4456         }
4457         g_free (str);
4458 }
4459
4460 static guint32
4461 load_public_key (MonoArray *pkey, MonoDynamicImage *assembly) {
4462         gsize len;
4463         guint32 token = 0;
4464         char blob_size [6];
4465         char *b = blob_size;
4466
4467         if (!pkey)
4468                 return token;
4469
4470         len = mono_array_length (pkey);
4471         mono_metadata_encode_value (len, b, &b);
4472         token = mono_image_add_stream_data (&assembly->blob, blob_size, b - blob_size);
4473         mono_image_add_stream_data (&assembly->blob, mono_array_addr (pkey, char, 0), len);
4474
4475         assembly->public_key = g_malloc (len);
4476         memcpy (assembly->public_key, mono_array_addr (pkey, char, 0), len);
4477         assembly->public_key_len = len;
4478
4479         /* Special case: check for ECMA key (16 bytes) */
4480         if ((len == MONO_ECMA_KEY_LENGTH) && mono_is_ecma_key (mono_array_addr (pkey, char, 0), len)) {
4481                 /* In this case we must reserve 128 bytes (1024 bits) for the signature */
4482                 assembly->strong_name_size = MONO_DEFAULT_PUBLIC_KEY_LENGTH;
4483         } else if (len >= MONO_PUBLIC_KEY_HEADER_LENGTH + MONO_MINIMUM_PUBLIC_KEY_LENGTH) {
4484                 /* minimum key size (in 2.0) is 384 bits */
4485                 assembly->strong_name_size = len - MONO_PUBLIC_KEY_HEADER_LENGTH;
4486         } else {
4487                 /* FIXME - verifier */
4488                 g_warning ("Invalid public key length: %d bits (total: %d)", (int)MONO_PUBLIC_KEY_BIT_SIZE (len), (int)len);
4489                 assembly->strong_name_size = MONO_DEFAULT_PUBLIC_KEY_LENGTH; /* to be safe */
4490         }
4491         assembly->strong_name = g_malloc0 (assembly->strong_name_size);
4492
4493         return token;
4494 }
4495
4496 static void
4497 mono_image_emit_manifest (MonoReflectionModuleBuilder *moduleb)
4498 {
4499         MonoDynamicTable *table;
4500         MonoDynamicImage *assembly;
4501         MonoReflectionAssemblyBuilder *assemblyb;
4502         MonoDomain *domain;
4503         guint32 *values;
4504         int i;
4505         guint32 module_index;
4506
4507         assemblyb = moduleb->assemblyb;
4508         assembly = moduleb->dynamic_image;
4509         domain = mono_object_domain (assemblyb);
4510
4511         /* Emit ASSEMBLY table */
4512         table = &assembly->tables [MONO_TABLE_ASSEMBLY];
4513         alloc_table (table, 1);
4514         values = table->values + MONO_ASSEMBLY_SIZE;
4515         values [MONO_ASSEMBLY_HASH_ALG] = assemblyb->algid? assemblyb->algid: ASSEMBLY_HASH_SHA1;
4516         values [MONO_ASSEMBLY_NAME] = string_heap_insert_mstring (&assembly->sheap, assemblyb->name);
4517         if (assemblyb->culture) {
4518                 values [MONO_ASSEMBLY_CULTURE] = string_heap_insert_mstring (&assembly->sheap, assemblyb->culture);
4519         } else {
4520                 values [MONO_ASSEMBLY_CULTURE] = string_heap_insert (&assembly->sheap, "");
4521         }
4522         values [MONO_ASSEMBLY_PUBLIC_KEY] = load_public_key (assemblyb->public_key, assembly);
4523         values [MONO_ASSEMBLY_FLAGS] = assemblyb->flags;
4524         set_version_from_string (assemblyb->version, values);
4525
4526         /* Emit FILE + EXPORTED_TYPE table */
4527         module_index = 0;
4528         for (i = 0; i < mono_array_length (assemblyb->modules); ++i) {
4529                 int j;
4530                 MonoReflectionModuleBuilder *file_module = 
4531                         mono_array_get (assemblyb->modules, MonoReflectionModuleBuilder*, i);
4532                 if (file_module != moduleb) {
4533                         mono_image_fill_file_table (domain, (MonoReflectionModule*)file_module, assembly);
4534                         module_index ++;
4535                         if (file_module->types) {
4536                                 for (j = 0; j < file_module->num_types; ++j) {
4537                                         MonoReflectionTypeBuilder *tb = mono_array_get (file_module->types, MonoReflectionTypeBuilder*, j);
4538                                         mono_image_fill_export_table (domain, tb, module_index, 0, assembly);
4539                                 }
4540                         }
4541                 }
4542         }
4543         if (assemblyb->loaded_modules) {
4544                 for (i = 0; i < mono_array_length (assemblyb->loaded_modules); ++i) {
4545                         MonoReflectionModule *file_module = 
4546                                 mono_array_get (assemblyb->loaded_modules, MonoReflectionModule*, i);
4547                         mono_image_fill_file_table (domain, file_module, assembly);
4548                         module_index ++;
4549                         mono_image_fill_export_table_from_module (domain, file_module, module_index, assembly);
4550                 }
4551         }
4552         if (assemblyb->type_forwarders)
4553                 mono_image_fill_export_table_from_type_forwarders (assemblyb, assembly);
4554
4555         /* Emit MANIFESTRESOURCE table */
4556         module_index = 0;
4557         for (i = 0; i < mono_array_length (assemblyb->modules); ++i) {
4558                 int j;
4559                 MonoReflectionModuleBuilder *file_module = 
4560                         mono_array_get (assemblyb->modules, MonoReflectionModuleBuilder*, i);
4561                 /* The table for the main module is emitted later */
4562                 if (file_module != moduleb) {
4563                         module_index ++;
4564                         if (file_module->resources) {
4565                                 int len = mono_array_length (file_module->resources);
4566                                 for (j = 0; j < len; ++j) {
4567                                         MonoReflectionResource* res = (MonoReflectionResource*)mono_array_addr (file_module->resources, MonoReflectionResource, j);
4568                                         assembly_add_resource_manifest (file_module, assembly, res, MONO_IMPLEMENTATION_FILE | (module_index << MONO_IMPLEMENTATION_BITS));
4569                                 }
4570                         }
4571                 }
4572         }               
4573 }
4574
4575 #ifndef DISABLE_REFLECTION_EMIT_SAVE
4576
4577 /*
4578  * mono_image_build_metadata() will fill the info in all the needed metadata tables
4579  * for the modulebuilder @moduleb.
4580  * At the end of the process, method and field tokens are fixed up and the 
4581  * on-disk compressed metadata representation is created.
4582  */
4583 void
4584 mono_image_build_metadata (MonoReflectionModuleBuilder *moduleb)
4585 {
4586         MonoDynamicTable *table;
4587         MonoDynamicImage *assembly;
4588         MonoReflectionAssemblyBuilder *assemblyb;
4589         MonoDomain *domain;
4590         MonoPtrArray types;
4591         guint32 *values;
4592         int i, j;
4593
4594         assemblyb = moduleb->assemblyb;
4595         assembly = moduleb->dynamic_image;
4596         domain = mono_object_domain (assemblyb);
4597
4598         if (assembly->text_rva)
4599                 return;
4600
4601         assembly->text_rva = START_TEXT_RVA;
4602
4603         if (moduleb->is_main) {
4604                 mono_image_emit_manifest (moduleb);
4605         }
4606
4607         table = &assembly->tables [MONO_TABLE_TYPEDEF];
4608         table->rows = 1; /* .<Module> */
4609         table->next_idx++;
4610         alloc_table (table, table->rows);
4611         /*
4612          * Set the first entry.
4613          */
4614         values = table->values + table->columns;
4615         values [MONO_TYPEDEF_FLAGS] = 0;
4616         values [MONO_TYPEDEF_NAME] = string_heap_insert (&assembly->sheap, "<Module>") ;
4617         values [MONO_TYPEDEF_NAMESPACE] = string_heap_insert (&assembly->sheap, "") ;
4618         values [MONO_TYPEDEF_EXTENDS] = 0;
4619         values [MONO_TYPEDEF_FIELD_LIST] = 1;
4620         values [MONO_TYPEDEF_METHOD_LIST] = 1;
4621
4622         /* 
4623          * handle global methods 
4624          * FIXME: test what to do when global methods are defined in multiple modules.
4625          */
4626         if (moduleb->global_methods) {
4627                 table = &assembly->tables [MONO_TABLE_METHOD];
4628                 table->rows += mono_array_length (moduleb->global_methods);
4629                 alloc_table (table, table->rows);
4630                 for (i = 0; i < mono_array_length (moduleb->global_methods); ++i)
4631                         mono_image_get_method_info (
4632                                 mono_array_get (moduleb->global_methods, MonoReflectionMethodBuilder*, i), assembly);
4633         }
4634         if (moduleb->global_fields) {
4635                 table = &assembly->tables [MONO_TABLE_FIELD];
4636                 table->rows += mono_array_length (moduleb->global_fields);
4637                 alloc_table (table, table->rows);
4638                 for (i = 0; i < mono_array_length (moduleb->global_fields); ++i)
4639                         mono_image_get_field_info (
4640                                 mono_array_get (moduleb->global_fields, MonoReflectionFieldBuilder*, i), assembly);
4641         }
4642
4643         table = &assembly->tables [MONO_TABLE_MODULE];
4644         alloc_table (table, 1);
4645         mono_image_fill_module_table (domain, moduleb, assembly);
4646
4647         /* Collect all types into a list sorted by their table_idx */
4648         mono_ptr_array_init (types, moduleb->num_types);
4649
4650         if (moduleb->types)
4651                 for (i = 0; i < moduleb->num_types; ++i) {
4652                         MonoReflectionTypeBuilder *type = mono_array_get (moduleb->types, MonoReflectionTypeBuilder*, i);
4653                         collect_types (&types, type);
4654                 }
4655
4656         mono_ptr_array_sort (types, (gpointer)compare_types_by_table_idx);
4657         table = &assembly->tables [MONO_TABLE_TYPEDEF];
4658         table->rows += mono_ptr_array_size (types);
4659         alloc_table (table, table->rows);
4660
4661         /*
4662          * Emit type names + namespaces at one place inside the string heap,
4663          * so load_class_names () needs to touch fewer pages.
4664          */
4665         for (i = 0; i < mono_ptr_array_size (types); ++i) {
4666                 MonoReflectionTypeBuilder *tb = mono_ptr_array_get (types, i);
4667                 string_heap_insert_mstring (&assembly->sheap, tb->nspace);
4668         }
4669         for (i = 0; i < mono_ptr_array_size (types); ++i) {
4670                 MonoReflectionTypeBuilder *tb = mono_ptr_array_get (types, i);
4671                 string_heap_insert_mstring (&assembly->sheap, tb->name);
4672         }
4673
4674         for (i = 0; i < mono_ptr_array_size (types); ++i) {
4675                 MonoReflectionTypeBuilder *type = mono_ptr_array_get (types, i);
4676                 mono_image_get_type_info (domain, type, assembly);
4677         }
4678
4679         /* 
4680          * table->rows is already set above and in mono_image_fill_module_table.
4681          */
4682         /* add all the custom attributes at the end, once all the indexes are stable */
4683         mono_image_add_cattrs (assembly, 1, MONO_CUSTOM_ATTR_ASSEMBLY, assemblyb->cattrs);
4684
4685         /* CAS assembly permissions */
4686         if (assemblyb->permissions_minimum)
4687                 mono_image_add_decl_security (assembly, mono_metadata_make_token (MONO_TABLE_ASSEMBLY, 1), assemblyb->permissions_minimum);
4688         if (assemblyb->permissions_optional)
4689                 mono_image_add_decl_security (assembly, mono_metadata_make_token (MONO_TABLE_ASSEMBLY, 1), assemblyb->permissions_optional);
4690         if (assemblyb->permissions_refused)
4691                 mono_image_add_decl_security (assembly, mono_metadata_make_token (MONO_TABLE_ASSEMBLY, 1), assemblyb->permissions_refused);
4692
4693         module_add_cattrs (assembly, moduleb);
4694
4695         /* fixup tokens */
4696         mono_g_hash_table_foreach (assembly->token_fixups, (GHFunc)fixup_method, assembly);
4697
4698         /* Create the MethodImpl table.  We do this after emitting all methods so we already know
4699          * the final tokens and don't need another fixup pass. */
4700
4701         if (moduleb->global_methods) {
4702                 for (i = 0; i < mono_array_length (moduleb->global_methods); ++i) {
4703                         MonoReflectionMethodBuilder *mb = mono_array_get (
4704                                 moduleb->global_methods, MonoReflectionMethodBuilder*, i);
4705                         mono_image_add_methodimpl (assembly, mb);
4706                 }
4707         }
4708
4709         for (i = 0; i < mono_ptr_array_size (types); ++i) {
4710                 MonoReflectionTypeBuilder *type = mono_ptr_array_get (types, i);
4711                 if (type->methods) {
4712                         for (j = 0; j < type->num_methods; ++j) {
4713                                 MonoReflectionMethodBuilder *mb = mono_array_get (
4714                                         type->methods, MonoReflectionMethodBuilder*, j);
4715
4716                                 mono_image_add_methodimpl (assembly, mb);
4717                         }
4718                 }
4719         }
4720
4721         mono_ptr_array_destroy (types);
4722
4723         fixup_cattrs (assembly);
4724 }
4725
4726 #else /* DISABLE_REFLECTION_EMIT_SAVE */
4727
4728 void
4729 mono_image_build_metadata (MonoReflectionModuleBuilder *moduleb)
4730 {
4731         g_error ("This mono runtime was configured with --enable-minimal=reflection_emit_save, so saving of dynamic assemblies is not supported.");
4732 }
4733
4734 #endif /* DISABLE_REFLECTION_EMIT_SAVE */
4735
4736
4737 typedef struct {
4738         guint32 import_lookup_table;
4739         guint32 timestamp;
4740         guint32 forwarder;
4741         guint32 name_rva;
4742         guint32 import_address_table_rva;
4743 } MonoIDT;
4744
4745 typedef struct {
4746         guint32 name_rva;
4747         guint32 flags;
4748 } MonoILT;
4749
4750 #ifndef DISABLE_REFLECTION_EMIT
4751
4752 /*
4753  * mono_image_insert_string:
4754  * @module: module builder object
4755  * @str: a string
4756  *
4757  * Insert @str into the user string stream of @module.
4758  */
4759 guint32
4760 mono_image_insert_string (MonoReflectionModuleBuilder *module, MonoString *str)
4761 {
4762         MonoDynamicImage *assembly;
4763         guint32 idx;
4764         char buf [16];
4765         char *b = buf;
4766         
4767         MONO_ARCH_SAVE_REGS;
4768
4769         if (!module->dynamic_image)
4770                 mono_image_module_basic_init (module);
4771
4772         assembly = module->dynamic_image;
4773         
4774         if (assembly->save) {
4775                 mono_metadata_encode_value (1 | (str->length * 2), b, &b);
4776                 idx = mono_image_add_stream_data (&assembly->us, buf, b-buf);
4777 #if G_BYTE_ORDER != G_LITTLE_ENDIAN
4778         {
4779                 char *swapped = g_malloc (2 * mono_string_length (str));
4780                 const char *p = (const char*)mono_string_chars (str);
4781
4782                 swap_with_size (swapped, p, 2, mono_string_length (str));
4783                 mono_image_add_stream_data (&assembly->us, swapped, str->length * 2);
4784                 g_free (swapped);
4785         }
4786 #else
4787                 mono_image_add_stream_data (&assembly->us, (const char*)mono_string_chars (str), str->length * 2);
4788 #endif
4789                 mono_image_add_stream_data (&assembly->us, "", 1);
4790         } else {
4791                 idx = assembly->us.index ++;
4792         }
4793
4794         mono_g_hash_table_insert (assembly->tokens, GUINT_TO_POINTER (MONO_TOKEN_STRING | idx), str);
4795
4796         return MONO_TOKEN_STRING | idx;
4797 }
4798
4799 guint32
4800 mono_image_create_method_token (MonoDynamicImage *assembly, MonoObject *obj, MonoArray *opt_param_types)
4801 {
4802         MonoClass *klass;
4803         guint32 token = 0;
4804         MonoMethodSignature *sig;
4805
4806         klass = obj->vtable->klass;
4807         if (strcmp (klass->name, "MonoMethod") == 0 || strcmp (klass->name, "MonoCMethod") == 0) {
4808                 MonoMethod *method = ((MonoReflectionMethod *)obj)->method;
4809                 MonoMethodSignature *old;
4810                 guint32 sig_token, parent;
4811                 int nargs, i;
4812
4813                 g_assert (opt_param_types && (mono_method_signature (method)->sentinelpos >= 0));
4814
4815                 nargs = mono_array_length (opt_param_types);
4816                 old = mono_method_signature (method);
4817                 sig = mono_metadata_signature_alloc ( &assembly->image, old->param_count + nargs);
4818
4819                 sig->hasthis = old->hasthis;
4820                 sig->explicit_this = old->explicit_this;
4821                 sig->call_convention = old->call_convention;
4822                 sig->generic_param_count = old->generic_param_count;
4823                 sig->param_count = old->param_count + nargs;
4824                 sig->sentinelpos = old->param_count;
4825                 sig->ret = old->ret;
4826
4827                 for (i = 0; i < old->param_count; i++)
4828                         sig->params [i] = old->params [i];
4829
4830                 for (i = 0; i < nargs; i++) {
4831                         MonoReflectionType *rt = mono_array_get (opt_param_types, MonoReflectionType *, i);
4832                         sig->params [old->param_count + i] = mono_reflection_type_get_handle (rt);
4833                 }
4834
4835                 parent = mono_image_typedef_or_ref (assembly, &method->klass->byval_arg);
4836                 g_assert ((parent & MONO_TYPEDEFORREF_MASK) == MONO_MEMBERREF_PARENT_TYPEREF);
4837                 parent >>= MONO_TYPEDEFORREF_BITS;
4838
4839                 parent <<= MONO_MEMBERREF_PARENT_BITS;
4840                 parent |= MONO_MEMBERREF_PARENT_TYPEREF;
4841
4842                 sig_token = method_encode_signature (assembly, sig);
4843                 token = mono_image_get_varargs_method_token (assembly, parent, method->name, sig_token);
4844         } else if (strcmp (klass->name, "MethodBuilder") == 0) {
4845                 MonoReflectionMethodBuilder *mb = (MonoReflectionMethodBuilder *)obj;
4846                 ReflectionMethodBuilder rmb;
4847                 guint32 parent, sig_token;
4848                 int nopt_args, nparams, ngparams, i;
4849                 char *name;
4850
4851                 reflection_methodbuilder_from_method_builder (&rmb, mb);
4852                 rmb.opt_types = opt_param_types;
4853                 nopt_args = mono_array_length (opt_param_types);
4854
4855                 nparams = rmb.parameters ? mono_array_length (rmb.parameters): 0;
4856                 ngparams = rmb.generic_params ? mono_array_length (rmb.generic_params): 0;
4857                 sig = mono_metadata_signature_alloc (&assembly->image, nparams + nopt_args);
4858
4859                 sig->hasthis = !(rmb.attrs & METHOD_ATTRIBUTE_STATIC);
4860                 sig->explicit_this = (rmb.call_conv & 0x40) == 0x40;
4861                 sig->call_convention = rmb.call_conv;
4862                 sig->generic_param_count = ngparams;
4863                 sig->param_count = nparams + nopt_args;
4864                 sig->sentinelpos = nparams;
4865                 sig->ret = mono_reflection_type_get_handle (rmb.rtype);
4866
4867                 for (i = 0; i < nparams; i++) {
4868                         MonoReflectionType *rt = mono_array_get (rmb.parameters, MonoReflectionType *, i);
4869                         sig->params [i] = mono_reflection_type_get_handle (rt);
4870                 }
4871
4872                 for (i = 0; i < nopt_args; i++) {
4873                         MonoReflectionType *rt = mono_array_get (opt_param_types, MonoReflectionType *, i);
4874                         sig->params [nparams + i] = mono_reflection_type_get_handle (rt);
4875                 }
4876
4877                 sig_token = method_builder_encode_signature (assembly, &rmb);
4878
4879                 parent = mono_image_create_token (assembly, obj, TRUE, TRUE);
4880                 g_assert (mono_metadata_token_table (parent) == MONO_TABLE_METHOD);
4881
4882                 parent = mono_metadata_token_index (parent) << MONO_MEMBERREF_PARENT_BITS;
4883                 parent |= MONO_MEMBERREF_PARENT_METHODDEF;
4884
4885                 name = mono_string_to_utf8 (rmb.name);
4886                 token = mono_image_get_varargs_method_token (
4887                         assembly, parent, name, sig_token);
4888                 g_free (name);
4889         } else {
4890                 g_error ("requested method token for %s\n", klass->name);
4891         }
4892
4893         g_hash_table_insert (assembly->vararg_aux_hash, GUINT_TO_POINTER (token), sig);
4894         mono_g_hash_table_insert (assembly->tokens, GUINT_TO_POINTER (token), obj);
4895         return token;
4896 }
4897
4898 /*
4899  * mono_image_create_token:
4900  * @assembly: a dynamic assembly
4901  * @obj:
4902  * @register_token: Whenever to register the token in the assembly->tokens hash. 
4903  *
4904  * Get a token to insert in the IL code stream for the given MemberInfo.
4905  * The metadata emission routines need to pass FALSE as REGISTER_TOKEN, since by that time, 
4906  * the table_idx-es were recomputed, so registering the token would overwrite an existing 
4907  * entry.
4908  */
4909 guint32
4910 mono_image_create_token (MonoDynamicImage *assembly, MonoObject *obj, 
4911                                                  gboolean create_open_instance, gboolean register_token)
4912 {
4913         MonoClass *klass;
4914         guint32 token = 0;
4915
4916         klass = obj->vtable->klass;
4917
4918         /* Check for user defined reflection objects */
4919         /* TypeDelegator is the only corlib type which doesn't look like a MonoReflectionType */
4920         if (klass->image != mono_defaults.corlib || (strcmp (klass->name, "TypeDelegator") == 0))
4921                 mono_raise_exception (mono_get_exception_not_supported ("User defined subclasses of System.Type are not yet supported")); \
4922
4923         if (strcmp (klass->name, "MethodBuilder") == 0) {
4924                 MonoReflectionMethodBuilder *mb = (MonoReflectionMethodBuilder *)obj;
4925                 MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder*)mb->type;
4926
4927                 if (tb->module->dynamic_image == assembly && !tb->generic_params && !mb->generic_params)
4928                         token = mb->table_idx | MONO_TOKEN_METHOD_DEF;
4929                 else
4930                         token = mono_image_get_methodbuilder_token (assembly, mb, create_open_instance);
4931                 /*g_print ("got token 0x%08x for %s\n", token, mono_string_to_utf8 (mb->name));*/
4932         } else if (strcmp (klass->name, "ConstructorBuilder") == 0) {
4933                 MonoReflectionCtorBuilder *mb = (MonoReflectionCtorBuilder *)obj;
4934                 MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder*)mb->type;
4935
4936                 if (tb->module->dynamic_image == assembly && !tb->generic_params)
4937                         token = mb->table_idx | MONO_TOKEN_METHOD_DEF;
4938                 else
4939                         token = mono_image_get_ctorbuilder_token (assembly, mb);
4940                 /*g_print ("got token 0x%08x for %s\n", token, mono_string_to_utf8 (mb->name));*/
4941         } else if (strcmp (klass->name, "FieldBuilder") == 0) {
4942                 MonoReflectionFieldBuilder *fb = (MonoReflectionFieldBuilder *)obj;
4943                 MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder *)fb->typeb;
4944                 if (tb->generic_params) {
4945                         token = mono_image_get_generic_field_token (assembly, fb);
4946                 } else {
4947                         if (tb->module->dynamic_image == assembly) {
4948                                 token = fb->table_idx | MONO_TOKEN_FIELD_DEF;
4949                         } else {
4950                                 token = mono_image_get_fieldref_token (assembly, (MonoObject*)fb, fb->handle);
4951                         }
4952                 }
4953         } else if (strcmp (klass->name, "TypeBuilder") == 0) {
4954                 MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder *)obj;
4955                 if (create_open_instance && tb->generic_params) {
4956                         MonoType *type;
4957                         init_type_builder_generics (obj);
4958                         type = mono_reflection_type_get_handle ((MonoReflectionType *)obj);
4959                         token = mono_image_typedef_or_ref_full (assembly, type, TRUE);
4960                         token = mono_metadata_token_from_dor (token);
4961                 } else if (tb->module->dynamic_image == assembly) {
4962                         token = tb->table_idx | MONO_TOKEN_TYPE_DEF;
4963                 } else {
4964                         MonoType *type;
4965                         type = mono_reflection_type_get_handle ((MonoReflectionType *)obj);
4966                         token = mono_metadata_token_from_dor (mono_image_typedef_or_ref (assembly, type));
4967                 }
4968         } else if (strcmp (klass->name, "MonoType") == 0) {
4969                 MonoType *type = mono_reflection_type_get_handle ((MonoReflectionType *)obj);
4970                 MonoClass *mc = mono_class_from_mono_type (type);
4971                 token = mono_metadata_token_from_dor (
4972                         mono_image_typedef_or_ref_full (assembly, type, mc->generic_container == NULL || create_open_instance));
4973         } else if (strcmp (klass->name, "GenericTypeParameterBuilder") == 0) {
4974                 MonoType *type = mono_reflection_type_get_handle ((MonoReflectionType *)obj);
4975                 token = mono_metadata_token_from_dor (
4976                         mono_image_typedef_or_ref (assembly, type));
4977         } else if (strcmp (klass->name, "MonoGenericClass") == 0) {
4978                 MonoType *type = mono_reflection_type_get_handle ((MonoReflectionType *)obj);
4979                 token = mono_metadata_token_from_dor (
4980                         mono_image_typedef_or_ref (assembly, type));
4981         } else if (strcmp (klass->name, "MonoCMethod") == 0 ||
4982                    strcmp (klass->name, "MonoMethod") == 0 ||
4983                    strcmp (klass->name, "MonoGenericMethod") == 0 ||
4984                    strcmp (klass->name, "MonoGenericCMethod") == 0) {
4985                 MonoReflectionMethod *m = (MonoReflectionMethod *)obj;
4986                 if (m->method->is_inflated) {
4987                         if (create_open_instance)
4988                                 token = mono_image_get_methodspec_token (assembly, m->method);
4989                         else
4990                                 token = mono_image_get_inflated_method_token (assembly, m->method);
4991                 } else if ((m->method->klass->image == &assembly->image) &&
4992                          !m->method->klass->generic_class) {
4993                         static guint32 method_table_idx = 0xffffff;
4994                         if (m->method->klass->wastypebuilder) {
4995                                 /* we use the same token as the one that was assigned
4996                                  * to the Methodbuilder.
4997                                  * FIXME: do the equivalent for Fields.
4998                                  */
4999                                 token = m->method->token;
5000                         } else {
5001                                 /*
5002                                  * Each token should have a unique index, but the indexes are
5003                                  * assigned by managed code, so we don't know about them. An
5004                                  * easy solution is to count backwards...
5005                                  */
5006                                 method_table_idx --;
5007                                 token = MONO_TOKEN_METHOD_DEF | method_table_idx;
5008                         }
5009                 } else {
5010                         token = mono_image_get_methodref_token (assembly, m->method, create_open_instance);
5011                 }
5012                 /*g_print ("got token 0x%08x for %s\n", token, m->method->name);*/
5013         } else if (strcmp (klass->name, "MonoField") == 0) {
5014                 MonoReflectionField *f = (MonoReflectionField *)obj;
5015                 if ((f->field->parent->image == &assembly->image) && !is_field_on_inst (f->field)) {
5016                         static guint32 field_table_idx = 0xffffff;
5017                         field_table_idx --;
5018                         token = MONO_TOKEN_FIELD_DEF | field_table_idx;
5019                 } else {
5020                         token = mono_image_get_fieldref_token (assembly, (MonoObject*)f, f->field);
5021                 }
5022                 /*g_print ("got token 0x%08x for %s\n", token, f->field->name);*/
5023         } else if (strcmp (klass->name, "MonoArrayMethod") == 0) {
5024                 MonoReflectionArrayMethod *m = (MonoReflectionArrayMethod *)obj;
5025                 token = mono_image_get_array_token (assembly, m);
5026         } else if (strcmp (klass->name, "SignatureHelper") == 0) {
5027                 MonoReflectionSigHelper *s = (MonoReflectionSigHelper*)obj;
5028                 token = MONO_TOKEN_SIGNATURE | mono_image_get_sighelper_token (assembly, s);
5029         } else if (strcmp (klass->name, "EnumBuilder") == 0) {
5030                 MonoType *type = mono_reflection_type_get_handle ((MonoReflectionType *)obj);
5031                 token = mono_metadata_token_from_dor (
5032                         mono_image_typedef_or_ref (assembly, type));
5033         } else if (strcmp (klass->name, "FieldOnTypeBuilderInst") == 0) {
5034                 MonoReflectionFieldOnTypeBuilderInst *f = (MonoReflectionFieldOnTypeBuilderInst*)obj;
5035                 token = mono_image_get_field_on_inst_token (assembly, f);
5036         } else if (strcmp (klass->name, "ConstructorOnTypeBuilderInst") == 0) {
5037                 MonoReflectionCtorOnTypeBuilderInst *c = (MonoReflectionCtorOnTypeBuilderInst*)obj;
5038                 token = mono_image_get_ctor_on_inst_token (assembly, c, create_open_instance);
5039         } else if (strcmp (klass->name, "MethodOnTypeBuilderInst") == 0) {
5040                 MonoReflectionMethodOnTypeBuilderInst *m = (MonoReflectionMethodOnTypeBuilderInst*)obj;
5041                 token = mono_image_get_method_on_inst_token (assembly, m, create_open_instance);
5042         } else if (is_sre_array (klass) || is_sre_byref (klass) || is_sre_pointer (klass)) {
5043                 MonoReflectionType *type = (MonoReflectionType *)obj;
5044                 token = mono_metadata_token_from_dor (
5045                                 mono_image_typedef_or_ref (assembly, mono_reflection_type_get_handle (type)));
5046         } else {
5047                 g_error ("requested token for %s\n", klass->name);
5048         }
5049
5050         if (register_token)
5051                 mono_image_register_token (assembly, token, obj);
5052
5053         return token;
5054 }
5055
5056 /*
5057  * mono_image_register_token:
5058  *
5059  *   Register the TOKEN->OBJ mapping in the mapping table in ASSEMBLY. This is required for
5060  * the Module.ResolveXXXToken () methods to work.
5061  */
5062 void
5063 mono_image_register_token (MonoDynamicImage *assembly, guint32 token, MonoObject *obj)
5064 {
5065         MonoObject *prev = mono_g_hash_table_lookup (assembly->tokens, GUINT_TO_POINTER (token));
5066         if (prev) {
5067                 /* There could be multiple MethodInfo objects with the same token */
5068                 //g_assert (prev == obj);
5069         } else {
5070                 mono_g_hash_table_insert (assembly->tokens, GUINT_TO_POINTER (token), obj);
5071         }
5072 }
5073
5074 static MonoDynamicImage*
5075 create_dynamic_mono_image (MonoDynamicAssembly *assembly, char *assembly_name, char *module_name)
5076 {
5077         static const guchar entrycode [16] = {0xff, 0x25, 0};
5078         MonoDynamicImage *image;
5079         int i;
5080
5081         const char *version;
5082
5083         if (!strcmp (mono_get_runtime_info ()->framework_version, "2.1"))
5084                 version = "v2.0.50727"; /* HACK: SL 2 enforces the .net 2 metadata version */
5085         else
5086                 version = mono_get_runtime_info ()->runtime_version;
5087
5088 #if HAVE_BOEHM_GC
5089         /* The MonoGHashTable's need GC tracking */
5090         image = GC_MALLOC (sizeof (MonoDynamicImage));
5091 #else
5092         image = g_new0 (MonoDynamicImage, 1);
5093 #endif
5094         
5095         mono_profiler_module_event (&image->image, MONO_PROFILE_START_LOAD);
5096         
5097         /*g_print ("created image %p\n", image);*/
5098         /* keep in sync with image.c */
5099         image->image.name = assembly_name;
5100         image->image.assembly_name = image->image.name; /* they may be different */
5101         image->image.module_name = module_name;
5102         image->image.version = g_strdup (version);
5103         image->image.md_version_major = 1;
5104         image->image.md_version_minor = 1;
5105         image->image.dynamic = TRUE;
5106
5107         image->image.references = g_new0 (MonoAssembly*, 1);
5108         image->image.references [0] = NULL;
5109
5110         mono_image_init (&image->image);
5111
5112         image->token_fixups = mono_g_hash_table_new_type ((GHashFunc)mono_object_hash, NULL, MONO_HASH_KEY_GC);
5113         image->method_to_table_idx = g_hash_table_new (NULL, NULL);
5114         image->field_to_table_idx = g_hash_table_new (NULL, NULL);
5115         image->method_aux_hash = g_hash_table_new (NULL, NULL);
5116         image->vararg_aux_hash = g_hash_table_new (NULL, NULL);
5117         image->handleref = g_hash_table_new (NULL, NULL);
5118         image->handleref_managed = mono_g_hash_table_new_type ((GHashFunc)mono_object_hash, NULL, MONO_HASH_KEY_GC);
5119         image->tokens = mono_g_hash_table_new_type (NULL, NULL, MONO_HASH_VALUE_GC);
5120         image->generic_def_objects = mono_g_hash_table_new_type (NULL, NULL, MONO_HASH_VALUE_GC);
5121         image->methodspec = mono_g_hash_table_new_type ((GHashFunc)mono_object_hash, NULL, MONO_HASH_KEY_GC);
5122         image->typespec = g_hash_table_new ((GHashFunc)mono_metadata_type_hash, (GCompareFunc)mono_metadata_type_equal);
5123         image->typeref = g_hash_table_new ((GHashFunc)mono_metadata_type_hash, (GCompareFunc)mono_metadata_type_equal);
5124         image->blob_cache = g_hash_table_new ((GHashFunc)mono_blob_entry_hash, (GCompareFunc)mono_blob_entry_equal);
5125         image->gen_params = g_ptr_array_new ();
5126         image->remapped_tokens = mono_g_hash_table_new_type (NULL, NULL, MONO_HASH_VALUE_GC);
5127
5128         /*g_print ("string heap create for image %p (%s)\n", image, module_name);*/
5129         string_heap_init (&image->sheap);
5130         mono_image_add_stream_data (&image->us, "", 1);
5131         add_to_blob_cached (image, (char*) "", 1, NULL, 0);
5132         /* import tables... */
5133         mono_image_add_stream_data (&image->code, (char*)entrycode, sizeof (entrycode));
5134         image->iat_offset = mono_image_add_stream_zero (&image->code, 8); /* two IAT entries */
5135         image->idt_offset = mono_image_add_stream_zero (&image->code, 2 * sizeof (MonoIDT)); /* two IDT entries */
5136         image->imp_names_offset = mono_image_add_stream_zero (&image->code, 2); /* flags for name entry */
5137         mono_image_add_stream_data (&image->code, "_CorExeMain", 12);
5138         mono_image_add_stream_data (&image->code, "mscoree.dll", 12);
5139         image->ilt_offset = mono_image_add_stream_zero (&image->code, 8); /* two ILT entries */
5140         stream_data_align (&image->code);
5141
5142         image->cli_header_offset = mono_image_add_stream_zero (&image->code, sizeof (MonoCLIHeader));
5143
5144         for (i=0; i < MONO_TABLE_NUM; ++i) {
5145                 image->tables [i].next_idx = 1;
5146                 image->tables [i].columns = table_sizes [i];
5147         }
5148
5149         image->image.assembly = (MonoAssembly*)assembly;
5150         image->run = assembly->run;
5151         image->save = assembly->save;
5152         image->pe_kind = 0x1; /* ILOnly */
5153         image->machine = 0x14c; /* I386 */
5154         
5155         mono_profiler_module_loaded (&image->image, MONO_PROFILE_OK);
5156
5157         return image;
5158 }
5159 #endif
5160
5161 static void
5162 free_blob_cache_entry (gpointer key, gpointer val, gpointer user_data)
5163 {
5164         g_free (key);
5165 }
5166
5167 static void
5168 release_hashtable (MonoGHashTable **hash)
5169 {
5170         if (*hash) {
5171                 mono_g_hash_table_destroy (*hash);
5172                 *hash = NULL;
5173         }
5174 }
5175
5176 void
5177 mono_dynamic_image_release_gc_roots (MonoDynamicImage *image)
5178 {
5179         release_hashtable (&image->token_fixups);
5180         release_hashtable (&image->handleref_managed);
5181         release_hashtable (&image->tokens);
5182         release_hashtable (&image->remapped_tokens);
5183         release_hashtable (&image->generic_def_objects);
5184         release_hashtable (&image->methodspec);
5185 }
5186
5187 void
5188 mono_dynamic_image_free (MonoDynamicImage *image)
5189 {
5190         MonoDynamicImage *di = image;
5191         GList *list;
5192         int i;
5193
5194         if (di->methodspec)
5195                 mono_g_hash_table_destroy (di->methodspec);
5196         if (di->typespec)
5197                 g_hash_table_destroy (di->typespec);
5198         if (di->typeref)
5199                 g_hash_table_destroy (di->typeref);
5200         if (di->handleref)
5201                 g_hash_table_destroy (di->handleref);
5202         if (di->handleref_managed)
5203                 mono_g_hash_table_destroy (di->handleref_managed);
5204         if (di->tokens)
5205                 mono_g_hash_table_destroy (di->tokens);
5206         if (di->remapped_tokens)
5207                 mono_g_hash_table_destroy (di->remapped_tokens);
5208         if (di->generic_def_objects)
5209                 mono_g_hash_table_destroy (di->generic_def_objects);
5210         if (di->blob_cache) {
5211                 g_hash_table_foreach (di->blob_cache, free_blob_cache_entry, NULL);
5212                 g_hash_table_destroy (di->blob_cache);
5213         }
5214         if (di->standalonesig_cache)
5215                 g_hash_table_destroy (di->standalonesig_cache);
5216         for (list = di->array_methods; list; list = list->next) {
5217                 ArrayMethod *am = (ArrayMethod *)list->data;
5218                 g_free (am->sig);
5219                 g_free (am->name);
5220                 g_free (am);
5221         }
5222         g_list_free (di->array_methods);
5223         if (di->gen_params) {
5224                 for (i = 0; i < di->gen_params->len; i++) {
5225                         GenericParamTableEntry *entry = g_ptr_array_index (di->gen_params, i);
5226                         mono_gc_deregister_root ((char*) &entry->gparam);
5227                         g_free (entry);
5228                 }
5229                 g_ptr_array_free (di->gen_params, TRUE);
5230         }
5231         if (di->token_fixups)
5232                 mono_g_hash_table_destroy (di->token_fixups);
5233         if (di->method_to_table_idx)
5234                 g_hash_table_destroy (di->method_to_table_idx);
5235         if (di->field_to_table_idx)
5236                 g_hash_table_destroy (di->field_to_table_idx);
5237         if (di->method_aux_hash)
5238                 g_hash_table_destroy (di->method_aux_hash);
5239         if (di->vararg_aux_hash)
5240                 g_hash_table_destroy (di->vararg_aux_hash);
5241         g_free (di->strong_name);
5242         g_free (di->win32_res);
5243         if (di->public_key)
5244                 g_free (di->public_key);
5245
5246         /*g_print ("string heap destroy for image %p\n", di);*/
5247         mono_dynamic_stream_reset (&di->sheap);
5248         mono_dynamic_stream_reset (&di->code);
5249         mono_dynamic_stream_reset (&di->resources);
5250         mono_dynamic_stream_reset (&di->us);
5251         mono_dynamic_stream_reset (&di->blob);
5252         mono_dynamic_stream_reset (&di->tstream);
5253         mono_dynamic_stream_reset (&di->guid);
5254         for (i = 0; i < MONO_TABLE_NUM; ++i) {
5255                 g_free (di->tables [i].values);
5256         }
5257 }       
5258
5259 #ifndef DISABLE_REFLECTION_EMIT
5260
5261 /*
5262  * mono_image_basic_init:
5263  * @assembly: an assembly builder object
5264  *
5265  * Create the MonoImage that represents the assembly builder and setup some
5266  * of the helper hash table and the basic metadata streams.
5267  */
5268 void
5269 mono_image_basic_init (MonoReflectionAssemblyBuilder *assemblyb)
5270 {
5271         MonoDynamicAssembly *assembly;
5272         MonoDynamicImage *image;
5273         MonoDomain *domain = mono_object_domain (assemblyb);
5274         
5275         MONO_ARCH_SAVE_REGS;
5276
5277         if (assemblyb->dynamic_assembly)
5278                 return;
5279
5280 #if HAVE_BOEHM_GC
5281         /* assembly->assembly.image might be GC allocated */
5282         assembly = assemblyb->dynamic_assembly = GC_MALLOC (sizeof (MonoDynamicAssembly));
5283 #else
5284         assembly = assemblyb->dynamic_assembly = g_new0 (MonoDynamicAssembly, 1);
5285 #endif
5286
5287         mono_profiler_assembly_event (&assembly->assembly, MONO_PROFILE_START_LOAD);
5288         
5289         assembly->assembly.ref_count = 1;
5290         assembly->assembly.dynamic = TRUE;
5291         assembly->assembly.corlib_internal = assemblyb->corlib_internal;
5292         assemblyb->assembly.assembly = (MonoAssembly*)assembly;
5293         assembly->assembly.basedir = mono_string_to_utf8 (assemblyb->dir);
5294         if (assemblyb->culture)
5295                 assembly->assembly.aname.culture = mono_string_to_utf8 (assemblyb->culture);
5296         else
5297                 assembly->assembly.aname.culture = g_strdup ("");
5298
5299         if (assemblyb->version) {
5300                         char *vstr = mono_string_to_utf8 (assemblyb->version);
5301                         char **version = g_strsplit (vstr, ".", 4);
5302                         char **parts = version;
5303                         assembly->assembly.aname.major = atoi (*parts++);
5304                         assembly->assembly.aname.minor = atoi (*parts++);
5305                         assembly->assembly.aname.build = *parts != NULL ? atoi (*parts++) : 0;
5306                         assembly->assembly.aname.revision = *parts != NULL ? atoi (*parts) : 0;
5307
5308                         g_strfreev (version);
5309                         g_free (vstr);
5310         } else {
5311                         assembly->assembly.aname.major = 0;
5312                         assembly->assembly.aname.minor = 0;
5313                         assembly->assembly.aname.build = 0;
5314                         assembly->assembly.aname.revision = 0;
5315         }
5316
5317         assembly->run = assemblyb->access != 2;
5318         assembly->save = assemblyb->access != 1;
5319         assembly->domain = domain;
5320
5321         image = create_dynamic_mono_image (assembly, mono_string_to_utf8 (assemblyb->name), g_strdup ("RefEmit_YouForgotToDefineAModule"));
5322         image->initial_image = TRUE;
5323         assembly->assembly.aname.name = image->image.name;
5324         assembly->assembly.image = &image->image;
5325         if (assemblyb->pktoken && assemblyb->pktoken->max_length) {
5326                 /* -1 to correct for the trailing NULL byte */
5327                 if (assemblyb->pktoken->max_length != MONO_PUBLIC_KEY_TOKEN_LENGTH - 1) {
5328                         g_error ("Public key token length invalid for assembly %s: %i", assembly->assembly.aname.name, assemblyb->pktoken->max_length);
5329                 }
5330                 memcpy (&assembly->assembly.aname.public_key_token, mono_array_addr (assemblyb->pktoken, guint8, 0), assemblyb->pktoken->max_length);           
5331         }
5332
5333         mono_domain_assemblies_lock (domain);
5334         domain->domain_assemblies = g_slist_append (domain->domain_assemblies, assembly);
5335         mono_domain_assemblies_unlock (domain);
5336
5337         register_assembly (mono_object_domain (assemblyb), &assemblyb->assembly, &assembly->assembly);
5338         
5339         mono_profiler_assembly_loaded (&assembly->assembly, MONO_PROFILE_OK);
5340         
5341         mono_assembly_invoke_load_hook ((MonoAssembly*)assembly);
5342 }
5343
5344 #endif /* !DISABLE_REFLECTION_EMIT */
5345
5346 #ifndef DISABLE_REFLECTION_EMIT_SAVE
5347
5348 static int
5349 calc_section_size (MonoDynamicImage *assembly)
5350 {
5351         int nsections = 0;
5352
5353         /* alignment constraints */
5354         mono_image_add_stream_zero (&assembly->code, 4 - (assembly->code.index % 4));
5355         g_assert ((assembly->code.index % 4) == 0);
5356         assembly->meta_size += 3;
5357         assembly->meta_size &= ~3;
5358         mono_image_add_stream_zero (&assembly->resources, 4 - (assembly->resources.index % 4));
5359         g_assert ((assembly->resources.index % 4) == 0);
5360
5361         assembly->sections [MONO_SECTION_TEXT].size = assembly->meta_size + assembly->code.index + assembly->resources.index + assembly->strong_name_size;
5362         assembly->sections [MONO_SECTION_TEXT].attrs = SECT_FLAGS_HAS_CODE | SECT_FLAGS_MEM_EXECUTE | SECT_FLAGS_MEM_READ;
5363         nsections++;
5364
5365         if (assembly->win32_res) {
5366                 guint32 res_size = (assembly->win32_res_size + 3) & ~3;
5367
5368                 assembly->sections [MONO_SECTION_RSRC].size = res_size;
5369                 assembly->sections [MONO_SECTION_RSRC].attrs = SECT_FLAGS_HAS_INITIALIZED_DATA | SECT_FLAGS_MEM_READ;
5370                 nsections++;
5371         }
5372
5373         assembly->sections [MONO_SECTION_RELOC].size = 12;
5374         assembly->sections [MONO_SECTION_RELOC].attrs = SECT_FLAGS_MEM_READ | SECT_FLAGS_MEM_DISCARDABLE | SECT_FLAGS_HAS_INITIALIZED_DATA;
5375         nsections++;
5376
5377         return nsections;
5378 }
5379
5380 typedef struct {
5381         guint32 id;
5382         guint32 offset;
5383         GSList *children;
5384         MonoReflectionWin32Resource *win32_res; /* Only for leaf nodes */
5385 } ResTreeNode;
5386
5387 static int
5388 resource_tree_compare_by_id (gconstpointer a, gconstpointer b)
5389 {
5390         ResTreeNode *t1 = (ResTreeNode*)a;
5391         ResTreeNode *t2 = (ResTreeNode*)b;
5392
5393         return t1->id - t2->id;
5394 }
5395
5396 /*
5397  * resource_tree_create:
5398  *
5399  *  Organize the resources into a resource tree.
5400  */
5401 static ResTreeNode *
5402 resource_tree_create (MonoArray *win32_resources)
5403 {
5404         ResTreeNode *tree, *res_node, *type_node, *lang_node;
5405         GSList *l;
5406         int i;
5407
5408         tree = g_new0 (ResTreeNode, 1);
5409         
5410         for (i = 0; i < mono_array_length (win32_resources); ++i) {
5411                 MonoReflectionWin32Resource *win32_res =
5412                         (MonoReflectionWin32Resource*)mono_array_addr (win32_resources, MonoReflectionWin32Resource, i);
5413
5414                 /* Create node */
5415
5416                 /* FIXME: BUG: this stores managed references in unmanaged memory */
5417                 lang_node = g_new0 (ResTreeNode, 1);
5418                 lang_node->id = win32_res->lang_id;
5419                 lang_node->win32_res = win32_res;
5420
5421                 /* Create type node if neccesary */
5422                 type_node = NULL;
5423                 for (l = tree->children; l; l = l->next)
5424                         if (((ResTreeNode*)(l->data))->id == win32_res->res_type) {
5425                                 type_node = (ResTreeNode*)l->data;
5426                                 break;
5427                         }
5428
5429                 if (!type_node) {
5430                         type_node = g_new0 (ResTreeNode, 1);
5431                         type_node->id = win32_res->res_type;
5432
5433                         /* 
5434                          * The resource types have to be sorted otherwise
5435                          * Windows Explorer can't display the version information.
5436                          */
5437                         tree->children = g_slist_insert_sorted (tree->children, 
5438                                 type_node, resource_tree_compare_by_id);
5439                 }
5440
5441                 /* Create res node if neccesary */
5442                 res_node = NULL;
5443                 for (l = type_node->children; l; l = l->next)
5444                         if (((ResTreeNode*)(l->data))->id == win32_res->res_id) {
5445                                 res_node = (ResTreeNode*)l->data;
5446                                 break;
5447                         }
5448
5449                 if (!res_node) {
5450                         res_node = g_new0 (ResTreeNode, 1);
5451                         res_node->id = win32_res->res_id;
5452                         type_node->children = g_slist_append (type_node->children, res_node);
5453                 }
5454
5455                 res_node->children = g_slist_append (res_node->children, lang_node);
5456         }
5457
5458         return tree;
5459 }
5460
5461 /*
5462  * resource_tree_encode:
5463  * 
5464  *   Encode the resource tree into the format used in the PE file.
5465  */
5466 static void
5467 resource_tree_encode (ResTreeNode *node, char *begin, char *p, char **endbuf)
5468 {
5469         char *entries;
5470         MonoPEResourceDir dir;
5471         MonoPEResourceDirEntry dir_entry;
5472         MonoPEResourceDataEntry data_entry;
5473         GSList *l;
5474         guint32 res_id_entries;
5475
5476         /*
5477          * For the format of the resource directory, see the article
5478          * "An In-Depth Look into the Win32 Portable Executable File Format" by
5479          * Matt Pietrek
5480          */
5481
5482         memset (&dir, 0, sizeof (dir));
5483         memset (&dir_entry, 0, sizeof (dir_entry));
5484         memset (&data_entry, 0, sizeof (data_entry));
5485
5486         g_assert (sizeof (dir) == 16);
5487         g_assert (sizeof (dir_entry) == 8);
5488         g_assert (sizeof (data_entry) == 16);
5489
5490         node->offset = p - begin;
5491
5492         /* IMAGE_RESOURCE_DIRECTORY */
5493         res_id_entries = g_slist_length (node->children);
5494         dir.res_id_entries = GUINT16_TO_LE (res_id_entries);
5495
5496         memcpy (p, &dir, sizeof (dir));
5497         p += sizeof (dir);
5498
5499         /* Reserve space for entries */
5500         entries = p;
5501         p += sizeof (dir_entry) * res_id_entries;
5502
5503         /* Write children */
5504         for (l = node->children; l; l = l->next) {
5505                 ResTreeNode *child = (ResTreeNode*)l->data;
5506
5507                 if (child->win32_res) {
5508                         guint32 size;
5509
5510                         child->offset = p - begin;
5511
5512                         /* IMAGE_RESOURCE_DATA_ENTRY */
5513                         data_entry.rde_data_offset = GUINT32_TO_LE (p - begin + sizeof (data_entry));
5514                         size = mono_array_length (child->win32_res->res_data);
5515                         data_entry.rde_size = GUINT32_TO_LE (size);
5516
5517                         memcpy (p, &data_entry, sizeof (data_entry));
5518                         p += sizeof (data_entry);
5519
5520                         memcpy (p, mono_array_addr (child->win32_res->res_data, char, 0), size);
5521                         p += size;
5522                 } else {
5523                         resource_tree_encode (child, begin, p, &p);
5524                 }
5525         }
5526
5527         /* IMAGE_RESOURCE_ENTRY */
5528         for (l = node->children; l; l = l->next) {
5529                 ResTreeNode *child = (ResTreeNode*)l->data;
5530
5531                 MONO_PE_RES_DIR_ENTRY_SET_NAME (dir_entry, FALSE, child->id);
5532                 MONO_PE_RES_DIR_ENTRY_SET_DIR (dir_entry, !child->win32_res, child->offset);
5533
5534                 memcpy (entries, &dir_entry, sizeof (dir_entry));
5535                 entries += sizeof (dir_entry);
5536         }
5537
5538         *endbuf = p;
5539 }
5540
5541 static void
5542 resource_tree_free (ResTreeNode * node)
5543 {
5544         GSList * list;
5545         for (list = node->children; list; list = list->next)
5546                 resource_tree_free ((ResTreeNode*)list->data);
5547         g_slist_free(node->children);
5548         g_free (node);
5549 }
5550
5551 static void
5552 assembly_add_win32_resources (MonoDynamicImage *assembly, MonoReflectionAssemblyBuilder *assemblyb)
5553 {
5554         char *buf;
5555         char *p;
5556         guint32 size, i;
5557         MonoReflectionWin32Resource *win32_res;
5558         ResTreeNode *tree;
5559
5560         if (!assemblyb->win32_resources)
5561                 return;
5562
5563         /*
5564          * Resources are stored in a three level tree inside the PE file.
5565          * - level one contains a node for each type of resource
5566          * - level two contains a node for each resource
5567          * - level three contains a node for each instance of a resource for a
5568          *   specific language.
5569          */
5570
5571         tree = resource_tree_create (assemblyb->win32_resources);
5572
5573         /* Estimate the size of the encoded tree */
5574         size = 0;
5575         for (i = 0; i < mono_array_length (assemblyb->win32_resources); ++i) {
5576                 win32_res = (MonoReflectionWin32Resource*)mono_array_addr (assemblyb->win32_resources, MonoReflectionWin32Resource, i);
5577                 size += mono_array_length (win32_res->res_data);
5578         }
5579         /* Directory structure */
5580         size += mono_array_length (assemblyb->win32_resources) * 256;
5581         p = buf = g_malloc (size);
5582
5583         resource_tree_encode (tree, p, p, &p);
5584
5585         g_assert (p - buf <= size);
5586
5587         assembly->win32_res = g_malloc (p - buf);
5588         assembly->win32_res_size = p - buf;
5589         memcpy (assembly->win32_res, buf, p - buf);
5590
5591         g_free (buf);
5592         resource_tree_free (tree);
5593 }
5594
5595 static void
5596 fixup_resource_directory (char *res_section, char *p, guint32 rva)
5597 {
5598         MonoPEResourceDir *dir = (MonoPEResourceDir*)p;
5599         int i;
5600
5601         p += sizeof (MonoPEResourceDir);
5602         for (i = 0; i < GUINT16_FROM_LE (dir->res_named_entries) + GUINT16_FROM_LE (dir->res_id_entries); ++i) {
5603                 MonoPEResourceDirEntry *dir_entry = (MonoPEResourceDirEntry*)p;
5604                 char *child = res_section + MONO_PE_RES_DIR_ENTRY_DIR_OFFSET (*dir_entry);
5605                 if (MONO_PE_RES_DIR_ENTRY_IS_DIR (*dir_entry)) {
5606                         fixup_resource_directory (res_section, child, rva);
5607                 } else {
5608                         MonoPEResourceDataEntry *data_entry = (MonoPEResourceDataEntry*)child;
5609                         data_entry->rde_data_offset = GUINT32_TO_LE (GUINT32_FROM_LE (data_entry->rde_data_offset) + rva);
5610                 }
5611
5612                 p += sizeof (MonoPEResourceDirEntry);
5613         }
5614 }
5615
5616 static void
5617 checked_write_file (HANDLE f, gconstpointer buffer, guint32 numbytes)
5618 {
5619         guint32 dummy;
5620         if (!WriteFile (f, buffer, numbytes, &dummy, NULL))
5621                 g_error ("WriteFile returned %d\n", GetLastError ());
5622 }
5623
5624 /*
5625  * mono_image_create_pefile:
5626  * @mb: a module builder object
5627  * 
5628  * This function creates the PE-COFF header, the image sections, the CLI header  * etc. all the data is written in
5629  * assembly->pefile where it can be easily retrieved later in chunks.
5630  */
5631 void
5632 mono_image_create_pefile (MonoReflectionModuleBuilder *mb, HANDLE file)
5633 {
5634         MonoMSDOSHeader *msdos;
5635         MonoDotNetHeader *header;
5636         MonoSectionTable *section;
5637         MonoCLIHeader *cli_header;
5638         guint32 size, image_size, virtual_base, text_offset;
5639         guint32 header_start, section_start, file_offset, virtual_offset;
5640         MonoDynamicImage *assembly;
5641         MonoReflectionAssemblyBuilder *assemblyb;
5642         MonoDynamicStream pefile_stream = {0};
5643         MonoDynamicStream *pefile = &pefile_stream;
5644         int i, nsections;
5645         guint32 *rva, value;
5646         guchar *p;
5647         static const unsigned char msheader[] = {
5648                 0x4d, 0x5a, 0x90, 0x00, 0x03, 0x00, 0x00, 0x00,  0x04, 0x00, 0x00, 0x00, 0xff, 0xff, 0x00, 0x00,
5649                 0xb8, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,  0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
5650                 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
5651                 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,  0x00, 0x00, 0x00, 0x00, 0x80, 0x00, 0x00, 0x00,
5652                 0x0e, 0x1f, 0xba, 0x0e, 0x00, 0xb4, 0x09, 0xcd,  0x21, 0xb8, 0x01, 0x4c, 0xcd, 0x21, 0x54, 0x68,
5653                 0x69, 0x73, 0x20, 0x70, 0x72, 0x6f, 0x67, 0x72,  0x61, 0x6d, 0x20, 0x63, 0x61, 0x6e, 0x6e, 0x6f,
5654                 0x74, 0x20, 0x62, 0x65, 0x20, 0x72, 0x75, 0x6e,  0x20, 0x69, 0x6e, 0x20, 0x44, 0x4f, 0x53, 0x20,
5655                 0x6d, 0x6f, 0x64, 0x65, 0x2e, 0x0d, 0x0d, 0x0a,  0x24, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
5656         };
5657
5658         assemblyb = mb->assemblyb;
5659
5660         mono_image_basic_init (assemblyb);
5661         assembly = mb->dynamic_image;
5662
5663         assembly->pe_kind = assemblyb->pe_kind;
5664         assembly->machine = assemblyb->machine;
5665         ((MonoDynamicImage*)assemblyb->dynamic_assembly->assembly.image)->pe_kind = assemblyb->pe_kind;
5666         ((MonoDynamicImage*)assemblyb->dynamic_assembly->assembly.image)->machine = assemblyb->machine;
5667         
5668         mono_image_build_metadata (mb);
5669
5670         if (mb->is_main && assemblyb->resources) {
5671                 int len = mono_array_length (assemblyb->resources);
5672                 for (i = 0; i < len; ++i)
5673                         assembly_add_resource (mb, assembly, (MonoReflectionResource*)mono_array_addr (assemblyb->resources, MonoReflectionResource, i));
5674         }
5675
5676         if (mb->resources) {
5677                 int len = mono_array_length (mb->resources);
5678                 for (i = 0; i < len; ++i)
5679                         assembly_add_resource (mb, assembly, (MonoReflectionResource*)mono_array_addr (mb->resources, MonoReflectionResource, i));
5680         }
5681
5682         build_compressed_metadata (assembly);
5683
5684         if (mb->is_main)
5685                 assembly_add_win32_resources (assembly, assemblyb);
5686
5687         nsections = calc_section_size (assembly);
5688         
5689         /* The DOS header and stub */
5690         g_assert (sizeof (MonoMSDOSHeader) == sizeof (msheader));
5691         mono_image_add_stream_data (pefile, (char*)msheader, sizeof (msheader));
5692
5693         /* the dotnet header */
5694         header_start = mono_image_add_stream_zero (pefile, sizeof (MonoDotNetHeader));
5695
5696         /* the section tables */
5697         section_start = mono_image_add_stream_zero (pefile, sizeof (MonoSectionTable) * nsections);
5698
5699         file_offset = section_start + sizeof (MonoSectionTable) * nsections;
5700         virtual_offset = VIRT_ALIGN;
5701         image_size = 0;
5702
5703         for (i = 0; i < MONO_SECTION_MAX; ++i) {
5704                 if (!assembly->sections [i].size)
5705                         continue;
5706                 /* align offsets */
5707                 file_offset += FILE_ALIGN - 1;
5708                 file_offset &= ~(FILE_ALIGN - 1);
5709                 virtual_offset += VIRT_ALIGN - 1;
5710                 virtual_offset &= ~(VIRT_ALIGN - 1);
5711
5712                 assembly->sections [i].offset = file_offset;
5713                 assembly->sections [i].rva = virtual_offset;
5714
5715                 file_offset += assembly->sections [i].size;
5716                 virtual_offset += assembly->sections [i].size;
5717                 image_size += (assembly->sections [i].size + VIRT_ALIGN - 1) & ~(VIRT_ALIGN - 1);
5718         }
5719
5720         file_offset += FILE_ALIGN - 1;
5721         file_offset &= ~(FILE_ALIGN - 1);
5722
5723         image_size += section_start + sizeof (MonoSectionTable) * nsections;
5724
5725         /* back-patch info */
5726         msdos = (MonoMSDOSHeader*)pefile->data;
5727         msdos->pe_offset = GUINT32_FROM_LE (sizeof (MonoMSDOSHeader));
5728
5729         header = (MonoDotNetHeader*)(pefile->data + header_start);
5730         header->pesig [0] = 'P';
5731         header->pesig [1] = 'E';
5732         
5733         header->coff.coff_machine = GUINT16_FROM_LE (assemblyb->machine);
5734         header->coff.coff_sections = GUINT16_FROM_LE (nsections);
5735         header->coff.coff_time = GUINT32_FROM_LE (time (NULL));
5736         header->coff.coff_opt_header_size = GUINT16_FROM_LE (sizeof (MonoDotNetHeader) - sizeof (MonoCOFFHeader) - 4);
5737         if (assemblyb->pekind == 1) {
5738                 /* it's a dll */
5739                 header->coff.coff_attributes = GUINT16_FROM_LE (0x210e);
5740         } else {
5741                 /* it's an exe */
5742                 header->coff.coff_attributes = GUINT16_FROM_LE (0x010e);
5743         }
5744
5745         virtual_base = 0x400000; /* FIXME: 0x10000000 if a DLL */
5746
5747         header->pe.pe_magic = GUINT16_FROM_LE (0x10B);
5748         header->pe.pe_major = 6;
5749         header->pe.pe_minor = 0;
5750         size = assembly->sections [MONO_SECTION_TEXT].size;
5751         size += FILE_ALIGN - 1;
5752         size &= ~(FILE_ALIGN - 1);
5753         header->pe.pe_code_size = GUINT32_FROM_LE(size);
5754         size = assembly->sections [MONO_SECTION_RSRC].size;
5755         size += FILE_ALIGN - 1;
5756         size &= ~(FILE_ALIGN - 1);
5757         header->pe.pe_data_size = GUINT32_FROM_LE(size);
5758         g_assert (START_TEXT_RVA == assembly->sections [MONO_SECTION_TEXT].rva);
5759         header->pe.pe_rva_code_base = GUINT32_FROM_LE (assembly->sections [MONO_SECTION_TEXT].rva);
5760         header->pe.pe_rva_data_base = GUINT32_FROM_LE (assembly->sections [MONO_SECTION_RSRC].rva);
5761         /* pe_rva_entry_point always at the beginning of the text section */
5762         header->pe.pe_rva_entry_point = GUINT32_FROM_LE (assembly->sections [MONO_SECTION_TEXT].rva);
5763
5764         header->nt.pe_image_base = GUINT32_FROM_LE (virtual_base);
5765         header->nt.pe_section_align = GUINT32_FROM_LE (VIRT_ALIGN);
5766         header->nt.pe_file_alignment = GUINT32_FROM_LE (FILE_ALIGN);
5767         header->nt.pe_os_major = GUINT16_FROM_LE (4);
5768         header->nt.pe_os_minor = GUINT16_FROM_LE (0);
5769         header->nt.pe_subsys_major = GUINT16_FROM_LE (4);
5770         size = section_start;
5771         size += FILE_ALIGN - 1;
5772         size &= ~(FILE_ALIGN - 1);
5773         header->nt.pe_header_size = GUINT32_FROM_LE (size);
5774         size = image_size;
5775         size += VIRT_ALIGN - 1;
5776         size &= ~(VIRT_ALIGN - 1);
5777         header->nt.pe_image_size = GUINT32_FROM_LE (size);
5778
5779         /*
5780         // Translate the PEFileKind value to the value expected by the Windows loader
5781         */
5782         {
5783                 short kind;
5784
5785                 /*
5786                 // PEFileKinds.Dll == 1
5787                 // PEFileKinds.ConsoleApplication == 2
5788                 // PEFileKinds.WindowApplication == 3
5789                 //
5790                 // need to get:
5791                 //     IMAGE_SUBSYSTEM_WINDOWS_GUI 2 // Image runs in the Windows GUI subsystem.
5792                 //     IMAGE_SUBSYSTEM_WINDOWS_CUI 3 // Image runs in the Windows character subsystem.
5793                 */
5794                 if (assemblyb->pekind == 3)
5795                         kind = 2;
5796                 else
5797                         kind = 3;
5798                 
5799                 header->nt.pe_subsys_required = GUINT16_FROM_LE (kind);
5800         }    
5801         header->nt.pe_stack_reserve = GUINT32_FROM_LE (0x00100000);
5802         header->nt.pe_stack_commit = GUINT32_FROM_LE (0x00001000);
5803         header->nt.pe_heap_reserve = GUINT32_FROM_LE (0x00100000);
5804         header->nt.pe_heap_commit = GUINT32_FROM_LE (0x00001000);
5805         header->nt.pe_loader_flags = GUINT32_FROM_LE (0);
5806         header->nt.pe_data_dir_count = GUINT32_FROM_LE (16);
5807
5808         /* fill data directory entries */
5809
5810         header->datadir.pe_resource_table.size = GUINT32_FROM_LE (assembly->sections [MONO_SECTION_RSRC].size);
5811         header->datadir.pe_resource_table.rva = GUINT32_FROM_LE (assembly->sections [MONO_SECTION_RSRC].rva);
5812
5813         header->datadir.pe_reloc_table.size = GUINT32_FROM_LE (assembly->sections [MONO_SECTION_RELOC].size);
5814         header->datadir.pe_reloc_table.rva = GUINT32_FROM_LE (assembly->sections [MONO_SECTION_RELOC].rva);
5815
5816         header->datadir.pe_cli_header.size = GUINT32_FROM_LE (72);
5817         header->datadir.pe_cli_header.rva = GUINT32_FROM_LE (assembly->text_rva + assembly->cli_header_offset);
5818         header->datadir.pe_iat.size = GUINT32_FROM_LE (8);
5819         header->datadir.pe_iat.rva = GUINT32_FROM_LE (assembly->text_rva + assembly->iat_offset);
5820         /* patch entrypoint name */
5821         if (assemblyb->pekind == 1)
5822                 memcpy (assembly->code.data + assembly->imp_names_offset + 2, "_CorDllMain", 12);
5823         else
5824                 memcpy (assembly->code.data + assembly->imp_names_offset + 2, "_CorExeMain", 12);
5825         /* patch imported function RVA name */
5826         rva = (guint32*)(assembly->code.data + assembly->iat_offset);
5827         *rva = GUINT32_FROM_LE (assembly->text_rva + assembly->imp_names_offset);
5828
5829         /* the import table */
5830         header->datadir.pe_import_table.size = GUINT32_FROM_LE (79); /* FIXME: magic number? */
5831         header->datadir.pe_import_table.rva = GUINT32_FROM_LE (assembly->text_rva + assembly->idt_offset);
5832         /* patch imported dll RVA name and other entries in the dir */
5833         rva = (guint32*)(assembly->code.data + assembly->idt_offset + G_STRUCT_OFFSET (MonoIDT, name_rva));
5834         *rva = GUINT32_FROM_LE (assembly->text_rva + assembly->imp_names_offset + 14); /* 14 is hint+strlen+1 of func name */
5835         rva = (guint32*)(assembly->code.data + assembly->idt_offset + G_STRUCT_OFFSET (MonoIDT, import_address_table_rva));
5836         *rva = GUINT32_FROM_LE (assembly->text_rva + assembly->iat_offset);
5837         rva = (guint32*)(assembly->code.data + assembly->idt_offset + G_STRUCT_OFFSET (MonoIDT, import_lookup_table));
5838         *rva = GUINT32_FROM_LE (assembly->text_rva + assembly->ilt_offset);
5839
5840         p = (guchar*)(assembly->code.data + assembly->ilt_offset);
5841         value = (assembly->text_rva + assembly->imp_names_offset);
5842         *p++ = (value) & 0xff;
5843         *p++ = (value >> 8) & (0xff);
5844         *p++ = (value >> 16) & (0xff);
5845         *p++ = (value >> 24) & (0xff);
5846
5847         /* the CLI header info */
5848         cli_header = (MonoCLIHeader*)(assembly->code.data + assembly->cli_header_offset);
5849         cli_header->ch_size = GUINT32_FROM_LE (72);
5850         cli_header->ch_runtime_major = GUINT16_FROM_LE (2);
5851         cli_header->ch_runtime_minor = GUINT16_FROM_LE (5);
5852         cli_header->ch_flags = GUINT32_FROM_LE (assemblyb->pe_kind);
5853         if (assemblyb->entry_point) {
5854                 guint32 table_idx = 0;
5855                 if (!strcmp (assemblyb->entry_point->object.vtable->klass->name, "MethodBuilder")) {
5856                         MonoReflectionMethodBuilder *methodb = (MonoReflectionMethodBuilder*)assemblyb->entry_point;
5857                         table_idx = methodb->table_idx;
5858                 } else {
5859                         table_idx = GPOINTER_TO_UINT (g_hash_table_lookup (assembly->method_to_table_idx, assemblyb->entry_point->method));
5860                 }
5861                 cli_header->ch_entry_point = GUINT32_FROM_LE (table_idx | MONO_TOKEN_METHOD_DEF);
5862         } else {
5863                 cli_header->ch_entry_point = GUINT32_FROM_LE (0);
5864         }
5865         /* The embedded managed resources */
5866         text_offset = assembly->text_rva + assembly->code.index;
5867         cli_header->ch_resources.rva = GUINT32_FROM_LE (text_offset);
5868         cli_header->ch_resources.size = GUINT32_FROM_LE (assembly->resources.index);
5869         text_offset += assembly->resources.index;
5870         cli_header->ch_metadata.rva = GUINT32_FROM_LE (text_offset);
5871         cli_header->ch_metadata.size = GUINT32_FROM_LE (assembly->meta_size);
5872         text_offset += assembly->meta_size;
5873         if (assembly->strong_name_size) {
5874                 cli_header->ch_strong_name.rva = GUINT32_FROM_LE (text_offset);
5875                 cli_header->ch_strong_name.size = GUINT32_FROM_LE (assembly->strong_name_size);
5876                 text_offset += assembly->strong_name_size;
5877         }
5878
5879         /* write the section tables and section content */
5880         section = (MonoSectionTable*)(pefile->data + section_start);
5881         for (i = 0; i < MONO_SECTION_MAX; ++i) {
5882                 static const char section_names [][7] = {
5883                         ".text", ".rsrc", ".reloc"
5884                 };
5885                 if (!assembly->sections [i].size)
5886                         continue;
5887                 strcpy (section->st_name, section_names [i]);
5888                 /*g_print ("output section %s (%d), size: %d\n", section->st_name, i, assembly->sections [i].size);*/
5889                 section->st_virtual_address = GUINT32_FROM_LE (assembly->sections [i].rva);
5890                 section->st_virtual_size = GUINT32_FROM_LE (assembly->sections [i].size);
5891                 section->st_raw_data_size = GUINT32_FROM_LE (GUINT32_TO_LE (section->st_virtual_size) + (FILE_ALIGN - 1));
5892                 section->st_raw_data_size &= GUINT32_FROM_LE (~(FILE_ALIGN - 1));
5893                 section->st_raw_data_ptr = GUINT32_FROM_LE (assembly->sections [i].offset);
5894                 section->st_flags = GUINT32_FROM_LE (assembly->sections [i].attrs);
5895                 section ++;
5896         }
5897         
5898         checked_write_file (file, pefile->data, pefile->index);
5899         
5900         mono_dynamic_stream_reset (pefile);
5901         
5902         for (i = 0; i < MONO_SECTION_MAX; ++i) {
5903                 if (!assembly->sections [i].size)
5904                         continue;
5905                 
5906                 if (SetFilePointer (file, assembly->sections [i].offset, NULL, FILE_BEGIN) == INVALID_SET_FILE_POINTER)
5907                         g_error ("SetFilePointer returned %d\n", GetLastError ());
5908                 
5909                 switch (i) {
5910                 case MONO_SECTION_TEXT:
5911                         /* patch entry point */
5912                         p = (guchar*)(assembly->code.data + 2);
5913                         value = (virtual_base + assembly->text_rva + assembly->iat_offset);
5914                         *p++ = (value) & 0xff;
5915                         *p++ = (value >> 8) & 0xff;
5916                         *p++ = (value >> 16) & 0xff;
5917                         *p++ = (value >> 24) & 0xff;
5918                 
5919                         checked_write_file (file, assembly->code.data, assembly->code.index);
5920                         checked_write_file (file, assembly->resources.data, assembly->resources.index);
5921                         checked_write_file (file, assembly->image.raw_metadata, assembly->meta_size);
5922                         checked_write_file (file, assembly->strong_name, assembly->strong_name_size);
5923                                 
5924
5925                         g_free (assembly->image.raw_metadata);
5926                         break;
5927                 case MONO_SECTION_RELOC: {
5928                         struct {
5929                                 guint32 page_rva;
5930                                 guint32 block_size;
5931                                 guint16 type_and_offset;
5932                                 guint16 term;
5933                         } reloc;
5934                         
5935                         g_assert (sizeof (reloc) == 12);
5936                         
5937                         reloc.page_rva = GUINT32_FROM_LE (assembly->text_rva);
5938                         reloc.block_size = GUINT32_FROM_LE (12);
5939                         
5940                         /* 
5941                          * the entrypoint is always at the start of the text section 
5942                          * 3 is IMAGE_REL_BASED_HIGHLOW
5943                          * 2 is patch_size_rva - text_rva
5944                          */
5945                         reloc.type_and_offset = GUINT16_FROM_LE ((3 << 12) + (2));
5946                         reloc.term = 0;
5947                         
5948                         checked_write_file (file, &reloc, sizeof (reloc));
5949                         
5950                         break;
5951                 }
5952                 case MONO_SECTION_RSRC:
5953                         if (assembly->win32_res) {
5954
5955                                 /* Fixup the offsets in the IMAGE_RESOURCE_DATA_ENTRY structures */
5956                                 fixup_resource_directory (assembly->win32_res, assembly->win32_res, assembly->sections [i].rva);
5957                                 checked_write_file (file, assembly->win32_res, assembly->win32_res_size);
5958                         }
5959                         break;
5960                 default:
5961                         g_assert_not_reached ();
5962                 }
5963         }
5964         
5965         /* check that the file is properly padded */
5966         if (SetFilePointer (file, file_offset, NULL, FILE_BEGIN) == INVALID_SET_FILE_POINTER)
5967                 g_error ("SetFilePointer returned %d\n", GetLastError ());
5968         if (! SetEndOfFile (file))
5969                 g_error ("SetEndOfFile returned %d\n", GetLastError ());
5970         
5971         mono_dynamic_stream_reset (&assembly->code);
5972         mono_dynamic_stream_reset (&assembly->us);
5973         mono_dynamic_stream_reset (&assembly->blob);
5974         mono_dynamic_stream_reset (&assembly->guid);
5975         mono_dynamic_stream_reset (&assembly->sheap);
5976
5977         g_hash_table_foreach (assembly->blob_cache, (GHFunc)g_free, NULL);
5978         g_hash_table_destroy (assembly->blob_cache);
5979         assembly->blob_cache = NULL;
5980 }
5981
5982 #else /* DISABLE_REFLECTION_EMIT_SAVE */
5983
5984 void
5985 mono_image_create_pefile (MonoReflectionModuleBuilder *mb, HANDLE file)
5986 {
5987         g_assert_not_reached ();
5988 }
5989
5990 #endif /* DISABLE_REFLECTION_EMIT_SAVE */
5991
5992 #ifndef DISABLE_REFLECTION_EMIT
5993
5994 MonoReflectionModule *
5995 mono_image_load_module_dynamic (MonoReflectionAssemblyBuilder *ab, MonoString *fileName)
5996 {
5997         char *name;
5998         MonoImage *image;
5999         MonoImageOpenStatus status;
6000         MonoDynamicAssembly *assembly;
6001         guint32 module_count;
6002         MonoImage **new_modules;
6003         gboolean *new_modules_loaded;
6004         
6005         name = mono_string_to_utf8 (fileName);
6006
6007         image = mono_image_open (name, &status);
6008         if (!image) {
6009                 MonoException *exc;
6010                 if (status == MONO_IMAGE_ERROR_ERRNO)
6011                         exc = mono_get_exception_file_not_found (fileName);
6012                 else
6013                         exc = mono_get_exception_bad_image_format (name);
6014                 g_free (name);
6015                 mono_raise_exception (exc);
6016         }
6017
6018         g_free (name);
6019
6020         assembly = ab->dynamic_assembly;
6021         image->assembly = (MonoAssembly*)assembly;
6022
6023         module_count = image->assembly->image->module_count;
6024         new_modules = g_new0 (MonoImage *, module_count + 1);
6025         new_modules_loaded = g_new0 (gboolean, module_count + 1);
6026
6027         if (image->assembly->image->modules)
6028                 memcpy (new_modules, image->assembly->image->modules, module_count * sizeof (MonoImage *));
6029         if (image->assembly->image->modules_loaded)
6030                 memcpy (new_modules_loaded, image->assembly->image->modules_loaded, module_count * sizeof (gboolean));
6031         new_modules [module_count] = image;
6032         new_modules_loaded [module_count] = TRUE;
6033         mono_image_addref (image);
6034
6035         g_free (image->assembly->image->modules);
6036         image->assembly->image->modules = new_modules;
6037         image->assembly->image->modules_loaded = new_modules_loaded;
6038         image->assembly->image->module_count ++;
6039
6040         mono_assembly_load_references (image, &status);
6041         if (status) {
6042                 mono_image_close (image);
6043                 mono_raise_exception (mono_get_exception_file_not_found (fileName));
6044         }
6045
6046         return mono_module_get_object (mono_domain_get (), image);
6047 }
6048
6049 #endif /* DISABLE_REFLECTION_EMIT */
6050
6051 /*
6052  * We need to return always the same object for MethodInfo, FieldInfo etc..
6053  * but we need to consider the reflected type.
6054  * type uses a different hash, since it uses custom hash/equal functions.
6055  */
6056
6057 typedef struct {
6058         gpointer item;
6059         MonoClass *refclass;
6060 } ReflectedEntry;
6061
6062 static gboolean
6063 reflected_equal (gconstpointer a, gconstpointer b) {
6064         const ReflectedEntry *ea = a;
6065         const ReflectedEntry *eb = b;
6066
6067         return (ea->item == eb->item) && (ea->refclass == eb->refclass);
6068 }
6069
6070 static guint
6071 reflected_hash (gconstpointer a) {
6072         const ReflectedEntry *ea = a;
6073         return mono_aligned_addr_hash (ea->item);
6074 }
6075
6076 #define CHECK_OBJECT(t,p,k)     \
6077         do {    \
6078                 t _obj; \
6079                 ReflectedEntry e;       \
6080                 e.item = (p);   \
6081                 e.refclass = (k);       \
6082                 mono_domain_lock (domain);      \
6083                 if (!domain->refobject_hash)    \
6084                         domain->refobject_hash = mono_g_hash_table_new_type (reflected_hash, reflected_equal, MONO_HASH_VALUE_GC);      \
6085                 if ((_obj = mono_g_hash_table_lookup (domain->refobject_hash, &e))) {   \
6086                         mono_domain_unlock (domain);    \
6087                         return _obj;    \
6088                 }       \
6089         mono_domain_unlock (domain); \
6090         } while (0)
6091
6092 #ifdef HAVE_BOEHM_GC
6093 /* ReflectedEntry doesn't need to be GC tracked */
6094 #define ALLOC_REFENTRY g_new0 (ReflectedEntry, 1)
6095 #define FREE_REFENTRY(entry) g_free ((entry))
6096 #define REFENTRY_REQUIRES_CLEANUP
6097 #else
6098 #define ALLOC_REFENTRY mono_mempool_alloc (domain->mp, sizeof (ReflectedEntry))
6099 /* FIXME: */
6100 #define FREE_REFENTRY(entry)
6101 #endif
6102
6103 #define CACHE_OBJECT(t,p,o,k)   \
6104         do {    \
6105                 t _obj; \
6106         ReflectedEntry pe; \
6107         pe.item = (p); \
6108         pe.refclass = (k); \
6109         mono_domain_lock (domain); \
6110                 if (!domain->refobject_hash)    \
6111                         domain->refobject_hash = mono_g_hash_table_new_type (reflected_hash, reflected_equal, MONO_HASH_VALUE_GC);      \
6112         _obj = mono_g_hash_table_lookup (domain->refobject_hash, &pe); \
6113         if (!_obj) { \
6114                     ReflectedEntry *e = ALLOC_REFENTRY;         \
6115                     e->item = (p);      \
6116                     e->refclass = (k);  \
6117                     mono_g_hash_table_insert (domain->refobject_hash, e,o);     \
6118             _obj = o; \
6119         } \
6120                 mono_domain_unlock (domain);    \
6121         return _obj; \
6122         } while (0)
6123
6124 static void
6125 clear_cached_object (MonoDomain *domain, gpointer o, MonoClass *klass)
6126 {
6127         mono_domain_lock (domain);
6128         if (domain->refobject_hash) {
6129         ReflectedEntry pe;
6130                 gpointer orig_pe, orig_value;
6131
6132                 pe.item = o;
6133                 pe.refclass = klass;
6134                 if (mono_g_hash_table_lookup_extended (domain->refobject_hash, &pe, &orig_pe, &orig_value)) {
6135                         mono_g_hash_table_remove (domain->refobject_hash, &pe);
6136                         FREE_REFENTRY (orig_pe);
6137                 }
6138         }
6139         mono_domain_unlock (domain);
6140 }
6141
6142 #ifdef REFENTRY_REQUIRES_CLEANUP
6143 static void
6144 cleanup_refobject_hash (gpointer key, gpointer value, gpointer user_data)
6145 {
6146         FREE_REFENTRY (key);
6147 }
6148 #endif
6149
6150 void
6151 mono_reflection_cleanup_domain (MonoDomain *domain)
6152 {
6153         if (domain->refobject_hash) {
6154 /*let's avoid scanning the whole hashtable if not needed*/
6155 #ifdef REFENTRY_REQUIRES_CLEANUP
6156                 mono_g_hash_table_foreach (domain->refobject_hash, cleanup_refobject_hash, NULL);
6157 #endif
6158                 mono_g_hash_table_destroy (domain->refobject_hash);
6159                 domain->refobject_hash = NULL;
6160         }
6161 }
6162
6163 #ifndef DISABLE_REFLECTION_EMIT
6164 static gpointer
6165 register_assembly (MonoDomain *domain, MonoReflectionAssembly *res, MonoAssembly *assembly)
6166 {
6167         CACHE_OBJECT (MonoReflectionAssembly *, assembly, res, NULL);
6168 }
6169
6170 static gpointer
6171 register_module (MonoDomain *domain, MonoReflectionModuleBuilder *res, MonoDynamicImage *module)
6172 {
6173         CACHE_OBJECT (MonoReflectionModuleBuilder *, module, res, NULL);
6174 }
6175
6176 void
6177 mono_image_module_basic_init (MonoReflectionModuleBuilder *moduleb)
6178 {
6179         MonoDynamicImage *image = moduleb->dynamic_image;
6180         MonoReflectionAssemblyBuilder *ab = moduleb->assemblyb;
6181         if (!image) {
6182                 MonoError error;
6183                 int module_count;
6184                 MonoImage **new_modules;
6185                 MonoImage *ass;
6186                 char *name, *fqname;
6187                 /*
6188                  * FIXME: we already created an image in mono_image_basic_init (), but
6189                  * we don't know which module it belongs to, since that is only 
6190                  * determined at assembly save time.
6191                  */
6192                 /*image = (MonoDynamicImage*)ab->dynamic_assembly->assembly.image; */
6193                 name = mono_string_to_utf8 (ab->name);
6194                 fqname = mono_string_to_utf8_checked (moduleb->module.fqname, &error);
6195                 if (!mono_error_ok (&error)) {
6196                         g_free (name);
6197                         mono_error_raise_exception (&error);
6198                 }
6199                 image = create_dynamic_mono_image (ab->dynamic_assembly, name, fqname);
6200
6201                 moduleb->module.image = &image->image;
6202                 moduleb->dynamic_image = image;
6203                 register_module (mono_object_domain (moduleb), moduleb, image);
6204
6205                 /* register the module with the assembly */
6206                 ass = ab->dynamic_assembly->assembly.image;
6207                 module_count = ass->module_count;
6208                 new_modules = g_new0 (MonoImage *, module_count + 1);
6209
6210                 if (ass->modules)
6211                         memcpy (new_modules, ass->modules, module_count * sizeof (MonoImage *));
6212                 new_modules [module_count] = &image->image;
6213                 mono_image_addref (&image->image);
6214
6215                 g_free (ass->modules);
6216                 ass->modules = new_modules;
6217                 ass->module_count ++;
6218         }
6219 }
6220
6221 void
6222 mono_image_set_wrappers_type (MonoReflectionModuleBuilder *moduleb, MonoReflectionType *type)
6223 {
6224         MonoDynamicImage *image = moduleb->dynamic_image;
6225
6226         g_assert (type->type);
6227         image->wrappers_type = mono_class_from_mono_type (type->type);
6228 }
6229
6230 #endif
6231
6232 /*
6233  * mono_assembly_get_object:
6234  * @domain: an app domain
6235  * @assembly: an assembly
6236  *
6237  * Return an System.Reflection.Assembly object representing the MonoAssembly @assembly.
6238  */
6239 MonoReflectionAssembly*
6240 mono_assembly_get_object (MonoDomain *domain, MonoAssembly *assembly)
6241 {
6242         static MonoClass *assembly_type;
6243         MonoReflectionAssembly *res;
6244         
6245         CHECK_OBJECT (MonoReflectionAssembly *, assembly, NULL);
6246         if (!assembly_type) {
6247                 MonoClass *class = mono_class_from_name (mono_defaults.corlib, "System.Reflection", "MonoAssembly");
6248                 if (class == NULL)
6249                         class = mono_class_from_name (mono_defaults.corlib, "System.Reflection", "Assembly");
6250                 g_assert (class);
6251                 assembly_type = class;
6252         }
6253         res = (MonoReflectionAssembly *)mono_object_new (domain, assembly_type);
6254         res->assembly = assembly;
6255
6256         CACHE_OBJECT (MonoReflectionAssembly *, assembly, res, NULL);
6257 }
6258
6259
6260
6261 MonoReflectionModule*   
6262 mono_module_get_object   (MonoDomain *domain, MonoImage *image)
6263 {
6264         static MonoClass *module_type;
6265         MonoReflectionModule *res;
6266         char* basename;
6267         
6268         CHECK_OBJECT (MonoReflectionModule *, image, NULL);
6269         if (!module_type) {
6270                 MonoClass *class = mono_class_from_name (mono_defaults.corlib, "System.Reflection", "MonoModule");
6271                 if (class == NULL)
6272                         class = mono_class_from_name (mono_defaults.corlib, "System.Reflection", "Module");
6273                 g_assert (class);
6274                 module_type = class;
6275         }
6276         res = (MonoReflectionModule *)mono_object_new (domain, module_type);
6277
6278         res->image = image;
6279         MONO_OBJECT_SETREF (res, assembly, (MonoReflectionAssembly *) mono_assembly_get_object(domain, image->assembly));
6280
6281         MONO_OBJECT_SETREF (res, fqname, mono_string_new (domain, image->name));
6282         basename = g_path_get_basename (image->name);
6283         MONO_OBJECT_SETREF (res, name, mono_string_new (domain, basename));
6284         MONO_OBJECT_SETREF (res, scopename, mono_string_new (domain, image->module_name));
6285         
6286         g_free (basename);
6287
6288         if (image->assembly->image == image) {
6289                 res->token = mono_metadata_make_token (MONO_TABLE_MODULE, 1);
6290         } else {
6291                 int i;
6292                 res->token = 0;
6293                 if (image->assembly->image->modules) {
6294                         for (i = 0; i < image->assembly->image->module_count; i++) {
6295                                 if (image->assembly->image->modules [i] == image)
6296                                         res->token = mono_metadata_make_token (MONO_TABLE_MODULEREF, i + 1);
6297                         }
6298                         g_assert (res->token);
6299                 }
6300         }
6301
6302         CACHE_OBJECT (MonoReflectionModule *, image, res, NULL);
6303 }
6304
6305 MonoReflectionModule*   
6306 mono_module_file_get_object (MonoDomain *domain, MonoImage *image, int table_index)
6307 {
6308         static MonoClass *module_type;
6309         MonoReflectionModule *res;
6310         MonoTableInfo *table;
6311         guint32 cols [MONO_FILE_SIZE];
6312         const char *name;
6313         guint32 i, name_idx;
6314         const char *val;
6315         
6316         if (!module_type) {
6317                 MonoClass *class = mono_class_from_name (mono_defaults.corlib, "System.Reflection", "MonoModule");
6318                 if (class == NULL)
6319                         class = mono_class_from_name (mono_defaults.corlib, "System.Reflection", "Module");
6320                 g_assert (class);
6321                 module_type = class;
6322         }
6323         res = (MonoReflectionModule *)mono_object_new (domain, module_type);
6324
6325         table = &image->tables [MONO_TABLE_FILE];
6326         g_assert (table_index < table->rows);
6327         mono_metadata_decode_row (table, table_index, cols, MONO_FILE_SIZE);
6328
6329         res->image = NULL;
6330         MONO_OBJECT_SETREF (res, assembly, (MonoReflectionAssembly *) mono_assembly_get_object(domain, image->assembly));
6331         name = mono_metadata_string_heap (image, cols [MONO_FILE_NAME]);
6332
6333         /* Check whenever the row has a corresponding row in the moduleref table */
6334         table = &image->tables [MONO_TABLE_MODULEREF];
6335         for (i = 0; i < table->rows; ++i) {
6336                 name_idx = mono_metadata_decode_row_col (table, i, MONO_MODULEREF_NAME);
6337                 val = mono_metadata_string_heap (image, name_idx);
6338                 if (strcmp (val, name) == 0)
6339                         res->image = image->modules [i];
6340         }
6341
6342         MONO_OBJECT_SETREF (res, fqname, mono_string_new (domain, name));
6343         MONO_OBJECT_SETREF (res, name, mono_string_new (domain, name));
6344         MONO_OBJECT_SETREF (res, scopename, mono_string_new (domain, name));
6345         res->is_resource = cols [MONO_FILE_FLAGS] && FILE_CONTAINS_NO_METADATA;
6346         res->token = mono_metadata_make_token (MONO_TABLE_FILE, table_index + 1);
6347
6348         return res;
6349 }
6350
6351 static gboolean
6352 verify_safe_for_managed_space (MonoType *type)
6353 {
6354         switch (type->type) {
6355 #ifdef DEBUG_HARDER
6356         case MONO_TYPE_ARRAY:
6357                 return verify_safe_for_managed_space (&type->data.array->eklass->byval_arg);
6358         case MONO_TYPE_PTR:
6359                 return verify_safe_for_managed_space (type->data.type);
6360         case MONO_TYPE_SZARRAY:
6361                 return verify_safe_for_managed_space (&type->data.klass->byval_arg);
6362         case MONO_TYPE_GENERICINST: {
6363                 MonoGenericInst *inst = type->data.generic_class->inst;
6364                 int i;
6365                 if (!inst->is_open)
6366                         break;
6367                 for (i = 0; i < inst->type_argc; ++i)
6368                         if (!verify_safe_for_managed_space (inst->type_argv [i]))
6369                                 return FALSE;
6370                 break;
6371         }
6372 #endif
6373         case MONO_TYPE_VAR:
6374         case MONO_TYPE_MVAR:
6375                 return TRUE;
6376         }
6377         return TRUE;
6378 }
6379
6380 static MonoType*
6381 mono_type_normalize (MonoType *type)
6382 {
6383         int i;
6384         MonoGenericClass *gclass;
6385         MonoGenericInst *ginst;
6386         MonoClass *gtd;
6387         MonoGenericContainer *gcontainer;
6388         MonoType **argv = NULL;
6389         gboolean is_denorm_gtd = TRUE, requires_rebind = FALSE;
6390
6391         if (type->type != MONO_TYPE_GENERICINST)
6392                 return type;
6393
6394         gclass = type->data.generic_class;
6395         ginst = gclass->context.class_inst;
6396         if (!ginst->is_open)
6397                 return type;
6398
6399         gtd = gclass->container_class;
6400         gcontainer = gtd->generic_container;
6401         argv = g_newa (MonoType*, ginst->type_argc);
6402
6403         for (i = 0; i < ginst->type_argc; ++i) {
6404                 MonoType *t = ginst->type_argv [i], *norm;
6405                 if (t->type != MONO_TYPE_VAR || t->data.generic_param->num != i || t->data.generic_param->owner != gcontainer)
6406                         is_denorm_gtd = FALSE;
6407                 norm = mono_type_normalize (t);
6408                 argv [i] = norm;
6409                 if (norm != t)
6410                         requires_rebind = TRUE;
6411         }
6412
6413         if (is_denorm_gtd)
6414                 return type->byref == gtd->byval_arg.byref ? &gtd->byval_arg : &gtd->this_arg;
6415
6416         if (requires_rebind) {
6417                 MonoClass *klass = mono_class_bind_generic_parameters (gtd, ginst->type_argc, argv, gclass->is_dynamic);
6418                 return type->byref == klass->byval_arg.byref ? &klass->byval_arg : &klass->this_arg;
6419         }
6420
6421         return type;
6422 }
6423 /*
6424  * mono_type_get_object:
6425  * @domain: an app domain
6426  * @type: a type
6427  *
6428  * Return an System.MonoType object representing the type @type.
6429  */
6430 MonoReflectionType*
6431 mono_type_get_object (MonoDomain *domain, MonoType *type)
6432 {
6433         MonoType *norm_type;
6434         MonoReflectionType *res;
6435         MonoClass *klass = mono_class_from_mono_type (type);
6436
6437         /*we must avoid using @type as it might have come
6438          * from a mono_metadata_type_dup and the caller
6439          * expects that is can be freed.
6440          * Using the right type from 
6441          */
6442         type = klass->byval_arg.byref == type->byref ? &klass->byval_arg : &klass->this_arg;
6443
6444         /* void is very common */
6445         if (type->type == MONO_TYPE_VOID && domain->typeof_void)
6446                 return (MonoReflectionType*)domain->typeof_void;
6447
6448         /*
6449          * If the vtable of the given class was already created, we can use
6450          * the MonoType from there and avoid all locking and hash table lookups.
6451          * 
6452          * We cannot do this for TypeBuilders as mono_reflection_create_runtime_class expects
6453          * that the resulting object is different.   
6454          */
6455         if (type == &klass->byval_arg && !klass->image->dynamic) {
6456                 MonoVTable *vtable = mono_class_try_get_vtable (domain, klass);
6457                 if (vtable && vtable->type)
6458                         return vtable->type;
6459         }
6460
6461         mono_loader_lock (); /*FIXME mono_class_init and mono_class_vtable acquire it*/
6462         mono_domain_lock (domain);
6463         if (!domain->type_hash)
6464                 domain->type_hash = mono_g_hash_table_new_type ((GHashFunc)mono_metadata_type_hash, 
6465                                 (GCompareFunc)mono_metadata_type_equal, MONO_HASH_VALUE_GC);
6466         if ((res = mono_g_hash_table_lookup (domain->type_hash, type))) {
6467                 mono_domain_unlock (domain);
6468                 mono_loader_unlock ();
6469                 return res;
6470         }
6471
6472         /*Types must be normalized so a generic instance of the GTD get's the same inner type.
6473          * For example in: Foo<A,B>; Bar<A> : Foo<A, Bar<A>>
6474          * The second Bar will be encoded a generic instance of Bar with <A> as parameter.
6475          * On all other places, Bar<A> will be encoded as the GTD itself. This is an implementation
6476          * artifact of how generics are encoded and should be transparent to managed code so we
6477          * need to weed out this diference when retrieving managed System.Type objects.
6478          */
6479         norm_type = mono_type_normalize (type);
6480         if (norm_type != type) {
6481                 res = mono_type_get_object (domain, norm_type);
6482                 mono_g_hash_table_insert (domain->type_hash, type, res);
6483                 mono_domain_unlock (domain);
6484                 mono_loader_unlock ();
6485                 return res;
6486         }
6487
6488         /* This MonoGenericClass hack is no longer necessary. Let's leave it here until we finish with the 2-stage type-builder setup.*/
6489         if ((type->type == MONO_TYPE_GENERICINST) && type->data.generic_class->is_dynamic && !type->data.generic_class->container_class->wastypebuilder)
6490                 g_assert (0);
6491
6492         if (!verify_safe_for_managed_space (type)) {
6493                 mono_domain_unlock (domain);
6494                 mono_loader_unlock ();
6495                 mono_raise_exception (mono_get_exception_invalid_operation ("This type cannot be propagated to managed space"));
6496         }
6497
6498         if (mono_class_get_ref_info (klass) && !klass->wastypebuilder) {
6499                 gboolean is_type_done = TRUE;
6500                 /* Generic parameters have reflection_info set but they are not finished together with their enclosing type.
6501                  * We must ensure that once a type is finished we don't return a GenericTypeParameterBuilder.
6502                  * We can't simply close the types as this will interfere with other parts of the generics machinery.
6503                 */
6504                 if (klass->byval_arg.type == MONO_TYPE_MVAR || klass->byval_arg.type == MONO_TYPE_VAR) {
6505                         MonoGenericParam *gparam = klass->byval_arg.data.generic_param;
6506
6507                         if (gparam->owner && gparam->owner->is_method) {
6508                                 MonoMethod *method = gparam->owner->owner.method;
6509                                 if (method && mono_class_get_generic_type_definition (method->klass)->wastypebuilder)
6510                                         is_type_done = FALSE;
6511                         } else if (gparam->owner && !gparam->owner->is_method) {
6512                                 MonoClass *klass = gparam->owner->owner.klass;
6513                                 if (klass && mono_class_get_generic_type_definition (klass)->wastypebuilder)
6514                                         is_type_done = FALSE;
6515                         }
6516                 } 
6517
6518                 /* g_assert_not_reached (); */
6519                 /* should this be considered an error condition? */
6520                 if (is_type_done && !type->byref) {
6521                         mono_domain_unlock (domain);
6522                         mono_loader_unlock ();
6523                         return mono_class_get_ref_info (klass);
6524                 }
6525         }
6526         /* This is stored in vtables/JITted code so it has to be pinned */
6527         res = (MonoReflectionType *)mono_object_new_pinned (domain, mono_defaults.monotype_class);
6528         res->type = type;
6529         mono_g_hash_table_insert (domain->type_hash, type, res);
6530
6531         if (type->type == MONO_TYPE_VOID)
6532                 domain->typeof_void = (MonoObject*)res;
6533
6534         mono_domain_unlock (domain);
6535         mono_loader_unlock ();
6536         return res;
6537 }
6538
6539 /*
6540  * mono_method_get_object:
6541  * @domain: an app domain
6542  * @method: a method
6543  * @refclass: the reflected type (can be NULL)
6544  *
6545  * Return an System.Reflection.MonoMethod object representing the method @method.
6546  */
6547 MonoReflectionMethod*
6548 mono_method_get_object (MonoDomain *domain, MonoMethod *method, MonoClass *refclass)
6549 {
6550         /*
6551          * We use the same C representation for methods and constructors, but the type 
6552          * name in C# is different.
6553          */
6554         static MonoClass *System_Reflection_MonoMethod = NULL;
6555         static MonoClass *System_Reflection_MonoCMethod = NULL;
6556         static MonoClass *System_Reflection_MonoGenericMethod = NULL;
6557         static MonoClass *System_Reflection_MonoGenericCMethod = NULL;
6558         MonoClass *klass;
6559         MonoReflectionMethod *ret;
6560
6561         if (method->is_inflated) {
6562                 MonoReflectionGenericMethod *gret;
6563
6564                 refclass = method->klass;
6565                 CHECK_OBJECT (MonoReflectionMethod *, method, refclass);
6566                 if ((*method->name == '.') && (!strcmp (method->name, ".ctor") || !strcmp (method->name, ".cctor"))) {
6567                         if (!System_Reflection_MonoGenericCMethod)
6568                                 System_Reflection_MonoGenericCMethod = mono_class_from_name (mono_defaults.corlib, "System.Reflection", "MonoGenericCMethod");
6569                         klass = System_Reflection_MonoGenericCMethod;
6570                 } else {
6571                         if (!System_Reflection_MonoGenericMethod)
6572                                 System_Reflection_MonoGenericMethod = mono_class_from_name (mono_defaults.corlib, "System.Reflection", "MonoGenericMethod");
6573                         klass = System_Reflection_MonoGenericMethod;
6574                 }
6575                 gret = (MonoReflectionGenericMethod*)mono_object_new (domain, klass);
6576                 gret->method.method = method;
6577                 MONO_OBJECT_SETREF (gret, method.name, mono_string_new (domain, method->name));
6578                 MONO_OBJECT_SETREF (gret, method.reftype, mono_type_get_object (domain, &refclass->byval_arg));
6579                 CACHE_OBJECT (MonoReflectionMethod *, method, (MonoReflectionMethod*)gret, refclass);
6580         }
6581
6582         if (!refclass)
6583                 refclass = method->klass;
6584
6585         CHECK_OBJECT (MonoReflectionMethod *, method, refclass);
6586         if (*method->name == '.' && (strcmp (method->name, ".ctor") == 0 || strcmp (method->name, ".cctor") == 0)) {
6587                 if (!System_Reflection_MonoCMethod)
6588                         System_Reflection_MonoCMethod = mono_class_from_name (mono_defaults.corlib, "System.Reflection", "MonoCMethod");
6589                 klass = System_Reflection_MonoCMethod;
6590         }
6591         else {
6592                 if (!System_Reflection_MonoMethod)
6593                         System_Reflection_MonoMethod = mono_class_from_name (mono_defaults.corlib, "System.Reflection", "MonoMethod");
6594                 klass = System_Reflection_MonoMethod;
6595         }
6596         ret = (MonoReflectionMethod*)mono_object_new (domain, klass);
6597         ret->method = method;
6598         MONO_OBJECT_SETREF (ret, reftype, mono_type_get_object (domain, &refclass->byval_arg));
6599         CACHE_OBJECT (MonoReflectionMethod *, method, ret, refclass);
6600 }
6601
6602 /*
6603  * mono_method_clear_object:
6604  *
6605  *   Clear the cached reflection objects for the dynamic method METHOD.
6606  */
6607 void
6608 mono_method_clear_object (MonoDomain *domain, MonoMethod *method)
6609 {
6610         MonoClass *klass;
6611         g_assert (method->dynamic);
6612
6613         klass = method->klass;
6614         while (klass) {
6615                 clear_cached_object (domain, method, klass);
6616                 klass = klass->parent;
6617         }
6618         /* Added by mono_param_get_objects () */
6619         clear_cached_object (domain, &(method->signature), NULL);
6620         klass = method->klass;
6621         while (klass) {
6622                 clear_cached_object (domain, &(method->signature), klass);
6623                 klass = klass->parent;
6624         }
6625 }
6626
6627 /*
6628  * mono_field_get_object:
6629  * @domain: an app domain
6630  * @klass: a type
6631  * @field: a field
6632  *
6633  * Return an System.Reflection.MonoField object representing the field @field
6634  * in class @klass.
6635  */
6636 MonoReflectionField*
6637 mono_field_get_object (MonoDomain *domain, MonoClass *klass, MonoClassField *field)
6638 {
6639         MonoReflectionField *res;
6640         static MonoClass *monofield_klass;
6641
6642         CHECK_OBJECT (MonoReflectionField *, field, klass);
6643         if (!monofield_klass)
6644                 monofield_klass = mono_class_from_name (mono_defaults.corlib, "System.Reflection", "MonoField");
6645         res = (MonoReflectionField *)mono_object_new (domain, monofield_klass);
6646         res->klass = klass;
6647         res->field = field;
6648         MONO_OBJECT_SETREF (res, name, mono_string_new (domain, mono_field_get_name (field)));
6649
6650         if (is_field_on_inst (field)) {
6651                 res->attrs = get_field_on_inst_generic_type (field)->attrs;
6652                 MONO_OBJECT_SETREF (res, type, mono_type_get_object (domain, field->type));
6653         } else {
6654                 if (field->type)
6655                         MONO_OBJECT_SETREF (res, type, mono_type_get_object (domain, field->type));
6656                 res->attrs = mono_field_get_flags (field);
6657         }
6658         CACHE_OBJECT (MonoReflectionField *, field, res, klass);
6659 }
6660
6661 /*
6662  * mono_property_get_object:
6663  * @domain: an app domain
6664  * @klass: a type
6665  * @property: a property
6666  *
6667  * Return an System.Reflection.MonoProperty object representing the property @property
6668  * in class @klass.
6669  */
6670 MonoReflectionProperty*
6671 mono_property_get_object (MonoDomain *domain, MonoClass *klass, MonoProperty *property)
6672 {
6673         MonoReflectionProperty *res;
6674         static MonoClass *monoproperty_klass;
6675
6676         CHECK_OBJECT (MonoReflectionProperty *, property, klass);
6677         if (!monoproperty_klass)
6678                 monoproperty_klass = mono_class_from_name (mono_defaults.corlib, "System.Reflection", "MonoProperty");
6679         res = (MonoReflectionProperty *)mono_object_new (domain, monoproperty_klass);
6680         res->klass = klass;
6681         res->property = property;
6682         CACHE_OBJECT (MonoReflectionProperty *, property, res, klass);
6683 }
6684
6685 /*
6686  * mono_event_get_object:
6687  * @domain: an app domain
6688  * @klass: a type
6689  * @event: a event
6690  *
6691  * Return an System.Reflection.MonoEvent object representing the event @event
6692  * in class @klass.
6693  */
6694 MonoReflectionEvent*
6695 mono_event_get_object (MonoDomain *domain, MonoClass *klass, MonoEvent *event)
6696 {
6697         MonoReflectionEvent *res;
6698         MonoReflectionMonoEvent *mono_event;
6699         static MonoClass *monoevent_klass;
6700
6701         CHECK_OBJECT (MonoReflectionEvent *, event, klass);
6702         if (!monoevent_klass)
6703                 monoevent_klass = mono_class_from_name (mono_defaults.corlib, "System.Reflection", "MonoEvent");
6704         mono_event = (MonoReflectionMonoEvent *)mono_object_new (domain, monoevent_klass);
6705         mono_event->klass = klass;
6706         mono_event->event = event;
6707         res = (MonoReflectionEvent*)mono_event;
6708         CACHE_OBJECT (MonoReflectionEvent *, event, res, klass);
6709 }
6710
6711 /**
6712  * mono_get_reflection_missing_object:
6713  * @domain: Domain where the object lives
6714  *
6715  * Returns the System.Reflection.Missing.Value singleton object
6716  * (of type System.Reflection.Missing).
6717  *
6718  * Used as the value for ParameterInfo.DefaultValue when Optional
6719  * is present
6720  */
6721 static MonoObject *
6722 mono_get_reflection_missing_object (MonoDomain *domain)
6723 {
6724         MonoObject *obj;
6725         static MonoClassField *missing_value_field = NULL;
6726         
6727         if (!missing_value_field) {
6728                 MonoClass *missing_klass;
6729                 missing_klass = mono_class_from_name (mono_defaults.corlib, "System.Reflection", "Missing");
6730                 mono_class_init (missing_klass);
6731                 missing_value_field = mono_class_get_field_from_name (missing_klass, "Value");
6732                 g_assert (missing_value_field);
6733         }
6734         obj = mono_field_get_value_object (domain, missing_value_field, NULL); 
6735         g_assert (obj);
6736         return obj;
6737 }
6738
6739 static MonoObject*
6740 get_dbnull (MonoDomain *domain, MonoObject **dbnull)
6741 {
6742         if (!*dbnull)
6743                 *dbnull = mono_get_dbnull_object (domain);
6744         return *dbnull;
6745 }
6746
6747 static MonoObject*
6748 get_reflection_missing (MonoDomain *domain, MonoObject **reflection_missing)
6749 {
6750         if (!*reflection_missing)
6751                 *reflection_missing = mono_get_reflection_missing_object (domain);
6752         return *reflection_missing;
6753 }
6754
6755 /*
6756  * mono_param_get_objects:
6757  * @domain: an app domain
6758  * @method: a method
6759  *
6760  * Return an System.Reflection.ParameterInfo array object representing the parameters
6761  * in the method @method.
6762  */
6763 MonoArray*
6764 mono_param_get_objects_internal (MonoDomain *domain, MonoMethod *method, MonoClass *refclass)
6765 {
6766         static MonoClass *System_Reflection_ParameterInfo;
6767         static MonoClass *System_Reflection_ParameterInfo_array;
6768         MonoError error;
6769         MonoArray *res = NULL;
6770         MonoReflectionMethod *member = NULL;
6771         MonoReflectionParameter *param = NULL;
6772         char **names, **blobs = NULL;
6773         guint32 *types = NULL;
6774         MonoType *type = NULL;
6775         MonoObject *dbnull = NULL;
6776         MonoObject *missing = NULL;
6777         MonoMarshalSpec **mspecs;
6778         MonoMethodSignature *sig;
6779         MonoVTable *pinfo_vtable;
6780         int i;
6781
6782         if (!System_Reflection_ParameterInfo_array) {
6783                 MonoClass *klass;
6784
6785                 klass = mono_class_from_name (mono_defaults.corlib, "System.Reflection", "MonoParameterInfo");
6786                 if (!klass)
6787                         klass = mono_class_from_name (mono_defaults.corlib, "System.Reflection", "ParameterInfo");
6788
6789                 mono_memory_barrier ();
6790                 System_Reflection_ParameterInfo = klass; 
6791
6792         
6793                 klass = mono_array_class_get (klass, 1);
6794                 mono_memory_barrier ();
6795                 System_Reflection_ParameterInfo_array = klass;
6796         }
6797
6798         sig = mono_method_signature_checked (method, &error);
6799         if (!mono_error_ok (&error))
6800                 mono_error_raise_exception (&error);
6801
6802         if (!sig->param_count)
6803                 return mono_array_new_specific (mono_class_vtable (domain, System_Reflection_ParameterInfo_array), 0);
6804
6805         /* Note: the cache is based on the address of the signature into the method
6806          * since we already cache MethodInfos with the method as keys.
6807          */
6808         CHECK_OBJECT (MonoArray*, &(method->signature), refclass);
6809
6810         member = mono_method_get_object (domain, method, refclass);
6811         names = g_new (char *, sig->param_count);
6812         mono_method_get_param_names (method, (const char **) names);
6813
6814         mspecs = g_new (MonoMarshalSpec*, sig->param_count + 1);
6815         mono_method_get_marshal_info (method, mspecs);
6816
6817         res = mono_array_new_specific (mono_class_vtable (domain, System_Reflection_ParameterInfo_array), sig->param_count);
6818         pinfo_vtable = mono_class_vtable (domain, System_Reflection_ParameterInfo);
6819         for (i = 0; i < sig->param_count; ++i) {
6820                 param = (MonoReflectionParameter *)mono_object_new_specific (pinfo_vtable);
6821                 MONO_OBJECT_SETREF (param, ClassImpl, mono_type_get_object (domain, sig->params [i]));
6822                 MONO_OBJECT_SETREF (param, MemberImpl, (MonoObject*)member);
6823                 MONO_OBJECT_SETREF (param, NameImpl, mono_string_new (domain, names [i]));
6824                 param->PositionImpl = i;
6825                 param->AttrsImpl = sig->params [i]->attrs;
6826
6827                 if (!(param->AttrsImpl & PARAM_ATTRIBUTE_HAS_DEFAULT)) {
6828                         if (param->AttrsImpl & PARAM_ATTRIBUTE_OPTIONAL)
6829                                 MONO_OBJECT_SETREF (param, DefaultValueImpl, get_reflection_missing (domain, &missing));
6830                         else
6831                                 MONO_OBJECT_SETREF (param, DefaultValueImpl, get_dbnull (domain, &dbnull));
6832                 } else {
6833
6834                         if (!blobs) {
6835                                 blobs = g_new0 (char *, sig->param_count);
6836                                 types = g_new0 (guint32, sig->param_count);
6837                                 get_default_param_value_blobs (method, blobs, types); 
6838                         }
6839
6840                         /* Build MonoType for the type from the Constant Table */
6841                         if (!type)
6842                                 type = g_new0 (MonoType, 1);
6843                         type->type = types [i];
6844                         type->data.klass = NULL;
6845                         if (types [i] == MONO_TYPE_CLASS)
6846                                 type->data.klass = mono_defaults.object_class;
6847                         else if ((sig->params [i]->type == MONO_TYPE_VALUETYPE) && sig->params [i]->data.klass->enumtype) {
6848                                 /* For enums, types [i] contains the base type */
6849
6850                                         type->type = MONO_TYPE_VALUETYPE;
6851                                         type->data.klass = mono_class_from_mono_type (sig->params [i]);
6852                         } else
6853                                 type->data.klass = mono_class_from_mono_type (type);
6854
6855                         MONO_OBJECT_SETREF (param, DefaultValueImpl, mono_get_object_from_blob (domain, type, blobs [i]));
6856
6857                         /* Type in the Constant table is MONO_TYPE_CLASS for nulls */
6858                         if (types [i] != MONO_TYPE_CLASS && !param->DefaultValueImpl) {
6859                                 if (param->AttrsImpl & PARAM_ATTRIBUTE_OPTIONAL)
6860                                         MONO_OBJECT_SETREF (param, DefaultValueImpl, get_reflection_missing (domain, &missing));
6861                                 else
6862                                         MONO_OBJECT_SETREF (param, DefaultValueImpl, get_dbnull (domain, &dbnull));
6863                         }
6864                         
6865                 }
6866
6867                 if (mspecs [i + 1])
6868                         MONO_OBJECT_SETREF (param, MarshalAsImpl, (MonoObject*)mono_reflection_marshal_as_attribute_from_marshal_spec (domain, method->klass, mspecs [i + 1]));
6869                 
6870                 mono_array_setref (res, i, param);
6871         }
6872         g_free (names);
6873         g_free (blobs);
6874         g_free (types);
6875         g_free (type);
6876
6877         for (i = mono_method_signature (method)->param_count; i >= 0; i--)
6878                 if (mspecs [i])
6879                         mono_metadata_free_marshal_spec (mspecs [i]);
6880         g_free (mspecs);
6881         
6882         CACHE_OBJECT (MonoArray *, &(method->signature), res, refclass);
6883 }
6884
6885 MonoArray*
6886 mono_param_get_objects (MonoDomain *domain, MonoMethod *method)
6887 {
6888         return mono_param_get_objects_internal (domain, method, NULL);
6889 }
6890
6891 /*
6892  * mono_method_body_get_object:
6893  * @domain: an app domain
6894  * @method: a method
6895  *
6896  * Return an System.Reflection.MethodBody object representing the method @method.
6897  */
6898 MonoReflectionMethodBody*
6899 mono_method_body_get_object (MonoDomain *domain, MonoMethod *method)
6900 {
6901         static MonoClass *System_Reflection_MethodBody = NULL;
6902         static MonoClass *System_Reflection_LocalVariableInfo = NULL;
6903         static MonoClass *System_Reflection_ExceptionHandlingClause = NULL;
6904         MonoReflectionMethodBody *ret;
6905         MonoMethodHeader *header;
6906         MonoImage *image;
6907         guint32 method_rva, local_var_sig_token;
6908     char *ptr;
6909         unsigned char format, flags;
6910         int i;
6911
6912         /* for compatibility with .net */
6913     if (method->dynamic)
6914         mono_raise_exception (mono_get_exception_invalid_operation (NULL));
6915
6916         if (!System_Reflection_MethodBody)
6917                 System_Reflection_MethodBody = mono_class_from_name (mono_defaults.corlib, "System.Reflection", "MethodBody");
6918         if (!System_Reflection_LocalVariableInfo)
6919                 System_Reflection_LocalVariableInfo = mono_class_from_name (mono_defaults.corlib, "System.Reflection", "LocalVariableInfo");
6920         if (!System_Reflection_ExceptionHandlingClause)
6921                 System_Reflection_ExceptionHandlingClause = mono_class_from_name (mono_defaults.corlib, "System.Reflection", "ExceptionHandlingClause");
6922
6923         CHECK_OBJECT (MonoReflectionMethodBody *, method, NULL);
6924
6925         if ((method->flags & METHOD_ATTRIBUTE_PINVOKE_IMPL) ||
6926                 (method->flags & METHOD_ATTRIBUTE_ABSTRACT) ||
6927             (method->iflags & METHOD_IMPL_ATTRIBUTE_INTERNAL_CALL) ||
6928             (method->iflags & METHOD_IMPL_ATTRIBUTE_RUNTIME))
6929                 return NULL;
6930
6931         image = method->klass->image;
6932         header = mono_method_get_header (method);
6933
6934         if (!image->dynamic) {
6935                 /* Obtain local vars signature token */
6936                 method_rva = mono_metadata_decode_row_col (&image->tables [MONO_TABLE_METHOD], mono_metadata_token_index (method->token) - 1, MONO_METHOD_RVA);
6937                 ptr = mono_image_rva_map (image, method_rva);
6938                 flags = *(const unsigned char *) ptr;
6939                 format = flags & METHOD_HEADER_FORMAT_MASK;
6940                 switch (format){
6941                 case METHOD_HEADER_TINY_FORMAT:
6942                         local_var_sig_token = 0;
6943                         break;
6944                 case METHOD_HEADER_FAT_FORMAT:
6945                         ptr += 2;
6946                         ptr += 2;
6947                         ptr += 4;
6948                         local_var_sig_token = read32 (ptr);
6949                         break;
6950                 default:
6951                         g_assert_not_reached ();
6952                 }
6953         } else
6954                 local_var_sig_token = 0; //FIXME
6955
6956         ret = (MonoReflectionMethodBody*)mono_object_new (domain, System_Reflection_MethodBody);
6957
6958         ret->init_locals = header->init_locals;
6959         ret->max_stack = header->max_stack;
6960         ret->local_var_sig_token = local_var_sig_token;
6961         MONO_OBJECT_SETREF (ret, il, mono_array_new_cached (domain, mono_defaults.byte_class, header->code_size));
6962         memcpy (mono_array_addr (ret->il, guint8, 0), header->code, header->code_size);
6963
6964         /* Locals */
6965         MONO_OBJECT_SETREF (ret, locals, mono_array_new_cached (domain, System_Reflection_LocalVariableInfo, header->num_locals));
6966         for (i = 0; i < header->num_locals; ++i) {
6967                 MonoReflectionLocalVariableInfo *info = (MonoReflectionLocalVariableInfo*)mono_object_new (domain, System_Reflection_LocalVariableInfo);
6968                 MONO_OBJECT_SETREF (info, local_type, mono_type_get_object (domain, header->locals [i]));
6969                 info->is_pinned = header->locals [i]->pinned;
6970                 info->local_index = i;
6971                 mono_array_setref (ret->locals, i, info);
6972         }
6973
6974         /* Exceptions */
6975         MONO_OBJECT_SETREF (ret, clauses, mono_array_new_cached (domain, System_Reflection_ExceptionHandlingClause, header->num_clauses));
6976         for (i = 0; i < header->num_clauses; ++i) {
6977                 MonoReflectionExceptionHandlingClause *info = (MonoReflectionExceptionHandlingClause*)mono_object_new (domain, System_Reflection_ExceptionHandlingClause);
6978                 MonoExceptionClause *clause = &header->clauses [i];
6979
6980                 info->flags = clause->flags;
6981                 info->try_offset = clause->try_offset;
6982                 info->try_length = clause->try_len;
6983                 info->handler_offset = clause->handler_offset;
6984                 info->handler_length = clause->handler_len;
6985                 if (clause->flags == MONO_EXCEPTION_CLAUSE_FILTER)
6986                         info->filter_offset = clause->data.filter_offset;
6987                 else if (clause->data.catch_class)
6988                         MONO_OBJECT_SETREF (info, catch_type, mono_type_get_object (mono_domain_get (), &clause->data.catch_class->byval_arg));
6989
6990                 mono_array_setref (ret->clauses, i, info);
6991         }
6992
6993         mono_metadata_free_mh (header);
6994         CACHE_OBJECT (MonoReflectionMethodBody *, method, ret, NULL);
6995         return ret;
6996 }
6997
6998 /**
6999  * mono_get_dbnull_object:
7000  * @domain: Domain where the object lives
7001  *
7002  * Returns the System.DBNull.Value singleton object
7003  *
7004  * Used as the value for ParameterInfo.DefaultValue 
7005  */
7006 MonoObject *
7007 mono_get_dbnull_object (MonoDomain *domain)
7008 {
7009         MonoObject *obj;
7010         static MonoClassField *dbnull_value_field = NULL;
7011         
7012         if (!dbnull_value_field) {
7013                 MonoClass *dbnull_klass;
7014                 dbnull_klass = mono_class_from_name (mono_defaults.corlib, "System", "DBNull");
7015                 mono_class_init (dbnull_klass);
7016                 dbnull_value_field = mono_class_get_field_from_name (dbnull_klass, "Value");
7017                 g_assert (dbnull_value_field);
7018         }
7019         obj = mono_field_get_value_object (domain, dbnull_value_field, NULL); 
7020         g_assert (obj);
7021         return obj;
7022 }
7023
7024 static void
7025 get_default_param_value_blobs (MonoMethod *method, char **blobs, guint32 *types)
7026 {
7027         guint32 param_index, i, lastp, crow = 0;
7028         guint32 param_cols [MONO_PARAM_SIZE], const_cols [MONO_CONSTANT_SIZE];
7029         gint32 idx;
7030
7031         MonoClass *klass = method->klass;
7032         MonoImage *image = klass->image;
7033         MonoMethodSignature *methodsig = mono_method_signature (method);
7034
7035         MonoTableInfo *constt;
7036         MonoTableInfo *methodt;
7037         MonoTableInfo *paramt;
7038
7039         if (!methodsig->param_count)
7040                 return;
7041
7042         mono_class_init (klass);
7043
7044         if (klass->image->dynamic) {
7045                 MonoReflectionMethodAux *aux;
7046                 if (method->is_inflated)
7047                         method = ((MonoMethodInflated*)method)->declaring;
7048                 aux = g_hash_table_lookup (((MonoDynamicImage*)method->klass->image)->method_aux_hash, method);
7049                 if (aux && aux->param_defaults) {
7050                         memcpy (blobs, &(aux->param_defaults [1]), methodsig->param_count * sizeof (char*));
7051                         memcpy (types, &(aux->param_default_types [1]), methodsig->param_count * sizeof (guint32));
7052                 }
7053                 return;
7054         }
7055
7056         methodt = &klass->image->tables [MONO_TABLE_METHOD];
7057         paramt = &klass->image->tables [MONO_TABLE_PARAM];
7058         constt = &image->tables [MONO_TABLE_CONSTANT];
7059
7060         idx = mono_method_get_index (method) - 1;
7061         g_assert (idx != -1);
7062
7063         param_index = mono_metadata_decode_row_col (methodt, idx, MONO_METHOD_PARAMLIST);
7064         if (idx + 1 < methodt->rows)
7065                 lastp = mono_metadata_decode_row_col (methodt, idx + 1, MONO_METHOD_PARAMLIST);
7066         else
7067                 lastp = paramt->rows + 1;
7068
7069         for (i = param_index; i < lastp; ++i) {
7070                 guint32 paramseq;
7071
7072                 mono_metadata_decode_row (paramt, i - 1, param_cols, MONO_PARAM_SIZE);
7073                 paramseq = param_cols [MONO_PARAM_SEQUENCE];
7074
7075                 if (!(param_cols [MONO_PARAM_FLAGS] & PARAM_ATTRIBUTE_HAS_DEFAULT))
7076                         continue;
7077
7078                 crow = mono_metadata_get_constant_index (image, MONO_TOKEN_PARAM_DEF | i, crow + 1);
7079                 if (!crow) {
7080                         continue;
7081                 }
7082         
7083                 mono_metadata_decode_row (constt, crow - 1, const_cols, MONO_CONSTANT_SIZE);
7084                 blobs [paramseq - 1] = (gpointer) mono_metadata_blob_heap (image, const_cols [MONO_CONSTANT_VALUE]);
7085                 types [paramseq - 1] = const_cols [MONO_CONSTANT_TYPE];
7086         }
7087
7088         return;
7089 }
7090
7091 MonoObject *
7092 mono_get_object_from_blob (MonoDomain *domain, MonoType *type, const char *blob)
7093 {
7094         void *retval;
7095         MonoClass *klass;
7096         MonoObject *object;
7097         MonoType *basetype = type;
7098
7099         if (!blob)
7100                 return NULL;
7101         
7102         klass = mono_class_from_mono_type (type);
7103         if (klass->valuetype) {
7104                 object = mono_object_new (domain, klass);
7105                 retval = ((gchar *) object + sizeof (MonoObject));
7106                 if (klass->enumtype)
7107                         basetype = mono_class_enum_basetype (klass);
7108         } else {
7109                 retval = &object;
7110         }
7111                         
7112         if (!mono_get_constant_value_from_blob (domain, basetype->type,  blob, retval))
7113                 return object;
7114         else
7115                 return NULL;
7116 }
7117
7118 static int
7119 assembly_name_to_aname (MonoAssemblyName *assembly, char *p) {
7120         int found_sep;
7121         char *s;
7122         gboolean quoted = FALSE;
7123
7124         memset (assembly, 0, sizeof (MonoAssemblyName));
7125         assembly->culture = "";
7126         memset (assembly->public_key_token, 0, MONO_PUBLIC_KEY_TOKEN_LENGTH);
7127
7128         if (*p == '"') {
7129                 quoted = TRUE;
7130                 p++;
7131         }
7132         assembly->name = p;
7133         while (*p && (isalnum (*p) || *p == '.' || *p == '-' || *p == '_' || *p == '$' || *p == '@' || g_ascii_isspace (*p)))
7134                 p++;
7135         if (quoted) {
7136                 if (*p != '"')
7137                         return 1;
7138                 *p = 0;
7139                 p++;
7140         }
7141         if (*p != ',')
7142                 return 1;
7143         *p = 0;
7144         /* Remove trailing whitespace */
7145         s = p - 1;
7146         while (*s && g_ascii_isspace (*s))
7147                 *s-- = 0;
7148         p ++;
7149         while (g_ascii_isspace (*p))
7150                 p++;
7151         while (*p) {
7152                 if (*p == 'V' && g_ascii_strncasecmp (p, "Version=", 8) == 0) {
7153                         p += 8;
7154                         assembly->major = strtoul (p, &s, 10);
7155                         if (s == p || *s != '.')
7156                                 return 1;
7157                         p = ++s;
7158                         assembly->minor = strtoul (p, &s, 10);
7159                         if (s == p || *s != '.')
7160                                 return 1;
7161                         p = ++s;
7162                         assembly->build = strtoul (p, &s, 10);
7163                         if (s == p || *s != '.')
7164                                 return 1;
7165                         p = ++s;
7166                         assembly->revision = strtoul (p, &s, 10);
7167                         if (s == p)
7168                                 return 1;
7169                         p = s;
7170                 } else if (*p == 'C' && g_ascii_strncasecmp (p, "Culture=", 8) == 0) {
7171                         p += 8;
7172                         if (g_ascii_strncasecmp (p, "neutral", 7) == 0) {
7173                                 assembly->culture = "";
7174                                 p += 7;
7175                         } else {
7176                                 assembly->culture = p;
7177                                 while (*p && *p != ',') {
7178                                         p++;
7179                                 }
7180                         }
7181                 } else if (*p == 'P' && g_ascii_strncasecmp (p, "PublicKeyToken=", 15) == 0) {
7182                         p += 15;
7183                         if (strncmp (p, "null", 4) == 0) {
7184                                 p += 4;
7185                         } else {
7186                                 int len;
7187                                 gchar *start = p;
7188                                 while (*p && *p != ',') {
7189                                         p++;
7190                                 }
7191                                 len = (p - start + 1);
7192                                 if (len > MONO_PUBLIC_KEY_TOKEN_LENGTH)
7193                                         len = MONO_PUBLIC_KEY_TOKEN_LENGTH;
7194                                 g_strlcpy ((char*)assembly->public_key_token, start, len);
7195                         }
7196                 } else {
7197                         while (*p && *p != ',')
7198                                 p++;
7199                 }
7200                 found_sep = 0;
7201                 while (g_ascii_isspace (*p) || *p == ',') {
7202                         *p++ = 0;
7203                         found_sep = 1;
7204                         continue;
7205                 }
7206                 /* failed */
7207                 if (!found_sep)
7208                         return 1;
7209         }
7210
7211         return 0;
7212 }
7213
7214 /*
7215  * mono_reflection_parse_type:
7216  * @name: type name
7217  *
7218  * Parse a type name as accepted by the GetType () method and output the info
7219  * extracted in the info structure.
7220  * the name param will be mangled, so, make a copy before passing it to this function.
7221  * The fields in info will be valid until the memory pointed to by name is valid.
7222  *
7223  * See also mono_type_get_name () below.
7224  *
7225  * Returns: 0 on parse error.
7226  */
7227 static int
7228 _mono_reflection_parse_type (char *name, char **endptr, gboolean is_recursed,
7229                              MonoTypeNameParse *info)
7230 {
7231         char *start, *p, *w, *last_point, *startn;
7232         int in_modifiers = 0;
7233         int isbyref = 0, rank = 0;
7234
7235         start = p = w = name;
7236
7237         //FIXME could we just zero the whole struct? memset (&info, 0, sizeof (MonoTypeNameParse))
7238         memset (&info->assembly, 0, sizeof (MonoAssemblyName));
7239         info->name = info->name_space = NULL;
7240         info->nested = NULL;
7241         info->modifiers = NULL;
7242         info->type_arguments = NULL;
7243
7244         /* last_point separates the namespace from the name */
7245         last_point = NULL;
7246         /* Skips spaces */
7247         while (*p == ' ') p++, start++, w++, name++;
7248
7249         while (*p) {
7250                 switch (*p) {
7251                 case '+':
7252                         *p = 0; /* NULL terminate the name */
7253                         startn = p + 1;
7254                         info->nested = g_list_append (info->nested, startn);
7255                         /* we have parsed the nesting namespace + name */
7256                         if (info->name)
7257                                 break;
7258                         if (last_point) {
7259                                 info->name_space = start;
7260                                 *last_point = 0;
7261                                 info->name = last_point + 1;
7262                         } else {
7263                                 info->name_space = (char *)"";
7264                                 info->name = start;
7265                         }
7266                         break;
7267                 case '.':
7268                         last_point = p;
7269                         break;
7270                 case '\\':
7271                         ++p;
7272                         break;
7273                 case '&':
7274                 case '*':
7275                 case '[':
7276                 case ',':
7277                 case ']':
7278                         in_modifiers = 1;
7279                         break;
7280                 default:
7281                         break;
7282                 }
7283                 if (in_modifiers)
7284                         break;
7285                 // *w++ = *p++;
7286                 p++;
7287         }
7288         
7289         if (!info->name) {
7290                 if (last_point) {
7291                         info->name_space = start;
7292                         *last_point = 0;
7293                         info->name = last_point + 1;
7294                 } else {
7295                         info->name_space = (char *)"";
7296                         info->name = start;
7297                 }
7298         }
7299         while (*p) {
7300                 switch (*p) {
7301                 case '&':
7302                         if (isbyref) /* only one level allowed by the spec */
7303                                 return 0;
7304                         isbyref = 1;
7305                         info->modifiers = g_list_append (info->modifiers, GUINT_TO_POINTER (0));
7306                         *p++ = 0;
7307                         break;
7308                 case '*':
7309                         info->modifiers = g_list_append (info->modifiers, GUINT_TO_POINTER (-1));
7310                         *p++ = 0;
7311                         break;
7312                 case '[':
7313                         //Decide if it's an array of a generic argument list
7314                         *p++ = 0;
7315
7316                         if (!*p) //XXX test
7317                                 return 0;
7318                         if (*p  == ',' || *p == '*' || *p == ']') { //array
7319                                 rank = 1;
7320                                 while (*p) {
7321                                         if (*p == ']')
7322                                                 break;
7323                                         if (*p == ',')
7324                                                 rank++;
7325                                         else if (*p == '*') /* '*' means unknown lower bound */
7326                                                 info->modifiers = g_list_append (info->modifiers, GUINT_TO_POINTER (-2));
7327                                         else
7328                                                 return 0;
7329                                         ++p;
7330                                 }
7331                                 if (*p++ != ']')
7332                                         return 0;
7333                                 info->modifiers = g_list_append (info->modifiers, GUINT_TO_POINTER (rank));
7334                         } else {
7335                                 if (rank) /* generic args after array spec*/ //XXX test
7336                                         return 0;
7337                                 info->type_arguments = g_ptr_array_new ();
7338                                 while (*p) {
7339                                         MonoTypeNameParse *subinfo = g_new0 (MonoTypeNameParse, 1);
7340                                         gboolean fqname = FALSE;
7341
7342                                         g_ptr_array_add (info->type_arguments, subinfo);
7343
7344                                         if (*p == '[') {
7345                                                 p++;
7346                                                 fqname = TRUE;
7347                                         }
7348
7349                                         if (!_mono_reflection_parse_type (p, &p, TRUE, subinfo))
7350                                                 return 0;
7351
7352                                         /*MS is lenient on [] delimited parameters that aren't fqn - and F# uses them.*/
7353                                         if (fqname && (*p != ']')) {
7354                                                 char *aname;
7355
7356                                                 if (*p != ',')
7357                                                         return 0;
7358                                                 *p++ = 0;
7359
7360                                                 aname = p;
7361                                                 while (*p && (*p != ']'))
7362                                                         p++;
7363
7364                                                 if (*p != ']')
7365                                                         return 0;
7366
7367                                                 *p++ = 0;
7368                                                 while (*aname) {
7369                                                         if (g_ascii_isspace (*aname)) {
7370                                                                 ++aname;
7371                                                                 continue;
7372                                                         }
7373                                                         break;
7374                                                 }
7375                                                 if (!*aname ||
7376                                                     !assembly_name_to_aname (&subinfo->assembly, aname))
7377                                                         return 0;
7378                                         } else if (fqname && (*p == ']')) {
7379                                                 *p++ = 0;
7380                                         }
7381                                         if (*p == ']') {
7382                                                 *p++ = 0;
7383                                                 break;
7384                                         } else if (!*p) {
7385                                                 return 0;
7386                                         }
7387                                         *p++ = 0;
7388                                 }
7389                         }
7390                         break;
7391                 case ']':
7392                         if (is_recursed)
7393                                 goto end;
7394                         return 0;
7395                 case ',':
7396                         if (is_recursed)
7397                                 goto end;
7398                         *p++ = 0;
7399                         while (*p) {
7400                                 if (g_ascii_isspace (*p)) {
7401                                         ++p;
7402                                         continue;
7403                                 }
7404                                 break;
7405                         }
7406                         if (!*p)
7407                                 return 0; /* missing assembly name */
7408                         if (!assembly_name_to_aname (&info->assembly, p))
7409                                 return 0;
7410                         break;
7411                 default:
7412                         return 0;
7413                 }
7414                 if (info->assembly.name)
7415                         break;
7416         }
7417         // *w = 0; /* terminate class name */
7418  end:
7419         if (!info->name || !*info->name)
7420                 return 0;
7421         if (endptr)
7422                 *endptr = p;
7423         /* add other consistency checks */
7424         return 1;
7425 }
7426
7427 int
7428 mono_reflection_parse_type (char *name, MonoTypeNameParse *info)
7429 {
7430         return _mono_reflection_parse_type (name, NULL, FALSE, info);
7431 }
7432
7433 static MonoType*
7434 _mono_reflection_get_type_from_info (MonoTypeNameParse *info, MonoImage *image, gboolean ignorecase)
7435 {
7436         gboolean type_resolve = FALSE;
7437         MonoType *type;
7438         MonoImage *rootimage = image;
7439
7440         if (info->assembly.name) {
7441                 MonoAssembly *assembly = mono_assembly_loaded (&info->assembly);
7442                 if (!assembly && image && image->assembly && mono_assembly_names_equal (&info->assembly, &image->assembly->aname))
7443                         /* 
7444                          * This could happen in the AOT compiler case when the search hook is not
7445                          * installed.
7446                          */
7447                         assembly = image->assembly;
7448                 if (!assembly) {
7449                         /* then we must load the assembly ourselve - see #60439 */
7450                         assembly = mono_assembly_load (&info->assembly, NULL, NULL);
7451                         if (!assembly)
7452                                 return NULL;
7453                 }
7454                 image = assembly->image;
7455         } else if (!image) {
7456                 image = mono_defaults.corlib;
7457         }
7458
7459         type = mono_reflection_get_type_with_rootimage (rootimage, image, info, ignorecase, &type_resolve);
7460         if (type == NULL && !info->assembly.name && image != mono_defaults.corlib) {
7461                 image = mono_defaults.corlib;
7462                 type = mono_reflection_get_type_with_rootimage (rootimage, image, info, ignorecase, &type_resolve);
7463         }
7464
7465         return type;
7466 }
7467
7468 static MonoType*
7469 mono_reflection_get_type_internal (MonoImage *rootimage, MonoImage* image, MonoTypeNameParse *info, gboolean ignorecase)
7470 {
7471         MonoClass *klass;
7472         GList *mod;
7473         int modval;
7474         gboolean bounded = FALSE;
7475         
7476         if (!image)
7477                 image = mono_defaults.corlib;
7478
7479         if (ignorecase)
7480                 klass = mono_class_from_name_case (image, info->name_space, info->name);
7481         else
7482                 klass = mono_class_from_name (image, info->name_space, info->name);
7483         if (!klass)
7484                 return NULL;
7485         for (mod = info->nested; mod; mod = mod->next) {
7486                 gpointer iter = NULL;
7487                 MonoClass *parent;
7488
7489                 parent = klass;
7490                 mono_class_init (parent);
7491
7492                 while ((klass = mono_class_get_nested_types (parent, &iter))) {
7493                         if (ignorecase) {
7494                                 if (mono_utf8_strcasecmp (klass->name, mod->data) == 0)
7495                                         break;
7496                         } else {
7497                                 if (strcmp (klass->name, mod->data) == 0)
7498                                         break;
7499                         }
7500                 }
7501                 if (!klass)
7502                         break;
7503         }
7504         if (!klass)
7505                 return NULL;
7506
7507         if (info->type_arguments) {
7508                 MonoType **type_args = g_new0 (MonoType *, info->type_arguments->len);
7509                 MonoReflectionType *the_type;
7510                 MonoType *instance;
7511                 int i;
7512
7513                 for (i = 0; i < info->type_arguments->len; i++) {
7514                         MonoTypeNameParse *subinfo = g_ptr_array_index (info->type_arguments, i);
7515
7516                         type_args [i] = _mono_reflection_get_type_from_info (subinfo, rootimage, ignorecase);
7517                         if (!type_args [i]) {
7518                                 g_free (type_args);
7519                                 return NULL;
7520                         }
7521                 }
7522
7523                 the_type = mono_type_get_object (mono_domain_get (), &klass->byval_arg);
7524
7525                 instance = mono_reflection_bind_generic_parameters (
7526                         the_type, info->type_arguments->len, type_args);
7527
7528                 g_free (type_args);
7529                 if (!instance)
7530                         return NULL;
7531
7532                 klass = mono_class_from_mono_type (instance);
7533         }
7534
7535         for (mod = info->modifiers; mod; mod = mod->next) {
7536                 modval = GPOINTER_TO_UINT (mod->data);
7537                 if (!modval) { /* byref: must be last modifier */
7538                         return &klass->this_arg;
7539                 } else if (modval == -1) {
7540                         klass = mono_ptr_class_get (&klass->byval_arg);
7541                 } else if (modval == -2) {
7542                         bounded = TRUE;
7543                 } else { /* array rank */
7544                         klass = mono_bounded_array_class_get (klass, modval, bounded);
7545                 }
7546         }
7547
7548         return &klass->byval_arg;
7549 }
7550
7551 /*
7552  * mono_reflection_get_type:
7553  * @image: a metadata context
7554  * @info: type description structure
7555  * @ignorecase: flag for case-insensitive string compares
7556  * @type_resolve: whenever type resolve was already tried
7557  *
7558  * Build a MonoType from the type description in @info.
7559  * 
7560  */
7561
7562 MonoType*
7563 mono_reflection_get_type (MonoImage* image, MonoTypeNameParse *info, gboolean ignorecase, gboolean *type_resolve) {
7564         return mono_reflection_get_type_with_rootimage(image, image, info, ignorecase, type_resolve);
7565 }
7566
7567 static MonoType*
7568 mono_reflection_get_type_internal_dynamic (MonoImage *rootimage, MonoAssembly *assembly, MonoTypeNameParse *info, gboolean ignorecase)
7569 {
7570         MonoReflectionAssemblyBuilder *abuilder;
7571         MonoType *type;
7572         int i;
7573
7574         g_assert (assembly->dynamic);
7575         abuilder = (MonoReflectionAssemblyBuilder*)mono_assembly_get_object (((MonoDynamicAssembly*)assembly)->domain, assembly);
7576
7577         /* Enumerate all modules */
7578
7579         type = NULL;
7580         if (abuilder->modules) {
7581                 for (i = 0; i < mono_array_length (abuilder->modules); ++i) {
7582                         MonoReflectionModuleBuilder *mb = mono_array_get (abuilder->modules, MonoReflectionModuleBuilder*, i);
7583                         type = mono_reflection_get_type_internal (rootimage, &mb->dynamic_image->image, info, ignorecase);
7584                         if (type)
7585                                 break;
7586                 }
7587         }
7588
7589         if (!type && abuilder->loaded_modules) {
7590                 for (i = 0; i < mono_array_length (abuilder->loaded_modules); ++i) {
7591                         MonoReflectionModule *mod = mono_array_get (abuilder->loaded_modules, MonoReflectionModule*, i);
7592                         type = mono_reflection_get_type_internal (rootimage, mod->image, info, ignorecase);
7593                         if (type)
7594                                 break;
7595                 }
7596         }
7597
7598         return type;
7599 }
7600         
7601 MonoType*
7602 mono_reflection_get_type_with_rootimage (MonoImage *rootimage, MonoImage* image, MonoTypeNameParse *info, gboolean ignorecase, gboolean *type_resolve)
7603 {
7604         MonoType *type;
7605         MonoReflectionAssembly *assembly;
7606         GString *fullName;
7607         GList *mod;
7608
7609         if (image && image->dynamic)
7610                 type = mono_reflection_get_type_internal_dynamic (rootimage, image->assembly, info, ignorecase);
7611         else
7612                 type = mono_reflection_get_type_internal (rootimage, image, info, ignorecase);
7613         if (type)
7614                 return type;
7615         if (!mono_domain_has_type_resolve (mono_domain_get ()))
7616                 return NULL;
7617
7618         if (type_resolve) {
7619                 if (*type_resolve) 
7620                         return NULL;
7621                 else
7622                         *type_resolve = TRUE;
7623         }
7624         
7625         /* Reconstruct the type name */
7626         fullName = g_string_new ("");
7627         if (info->name_space && (info->name_space [0] != '\0'))
7628                 g_string_printf (fullName, "%s.%s", info->name_space, info->name);
7629         else
7630                 g_string_printf (fullName, "%s", info->name);
7631         for (mod = info->nested; mod; mod = mod->next)
7632                 g_string_append_printf (fullName, "+%s", (char*)mod->data);
7633
7634         assembly = mono_domain_try_type_resolve ( mono_domain_get (), fullName->str, NULL);
7635         if (assembly) {
7636                 if (assembly->assembly->dynamic)
7637                         type = mono_reflection_get_type_internal_dynamic (rootimage, assembly->assembly, info, ignorecase);
7638                 else
7639                         type = mono_reflection_get_type_internal (rootimage, assembly->assembly->image, 
7640                                                                                                           info, ignorecase);
7641         }
7642         g_string_free (fullName, TRUE);
7643         return type;
7644 }
7645
7646 void
7647 mono_reflection_free_type_info (MonoTypeNameParse *info)
7648 {
7649         g_list_free (info->modifiers);
7650         g_list_free (info->nested);
7651
7652         if (info->type_arguments) {
7653                 int i;
7654
7655                 for (i = 0; i < info->type_arguments->len; i++) {
7656                         MonoTypeNameParse *subinfo = g_ptr_array_index (info->type_arguments, i);
7657
7658                         mono_reflection_free_type_info (subinfo);
7659                         /*We free the subinfo since it is allocated by _mono_reflection_parse_type*/
7660                         g_free (subinfo);
7661                 }
7662
7663                 g_ptr_array_free (info->type_arguments, TRUE);
7664         }
7665 }
7666
7667 /*
7668  * mono_reflection_type_from_name:
7669  * @name: type name.
7670  * @image: a metadata context (can be NULL).
7671  *
7672  * Retrieves a MonoType from its @name. If the name is not fully qualified,
7673  * it defaults to get the type from @image or, if @image is NULL or loading
7674  * from it fails, uses corlib.
7675  * 
7676  */
7677 MonoType*
7678 mono_reflection_type_from_name (char *name, MonoImage *image)
7679 {
7680         MonoType *type = NULL;
7681         MonoTypeNameParse info;
7682         char *tmp;
7683
7684         /* Make a copy since parse_type modifies its argument */
7685         tmp = g_strdup (name);
7686         
7687         /*g_print ("requested type %s\n", str);*/
7688         if (mono_reflection_parse_type (tmp, &info)) {
7689                 type = _mono_reflection_get_type_from_info (&info, image, FALSE);
7690         }
7691
7692         g_free (tmp);
7693         mono_reflection_free_type_info (&info);
7694         return type;
7695 }
7696
7697 /*
7698  * mono_reflection_get_token:
7699  *
7700  *   Return the metadata token of OBJ which should be an object
7701  * representing a metadata element.
7702  */
7703 guint32
7704 mono_reflection_get_token (MonoObject *obj)
7705 {
7706         MonoClass *klass;
7707         guint32 token = 0;
7708
7709         klass = obj->vtable->klass;
7710
7711         if (strcmp (klass->name, "MethodBuilder") == 0) {
7712                 MonoReflectionMethodBuilder *mb = (MonoReflectionMethodBuilder *)obj;
7713
7714                 token = mb->table_idx | MONO_TOKEN_METHOD_DEF;
7715         } else if (strcmp (klass->name, "ConstructorBuilder") == 0) {
7716                 MonoReflectionCtorBuilder *mb = (MonoReflectionCtorBuilder *)obj;
7717
7718                 token = mb->table_idx | MONO_TOKEN_METHOD_DEF;
7719         } else if (strcmp (klass->name, "FieldBuilder") == 0) {
7720                 MonoReflectionFieldBuilder *fb = (MonoReflectionFieldBuilder *)obj;
7721
7722                 token = fb->table_idx | MONO_TOKEN_FIELD_DEF;
7723         } else if (strcmp (klass->name, "TypeBuilder") == 0) {
7724                 MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder *)obj;
7725                 token = tb->table_idx | MONO_TOKEN_TYPE_DEF;
7726         } else if (strcmp (klass->name, "MonoType") == 0) {
7727                 MonoType *type = mono_reflection_type_get_handle ((MonoReflectionType*)obj);
7728                 MonoClass *mc = mono_class_from_mono_type (type);
7729                 if (!mono_class_init (mc))
7730                         mono_raise_exception (mono_class_get_exception_for_failure (mc));
7731
7732                 token = mc->type_token;
7733         } else if (strcmp (klass->name, "MonoCMethod") == 0 ||
7734                    strcmp (klass->name, "MonoMethod") == 0 ||
7735                    strcmp (klass->name, "MonoGenericMethod") == 0 ||
7736                    strcmp (klass->name, "MonoGenericCMethod") == 0) {
7737                 MonoReflectionMethod *m = (MonoReflectionMethod *)obj;
7738                 if (m->method->is_inflated) {
7739                         MonoMethodInflated *inflated = (MonoMethodInflated *) m->method;
7740                         return inflated->declaring->token;
7741                 } else {
7742                         token = m->method->token;
7743                 }
7744         } else if (strcmp (klass->name, "MonoField") == 0) {
7745                 MonoReflectionField *f = (MonoReflectionField*)obj;
7746
7747                 if (is_field_on_inst (f->field)) {
7748                         MonoDynamicGenericClass *dgclass = (MonoDynamicGenericClass*)f->field->parent->generic_class;
7749                         int field_index = f->field - dgclass->fields;
7750                         MonoObject *obj;
7751
7752                         g_assert (field_index >= 0 && field_index < dgclass->count_fields);
7753                         obj = dgclass->field_objects [field_index];
7754                         return mono_reflection_get_token (obj);
7755                 }
7756                 token = mono_class_get_field_token (f->field);
7757         } else if (strcmp (klass->name, "MonoProperty") == 0) {
7758                 MonoReflectionProperty *p = (MonoReflectionProperty*)obj;
7759
7760                 token = mono_class_get_property_token (p->property);
7761         } else if (strcmp (klass->name, "MonoEvent") == 0) {
7762                 MonoReflectionMonoEvent *p = (MonoReflectionMonoEvent*)obj;
7763
7764                 token = mono_class_get_event_token (p->event);
7765         } else if (strcmp (klass->name, "ParameterInfo") == 0 || strcmp (klass->name, "MonoParameterInfo") == 0) {
7766                 MonoReflectionParameter *p = (MonoReflectionParameter*)obj;
7767                 MonoClass *member_class = mono_object_class (p->MemberImpl);
7768                 g_assert (mono_class_is_reflection_method_or_constructor (member_class));
7769
7770                 token = mono_method_get_param_token (((MonoReflectionMethod*)p->MemberImpl)->method, p->PositionImpl);
7771         } else if (strcmp (klass->name, "Module") == 0 || strcmp (klass->name, "MonoModule") == 0) {
7772                 MonoReflectionModule *m = (MonoReflectionModule*)obj;
7773
7774                 token = m->token;
7775         } else if (strcmp (klass->name, "Assembly") == 0 || strcmp (klass->name, "MonoAssembly") == 0) {
7776                 token = mono_metadata_make_token (MONO_TABLE_ASSEMBLY, 1);
7777         } else {
7778                 gchar *msg = g_strdup_printf ("MetadataToken is not supported for type '%s.%s'", klass->name_space, klass->name);
7779                 MonoException *ex = mono_get_exception_not_implemented (msg);
7780                 g_free (msg);
7781                 mono_raise_exception (ex);
7782         }
7783
7784         return token;
7785 }
7786
7787 static MonoClass*
7788 load_cattr_enum_type (MonoImage *image, const char *p, const char **end)
7789 {
7790         char *n;
7791         MonoType *t;
7792         int slen = mono_metadata_decode_value (p, &p);
7793         n = g_memdup (p, slen + 1);
7794         n [slen] = 0;
7795         t = mono_reflection_type_from_name (n, image);
7796         if (!t)
7797                 g_error ("Cannot load type '%s'", n);
7798         g_free (n);
7799         p += slen;
7800         *end = p;
7801         return mono_class_from_mono_type (t);
7802 }
7803
7804 static void*
7805 load_cattr_value (MonoImage *image, MonoType *t, const char *p, const char **end)
7806 {
7807         int slen, type = t->type;
7808         MonoClass *tklass = t->data.klass;
7809
7810 handle_enum:
7811         switch (type) {
7812         case MONO_TYPE_U1:
7813         case MONO_TYPE_I1:
7814         case MONO_TYPE_BOOLEAN: {
7815                 MonoBoolean *bval = g_malloc (sizeof (MonoBoolean));
7816                 *bval = *p;
7817                 *end = p + 1;
7818                 return bval;
7819         }
7820         case MONO_TYPE_CHAR:
7821         case MONO_TYPE_U2:
7822         case MONO_TYPE_I2: {
7823                 guint16 *val = g_malloc (sizeof (guint16));
7824                 *val = read16 (p);
7825                 *end = p + 2;
7826                 return val;
7827         }
7828 #if SIZEOF_VOID_P == 4
7829         case MONO_TYPE_U:
7830         case MONO_TYPE_I:
7831 #endif
7832         case MONO_TYPE_R4:
7833         case MONO_TYPE_U4:
7834         case MONO_TYPE_I4: {
7835                 guint32 *val = g_malloc (sizeof (guint32));
7836                 *val = read32 (p);
7837                 *end = p + 4;
7838                 return val;
7839         }
7840 #if SIZEOF_VOID_P == 8
7841         case MONO_TYPE_U: /* error out instead? this should probably not happen */
7842         case MONO_TYPE_I:
7843 #endif
7844         case MONO_TYPE_U8:
7845         case MONO_TYPE_I8: {
7846                 guint64 *val = g_malloc (sizeof (guint64));
7847                 *val = read64 (p);
7848                 *end = p + 8;
7849                 return val;
7850         }
7851         case MONO_TYPE_R8: {
7852                 double *val = g_malloc (sizeof (double));
7853                 readr8 (p, val);
7854                 *end = p + 8;
7855                 return val;
7856         }
7857         case MONO_TYPE_VALUETYPE:
7858                 if (t->data.klass->enumtype) {
7859                         type = mono_class_enum_basetype (t->data.klass)->type;
7860                         goto handle_enum;
7861                 } else {
7862                         MonoClass *k =  t->data.klass;
7863                         
7864                         if (mono_is_corlib_image (k->image) && strcmp (k->name_space, "System") == 0 && strcmp (k->name, "DateTime") == 0){
7865                                 guint64 *val = g_malloc (sizeof (guint64));
7866                                 *val = read64 (p);
7867                                 *end = p + 8;
7868                                 return val;
7869                         }
7870                 }
7871                 g_error ("generic valutype %s not handled in custom attr value decoding", t->data.klass->name);
7872                 break;
7873                 
7874         case MONO_TYPE_STRING:
7875                 if (*p == (char)0xFF) {
7876                         *end = p + 1;
7877                         return NULL;
7878                 }
7879                 slen = mono_metadata_decode_value (p, &p);
7880                 *end = p + slen;
7881                 return mono_string_new_len (mono_domain_get (), p, slen);
7882         case MONO_TYPE_CLASS: {
7883                 char *n;
7884                 MonoType *t;
7885                 if (*p == (char)0xFF) {
7886                         *end = p + 1;
7887                         return NULL;
7888                 }
7889 handle_type:
7890                 slen = mono_metadata_decode_value (p, &p);
7891                 n = g_memdup (p, slen + 1);
7892                 n [slen] = 0;
7893                 t = mono_reflection_type_from_name (n, image);
7894                 if (!t)
7895                         g_warning ("Cannot load type '%s'", n);
7896                 g_free (n);
7897                 *end = p + slen;
7898                 if (t)
7899                         return mono_type_get_object (mono_domain_get (), t);
7900                 else
7901                         return NULL;
7902         }
7903         case MONO_TYPE_OBJECT: {
7904                 char subt = *p++;
7905                 MonoObject *obj;
7906                 MonoClass *subc = NULL;
7907                 void *val;
7908
7909                 if (subt == 0x50) {
7910                         goto handle_type;
7911                 } else if (subt == 0x0E) {
7912                         type = MONO_TYPE_STRING;
7913                         goto handle_enum;
7914                 } else if (subt == 0x1D) {
7915                         MonoType simple_type = {{0}};
7916                         int etype = *p;
7917                         p ++;
7918
7919                         type = MONO_TYPE_SZARRAY;
7920                         if (etype == 0x50) {
7921                                 tklass = mono_defaults.systemtype_class;
7922                         } else if (etype == 0x55) {
7923                                 tklass = load_cattr_enum_type (image, p, &p);
7924                         } else {
7925                                 if (etype == 0x51)
7926                                         /* See Partition II, Appendix B3 */
7927                                         etype = MONO_TYPE_OBJECT;
7928                                 simple_type.type = etype;
7929                                 tklass = mono_class_from_mono_type (&simple_type);
7930                         }
7931                         goto handle_enum;
7932                 } else if (subt == 0x55) {
7933                         char *n;
7934                         MonoType *t;
7935                         slen = mono_metadata_decode_value (p, &p);
7936                         n = g_memdup (p, slen + 1);
7937                         n [slen] = 0;
7938                         t = mono_reflection_type_from_name (n, image);
7939                         if (!t)
7940                                 g_error ("Cannot load type '%s'", n);
7941                         g_free (n);
7942                         p += slen;
7943                         subc = mono_class_from_mono_type (t);
7944                 } else if (subt >= MONO_TYPE_BOOLEAN && subt <= MONO_TYPE_R8) {
7945                         MonoType simple_type = {{0}};
7946                         simple_type.type = subt;
7947                         subc = mono_class_from_mono_type (&simple_type);
7948                 } else {
7949                         g_error ("Unknown type 0x%02x for object type encoding in custom attr", subt);
7950                 }
7951                 val = load_cattr_value (image, &subc->byval_arg, p, end);
7952                 obj = mono_object_new (mono_domain_get (), subc);
7953                 g_assert (!subc->has_references);
7954                 mono_gc_memmove ((char*)obj + sizeof (MonoObject), val, mono_class_value_size (subc, NULL));
7955                 g_free (val);
7956                 return obj;
7957         }
7958         case MONO_TYPE_SZARRAY: {
7959                 MonoArray *arr;
7960                 guint32 i, alen, basetype;
7961                 alen = read32 (p);
7962                 p += 4;
7963                 if (alen == 0xffffffff) {
7964                         *end = p;
7965                         return NULL;
7966                 }
7967                 arr = mono_array_new (mono_domain_get(), tklass, alen);
7968                 basetype = tklass->byval_arg.type;
7969                 if (basetype == MONO_TYPE_VALUETYPE && tklass->enumtype)
7970                         basetype = mono_class_enum_basetype (tklass)->type;
7971                 switch (basetype)
7972                 {
7973                         case MONO_TYPE_U1:
7974                         case MONO_TYPE_I1:
7975                         case MONO_TYPE_BOOLEAN:
7976                                 for (i = 0; i < alen; i++) {
7977                                         MonoBoolean val = *p++;
7978                                         mono_array_set (arr, MonoBoolean, i, val);
7979                                 }
7980                                 break;
7981                         case MONO_TYPE_CHAR:
7982                         case MONO_TYPE_U2:
7983                         case MONO_TYPE_I2:
7984                                 for (i = 0; i < alen; i++) {
7985                                         guint16 val = read16 (p);
7986                                         mono_array_set (arr, guint16, i, val);
7987                                         p += 2;
7988                                 }
7989                                 break;
7990                         case MONO_TYPE_R4:
7991                         case MONO_TYPE_U4:
7992                         case MONO_TYPE_I4:
7993                                 for (i = 0; i < alen; i++) {
7994                                         guint32 val = read32 (p);
7995                                         mono_array_set (arr, guint32, i, val);
7996                                         p += 4;
7997                                 }
7998                                 break;
7999                         case MONO_TYPE_R8:
8000                                 for (i = 0; i < alen; i++) {
8001                                         double val;
8002                                         readr8 (p, &val);
8003                                         mono_array_set (arr, double, i, val);
8004                                         p += 8;
8005                                 }
8006                                 break;
8007                         case MONO_TYPE_U8:
8008                         case MONO_TYPE_I8:
8009                                 for (i = 0; i < alen; i++) {
8010                                         guint64 val = read64 (p);
8011                                         mono_array_set (arr, guint64, i, val);
8012                                         p += 8;
8013                                 }
8014                                 break;
8015                         case MONO_TYPE_CLASS:
8016                         case MONO_TYPE_OBJECT:
8017                         case MONO_TYPE_STRING:
8018                                 for (i = 0; i < alen; i++) {
8019                                         MonoObject *item = load_cattr_value (image, &tklass->byval_arg, p, &p);
8020                                         mono_array_setref (arr, i, item);
8021                                 }
8022                                 break;
8023                         default:
8024                                 g_error ("Type 0x%02x not handled in custom attr array decoding", basetype);
8025                 }
8026                 *end=p;
8027                 return arr;
8028         }
8029         default:
8030                 g_error ("Type 0x%02x not handled in custom attr value decoding", type);
8031         }
8032         return NULL;
8033 }
8034
8035 static MonoObject*
8036 create_cattr_typed_arg (MonoType *t, MonoObject *val)
8037 {
8038         static MonoClass *klass;
8039         static MonoMethod *ctor;
8040         MonoObject *retval;
8041         void *params [2], *unboxed;
8042
8043         if (!klass)
8044                 klass = mono_class_from_name (mono_defaults.corlib, "System.Reflection", "CustomAttributeTypedArgument");
8045         if (!ctor)
8046                 ctor = mono_class_get_method_from_name (klass, ".ctor", 2);
8047         
8048         params [0] = mono_type_get_object (mono_domain_get (), t);
8049         params [1] = val;
8050         retval = mono_object_new (mono_domain_get (), klass);
8051         unboxed = mono_object_unbox (retval);
8052         mono_runtime_invoke (ctor, unboxed, params, NULL);
8053
8054         return retval;
8055 }
8056
8057 static MonoObject*
8058 create_cattr_named_arg (void *minfo, MonoObject *typedarg)
8059 {
8060         static MonoClass *klass;
8061         static MonoMethod *ctor;
8062         MonoObject *retval;
8063         void *unboxed, *params [2];
8064
8065         if (!klass)
8066                 klass = mono_class_from_name (mono_defaults.corlib, "System.Reflection", "CustomAttributeNamedArgument");
8067         if (!ctor)
8068                 ctor = mono_class_get_method_from_name (klass, ".ctor", 2);
8069
8070         params [0] = minfo;
8071         params [1] = typedarg;
8072         retval = mono_object_new (mono_domain_get (), klass);
8073         unboxed = mono_object_unbox (retval);
8074         mono_runtime_invoke (ctor, unboxed, params, NULL);
8075
8076         return retval;
8077 }
8078
8079 static gboolean
8080 type_is_reference (MonoType *type)
8081 {
8082         switch (type->type) {
8083         case MONO_TYPE_BOOLEAN:
8084         case MONO_TYPE_CHAR:
8085         case MONO_TYPE_U:
8086         case MONO_TYPE_I:
8087         case MONO_TYPE_U1:
8088         case MONO_TYPE_I1:
8089         case MONO_TYPE_U2:
8090         case MONO_TYPE_I2:
8091         case MONO_TYPE_U4:
8092         case MONO_TYPE_I4:
8093         case MONO_TYPE_U8:
8094         case MONO_TYPE_I8:
8095         case MONO_TYPE_R8:
8096         case MONO_TYPE_R4:
8097         case MONO_TYPE_VALUETYPE:
8098                 return FALSE;
8099         default:
8100                 return TRUE;
8101         }
8102 }
8103
8104 static void
8105 free_param_data (MonoMethodSignature *sig, void **params) {
8106         int i;
8107         for (i = 0; i < sig->param_count; ++i) {
8108                 if (!type_is_reference (sig->params [i]))
8109                         g_free (params [i]);
8110         }
8111 }
8112
8113 /*
8114  * Find the field index in the metadata FieldDef table.
8115  */
8116 static guint32
8117 find_field_index (MonoClass *klass, MonoClassField *field) {
8118         int i;
8119
8120         for (i = 0; i < klass->field.count; ++i) {
8121                 if (field == &klass->fields [i])
8122                         return klass->field.first + 1 + i;
8123         }
8124         return 0;
8125 }
8126
8127 /*
8128  * Find the property index in the metadata Property table.
8129  */
8130 static guint32
8131 find_property_index (MonoClass *klass, MonoProperty *property) {
8132         int i;
8133
8134         for (i = 0; i < klass->ext->property.count; ++i) {
8135                 if (property == &klass->ext->properties [i])
8136                         return klass->ext->property.first + 1 + i;
8137         }
8138         return 0;
8139 }
8140
8141 /*
8142  * Find the event index in the metadata Event table.
8143  */
8144 static guint32
8145 find_event_index (MonoClass *klass, MonoEvent *event) {
8146         int i;
8147
8148         for (i = 0; i < klass->ext->event.count; ++i) {
8149                 if (event == &klass->ext->events [i])
8150                         return klass->ext->event.first + 1 + i;
8151         }
8152         return 0;
8153 }
8154
8155 static MonoObject*
8156 create_custom_attr (MonoImage *image, MonoMethod *method, const guchar *data, guint32 len, MonoError *error)
8157 {
8158         const char *p = (const char*)data;
8159         const char *named;
8160         guint32 i, j, num_named;
8161         MonoObject *attr;
8162         void *params_buf [32];
8163         void **params;
8164         MonoMethodSignature *sig;
8165
8166         mono_error_init (error);
8167
8168         mono_class_init (method->klass);
8169
8170         if (!mono_verifier_verify_cattr_content (image, method, data, len, NULL)) {
8171                 mono_error_set_generic_error (error, "System.Reflection", "CustomAttributeFormatException", "Binary format of the specified custom attribute was invalid.");
8172                 return NULL;
8173         }
8174
8175         if (len == 0) {
8176                 attr = mono_object_new (mono_domain_get (), method->klass);
8177                 mono_runtime_invoke (method, attr, NULL, NULL);
8178                 return attr;
8179         }
8180
8181         if (len < 2 || read16 (p) != 0x0001) /* Prolog */
8182                 return NULL;
8183
8184         /*g_print ("got attr %s\n", method->klass->name);*/
8185
8186         sig = mono_method_signature (method);
8187         if (sig->param_count < 32)
8188                 params = params_buf;
8189         else
8190                 /* Allocate using GC so it gets GC tracking */
8191                 params = mono_gc_alloc_fixed (sig->param_count * sizeof (void*), NULL);
8192
8193         /* skip prolog */
8194         p += 2;
8195         for (i = 0; i < mono_method_signature (method)->param_count; ++i) {
8196                 params [i] = load_cattr_value (image, mono_method_signature (method)->params [i], p, &p);
8197         }
8198
8199         named = p;
8200         attr = mono_object_new (mono_domain_get (), method->klass);
8201         mono_runtime_invoke (method, attr, params, NULL);
8202         free_param_data (method->signature, params);
8203         num_named = read16 (named);
8204         named += 2;
8205         for (j = 0; j < num_named; j++) {
8206                 gint name_len;
8207                 char *name, named_type, data_type;
8208                 named_type = *named++;
8209                 data_type = *named++; /* type of data */
8210                 if (data_type == MONO_TYPE_SZARRAY)
8211                         data_type = *named++;
8212                 if (data_type == MONO_TYPE_ENUM) {
8213                         gint type_len;
8214                         char *type_name;
8215                         type_len = mono_metadata_decode_blob_size (named, &named);
8216                         type_name = g_malloc (type_len + 1);
8217                         memcpy (type_name, named, type_len);
8218                         type_name [type_len] = 0;
8219                         named += type_len;
8220                         /* FIXME: lookup the type and check type consistency */
8221                         g_free (type_name);
8222                 }
8223                 name_len = mono_metadata_decode_blob_size (named, &named);
8224                 name = g_malloc (name_len + 1);
8225                 memcpy (name, named, name_len);
8226                 name [name_len] = 0;
8227                 named += name_len;
8228                 if (named_type == 0x53) {
8229                         MonoClassField *field = mono_class_get_field_from_name (mono_object_class (attr), name);
8230                         void *val = load_cattr_value (image, field->type, named, &named);
8231                         mono_field_set_value (attr, field, val);
8232                         if (!type_is_reference (field->type))
8233                                 g_free (val);
8234                 } else if (named_type == 0x54) {
8235                         MonoProperty *prop;
8236                         void *pparams [1];
8237                         MonoType *prop_type;
8238
8239                         prop = mono_class_get_property_from_name (mono_object_class (attr), name);
8240                         /* can we have more that 1 arg in a custom attr named property? */
8241                         prop_type = prop->get? mono_method_signature (prop->get)->ret :
8242                              mono_method_signature (prop->set)->params [mono_method_signature (prop->set)->param_count - 1];
8243                         pparams [0] = load_cattr_value (image, prop_type, named, &named);
8244                         mono_property_set_value (prop, attr, pparams, NULL);
8245                         if (!type_is_reference (prop_type))
8246                                 g_free (pparams [0]);
8247                 }
8248                 g_free (name);
8249         }
8250
8251         if (params != params_buf)
8252                 mono_gc_free_fixed (params);
8253
8254         return attr;
8255 }
8256         
8257 /*
8258  * mono_reflection_create_custom_attr_data_args:
8259  *
8260  *   Create an array of typed and named arguments from the cattr blob given by DATA.
8261  * TYPED_ARGS and NAMED_ARGS will contain the objects representing the arguments,
8262  * NAMED_ARG_INFO will contain information about the named arguments.
8263  */
8264 void
8265 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)
8266 {
8267         MonoArray *typedargs, *namedargs;
8268         MonoClass *attrklass;
8269         MonoDomain *domain;
8270         const char *p = (const char*)data;
8271         const char *named;
8272         guint32 i, j, num_named;
8273         CattrNamedArg *arginfo = NULL;
8274
8275         *typed_args = NULL;
8276         *named_args = NULL;
8277         *named_arg_info = NULL;
8278
8279         mono_error_init (error);
8280
8281         if (!mono_verifier_verify_cattr_content (image, method, data, len, NULL)) {
8282                 mono_error_set_generic_error (error, "System.Reflection", "CustomAttributeFormatException", "Binary format of the specified custom attribute was invalid.");
8283                 return;
8284         }
8285
8286         mono_class_init (method->klass);
8287         
8288         domain = mono_domain_get ();
8289
8290         if (len < 2 || read16 (p) != 0x0001) /* Prolog */
8291                 return;
8292
8293         typedargs = mono_array_new (domain, mono_get_object_class (), mono_method_signature (method)->param_count);
8294         
8295         /* skip prolog */
8296         p += 2;
8297         for (i = 0; i < mono_method_signature (method)->param_count; ++i) {
8298                 MonoObject *obj;
8299                 void *val;
8300
8301                 val = load_cattr_value (image, mono_method_signature (method)->params [i], p, &p);
8302                 obj = type_is_reference (mono_method_signature (method)->params [i]) ? 
8303                         val : mono_value_box (domain, mono_class_from_mono_type (mono_method_signature (method)->params [i]), val);
8304                 mono_array_setref (typedargs, i, obj);
8305
8306                 if (!type_is_reference (mono_method_signature (method)->params [i]))
8307                         g_free (val);
8308         }
8309
8310         named = p;
8311         num_named = read16 (named);
8312         namedargs = mono_array_new (domain, mono_get_object_class (), num_named);
8313         named += 2;
8314         attrklass = method->klass;
8315
8316         arginfo = g_new0 (CattrNamedArg, num_named);
8317         *named_arg_info = arginfo;
8318
8319         for (j = 0; j < num_named; j++) {
8320                 gint name_len;
8321                 char *name, named_type, data_type;
8322                 named_type = *named++;
8323                 data_type = *named++; /* type of data */
8324                 if (data_type == MONO_TYPE_SZARRAY)
8325                         data_type = *named++;
8326                 if (data_type == MONO_TYPE_ENUM) {
8327                         gint type_len;
8328                         char *type_name;
8329                         type_len = mono_metadata_decode_blob_size (named, &named);
8330                         if (ADDP_IS_GREATER_OR_OVF ((const guchar*)named, type_len, data + len))
8331                                 goto fail;
8332
8333                         type_name = g_malloc (type_len + 1);
8334                         memcpy (type_name, named, type_len);
8335                         type_name [type_len] = 0;
8336                         named += type_len;
8337                         /* FIXME: lookup the type and check type consistency */
8338                         g_free (type_name);
8339                 }
8340                 name_len = mono_metadata_decode_blob_size (named, &named);
8341                 if (ADDP_IS_GREATER_OR_OVF ((const guchar*)named, name_len, data + len))
8342                         goto fail;
8343                 name = g_malloc (name_len + 1);
8344                 memcpy (name, named, name_len);
8345                 name [name_len] = 0;
8346                 named += name_len;
8347                 if (named_type == 0x53) {
8348                         MonoObject *obj;
8349                         MonoClassField *field = mono_class_get_field_from_name (attrklass, name);
8350                         void *val;
8351
8352                         arginfo [j].type = field->type;
8353                         arginfo [j].field = field;
8354
8355                         val = load_cattr_value (image, field->type, named, &named);
8356                         obj = type_is_reference (field->type) ? val : mono_value_box (domain, mono_class_from_mono_type (field->type), val);
8357                         mono_array_setref (namedargs, j, obj);
8358                         if (!type_is_reference (field->type))
8359                                 g_free (val);
8360                 } else if (named_type == 0x54) {
8361                         MonoObject *obj;
8362                         MonoType *prop_type;
8363                         MonoProperty *prop = mono_class_get_property_from_name (attrklass, name);
8364                         void *val;
8365
8366                         prop_type = prop->get? mono_method_signature (prop->get)->ret :
8367                              mono_method_signature (prop->set)->params [mono_method_signature (prop->set)->param_count - 1];
8368
8369                         arginfo [j].type = prop_type;
8370                         arginfo [j].prop = prop;
8371
8372                         val = load_cattr_value (image, prop_type, named, &named);
8373                         obj = type_is_reference (prop_type) ? val : mono_value_box (domain, mono_class_from_mono_type (prop_type), val);
8374                         mono_array_setref (namedargs, j, obj);
8375                         if (!type_is_reference (prop_type))
8376                                 g_free (val);
8377                 }
8378                 g_free (name);
8379         }
8380
8381         *typed_args = typedargs;
8382         *named_args = namedargs;
8383         return;
8384 fail:
8385         mono_error_set_generic_error (error, "System.Reflection", "CustomAttributeFormatException", "Binary format of the specified custom attribute was invalid.");
8386         g_free (arginfo);
8387         *named_arg_info = NULL;
8388 }
8389
8390 void
8391 mono_reflection_resolve_custom_attribute_data (MonoReflectionMethod *ref_method, MonoReflectionAssembly *assembly, gpointer data, guint32 len, MonoArray **ctor_args, MonoArray **named_args)
8392 {
8393         MonoDomain *domain;
8394         MonoArray *typedargs, *namedargs;
8395         MonoImage *image;
8396         MonoMethod *method;
8397         CattrNamedArg *arginfo = NULL;
8398         MonoError error;
8399         int i;
8400
8401         *ctor_args = NULL;
8402         *named_args = NULL;
8403
8404         if (len == 0)
8405                 return;
8406
8407         image = assembly->assembly->image;
8408         method = ref_method->method;
8409         domain = mono_object_domain (ref_method);
8410
8411         if (!mono_class_init (method->klass))
8412                 mono_raise_exception (mono_class_get_exception_for_failure (method->klass));
8413
8414         mono_reflection_create_custom_attr_data_args (image, method, data, len, &typedargs, &namedargs, &arginfo, &error);
8415         if (!mono_error_ok (&error))
8416                 mono_error_raise_exception (&error);
8417         if (mono_loader_get_last_error ())
8418                 mono_raise_exception (mono_loader_error_prepare_exception (mono_loader_get_last_error ()));
8419
8420         if (!typedargs || !namedargs) {
8421                 g_free (arginfo);
8422                 return;
8423         }
8424
8425         for (i = 0; i < mono_method_signature (method)->param_count; ++i) {
8426                 MonoObject *obj = mono_array_get (typedargs, MonoObject*, i);
8427                 MonoObject *typedarg;
8428
8429                 typedarg = create_cattr_typed_arg (mono_method_signature (method)->params [i], obj);
8430                 mono_array_setref (typedargs, i, typedarg);
8431         }
8432
8433         for (i = 0; i < mono_array_length (namedargs); ++i) {
8434                 MonoObject *obj = mono_array_get (namedargs, MonoObject*, i);
8435                 MonoObject *typedarg, *namedarg, *minfo;
8436
8437                 if (arginfo [i].prop)
8438                         minfo = (MonoObject*)mono_property_get_object (domain, NULL, arginfo [i].prop);
8439                 else
8440                         minfo = (MonoObject*)mono_field_get_object (domain, NULL, arginfo [i].field);
8441
8442                 typedarg = create_cattr_typed_arg (arginfo [i].type, obj);
8443                 namedarg = create_cattr_named_arg (minfo, typedarg);
8444
8445                 mono_array_setref (namedargs, i, namedarg);
8446         }
8447
8448         *ctor_args = typedargs;
8449         *named_args = namedargs;
8450         g_free (arginfo);
8451 }
8452
8453 static MonoObject*
8454 create_custom_attr_data (MonoImage *image, MonoCustomAttrEntry *cattr)
8455 {
8456         static MonoMethod *ctor;
8457         MonoDomain *domain;
8458         MonoObject *attr;
8459         void *params [4];
8460
8461         g_assert (image->assembly);
8462
8463         if (!ctor)
8464                 ctor = mono_class_get_method_from_name (mono_defaults.customattribute_data_class, ".ctor", 4);
8465
8466         domain = mono_domain_get ();
8467         attr = mono_object_new (domain, mono_defaults.customattribute_data_class);
8468         params [0] = mono_method_get_object (domain, cattr->ctor, NULL);
8469         params [1] = mono_assembly_get_object (domain, image->assembly);
8470         params [2] = (gpointer)&cattr->data;
8471         params [3] = &cattr->data_size;
8472         mono_runtime_invoke (ctor, attr, params, NULL);
8473         return attr;
8474 }
8475
8476 static MonoArray*
8477 mono_custom_attrs_construct_by_type (MonoCustomAttrInfo *cinfo, MonoClass *attr_klass, MonoError *error)
8478 {
8479         MonoArray *result;
8480         MonoObject *attr;
8481         int i, n;
8482
8483         mono_error_init (error);
8484
8485         n = 0;
8486         for (i = 0; i < cinfo->num_attrs; ++i) {
8487                 if (!attr_klass || mono_class_is_assignable_from (attr_klass, cinfo->attrs [i].ctor->klass))
8488                         n ++;
8489         }
8490
8491         result = mono_array_new_cached (mono_domain_get (), mono_defaults.attribute_class, n);
8492         n = 0;
8493         for (i = 0; i < cinfo->num_attrs; ++i) {
8494                 if (!cinfo->attrs [i].ctor)
8495                         /* The cattr type is not finished yet */
8496                         /* We should include the type name but cinfo doesn't contain it */
8497                         mono_raise_exception (mono_get_exception_type_load (NULL, NULL));
8498                 if (!attr_klass || mono_class_is_assignable_from (attr_klass, cinfo->attrs [i].ctor->klass)) {
8499                         attr = create_custom_attr (cinfo->image, cinfo->attrs [i].ctor, cinfo->attrs [i].data, cinfo->attrs [i].data_size, error);
8500                         if (!mono_error_ok (error))
8501                                 return result;
8502                         mono_array_setref (result, n, attr);
8503                         n ++;
8504                 }
8505         }
8506         return result;
8507 }
8508
8509 MonoArray*
8510 mono_custom_attrs_construct (MonoCustomAttrInfo *cinfo)
8511 {
8512         MonoError error;
8513
8514         return mono_custom_attrs_construct_by_type (cinfo, NULL, &error);
8515 }
8516
8517 static MonoArray*
8518 mono_custom_attrs_data_construct (MonoCustomAttrInfo *cinfo)
8519 {
8520         MonoArray *result;
8521         MonoObject *attr;
8522         int i;
8523         
8524         result = mono_array_new (mono_domain_get (), mono_defaults.customattribute_data_class, cinfo->num_attrs);
8525         for (i = 0; i < cinfo->num_attrs; ++i) {
8526                 attr = create_custom_attr_data (cinfo->image, &cinfo->attrs [i]);
8527                 mono_array_setref (result, i, attr);
8528         }
8529         return result;
8530 }
8531
8532 /**
8533  * mono_custom_attrs_from_index:
8534  *
8535  * Returns: NULL if no attributes are found or if a loading error occurs.
8536  */
8537 MonoCustomAttrInfo*
8538 mono_custom_attrs_from_index (MonoImage *image, guint32 idx)
8539 {
8540         guint32 mtoken, i, len;
8541         guint32 cols [MONO_CUSTOM_ATTR_SIZE];
8542         MonoTableInfo *ca;
8543         MonoCustomAttrInfo *ainfo;
8544         GList *tmp, *list = NULL;
8545         const char *data;
8546
8547         ca = &image->tables [MONO_TABLE_CUSTOMATTRIBUTE];
8548
8549         i = mono_metadata_custom_attrs_from_index (image, idx);
8550         if (!i)
8551                 return NULL;
8552         i --;
8553         while (i < ca->rows) {
8554                 if (mono_metadata_decode_row_col (ca, i, MONO_CUSTOM_ATTR_PARENT) != idx)
8555                         break;
8556                 list = g_list_prepend (list, GUINT_TO_POINTER (i));
8557                 ++i;
8558         }
8559         len = g_list_length (list);
8560         if (!len)
8561                 return NULL;
8562         ainfo = g_malloc0 (MONO_SIZEOF_CUSTOM_ATTR_INFO + sizeof (MonoCustomAttrEntry) * len);
8563         ainfo->num_attrs = len;
8564         ainfo->image = image;
8565         for (i = 0, tmp = list; i < len; ++i, tmp = tmp->next) {
8566                 mono_metadata_decode_row (ca, GPOINTER_TO_UINT (tmp->data), cols, MONO_CUSTOM_ATTR_SIZE);
8567                 mtoken = cols [MONO_CUSTOM_ATTR_TYPE] >> MONO_CUSTOM_ATTR_TYPE_BITS;
8568                 switch (cols [MONO_CUSTOM_ATTR_TYPE] & MONO_CUSTOM_ATTR_TYPE_MASK) {
8569                 case MONO_CUSTOM_ATTR_TYPE_METHODDEF:
8570                         mtoken |= MONO_TOKEN_METHOD_DEF;
8571                         break;
8572                 case MONO_CUSTOM_ATTR_TYPE_MEMBERREF:
8573                         mtoken |= MONO_TOKEN_MEMBER_REF;
8574                         break;
8575                 default:
8576                         g_error ("Unknown table for custom attr type %08x", cols [MONO_CUSTOM_ATTR_TYPE]);
8577                         break;
8578                 }
8579                 ainfo->attrs [i].ctor = mono_get_method (image, mtoken, NULL);
8580                 if (!ainfo->attrs [i].ctor) {
8581                         g_warning ("Can't find custom attr constructor image: %s mtoken: 0x%08x", image->name, mtoken);
8582                         g_list_free (list);
8583                         g_free (ainfo);
8584                         return NULL;
8585                 }
8586
8587                 if (!mono_verifier_verify_cattr_blob (image, cols [MONO_CUSTOM_ATTR_VALUE], NULL)) {
8588                         /*FIXME raising an exception here doesn't make any sense*/
8589                         g_warning ("Invalid custom attribute blob on image %s for index %x", image->name, idx);
8590                         g_list_free (list);
8591                         g_free (ainfo);
8592                         return NULL;
8593                 }
8594                 data = mono_metadata_blob_heap (image, cols [MONO_CUSTOM_ATTR_VALUE]);
8595                 ainfo->attrs [i].data_size = mono_metadata_decode_value (data, &data);
8596                 ainfo->attrs [i].data = (guchar*)data;
8597         }
8598         g_list_free (list);
8599
8600         return ainfo;
8601 }
8602
8603 MonoCustomAttrInfo*
8604 mono_custom_attrs_from_method (MonoMethod *method)
8605 {
8606         guint32 idx;
8607
8608         /*
8609          * An instantiated method has the same cattrs as the generic method definition.
8610          *
8611          * LAMESPEC: The .NET SRE throws an exception for instantiations of generic method builders
8612          *           Note that this stanza is not necessary for non-SRE types, but it's a micro-optimization
8613          */
8614         if (method->is_inflated)
8615                 method = ((MonoMethodInflated *) method)->declaring;
8616         
8617         if (method->dynamic || method->klass->image->dynamic)
8618                 return lookup_custom_attr (method->klass->image, method);
8619
8620         if (!method->token)
8621                 /* Synthetic methods */
8622                 return NULL;
8623
8624         idx = mono_method_get_index (method);
8625         idx <<= MONO_CUSTOM_ATTR_BITS;
8626         idx |= MONO_CUSTOM_ATTR_METHODDEF;
8627         return mono_custom_attrs_from_index (method->klass->image, idx);
8628 }
8629
8630 MonoCustomAttrInfo*
8631 mono_custom_attrs_from_class (MonoClass *klass)
8632 {
8633         guint32 idx;
8634
8635         if (klass->generic_class)
8636                 klass = klass->generic_class->container_class;
8637
8638         if (klass->image->dynamic)
8639                 return lookup_custom_attr (klass->image, klass);
8640
8641         if (klass->byval_arg.type == MONO_TYPE_VAR || klass->byval_arg.type == MONO_TYPE_MVAR) {
8642                 idx = mono_metadata_token_index (klass->sizes.generic_param_token);
8643                 idx <<= MONO_CUSTOM_ATTR_BITS;
8644                 idx |= MONO_CUSTOM_ATTR_GENERICPAR;
8645         } else {
8646                 idx = mono_metadata_token_index (klass->type_token);
8647                 idx <<= MONO_CUSTOM_ATTR_BITS;
8648                 idx |= MONO_CUSTOM_ATTR_TYPEDEF;
8649         }
8650         return mono_custom_attrs_from_index (klass->image, idx);
8651 }
8652
8653 MonoCustomAttrInfo*
8654 mono_custom_attrs_from_assembly (MonoAssembly *assembly)
8655 {
8656         guint32 idx;
8657         
8658         if (assembly->image->dynamic)
8659                 return lookup_custom_attr (assembly->image, assembly);
8660         idx = 1; /* there is only one assembly */
8661         idx <<= MONO_CUSTOM_ATTR_BITS;
8662         idx |= MONO_CUSTOM_ATTR_ASSEMBLY;
8663         return mono_custom_attrs_from_index (assembly->image, idx);
8664 }
8665
8666 static MonoCustomAttrInfo*
8667 mono_custom_attrs_from_module (MonoImage *image)
8668 {
8669         guint32 idx;
8670         
8671         if (image->dynamic)
8672                 return lookup_custom_attr (image, image);
8673         idx = 1; /* there is only one module */
8674         idx <<= MONO_CUSTOM_ATTR_BITS;
8675         idx |= MONO_CUSTOM_ATTR_MODULE;
8676         return mono_custom_attrs_from_index (image, idx);
8677 }
8678
8679 MonoCustomAttrInfo*
8680 mono_custom_attrs_from_property (MonoClass *klass, MonoProperty *property)
8681 {
8682         guint32 idx;
8683         
8684         if (klass->image->dynamic) {
8685                 property = mono_metadata_get_corresponding_property_from_generic_type_definition (property);
8686                 return lookup_custom_attr (klass->image, property);
8687         }
8688         idx = find_property_index (klass, property);
8689         idx <<= MONO_CUSTOM_ATTR_BITS;
8690         idx |= MONO_CUSTOM_ATTR_PROPERTY;
8691         return mono_custom_attrs_from_index (klass->image, idx);
8692 }
8693
8694 MonoCustomAttrInfo*
8695 mono_custom_attrs_from_event (MonoClass *klass, MonoEvent *event)
8696 {
8697         guint32 idx;
8698         
8699         if (klass->image->dynamic) {
8700                 event = mono_metadata_get_corresponding_event_from_generic_type_definition (event);
8701                 return lookup_custom_attr (klass->image, event);
8702         }
8703         idx = find_event_index (klass, event);
8704         idx <<= MONO_CUSTOM_ATTR_BITS;
8705         idx |= MONO_CUSTOM_ATTR_EVENT;
8706         return mono_custom_attrs_from_index (klass->image, idx);
8707 }
8708
8709 MonoCustomAttrInfo*
8710 mono_custom_attrs_from_field (MonoClass *klass, MonoClassField *field)
8711 {
8712         guint32 idx;
8713         if (klass->image->dynamic) {
8714                 field = mono_metadata_get_corresponding_field_from_generic_type_definition (field);
8715                 return lookup_custom_attr (klass->image, field);
8716         }
8717         idx = find_field_index (klass, field);
8718         idx <<= MONO_CUSTOM_ATTR_BITS;
8719         idx |= MONO_CUSTOM_ATTR_FIELDDEF;
8720         return mono_custom_attrs_from_index (klass->image, idx);
8721 }
8722
8723 /**
8724  * mono_custom_attrs_from_param:
8725  * @method: handle to the method that we want to retrieve custom parameter information from
8726  * @param: parameter number, where zero represent the return value, and one is the first parameter in the method
8727  *
8728  * The result must be released with mono_custom_attrs_free().
8729  *
8730  * Returns: the custom attribute object for the specified parameter, or NULL if there are none.
8731  */
8732 MonoCustomAttrInfo*
8733 mono_custom_attrs_from_param (MonoMethod *method, guint32 param)
8734 {
8735         MonoTableInfo *ca;
8736         guint32 i, idx, method_index;
8737         guint32 param_list, param_last, param_pos, found;
8738         MonoImage *image;
8739         MonoReflectionMethodAux *aux;
8740
8741         /*
8742          * An instantiated method has the same cattrs as the generic method definition.
8743          *
8744          * LAMESPEC: The .NET SRE throws an exception for instantiations of generic method builders
8745          *           Note that this stanza is not necessary for non-SRE types, but it's a micro-optimization
8746          */
8747         if (method->is_inflated)
8748                 method = ((MonoMethodInflated *) method)->declaring;
8749
8750         if (method->klass->image->dynamic) {
8751                 MonoCustomAttrInfo *res, *ainfo;
8752                 int size;
8753
8754                 aux = g_hash_table_lookup (((MonoDynamicImage*)method->klass->image)->method_aux_hash, method);
8755                 if (!aux || !aux->param_cattr)
8756                         return NULL;
8757
8758                 /* Need to copy since it will be freed later */
8759                 ainfo = aux->param_cattr [param];
8760                 if (!ainfo)
8761                         return NULL;
8762                 size = MONO_SIZEOF_CUSTOM_ATTR_INFO + sizeof (MonoCustomAttrEntry) * ainfo->num_attrs;
8763                 res = g_malloc0 (size);
8764                 memcpy (res, ainfo, size);
8765                 return res;
8766         }
8767
8768         image = method->klass->image;
8769         method_index = mono_method_get_index (method);
8770         if (!method_index)
8771                 return NULL;
8772         ca = &image->tables [MONO_TABLE_METHOD];
8773
8774         param_list = mono_metadata_decode_row_col (ca, method_index - 1, MONO_METHOD_PARAMLIST);
8775         if (method_index == ca->rows) {
8776                 ca = &image->tables [MONO_TABLE_PARAM];
8777                 param_last = ca->rows + 1;
8778         } else {
8779                 param_last = mono_metadata_decode_row_col (ca, method_index, MONO_METHOD_PARAMLIST);
8780                 ca = &image->tables [MONO_TABLE_PARAM];
8781         }
8782         found = FALSE;
8783         for (i = param_list; i < param_last; ++i) {
8784                 param_pos = mono_metadata_decode_row_col (ca, i - 1, MONO_PARAM_SEQUENCE);
8785                 if (param_pos == param) {
8786                         found = TRUE;
8787                         break;
8788                 }
8789         }
8790         if (!found)
8791                 return NULL;
8792         idx = i;
8793         idx <<= MONO_CUSTOM_ATTR_BITS;
8794         idx |= MONO_CUSTOM_ATTR_PARAMDEF;
8795         return mono_custom_attrs_from_index (image, idx);
8796 }
8797
8798 gboolean
8799 mono_custom_attrs_has_attr (MonoCustomAttrInfo *ainfo, MonoClass *attr_klass)
8800 {
8801         int i;
8802         MonoClass *klass;
8803         for (i = 0; i < ainfo->num_attrs; ++i) {
8804                 klass = ainfo->attrs [i].ctor->klass;
8805                 if (mono_class_has_parent (klass, attr_klass) || (MONO_CLASS_IS_INTERFACE (attr_klass) && mono_class_is_assignable_from (attr_klass, klass)))
8806                         return TRUE;
8807         }
8808         return FALSE;
8809 }
8810
8811 MonoObject*
8812 mono_custom_attrs_get_attr (MonoCustomAttrInfo *ainfo, MonoClass *attr_klass)
8813 {
8814         int i, attr_index;
8815         MonoClass *klass;
8816         MonoArray *attrs;
8817
8818         attr_index = -1;
8819         for (i = 0; i < ainfo->num_attrs; ++i) {
8820                 klass = ainfo->attrs [i].ctor->klass;
8821                 if (mono_class_has_parent (klass, attr_klass)) {
8822                         attr_index = i;
8823                         break;
8824                 }
8825         }
8826         if (attr_index == -1)
8827                 return NULL;
8828
8829         attrs = mono_custom_attrs_construct (ainfo);
8830         if (attrs)
8831                 return mono_array_get (attrs, MonoObject*, attr_index);
8832         else
8833                 return NULL;
8834 }
8835
8836 /*
8837  * mono_reflection_get_custom_attrs_info:
8838  * @obj: a reflection object handle
8839  *
8840  * Return the custom attribute info for attributes defined for the
8841  * reflection handle @obj. The objects.
8842  *
8843  * FIXME this function leaks like a sieve for SRE objects.
8844  */
8845 MonoCustomAttrInfo*
8846 mono_reflection_get_custom_attrs_info (MonoObject *obj)
8847 {
8848         MonoClass *klass;
8849         MonoCustomAttrInfo *cinfo = NULL;
8850         
8851         klass = obj->vtable->klass;
8852         if (klass == mono_defaults.monotype_class) {
8853                 MonoType *type = mono_reflection_type_get_handle ((MonoReflectionType *)obj);
8854                 klass = mono_class_from_mono_type (type);
8855                 /*We cannot mono_class_init the class from which we'll load the custom attributes since this must work with broken types.*/
8856                 cinfo = mono_custom_attrs_from_class (klass);
8857         } else if (strcmp ("Assembly", klass->name) == 0 || strcmp ("MonoAssembly", klass->name) == 0) {
8858                 MonoReflectionAssembly *rassembly = (MonoReflectionAssembly*)obj;
8859                 cinfo = mono_custom_attrs_from_assembly (rassembly->assembly);
8860         } else if (strcmp ("Module", klass->name) == 0 || strcmp ("MonoModule", klass->name) == 0) {
8861                 MonoReflectionModule *module = (MonoReflectionModule*)obj;
8862                 cinfo = mono_custom_attrs_from_module (module->image);
8863         } else if (strcmp ("MonoProperty", klass->name) == 0) {
8864                 MonoReflectionProperty *rprop = (MonoReflectionProperty*)obj;
8865                 cinfo = mono_custom_attrs_from_property (rprop->property->parent, rprop->property);
8866         } else if (strcmp ("MonoEvent", klass->name) == 0) {
8867                 MonoReflectionMonoEvent *revent = (MonoReflectionMonoEvent*)obj;
8868                 cinfo = mono_custom_attrs_from_event (revent->event->parent, revent->event);
8869         } else if (strcmp ("MonoField", klass->name) == 0) {
8870                 MonoReflectionField *rfield = (MonoReflectionField*)obj;
8871                 cinfo = mono_custom_attrs_from_field (rfield->field->parent, rfield->field);
8872         } else if ((strcmp ("MonoMethod", klass->name) == 0) || (strcmp ("MonoCMethod", klass->name) == 0)) {
8873                 MonoReflectionMethod *rmethod = (MonoReflectionMethod*)obj;
8874                 cinfo = mono_custom_attrs_from_method (rmethod->method);
8875         } else if ((strcmp ("MonoGenericMethod", klass->name) == 0) || (strcmp ("MonoGenericCMethod", klass->name) == 0)) {
8876                 MonoReflectionMethod *rmethod = (MonoReflectionMethod*)obj;
8877                 cinfo = mono_custom_attrs_from_method (rmethod->method);
8878         } else if (strcmp ("ParameterInfo", klass->name) == 0 || strcmp ("MonoParameterInfo", klass->name) == 0) {
8879                 MonoReflectionParameter *param = (MonoReflectionParameter*)obj;
8880                 MonoClass *member_class = mono_object_class (param->MemberImpl);
8881                 if (mono_class_is_reflection_method_or_constructor (member_class)) {
8882                         MonoReflectionMethod *rmethod = (MonoReflectionMethod*)param->MemberImpl;
8883                         cinfo = mono_custom_attrs_from_param (rmethod->method, param->PositionImpl + 1);
8884                 } else if (is_sr_mono_property (member_class)) {
8885                         MonoReflectionProperty *prop = (MonoReflectionProperty *)param->MemberImpl;
8886                         MonoMethod *method;
8887                         if (!(method = prop->property->get))
8888                                 method = prop->property->set;
8889                         g_assert (method);
8890
8891                         cinfo = mono_custom_attrs_from_param (method, param->PositionImpl + 1);
8892                 } 
8893 #ifndef DISABLE_REFLECTION_EMIT
8894                 else if (is_sre_method_on_tb_inst (member_class)) {/*XXX This is a workaround for Compiler Context*/
8895                         MonoMethod *method = mono_reflection_method_on_tb_inst_get_handle ((MonoReflectionMethodOnTypeBuilderInst*)param->MemberImpl);
8896                         cinfo = mono_custom_attrs_from_param (method, param->PositionImpl + 1);
8897                 } else if (is_sre_ctor_on_tb_inst (member_class)) { /*XX This is a workaround for Compiler Context*/
8898                         MonoReflectionCtorOnTypeBuilderInst *c = (MonoReflectionCtorOnTypeBuilderInst*)param->MemberImpl;
8899                         MonoMethod *method = NULL;
8900                         if (is_sre_ctor_builder (mono_object_class (c->cb)))
8901                                 method = ((MonoReflectionCtorBuilder *)c->cb)->mhandle;
8902                         else if (is_sr_mono_cmethod (mono_object_class (c->cb)))
8903                                 method = ((MonoReflectionMethod *)c->cb)->method;
8904                         else
8905                                 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));
8906
8907                         cinfo = mono_custom_attrs_from_param (method, param->PositionImpl + 1);
8908                 } 
8909 #endif
8910                 else {
8911                         char *type_name = mono_type_get_full_name (member_class);
8912                         char *msg = g_strdup_printf ("Custom attributes on a ParamInfo with member %s are not supported", type_name);
8913                         MonoException *ex = mono_get_exception_not_supported  (msg);
8914                         g_free (type_name);
8915                         g_free (msg);
8916                         mono_raise_exception (ex);
8917                 }
8918         } else if (strcmp ("AssemblyBuilder", klass->name) == 0) {
8919                 MonoReflectionAssemblyBuilder *assemblyb = (MonoReflectionAssemblyBuilder*)obj;
8920                 cinfo = mono_custom_attrs_from_builders (NULL, assemblyb->assembly.assembly->image, assemblyb->cattrs);
8921         } else if (strcmp ("TypeBuilder", klass->name) == 0) {
8922                 MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder*)obj;
8923                 cinfo = mono_custom_attrs_from_builders (NULL, &tb->module->dynamic_image->image, tb->cattrs);
8924         } else if (strcmp ("ModuleBuilder", klass->name) == 0) {
8925                 MonoReflectionModuleBuilder *mb = (MonoReflectionModuleBuilder*)obj;
8926                 cinfo = mono_custom_attrs_from_builders (NULL, &mb->dynamic_image->image, mb->cattrs);
8927         } else if (strcmp ("ConstructorBuilder", klass->name) == 0) {
8928                 MonoReflectionCtorBuilder *cb = (MonoReflectionCtorBuilder*)obj;
8929                 cinfo = mono_custom_attrs_from_builders (NULL, cb->mhandle->klass->image, cb->cattrs);
8930         } else if (strcmp ("MethodBuilder", klass->name) == 0) {
8931                 MonoReflectionMethodBuilder *mb = (MonoReflectionMethodBuilder*)obj;
8932                 cinfo = mono_custom_attrs_from_builders (NULL, mb->mhandle->klass->image, mb->cattrs);
8933         } else if (strcmp ("FieldBuilder", klass->name) == 0) {
8934                 MonoReflectionFieldBuilder *fb = (MonoReflectionFieldBuilder*)obj;
8935                 cinfo = mono_custom_attrs_from_builders (NULL, &((MonoReflectionTypeBuilder*)fb->typeb)->module->dynamic_image->image, fb->cattrs);
8936         } else if (strcmp ("MonoGenericClass", klass->name) == 0) {
8937                 MonoReflectionGenericClass *gclass = (MonoReflectionGenericClass*)obj;
8938                 cinfo = mono_reflection_get_custom_attrs_info ((MonoObject*)gclass->generic_type);
8939         } else { /* handle other types here... */
8940                 g_error ("get custom attrs not yet supported for %s", klass->name);
8941         }
8942
8943         return cinfo;
8944 }
8945
8946 /*
8947  * mono_reflection_get_custom_attrs_by_type:
8948  * @obj: a reflection object handle
8949  *
8950  * Return an array with all the custom attributes defined of the
8951  * reflection handle @obj. If @attr_klass is non-NULL, only custom attributes 
8952  * of that type are returned. The objects are fully build. Return NULL if a loading error
8953  * occurs.
8954  */
8955 MonoArray*
8956 mono_reflection_get_custom_attrs_by_type (MonoObject *obj, MonoClass *attr_klass, MonoError *error)
8957 {
8958         MonoArray *result;
8959         MonoCustomAttrInfo *cinfo;
8960
8961         mono_error_init (error);
8962
8963         cinfo = mono_reflection_get_custom_attrs_info (obj);
8964         if (cinfo) {
8965                 result = mono_custom_attrs_construct_by_type (cinfo, attr_klass, error);
8966                 if (!cinfo->cached)
8967                         mono_custom_attrs_free (cinfo);
8968         } else {
8969                 if (mono_loader_get_last_error ())
8970                         return NULL;
8971                 result = mono_array_new_cached (mono_domain_get (), mono_defaults.attribute_class, 0);
8972         }
8973
8974         return result;
8975 }
8976
8977 /*
8978  * mono_reflection_get_custom_attrs:
8979  * @obj: a reflection object handle
8980  *
8981  * Return an array with all the custom attributes defined of the
8982  * reflection handle @obj. The objects are fully build. Return NULL if a loading error
8983  * occurs.
8984  */
8985 MonoArray*
8986 mono_reflection_get_custom_attrs (MonoObject *obj)
8987 {
8988         MonoError error;
8989
8990         return mono_reflection_get_custom_attrs_by_type (obj, NULL, &error);
8991 }
8992
8993 /*
8994  * mono_reflection_get_custom_attrs_data:
8995  * @obj: a reflection obj handle
8996  *
8997  * Returns an array of System.Reflection.CustomAttributeData,
8998  * which include information about attributes reflected on
8999  * types loaded using the Reflection Only methods
9000  */
9001 MonoArray*
9002 mono_reflection_get_custom_attrs_data (MonoObject *obj)
9003 {
9004         MonoArray *result;
9005         MonoCustomAttrInfo *cinfo;
9006
9007         cinfo = mono_reflection_get_custom_attrs_info (obj);
9008         if (cinfo) {
9009                 result = mono_custom_attrs_data_construct (cinfo);
9010                 if (!cinfo->cached)
9011                         mono_custom_attrs_free (cinfo);
9012         } else
9013                 result = mono_array_new (mono_domain_get (), mono_defaults.customattribute_data_class, 0);
9014
9015         return result;
9016 }
9017
9018 static MonoReflectionType*
9019 mono_reflection_type_get_underlying_system_type (MonoReflectionType* t)
9020 {
9021         static MonoMethod *method_get_underlying_system_type = NULL;
9022         MonoMethod *usertype_method;
9023
9024         if (!method_get_underlying_system_type)
9025                 method_get_underlying_system_type = mono_class_get_method_from_name (mono_defaults.systemtype_class, "get_UnderlyingSystemType", 0);
9026         usertype_method = mono_object_get_virtual_method ((MonoObject *) t, method_get_underlying_system_type);
9027         return (MonoReflectionType *) mono_runtime_invoke (usertype_method, t, NULL, NULL);
9028 }
9029
9030
9031 static gboolean
9032 is_corlib_type (MonoClass *class)
9033 {
9034         return class->image == mono_defaults.corlib;
9035 }
9036
9037 #define check_corlib_type_cached(_class, _namespace, _name) do { \
9038         static MonoClass *cached_class; \
9039         if (cached_class) \
9040                 return cached_class == _class; \
9041         if (is_corlib_type (_class) && !strcmp (_name, _class->name) && !strcmp (_namespace, _class->name_space)) { \
9042                 cached_class = _class; \
9043                 return TRUE; \
9044         } \
9045         return FALSE; \
9046 } while (0) \
9047
9048
9049 #ifndef DISABLE_REFLECTION_EMIT
9050 static gboolean
9051 is_sre_array (MonoClass *class)
9052 {
9053         check_corlib_type_cached (class, "System.Reflection.Emit", "ArrayType");
9054 }
9055
9056 static gboolean
9057 is_sre_byref (MonoClass *class)
9058 {
9059         check_corlib_type_cached (class, "System.Reflection.Emit", "ByRefType");
9060 }
9061
9062 static gboolean
9063 is_sre_pointer (MonoClass *class)
9064 {
9065         check_corlib_type_cached (class, "System.Reflection.Emit", "PointerType");
9066 }
9067
9068 static gboolean
9069 is_sre_generic_instance (MonoClass *class)
9070 {
9071         check_corlib_type_cached (class, "System.Reflection", "MonoGenericClass");
9072 }
9073
9074 static gboolean
9075 is_sre_type_builder (MonoClass *class)
9076 {
9077         check_corlib_type_cached (class, "System.Reflection.Emit", "TypeBuilder");
9078 }
9079
9080 static gboolean
9081 is_sre_method_builder (MonoClass *class)
9082 {
9083         check_corlib_type_cached (class, "System.Reflection.Emit", "MethodBuilder");
9084 }
9085
9086 static gboolean
9087 is_sre_ctor_builder (MonoClass *class)
9088 {
9089         check_corlib_type_cached (class, "System.Reflection.Emit", "ConstructorBuilder");
9090 }
9091
9092 static gboolean
9093 is_sre_field_builder (MonoClass *class)
9094 {
9095         check_corlib_type_cached (class, "System.Reflection.Emit", "FieldBuilder");
9096 }
9097
9098 static gboolean
9099 is_sre_method_on_tb_inst (MonoClass *class)
9100 {
9101         check_corlib_type_cached (class, "System.Reflection.Emit", "MethodOnTypeBuilderInst");
9102 }
9103
9104 static gboolean
9105 is_sre_ctor_on_tb_inst (MonoClass *class)
9106 {
9107         check_corlib_type_cached (class, "System.Reflection.Emit", "ConstructorOnTypeBuilderInst");
9108 }
9109
9110 MonoType*
9111 mono_reflection_type_get_handle (MonoReflectionType* ref)
9112 {
9113         MonoClass *class;
9114         if (!ref)
9115                 return NULL;
9116         if (ref->type)
9117                 return ref->type;
9118
9119         if (is_usertype (ref)) {
9120                 ref = mono_reflection_type_get_underlying_system_type (ref);
9121                 if (ref == NULL || is_usertype (ref))
9122                         return NULL;
9123                 if (ref->type)
9124                         return ref->type;
9125         }
9126
9127         class = mono_object_class (ref);
9128
9129         if (is_sre_array (class)) {
9130                 MonoType *res;
9131                 MonoReflectionArrayType *sre_array = (MonoReflectionArrayType*)ref;
9132                 MonoType *base = mono_reflection_type_get_handle (sre_array->element_type);
9133                 g_assert (base);
9134                 if (sre_array->rank == 0) //single dimentional array
9135                         res = &mono_array_class_get (mono_class_from_mono_type (base), 1)->byval_arg;
9136                 else
9137                         res = &mono_bounded_array_class_get (mono_class_from_mono_type (base), sre_array->rank, TRUE)->byval_arg;
9138                 sre_array->type.type = res;
9139                 return res;
9140         } else if (is_sre_byref (class)) {
9141                 MonoType *res;
9142                 MonoReflectionDerivedType *sre_byref = (MonoReflectionDerivedType*)ref;
9143                 MonoType *base = mono_reflection_type_get_handle (sre_byref->element_type);
9144                 g_assert (base);
9145                 res = &mono_class_from_mono_type (base)->this_arg;
9146                 sre_byref->type.type = res;
9147                 return res;
9148         } else if (is_sre_pointer (class)) {
9149                 MonoType *res;
9150                 MonoReflectionDerivedType *sre_pointer = (MonoReflectionDerivedType*)ref;
9151                 MonoType *base = mono_reflection_type_get_handle (sre_pointer->element_type);
9152                 g_assert (base);
9153                 res = &mono_ptr_class_get (base)->byval_arg;
9154                 sre_pointer->type.type = res;
9155                 return res;
9156         } else if (is_sre_generic_instance (class)) {
9157                 MonoType *res, **types;
9158                 MonoReflectionGenericClass *gclass = (MonoReflectionGenericClass*)ref;
9159                 int i, count;
9160
9161                 count = mono_array_length (gclass->type_arguments);
9162                 types = g_new0 (MonoType*, count);
9163                 for (i = 0; i < count; ++i) {
9164                         MonoReflectionType *t = mono_array_get (gclass->type_arguments, gpointer, i);
9165                         types [i] = mono_reflection_type_get_handle (t);
9166                         if (!types[i]) {
9167                                 g_free (types);
9168                                 return NULL;
9169                         }
9170                 }
9171
9172                 res = mono_reflection_bind_generic_parameters (gclass->generic_type, count, types);
9173                 g_free (types);
9174                 g_assert (res);
9175                 gclass->type.type = res;
9176                 return res;
9177         }
9178
9179         g_error ("Cannot handle corlib user type %s", mono_type_full_name (&mono_object_class(ref)->byval_arg));
9180         return NULL;
9181 }
9182
9183
9184
9185 void
9186 mono_reflection_create_unmanaged_type (MonoReflectionType *type)
9187 {
9188         mono_reflection_type_get_handle (type);
9189 }
9190
9191 void
9192 mono_reflection_register_with_runtime (MonoReflectionType *type)
9193 {
9194         MonoType *res = mono_reflection_type_get_handle (type);
9195         MonoDomain *domain = mono_object_domain ((MonoObject*)type);
9196         MonoClass *class;
9197
9198         if (!res)
9199                 mono_raise_exception (mono_get_exception_argument (NULL, "Invalid generic instantiation, one or more arguments are not proper user types"));
9200
9201         class = mono_class_from_mono_type (res);
9202
9203         mono_loader_lock (); /*same locking as mono_type_get_object*/
9204         mono_domain_lock (domain);
9205
9206         if (!class->image->dynamic) {
9207                 mono_class_setup_supertypes (class);
9208         } else {
9209                 if (!domain->type_hash)
9210                         domain->type_hash = mono_g_hash_table_new_type ((GHashFunc)mono_metadata_type_hash, 
9211                                         (GCompareFunc)mono_metadata_type_equal, MONO_HASH_VALUE_GC);
9212                 mono_g_hash_table_insert (domain->type_hash, res, type);
9213         }
9214         mono_domain_unlock (domain);
9215         mono_loader_unlock ();
9216 }
9217
9218 /**
9219  * LOCKING: Assumes the loader lock is held.
9220  */
9221 static MonoMethodSignature*
9222 parameters_to_signature (MonoImage *image, MonoArray *parameters) {
9223         MonoMethodSignature *sig;
9224         int count, i;
9225
9226         count = parameters? mono_array_length (parameters): 0;
9227
9228         sig = image_g_malloc0 (image, MONO_SIZEOF_METHOD_SIGNATURE + sizeof (MonoType*) * count);
9229         sig->param_count = count;
9230         sig->sentinelpos = -1; /* FIXME */
9231         for (i = 0; i < count; ++i)
9232                 sig->params [i] = mono_type_array_get_and_resolve (parameters, i);
9233         return sig;
9234 }
9235
9236 /**
9237  * LOCKING: Assumes the loader lock is held.
9238  */
9239 static MonoMethodSignature*
9240 ctor_builder_to_signature (MonoImage *image, MonoReflectionCtorBuilder *ctor) {
9241         MonoMethodSignature *sig;
9242
9243         sig = parameters_to_signature (image, ctor->parameters);
9244         sig->hasthis = ctor->attrs & METHOD_ATTRIBUTE_STATIC? 0: 1;
9245         sig->ret = &mono_defaults.void_class->byval_arg;
9246         return sig;
9247 }
9248
9249 /**
9250  * LOCKING: Assumes the loader lock is held.
9251  */
9252 static MonoMethodSignature*
9253 method_builder_to_signature (MonoImage *image, MonoReflectionMethodBuilder *method) {
9254         MonoMethodSignature *sig;
9255
9256         sig = parameters_to_signature (image, method->parameters);
9257         sig->hasthis = method->attrs & METHOD_ATTRIBUTE_STATIC? 0: 1;
9258         sig->ret = method->rtype? mono_reflection_type_get_handle ((MonoReflectionType*)method->rtype): &mono_defaults.void_class->byval_arg;
9259         sig->generic_param_count = method->generic_params ? mono_array_length (method->generic_params) : 0;
9260         return sig;
9261 }
9262
9263 static MonoMethodSignature*
9264 dynamic_method_to_signature (MonoReflectionDynamicMethod *method) {
9265         MonoMethodSignature *sig;
9266
9267         sig = parameters_to_signature (NULL, method->parameters);
9268         sig->hasthis = method->attrs & METHOD_ATTRIBUTE_STATIC? 0: 1;
9269         sig->ret = method->rtype? mono_reflection_type_get_handle (method->rtype): &mono_defaults.void_class->byval_arg;
9270         sig->generic_param_count = 0;
9271         return sig;
9272 }
9273
9274 static void
9275 get_prop_name_and_type (MonoObject *prop, char **name, MonoType **type)
9276 {
9277         MonoClass *klass = mono_object_class (prop);
9278         if (strcmp (klass->name, "PropertyBuilder") == 0) {
9279                 MonoReflectionPropertyBuilder *pb = (MonoReflectionPropertyBuilder *)prop;
9280                 *name = mono_string_to_utf8 (pb->name);
9281                 *type = mono_reflection_type_get_handle ((MonoReflectionType*)pb->type);
9282         } else {
9283                 MonoReflectionProperty *p = (MonoReflectionProperty *)prop;
9284                 *name = g_strdup (p->property->name);
9285                 if (p->property->get)
9286                         *type = mono_method_signature (p->property->get)->ret;
9287                 else
9288                         *type = mono_method_signature (p->property->set)->params [mono_method_signature (p->property->set)->param_count - 1];
9289         }
9290 }
9291
9292 static void
9293 get_field_name_and_type (MonoObject *field, char **name, MonoType **type)
9294 {
9295         MonoClass *klass = mono_object_class (field);
9296         if (strcmp (klass->name, "FieldBuilder") == 0) {
9297                 MonoReflectionFieldBuilder *fb = (MonoReflectionFieldBuilder *)field;
9298                 *name = mono_string_to_utf8 (fb->name);
9299                 *type = mono_reflection_type_get_handle ((MonoReflectionType*)fb->type);
9300         } else {
9301                 MonoReflectionField *f = (MonoReflectionField *)field;
9302                 *name = g_strdup (mono_field_get_name (f->field));
9303                 *type = f->field->type;
9304         }
9305 }
9306
9307 #else /* DISABLE_REFLECTION_EMIT */
9308
9309 void
9310 mono_reflection_register_with_runtime (MonoReflectionType *type)
9311 {
9312         /* This is empty */
9313 }
9314
9315 static gboolean
9316 is_sre_type_builder (MonoClass *class)
9317 {
9318         return FALSE;
9319 }
9320
9321 static gboolean
9322 is_sre_generic_instance (MonoClass *class)
9323 {
9324         return FALSE;
9325 }
9326
9327 static void
9328 init_type_builder_generics (MonoObject *type)
9329 {
9330 }
9331
9332 #endif /* !DISABLE_REFLECTION_EMIT */
9333
9334
9335 static gboolean
9336 is_sr_mono_field (MonoClass *class)
9337 {
9338         check_corlib_type_cached (class, "System.Reflection", "MonoField");
9339 }
9340
9341 static gboolean
9342 is_sr_mono_property (MonoClass *class)
9343 {
9344         check_corlib_type_cached (class, "System.Reflection", "MonoProperty");
9345 }
9346
9347 static gboolean
9348 is_sr_mono_method (MonoClass *class)
9349 {
9350         check_corlib_type_cached (class, "System.Reflection", "MonoMethod");
9351 }
9352
9353 static gboolean
9354 is_sr_mono_cmethod (MonoClass *class)
9355 {
9356         check_corlib_type_cached (class, "System.Reflection", "MonoCMethod");
9357 }
9358
9359 static gboolean
9360 is_sr_mono_generic_method (MonoClass *class)
9361 {
9362         check_corlib_type_cached (class, "System.Reflection", "MonoGenericMethod");
9363 }
9364
9365 static gboolean
9366 is_sr_mono_generic_cmethod (MonoClass *class)
9367 {
9368         check_corlib_type_cached (class, "System.Reflection", "MonoGenericCMethod");
9369 }
9370
9371 gboolean
9372 mono_class_is_reflection_method_or_constructor (MonoClass *class)
9373 {
9374         return is_sr_mono_method (class) || is_sr_mono_cmethod (class) || is_sr_mono_generic_method (class) || is_sr_mono_generic_cmethod (class);
9375 }
9376
9377 static gboolean
9378 is_usertype (MonoReflectionType *ref)
9379 {
9380         MonoClass *class = mono_object_class (ref);
9381         return class->image != mono_defaults.corlib || strcmp ("TypeDelegator", class->name) == 0;
9382 }
9383
9384 static MonoReflectionType*
9385 mono_reflection_type_resolve_user_types (MonoReflectionType *type)
9386 {
9387         if (!type || type->type)
9388                 return type;
9389
9390         if (is_usertype (type)) {
9391                 type = mono_reflection_type_get_underlying_system_type (type);
9392                 if (is_usertype (type))
9393                         mono_raise_exception (mono_get_exception_not_supported ("User defined subclasses of System.Type are not yet supported22"));
9394         }
9395
9396         return type;
9397 }
9398 /*
9399  * Encode a value in a custom attribute stream of bytes.
9400  * The value to encode is either supplied as an object in argument val
9401  * (valuetypes are boxed), or as a pointer to the data in the
9402  * argument argval.
9403  * @type represents the type of the value
9404  * @buffer is the start of the buffer
9405  * @p the current position in the buffer
9406  * @buflen contains the size of the buffer and is used to return the new buffer size
9407  * if this needs to be realloced.
9408  * @retbuffer and @retp return the start and the position of the buffer
9409  */
9410 static void
9411 encode_cattr_value (MonoAssembly *assembly, char *buffer, char *p, char **retbuffer, char **retp, guint32 *buflen, MonoType *type, MonoObject *arg, char *argval)
9412 {
9413         MonoTypeEnum simple_type;
9414         
9415         if ((p-buffer) + 10 >= *buflen) {
9416                 char *newbuf;
9417                 *buflen *= 2;
9418                 newbuf = g_realloc (buffer, *buflen);
9419                 p = newbuf + (p-buffer);
9420                 buffer = newbuf;
9421         }
9422         if (!argval)
9423                 argval = ((char*)arg + sizeof (MonoObject));
9424         simple_type = type->type;
9425 handle_enum:
9426         switch (simple_type) {
9427         case MONO_TYPE_BOOLEAN:
9428         case MONO_TYPE_U1:
9429         case MONO_TYPE_I1:
9430                 *p++ = *argval;
9431                 break;
9432         case MONO_TYPE_CHAR:
9433         case MONO_TYPE_U2:
9434         case MONO_TYPE_I2:
9435                 swap_with_size (p, argval, 2, 1);
9436                 p += 2;
9437                 break;
9438         case MONO_TYPE_U4:
9439         case MONO_TYPE_I4:
9440         case MONO_TYPE_R4:
9441                 swap_with_size (p, argval, 4, 1);
9442                 p += 4;
9443                 break;
9444         case MONO_TYPE_R8:
9445                 swap_with_size (p, argval, 8, 1);
9446                 p += 8;
9447                 break;
9448         case MONO_TYPE_U8:
9449         case MONO_TYPE_I8:
9450                 swap_with_size (p, argval, 8, 1);
9451                 p += 8;
9452                 break;
9453         case MONO_TYPE_VALUETYPE:
9454                 if (type->data.klass->enumtype) {
9455                         simple_type = mono_class_enum_basetype (type->data.klass)->type;
9456                         goto handle_enum;
9457                 } else {
9458                         g_warning ("generic valutype %s not handled in custom attr value decoding", type->data.klass->name);
9459                 }
9460                 break;
9461         case MONO_TYPE_STRING: {
9462                 char *str;
9463                 guint32 slen;
9464                 if (!arg) {
9465                         *p++ = 0xFF;
9466                         break;
9467                 }
9468                 str = mono_string_to_utf8 ((MonoString*)arg);
9469                 slen = strlen (str);
9470                 if ((p-buffer) + 10 + slen >= *buflen) {
9471                         char *newbuf;
9472                         *buflen *= 2;
9473                         *buflen += slen;
9474                         newbuf = g_realloc (buffer, *buflen);
9475                         p = newbuf + (p-buffer);
9476                         buffer = newbuf;
9477                 }
9478                 mono_metadata_encode_value (slen, p, &p);
9479                 memcpy (p, str, slen);
9480                 p += slen;
9481                 g_free (str);
9482                 break;
9483         }
9484         case MONO_TYPE_CLASS: {
9485                 char *str;
9486                 guint32 slen;
9487                 if (!arg) {
9488                         *p++ = 0xFF;
9489                         break;
9490                 }
9491 handle_type:
9492                 str = type_get_qualified_name (mono_reflection_type_get_handle ((MonoReflectionType*)arg), NULL);
9493                 slen = strlen (str);
9494                 if ((p-buffer) + 10 + slen >= *buflen) {
9495                         char *newbuf;
9496                         *buflen *= 2;
9497                         *buflen += slen;
9498                         newbuf = g_realloc (buffer, *buflen);
9499                         p = newbuf + (p-buffer);
9500                         buffer = newbuf;
9501                 }
9502                 mono_metadata_encode_value (slen, p, &p);
9503                 memcpy (p, str, slen);
9504                 p += slen;
9505                 g_free (str);
9506                 break;
9507         }
9508         case MONO_TYPE_SZARRAY: {
9509                 int len, i;
9510                 MonoClass *eclass, *arg_eclass;
9511
9512                 if (!arg) {
9513                         *p++ = 0xff; *p++ = 0xff; *p++ = 0xff; *p++ = 0xff;
9514                         break;
9515                 }
9516                 len = mono_array_length ((MonoArray*)arg);
9517                 *p++ = len & 0xff;
9518                 *p++ = (len >> 8) & 0xff;
9519                 *p++ = (len >> 16) & 0xff;
9520                 *p++ = (len >> 24) & 0xff;
9521                 *retp = p;
9522                 *retbuffer = buffer;
9523                 eclass = type->data.klass;
9524                 arg_eclass = mono_object_class (arg)->element_class;
9525
9526                 if (!eclass) {
9527                         /* Happens when we are called from the MONO_TYPE_OBJECT case below */
9528                         eclass = mono_defaults.object_class;
9529                 }
9530                 if (eclass == mono_defaults.object_class && arg_eclass->valuetype) {
9531                         char *elptr = mono_array_addr ((MonoArray*)arg, char, 0);
9532                         int elsize = mono_class_array_element_size (arg_eclass);
9533                         for (i = 0; i < len; ++i) {
9534                                 encode_cattr_value (assembly, buffer, p, &buffer, &p, buflen, &arg_eclass->byval_arg, NULL, elptr);
9535                                 elptr += elsize;
9536                         }
9537                 } else if (eclass->valuetype && arg_eclass->valuetype) {
9538                         char *elptr = mono_array_addr ((MonoArray*)arg, char, 0);
9539                         int elsize = mono_class_array_element_size (eclass);
9540                         for (i = 0; i < len; ++i) {
9541                                 encode_cattr_value (assembly, buffer, p, &buffer, &p, buflen, &eclass->byval_arg, NULL, elptr);
9542                                 elptr += elsize;
9543                         }
9544                 } else {
9545                         for (i = 0; i < len; ++i) {
9546                                 encode_cattr_value (assembly, buffer, p, &buffer, &p, buflen, &eclass->byval_arg, mono_array_get ((MonoArray*)arg, MonoObject*, i), NULL);
9547                         }
9548                 }
9549                 break;
9550         }
9551         case MONO_TYPE_OBJECT: {
9552                 MonoClass *klass;
9553                 char *str;
9554                 guint32 slen;
9555
9556                 /*
9557                  * The parameter type is 'object' but the type of the actual
9558                  * argument is not. So we have to add type information to the blob
9559                  * too. This is completely undocumented in the spec.
9560                  */
9561
9562                 if (arg == NULL) {
9563                         *p++ = MONO_TYPE_STRING;        // It's same hack as MS uses
9564                         *p++ = 0xFF;
9565                         break;
9566                 }
9567                 
9568                 klass = mono_object_class (arg);
9569
9570                 if (mono_object_isinst (arg, mono_defaults.systemtype_class)) {
9571                         *p++ = 0x50;
9572                         goto handle_type;
9573                 } else if (klass->enumtype) {
9574                         *p++ = 0x55;
9575                 } else if (klass == mono_defaults.string_class) {
9576                         simple_type = MONO_TYPE_STRING;
9577                         *p++ = 0x0E;
9578                         goto handle_enum;
9579                 } else if (klass->rank == 1) {
9580                         *p++ = 0x1D;
9581                         if (klass->element_class->byval_arg.type == MONO_TYPE_OBJECT)
9582                                 /* See Partition II, Appendix B3 */
9583                                 *p++ = 0x51;
9584                         else
9585                                 *p++ = klass->element_class->byval_arg.type;
9586                         encode_cattr_value (assembly, buffer, p, &buffer, &p, buflen, &klass->byval_arg, arg, NULL);
9587                         break;
9588                 } else if (klass->byval_arg.type >= MONO_TYPE_BOOLEAN && klass->byval_arg.type <= MONO_TYPE_R8) {
9589                         *p++ = simple_type = klass->byval_arg.type;
9590                         goto handle_enum;
9591                 } else {
9592                         g_error ("unhandled type in custom attr");
9593                 }
9594                 str = type_get_qualified_name (mono_class_get_type(klass), NULL);
9595                 slen = strlen (str);
9596                 if ((p-buffer) + 10 + slen >= *buflen) {
9597                         char *newbuf;
9598                         *buflen *= 2;
9599                         *buflen += slen;
9600                         newbuf = g_realloc (buffer, *buflen);
9601                         p = newbuf + (p-buffer);
9602                         buffer = newbuf;
9603                 }
9604                 mono_metadata_encode_value (slen, p, &p);
9605                 memcpy (p, str, slen);
9606                 p += slen;
9607                 g_free (str);
9608                 simple_type = mono_class_enum_basetype (klass)->type;
9609                 goto handle_enum;
9610         }
9611         default:
9612                 g_error ("type 0x%02x not yet supported in custom attr encoder", simple_type);
9613         }
9614         *retp = p;
9615         *retbuffer = buffer;
9616 }
9617
9618 static void
9619 encode_field_or_prop_type (MonoType *type, char *p, char **retp)
9620 {
9621         if (type->type == MONO_TYPE_VALUETYPE && type->data.klass->enumtype) {
9622                 char *str = type_get_qualified_name (type, NULL);
9623                 int slen = strlen (str);
9624
9625                 *p++ = 0x55;
9626                 /*
9627                  * This seems to be optional...
9628                  * *p++ = 0x80;
9629                  */
9630                 mono_metadata_encode_value (slen, p, &p);
9631                 memcpy (p, str, slen);
9632                 p += slen;
9633                 g_free (str);
9634         } else if (type->type == MONO_TYPE_OBJECT) {
9635                 *p++ = 0x51;
9636         } else if (type->type == MONO_TYPE_CLASS) {
9637                 /* it should be a type: encode_cattr_value () has the check */
9638                 *p++ = 0x50;
9639         } else {
9640                 mono_metadata_encode_value (type->type, p, &p);
9641                 if (type->type == MONO_TYPE_SZARRAY)
9642                         /* See the examples in Partition VI, Annex B */
9643                         encode_field_or_prop_type (&type->data.klass->byval_arg, p, &p);
9644         }
9645
9646         *retp = p;
9647 }
9648
9649 #ifndef DISABLE_REFLECTION_EMIT
9650 static void
9651 encode_named_val (MonoReflectionAssembly *assembly, char *buffer, char *p, char **retbuffer, char **retp, guint32 *buflen, MonoType *type, char *name, MonoObject *value)
9652 {
9653         int len;
9654         /* Preallocate a large enough buffer */
9655         if (type->type == MONO_TYPE_VALUETYPE && type->data.klass->enumtype) {
9656                 char *str = type_get_qualified_name (type, NULL);
9657                 len = strlen (str);
9658                 g_free (str);
9659         } else if (type->type == MONO_TYPE_SZARRAY && type->data.klass->enumtype) {
9660                 char *str = type_get_qualified_name (&type->data.klass->byval_arg, NULL);
9661                 len = strlen (str);
9662                 g_free (str);
9663         } else {
9664                 len = 0;
9665         }
9666         len += strlen (name);
9667
9668         if ((p-buffer) + 20 + len >= *buflen) {
9669                 char *newbuf;
9670                 *buflen *= 2;
9671                 *buflen += len;
9672                 newbuf = g_realloc (buffer, *buflen);
9673                 p = newbuf + (p-buffer);
9674                 buffer = newbuf;
9675         }
9676
9677         encode_field_or_prop_type (type, p, &p);
9678
9679         len = strlen (name);
9680         mono_metadata_encode_value (len, p, &p);
9681         memcpy (p, name, len);
9682         p += len;
9683         encode_cattr_value (assembly->assembly, buffer, p, &buffer, &p, buflen, type, value, NULL);
9684         *retp = p;
9685         *retbuffer = buffer;
9686 }
9687
9688 /*
9689  * mono_reflection_get_custom_attrs_blob:
9690  * @ctor: custom attribute constructor
9691  * @ctorArgs: arguments o the constructor
9692  * @properties:
9693  * @propValues:
9694  * @fields:
9695  * @fieldValues:
9696  * 
9697  * Creates the blob of data that needs to be saved in the metadata and that represents
9698  * the custom attributed described by @ctor, @ctorArgs etc.
9699  * Returns: a Byte array representing the blob of data.
9700  */
9701 MonoArray*
9702 mono_reflection_get_custom_attrs_blob (MonoReflectionAssembly *assembly, MonoObject *ctor, MonoArray *ctorArgs, MonoArray *properties, MonoArray *propValues, MonoArray *fields, MonoArray* fieldValues) 
9703 {
9704         MonoArray *result;
9705         MonoMethodSignature *sig;
9706         MonoObject *arg;
9707         char *buffer, *p;
9708         guint32 buflen, i;
9709
9710         MONO_ARCH_SAVE_REGS;
9711
9712         if (strcmp (ctor->vtable->klass->name, "MonoCMethod")) {
9713                 /* sig is freed later so allocate it in the heap */
9714                 sig = ctor_builder_to_signature (NULL, (MonoReflectionCtorBuilder*)ctor);
9715         } else {
9716                 sig = mono_method_signature (((MonoReflectionMethod*)ctor)->method);
9717         }
9718
9719         g_assert (mono_array_length (ctorArgs) == sig->param_count);
9720         buflen = 256;
9721         p = buffer = g_malloc (buflen);
9722         /* write the prolog */
9723         *p++ = 1;
9724         *p++ = 0;
9725         for (i = 0; i < sig->param_count; ++i) {
9726                 arg = mono_array_get (ctorArgs, MonoObject*, i);
9727                 encode_cattr_value (assembly->assembly, buffer, p, &buffer, &p, &buflen, sig->params [i], arg, NULL);
9728         }
9729         i = 0;
9730         if (properties)
9731                 i += mono_array_length (properties);
9732         if (fields)
9733                 i += mono_array_length (fields);
9734         *p++ = i & 0xff;
9735         *p++ = (i >> 8) & 0xff;
9736         if (properties) {
9737                 MonoObject *prop;
9738                 for (i = 0; i < mono_array_length (properties); ++i) {
9739                         MonoType *ptype;
9740                         char *pname;
9741
9742                         prop = mono_array_get (properties, gpointer, i);
9743                         get_prop_name_and_type (prop, &pname, &ptype);
9744                         *p++ = 0x54; /* PROPERTY signature */
9745                         encode_named_val (assembly, buffer, p, &buffer, &p, &buflen, ptype, pname, (MonoObject*)mono_array_get (propValues, gpointer, i));
9746                         g_free (pname);
9747                 }
9748         }
9749
9750         if (fields) {
9751                 MonoObject *field;
9752                 for (i = 0; i < mono_array_length (fields); ++i) {
9753                         MonoType *ftype;
9754                         char *fname;
9755
9756                         field = mono_array_get (fields, gpointer, i);
9757                         get_field_name_and_type (field, &fname, &ftype);
9758                         *p++ = 0x53; /* FIELD signature */
9759                         encode_named_val (assembly, buffer, p, &buffer, &p, &buflen, ftype, fname, (MonoObject*)mono_array_get (fieldValues, gpointer, i));
9760                         g_free (fname);
9761                 }
9762         }
9763
9764         g_assert (p - buffer <= buflen);
9765         buflen = p - buffer;
9766         result = mono_array_new (mono_domain_get (), mono_defaults.byte_class, buflen);
9767         p = mono_array_addr (result, char, 0);
9768         memcpy (p, buffer, buflen);
9769         g_free (buffer);
9770         if (strcmp (ctor->vtable->klass->name, "MonoCMethod"))
9771                 g_free (sig);
9772         return result;
9773 }
9774
9775 /*
9776  * mono_reflection_setup_internal_class:
9777  * @tb: a TypeBuilder object
9778  *
9779  * Creates a MonoClass that represents the TypeBuilder.
9780  * This is a trick that lets us simplify a lot of reflection code
9781  * (and will allow us to support Build and Run assemblies easier).
9782  */
9783 void
9784 mono_reflection_setup_internal_class (MonoReflectionTypeBuilder *tb)
9785 {
9786         MonoError error;
9787         MonoClass *klass, *parent;
9788
9789         MONO_ARCH_SAVE_REGS;
9790
9791         RESOLVE_TYPE (tb->parent);
9792
9793         mono_loader_lock ();
9794
9795         if (tb->parent) {
9796                 /* check so we can compile corlib correctly */
9797                 if (strcmp (mono_object_class (tb->parent)->name, "TypeBuilder") == 0) {
9798                         /* mono_class_setup_mono_type () guaranteess type->data.klass is valid */
9799                         parent = mono_reflection_type_get_handle ((MonoReflectionType*)tb->parent)->data.klass;
9800                 } else {
9801                         parent = mono_class_from_mono_type (mono_reflection_type_get_handle ((MonoReflectionType*)tb->parent));
9802                 }
9803         } else {
9804                 parent = NULL;
9805         }
9806         
9807         /* the type has already being created: it means we just have to change the parent */
9808         if (tb->type.type) {
9809                 klass = mono_class_from_mono_type (tb->type.type);
9810                 klass->parent = NULL;
9811                 /* fool mono_class_setup_parent */
9812                 klass->supertypes = NULL;
9813                 mono_class_setup_parent (klass, parent);
9814                 mono_class_setup_mono_type (klass);
9815                 mono_loader_unlock ();
9816                 return;
9817         }
9818
9819         klass = mono_image_alloc0 (&tb->module->dynamic_image->image, sizeof (MonoClass));
9820
9821         klass->image = &tb->module->dynamic_image->image;
9822
9823         klass->inited = 1; /* we lie to the runtime */
9824         klass->name = mono_string_to_utf8_image (klass->image, tb->name, &error);
9825         if (!mono_error_ok (&error))
9826                 goto failure;
9827         klass->name_space = mono_string_to_utf8_image (klass->image, tb->nspace, &error);
9828         if (!mono_error_ok (&error))
9829                 goto failure;
9830         klass->type_token = MONO_TOKEN_TYPE_DEF | tb->table_idx;
9831         klass->flags = tb->attrs;
9832         
9833         mono_profiler_class_event (klass, MONO_PROFILE_START_LOAD);
9834
9835         klass->element_class = klass;
9836
9837         if (mono_class_get_ref_info (klass) == NULL) {
9838
9839                 mono_class_set_ref_info (klass, tb);
9840
9841                 /* Put into cache so mono_class_get () will find it.
9842                 Skip nested types as those should not be available on the global scope. */
9843                 if (!tb->nesting_type) {
9844                         mono_image_add_to_name_cache (klass->image, klass->name_space, klass->name, tb->table_idx);
9845                 } else {
9846                         mono_image_append_class_to_reflection_info_set (klass);
9847                 }
9848         } else {
9849                 g_assert (mono_class_get_ref_info (klass) == tb);
9850         }
9851
9852         mono_g_hash_table_insert (tb->module->dynamic_image->tokens,
9853                 GUINT_TO_POINTER (MONO_TOKEN_TYPE_DEF | tb->table_idx), tb);
9854
9855         if (parent != NULL) {
9856                 mono_class_setup_parent (klass, parent);
9857         } else if (strcmp (klass->name, "Object") == 0 && strcmp (klass->name_space, "System") == 0) {
9858                 const char *old_n = klass->name;
9859                 /* trick to get relative numbering right when compiling corlib */
9860                 klass->name = "BuildingObject";
9861                 mono_class_setup_parent (klass, mono_defaults.object_class);
9862                 klass->name = old_n;
9863         }
9864
9865         if ((!strcmp (klass->name, "ValueType") && !strcmp (klass->name_space, "System")) ||
9866                         (!strcmp (klass->name, "Object") && !strcmp (klass->name_space, "System")) ||
9867                         (!strcmp (klass->name, "Enum") && !strcmp (klass->name_space, "System"))) {
9868                 klass->instance_size = sizeof (MonoObject);
9869                 klass->size_inited = 1;
9870                 mono_class_setup_vtable_general (klass, NULL, 0, NULL);
9871         }
9872
9873         mono_class_setup_mono_type (klass);
9874
9875         mono_class_setup_supertypes (klass);
9876
9877         /*
9878          * FIXME: handle interfaces.
9879          */
9880
9881         tb->type.type = &klass->byval_arg;
9882
9883         if (tb->nesting_type) {
9884                 g_assert (tb->nesting_type->type);
9885                 klass->nested_in = mono_class_from_mono_type (mono_reflection_type_get_handle (tb->nesting_type));
9886         }
9887
9888         /*g_print ("setup %s as %s (%p)\n", klass->name, ((MonoObject*)tb)->vtable->klass->name, tb);*/
9889
9890         mono_profiler_class_loaded (klass, MONO_PROFILE_OK);
9891         
9892         mono_loader_unlock ();
9893         return;
9894
9895 failure:
9896         mono_loader_unlock ();
9897         mono_error_raise_exception (&error);
9898 }
9899
9900 /*
9901  * mono_reflection_setup_generic_class:
9902  * @tb: a TypeBuilder object
9903  *
9904  * Setup the generic class before adding the first generic parameter.
9905  */
9906 void
9907 mono_reflection_setup_generic_class (MonoReflectionTypeBuilder *tb)
9908 {
9909 }
9910
9911 /*
9912  * mono_reflection_create_generic_class:
9913  * @tb: a TypeBuilder object
9914  *
9915  * Creates the generic class after all generic parameters have been added.
9916  */
9917 void
9918 mono_reflection_create_generic_class (MonoReflectionTypeBuilder *tb)
9919 {
9920         MonoClass *klass;
9921         int count, i;
9922
9923         MONO_ARCH_SAVE_REGS;
9924
9925         klass = mono_class_from_mono_type (tb->type.type);
9926
9927         count = tb->generic_params ? mono_array_length (tb->generic_params) : 0;
9928
9929         if (klass->generic_container || (count == 0))
9930                 return;
9931
9932         g_assert (tb->generic_container && (tb->generic_container->owner.klass == klass));
9933
9934         klass->generic_container = mono_image_alloc0 (klass->image, sizeof (MonoGenericContainer));
9935
9936         klass->generic_container->owner.klass = klass;
9937         klass->generic_container->type_argc = count;
9938         klass->generic_container->type_params = mono_image_alloc0 (klass->image, sizeof (MonoGenericParamFull) * count);
9939
9940         klass->is_generic = 1;
9941
9942         for (i = 0; i < count; i++) {
9943                 MonoReflectionGenericParam *gparam = mono_array_get (tb->generic_params, gpointer, i);
9944                 MonoGenericParamFull *param = (MonoGenericParamFull *) mono_reflection_type_get_handle ((MonoReflectionType*)gparam)->data.generic_param;
9945                 klass->generic_container->type_params [i] = *param;
9946                 /*Make sure we are a diferent type instance */
9947                 klass->generic_container->type_params [i].param.owner = klass->generic_container;
9948                 klass->generic_container->type_params [i].info.pklass = NULL;
9949                 klass->generic_container->type_params [i].info.flags = gparam->attrs;
9950
9951                 g_assert (klass->generic_container->type_params [i].param.owner);
9952         }
9953
9954         klass->generic_container->context.class_inst = mono_get_shared_generic_inst (klass->generic_container);
9955 }
9956
9957 /*
9958  * mono_reflection_create_internal_class:
9959  * @tb: a TypeBuilder object
9960  *
9961  * Actually create the MonoClass that is associated with the TypeBuilder.
9962  */
9963 void
9964 mono_reflection_create_internal_class (MonoReflectionTypeBuilder *tb)
9965 {
9966         MonoClass *klass;
9967
9968         MONO_ARCH_SAVE_REGS;
9969
9970         klass = mono_class_from_mono_type (tb->type.type);
9971
9972         mono_loader_lock ();
9973         if (klass->enumtype && mono_class_enum_basetype (klass) == NULL) {
9974                 MonoReflectionFieldBuilder *fb;
9975                 MonoClass *ec;
9976                 MonoType *enum_basetype;
9977
9978                 g_assert (tb->fields != NULL);
9979                 g_assert (mono_array_length (tb->fields) >= 1);
9980
9981                 fb = mono_array_get (tb->fields, MonoReflectionFieldBuilder*, 0);
9982
9983                 if (!mono_type_is_valid_enum_basetype (mono_reflection_type_get_handle ((MonoReflectionType*)fb->type))) {
9984                         mono_loader_unlock ();
9985                         return;
9986                 }
9987
9988                 enum_basetype = mono_reflection_type_get_handle ((MonoReflectionType*)fb->type);
9989                 klass->element_class = mono_class_from_mono_type (enum_basetype);
9990                 if (!klass->element_class)
9991                         klass->element_class = mono_class_from_mono_type (enum_basetype);
9992
9993                 /*
9994                  * get the element_class from the current corlib.
9995                  */
9996                 ec = default_class_from_mono_type (enum_basetype);
9997                 klass->instance_size = ec->instance_size;
9998                 klass->size_inited = 1;
9999                 /* 
10000                  * this is almost safe to do with enums and it's needed to be able
10001                  * to create objects of the enum type (for use in SetConstant).
10002                  */
10003                 /* FIXME: Does this mean enums can't have method overrides ? */
10004                 mono_class_setup_vtable_general (klass, NULL, 0, NULL);
10005         }
10006         mono_loader_unlock ();
10007 }
10008
10009 static MonoMarshalSpec*
10010 mono_marshal_spec_from_builder (MonoImage *image, MonoAssembly *assembly,
10011                                                                 MonoReflectionMarshal *minfo)
10012 {
10013         MonoMarshalSpec *res;
10014
10015         res = image_g_new0 (image, MonoMarshalSpec, 1);
10016         res->native = minfo->type;
10017
10018         switch (minfo->type) {
10019         case MONO_NATIVE_LPARRAY:
10020                 res->data.array_data.elem_type = minfo->eltype;
10021                 if (minfo->has_size) {
10022                         res->data.array_data.param_num = minfo->param_num;
10023                         res->data.array_data.num_elem = minfo->count;
10024                         res->data.array_data.elem_mult = minfo->param_num == -1 ? 0 : 1;
10025                 }
10026                 else {
10027                         res->data.array_data.param_num = -1;
10028                         res->data.array_data.num_elem = -1;
10029                         res->data.array_data.elem_mult = -1;
10030                 }
10031                 break;
10032
10033         case MONO_NATIVE_BYVALTSTR:
10034         case MONO_NATIVE_BYVALARRAY:
10035                 res->data.array_data.num_elem = minfo->count;
10036                 break;
10037
10038         case MONO_NATIVE_CUSTOM:
10039                 if (minfo->marshaltyperef)
10040                         res->data.custom_data.custom_name =
10041                                 type_get_fully_qualified_name (mono_reflection_type_get_handle ((MonoReflectionType*)minfo->marshaltyperef));
10042                 if (minfo->mcookie)
10043                         res->data.custom_data.cookie = mono_string_to_utf8 (minfo->mcookie);
10044                 break;
10045
10046         default:
10047                 break;
10048         }
10049
10050         return res;
10051 }
10052 #endif /* !DISABLE_REFLECTION_EMIT */
10053
10054 MonoReflectionMarshalAsAttribute*
10055 mono_reflection_marshal_as_attribute_from_marshal_spec (MonoDomain *domain, MonoClass *klass,
10056                                                                                    MonoMarshalSpec *spec)
10057 {
10058         static MonoClass *System_Reflection_Emit_MarshalAsAttribute;
10059         MonoReflectionMarshalAsAttribute *minfo;
10060         MonoType *mtype;
10061
10062         if (!System_Reflection_Emit_MarshalAsAttribute) {
10063                 System_Reflection_Emit_MarshalAsAttribute = mono_class_from_name (
10064                    mono_defaults.corlib, "System.Runtime.InteropServices", "MarshalAsAttribute");
10065                 g_assert (System_Reflection_Emit_MarshalAsAttribute);
10066         }
10067
10068         minfo = (MonoReflectionMarshalAsAttribute*)mono_object_new (domain, System_Reflection_Emit_MarshalAsAttribute);
10069         minfo->utype = spec->native;
10070
10071         switch (minfo->utype) {
10072         case MONO_NATIVE_LPARRAY:
10073                 minfo->array_subtype = spec->data.array_data.elem_type;
10074                 minfo->size_const = spec->data.array_data.num_elem;
10075                 if (spec->data.array_data.param_num != -1)
10076                         minfo->size_param_index = spec->data.array_data.param_num;
10077                 break;
10078
10079         case MONO_NATIVE_BYVALTSTR:
10080         case MONO_NATIVE_BYVALARRAY:
10081                 minfo->size_const = spec->data.array_data.num_elem;
10082                 break;
10083
10084         case MONO_NATIVE_CUSTOM:
10085                 if (spec->data.custom_data.custom_name) {
10086                         mtype = mono_reflection_type_from_name (spec->data.custom_data.custom_name, klass->image);
10087                         if (mtype)
10088                                 MONO_OBJECT_SETREF (minfo, marshal_type_ref, mono_type_get_object (domain, mtype));
10089
10090                         MONO_OBJECT_SETREF (minfo, marshal_type, mono_string_new (domain, spec->data.custom_data.custom_name));
10091                 }
10092                 if (spec->data.custom_data.cookie)
10093                         MONO_OBJECT_SETREF (minfo, marshal_cookie, mono_string_new (domain, spec->data.custom_data.cookie));
10094                 break;
10095
10096         default:
10097                 break;
10098         }
10099
10100         return minfo;
10101 }
10102
10103 #ifndef DISABLE_REFLECTION_EMIT
10104 static MonoMethod*
10105 reflection_methodbuilder_to_mono_method (MonoClass *klass,
10106                                          ReflectionMethodBuilder *rmb,
10107                                          MonoMethodSignature *sig)
10108 {
10109         MonoError error;
10110         MonoMethod *m;
10111         MonoMethodWrapper *wrapperm;
10112         MonoMarshalSpec **specs;
10113         MonoReflectionMethodAux *method_aux;
10114         MonoImage *image;
10115         gboolean dynamic;
10116         int i;
10117
10118         mono_error_init (&error);
10119         /*
10120          * Methods created using a MethodBuilder should have their memory allocated
10121          * inside the image mempool, while dynamic methods should have their memory
10122          * malloc'd.
10123          */
10124         dynamic = rmb->refs != NULL;
10125         image = dynamic ? NULL : klass->image;
10126
10127         if (!dynamic)
10128                 g_assert (!klass->generic_class);
10129
10130         mono_loader_lock ();
10131
10132         if ((rmb->attrs & METHOD_ATTRIBUTE_PINVOKE_IMPL) ||
10133                         (rmb->iattrs & METHOD_IMPL_ATTRIBUTE_INTERNAL_CALL))
10134                 m = (MonoMethod *)image_g_new0 (image, MonoMethodPInvoke, 1);
10135         else
10136                 m = (MonoMethod *)image_g_new0 (image, MonoMethodWrapper, 1);
10137
10138         wrapperm = (MonoMethodWrapper*)m;
10139
10140         m->dynamic = dynamic;
10141         m->slot = -1;
10142         m->flags = rmb->attrs;
10143         m->iflags = rmb->iattrs;
10144         m->name = mono_string_to_utf8_image_ignore (image, rmb->name);
10145         m->klass = klass;
10146         m->signature = sig;
10147         m->sre_method = TRUE;
10148         m->skip_visibility = rmb->skip_visibility;
10149         if (rmb->table_idx)
10150                 m->token = MONO_TOKEN_METHOD_DEF | (*rmb->table_idx);
10151
10152         if (m->iflags & METHOD_IMPL_ATTRIBUTE_INTERNAL_CALL) {
10153                 if (klass == mono_defaults.string_class && !strcmp (m->name, ".ctor"))
10154                         m->string_ctor = 1;
10155
10156                 m->signature->pinvoke = 1;
10157         } else if (m->flags & METHOD_ATTRIBUTE_PINVOKE_IMPL) {
10158                 m->signature->pinvoke = 1;
10159
10160                 method_aux = image_g_new0 (image, MonoReflectionMethodAux, 1);
10161
10162                 method_aux->dllentry = rmb->dllentry ? mono_string_to_utf8_image (image, rmb->dllentry, &error) : image_strdup (image, m->name);
10163                 g_assert (mono_error_ok (&error));
10164                 method_aux->dll = mono_string_to_utf8_image (image, rmb->dll, &error);
10165                 g_assert (mono_error_ok (&error));
10166                 
10167                 ((MonoMethodPInvoke*)m)->piflags = (rmb->native_cc << 8) | (rmb->charset ? (rmb->charset - 1) * 2 : 0) | rmb->extra_flags;
10168
10169                 if (klass->image->dynamic)
10170                         g_hash_table_insert (((MonoDynamicImage*)klass->image)->method_aux_hash, m, method_aux);
10171
10172                 mono_loader_unlock ();
10173
10174                 return m;
10175         } else if (!(m->flags & METHOD_ATTRIBUTE_ABSTRACT) &&
10176                            !(m->iflags & METHOD_IMPL_ATTRIBUTE_RUNTIME)) {
10177                 MonoMethodHeader *header;
10178                 guint32 code_size;
10179                 gint32 max_stack, i;
10180                 gint32 num_locals = 0;
10181                 gint32 num_clauses = 0;
10182                 guint8 *code;
10183
10184                 if (rmb->ilgen) {
10185                         code = mono_array_addr (rmb->ilgen->code, guint8, 0);
10186                         code_size = rmb->ilgen->code_len;
10187                         max_stack = rmb->ilgen->max_stack;
10188                         num_locals = rmb->ilgen->locals ? mono_array_length (rmb->ilgen->locals) : 0;
10189                         if (rmb->ilgen->ex_handlers)
10190                                 num_clauses = method_count_clauses (rmb->ilgen);
10191                 } else {
10192                         if (rmb->code) {
10193                                 code = mono_array_addr (rmb->code, guint8, 0);
10194                                 code_size = mono_array_length (rmb->code);
10195                                 /* we probably need to run a verifier on the code... */
10196                                 max_stack = 8; 
10197                         }
10198                         else {
10199                                 code = NULL;
10200                                 code_size = 0;
10201                                 max_stack = 8;
10202                         }
10203                 }
10204
10205                 header = image_g_malloc0 (image, MONO_SIZEOF_METHOD_HEADER + num_locals * sizeof (MonoType*));
10206                 header->code_size = code_size;
10207                 header->code = image_g_malloc (image, code_size);
10208                 memcpy ((char*)header->code, code, code_size);
10209                 header->max_stack = max_stack;
10210                 header->init_locals = rmb->init_locals;
10211                 header->num_locals = num_locals;
10212
10213                 for (i = 0; i < num_locals; ++i) {
10214                         MonoReflectionLocalBuilder *lb = 
10215                                 mono_array_get (rmb->ilgen->locals, MonoReflectionLocalBuilder*, i);
10216
10217                         header->locals [i] = image_g_new0 (image, MonoType, 1);
10218                         memcpy (header->locals [i], mono_reflection_type_get_handle ((MonoReflectionType*)lb->type), MONO_SIZEOF_TYPE);
10219                 }
10220
10221                 header->num_clauses = num_clauses;
10222                 if (num_clauses) {
10223                         header->clauses = method_encode_clauses (image, (MonoDynamicImage*)klass->image,
10224                                  rmb->ilgen, num_clauses);
10225                 }
10226
10227                 wrapperm->header = header;
10228         }
10229
10230         if (rmb->generic_params) {
10231                 int count = mono_array_length (rmb->generic_params);
10232                 MonoGenericContainer *container = rmb->generic_container;
10233
10234                 g_assert (container);
10235
10236                 container->type_argc = count;
10237                 container->type_params = image_g_new0 (image, MonoGenericParamFull, count);
10238                 container->owner.method = m;
10239
10240                 m->is_generic = TRUE;
10241                 mono_method_set_generic_container (m, container);
10242
10243                 for (i = 0; i < count; i++) {
10244                         MonoReflectionGenericParam *gp =
10245                                 mono_array_get (rmb->generic_params, MonoReflectionGenericParam*, i);
10246                         MonoGenericParamFull *param = (MonoGenericParamFull *) mono_reflection_type_get_handle ((MonoReflectionType*)gp)->data.generic_param;
10247                         container->type_params [i] = *param;
10248                 }
10249
10250                 /*
10251                  * The method signature might have pointers to generic parameters that belong to other methods.
10252                  * This is a valid SRE case, but the resulting method signature must be encoded using the proper
10253                  * generic parameters.
10254                  */
10255                 for (i = 0; i < m->signature->param_count; ++i) {
10256                         MonoType *t = m->signature->params [i];
10257                         if (t->type == MONO_TYPE_MVAR) {
10258                                 MonoGenericParam *gparam =  t->data.generic_param;
10259                                 if (gparam->num < count) {
10260                                         m->signature->params [i] = mono_metadata_type_dup (image, m->signature->params [i]);
10261                                         m->signature->params [i]->data.generic_param = mono_generic_container_get_param (container, gparam->num);
10262                                 }
10263
10264                         }
10265                 }
10266
10267                 if (klass->generic_container) {
10268                         container->parent = klass->generic_container;
10269                         container->context.class_inst = klass->generic_container->context.class_inst;
10270                 }
10271                 container->context.method_inst = mono_get_shared_generic_inst (container);
10272         }
10273
10274         if (rmb->refs) {
10275                 MonoMethodWrapper *mw = (MonoMethodWrapper*)m;
10276                 int i;
10277                 void **data;
10278
10279                 m->wrapper_type = MONO_WRAPPER_DYNAMIC_METHOD;
10280
10281                 mw->method_data = data = image_g_new (image, gpointer, rmb->nrefs + 1);
10282                 data [0] = GUINT_TO_POINTER (rmb->nrefs);
10283                 for (i = 0; i < rmb->nrefs; ++i)
10284                         data [i + 1] = rmb->refs [i];
10285         }
10286
10287         method_aux = NULL;
10288
10289         /* Parameter info */
10290         if (rmb->pinfo) {
10291                 if (!method_aux)
10292                         method_aux = image_g_new0 (image, MonoReflectionMethodAux, 1);
10293                 method_aux->param_names = image_g_new0 (image, char *, mono_method_signature (m)->param_count + 1);
10294                 for (i = 0; i <= m->signature->param_count; ++i) {
10295                         MonoReflectionParamBuilder *pb;
10296                         if ((pb = mono_array_get (rmb->pinfo, MonoReflectionParamBuilder*, i))) {
10297                                 if ((i > 0) && (pb->attrs)) {
10298                                         /* Make a copy since it might point to a shared type structure */
10299                                         m->signature->params [i - 1] = mono_metadata_type_dup (klass->image, m->signature->params [i - 1]);
10300                                         m->signature->params [i - 1]->attrs = pb->attrs;
10301                                 }
10302
10303                                 if (pb->attrs & PARAM_ATTRIBUTE_HAS_DEFAULT) {
10304                                         MonoDynamicImage *assembly;
10305                                         guint32 idx, def_type, len;
10306                                         char *p;
10307                                         const char *p2;
10308
10309                                         if (!method_aux->param_defaults) {
10310                                                 method_aux->param_defaults = image_g_new0 (image, guint8*, m->signature->param_count + 1);
10311                                                 method_aux->param_default_types = image_g_new0 (image, guint32, m->signature->param_count + 1);
10312                                         }
10313                                         assembly = (MonoDynamicImage*)klass->image;
10314                                         idx = encode_constant (assembly, pb->def_value, &def_type);
10315                                         /* Copy the data from the blob since it might get realloc-ed */
10316                                         p = assembly->blob.data + idx;
10317                                         len = mono_metadata_decode_blob_size (p, &p2);
10318                                         len += p2 - p;
10319                                         method_aux->param_defaults [i] = image_g_malloc (image, len);
10320                                         method_aux->param_default_types [i] = def_type;
10321                                         memcpy ((gpointer)method_aux->param_defaults [i], p, len);
10322                                 }
10323
10324                                 if (pb->name) {
10325                                         method_aux->param_names [i] = mono_string_to_utf8_image (image, pb->name, &error);
10326                                         g_assert (mono_error_ok (&error));
10327                                 }
10328                                 if (pb->cattrs) {
10329                                         if (!method_aux->param_cattr)
10330                                                 method_aux->param_cattr = image_g_new0 (image, MonoCustomAttrInfo*, m->signature->param_count + 1);
10331                                         method_aux->param_cattr [i] = mono_custom_attrs_from_builders (image, klass->image, pb->cattrs);
10332                                 }
10333                         }
10334                 }
10335         }
10336
10337         /* Parameter marshalling */
10338         specs = NULL;
10339         if (rmb->pinfo)         
10340                 for (i = 0; i < mono_array_length (rmb->pinfo); ++i) {
10341                         MonoReflectionParamBuilder *pb;
10342                         if ((pb = mono_array_get (rmb->pinfo, MonoReflectionParamBuilder*, i))) {
10343                                 if (pb->marshal_info) {
10344                                         if (specs == NULL)
10345                                                 specs = image_g_new0 (image, MonoMarshalSpec*, sig->param_count + 1);
10346                                         specs [pb->position] = 
10347                                                 mono_marshal_spec_from_builder (image, klass->image->assembly, pb->marshal_info);
10348                                 }
10349                         }
10350                 }
10351         if (specs != NULL) {
10352                 if (!method_aux)
10353                         method_aux = image_g_new0 (image, MonoReflectionMethodAux, 1);
10354                 method_aux->param_marshall = specs;
10355         }
10356
10357         if (klass->image->dynamic && method_aux)
10358                 g_hash_table_insert (((MonoDynamicImage*)klass->image)->method_aux_hash, m, method_aux);
10359
10360         mono_loader_unlock ();
10361
10362         return m;
10363 }       
10364
10365 static MonoMethod*
10366 ctorbuilder_to_mono_method (MonoClass *klass, MonoReflectionCtorBuilder* mb)
10367 {
10368         ReflectionMethodBuilder rmb;
10369         MonoMethodSignature *sig;
10370
10371         mono_loader_lock ();
10372         sig = ctor_builder_to_signature (klass->image, mb);
10373         mono_loader_unlock ();
10374
10375         reflection_methodbuilder_from_ctor_builder (&rmb, mb);
10376
10377         mb->mhandle = reflection_methodbuilder_to_mono_method (klass, &rmb, sig);
10378         mono_save_custom_attrs (klass->image, mb->mhandle, mb->cattrs);
10379
10380         /* If we are in a generic class, we might be called multiple times from inflate_method */
10381         if (!((MonoDynamicImage*)(MonoDynamicImage*)klass->image)->save && !klass->generic_container) {
10382                 /* ilgen is no longer needed */
10383                 mb->ilgen = NULL;
10384         }
10385
10386         return mb->mhandle;
10387 }
10388
10389 static MonoMethod*
10390 methodbuilder_to_mono_method (MonoClass *klass, MonoReflectionMethodBuilder* mb)
10391 {
10392         ReflectionMethodBuilder rmb;
10393         MonoMethodSignature *sig;
10394
10395         mono_loader_lock ();
10396         sig = method_builder_to_signature (klass->image, mb);
10397         mono_loader_unlock ();
10398
10399         reflection_methodbuilder_from_method_builder (&rmb, mb);
10400
10401         mb->mhandle = reflection_methodbuilder_to_mono_method (klass, &rmb, sig);
10402         mono_save_custom_attrs (klass->image, mb->mhandle, mb->cattrs);
10403
10404         /* If we are in a generic class, we might be called multiple times from inflate_method */
10405         if (!((MonoDynamicImage*)(MonoDynamicImage*)klass->image)->save && !klass->generic_container) {
10406                 /* ilgen is no longer needed */
10407                 mb->ilgen = NULL;
10408         }
10409         return mb->mhandle;
10410 }
10411
10412 static MonoClassField*
10413 fieldbuilder_to_mono_class_field (MonoClass *klass, MonoReflectionFieldBuilder* fb)
10414 {
10415         MonoClassField *field;
10416         MonoType *custom;
10417         MonoError error;
10418
10419         field = g_new0 (MonoClassField, 1);
10420
10421         field->name = mono_string_to_utf8_image (klass->image, fb->name, &error);
10422         g_assert (mono_error_ok (&error));
10423         if (fb->attrs || fb->modreq || fb->modopt) {
10424                 field->type = mono_metadata_type_dup (NULL, mono_reflection_type_get_handle ((MonoReflectionType*)fb->type));
10425                 field->type->attrs = fb->attrs;
10426
10427                 g_assert (klass->image->dynamic);
10428                 custom = add_custom_modifiers ((MonoDynamicImage*)klass->image, field->type, fb->modreq, fb->modopt);
10429                 g_free (field->type);
10430                 field->type = mono_metadata_type_dup (klass->image, custom);
10431                 g_free (custom);
10432         } else {
10433                 field->type = mono_reflection_type_get_handle ((MonoReflectionType*)fb->type);
10434         }
10435         if (fb->offset != -1)
10436                 field->offset = fb->offset;
10437         field->parent = klass;
10438         mono_save_custom_attrs (klass->image, field, fb->cattrs);
10439
10440         // FIXME: Can't store fb->def_value/RVA, is it needed for field_on_insts ?
10441
10442         return field;
10443 }
10444 #endif
10445
10446 MonoType*
10447 mono_reflection_bind_generic_parameters (MonoReflectionType *type, int type_argc, MonoType **types)
10448 {
10449         MonoClass *klass;
10450         MonoReflectionTypeBuilder *tb = NULL;
10451         gboolean is_dynamic = FALSE;
10452         MonoDomain *domain;
10453         MonoClass *geninst;
10454
10455         mono_loader_lock ();
10456
10457         domain = mono_object_domain (type);
10458
10459         if (is_sre_type_builder (mono_object_class (type))) {
10460                 tb = (MonoReflectionTypeBuilder *) type;
10461
10462                 is_dynamic = TRUE;
10463         } else if (is_sre_generic_instance (mono_object_class (type))) {
10464                 MonoReflectionGenericClass *rgi = (MonoReflectionGenericClass *) type;
10465                 MonoReflectionType *gtd = rgi->generic_type;
10466
10467                 if (is_sre_type_builder (mono_object_class (gtd))) {
10468                         tb = (MonoReflectionTypeBuilder *)gtd;
10469                         is_dynamic = TRUE;
10470                 }
10471         }
10472
10473         /* FIXME: fix the CreateGenericParameters protocol to avoid the two stage setup of TypeBuilders */
10474         if (tb && tb->generic_container)
10475                 mono_reflection_create_generic_class (tb);
10476
10477         klass = mono_class_from_mono_type (mono_reflection_type_get_handle (type));
10478         if (!klass->generic_container) {
10479                 mono_loader_unlock ();
10480                 return NULL;
10481         }
10482
10483         if (klass->wastypebuilder) {
10484                 tb = (MonoReflectionTypeBuilder *) mono_class_get_ref_info (klass);
10485
10486                 is_dynamic = TRUE;
10487         }
10488
10489         mono_loader_unlock ();
10490
10491         geninst = mono_class_bind_generic_parameters (klass, type_argc, types, is_dynamic);
10492
10493         return &geninst->byval_arg;
10494 }
10495
10496 MonoClass*
10497 mono_class_bind_generic_parameters (MonoClass *klass, int type_argc, MonoType **types, gboolean is_dynamic)
10498 {
10499         MonoGenericClass *gclass;
10500         MonoGenericInst *inst;
10501
10502         g_assert (klass->generic_container);
10503
10504         inst = mono_metadata_get_generic_inst (type_argc, types);
10505         gclass = mono_metadata_lookup_generic_class (klass, inst, is_dynamic);
10506
10507         return mono_generic_class_get_class (gclass);
10508 }
10509
10510 MonoReflectionMethod*
10511 mono_reflection_bind_generic_method_parameters (MonoReflectionMethod *rmethod, MonoArray *types)
10512 {
10513         MonoClass *klass;
10514         MonoMethod *method, *inflated;
10515         MonoMethodInflated *imethod;
10516         MonoGenericContext tmp_context;
10517         MonoGenericInst *ginst;
10518         MonoType **type_argv;
10519         int count, i;
10520
10521         MONO_ARCH_SAVE_REGS;
10522
10523         /*FIXME but this no longer should happen*/
10524         if (!strcmp (rmethod->object.vtable->klass->name, "MethodBuilder")) {
10525 #ifndef DISABLE_REFLECTION_EMIT
10526                 MonoReflectionMethodBuilder *mb = NULL;
10527                 MonoReflectionTypeBuilder *tb;
10528                 MonoClass *klass;
10529
10530                 mb = (MonoReflectionMethodBuilder *) rmethod;
10531                 tb = (MonoReflectionTypeBuilder *) mb->type;
10532                 klass = mono_class_from_mono_type (mono_reflection_type_get_handle ((MonoReflectionType*)tb));
10533
10534                 method = methodbuilder_to_mono_method (klass, mb);
10535 #else
10536                 g_assert_not_reached ();
10537                 method = NULL;
10538 #endif
10539         } else {
10540                 method = rmethod->method;
10541         }
10542
10543         klass = method->klass;
10544
10545         if (method->is_inflated)
10546                 method = ((MonoMethodInflated *) method)->declaring;
10547
10548         count = mono_method_signature (method)->generic_param_count;
10549         if (count != mono_array_length (types))
10550                 return NULL;
10551
10552         type_argv = g_new0 (MonoType *, count);
10553         for (i = 0; i < count; i++) {
10554                 MonoReflectionType *garg = mono_array_get (types, gpointer, i);
10555                 type_argv [i] = mono_reflection_type_get_handle (garg);
10556         }
10557         ginst = mono_metadata_get_generic_inst (count, type_argv);
10558         g_free (type_argv);
10559
10560         tmp_context.class_inst = klass->generic_class ? klass->generic_class->context.class_inst : NULL;
10561         tmp_context.method_inst = ginst;
10562
10563         inflated = mono_class_inflate_generic_method (method, &tmp_context);
10564         imethod = (MonoMethodInflated *) inflated;
10565
10566         /*FIXME but I think this is no longer necessary*/
10567         if (method->klass->image->dynamic) {
10568                 MonoDynamicImage *image = (MonoDynamicImage*)method->klass->image;
10569                 /*
10570                  * This table maps metadata structures representing inflated methods/fields
10571                  * to the reflection objects representing their generic definitions.
10572                  */
10573                 mono_image_lock ((MonoImage*)image);
10574                 mono_g_hash_table_insert (image->generic_def_objects, imethod, rmethod);
10575                 mono_image_unlock ((MonoImage*)image);
10576         }
10577
10578         if (!mono_verifier_is_method_valid_generic_instantiation (inflated))
10579                 mono_raise_exception (mono_get_exception_argument ("typeArguments", "Invalid generic arguments"));
10580         
10581         return mono_method_get_object (mono_object_domain (rmethod), inflated, NULL);
10582 }
10583
10584 #ifndef DISABLE_REFLECTION_EMIT
10585
10586 static MonoMethod *
10587 inflate_mono_method (MonoClass *klass, MonoMethod *method, MonoObject *obj)
10588 {
10589         MonoMethodInflated *imethod;
10590         MonoGenericContext *context;
10591         int i;
10592
10593         /*
10594          * With generic code sharing the klass might not be inflated.
10595          * This can happen because classes inflated with their own
10596          * type arguments are "normalized" to the uninflated class.
10597          */
10598         if (!klass->generic_class)
10599                 return method;
10600
10601         context = mono_class_get_context (klass);
10602
10603         if (klass->method.count && klass->methods) {
10604                 /* Find the already created inflated method */
10605                 for (i = 0; i < klass->method.count; ++i) {
10606                         g_assert (klass->methods [i]->is_inflated);
10607                         if (((MonoMethodInflated*)klass->methods [i])->declaring == method)
10608                                 break;
10609                 }
10610                 g_assert (i < klass->method.count);
10611                 imethod = (MonoMethodInflated*)klass->methods [i];
10612         } else {
10613                 imethod = (MonoMethodInflated *) mono_class_inflate_generic_method_full (method, klass, context);
10614         }
10615
10616         if (method->is_generic && method->klass->image->dynamic) {
10617                 MonoDynamicImage *image = (MonoDynamicImage*)method->klass->image;
10618
10619                 mono_image_lock ((MonoImage*)image);
10620                 mono_g_hash_table_insert (image->generic_def_objects, imethod, obj);
10621                 mono_image_unlock ((MonoImage*)image);
10622         }
10623         return (MonoMethod *) imethod;
10624 }
10625
10626 static MonoMethod *
10627 inflate_method (MonoReflectionType *type, MonoObject *obj)
10628 {
10629         MonoMethod *method;
10630         MonoClass *gklass;
10631
10632         MonoClass *type_class = mono_object_class (type);
10633
10634         if (is_sre_generic_instance (type_class)) {
10635                 MonoReflectionGenericClass *mgc = (MonoReflectionGenericClass*)type;
10636                 gklass = mono_class_from_mono_type (mono_reflection_type_get_handle ((MonoReflectionType*)mgc->generic_type));
10637         } else if (is_sre_type_builder (type_class)) {
10638                 gklass = mono_class_from_mono_type (mono_reflection_type_get_handle (type));
10639         } else if (type->type) {
10640                 gklass = mono_class_from_mono_type (type->type);
10641                 gklass = mono_class_get_generic_type_definition (gklass);
10642         } else {
10643                 g_error ("Can't handle type %s", mono_type_get_full_name (mono_object_class (type)));
10644         }
10645
10646         if (!strcmp (obj->vtable->klass->name, "MethodBuilder"))
10647                 if (((MonoReflectionMethodBuilder*)obj)->mhandle)
10648                         method = ((MonoReflectionMethodBuilder*)obj)->mhandle;
10649                 else
10650                         method = methodbuilder_to_mono_method (gklass, (MonoReflectionMethodBuilder *) obj);
10651         else if (!strcmp (obj->vtable->klass->name, "ConstructorBuilder"))
10652                 method = ctorbuilder_to_mono_method (gklass, (MonoReflectionCtorBuilder *) obj);
10653         else if (!strcmp (obj->vtable->klass->name, "MonoMethod") || !strcmp (obj->vtable->klass->name, "MonoCMethod"))
10654                 method = ((MonoReflectionMethod *) obj)->method;
10655         else {
10656                 method = NULL; /* prevent compiler warning */
10657                 g_error ("can't handle type %s", obj->vtable->klass->name);
10658         }
10659
10660         return inflate_mono_method (mono_class_from_mono_type (mono_reflection_type_get_handle ((MonoReflectionType*)type)), method, obj);
10661 }
10662
10663 /*TODO avoid saving custom attrs for generic classes as it's enough to have them on the generic type definition.*/
10664 void
10665 mono_reflection_generic_class_initialize (MonoReflectionGenericClass *type, MonoArray *fields)
10666 {
10667         MonoGenericClass *gclass;
10668         MonoDynamicGenericClass *dgclass;
10669         MonoClass *klass, *gklass;
10670         MonoType *gtype;
10671         int i;
10672
10673         MONO_ARCH_SAVE_REGS;
10674
10675         gtype = mono_reflection_type_get_handle ((MonoReflectionType*)type);
10676         klass = mono_class_from_mono_type (gtype);
10677         g_assert (gtype->type == MONO_TYPE_GENERICINST);
10678         gclass = gtype->data.generic_class;
10679
10680         if (!gclass->is_dynamic)
10681                 return;
10682
10683         dgclass = (MonoDynamicGenericClass *) gclass;
10684
10685         if (dgclass->initialized)
10686                 return;
10687
10688         gklass = gclass->container_class;
10689         mono_class_init (gklass);
10690
10691         dgclass->count_fields = fields ? mono_array_length (fields) : 0;
10692
10693         dgclass->fields = mono_image_set_new0 (gclass->owner, MonoClassField, dgclass->count_fields);
10694         dgclass->field_objects = mono_image_set_new0 (gclass->owner, MonoObject*, dgclass->count_fields);
10695         dgclass->field_generic_types = mono_image_set_new0 (gclass->owner, MonoType*, dgclass->count_fields);
10696
10697         for (i = 0; i < dgclass->count_fields; i++) {
10698                 MonoObject *obj = mono_array_get (fields, gpointer, i);
10699                 MonoClassField *field, *inflated_field = NULL;
10700
10701                 if (!strcmp (obj->vtable->klass->name, "FieldBuilder"))
10702                         inflated_field = field = fieldbuilder_to_mono_class_field (klass, (MonoReflectionFieldBuilder *) obj);
10703                 else if (!strcmp (obj->vtable->klass->name, "MonoField"))
10704                         field = ((MonoReflectionField *) obj)->field;
10705                 else {
10706                         field = NULL; /* prevent compiler warning */
10707                         g_assert_not_reached ();
10708                 }
10709
10710                 dgclass->fields [i] = *field;
10711                 dgclass->fields [i].parent = klass;
10712                 dgclass->fields [i].type = mono_class_inflate_generic_type (
10713                         field->type, mono_generic_class_get_context ((MonoGenericClass *) dgclass));
10714                 dgclass->field_generic_types [i] = field->type;
10715                 MONO_GC_REGISTER_ROOT_IF_MOVING (dgclass->field_objects [i]);
10716                 dgclass->field_objects [i] = obj;
10717
10718                 if (inflated_field) {
10719                         g_free (inflated_field);
10720                 } else {
10721                         dgclass->fields [i].name = mono_image_set_strdup (gclass->owner, dgclass->fields [i].name);
10722                 }
10723         }
10724
10725         dgclass->initialized = TRUE;
10726 }
10727
10728 void
10729 mono_reflection_free_dynamic_generic_class (MonoGenericClass *gclass)
10730 {
10731         MonoDynamicGenericClass *dgclass;
10732         int i;
10733
10734         g_assert (gclass->is_dynamic);
10735
10736         dgclass = (MonoDynamicGenericClass *)gclass;
10737
10738         for (i = 0; i < dgclass->count_fields; ++i) {
10739                 MonoClassField *field = dgclass->fields + i;
10740                 mono_metadata_free_type (field->type);
10741                 MONO_GC_UNREGISTER_ROOT_IF_MOVING (dgclass->field_objects [i]);
10742         }
10743 }
10744
10745 static void
10746 fix_partial_generic_class (MonoClass *klass)
10747 {
10748         MonoClass *gklass = klass->generic_class->container_class;
10749         MonoDynamicGenericClass *dgclass;
10750         int i;
10751
10752         if (klass->wastypebuilder)
10753                 return;
10754
10755         dgclass = (MonoDynamicGenericClass *)  klass->generic_class;
10756         if (klass->parent != gklass->parent) {
10757                 MonoError error;
10758                 MonoType *parent_type = mono_class_inflate_generic_type_checked (&gklass->parent->byval_arg, &klass->generic_class->context, &error);
10759                 if (mono_error_ok (&error)) {
10760                         MonoClass *parent = mono_class_from_mono_type (parent_type);
10761                         mono_metadata_free_type (parent_type);
10762                         if (parent != klass->parent) {
10763                                 /*fool mono_class_setup_parent*/
10764                                 klass->supertypes = NULL;
10765                                 mono_class_setup_parent (klass, parent);
10766                         }
10767                 } else {
10768                         mono_class_set_failure (klass, MONO_EXCEPTION_TYPE_LOAD, NULL);
10769                         mono_error_cleanup (&error);
10770                         if (gklass->wastypebuilder)
10771                                 klass->wastypebuilder = TRUE;
10772                         return;
10773                 }
10774         }
10775
10776         if (!dgclass->initialized)
10777                 return;
10778
10779         if (klass->method.count != gklass->method.count) {
10780                 klass->method.count = gklass->method.count;
10781                 klass->methods = mono_image_alloc (klass->image, sizeof (MonoMethod*) * (klass->method.count + 1));
10782
10783                 for (i = 0; i < klass->method.count; i++) {
10784                         klass->methods [i] = mono_class_inflate_generic_method_full (
10785                                 gklass->methods [i], klass, mono_class_get_context (klass));
10786                 }
10787         }
10788
10789         if (klass->interface_count && klass->interface_count != gklass->interface_count) {
10790                 klass->interface_count = gklass->interface_count;
10791                 klass->interfaces = mono_image_alloc (klass->image, sizeof (MonoClass*) * gklass->interface_count);
10792                 klass->interfaces_packed = NULL; /*make setup_interface_offsets happy*/
10793
10794                 for (i = 0; i < gklass->interface_count; ++i) {
10795                         MonoType *iface_type = mono_class_inflate_generic_type (&gklass->interfaces [i]->byval_arg, mono_class_get_context (klass));
10796                         klass->interfaces [i] = mono_class_from_mono_type (iface_type);
10797                         mono_metadata_free_type (iface_type);
10798
10799                         ensure_runtime_vtable (klass->interfaces [i]);
10800                 }
10801                 klass->interfaces_inited = 1;
10802         }
10803
10804         if (klass->field.count != gklass->field.count) {
10805                 klass->field.count = gklass->field.count;
10806                 klass->fields = image_g_new0 (klass->image, MonoClassField, klass->field.count);
10807
10808                 for (i = 0; i < klass->field.count; i++) {
10809                         klass->fields [i] = gklass->fields [i];
10810                         klass->fields [i].parent = klass;
10811                         klass->fields [i].type = mono_class_inflate_generic_type (gklass->fields [i].type, mono_class_get_context (klass));
10812                 }
10813         }
10814
10815         /*We can only finish with this klass once it's parent has as well*/
10816         if (gklass->wastypebuilder)
10817                 klass->wastypebuilder = TRUE;
10818         return;
10819 }
10820
10821 static void
10822 ensure_generic_class_runtime_vtable (MonoClass *klass)
10823 {
10824         MonoClass *gklass = klass->generic_class->container_class;
10825
10826         ensure_runtime_vtable (gklass); 
10827
10828         fix_partial_generic_class (klass);
10829 }
10830
10831 static void
10832 ensure_runtime_vtable (MonoClass *klass)
10833 {
10834         MonoReflectionTypeBuilder *tb = mono_class_get_ref_info (klass);
10835         int i, num, j;
10836
10837         if (!klass->image->dynamic || (!tb && !klass->generic_class) || klass->wastypebuilder)
10838                 return;
10839         if (klass->parent)
10840                 ensure_runtime_vtable (klass->parent);
10841
10842         if (tb) {
10843                 num = tb->ctors? mono_array_length (tb->ctors): 0;
10844                 num += tb->num_methods;
10845                 klass->method.count = num;
10846                 klass->methods = mono_image_alloc (klass->image, sizeof (MonoMethod*) * num);
10847                 num = tb->ctors? mono_array_length (tb->ctors): 0;
10848                 for (i = 0; i < num; ++i)
10849                         klass->methods [i] = ctorbuilder_to_mono_method (klass, mono_array_get (tb->ctors, MonoReflectionCtorBuilder*, i));
10850                 num = tb->num_methods;
10851                 j = i;
10852                 for (i = 0; i < num; ++i)
10853                         klass->methods [j++] = methodbuilder_to_mono_method (klass, mono_array_get (tb->methods, MonoReflectionMethodBuilder*, i));
10854         
10855                 if (tb->interfaces) {
10856                         klass->interface_count = mono_array_length (tb->interfaces);
10857                         klass->interfaces = mono_image_alloc (klass->image, sizeof (MonoClass*) * klass->interface_count);
10858                         for (i = 0; i < klass->interface_count; ++i) {
10859                                 MonoType *iface = mono_type_array_get_and_resolve (tb->interfaces, i);
10860                                 klass->interfaces [i] = mono_class_from_mono_type (iface);
10861                                 ensure_runtime_vtable (klass->interfaces [i]);
10862                         }
10863                         klass->interfaces_inited = 1;
10864                 }
10865         } else if (klass->generic_class){
10866                 ensure_generic_class_runtime_vtable (klass);
10867         }
10868
10869         if (klass->flags & TYPE_ATTRIBUTE_INTERFACE) {
10870                 int slot_num = 0;
10871                 for (i = 0; i < klass->method.count; ++i) {
10872                         MonoMethod *im = klass->methods [i];
10873                         if (!(im->flags & METHOD_ATTRIBUTE_STATIC))
10874                                 im->slot = slot_num++;
10875                 }
10876                 
10877                 klass->interfaces_packed = NULL; /*make setup_interface_offsets happy*/
10878                 mono_class_setup_interface_offsets (klass);
10879                 mono_class_setup_interface_id (klass);
10880         }
10881
10882         /*
10883          * The generic vtable is needed even if image->run is not set since some
10884          * runtime code like ves_icall_Type_GetMethodsByName depends on 
10885          * method->slot being defined.
10886          */
10887
10888         /* 
10889          * tb->methods could not be freed since it is used for determining 
10890          * overrides during dynamic vtable construction.
10891          */
10892 }
10893
10894 static MonoMethod*
10895 mono_reflection_method_get_handle (MonoObject *method)
10896 {
10897         MonoClass *class = mono_object_class (method);
10898         if (is_sr_mono_method (class) || is_sr_mono_generic_method (class)) {
10899                 MonoReflectionMethod *sr_method = (MonoReflectionMethod*)method;
10900                 return sr_method->method;
10901         }
10902         if (is_sre_method_builder (class)) {
10903                 MonoReflectionMethodBuilder *mb = (MonoReflectionMethodBuilder*)method;
10904                 return mb->mhandle;
10905         }
10906         if (is_sre_method_on_tb_inst (class)) {
10907                 MonoReflectionMethodOnTypeBuilderInst *m = (MonoReflectionMethodOnTypeBuilderInst*)method;
10908                 MonoMethod *result;
10909                 /*FIXME move this to a proper method and unify with resolve_object*/
10910                 if (m->method_args) {
10911                         result = mono_reflection_method_on_tb_inst_get_handle (m);
10912                 } else {
10913                         MonoType *type = mono_reflection_type_get_handle ((MonoReflectionType*)m->inst);
10914                         MonoClass *inflated_klass = mono_class_from_mono_type (type);
10915                         MonoMethod *mono_method;
10916
10917                         if (is_sre_method_builder (mono_object_class (m->mb)))
10918                                 mono_method = ((MonoReflectionMethodBuilder *)m->mb)->mhandle;
10919                         else if (is_sr_mono_method (mono_object_class (m->mb)))
10920                                 mono_method = ((MonoReflectionMethod *)m->mb)->method;
10921                         else
10922                                 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)));
10923
10924                         result = inflate_mono_method (inflated_klass, mono_method, (MonoObject*)m->mb);
10925                 }
10926                 return result;
10927         }
10928
10929         g_error ("Can't handle methods of type %s:%s", class->name_space, class->name);
10930         return NULL;
10931 }
10932
10933 void
10934 mono_reflection_get_dynamic_overrides (MonoClass *klass, MonoMethod ***overrides, int *num_overrides)
10935 {
10936         MonoReflectionTypeBuilder *tb;
10937         int i, j, onum;
10938         MonoReflectionMethod *m;
10939
10940         *overrides = NULL;
10941         *num_overrides = 0;
10942
10943         g_assert (klass->image->dynamic);
10944
10945         if (!mono_class_get_ref_info (klass))
10946                 return;
10947
10948         g_assert (strcmp (((MonoObject*)mono_class_get_ref_info (klass))->vtable->klass->name, "TypeBuilder") == 0);
10949
10950         tb = (MonoReflectionTypeBuilder*)mono_class_get_ref_info (klass);
10951
10952         onum = 0;
10953         if (tb->methods) {
10954                 for (i = 0; i < tb->num_methods; ++i) {
10955                         MonoReflectionMethodBuilder *mb = 
10956                                 mono_array_get (tb->methods, MonoReflectionMethodBuilder*, i);
10957                         if (mb->override_methods)
10958                                 onum += mono_array_length (mb->override_methods);
10959                 }
10960         }
10961
10962         if (onum) {
10963                 *overrides = g_new0 (MonoMethod*, onum * 2);
10964
10965                 onum = 0;
10966                 for (i = 0; i < tb->num_methods; ++i) {
10967                         MonoReflectionMethodBuilder *mb = 
10968                                 mono_array_get (tb->methods, MonoReflectionMethodBuilder*, i);
10969                         if (mb->override_methods) {
10970                                 for (j = 0; j < mono_array_length (mb->override_methods); ++j) {
10971                                         m = mono_array_get (mb->override_methods, MonoReflectionMethod*, j);
10972
10973                                         (*overrides) [onum * 2] = mono_reflection_method_get_handle ((MonoObject*)m);
10974                                         (*overrides) [onum * 2 + 1] = mb->mhandle;
10975
10976                                         g_assert (mb->mhandle);
10977
10978                                         onum ++;
10979                                 }
10980                         }
10981                 }
10982         }
10983
10984         *num_overrides = onum;
10985 }
10986
10987 static void
10988 typebuilder_setup_fields (MonoClass *klass, MonoError *error)
10989 {
10990         MonoReflectionTypeBuilder *tb = mono_class_get_ref_info (klass);
10991         MonoReflectionFieldBuilder *fb;
10992         MonoClassField *field;
10993         MonoImage *image = klass->image;
10994         const char *p, *p2;
10995         int i;
10996         guint32 len, idx, real_size = 0;
10997
10998         klass->field.count = tb->num_fields;
10999         klass->field.first = 0;
11000
11001         mono_error_init (error);
11002
11003         if (tb->class_size) {
11004                 if ((tb->packing_size & 0xfffffff0) != 0) {
11005                         char *err_msg = g_strdup_printf ("Could not load struct '%s' with packing size %d >= 16", klass->name, tb->packing_size);
11006                         mono_class_set_failure (klass, MONO_EXCEPTION_TYPE_LOAD, err_msg);
11007                         return;
11008                 }
11009                 klass->packing_size = tb->packing_size;
11010                 real_size = klass->instance_size + tb->class_size;
11011         }
11012
11013         if (!klass->field.count) {
11014                 klass->instance_size = MAX (klass->instance_size, real_size);
11015                 return;
11016         }
11017         
11018         klass->fields = image_g_new0 (image, MonoClassField, klass->field.count);
11019         mono_class_alloc_ext (klass);
11020         klass->ext->field_def_values = image_g_new0 (image, MonoFieldDefaultValue, klass->field.count);
11021         /*
11022         This is, guess what, a hack.
11023         The issue is that the runtime doesn't know how to setup the fields of a typebuider and crash.
11024         On the static path no field class is resolved, only types are built. This is the right thing to do
11025         but we suck.
11026         Setting size_inited is harmless because we're doing the same job as mono_class_setup_fields anyway.
11027         */
11028         klass->size_inited = 1;
11029
11030         for (i = 0; i < klass->field.count; ++i) {
11031                 MonoArray *rva_data;
11032                 fb = mono_array_get (tb->fields, gpointer, i);
11033                 field = &klass->fields [i];
11034                 field->name = mono_string_to_utf8_image (image, fb->name, error);
11035                 if (!mono_error_ok (error))
11036                         return;
11037                 if (fb->attrs) {
11038                         field->type = mono_metadata_type_dup (klass->image, mono_reflection_type_get_handle ((MonoReflectionType*)fb->type));
11039                         field->type->attrs = fb->attrs;
11040                 } else {
11041                         field->type = mono_reflection_type_get_handle ((MonoReflectionType*)fb->type);
11042                 }
11043
11044                 if ((fb->attrs & FIELD_ATTRIBUTE_HAS_FIELD_RVA) && (rva_data = fb->rva_data)) {
11045                         char *base = mono_array_addr (rva_data, char, 0);
11046                         size_t size = mono_array_length (rva_data);
11047                         char *data = mono_image_alloc (klass->image, size);
11048                         memcpy (data, base, size);
11049                         klass->ext->field_def_values [i].data = data;
11050                 }
11051                 if (fb->offset != -1)
11052                         field->offset = fb->offset;
11053                 field->parent = klass;
11054                 fb->handle = field;
11055                 mono_save_custom_attrs (klass->image, field, fb->cattrs);
11056
11057                 if (klass->enumtype && !(field->type->attrs & FIELD_ATTRIBUTE_STATIC)) {
11058                         klass->cast_class = klass->element_class = mono_class_from_mono_type (field->type);
11059                 }
11060                 if (fb->def_value) {
11061                         MonoDynamicImage *assembly = (MonoDynamicImage*)klass->image;
11062                         field->type->attrs |= FIELD_ATTRIBUTE_HAS_DEFAULT;
11063                         idx = encode_constant (assembly, fb->def_value, &klass->ext->field_def_values [i].def_type);
11064                         /* Copy the data from the blob since it might get realloc-ed */
11065                         p = assembly->blob.data + idx;
11066                         len = mono_metadata_decode_blob_size (p, &p2);
11067                         len += p2 - p;
11068                         klass->ext->field_def_values [i].data = mono_image_alloc (image, len);
11069                         memcpy ((gpointer)klass->ext->field_def_values [i].data, p, len);
11070                 }
11071         }
11072
11073         klass->instance_size = MAX (klass->instance_size, real_size);
11074         mono_class_layout_fields (klass);
11075 }
11076
11077 static void
11078 typebuilder_setup_properties (MonoClass *klass, MonoError *error)
11079 {
11080         MonoReflectionTypeBuilder *tb = mono_class_get_ref_info (klass);
11081         MonoReflectionPropertyBuilder *pb;
11082         MonoImage *image = klass->image;
11083         MonoProperty *properties;
11084         int i;
11085
11086         mono_error_init (error);
11087
11088         if (!klass->ext)
11089                 klass->ext = image_g_new0 (image, MonoClassExt, 1);
11090
11091         klass->ext->property.count = tb->properties ? mono_array_length (tb->properties) : 0;
11092         klass->ext->property.first = 0;
11093
11094         properties = image_g_new0 (image, MonoProperty, klass->ext->property.count);
11095         klass->ext->properties = properties;
11096         for (i = 0; i < klass->ext->property.count; ++i) {
11097                 pb = mono_array_get (tb->properties, MonoReflectionPropertyBuilder*, i);
11098                 properties [i].parent = klass;
11099                 properties [i].attrs = pb->attrs;
11100                 properties [i].name = mono_string_to_utf8_image (image, pb->name, error);
11101                 if (!mono_error_ok (error))
11102                         return;
11103                 if (pb->get_method)
11104                         properties [i].get = pb->get_method->mhandle;
11105                 if (pb->set_method)
11106                         properties [i].set = pb->set_method->mhandle;
11107
11108                 mono_save_custom_attrs (klass->image, &properties [i], pb->cattrs);
11109                 if (pb->def_value) {
11110                         guint32 len, idx;
11111                         const char *p, *p2;
11112                         MonoDynamicImage *assembly = (MonoDynamicImage*)klass->image;
11113                         if (!klass->ext->prop_def_values)
11114                                 klass->ext->prop_def_values = image_g_new0 (image, MonoFieldDefaultValue, klass->ext->property.count);
11115                         properties [i].attrs |= PROPERTY_ATTRIBUTE_HAS_DEFAULT;
11116                         idx = encode_constant (assembly, pb->def_value, &klass->ext->prop_def_values [i].def_type);
11117                         /* Copy the data from the blob since it might get realloc-ed */
11118                         p = assembly->blob.data + idx;
11119                         len = mono_metadata_decode_blob_size (p, &p2);
11120                         len += p2 - p;
11121                         klass->ext->prop_def_values [i].data = mono_image_alloc (image, len);
11122                         memcpy ((gpointer)klass->ext->prop_def_values [i].data, p, len);
11123                 }
11124         }
11125 }
11126
11127 MonoReflectionEvent *
11128 mono_reflection_event_builder_get_event_info (MonoReflectionTypeBuilder *tb, MonoReflectionEventBuilder *eb)
11129 {
11130         MonoEvent *event = g_new0 (MonoEvent, 1);
11131         MonoClass *klass;
11132
11133         klass = mono_class_from_mono_type (mono_reflection_type_get_handle ((MonoReflectionType*)tb));
11134
11135         event->parent = klass;
11136         event->attrs = eb->attrs;
11137         event->name = mono_string_to_utf8 (eb->name);
11138         if (eb->add_method)
11139                 event->add = eb->add_method->mhandle;
11140         if (eb->remove_method)
11141                 event->remove = eb->remove_method->mhandle;
11142         if (eb->raise_method)
11143                 event->raise = eb->raise_method->mhandle;
11144
11145 #ifndef MONO_SMALL_CONFIG
11146         if (eb->other_methods) {
11147                 int j;
11148                 event->other = g_new0 (MonoMethod*, mono_array_length (eb->other_methods) + 1);
11149                 for (j = 0; j < mono_array_length (eb->other_methods); ++j) {
11150                         MonoReflectionMethodBuilder *mb = 
11151                                 mono_array_get (eb->other_methods,
11152                                                 MonoReflectionMethodBuilder*, j);
11153                         event->other [j] = mb->mhandle;
11154                 }
11155         }
11156 #endif
11157
11158         return mono_event_get_object (mono_object_domain (tb), klass, event);
11159 }
11160
11161 static void
11162 typebuilder_setup_events (MonoClass *klass, MonoError *error)
11163 {
11164         MonoReflectionTypeBuilder *tb = mono_class_get_ref_info (klass);
11165         MonoReflectionEventBuilder *eb;
11166         MonoImage *image = klass->image;
11167         MonoEvent *events;
11168         int i;
11169
11170         mono_error_init (error);
11171
11172         if (!klass->ext)
11173                 klass->ext = image_g_new0 (image, MonoClassExt, 1);
11174
11175         klass->ext->event.count = tb->events ? mono_array_length (tb->events) : 0;
11176         klass->ext->event.first = 0;
11177
11178         events = image_g_new0 (image, MonoEvent, klass->ext->event.count);
11179         klass->ext->events = events;
11180         for (i = 0; i < klass->ext->event.count; ++i) {
11181                 eb = mono_array_get (tb->events, MonoReflectionEventBuilder*, i);
11182                 events [i].parent = klass;
11183                 events [i].attrs = eb->attrs;
11184                 events [i].name = mono_string_to_utf8_image (image, eb->name, error);
11185                 if (!mono_error_ok (error))
11186                         return;
11187                 if (eb->add_method)
11188                         events [i].add = eb->add_method->mhandle;
11189                 if (eb->remove_method)
11190                         events [i].remove = eb->remove_method->mhandle;
11191                 if (eb->raise_method)
11192                         events [i].raise = eb->raise_method->mhandle;
11193
11194 #ifndef MONO_SMALL_CONFIG
11195                 if (eb->other_methods) {
11196                         int j;
11197                         events [i].other = image_g_new0 (image, MonoMethod*, mono_array_length (eb->other_methods) + 1);
11198                         for (j = 0; j < mono_array_length (eb->other_methods); ++j) {
11199                                 MonoReflectionMethodBuilder *mb = 
11200                                         mono_array_get (eb->other_methods,
11201                                                                         MonoReflectionMethodBuilder*, j);
11202                                 events [i].other [j] = mb->mhandle;
11203                         }
11204                 }
11205 #endif
11206                 mono_save_custom_attrs (klass->image, &events [i], eb->cattrs);
11207         }
11208 }
11209
11210 static gboolean
11211 remove_instantiations_of_and_ensure_contents (gpointer key,
11212                                                   gpointer value,
11213                                                   gpointer user_data)
11214 {
11215         MonoType *type = (MonoType*)key;
11216         MonoClass *klass = (MonoClass*)user_data;
11217
11218         if ((type->type == MONO_TYPE_GENERICINST) && (type->data.generic_class->container_class == klass)) {
11219                 fix_partial_generic_class (mono_class_from_mono_type (type)); //Ensure it's safe to use it.
11220                 return TRUE;
11221         } else
11222                 return FALSE;
11223 }
11224
11225 static void
11226 check_array_for_usertypes (MonoArray *arr)
11227 {
11228         int i;
11229
11230         if (!arr)
11231                 return;
11232
11233         for (i = 0; i < mono_array_length (arr); ++i)
11234                 RESOLVE_ARRAY_TYPE_ELEMENT (arr, i);
11235 }
11236
11237 MonoReflectionType*
11238 mono_reflection_create_runtime_class (MonoReflectionTypeBuilder *tb)
11239 {
11240         MonoError error;
11241         MonoClass *klass;
11242         MonoDomain* domain;
11243         MonoReflectionType* res;
11244         int i, j;
11245
11246         MONO_ARCH_SAVE_REGS;
11247
11248         domain = mono_object_domain (tb);
11249         klass = mono_class_from_mono_type (tb->type.type);
11250
11251         /*
11252          * Check for user defined Type subclasses.
11253          */
11254         RESOLVE_TYPE (tb->parent);
11255         check_array_for_usertypes (tb->interfaces);
11256         if (tb->fields) {
11257                 for (i = 0; i < mono_array_length (tb->fields); ++i) {
11258                         MonoReflectionFieldBuilder *fb = mono_array_get (tb->fields, gpointer, i);
11259                         if (fb) {
11260                                 RESOLVE_TYPE (fb->type);
11261                                 check_array_for_usertypes (fb->modreq);
11262                                 check_array_for_usertypes (fb->modopt);
11263                                 if (fb->marshal_info && fb->marshal_info->marshaltyperef)
11264                                         RESOLVE_TYPE (fb->marshal_info->marshaltyperef);
11265                         }
11266                 }
11267         }
11268         if (tb->methods) {
11269                 for (i = 0; i < mono_array_length (tb->methods); ++i) {
11270                         MonoReflectionMethodBuilder *mb = mono_array_get (tb->methods, gpointer, i);
11271                         if (mb) {
11272                                 RESOLVE_TYPE (mb->rtype);
11273                                 check_array_for_usertypes (mb->return_modreq);
11274                                 check_array_for_usertypes (mb->return_modopt);
11275                                 check_array_for_usertypes (mb->parameters);
11276                                 if (mb->param_modreq)
11277                                         for (j = 0; j < mono_array_length (mb->param_modreq); ++j)
11278                                                 check_array_for_usertypes (mono_array_get (mb->param_modreq, MonoArray*, j));
11279                                 if (mb->param_modopt)
11280                                         for (j = 0; j < mono_array_length (mb->param_modopt); ++j)
11281                                                 check_array_for_usertypes (mono_array_get (mb->param_modopt, MonoArray*, j));
11282                         }
11283                 }
11284         }
11285         if (tb->ctors) {
11286                 for (i = 0; i < mono_array_length (tb->ctors); ++i) {
11287                         MonoReflectionCtorBuilder *mb = mono_array_get (tb->ctors, gpointer, i);
11288                         if (mb) {
11289                                 check_array_for_usertypes (mb->parameters);
11290                                 if (mb->param_modreq)
11291                                         for (j = 0; j < mono_array_length (mb->param_modreq); ++j)
11292                                                 check_array_for_usertypes (mono_array_get (mb->param_modreq, MonoArray*, j));
11293                                 if (mb->param_modopt)
11294                                         for (j = 0; j < mono_array_length (mb->param_modopt); ++j)
11295                                                 check_array_for_usertypes (mono_array_get (mb->param_modopt, MonoArray*, j));
11296                         }
11297                 }
11298         }
11299
11300         mono_save_custom_attrs (klass->image, klass, tb->cattrs);
11301
11302         /* 
11303          * we need to lock the domain because the lock will be taken inside
11304          * So, we need to keep the locking order correct.
11305          */
11306         mono_loader_lock ();
11307         mono_domain_lock (domain);
11308         if (klass->wastypebuilder) {
11309                 mono_domain_unlock (domain);
11310                 mono_loader_unlock ();
11311                 return mono_type_get_object (mono_object_domain (tb), &klass->byval_arg);
11312         }
11313         /*
11314          * Fields to set in klass:
11315          * the various flags: delegate/unicode/contextbound etc.
11316          */
11317         klass->flags = tb->attrs;
11318         klass->has_cctor = 1;
11319         klass->has_finalize = 1;
11320         klass->has_finalize_inited = 1;
11321
11322         /* fool mono_class_setup_parent */
11323         klass->supertypes = NULL;
11324         mono_class_setup_parent (klass, klass->parent);
11325         mono_class_setup_mono_type (klass);
11326
11327 #if 0
11328         if (!((MonoDynamicImage*)klass->image)->run) {
11329                 if (klass->generic_container) {
11330                         /* FIXME: The code below can't handle generic classes */
11331                         klass->wastypebuilder = TRUE;
11332                         mono_loader_unlock ();
11333                         mono_domain_unlock (domain);
11334                         return mono_type_get_object (mono_object_domain (tb), &klass->byval_arg);
11335                 }
11336         }
11337 #endif
11338
11339         /* enums are done right away */
11340         if (!klass->enumtype)
11341                 ensure_runtime_vtable (klass);
11342
11343         if (tb->subtypes) {
11344                 for (i = 0; i < mono_array_length (tb->subtypes); ++i) {
11345                         MonoReflectionTypeBuilder *subtb = mono_array_get (tb->subtypes, MonoReflectionTypeBuilder*, i);
11346                         mono_class_alloc_ext (klass);
11347                         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)));
11348                 }
11349         }
11350
11351         klass->nested_classes_inited = TRUE;
11352
11353         /* fields and object layout */
11354         if (klass->parent) {
11355                 if (!klass->parent->size_inited)
11356                         mono_class_init (klass->parent);
11357                 klass->instance_size = klass->parent->instance_size;
11358                 klass->sizes.class_size = 0;
11359                 klass->min_align = klass->parent->min_align;
11360                 /* if the type has no fields we won't call the field_setup
11361                  * routine which sets up klass->has_references.
11362                  */
11363                 klass->has_references |= klass->parent->has_references;
11364         } else {
11365                 klass->instance_size = sizeof (MonoObject);
11366                 klass->min_align = 1;
11367         }
11368
11369         /* FIXME: handle packing_size and instance_size */
11370         typebuilder_setup_fields (klass, &error);
11371         if (!mono_error_ok (&error))
11372                 goto failure;
11373         typebuilder_setup_properties (klass, &error);
11374         if (!mono_error_ok (&error))
11375                 goto failure;
11376
11377         typebuilder_setup_events (klass, &error);
11378         if (!mono_error_ok (&error))
11379                 goto failure;
11380
11381         klass->wastypebuilder = TRUE;
11382
11383         /* 
11384          * If we are a generic TypeBuilder, there might be instantiations in the type cache
11385          * which have type System.Reflection.MonoGenericClass, but after the type is created, 
11386          * we want to return normal System.MonoType objects, so clear these out from the cache.
11387          *
11388          * Together with this we must ensure the contents of all instances to match the created type.
11389          */
11390         if (domain->type_hash && klass->generic_container)
11391                 mono_g_hash_table_foreach_remove (domain->type_hash, remove_instantiations_of_and_ensure_contents, klass);
11392
11393         mono_domain_unlock (domain);
11394         mono_loader_unlock ();
11395
11396         if (klass->enumtype && !mono_class_is_valid_enum (klass)) {
11397                 mono_class_set_failure (klass, MONO_EXCEPTION_TYPE_LOAD, NULL);
11398                 mono_raise_exception (mono_get_exception_type_load (tb->name, NULL));
11399         }
11400
11401         res = mono_type_get_object (mono_object_domain (tb), &klass->byval_arg);
11402         g_assert (res != (MonoReflectionType*)tb);
11403
11404         return res;
11405
11406 failure:
11407         mono_class_set_failure (klass, MONO_EXCEPTION_TYPE_LOAD, NULL);
11408         klass->wastypebuilder = TRUE;
11409         mono_domain_unlock (domain);
11410         mono_loader_unlock ();
11411         mono_error_raise_exception (&error);
11412         return NULL;
11413 }
11414
11415 void
11416 mono_reflection_initialize_generic_parameter (MonoReflectionGenericParam *gparam)
11417 {
11418         MonoGenericParamFull *param;
11419         MonoImage *image;
11420         MonoClass *pklass;
11421         MonoError error;
11422
11423         MONO_ARCH_SAVE_REGS;
11424
11425         image = &gparam->tbuilder->module->dynamic_image->image;
11426
11427         param = mono_image_new0 (image, MonoGenericParamFull, 1);
11428
11429         param->info.name = mono_string_to_utf8_image (image, gparam->name, &error);
11430         g_assert (mono_error_ok (&error));
11431         param->param.num = gparam->index;
11432
11433         if (gparam->mbuilder) {
11434                 if (!gparam->mbuilder->generic_container) {
11435                         MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder *)gparam->mbuilder->type;
11436                         MonoClass *klass = mono_class_from_mono_type (mono_reflection_type_get_handle ((MonoReflectionType*)tb));
11437                         gparam->mbuilder->generic_container = mono_image_alloc0 (klass->image, sizeof (MonoGenericContainer));
11438                         gparam->mbuilder->generic_container->is_method = TRUE;
11439                         /* 
11440                          * Cannot set owner.method, since the MonoMethod is not created yet.
11441                          * Set the image field instead, so type_in_image () works.
11442                          */
11443                         gparam->mbuilder->generic_container->image = klass->image;
11444                 }
11445                 param->param.owner = gparam->mbuilder->generic_container;
11446         } else if (gparam->tbuilder) {
11447                 if (!gparam->tbuilder->generic_container) {
11448                         MonoClass *klass = mono_class_from_mono_type (mono_reflection_type_get_handle ((MonoReflectionType*)gparam->tbuilder));
11449                         gparam->tbuilder->generic_container = mono_image_alloc0 (klass->image, sizeof (MonoGenericContainer));
11450                         gparam->tbuilder->generic_container->owner.klass = klass;
11451                 }
11452                 param->param.owner = gparam->tbuilder->generic_container;
11453         }
11454
11455         pklass = mono_class_from_generic_parameter ((MonoGenericParam *) param, image, gparam->mbuilder != NULL);
11456
11457         gparam->type.type = &pklass->byval_arg;
11458
11459         mono_class_set_ref_info (pklass, gparam);
11460         mono_image_append_class_to_reflection_info_set (pklass);
11461 }
11462
11463 MonoArray *
11464 mono_reflection_sighelper_get_signature_local (MonoReflectionSigHelper *sig)
11465 {
11466         MonoReflectionModuleBuilder *module = sig->module;
11467         MonoDynamicImage *assembly = module != NULL ? module->dynamic_image : NULL;
11468         guint32 na = sig->arguments ? mono_array_length (sig->arguments) : 0;
11469         guint32 buflen, i;
11470         MonoArray *result;
11471         SigBuffer buf;
11472
11473         check_array_for_usertypes (sig->arguments);
11474
11475         sigbuffer_init (&buf, 32);
11476
11477         sigbuffer_add_value (&buf, 0x07);
11478         sigbuffer_add_value (&buf, na);
11479         if (assembly != NULL){
11480                 for (i = 0; i < na; ++i) {
11481                         MonoReflectionType *type = mono_array_get (sig->arguments, MonoReflectionType*, i);
11482                         encode_reflection_type (assembly, type, &buf);
11483                 }
11484         }
11485
11486         buflen = buf.p - buf.buf;
11487         result = mono_array_new (mono_domain_get (), mono_defaults.byte_class, buflen);
11488         memcpy (mono_array_addr (result, char, 0), buf.buf, buflen);
11489         sigbuffer_free (&buf);
11490
11491         return result;
11492 }
11493
11494 MonoArray *
11495 mono_reflection_sighelper_get_signature_field (MonoReflectionSigHelper *sig)
11496 {
11497         MonoDynamicImage *assembly = sig->module->dynamic_image;
11498         guint32 na = sig->arguments ? mono_array_length (sig->arguments) : 0;
11499         guint32 buflen, i;
11500         MonoArray *result;
11501         SigBuffer buf;
11502
11503         check_array_for_usertypes (sig->arguments);
11504
11505         sigbuffer_init (&buf, 32);
11506
11507         sigbuffer_add_value (&buf, 0x06);
11508         for (i = 0; i < na; ++i) {
11509                 MonoReflectionType *type = mono_array_get (sig->arguments, MonoReflectionType*, i);
11510                 encode_reflection_type (assembly, type, &buf);
11511         }
11512
11513         buflen = buf.p - buf.buf;
11514         result = mono_array_new (mono_domain_get (), mono_defaults.byte_class, buflen);
11515         memcpy (mono_array_addr (result, char, 0), buf.buf, buflen);
11516         sigbuffer_free (&buf);
11517
11518         return result;
11519 }
11520
11521 typedef struct {
11522         MonoMethod *handle;
11523         MonoDomain *domain;
11524 } DynamicMethodReleaseData;
11525
11526 /*
11527  * The runtime automatically clean up those after finalization.
11528 */      
11529 static MonoReferenceQueue *dynamic_method_queue;
11530
11531 static void
11532 free_dynamic_method (void *dynamic_method)
11533 {
11534         DynamicMethodReleaseData *data = dynamic_method;
11535
11536         mono_runtime_free_method (data->domain, data->handle);
11537         g_free (data);
11538 }
11539
11540 void 
11541 mono_reflection_create_dynamic_method (MonoReflectionDynamicMethod *mb)
11542 {
11543         MonoReferenceQueue *queue;
11544         MonoMethod *handle;
11545         DynamicMethodReleaseData *release_data;
11546         ReflectionMethodBuilder rmb;
11547         MonoMethodSignature *sig;
11548         MonoClass *klass;
11549         GSList *l;
11550         int i;
11551
11552         if (mono_runtime_is_shutting_down ())
11553                 mono_raise_exception (mono_get_exception_invalid_operation (""));
11554
11555         if (!(queue = dynamic_method_queue)) {
11556                 mono_loader_lock ();
11557                 if (!(queue = dynamic_method_queue))
11558                         queue = dynamic_method_queue = mono_gc_reference_queue_new (free_dynamic_method);
11559                 mono_loader_unlock ();
11560         }
11561
11562         sig = dynamic_method_to_signature (mb);
11563
11564         reflection_methodbuilder_from_dynamic_method (&rmb, mb);
11565
11566         /*
11567          * Resolve references.
11568          */
11569         /* 
11570          * Every second entry in the refs array is reserved for storing handle_class,
11571          * which is needed by the ldtoken implementation in the JIT.
11572          */
11573         rmb.nrefs = mb->nrefs;
11574         rmb.refs = g_new0 (gpointer, mb->nrefs + 1);
11575         for (i = 0; i < mb->nrefs; i += 2) {
11576                 MonoClass *handle_class;
11577                 gpointer ref;
11578                 MonoObject *obj = mono_array_get (mb->refs, MonoObject*, i);
11579
11580                 if (strcmp (obj->vtable->klass->name, "DynamicMethod") == 0) {
11581                         MonoReflectionDynamicMethod *method = (MonoReflectionDynamicMethod*)obj;
11582                         /*
11583                          * The referenced DynamicMethod should already be created by the managed
11584                          * code, except in the case of circular references. In that case, we store
11585                          * method in the refs array, and fix it up later when the referenced 
11586                          * DynamicMethod is created.
11587                          */
11588                         if (method->mhandle) {
11589                                 ref = method->mhandle;
11590                         } else {
11591                                 /* FIXME: GC object stored in unmanaged memory */
11592                                 ref = method;
11593
11594                                 /* FIXME: GC object stored in unmanaged memory */
11595                                 method->referenced_by = g_slist_append (method->referenced_by, mb);
11596                         }
11597                         handle_class = mono_defaults.methodhandle_class;
11598                 } else {
11599                         MonoException *ex = NULL;
11600                         ref = resolve_object (mb->module->image, obj, &handle_class, NULL);
11601                         if (!ref)
11602                                 ex = mono_get_exception_type_load (NULL, NULL);
11603                         else if (mono_security_core_clr_enabled ())
11604                                 ex = mono_security_core_clr_ensure_dynamic_method_resolved_object (ref, handle_class);
11605
11606                         if (ex) {
11607                                 g_free (rmb.refs);
11608                                 mono_raise_exception (ex);
11609                                 return;
11610                         }
11611                 }
11612
11613                 rmb.refs [i] = ref; /* FIXME: GC object stored in unmanaged memory (change also resolve_object() signature) */
11614                 rmb.refs [i + 1] = handle_class;
11615         }               
11616
11617         klass = mb->owner ? mono_class_from_mono_type (mono_reflection_type_get_handle ((MonoReflectionType*)mb->owner)) : mono_defaults.object_class;
11618
11619         mb->mhandle = handle = reflection_methodbuilder_to_mono_method (klass, &rmb, sig);
11620         release_data = g_new (DynamicMethodReleaseData, 1);
11621         release_data->handle = handle;
11622         release_data->domain = mono_object_get_domain ((MonoObject*)mb);
11623         if (!mono_gc_reference_queue_add (queue, (MonoObject*)mb, release_data))
11624                 g_free (release_data);
11625
11626         /* Fix up refs entries pointing at us */
11627         for (l = mb->referenced_by; l; l = l->next) {
11628                 MonoReflectionDynamicMethod *method = (MonoReflectionDynamicMethod*)l->data;
11629                 MonoMethodWrapper *wrapper = (MonoMethodWrapper*)method->mhandle;
11630                 gpointer *data;
11631                 
11632                 g_assert (method->mhandle);
11633
11634                 data = (gpointer*)wrapper->method_data;
11635                 for (i = 0; i < GPOINTER_TO_UINT (data [0]); i += 2) {
11636                         if ((data [i + 1] == mb) && (data [i + 1 + 1] == mono_defaults.methodhandle_class))
11637                                 data [i + 1] = mb->mhandle;
11638                 }
11639         }
11640         g_slist_free (mb->referenced_by);
11641
11642         g_free (rmb.refs);
11643
11644         /* ilgen is no longer needed */
11645         mb->ilgen = NULL;
11646 }
11647
11648 #endif /* DISABLE_REFLECTION_EMIT */
11649
11650 /**
11651  * 
11652  * mono_reflection_is_valid_dynamic_token:
11653  * 
11654  * Returns TRUE if token is valid.
11655  * 
11656  */
11657 gboolean
11658 mono_reflection_is_valid_dynamic_token (MonoDynamicImage *image, guint32 token)
11659 {
11660         return mono_g_hash_table_lookup (image->tokens, GUINT_TO_POINTER (token)) != NULL;
11661 }
11662
11663 MonoMethodSignature *
11664 mono_reflection_lookup_signature (MonoImage *image, MonoMethod *method, guint32 token)
11665 {
11666         MonoMethodSignature *sig;
11667         g_assert (image->dynamic);
11668
11669         sig = g_hash_table_lookup (((MonoDynamicImage*)image)->vararg_aux_hash, GUINT_TO_POINTER (token));
11670         if (sig)
11671                 return sig;
11672
11673         return mono_method_signature (method);
11674 }
11675
11676 #ifndef DISABLE_REFLECTION_EMIT
11677
11678 /**
11679  * mono_reflection_lookup_dynamic_token:
11680  *
11681  * Finish the Builder object pointed to by TOKEN and return the corresponding
11682  * runtime structure. If HANDLE_CLASS is not NULL, it is set to the class required by 
11683  * mono_ldtoken. If valid_token is TRUE, assert if it is not found in the token->object
11684  * mapping table.
11685  *
11686  * LOCKING: Take the loader lock
11687  */
11688 gpointer
11689 mono_reflection_lookup_dynamic_token (MonoImage *image, guint32 token, gboolean valid_token, MonoClass **handle_class, MonoGenericContext *context)
11690 {
11691         MonoDynamicImage *assembly = (MonoDynamicImage*)image;
11692         MonoObject *obj;
11693         MonoClass *klass;
11694
11695         mono_loader_lock ();
11696         obj = mono_g_hash_table_lookup (assembly->tokens, GUINT_TO_POINTER (token));
11697         mono_loader_unlock ();
11698         if (!obj) {
11699                 if (valid_token)
11700                         g_error ("Could not find required dynamic token 0x%08x", token);
11701                 else
11702                         return NULL;
11703         }
11704
11705         if (!handle_class)
11706                 handle_class = &klass;
11707         return resolve_object (image, obj, handle_class, context);
11708 }
11709
11710 /*
11711  * ensure_complete_type:
11712  *
11713  *   Ensure that KLASS is completed if it is a dynamic type, or references
11714  * dynamic types.
11715  */
11716 static void
11717 ensure_complete_type (MonoClass *klass)
11718 {
11719         if (klass->image->dynamic && !klass->wastypebuilder && mono_class_get_ref_info (klass)) {
11720                 MonoReflectionTypeBuilder *tb = mono_class_get_ref_info (klass);
11721
11722                 mono_domain_try_type_resolve (mono_domain_get (), NULL, (MonoObject*)tb);
11723
11724                 // Asserting here could break a lot of code
11725                 //g_assert (klass->wastypebuilder);
11726         }
11727
11728         if (klass->generic_class) {
11729                 MonoGenericInst *inst = klass->generic_class->context.class_inst;
11730                 int i;
11731
11732                 for (i = 0; i < inst->type_argc; ++i) {
11733                         ensure_complete_type (mono_class_from_mono_type (inst->type_argv [i]));
11734                 }
11735         }
11736 }
11737
11738 static gpointer
11739 resolve_object (MonoImage *image, MonoObject *obj, MonoClass **handle_class, MonoGenericContext *context)
11740 {
11741         gpointer result = NULL;
11742
11743         if (strcmp (obj->vtable->klass->name, "String") == 0) {
11744                 result = mono_string_intern ((MonoString*)obj);
11745                 *handle_class = mono_defaults.string_class;
11746                 g_assert (result);
11747         } else if (strcmp (obj->vtable->klass->name, "MonoType") == 0) {
11748                 MonoType *type = mono_reflection_type_get_handle ((MonoReflectionType*)obj);
11749                 MonoClass *mc = mono_class_from_mono_type (type);
11750                 if (!mono_class_init (mc))
11751                         mono_raise_exception (mono_class_get_exception_for_failure (mc));
11752
11753                 if (context) {
11754                         MonoType *inflated = mono_class_inflate_generic_type (type, context);
11755                         result = mono_class_from_mono_type (inflated);
11756                         mono_metadata_free_type (inflated);
11757                 } else {
11758                         result = mono_class_from_mono_type (type);
11759                 }
11760                 *handle_class = mono_defaults.typehandle_class;
11761                 g_assert (result);
11762         } else if (strcmp (obj->vtable->klass->name, "MonoMethod") == 0 ||
11763                    strcmp (obj->vtable->klass->name, "MonoCMethod") == 0 ||
11764                    strcmp (obj->vtable->klass->name, "MonoGenericCMethod") == 0 ||
11765                    strcmp (obj->vtable->klass->name, "MonoGenericMethod") == 0) {
11766                 result = ((MonoReflectionMethod*)obj)->method;
11767                 if (context)
11768                         result = mono_class_inflate_generic_method (result, context);
11769                 *handle_class = mono_defaults.methodhandle_class;
11770                 g_assert (result);
11771         } else if (strcmp (obj->vtable->klass->name, "MethodBuilder") == 0) {
11772                 MonoReflectionMethodBuilder *mb = (MonoReflectionMethodBuilder*)obj;
11773                 result = mb->mhandle;
11774                 if (!result) {
11775                         /* Type is not yet created */
11776                         MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder*)mb->type;
11777
11778                         mono_domain_try_type_resolve (mono_domain_get (), NULL, (MonoObject*)tb);
11779
11780                         /*
11781                          * Hopefully this has been filled in by calling CreateType() on the
11782                          * TypeBuilder.
11783                          */
11784                         /*
11785                          * TODO: This won't work if the application finishes another 
11786                          * TypeBuilder instance instead of this one.
11787                          */
11788                         result = mb->mhandle;
11789                 }
11790                 if (context)
11791                         result = mono_class_inflate_generic_method (result, context);
11792                 *handle_class = mono_defaults.methodhandle_class;
11793         } else if (strcmp (obj->vtable->klass->name, "ConstructorBuilder") == 0) {
11794                 MonoReflectionCtorBuilder *cb = (MonoReflectionCtorBuilder*)obj;
11795
11796                 result = cb->mhandle;
11797                 if (!result) {
11798                         MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder*)cb->type;
11799
11800                         mono_domain_try_type_resolve (mono_domain_get (), NULL, (MonoObject*)tb);
11801                         result = cb->mhandle;
11802                 }
11803                 if (context)
11804                         result = mono_class_inflate_generic_method (result, context);
11805                 *handle_class = mono_defaults.methodhandle_class;
11806         } else if (strcmp (obj->vtable->klass->name, "MonoField") == 0) {
11807                 MonoClassField *field = ((MonoReflectionField*)obj)->field;
11808
11809                 ensure_complete_type (field->parent);
11810                 if (context) {
11811                         MonoType *inflated = mono_class_inflate_generic_type (&field->parent->byval_arg, context);
11812                         MonoClass *class = mono_class_from_mono_type (inflated);
11813                         MonoClassField *inflated_field;
11814                         gpointer iter = NULL;
11815                         mono_metadata_free_type (inflated);
11816                         while ((inflated_field = mono_class_get_fields (class, &iter))) {
11817                                 if (!strcmp (field->name, inflated_field->name))
11818                                         break;
11819                         }
11820                         g_assert (inflated_field && !strcmp (field->name, inflated_field->name));
11821                         result = inflated_field;
11822                 } else {
11823                         result = field;
11824                 }
11825                 *handle_class = mono_defaults.fieldhandle_class;
11826                 g_assert (result);
11827         } else if (strcmp (obj->vtable->klass->name, "FieldBuilder") == 0) {
11828                 MonoReflectionFieldBuilder *fb = (MonoReflectionFieldBuilder*)obj;
11829                 result = fb->handle;
11830
11831                 if (!result) {
11832                         MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder*)fb->typeb;
11833
11834                         mono_domain_try_type_resolve (mono_domain_get (), NULL, (MonoObject*)tb);
11835                         result = fb->handle;
11836                 }
11837
11838                 if (fb->handle && fb->handle->parent->generic_container) {
11839                         MonoClass *klass = fb->handle->parent;
11840                         MonoType *type = mono_class_inflate_generic_type (&klass->byval_arg, context);
11841                         MonoClass *inflated = mono_class_from_mono_type (type);
11842
11843                         result = mono_class_get_field_from_name (inflated, mono_field_get_name (fb->handle));
11844                         g_assert (result);
11845                         mono_metadata_free_type (type);
11846                 }
11847                 *handle_class = mono_defaults.fieldhandle_class;
11848         } else if (strcmp (obj->vtable->klass->name, "TypeBuilder") == 0) {
11849                 MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder*)obj;
11850                 MonoType *type = mono_reflection_type_get_handle ((MonoReflectionType*)tb); 
11851                 MonoClass *klass;
11852
11853                 klass = type->data.klass;
11854                 if (klass->wastypebuilder) {
11855                         /* Already created */
11856                         result = klass;
11857                 }
11858                 else {
11859                         mono_domain_try_type_resolve (mono_domain_get (), NULL, (MonoObject*)tb);
11860                         result = type->data.klass;
11861                         g_assert (result);
11862                 }
11863                 *handle_class = mono_defaults.typehandle_class;
11864         } else if (strcmp (obj->vtable->klass->name, "SignatureHelper") == 0) {
11865                 MonoReflectionSigHelper *helper = (MonoReflectionSigHelper*)obj;
11866                 MonoMethodSignature *sig;
11867                 int nargs, i;
11868
11869                 if (helper->arguments)
11870                         nargs = mono_array_length (helper->arguments);
11871                 else
11872                         nargs = 0;
11873
11874                 sig = mono_metadata_signature_alloc (image, nargs);
11875                 sig->explicit_this = helper->call_conv & 64 ? 1 : 0;
11876                 sig->hasthis = helper->call_conv & 32 ? 1 : 0;
11877
11878                 if (helper->unmanaged_call_conv) { /* unmanaged */
11879                         sig->call_convention = helper->unmanaged_call_conv - 1;
11880                         sig->pinvoke = TRUE;
11881                 } else if (helper->call_conv & 0x02) {
11882                         sig->call_convention = MONO_CALL_VARARG;
11883                 } else {
11884                         sig->call_convention = MONO_CALL_DEFAULT;
11885                 }
11886
11887                 sig->param_count = nargs;
11888                 /* TODO: Copy type ? */
11889                 sig->ret = helper->return_type->type;
11890                 for (i = 0; i < nargs; ++i)
11891                         sig->params [i] = mono_type_array_get_and_resolve (helper->arguments, i);
11892
11893                 result = sig;
11894                 *handle_class = NULL;
11895         } else if (strcmp (obj->vtable->klass->name, "DynamicMethod") == 0) {
11896                 MonoReflectionDynamicMethod *method = (MonoReflectionDynamicMethod*)obj;
11897                 /* Already created by the managed code */
11898                 g_assert (method->mhandle);
11899                 result = method->mhandle;
11900                 *handle_class = mono_defaults.methodhandle_class;
11901         } else if (strcmp (obj->vtable->klass->name, "GenericTypeParameterBuilder") == 0) {
11902                 MonoType *type = mono_reflection_type_get_handle ((MonoReflectionType*)obj);
11903                 type = mono_class_inflate_generic_type (type, context);
11904                 result = mono_class_from_mono_type (type);
11905                 *handle_class = mono_defaults.typehandle_class;
11906                 g_assert (result);
11907                 mono_metadata_free_type (type);
11908         } else if (strcmp (obj->vtable->klass->name, "MonoGenericClass") == 0) {
11909                 MonoType *type = mono_reflection_type_get_handle ((MonoReflectionType*)obj);
11910                 type = mono_class_inflate_generic_type (type, context);
11911                 result = mono_class_from_mono_type (type);
11912                 *handle_class = mono_defaults.typehandle_class;
11913                 g_assert (result);
11914                 mono_metadata_free_type (type);
11915         } else if (strcmp (obj->vtable->klass->name, "FieldOnTypeBuilderInst") == 0) {
11916                 MonoReflectionFieldOnTypeBuilderInst *f = (MonoReflectionFieldOnTypeBuilderInst*)obj;
11917                 MonoClass *inflated;
11918                 MonoType *type;
11919                 MonoClassField *field;
11920
11921                 if (is_sre_field_builder (mono_object_class (f->fb)))
11922                         field = ((MonoReflectionFieldBuilder*)f->fb)->handle;
11923                 else if (is_sr_mono_field (mono_object_class (f->fb)))
11924                         field = ((MonoReflectionField*)f->fb)->field;
11925                 else
11926                         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)));
11927
11928                 type = mono_class_inflate_generic_type (mono_reflection_type_get_handle ((MonoReflectionType*)f->inst), context);
11929                 inflated = mono_class_from_mono_type (type);
11930
11931                 result = field = mono_class_get_field_from_name (inflated, mono_field_get_name (field));
11932                 ensure_complete_type (field->parent);
11933                 g_assert (result);
11934                 mono_metadata_free_type (type);
11935                 *handle_class = mono_defaults.fieldhandle_class;
11936         } else if (strcmp (obj->vtable->klass->name, "ConstructorOnTypeBuilderInst") == 0) {
11937                 MonoReflectionCtorOnTypeBuilderInst *c = (MonoReflectionCtorOnTypeBuilderInst*)obj;
11938                 MonoType *type = mono_class_inflate_generic_type (mono_reflection_type_get_handle ((MonoReflectionType*)c->inst), context);
11939                 MonoClass *inflated_klass = mono_class_from_mono_type (type);
11940                 MonoMethod *method;
11941
11942                 if (is_sre_ctor_builder (mono_object_class (c->cb)))
11943                         method = ((MonoReflectionCtorBuilder *)c->cb)->mhandle;
11944                 else if (is_sr_mono_cmethod (mono_object_class (c->cb)))
11945                         method = ((MonoReflectionMethod *)c->cb)->method;
11946                 else
11947                         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)));
11948
11949                 result = inflate_mono_method (inflated_klass, method, (MonoObject*)c->cb);
11950                 *handle_class = mono_defaults.methodhandle_class;
11951                 mono_metadata_free_type (type);
11952         } else if (strcmp (obj->vtable->klass->name, "MethodOnTypeBuilderInst") == 0) {
11953                 MonoReflectionMethodOnTypeBuilderInst *m = (MonoReflectionMethodOnTypeBuilderInst*)obj;
11954                 if (m->method_args) {
11955                         result = mono_reflection_method_on_tb_inst_get_handle (m);
11956                         if (context)
11957                                 result = mono_class_inflate_generic_method (result, context);
11958                 } else {
11959                         MonoType *type = mono_class_inflate_generic_type (mono_reflection_type_get_handle ((MonoReflectionType*)m->inst), context);
11960                         MonoClass *inflated_klass = mono_class_from_mono_type (type);
11961                         MonoMethod *method;
11962
11963                         if (is_sre_method_builder (mono_object_class (m->mb)))
11964                                 method = ((MonoReflectionMethodBuilder *)m->mb)->mhandle;
11965                         else if (is_sr_mono_method (mono_object_class (m->mb)))
11966                                 method = ((MonoReflectionMethod *)m->mb)->method;
11967                         else
11968                                 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)));
11969
11970                         result = inflate_mono_method (inflated_klass, method, (MonoObject*)m->mb);
11971                         mono_metadata_free_type (type);
11972                 }
11973                 *handle_class = mono_defaults.methodhandle_class;
11974         } else if (strcmp (obj->vtable->klass->name, "MonoArrayMethod") == 0) {
11975                 MonoReflectionArrayMethod *m = (MonoReflectionArrayMethod*)obj;
11976                 MonoType *mtype;
11977                 MonoClass *klass;
11978                 MonoMethod *method;
11979                 gpointer iter;
11980                 char *name;
11981
11982                 mtype = mono_reflection_type_get_handle (m->parent);
11983                 klass = mono_class_from_mono_type (mtype);
11984
11985                 /* Find the method */
11986
11987                 name = mono_string_to_utf8 (m->name);
11988                 iter = NULL;
11989                 while ((method = mono_class_get_methods (klass, &iter))) {
11990                         if (!strcmp (method->name, name))
11991                                 break;
11992                 }
11993                 g_free (name);
11994
11995                 // FIXME:
11996                 g_assert (method);
11997                 // FIXME: Check parameters/return value etc. match
11998
11999                 result = method;
12000                 *handle_class = mono_defaults.methodhandle_class;
12001         } else if (is_sre_array (mono_object_get_class(obj)) ||
12002                                 is_sre_byref (mono_object_get_class(obj)) ||
12003                                 is_sre_pointer (mono_object_get_class(obj))) {
12004                 MonoReflectionType *ref_type = (MonoReflectionType *)obj;
12005                 MonoType *type = mono_reflection_type_get_handle (ref_type);
12006
12007                 if (context) {
12008                         MonoType *inflated = mono_class_inflate_generic_type (type, context);
12009                         result = mono_class_from_mono_type (inflated);
12010                         mono_metadata_free_type (inflated);
12011                 } else {
12012                         result = mono_class_from_mono_type (type);
12013                 }
12014                 *handle_class = mono_defaults.typehandle_class;
12015         } else {
12016                 g_print ("%s\n", obj->vtable->klass->name);
12017                 g_assert_not_reached ();
12018         }
12019         return result;
12020 }
12021
12022 #else /* DISABLE_REFLECTION_EMIT */
12023
12024 MonoArray*
12025 mono_reflection_get_custom_attrs_blob (MonoReflectionAssembly *assembly, MonoObject *ctor, MonoArray *ctorArgs, MonoArray *properties, MonoArray *propValues, MonoArray *fields, MonoArray* fieldValues) 
12026 {
12027         g_assert_not_reached ();
12028         return NULL;
12029 }
12030
12031 void
12032 mono_reflection_setup_internal_class (MonoReflectionTypeBuilder *tb)
12033 {
12034         g_assert_not_reached ();
12035 }
12036
12037 void
12038 mono_reflection_setup_generic_class (MonoReflectionTypeBuilder *tb)
12039 {
12040         g_assert_not_reached ();
12041 }
12042
12043 void
12044 mono_reflection_create_generic_class (MonoReflectionTypeBuilder *tb)
12045 {
12046         g_assert_not_reached ();
12047 }
12048
12049 void
12050 mono_reflection_create_internal_class (MonoReflectionTypeBuilder *tb)
12051 {
12052         g_assert_not_reached ();
12053 }
12054
12055 void
12056 mono_image_basic_init (MonoReflectionAssemblyBuilder *assemblyb)
12057 {
12058         g_error ("This mono runtime was configured with --enable-minimal=reflection_emit, so System.Reflection.Emit is not supported.");
12059 }
12060
12061 void
12062 mono_image_module_basic_init (MonoReflectionModuleBuilder *moduleb)
12063 {
12064         g_assert_not_reached ();
12065 }
12066
12067 void
12068 mono_image_set_wrappers_type (MonoReflectionModuleBuilder *moduleb, MonoReflectionType *type)
12069 {
12070         g_assert_not_reached ();
12071 }
12072
12073 MonoReflectionModule *
12074 mono_image_load_module_dynamic (MonoReflectionAssemblyBuilder *ab, MonoString *fileName)
12075 {
12076         g_assert_not_reached ();
12077         return NULL;
12078 }
12079
12080 guint32
12081 mono_image_insert_string (MonoReflectionModuleBuilder *module, MonoString *str)
12082 {
12083         g_assert_not_reached ();
12084         return 0;
12085 }
12086
12087 guint32
12088 mono_image_create_method_token (MonoDynamicImage *assembly, MonoObject *obj, MonoArray *opt_param_types)
12089 {
12090         g_assert_not_reached ();
12091         return 0;
12092 }
12093
12094 guint32
12095 mono_image_create_token (MonoDynamicImage *assembly, MonoObject *obj, 
12096                                                  gboolean create_open_instance, gboolean register_token)
12097 {
12098         g_assert_not_reached ();
12099         return 0;
12100 }
12101
12102 void
12103 mono_image_register_token (MonoDynamicImage *assembly, guint32 token, MonoObject *obj)
12104 {
12105 }
12106
12107 void
12108 mono_reflection_generic_class_initialize (MonoReflectionGenericClass *type, MonoArray *fields)
12109 {
12110         g_assert_not_reached ();
12111 }
12112
12113 void
12114 mono_reflection_get_dynamic_overrides (MonoClass *klass, MonoMethod ***overrides, int *num_overrides)
12115 {
12116         *overrides = NULL;
12117         *num_overrides = 0;
12118 }
12119
12120 MonoReflectionEvent *
12121 mono_reflection_event_builder_get_event_info (MonoReflectionTypeBuilder *tb, MonoReflectionEventBuilder *eb)
12122 {
12123         g_assert_not_reached ();
12124         return NULL;
12125 }
12126
12127 MonoReflectionType*
12128 mono_reflection_create_runtime_class (MonoReflectionTypeBuilder *tb)
12129 {
12130         g_assert_not_reached ();
12131         return NULL;
12132 }
12133
12134 void
12135 mono_reflection_initialize_generic_parameter (MonoReflectionGenericParam *gparam)
12136 {
12137         g_assert_not_reached ();
12138 }
12139
12140 MonoArray *
12141 mono_reflection_sighelper_get_signature_local (MonoReflectionSigHelper *sig)
12142 {
12143         g_assert_not_reached ();
12144         return NULL;
12145 }
12146
12147 MonoArray *
12148 mono_reflection_sighelper_get_signature_field (MonoReflectionSigHelper *sig)
12149 {
12150         g_assert_not_reached ();
12151         return NULL;
12152 }
12153
12154 void 
12155 mono_reflection_create_dynamic_method (MonoReflectionDynamicMethod *mb)
12156 {
12157 }
12158
12159 gpointer
12160 mono_reflection_lookup_dynamic_token (MonoImage *image, guint32 token, gboolean valid_token, MonoClass **handle_class, MonoGenericContext *context)
12161 {
12162         return NULL;
12163 }
12164
12165 MonoType*
12166 mono_reflection_type_get_handle (MonoReflectionType* ref)
12167 {
12168         if (!ref)
12169                 return NULL;
12170         return ref->type;
12171 }
12172
12173 void
12174 mono_reflection_free_dynamic_generic_class (MonoGenericClass *gclass)
12175 {
12176         g_assert_not_reached ();
12177 }
12178
12179 #endif /* DISABLE_REFLECTION_EMIT */
12180
12181 /* SECURITY_ACTION_* are defined in mono/metadata/tabledefs.h */
12182 const static guint32 declsec_flags_map[] = {
12183         0x00000000,                                     /* empty */
12184         MONO_DECLSEC_FLAG_REQUEST,                      /* SECURITY_ACTION_REQUEST                      (x01) */
12185         MONO_DECLSEC_FLAG_DEMAND,                       /* SECURITY_ACTION_DEMAND                       (x02) */
12186         MONO_DECLSEC_FLAG_ASSERT,                       /* SECURITY_ACTION_ASSERT                       (x03) */
12187         MONO_DECLSEC_FLAG_DENY,                         /* SECURITY_ACTION_DENY                         (x04) */
12188         MONO_DECLSEC_FLAG_PERMITONLY,                   /* SECURITY_ACTION_PERMITONLY                   (x05) */
12189         MONO_DECLSEC_FLAG_LINKDEMAND,                   /* SECURITY_ACTION_LINKDEMAND                   (x06) */
12190         MONO_DECLSEC_FLAG_INHERITANCEDEMAND,            /* SECURITY_ACTION_INHERITANCEDEMAND            (x07) */
12191         MONO_DECLSEC_FLAG_REQUEST_MINIMUM,              /* SECURITY_ACTION_REQUEST_MINIMUM              (x08) */
12192         MONO_DECLSEC_FLAG_REQUEST_OPTIONAL,             /* SECURITY_ACTION_REQUEST_OPTIONAL             (x09) */
12193         MONO_DECLSEC_FLAG_REQUEST_REFUSE,               /* SECURITY_ACTION_REQUEST_REFUSE               (x0A) */
12194         MONO_DECLSEC_FLAG_PREJIT_GRANT,                 /* SECURITY_ACTION_PREJIT_GRANT                 (x0B) */
12195         MONO_DECLSEC_FLAG_PREJIT_DENY,                  /* SECURITY_ACTION_PREJIT_DENY                  (x0C) */
12196         MONO_DECLSEC_FLAG_NONCAS_DEMAND,                /* SECURITY_ACTION_NONCAS_DEMAND                (x0D) */
12197         MONO_DECLSEC_FLAG_NONCAS_LINKDEMAND,            /* SECURITY_ACTION_NONCAS_LINKDEMAND            (x0E) */
12198         MONO_DECLSEC_FLAG_NONCAS_INHERITANCEDEMAND,     /* SECURITY_ACTION_NONCAS_INHERITANCEDEMAND     (x0F) */
12199         MONO_DECLSEC_FLAG_LINKDEMAND_CHOICE,            /* SECURITY_ACTION_LINKDEMAND_CHOICE            (x10) */
12200         MONO_DECLSEC_FLAG_INHERITANCEDEMAND_CHOICE,     /* SECURITY_ACTION_INHERITANCEDEMAND_CHOICE     (x11) */
12201         MONO_DECLSEC_FLAG_DEMAND_CHOICE,                /* SECURITY_ACTION_DEMAND_CHOICE                (x12) */
12202 };
12203
12204 /*
12205  * Returns flags that includes all available security action associated to the handle.
12206  * @token: metadata token (either for a class or a method)
12207  * @image: image where resides the metadata.
12208  */
12209 static guint32
12210 mono_declsec_get_flags (MonoImage *image, guint32 token)
12211 {
12212         int index = mono_metadata_declsec_from_index (image, token);
12213         MonoTableInfo *t = &image->tables [MONO_TABLE_DECLSECURITY];
12214         guint32 result = 0;
12215         guint32 action;
12216         int i;
12217
12218         /* HasSecurity can be present for other, not specially encoded, attributes,
12219            e.g. SuppressUnmanagedCodeSecurityAttribute */
12220         if (index < 0)
12221                 return 0;
12222
12223         for (i = index; i < t->rows; i++) {
12224                 guint32 cols [MONO_DECL_SECURITY_SIZE];
12225
12226                 mono_metadata_decode_row (t, i, cols, MONO_DECL_SECURITY_SIZE);
12227                 if (cols [MONO_DECL_SECURITY_PARENT] != token)
12228                         break;
12229
12230                 action = cols [MONO_DECL_SECURITY_ACTION];
12231                 if ((action >= MONO_DECLSEC_ACTION_MIN) && (action <= MONO_DECLSEC_ACTION_MAX)) {
12232                         result |= declsec_flags_map [action];
12233                 } else {
12234                         g_assert_not_reached ();
12235                 }
12236         }
12237         return result;
12238 }
12239
12240 /*
12241  * Get the security actions (in the form of flags) associated with the specified method.
12242  *
12243  * @method: The method for which we want the declarative security flags.
12244  * Return the declarative security flags for the method (only).
12245  *
12246  * Note: To keep MonoMethod size down we do not cache the declarative security flags
12247  *       (except for the stack modifiers which are kept in the MonoJitInfo structure)
12248  */
12249 guint32
12250 mono_declsec_flags_from_method (MonoMethod *method)
12251 {
12252         if (method->flags & METHOD_ATTRIBUTE_HAS_SECURITY) {
12253                 /* FIXME: No cache (for the moment) */
12254                 guint32 idx = mono_method_get_index (method);
12255                 idx <<= MONO_HAS_DECL_SECURITY_BITS;
12256                 idx |= MONO_HAS_DECL_SECURITY_METHODDEF;
12257                 return mono_declsec_get_flags (method->klass->image, idx);
12258         }
12259         return 0;
12260 }
12261
12262 /*
12263  * Get the security actions (in the form of flags) associated with the specified class.
12264  *
12265  * @klass: The class for which we want the declarative security flags.
12266  * Return the declarative security flags for the class.
12267  *
12268  * Note: We cache the flags inside the MonoClass structure as this will get 
12269  *       called very often (at least for each method).
12270  */
12271 guint32
12272 mono_declsec_flags_from_class (MonoClass *klass)
12273 {
12274         if (klass->flags & TYPE_ATTRIBUTE_HAS_SECURITY) {
12275                 if (!klass->ext || !klass->ext->declsec_flags) {
12276                         guint32 idx;
12277
12278                         idx = mono_metadata_token_index (klass->type_token);
12279                         idx <<= MONO_HAS_DECL_SECURITY_BITS;
12280                         idx |= MONO_HAS_DECL_SECURITY_TYPEDEF;
12281                         mono_loader_lock ();
12282                         mono_class_alloc_ext (klass);
12283                         mono_loader_unlock ();
12284                         /* we cache the flags on classes */
12285                         klass->ext->declsec_flags = mono_declsec_get_flags (klass->image, idx);
12286                 }
12287                 return klass->ext->declsec_flags;
12288         }
12289         return 0;
12290 }
12291
12292 /*
12293  * Get the security actions (in the form of flags) associated with the specified assembly.
12294  *
12295  * @assembly: The assembly for which we want the declarative security flags.
12296  * Return the declarative security flags for the assembly.
12297  */
12298 guint32
12299 mono_declsec_flags_from_assembly (MonoAssembly *assembly)
12300 {
12301         guint32 idx = 1; /* there is only one assembly */
12302         idx <<= MONO_HAS_DECL_SECURITY_BITS;
12303         idx |= MONO_HAS_DECL_SECURITY_ASSEMBLY;
12304         return mono_declsec_get_flags (assembly->image, idx);
12305 }
12306
12307
12308 /*
12309  * Fill actions for the specific index (which may either be an encoded class token or
12310  * an encoded method token) from the metadata image.
12311  * Returns TRUE if some actions requiring code generation are present, FALSE otherwise.
12312  */
12313 static MonoBoolean
12314 fill_actions_from_index (MonoImage *image, guint32 token, MonoDeclSecurityActions* actions,
12315         guint32 id_std, guint32 id_noncas, guint32 id_choice)
12316 {
12317         MonoBoolean result = FALSE;
12318         MonoTableInfo *t;
12319         guint32 cols [MONO_DECL_SECURITY_SIZE];
12320         int index = mono_metadata_declsec_from_index (image, token);
12321         int i;
12322
12323         t  = &image->tables [MONO_TABLE_DECLSECURITY];
12324         for (i = index; i < t->rows; i++) {
12325                 mono_metadata_decode_row (t, i, cols, MONO_DECL_SECURITY_SIZE);
12326
12327                 if (cols [MONO_DECL_SECURITY_PARENT] != token)
12328                         return result;
12329
12330                 /* if present only replace (class) permissions with method permissions */
12331                 /* if empty accept either class or method permissions */
12332                 if (cols [MONO_DECL_SECURITY_ACTION] == id_std) {
12333                         if (!actions->demand.blob) {
12334                                 const char *blob = mono_metadata_blob_heap (image, cols [MONO_DECL_SECURITY_PERMISSIONSET]);
12335                                 actions->demand.index = cols [MONO_DECL_SECURITY_PERMISSIONSET];
12336                                 actions->demand.blob = (char*) (blob + 2);
12337                                 actions->demand.size = mono_metadata_decode_blob_size (blob, &blob);
12338                                 result = TRUE;
12339                         }
12340                 } else if (cols [MONO_DECL_SECURITY_ACTION] == id_noncas) {
12341                         if (!actions->noncasdemand.blob) {
12342                                 const char *blob = mono_metadata_blob_heap (image, cols [MONO_DECL_SECURITY_PERMISSIONSET]);
12343                                 actions->noncasdemand.index = cols [MONO_DECL_SECURITY_PERMISSIONSET];
12344                                 actions->noncasdemand.blob = (char*) (blob + 2);
12345                                 actions->noncasdemand.size = mono_metadata_decode_blob_size (blob, &blob);
12346                                 result = TRUE;
12347                         }
12348                 } else if (cols [MONO_DECL_SECURITY_ACTION] == id_choice) {
12349                         if (!actions->demandchoice.blob) {
12350                                 const char *blob = mono_metadata_blob_heap (image, cols [MONO_DECL_SECURITY_PERMISSIONSET]);
12351                                 actions->demandchoice.index = cols [MONO_DECL_SECURITY_PERMISSIONSET];
12352                                 actions->demandchoice.blob = (char*) (blob + 2);
12353                                 actions->demandchoice.size = mono_metadata_decode_blob_size (blob, &blob);
12354                                 result = TRUE;
12355                         }
12356                 }
12357         }
12358
12359         return result;
12360 }
12361
12362 static MonoBoolean
12363 mono_declsec_get_class_demands_params (MonoClass *klass, MonoDeclSecurityActions* demands, 
12364         guint32 id_std, guint32 id_noncas, guint32 id_choice)
12365 {
12366         guint32 idx = mono_metadata_token_index (klass->type_token);
12367         idx <<= MONO_HAS_DECL_SECURITY_BITS;
12368         idx |= MONO_HAS_DECL_SECURITY_TYPEDEF;
12369         return fill_actions_from_index (klass->image, idx, demands, id_std, id_noncas, id_choice);
12370 }
12371
12372 static MonoBoolean
12373 mono_declsec_get_method_demands_params (MonoMethod *method, MonoDeclSecurityActions* demands, 
12374         guint32 id_std, guint32 id_noncas, guint32 id_choice)
12375 {
12376         guint32 idx = mono_method_get_index (method);
12377         idx <<= MONO_HAS_DECL_SECURITY_BITS;
12378         idx |= MONO_HAS_DECL_SECURITY_METHODDEF;
12379         return fill_actions_from_index (method->klass->image, idx, demands, id_std, id_noncas, id_choice);
12380 }
12381
12382 /*
12383  * Collect all actions (that requires to generate code in mini) assigned for
12384  * the specified method.
12385  * Note: Don't use the content of actions if the function return FALSE.
12386  */
12387 MonoBoolean
12388 mono_declsec_get_demands (MonoMethod *method, MonoDeclSecurityActions* demands)
12389 {
12390         guint32 mask = MONO_DECLSEC_FLAG_DEMAND | MONO_DECLSEC_FLAG_NONCAS_DEMAND | 
12391                 MONO_DECLSEC_FLAG_DEMAND_CHOICE;
12392         MonoBoolean result = FALSE;
12393         guint32 flags;
12394
12395         /* quick exit if no declarative security is present in the metadata */
12396         if (!method->klass->image->tables [MONO_TABLE_DECLSECURITY].rows)
12397                 return FALSE;
12398
12399         /* we want the original as the wrapper is "free" of the security informations */
12400         if (method->wrapper_type == MONO_WRAPPER_MANAGED_TO_NATIVE || method->wrapper_type == MONO_WRAPPER_MANAGED_TO_MANAGED) {
12401                 method = mono_marshal_method_from_wrapper (method);
12402                 if (!method)
12403                         return FALSE;
12404         }
12405
12406         /* First we look for method-level attributes */
12407         if (method->flags & METHOD_ATTRIBUTE_HAS_SECURITY) {
12408                 mono_class_init (method->klass);
12409                 memset (demands, 0, sizeof (MonoDeclSecurityActions));
12410
12411                 result = mono_declsec_get_method_demands_params (method, demands, 
12412                         SECURITY_ACTION_DEMAND, SECURITY_ACTION_NONCASDEMAND, SECURITY_ACTION_DEMANDCHOICE);
12413         }
12414
12415         /* Here we use (or create) the class declarative cache to look for demands */
12416         flags = mono_declsec_flags_from_class (method->klass);
12417         if (flags & mask) {
12418                 if (!result) {
12419                         mono_class_init (method->klass);
12420                         memset (demands, 0, sizeof (MonoDeclSecurityActions));
12421                 }
12422                 result |= mono_declsec_get_class_demands_params (method->klass, demands, 
12423                         SECURITY_ACTION_DEMAND, SECURITY_ACTION_NONCASDEMAND, SECURITY_ACTION_DEMANDCHOICE);
12424         }
12425
12426         /* The boolean return value is used as a shortcut in case nothing needs to
12427            be generated (e.g. LinkDemand[Choice] and InheritanceDemand[Choice]) */
12428         return result;
12429 }
12430
12431
12432 /*
12433  * Collect all Link actions: LinkDemand, NonCasLinkDemand and LinkDemandChoice (2.0).
12434  *
12435  * Note: Don't use the content of actions if the function return FALSE.
12436  */
12437 MonoBoolean
12438 mono_declsec_get_linkdemands (MonoMethod *method, MonoDeclSecurityActions* klass, MonoDeclSecurityActions *cmethod)
12439 {
12440         MonoBoolean result = FALSE;
12441         guint32 flags;
12442
12443         /* quick exit if no declarative security is present in the metadata */
12444         if (!method->klass->image->tables [MONO_TABLE_DECLSECURITY].rows)
12445                 return FALSE;
12446
12447         /* we want the original as the wrapper is "free" of the security informations */
12448         if (method->wrapper_type == MONO_WRAPPER_MANAGED_TO_NATIVE || method->wrapper_type == MONO_WRAPPER_MANAGED_TO_MANAGED) {
12449                 method = mono_marshal_method_from_wrapper (method);
12450                 if (!method)
12451                         return FALSE;
12452         }
12453
12454         /* results are independant - zeroize both */
12455         memset (cmethod, 0, sizeof (MonoDeclSecurityActions));
12456         memset (klass, 0, sizeof (MonoDeclSecurityActions));
12457
12458         /* First we look for method-level attributes */
12459         if (method->flags & METHOD_ATTRIBUTE_HAS_SECURITY) {
12460                 mono_class_init (method->klass);
12461
12462                 result = mono_declsec_get_method_demands_params (method, cmethod, 
12463                         SECURITY_ACTION_LINKDEMAND, SECURITY_ACTION_NONCASLINKDEMAND, SECURITY_ACTION_LINKDEMANDCHOICE);
12464         }
12465
12466         /* Here we use (or create) the class declarative cache to look for demands */
12467         flags = mono_declsec_flags_from_class (method->klass);
12468         if (flags & (MONO_DECLSEC_FLAG_LINKDEMAND | MONO_DECLSEC_FLAG_NONCAS_LINKDEMAND | MONO_DECLSEC_FLAG_LINKDEMAND_CHOICE)) {
12469                 mono_class_init (method->klass);
12470
12471                 result |= mono_declsec_get_class_demands_params (method->klass, klass, 
12472                         SECURITY_ACTION_LINKDEMAND, SECURITY_ACTION_NONCASLINKDEMAND, SECURITY_ACTION_LINKDEMANDCHOICE);
12473         }
12474
12475         return result;
12476 }
12477
12478 /*
12479  * Collect all Inherit actions: InheritanceDemand, NonCasInheritanceDemand and InheritanceDemandChoice (2.0).
12480  *
12481  * @klass       The inherited class - this is the class that provides the security check (attributes)
12482  * @demans      
12483  * return TRUE if inheritance demands (any kind) are present, FALSE otherwise.
12484  * 
12485  * Note: Don't use the content of actions if the function return FALSE.
12486  */
12487 MonoBoolean
12488 mono_declsec_get_inheritdemands_class (MonoClass *klass, MonoDeclSecurityActions* demands)
12489 {
12490         MonoBoolean result = FALSE;
12491         guint32 flags;
12492
12493         /* quick exit if no declarative security is present in the metadata */
12494         if (!klass->image->tables [MONO_TABLE_DECLSECURITY].rows)
12495                 return FALSE;
12496
12497         /* Here we use (or create) the class declarative cache to look for demands */
12498         flags = mono_declsec_flags_from_class (klass);
12499         if (flags & (MONO_DECLSEC_FLAG_INHERITANCEDEMAND | MONO_DECLSEC_FLAG_NONCAS_INHERITANCEDEMAND | MONO_DECLSEC_FLAG_INHERITANCEDEMAND_CHOICE)) {
12500                 mono_class_init (klass);
12501                 memset (demands, 0, sizeof (MonoDeclSecurityActions));
12502
12503                 result |= mono_declsec_get_class_demands_params (klass, demands, 
12504                         SECURITY_ACTION_INHERITDEMAND, SECURITY_ACTION_NONCASINHERITANCE, SECURITY_ACTION_INHERITDEMANDCHOICE);
12505         }
12506
12507         return result;
12508 }
12509
12510 /*
12511  * Collect all Inherit actions: InheritanceDemand, NonCasInheritanceDemand and InheritanceDemandChoice (2.0).
12512  *
12513  * Note: Don't use the content of actions if the function return FALSE.
12514  */
12515 MonoBoolean
12516 mono_declsec_get_inheritdemands_method (MonoMethod *method, MonoDeclSecurityActions* demands)
12517 {
12518         /* quick exit if no declarative security is present in the metadata */
12519         if (!method->klass->image->tables [MONO_TABLE_DECLSECURITY].rows)
12520                 return FALSE;
12521
12522         /* we want the original as the wrapper is "free" of the security informations */
12523         if (method->wrapper_type == MONO_WRAPPER_MANAGED_TO_NATIVE || method->wrapper_type == MONO_WRAPPER_MANAGED_TO_MANAGED) {
12524                 method = mono_marshal_method_from_wrapper (method);
12525                 if (!method)
12526                         return FALSE;
12527         }
12528
12529         if (method->flags & METHOD_ATTRIBUTE_HAS_SECURITY) {
12530                 mono_class_init (method->klass);
12531                 memset (demands, 0, sizeof (MonoDeclSecurityActions));
12532
12533                 return mono_declsec_get_method_demands_params (method, demands, 
12534                         SECURITY_ACTION_INHERITDEMAND, SECURITY_ACTION_NONCASINHERITANCE, SECURITY_ACTION_INHERITDEMANDCHOICE);
12535         }
12536         return FALSE;
12537 }
12538
12539
12540 static MonoBoolean
12541 get_declsec_action (MonoImage *image, guint32 token, guint32 action, MonoDeclSecurityEntry *entry)
12542 {
12543         guint32 cols [MONO_DECL_SECURITY_SIZE];
12544         MonoTableInfo *t;
12545         int i;
12546
12547         int index = mono_metadata_declsec_from_index (image, token);
12548         if (index == -1)
12549                 return FALSE;
12550
12551         t =  &image->tables [MONO_TABLE_DECLSECURITY];
12552         for (i = index; i < t->rows; i++) {
12553                 mono_metadata_decode_row (t, i, cols, MONO_DECL_SECURITY_SIZE);
12554
12555                 /* shortcut - index are ordered */
12556                 if (token != cols [MONO_DECL_SECURITY_PARENT])
12557                         return FALSE;
12558
12559                 if (cols [MONO_DECL_SECURITY_ACTION] == action) {
12560                         const char *metadata = mono_metadata_blob_heap (image, cols [MONO_DECL_SECURITY_PERMISSIONSET]);
12561                         entry->blob = (char*) (metadata + 2);
12562                         entry->size = mono_metadata_decode_blob_size (metadata, &metadata);
12563                         return TRUE;
12564                 }
12565         }
12566
12567         return FALSE;
12568 }
12569
12570 MonoBoolean
12571 mono_declsec_get_method_action (MonoMethod *method, guint32 action, MonoDeclSecurityEntry *entry)
12572 {
12573         if (method->flags & METHOD_ATTRIBUTE_HAS_SECURITY) {
12574                 guint32 idx = mono_method_get_index (method);
12575                 idx <<= MONO_HAS_DECL_SECURITY_BITS;
12576                 idx |= MONO_HAS_DECL_SECURITY_METHODDEF;
12577                 return get_declsec_action (method->klass->image, idx, action, entry);
12578         }
12579         return FALSE;
12580 }
12581
12582 MonoBoolean
12583 mono_declsec_get_class_action (MonoClass *klass, guint32 action, MonoDeclSecurityEntry *entry)
12584 {
12585         /* use cache */
12586         guint32 flags = mono_declsec_flags_from_class (klass);
12587         if (declsec_flags_map [action] & flags) {
12588                 guint32 idx = mono_metadata_token_index (klass->type_token);
12589                 idx <<= MONO_HAS_DECL_SECURITY_BITS;
12590                 idx |= MONO_HAS_DECL_SECURITY_TYPEDEF;
12591                 return get_declsec_action (klass->image, idx, action, entry);
12592         }
12593         return FALSE;
12594 }
12595
12596 MonoBoolean
12597 mono_declsec_get_assembly_action (MonoAssembly *assembly, guint32 action, MonoDeclSecurityEntry *entry)
12598 {
12599         guint32 idx = 1; /* there is only one assembly */
12600         idx <<= MONO_HAS_DECL_SECURITY_BITS;
12601         idx |= MONO_HAS_DECL_SECURITY_ASSEMBLY;
12602
12603         return get_declsec_action (assembly->image, idx, action, entry);
12604 }
12605
12606 gboolean
12607 mono_reflection_call_is_assignable_to (MonoClass *klass, MonoClass *oklass)
12608 {
12609         MonoObject *res, *exc;
12610         void *params [1];
12611         static MonoClass *System_Reflection_Emit_TypeBuilder = NULL;
12612         static MonoMethod *method = NULL;
12613
12614         if (!System_Reflection_Emit_TypeBuilder) {
12615                 System_Reflection_Emit_TypeBuilder = mono_class_from_name (mono_defaults.corlib, "System.Reflection.Emit", "TypeBuilder");
12616                 g_assert (System_Reflection_Emit_TypeBuilder);
12617         }
12618         if (method == NULL) {
12619                 method = mono_class_get_method_from_name (System_Reflection_Emit_TypeBuilder, "IsAssignableTo", 1);
12620                 g_assert (method);
12621         }
12622
12623         /* 
12624          * The result of mono_type_get_object () might be a System.MonoType but we
12625          * need a TypeBuilder so use mono_class_get_ref_info (klass).
12626          */
12627         g_assert (mono_class_get_ref_info (klass));
12628         g_assert (!strcmp (((MonoObject*)(mono_class_get_ref_info (klass)))->vtable->klass->name, "TypeBuilder"));
12629
12630         params [0] = mono_type_get_object (mono_domain_get (), &oklass->byval_arg);
12631
12632         res = mono_runtime_invoke (method, (MonoObject*)(mono_class_get_ref_info (klass)), params, &exc);
12633         if (exc)
12634                 return FALSE;
12635         else
12636                 return *(MonoBoolean*)mono_object_unbox (res);
12637 }
12638
12639 /**
12640  * mono_reflection_type_get_type:
12641  * @reftype: the System.Type object
12642  *
12643  * Returns the MonoType* associated with the C# System.Type object @reftype.
12644  */
12645 MonoType*
12646 mono_reflection_type_get_type (MonoReflectionType *reftype)
12647 {
12648         g_assert (reftype);
12649
12650         return mono_reflection_type_get_handle (reftype);
12651 }
12652