Merge pull request #268 from pcc/menudeactivate
[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, *temp, *last_point, *startn;
7232         int in_modifiers = 0;
7233         int isbyref = 0, rank, arity = 0, i;
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                 case '`':
7281                         ++p;
7282                         i = strtol (p, &temp, 10);
7283                         arity += i;
7284                         if (p == temp)
7285                                 return 0;
7286                         p = temp-1;
7287                         break;
7288                 default:
7289                         break;
7290                 }
7291                 if (in_modifiers)
7292                         break;
7293                 // *w++ = *p++;
7294                 p++;
7295         }
7296         
7297         if (!info->name) {
7298                 if (last_point) {
7299                         info->name_space = start;
7300                         *last_point = 0;
7301                         info->name = last_point + 1;
7302                 } else {
7303                         info->name_space = (char *)"";
7304                         info->name = start;
7305                 }
7306         }
7307         while (*p) {
7308                 switch (*p) {
7309                 case '&':
7310                         if (isbyref) /* only one level allowed by the spec */
7311                                 return 0;
7312                         isbyref = 1;
7313                         info->modifiers = g_list_append (info->modifiers, GUINT_TO_POINTER (0));
7314                         *p++ = 0;
7315                         break;
7316                 case '*':
7317                         info->modifiers = g_list_append (info->modifiers, GUINT_TO_POINTER (-1));
7318                         *p++ = 0;
7319                         break;
7320                 case '[':
7321                         if (arity != 0) {
7322                                 *p++ = 0;
7323                                 info->type_arguments = g_ptr_array_new ();
7324                                 for (i = 0; i < arity; i++) {
7325                                         MonoTypeNameParse *subinfo = g_new0 (MonoTypeNameParse, 1);
7326                                         gboolean fqname = FALSE;
7327
7328                                         g_ptr_array_add (info->type_arguments, subinfo);
7329
7330                                         if (*p == '[') {
7331                                                 p++;
7332                                                 fqname = TRUE;
7333                                         }
7334
7335                                         if (!_mono_reflection_parse_type (p, &p, TRUE, subinfo))
7336                                                 return 0;
7337
7338                                         /*MS is lenient on [] delimited parameters that aren't fqn - and F# uses them.*/
7339                                         if (fqname && (*p != ']')) {
7340                                                 char *aname;
7341
7342                                                 if (*p != ',')
7343                                                         return 0;
7344                                                 *p++ = 0;
7345
7346                                                 aname = p;
7347                                                 while (*p && (*p != ']'))
7348                                                         p++;
7349
7350                                                 if (*p != ']')
7351                                                         return 0;
7352
7353                                                 *p++ = 0;
7354                                                 while (*aname) {
7355                                                         if (g_ascii_isspace (*aname)) {
7356                                                                 ++aname;
7357                                                                 continue;
7358                                                         }
7359                                                         break;
7360                                                 }
7361                                                 if (!*aname ||
7362                                                     !assembly_name_to_aname (&subinfo->assembly, aname))
7363                                                         return 0;
7364                                         } else if (fqname && (*p == ']')) {
7365                                                 *p++ = 0;
7366                                         }
7367
7368                                         if (i + 1 < arity) {
7369                                                 if (*p != ',')
7370                                                         return 0;
7371                                         } else {
7372                                                 if (*p != ']')
7373                                                         return 0;
7374                                         }
7375                                         *p++ = 0;
7376                                 }
7377
7378                                 arity = 0;
7379                                 break;
7380                         }
7381                         rank = 1;
7382                         *p++ = 0;
7383                         while (*p) {
7384                                 if (*p == ']')
7385                                         break;
7386                                 if (*p == ',')
7387                                         rank++;
7388                                 else if (*p == '*') /* '*' means unknown lower bound */
7389                                         info->modifiers = g_list_append (info->modifiers, GUINT_TO_POINTER (-2));
7390                                 else
7391                                         return 0;
7392                                 ++p;
7393                         }
7394                         if (*p++ != ']')
7395                                 return 0;
7396                         info->modifiers = g_list_append (info->modifiers, GUINT_TO_POINTER (rank));
7397                         break;
7398                 case ']':
7399                         if (is_recursed)
7400                                 goto end;
7401                         return 0;
7402                 case ',':
7403                         if (is_recursed)
7404                                 goto end;
7405                         *p++ = 0;
7406                         while (*p) {
7407                                 if (g_ascii_isspace (*p)) {
7408                                         ++p;
7409                                         continue;
7410                                 }
7411                                 break;
7412                         }
7413                         if (!*p)
7414                                 return 0; /* missing assembly name */
7415                         if (!assembly_name_to_aname (&info->assembly, p))
7416                                 return 0;
7417                         break;
7418                 default:
7419                         return 0;
7420                 }
7421                 if (info->assembly.name)
7422                         break;
7423         }
7424         // *w = 0; /* terminate class name */
7425  end:
7426         if (!info->name || !*info->name)
7427                 return 0;
7428         if (endptr)
7429                 *endptr = p;
7430         /* add other consistency checks */
7431         return 1;
7432 }
7433
7434 int
7435 mono_reflection_parse_type (char *name, MonoTypeNameParse *info)
7436 {
7437         return _mono_reflection_parse_type (name, NULL, FALSE, info);
7438 }
7439
7440 static MonoType*
7441 _mono_reflection_get_type_from_info (MonoTypeNameParse *info, MonoImage *image, gboolean ignorecase)
7442 {
7443         gboolean type_resolve = FALSE;
7444         MonoType *type;
7445         MonoImage *rootimage = image;
7446
7447         if (info->assembly.name) {
7448                 MonoAssembly *assembly = mono_assembly_loaded (&info->assembly);
7449                 if (!assembly && image && image->assembly && mono_assembly_names_equal (&info->assembly, &image->assembly->aname))
7450                         /* 
7451                          * This could happen in the AOT compiler case when the search hook is not
7452                          * installed.
7453                          */
7454                         assembly = image->assembly;
7455                 if (!assembly) {
7456                         /* then we must load the assembly ourselve - see #60439 */
7457                         assembly = mono_assembly_load (&info->assembly, NULL, NULL);
7458                         if (!assembly)
7459                                 return NULL;
7460                 }
7461                 image = assembly->image;
7462         } else if (!image) {
7463                 image = mono_defaults.corlib;
7464         }
7465
7466         type = mono_reflection_get_type_with_rootimage (rootimage, image, info, ignorecase, &type_resolve);
7467         if (type == NULL && !info->assembly.name && image != mono_defaults.corlib) {
7468                 image = mono_defaults.corlib;
7469                 type = mono_reflection_get_type_with_rootimage (rootimage, image, info, ignorecase, &type_resolve);
7470         }
7471
7472         return type;
7473 }
7474
7475 static MonoType*
7476 mono_reflection_get_type_internal (MonoImage *rootimage, MonoImage* image, MonoTypeNameParse *info, gboolean ignorecase)
7477 {
7478         MonoClass *klass;
7479         GList *mod;
7480         int modval;
7481         gboolean bounded = FALSE;
7482         
7483         if (!image)
7484                 image = mono_defaults.corlib;
7485
7486         if (ignorecase)
7487                 klass = mono_class_from_name_case (image, info->name_space, info->name);
7488         else
7489                 klass = mono_class_from_name (image, info->name_space, info->name);
7490         if (!klass)
7491                 return NULL;
7492         for (mod = info->nested; mod; mod = mod->next) {
7493                 gpointer iter = NULL;
7494                 MonoClass *parent;
7495
7496                 parent = klass;
7497                 mono_class_init (parent);
7498
7499                 while ((klass = mono_class_get_nested_types (parent, &iter))) {
7500                         if (ignorecase) {
7501                                 if (mono_utf8_strcasecmp (klass->name, mod->data) == 0)
7502                                         break;
7503                         } else {
7504                                 if (strcmp (klass->name, mod->data) == 0)
7505                                         break;
7506                         }
7507                 }
7508                 if (!klass)
7509                         break;
7510         }
7511         if (!klass)
7512                 return NULL;
7513
7514         if (info->type_arguments) {
7515                 MonoType **type_args = g_new0 (MonoType *, info->type_arguments->len);
7516                 MonoReflectionType *the_type;
7517                 MonoType *instance;
7518                 int i;
7519
7520                 for (i = 0; i < info->type_arguments->len; i++) {
7521                         MonoTypeNameParse *subinfo = g_ptr_array_index (info->type_arguments, i);
7522
7523                         type_args [i] = _mono_reflection_get_type_from_info (subinfo, rootimage, ignorecase);
7524                         if (!type_args [i]) {
7525                                 g_free (type_args);
7526                                 return NULL;
7527                         }
7528                 }
7529
7530                 the_type = mono_type_get_object (mono_domain_get (), &klass->byval_arg);
7531
7532                 instance = mono_reflection_bind_generic_parameters (
7533                         the_type, info->type_arguments->len, type_args);
7534
7535                 g_free (type_args);
7536                 if (!instance)
7537                         return NULL;
7538
7539                 klass = mono_class_from_mono_type (instance);
7540         }
7541
7542         for (mod = info->modifiers; mod; mod = mod->next) {
7543                 modval = GPOINTER_TO_UINT (mod->data);
7544                 if (!modval) { /* byref: must be last modifier */
7545                         return &klass->this_arg;
7546                 } else if (modval == -1) {
7547                         klass = mono_ptr_class_get (&klass->byval_arg);
7548                 } else if (modval == -2) {
7549                         bounded = TRUE;
7550                 } else { /* array rank */
7551                         klass = mono_bounded_array_class_get (klass, modval, bounded);
7552                 }
7553         }
7554
7555         return &klass->byval_arg;
7556 }
7557
7558 /*
7559  * mono_reflection_get_type:
7560  * @image: a metadata context
7561  * @info: type description structure
7562  * @ignorecase: flag for case-insensitive string compares
7563  * @type_resolve: whenever type resolve was already tried
7564  *
7565  * Build a MonoType from the type description in @info.
7566  * 
7567  */
7568
7569 MonoType*
7570 mono_reflection_get_type (MonoImage* image, MonoTypeNameParse *info, gboolean ignorecase, gboolean *type_resolve) {
7571         return mono_reflection_get_type_with_rootimage(image, image, info, ignorecase, type_resolve);
7572 }
7573
7574 static MonoType*
7575 mono_reflection_get_type_internal_dynamic (MonoImage *rootimage, MonoAssembly *assembly, MonoTypeNameParse *info, gboolean ignorecase)
7576 {
7577         MonoReflectionAssemblyBuilder *abuilder;
7578         MonoType *type;
7579         int i;
7580
7581         g_assert (assembly->dynamic);
7582         abuilder = (MonoReflectionAssemblyBuilder*)mono_assembly_get_object (((MonoDynamicAssembly*)assembly)->domain, assembly);
7583
7584         /* Enumerate all modules */
7585
7586         type = NULL;
7587         if (abuilder->modules) {
7588                 for (i = 0; i < mono_array_length (abuilder->modules); ++i) {
7589                         MonoReflectionModuleBuilder *mb = mono_array_get (abuilder->modules, MonoReflectionModuleBuilder*, i);
7590                         type = mono_reflection_get_type_internal (rootimage, &mb->dynamic_image->image, info, ignorecase);
7591                         if (type)
7592                                 break;
7593                 }
7594         }
7595
7596         if (!type && abuilder->loaded_modules) {
7597                 for (i = 0; i < mono_array_length (abuilder->loaded_modules); ++i) {
7598                         MonoReflectionModule *mod = mono_array_get (abuilder->loaded_modules, MonoReflectionModule*, i);
7599                         type = mono_reflection_get_type_internal (rootimage, mod->image, info, ignorecase);
7600                         if (type)
7601                                 break;
7602                 }
7603         }
7604
7605         return type;
7606 }
7607         
7608 MonoType*
7609 mono_reflection_get_type_with_rootimage (MonoImage *rootimage, MonoImage* image, MonoTypeNameParse *info, gboolean ignorecase, gboolean *type_resolve)
7610 {
7611         MonoType *type;
7612         MonoReflectionAssembly *assembly;
7613         GString *fullName;
7614         GList *mod;
7615
7616         if (image && image->dynamic)
7617                 type = mono_reflection_get_type_internal_dynamic (rootimage, image->assembly, info, ignorecase);
7618         else
7619                 type = mono_reflection_get_type_internal (rootimage, image, info, ignorecase);
7620         if (type)
7621                 return type;
7622         if (!mono_domain_has_type_resolve (mono_domain_get ()))
7623                 return NULL;
7624
7625         if (type_resolve) {
7626                 if (*type_resolve) 
7627                         return NULL;
7628                 else
7629                         *type_resolve = TRUE;
7630         }
7631         
7632         /* Reconstruct the type name */
7633         fullName = g_string_new ("");
7634         if (info->name_space && (info->name_space [0] != '\0'))
7635                 g_string_printf (fullName, "%s.%s", info->name_space, info->name);
7636         else
7637                 g_string_printf (fullName, "%s", info->name);
7638         for (mod = info->nested; mod; mod = mod->next)
7639                 g_string_append_printf (fullName, "+%s", (char*)mod->data);
7640
7641         assembly = mono_domain_try_type_resolve ( mono_domain_get (), fullName->str, NULL);
7642         if (assembly) {
7643                 if (assembly->assembly->dynamic)
7644                         type = mono_reflection_get_type_internal_dynamic (rootimage, assembly->assembly, info, ignorecase);
7645                 else
7646                         type = mono_reflection_get_type_internal (rootimage, assembly->assembly->image, 
7647                                                                                                           info, ignorecase);
7648         }
7649         g_string_free (fullName, TRUE);
7650         return type;
7651 }
7652
7653 void
7654 mono_reflection_free_type_info (MonoTypeNameParse *info)
7655 {
7656         g_list_free (info->modifiers);
7657         g_list_free (info->nested);
7658
7659         if (info->type_arguments) {
7660                 int i;
7661
7662                 for (i = 0; i < info->type_arguments->len; i++) {
7663                         MonoTypeNameParse *subinfo = g_ptr_array_index (info->type_arguments, i);
7664
7665                         mono_reflection_free_type_info (subinfo);
7666                         /*We free the subinfo since it is allocated by _mono_reflection_parse_type*/
7667                         g_free (subinfo);
7668                 }
7669
7670                 g_ptr_array_free (info->type_arguments, TRUE);
7671         }
7672 }
7673
7674 /*
7675  * mono_reflection_type_from_name:
7676  * @name: type name.
7677  * @image: a metadata context (can be NULL).
7678  *
7679  * Retrieves a MonoType from its @name. If the name is not fully qualified,
7680  * it defaults to get the type from @image or, if @image is NULL or loading
7681  * from it fails, uses corlib.
7682  * 
7683  */
7684 MonoType*
7685 mono_reflection_type_from_name (char *name, MonoImage *image)
7686 {
7687         MonoType *type = NULL;
7688         MonoTypeNameParse info;
7689         char *tmp;
7690
7691         /* Make a copy since parse_type modifies its argument */
7692         tmp = g_strdup (name);
7693         
7694         /*g_print ("requested type %s\n", str);*/
7695         if (mono_reflection_parse_type (tmp, &info)) {
7696                 type = _mono_reflection_get_type_from_info (&info, image, FALSE);
7697         }
7698
7699         g_free (tmp);
7700         mono_reflection_free_type_info (&info);
7701         return type;
7702 }
7703
7704 /*
7705  * mono_reflection_get_token:
7706  *
7707  *   Return the metadata token of OBJ which should be an object
7708  * representing a metadata element.
7709  */
7710 guint32
7711 mono_reflection_get_token (MonoObject *obj)
7712 {
7713         MonoClass *klass;
7714         guint32 token = 0;
7715
7716         klass = obj->vtable->klass;
7717
7718         if (strcmp (klass->name, "MethodBuilder") == 0) {
7719                 MonoReflectionMethodBuilder *mb = (MonoReflectionMethodBuilder *)obj;
7720
7721                 token = mb->table_idx | MONO_TOKEN_METHOD_DEF;
7722         } else if (strcmp (klass->name, "ConstructorBuilder") == 0) {
7723                 MonoReflectionCtorBuilder *mb = (MonoReflectionCtorBuilder *)obj;
7724
7725                 token = mb->table_idx | MONO_TOKEN_METHOD_DEF;
7726         } else if (strcmp (klass->name, "FieldBuilder") == 0) {
7727                 MonoReflectionFieldBuilder *fb = (MonoReflectionFieldBuilder *)obj;
7728
7729                 token = fb->table_idx | MONO_TOKEN_FIELD_DEF;
7730         } else if (strcmp (klass->name, "TypeBuilder") == 0) {
7731                 MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder *)obj;
7732                 token = tb->table_idx | MONO_TOKEN_TYPE_DEF;
7733         } else if (strcmp (klass->name, "MonoType") == 0) {
7734                 MonoType *type = mono_reflection_type_get_handle ((MonoReflectionType*)obj);
7735                 MonoClass *mc = mono_class_from_mono_type (type);
7736                 if (!mono_class_init (mc))
7737                         mono_raise_exception (mono_class_get_exception_for_failure (mc));
7738
7739                 token = mc->type_token;
7740         } else if (strcmp (klass->name, "MonoCMethod") == 0 ||
7741                    strcmp (klass->name, "MonoMethod") == 0 ||
7742                    strcmp (klass->name, "MonoGenericMethod") == 0 ||
7743                    strcmp (klass->name, "MonoGenericCMethod") == 0) {
7744                 MonoReflectionMethod *m = (MonoReflectionMethod *)obj;
7745                 if (m->method->is_inflated) {
7746                         MonoMethodInflated *inflated = (MonoMethodInflated *) m->method;
7747                         return inflated->declaring->token;
7748                 } else {
7749                         token = m->method->token;
7750                 }
7751         } else if (strcmp (klass->name, "MonoField") == 0) {
7752                 MonoReflectionField *f = (MonoReflectionField*)obj;
7753
7754                 if (is_field_on_inst (f->field)) {
7755                         MonoDynamicGenericClass *dgclass = (MonoDynamicGenericClass*)f->field->parent->generic_class;
7756                         int field_index = f->field - dgclass->fields;
7757                         MonoObject *obj;
7758
7759                         g_assert (field_index >= 0 && field_index < dgclass->count_fields);
7760                         obj = dgclass->field_objects [field_index];
7761                         return mono_reflection_get_token (obj);
7762                 }
7763                 token = mono_class_get_field_token (f->field);
7764         } else if (strcmp (klass->name, "MonoProperty") == 0) {
7765                 MonoReflectionProperty *p = (MonoReflectionProperty*)obj;
7766
7767                 token = mono_class_get_property_token (p->property);
7768         } else if (strcmp (klass->name, "MonoEvent") == 0) {
7769                 MonoReflectionMonoEvent *p = (MonoReflectionMonoEvent*)obj;
7770
7771                 token = mono_class_get_event_token (p->event);
7772         } else if (strcmp (klass->name, "ParameterInfo") == 0 || strcmp (klass->name, "MonoParameterInfo") == 0) {
7773                 MonoReflectionParameter *p = (MonoReflectionParameter*)obj;
7774                 MonoClass *member_class = mono_object_class (p->MemberImpl);
7775                 g_assert (mono_class_is_reflection_method_or_constructor (member_class));
7776
7777                 token = mono_method_get_param_token (((MonoReflectionMethod*)p->MemberImpl)->method, p->PositionImpl);
7778         } else if (strcmp (klass->name, "Module") == 0 || strcmp (klass->name, "MonoModule") == 0) {
7779                 MonoReflectionModule *m = (MonoReflectionModule*)obj;
7780
7781                 token = m->token;
7782         } else if (strcmp (klass->name, "Assembly") == 0 || strcmp (klass->name, "MonoAssembly") == 0) {
7783                 token = mono_metadata_make_token (MONO_TABLE_ASSEMBLY, 1);
7784         } else {
7785                 gchar *msg = g_strdup_printf ("MetadataToken is not supported for type '%s.%s'", klass->name_space, klass->name);
7786                 MonoException *ex = mono_get_exception_not_implemented (msg);
7787                 g_free (msg);
7788                 mono_raise_exception (ex);
7789         }
7790
7791         return token;
7792 }
7793
7794 static MonoClass*
7795 load_cattr_enum_type (MonoImage *image, const char *p, const char **end)
7796 {
7797         char *n;
7798         MonoType *t;
7799         int slen = mono_metadata_decode_value (p, &p);
7800         n = g_memdup (p, slen + 1);
7801         n [slen] = 0;
7802         t = mono_reflection_type_from_name (n, image);
7803         if (!t)
7804                 g_error ("Cannot load type '%s'", n);
7805         g_free (n);
7806         p += slen;
7807         *end = p;
7808         return mono_class_from_mono_type (t);
7809 }
7810
7811 static void*
7812 load_cattr_value (MonoImage *image, MonoType *t, const char *p, const char **end)
7813 {
7814         int slen, type = t->type;
7815         MonoClass *tklass = t->data.klass;
7816
7817 handle_enum:
7818         switch (type) {
7819         case MONO_TYPE_U1:
7820         case MONO_TYPE_I1:
7821         case MONO_TYPE_BOOLEAN: {
7822                 MonoBoolean *bval = g_malloc (sizeof (MonoBoolean));
7823                 *bval = *p;
7824                 *end = p + 1;
7825                 return bval;
7826         }
7827         case MONO_TYPE_CHAR:
7828         case MONO_TYPE_U2:
7829         case MONO_TYPE_I2: {
7830                 guint16 *val = g_malloc (sizeof (guint16));
7831                 *val = read16 (p);
7832                 *end = p + 2;
7833                 return val;
7834         }
7835 #if SIZEOF_VOID_P == 4
7836         case MONO_TYPE_U:
7837         case MONO_TYPE_I:
7838 #endif
7839         case MONO_TYPE_R4:
7840         case MONO_TYPE_U4:
7841         case MONO_TYPE_I4: {
7842                 guint32 *val = g_malloc (sizeof (guint32));
7843                 *val = read32 (p);
7844                 *end = p + 4;
7845                 return val;
7846         }
7847 #if SIZEOF_VOID_P == 8
7848         case MONO_TYPE_U: /* error out instead? this should probably not happen */
7849         case MONO_TYPE_I:
7850 #endif
7851         case MONO_TYPE_U8:
7852         case MONO_TYPE_I8: {
7853                 guint64 *val = g_malloc (sizeof (guint64));
7854                 *val = read64 (p);
7855                 *end = p + 8;
7856                 return val;
7857         }
7858         case MONO_TYPE_R8: {
7859                 double *val = g_malloc (sizeof (double));
7860                 readr8 (p, val);
7861                 *end = p + 8;
7862                 return val;
7863         }
7864         case MONO_TYPE_VALUETYPE:
7865                 if (t->data.klass->enumtype) {
7866                         type = mono_class_enum_basetype (t->data.klass)->type;
7867                         goto handle_enum;
7868                 } else {
7869                         MonoClass *k =  t->data.klass;
7870                         
7871                         if (mono_is_corlib_image (k->image) && strcmp (k->name_space, "System") == 0 && strcmp (k->name, "DateTime") == 0){
7872                                 guint64 *val = g_malloc (sizeof (guint64));
7873                                 *val = read64 (p);
7874                                 *end = p + 8;
7875                                 return val;
7876                         }
7877                 }
7878                 g_error ("generic valutype %s not handled in custom attr value decoding", t->data.klass->name);
7879                 break;
7880                 
7881         case MONO_TYPE_STRING:
7882                 if (*p == (char)0xFF) {
7883                         *end = p + 1;
7884                         return NULL;
7885                 }
7886                 slen = mono_metadata_decode_value (p, &p);
7887                 *end = p + slen;
7888                 return mono_string_new_len (mono_domain_get (), p, slen);
7889         case MONO_TYPE_CLASS: {
7890                 char *n;
7891                 MonoType *t;
7892                 if (*p == (char)0xFF) {
7893                         *end = p + 1;
7894                         return NULL;
7895                 }
7896 handle_type:
7897                 slen = mono_metadata_decode_value (p, &p);
7898                 n = g_memdup (p, slen + 1);
7899                 n [slen] = 0;
7900                 t = mono_reflection_type_from_name (n, image);
7901                 if (!t)
7902                         g_warning ("Cannot load type '%s'", n);
7903                 g_free (n);
7904                 *end = p + slen;
7905                 if (t)
7906                         return mono_type_get_object (mono_domain_get (), t);
7907                 else
7908                         return NULL;
7909         }
7910         case MONO_TYPE_OBJECT: {
7911                 char subt = *p++;
7912                 MonoObject *obj;
7913                 MonoClass *subc = NULL;
7914                 void *val;
7915
7916                 if (subt == 0x50) {
7917                         goto handle_type;
7918                 } else if (subt == 0x0E) {
7919                         type = MONO_TYPE_STRING;
7920                         goto handle_enum;
7921                 } else if (subt == 0x1D) {
7922                         MonoType simple_type = {{0}};
7923                         int etype = *p;
7924                         p ++;
7925
7926                         type = MONO_TYPE_SZARRAY;
7927                         if (etype == 0x50) {
7928                                 tklass = mono_defaults.systemtype_class;
7929                         } else if (etype == 0x55) {
7930                                 tklass = load_cattr_enum_type (image, p, &p);
7931                         } else {
7932                                 if (etype == 0x51)
7933                                         /* See Partition II, Appendix B3 */
7934                                         etype = MONO_TYPE_OBJECT;
7935                                 simple_type.type = etype;
7936                                 tklass = mono_class_from_mono_type (&simple_type);
7937                         }
7938                         goto handle_enum;
7939                 } else if (subt == 0x55) {
7940                         char *n;
7941                         MonoType *t;
7942                         slen = mono_metadata_decode_value (p, &p);
7943                         n = g_memdup (p, slen + 1);
7944                         n [slen] = 0;
7945                         t = mono_reflection_type_from_name (n, image);
7946                         if (!t)
7947                                 g_error ("Cannot load type '%s'", n);
7948                         g_free (n);
7949                         p += slen;
7950                         subc = mono_class_from_mono_type (t);
7951                 } else if (subt >= MONO_TYPE_BOOLEAN && subt <= MONO_TYPE_R8) {
7952                         MonoType simple_type = {{0}};
7953                         simple_type.type = subt;
7954                         subc = mono_class_from_mono_type (&simple_type);
7955                 } else {
7956                         g_error ("Unknown type 0x%02x for object type encoding in custom attr", subt);
7957                 }
7958                 val = load_cattr_value (image, &subc->byval_arg, p, end);
7959                 obj = mono_object_new (mono_domain_get (), subc);
7960                 g_assert (!subc->has_references);
7961                 mono_gc_memmove ((char*)obj + sizeof (MonoObject), val, mono_class_value_size (subc, NULL));
7962                 g_free (val);
7963                 return obj;
7964         }
7965         case MONO_TYPE_SZARRAY: {
7966                 MonoArray *arr;
7967                 guint32 i, alen, basetype;
7968                 alen = read32 (p);
7969                 p += 4;
7970                 if (alen == 0xffffffff) {
7971                         *end = p;
7972                         return NULL;
7973                 }
7974                 arr = mono_array_new (mono_domain_get(), tklass, alen);
7975                 basetype = tklass->byval_arg.type;
7976                 if (basetype == MONO_TYPE_VALUETYPE && tklass->enumtype)
7977                         basetype = mono_class_enum_basetype (tklass)->type;
7978                 switch (basetype)
7979                 {
7980                         case MONO_TYPE_U1:
7981                         case MONO_TYPE_I1:
7982                         case MONO_TYPE_BOOLEAN:
7983                                 for (i = 0; i < alen; i++) {
7984                                         MonoBoolean val = *p++;
7985                                         mono_array_set (arr, MonoBoolean, i, val);
7986                                 }
7987                                 break;
7988                         case MONO_TYPE_CHAR:
7989                         case MONO_TYPE_U2:
7990                         case MONO_TYPE_I2:
7991                                 for (i = 0; i < alen; i++) {
7992                                         guint16 val = read16 (p);
7993                                         mono_array_set (arr, guint16, i, val);
7994                                         p += 2;
7995                                 }
7996                                 break;
7997                         case MONO_TYPE_R4:
7998                         case MONO_TYPE_U4:
7999                         case MONO_TYPE_I4:
8000                                 for (i = 0; i < alen; i++) {
8001                                         guint32 val = read32 (p);
8002                                         mono_array_set (arr, guint32, i, val);
8003                                         p += 4;
8004                                 }
8005                                 break;
8006                         case MONO_TYPE_R8:
8007                                 for (i = 0; i < alen; i++) {
8008                                         double val;
8009                                         readr8 (p, &val);
8010                                         mono_array_set (arr, double, i, val);
8011                                         p += 8;
8012                                 }
8013                                 break;
8014                         case MONO_TYPE_U8:
8015                         case MONO_TYPE_I8:
8016                                 for (i = 0; i < alen; i++) {
8017                                         guint64 val = read64 (p);
8018                                         mono_array_set (arr, guint64, i, val);
8019                                         p += 8;
8020                                 }
8021                                 break;
8022                         case MONO_TYPE_CLASS:
8023                         case MONO_TYPE_OBJECT:
8024                         case MONO_TYPE_STRING:
8025                                 for (i = 0; i < alen; i++) {
8026                                         MonoObject *item = load_cattr_value (image, &tklass->byval_arg, p, &p);
8027                                         mono_array_setref (arr, i, item);
8028                                 }
8029                                 break;
8030                         default:
8031                                 g_error ("Type 0x%02x not handled in custom attr array decoding", basetype);
8032                 }
8033                 *end=p;
8034                 return arr;
8035         }
8036         default:
8037                 g_error ("Type 0x%02x not handled in custom attr value decoding", type);
8038         }
8039         return NULL;
8040 }
8041
8042 static MonoObject*
8043 create_cattr_typed_arg (MonoType *t, MonoObject *val)
8044 {
8045         static MonoClass *klass;
8046         static MonoMethod *ctor;
8047         MonoObject *retval;
8048         void *params [2], *unboxed;
8049
8050         if (!klass)
8051                 klass = mono_class_from_name (mono_defaults.corlib, "System.Reflection", "CustomAttributeTypedArgument");
8052         if (!ctor)
8053                 ctor = mono_class_get_method_from_name (klass, ".ctor", 2);
8054         
8055         params [0] = mono_type_get_object (mono_domain_get (), t);
8056         params [1] = val;
8057         retval = mono_object_new (mono_domain_get (), klass);
8058         unboxed = mono_object_unbox (retval);
8059         mono_runtime_invoke (ctor, unboxed, params, NULL);
8060
8061         return retval;
8062 }
8063
8064 static MonoObject*
8065 create_cattr_named_arg (void *minfo, MonoObject *typedarg)
8066 {
8067         static MonoClass *klass;
8068         static MonoMethod *ctor;
8069         MonoObject *retval;
8070         void *unboxed, *params [2];
8071
8072         if (!klass)
8073                 klass = mono_class_from_name (mono_defaults.corlib, "System.Reflection", "CustomAttributeNamedArgument");
8074         if (!ctor)
8075                 ctor = mono_class_get_method_from_name (klass, ".ctor", 2);
8076
8077         params [0] = minfo;
8078         params [1] = typedarg;
8079         retval = mono_object_new (mono_domain_get (), klass);
8080         unboxed = mono_object_unbox (retval);
8081         mono_runtime_invoke (ctor, unboxed, params, NULL);
8082
8083         return retval;
8084 }
8085
8086 static gboolean
8087 type_is_reference (MonoType *type)
8088 {
8089         switch (type->type) {
8090         case MONO_TYPE_BOOLEAN:
8091         case MONO_TYPE_CHAR:
8092         case MONO_TYPE_U:
8093         case MONO_TYPE_I:
8094         case MONO_TYPE_U1:
8095         case MONO_TYPE_I1:
8096         case MONO_TYPE_U2:
8097         case MONO_TYPE_I2:
8098         case MONO_TYPE_U4:
8099         case MONO_TYPE_I4:
8100         case MONO_TYPE_U8:
8101         case MONO_TYPE_I8:
8102         case MONO_TYPE_R8:
8103         case MONO_TYPE_R4:
8104         case MONO_TYPE_VALUETYPE:
8105                 return FALSE;
8106         default:
8107                 return TRUE;
8108         }
8109 }
8110
8111 static void
8112 free_param_data (MonoMethodSignature *sig, void **params) {
8113         int i;
8114         for (i = 0; i < sig->param_count; ++i) {
8115                 if (!type_is_reference (sig->params [i]))
8116                         g_free (params [i]);
8117         }
8118 }
8119
8120 /*
8121  * Find the field index in the metadata FieldDef table.
8122  */
8123 static guint32
8124 find_field_index (MonoClass *klass, MonoClassField *field) {
8125         int i;
8126
8127         for (i = 0; i < klass->field.count; ++i) {
8128                 if (field == &klass->fields [i])
8129                         return klass->field.first + 1 + i;
8130         }
8131         return 0;
8132 }
8133
8134 /*
8135  * Find the property index in the metadata Property table.
8136  */
8137 static guint32
8138 find_property_index (MonoClass *klass, MonoProperty *property) {
8139         int i;
8140
8141         for (i = 0; i < klass->ext->property.count; ++i) {
8142                 if (property == &klass->ext->properties [i])
8143                         return klass->ext->property.first + 1 + i;
8144         }
8145         return 0;
8146 }
8147
8148 /*
8149  * Find the event index in the metadata Event table.
8150  */
8151 static guint32
8152 find_event_index (MonoClass *klass, MonoEvent *event) {
8153         int i;
8154
8155         for (i = 0; i < klass->ext->event.count; ++i) {
8156                 if (event == &klass->ext->events [i])
8157                         return klass->ext->event.first + 1 + i;
8158         }
8159         return 0;
8160 }
8161
8162 static MonoObject*
8163 create_custom_attr (MonoImage *image, MonoMethod *method, const guchar *data, guint32 len, MonoError *error)
8164 {
8165         const char *p = (const char*)data;
8166         const char *named;
8167         guint32 i, j, num_named;
8168         MonoObject *attr;
8169         void *params_buf [32];
8170         void **params;
8171         MonoMethodSignature *sig;
8172
8173         mono_error_init (error);
8174
8175         mono_class_init (method->klass);
8176
8177         if (!mono_verifier_verify_cattr_content (image, method, data, len, NULL)) {
8178                 mono_error_set_generic_error (error, "System.Reflection", "CustomAttributeFormatException", "Binary format of the specified custom attribute was invalid.");
8179                 return NULL;
8180         }
8181
8182         if (len == 0) {
8183                 attr = mono_object_new (mono_domain_get (), method->klass);
8184                 mono_runtime_invoke (method, attr, NULL, NULL);
8185                 return attr;
8186         }
8187
8188         if (len < 2 || read16 (p) != 0x0001) /* Prolog */
8189                 return NULL;
8190
8191         /*g_print ("got attr %s\n", method->klass->name);*/
8192
8193         sig = mono_method_signature (method);
8194         if (sig->param_count < 32)
8195                 params = params_buf;
8196         else
8197                 /* Allocate using GC so it gets GC tracking */
8198                 params = mono_gc_alloc_fixed (sig->param_count * sizeof (void*), NULL);
8199
8200         /* skip prolog */
8201         p += 2;
8202         for (i = 0; i < mono_method_signature (method)->param_count; ++i) {
8203                 params [i] = load_cattr_value (image, mono_method_signature (method)->params [i], p, &p);
8204         }
8205
8206         named = p;
8207         attr = mono_object_new (mono_domain_get (), method->klass);
8208         mono_runtime_invoke (method, attr, params, NULL);
8209         free_param_data (method->signature, params);
8210         num_named = read16 (named);
8211         named += 2;
8212         for (j = 0; j < num_named; j++) {
8213                 gint name_len;
8214                 char *name, named_type, data_type;
8215                 named_type = *named++;
8216                 data_type = *named++; /* type of data */
8217                 if (data_type == MONO_TYPE_SZARRAY)
8218                         data_type = *named++;
8219                 if (data_type == MONO_TYPE_ENUM) {
8220                         gint type_len;
8221                         char *type_name;
8222                         type_len = mono_metadata_decode_blob_size (named, &named);
8223                         type_name = g_malloc (type_len + 1);
8224                         memcpy (type_name, named, type_len);
8225                         type_name [type_len] = 0;
8226                         named += type_len;
8227                         /* FIXME: lookup the type and check type consistency */
8228                         g_free (type_name);
8229                 }
8230                 name_len = mono_metadata_decode_blob_size (named, &named);
8231                 name = g_malloc (name_len + 1);
8232                 memcpy (name, named, name_len);
8233                 name [name_len] = 0;
8234                 named += name_len;
8235                 if (named_type == 0x53) {
8236                         MonoClassField *field = mono_class_get_field_from_name (mono_object_class (attr), name);
8237                         void *val = load_cattr_value (image, field->type, named, &named);
8238                         mono_field_set_value (attr, field, val);
8239                         if (!type_is_reference (field->type))
8240                                 g_free (val);
8241                 } else if (named_type == 0x54) {
8242                         MonoProperty *prop;
8243                         void *pparams [1];
8244                         MonoType *prop_type;
8245
8246                         prop = mono_class_get_property_from_name (mono_object_class (attr), name);
8247                         /* can we have more that 1 arg in a custom attr named property? */
8248                         prop_type = prop->get? mono_method_signature (prop->get)->ret :
8249                              mono_method_signature (prop->set)->params [mono_method_signature (prop->set)->param_count - 1];
8250                         pparams [0] = load_cattr_value (image, prop_type, named, &named);
8251                         mono_property_set_value (prop, attr, pparams, NULL);
8252                         if (!type_is_reference (prop_type))
8253                                 g_free (pparams [0]);
8254                 }
8255                 g_free (name);
8256         }
8257
8258         if (params != params_buf)
8259                 mono_gc_free_fixed (params);
8260
8261         return attr;
8262 }
8263         
8264 /*
8265  * mono_reflection_create_custom_attr_data_args:
8266  *
8267  *   Create an array of typed and named arguments from the cattr blob given by DATA.
8268  * TYPED_ARGS and NAMED_ARGS will contain the objects representing the arguments,
8269  * NAMED_ARG_INFO will contain information about the named arguments.
8270  */
8271 void
8272 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)
8273 {
8274         MonoArray *typedargs, *namedargs;
8275         MonoClass *attrklass;
8276         MonoDomain *domain;
8277         const char *p = (const char*)data;
8278         const char *named;
8279         guint32 i, j, num_named;
8280         CattrNamedArg *arginfo = NULL;
8281
8282         *typed_args = NULL;
8283         *named_args = NULL;
8284         *named_arg_info = NULL;
8285
8286         mono_error_init (error);
8287
8288         if (!mono_verifier_verify_cattr_content (image, method, data, len, NULL)) {
8289                 mono_error_set_generic_error (error, "System.Reflection", "CustomAttributeFormatException", "Binary format of the specified custom attribute was invalid.");
8290                 return;
8291         }
8292
8293         mono_class_init (method->klass);
8294         
8295         domain = mono_domain_get ();
8296
8297         if (len < 2 || read16 (p) != 0x0001) /* Prolog */
8298                 return;
8299
8300         typedargs = mono_array_new (domain, mono_get_object_class (), mono_method_signature (method)->param_count);
8301         
8302         /* skip prolog */
8303         p += 2;
8304         for (i = 0; i < mono_method_signature (method)->param_count; ++i) {
8305                 MonoObject *obj;
8306                 void *val;
8307
8308                 val = load_cattr_value (image, mono_method_signature (method)->params [i], p, &p);
8309                 obj = type_is_reference (mono_method_signature (method)->params [i]) ? 
8310                         val : mono_value_box (domain, mono_class_from_mono_type (mono_method_signature (method)->params [i]), val);
8311                 mono_array_setref (typedargs, i, obj);
8312
8313                 if (!type_is_reference (mono_method_signature (method)->params [i]))
8314                         g_free (val);
8315         }
8316
8317         named = p;
8318         num_named = read16 (named);
8319         namedargs = mono_array_new (domain, mono_get_object_class (), num_named);
8320         named += 2;
8321         attrklass = method->klass;
8322
8323         arginfo = g_new0 (CattrNamedArg, num_named);
8324         *named_arg_info = arginfo;
8325
8326         for (j = 0; j < num_named; j++) {
8327                 gint name_len;
8328                 char *name, named_type, data_type;
8329                 named_type = *named++;
8330                 data_type = *named++; /* type of data */
8331                 if (data_type == MONO_TYPE_SZARRAY)
8332                         data_type = *named++;
8333                 if (data_type == MONO_TYPE_ENUM) {
8334                         gint type_len;
8335                         char *type_name;
8336                         type_len = mono_metadata_decode_blob_size (named, &named);
8337                         if (ADDP_IS_GREATER_OR_OVF ((const guchar*)named, type_len, data + len))
8338                                 goto fail;
8339
8340                         type_name = g_malloc (type_len + 1);
8341                         memcpy (type_name, named, type_len);
8342                         type_name [type_len] = 0;
8343                         named += type_len;
8344                         /* FIXME: lookup the type and check type consistency */
8345                         g_free (type_name);
8346                 }
8347                 name_len = mono_metadata_decode_blob_size (named, &named);
8348                 if (ADDP_IS_GREATER_OR_OVF ((const guchar*)named, name_len, data + len))
8349                         goto fail;
8350                 name = g_malloc (name_len + 1);
8351                 memcpy (name, named, name_len);
8352                 name [name_len] = 0;
8353                 named += name_len;
8354                 if (named_type == 0x53) {
8355                         MonoObject *obj;
8356                         MonoClassField *field = mono_class_get_field_from_name (attrklass, name);
8357                         void *val;
8358
8359                         arginfo [j].type = field->type;
8360                         arginfo [j].field = field;
8361
8362                         val = load_cattr_value (image, field->type, named, &named);
8363                         obj = type_is_reference (field->type) ? val : mono_value_box (domain, mono_class_from_mono_type (field->type), val);
8364                         mono_array_setref (namedargs, j, obj);
8365                         if (!type_is_reference (field->type))
8366                                 g_free (val);
8367                 } else if (named_type == 0x54) {
8368                         MonoObject *obj;
8369                         MonoType *prop_type;
8370                         MonoProperty *prop = mono_class_get_property_from_name (attrklass, name);
8371                         void *val;
8372
8373                         prop_type = prop->get? mono_method_signature (prop->get)->ret :
8374                              mono_method_signature (prop->set)->params [mono_method_signature (prop->set)->param_count - 1];
8375
8376                         arginfo [j].type = prop_type;
8377                         arginfo [j].prop = prop;
8378
8379                         val = load_cattr_value (image, prop_type, named, &named);
8380                         obj = type_is_reference (prop_type) ? val : mono_value_box (domain, mono_class_from_mono_type (prop_type), val);
8381                         mono_array_setref (namedargs, j, obj);
8382                         if (!type_is_reference (prop_type))
8383                                 g_free (val);
8384                 }
8385                 g_free (name);
8386         }
8387
8388         *typed_args = typedargs;
8389         *named_args = namedargs;
8390         return;
8391 fail:
8392         mono_error_set_generic_error (error, "System.Reflection", "CustomAttributeFormatException", "Binary format of the specified custom attribute was invalid.");
8393         g_free (arginfo);
8394         *named_arg_info = NULL;
8395 }
8396
8397 void
8398 mono_reflection_resolve_custom_attribute_data (MonoReflectionMethod *ref_method, MonoReflectionAssembly *assembly, gpointer data, guint32 len, MonoArray **ctor_args, MonoArray **named_args)
8399 {
8400         MonoDomain *domain;
8401         MonoArray *typedargs, *namedargs;
8402         MonoImage *image;
8403         MonoMethod *method;
8404         CattrNamedArg *arginfo = NULL;
8405         MonoError error;
8406         int i;
8407
8408         *ctor_args = NULL;
8409         *named_args = NULL;
8410
8411         if (len == 0)
8412                 return;
8413
8414         image = assembly->assembly->image;
8415         method = ref_method->method;
8416         domain = mono_object_domain (ref_method);
8417
8418         if (!mono_class_init (method->klass))
8419                 mono_raise_exception (mono_class_get_exception_for_failure (method->klass));
8420
8421         mono_reflection_create_custom_attr_data_args (image, method, data, len, &typedargs, &namedargs, &arginfo, &error);
8422         if (!mono_error_ok (&error))
8423                 mono_error_raise_exception (&error);
8424         if (mono_loader_get_last_error ())
8425                 mono_raise_exception (mono_loader_error_prepare_exception (mono_loader_get_last_error ()));
8426
8427         if (!typedargs || !namedargs) {
8428                 g_free (arginfo);
8429                 return;
8430         }
8431
8432         for (i = 0; i < mono_method_signature (method)->param_count; ++i) {
8433                 MonoObject *obj = mono_array_get (typedargs, MonoObject*, i);
8434                 MonoObject *typedarg;
8435
8436                 typedarg = create_cattr_typed_arg (mono_method_signature (method)->params [i], obj);
8437                 mono_array_setref (typedargs, i, typedarg);
8438         }
8439
8440         for (i = 0; i < mono_array_length (namedargs); ++i) {
8441                 MonoObject *obj = mono_array_get (namedargs, MonoObject*, i);
8442                 MonoObject *typedarg, *namedarg, *minfo;
8443
8444                 if (arginfo [i].prop)
8445                         minfo = (MonoObject*)mono_property_get_object (domain, NULL, arginfo [i].prop);
8446                 else
8447                         minfo = (MonoObject*)mono_field_get_object (domain, NULL, arginfo [i].field);
8448
8449                 typedarg = create_cattr_typed_arg (arginfo [i].type, obj);
8450                 namedarg = create_cattr_named_arg (minfo, typedarg);
8451
8452                 mono_array_setref (namedargs, i, namedarg);
8453         }
8454
8455         *ctor_args = typedargs;
8456         *named_args = namedargs;
8457         g_free (arginfo);
8458 }
8459
8460 static MonoObject*
8461 create_custom_attr_data (MonoImage *image, MonoCustomAttrEntry *cattr)
8462 {
8463         static MonoMethod *ctor;
8464         MonoDomain *domain;
8465         MonoObject *attr;
8466         void *params [4];
8467
8468         g_assert (image->assembly);
8469
8470         if (!ctor)
8471                 ctor = mono_class_get_method_from_name (mono_defaults.customattribute_data_class, ".ctor", 4);
8472
8473         domain = mono_domain_get ();
8474         attr = mono_object_new (domain, mono_defaults.customattribute_data_class);
8475         params [0] = mono_method_get_object (domain, cattr->ctor, NULL);
8476         params [1] = mono_assembly_get_object (domain, image->assembly);
8477         params [2] = (gpointer)&cattr->data;
8478         params [3] = &cattr->data_size;
8479         mono_runtime_invoke (ctor, attr, params, NULL);
8480         return attr;
8481 }
8482
8483 static MonoArray*
8484 mono_custom_attrs_construct_by_type (MonoCustomAttrInfo *cinfo, MonoClass *attr_klass, MonoError *error)
8485 {
8486         MonoArray *result;
8487         MonoObject *attr;
8488         int i, n;
8489
8490         mono_error_init (error);
8491
8492         n = 0;
8493         for (i = 0; i < cinfo->num_attrs; ++i) {
8494                 if (!attr_klass || mono_class_is_assignable_from (attr_klass, cinfo->attrs [i].ctor->klass))
8495                         n ++;
8496         }
8497
8498         result = mono_array_new_cached (mono_domain_get (), mono_defaults.attribute_class, n);
8499         n = 0;
8500         for (i = 0; i < cinfo->num_attrs; ++i) {
8501                 if (!cinfo->attrs [i].ctor)
8502                         /* The cattr type is not finished yet */
8503                         /* We should include the type name but cinfo doesn't contain it */
8504                         mono_raise_exception (mono_get_exception_type_load (NULL, NULL));
8505                 if (!attr_klass || mono_class_is_assignable_from (attr_klass, cinfo->attrs [i].ctor->klass)) {
8506                         attr = create_custom_attr (cinfo->image, cinfo->attrs [i].ctor, cinfo->attrs [i].data, cinfo->attrs [i].data_size, error);
8507                         if (!mono_error_ok (error))
8508                                 return result;
8509                         mono_array_setref (result, n, attr);
8510                         n ++;
8511                 }
8512         }
8513         return result;
8514 }
8515
8516 MonoArray*
8517 mono_custom_attrs_construct (MonoCustomAttrInfo *cinfo)
8518 {
8519         MonoError error;
8520
8521         return mono_custom_attrs_construct_by_type (cinfo, NULL, &error);
8522 }
8523
8524 static MonoArray*
8525 mono_custom_attrs_data_construct (MonoCustomAttrInfo *cinfo)
8526 {
8527         MonoArray *result;
8528         MonoObject *attr;
8529         int i;
8530         
8531         result = mono_array_new (mono_domain_get (), mono_defaults.customattribute_data_class, cinfo->num_attrs);
8532         for (i = 0; i < cinfo->num_attrs; ++i) {
8533                 attr = create_custom_attr_data (cinfo->image, &cinfo->attrs [i]);
8534                 mono_array_setref (result, i, attr);
8535         }
8536         return result;
8537 }
8538
8539 /**
8540  * mono_custom_attrs_from_index:
8541  *
8542  * Returns: NULL if no attributes are found or if a loading error occurs.
8543  */
8544 MonoCustomAttrInfo*
8545 mono_custom_attrs_from_index (MonoImage *image, guint32 idx)
8546 {
8547         guint32 mtoken, i, len;
8548         guint32 cols [MONO_CUSTOM_ATTR_SIZE];
8549         MonoTableInfo *ca;
8550         MonoCustomAttrInfo *ainfo;
8551         GList *tmp, *list = NULL;
8552         const char *data;
8553
8554         ca = &image->tables [MONO_TABLE_CUSTOMATTRIBUTE];
8555
8556         i = mono_metadata_custom_attrs_from_index (image, idx);
8557         if (!i)
8558                 return NULL;
8559         i --;
8560         while (i < ca->rows) {
8561                 if (mono_metadata_decode_row_col (ca, i, MONO_CUSTOM_ATTR_PARENT) != idx)
8562                         break;
8563                 list = g_list_prepend (list, GUINT_TO_POINTER (i));
8564                 ++i;
8565         }
8566         len = g_list_length (list);
8567         if (!len)
8568                 return NULL;
8569         ainfo = g_malloc0 (MONO_SIZEOF_CUSTOM_ATTR_INFO + sizeof (MonoCustomAttrEntry) * len);
8570         ainfo->num_attrs = len;
8571         ainfo->image = image;
8572         for (i = 0, tmp = list; i < len; ++i, tmp = tmp->next) {
8573                 mono_metadata_decode_row (ca, GPOINTER_TO_UINT (tmp->data), cols, MONO_CUSTOM_ATTR_SIZE);
8574                 mtoken = cols [MONO_CUSTOM_ATTR_TYPE] >> MONO_CUSTOM_ATTR_TYPE_BITS;
8575                 switch (cols [MONO_CUSTOM_ATTR_TYPE] & MONO_CUSTOM_ATTR_TYPE_MASK) {
8576                 case MONO_CUSTOM_ATTR_TYPE_METHODDEF:
8577                         mtoken |= MONO_TOKEN_METHOD_DEF;
8578                         break;
8579                 case MONO_CUSTOM_ATTR_TYPE_MEMBERREF:
8580                         mtoken |= MONO_TOKEN_MEMBER_REF;
8581                         break;
8582                 default:
8583                         g_error ("Unknown table for custom attr type %08x", cols [MONO_CUSTOM_ATTR_TYPE]);
8584                         break;
8585                 }
8586                 ainfo->attrs [i].ctor = mono_get_method (image, mtoken, NULL);
8587                 if (!ainfo->attrs [i].ctor) {
8588                         g_warning ("Can't find custom attr constructor image: %s mtoken: 0x%08x", image->name, mtoken);
8589                         g_list_free (list);
8590                         g_free (ainfo);
8591                         return NULL;
8592                 }
8593
8594                 if (!mono_verifier_verify_cattr_blob (image, cols [MONO_CUSTOM_ATTR_VALUE], NULL)) {
8595                         /*FIXME raising an exception here doesn't make any sense*/
8596                         g_warning ("Invalid custom attribute blob on image %s for index %x", image->name, idx);
8597                         g_list_free (list);
8598                         g_free (ainfo);
8599                         return NULL;
8600                 }
8601                 data = mono_metadata_blob_heap (image, cols [MONO_CUSTOM_ATTR_VALUE]);
8602                 ainfo->attrs [i].data_size = mono_metadata_decode_value (data, &data);
8603                 ainfo->attrs [i].data = (guchar*)data;
8604         }
8605         g_list_free (list);
8606
8607         return ainfo;
8608 }
8609
8610 MonoCustomAttrInfo*
8611 mono_custom_attrs_from_method (MonoMethod *method)
8612 {
8613         guint32 idx;
8614
8615         /*
8616          * An instantiated method has the same cattrs as the generic method definition.
8617          *
8618          * LAMESPEC: The .NET SRE throws an exception for instantiations of generic method builders
8619          *           Note that this stanza is not necessary for non-SRE types, but it's a micro-optimization
8620          */
8621         if (method->is_inflated)
8622                 method = ((MonoMethodInflated *) method)->declaring;
8623         
8624         if (method->dynamic || method->klass->image->dynamic)
8625                 return lookup_custom_attr (method->klass->image, method);
8626
8627         if (!method->token)
8628                 /* Synthetic methods */
8629                 return NULL;
8630
8631         idx = mono_method_get_index (method);
8632         idx <<= MONO_CUSTOM_ATTR_BITS;
8633         idx |= MONO_CUSTOM_ATTR_METHODDEF;
8634         return mono_custom_attrs_from_index (method->klass->image, idx);
8635 }
8636
8637 MonoCustomAttrInfo*
8638 mono_custom_attrs_from_class (MonoClass *klass)
8639 {
8640         guint32 idx;
8641
8642         if (klass->generic_class)
8643                 klass = klass->generic_class->container_class;
8644
8645         if (klass->image->dynamic)
8646                 return lookup_custom_attr (klass->image, klass);
8647
8648         if (klass->byval_arg.type == MONO_TYPE_VAR || klass->byval_arg.type == MONO_TYPE_MVAR) {
8649                 idx = mono_metadata_token_index (klass->sizes.generic_param_token);
8650                 idx <<= MONO_CUSTOM_ATTR_BITS;
8651                 idx |= MONO_CUSTOM_ATTR_GENERICPAR;
8652         } else {
8653                 idx = mono_metadata_token_index (klass->type_token);
8654                 idx <<= MONO_CUSTOM_ATTR_BITS;
8655                 idx |= MONO_CUSTOM_ATTR_TYPEDEF;
8656         }
8657         return mono_custom_attrs_from_index (klass->image, idx);
8658 }
8659
8660 MonoCustomAttrInfo*
8661 mono_custom_attrs_from_assembly (MonoAssembly *assembly)
8662 {
8663         guint32 idx;
8664         
8665         if (assembly->image->dynamic)
8666                 return lookup_custom_attr (assembly->image, assembly);
8667         idx = 1; /* there is only one assembly */
8668         idx <<= MONO_CUSTOM_ATTR_BITS;
8669         idx |= MONO_CUSTOM_ATTR_ASSEMBLY;
8670         return mono_custom_attrs_from_index (assembly->image, idx);
8671 }
8672
8673 static MonoCustomAttrInfo*
8674 mono_custom_attrs_from_module (MonoImage *image)
8675 {
8676         guint32 idx;
8677         
8678         if (image->dynamic)
8679                 return lookup_custom_attr (image, image);
8680         idx = 1; /* there is only one module */
8681         idx <<= MONO_CUSTOM_ATTR_BITS;
8682         idx |= MONO_CUSTOM_ATTR_MODULE;
8683         return mono_custom_attrs_from_index (image, idx);
8684 }
8685
8686 MonoCustomAttrInfo*
8687 mono_custom_attrs_from_property (MonoClass *klass, MonoProperty *property)
8688 {
8689         guint32 idx;
8690         
8691         if (klass->image->dynamic) {
8692                 property = mono_metadata_get_corresponding_property_from_generic_type_definition (property);
8693                 return lookup_custom_attr (klass->image, property);
8694         }
8695         idx = find_property_index (klass, property);
8696         idx <<= MONO_CUSTOM_ATTR_BITS;
8697         idx |= MONO_CUSTOM_ATTR_PROPERTY;
8698         return mono_custom_attrs_from_index (klass->image, idx);
8699 }
8700
8701 MonoCustomAttrInfo*
8702 mono_custom_attrs_from_event (MonoClass *klass, MonoEvent *event)
8703 {
8704         guint32 idx;
8705         
8706         if (klass->image->dynamic) {
8707                 event = mono_metadata_get_corresponding_event_from_generic_type_definition (event);
8708                 return lookup_custom_attr (klass->image, event);
8709         }
8710         idx = find_event_index (klass, event);
8711         idx <<= MONO_CUSTOM_ATTR_BITS;
8712         idx |= MONO_CUSTOM_ATTR_EVENT;
8713         return mono_custom_attrs_from_index (klass->image, idx);
8714 }
8715
8716 MonoCustomAttrInfo*
8717 mono_custom_attrs_from_field (MonoClass *klass, MonoClassField *field)
8718 {
8719         guint32 idx;
8720         if (klass->image->dynamic) {
8721                 field = mono_metadata_get_corresponding_field_from_generic_type_definition (field);
8722                 return lookup_custom_attr (klass->image, field);
8723         }
8724         idx = find_field_index (klass, field);
8725         idx <<= MONO_CUSTOM_ATTR_BITS;
8726         idx |= MONO_CUSTOM_ATTR_FIELDDEF;
8727         return mono_custom_attrs_from_index (klass->image, idx);
8728 }
8729
8730 /**
8731  * mono_custom_attrs_from_param:
8732  * @method: handle to the method that we want to retrieve custom parameter information from
8733  * @param: parameter number, where zero represent the return value, and one is the first parameter in the method
8734  *
8735  * The result must be released with mono_custom_attrs_free().
8736  *
8737  * Returns: the custom attribute object for the specified parameter, or NULL if there are none.
8738  */
8739 MonoCustomAttrInfo*
8740 mono_custom_attrs_from_param (MonoMethod *method, guint32 param)
8741 {
8742         MonoTableInfo *ca;
8743         guint32 i, idx, method_index;
8744         guint32 param_list, param_last, param_pos, found;
8745         MonoImage *image;
8746         MonoReflectionMethodAux *aux;
8747
8748         /*
8749          * An instantiated method has the same cattrs as the generic method definition.
8750          *
8751          * LAMESPEC: The .NET SRE throws an exception for instantiations of generic method builders
8752          *           Note that this stanza is not necessary for non-SRE types, but it's a micro-optimization
8753          */
8754         if (method->is_inflated)
8755                 method = ((MonoMethodInflated *) method)->declaring;
8756
8757         if (method->klass->image->dynamic) {
8758                 MonoCustomAttrInfo *res, *ainfo;
8759                 int size;
8760
8761                 aux = g_hash_table_lookup (((MonoDynamicImage*)method->klass->image)->method_aux_hash, method);
8762                 if (!aux || !aux->param_cattr)
8763                         return NULL;
8764
8765                 /* Need to copy since it will be freed later */
8766                 ainfo = aux->param_cattr [param];
8767                 if (!ainfo)
8768                         return NULL;
8769                 size = MONO_SIZEOF_CUSTOM_ATTR_INFO + sizeof (MonoCustomAttrEntry) * ainfo->num_attrs;
8770                 res = g_malloc0 (size);
8771                 memcpy (res, ainfo, size);
8772                 return res;
8773         }
8774
8775         image = method->klass->image;
8776         method_index = mono_method_get_index (method);
8777         if (!method_index)
8778                 return NULL;
8779         ca = &image->tables [MONO_TABLE_METHOD];
8780
8781         param_list = mono_metadata_decode_row_col (ca, method_index - 1, MONO_METHOD_PARAMLIST);
8782         if (method_index == ca->rows) {
8783                 ca = &image->tables [MONO_TABLE_PARAM];
8784                 param_last = ca->rows + 1;
8785         } else {
8786                 param_last = mono_metadata_decode_row_col (ca, method_index, MONO_METHOD_PARAMLIST);
8787                 ca = &image->tables [MONO_TABLE_PARAM];
8788         }
8789         found = FALSE;
8790         for (i = param_list; i < param_last; ++i) {
8791                 param_pos = mono_metadata_decode_row_col (ca, i - 1, MONO_PARAM_SEQUENCE);
8792                 if (param_pos == param) {
8793                         found = TRUE;
8794                         break;
8795                 }
8796         }
8797         if (!found)
8798                 return NULL;
8799         idx = i;
8800         idx <<= MONO_CUSTOM_ATTR_BITS;
8801         idx |= MONO_CUSTOM_ATTR_PARAMDEF;
8802         return mono_custom_attrs_from_index (image, idx);
8803 }
8804
8805 gboolean
8806 mono_custom_attrs_has_attr (MonoCustomAttrInfo *ainfo, MonoClass *attr_klass)
8807 {
8808         int i;
8809         MonoClass *klass;
8810         for (i = 0; i < ainfo->num_attrs; ++i) {
8811                 klass = ainfo->attrs [i].ctor->klass;
8812                 if (mono_class_has_parent (klass, attr_klass) || (MONO_CLASS_IS_INTERFACE (attr_klass) && mono_class_is_assignable_from (attr_klass, klass)))
8813                         return TRUE;
8814         }
8815         return FALSE;
8816 }
8817
8818 MonoObject*
8819 mono_custom_attrs_get_attr (MonoCustomAttrInfo *ainfo, MonoClass *attr_klass)
8820 {
8821         int i, attr_index;
8822         MonoClass *klass;
8823         MonoArray *attrs;
8824
8825         attr_index = -1;
8826         for (i = 0; i < ainfo->num_attrs; ++i) {
8827                 klass = ainfo->attrs [i].ctor->klass;
8828                 if (mono_class_has_parent (klass, attr_klass)) {
8829                         attr_index = i;
8830                         break;
8831                 }
8832         }
8833         if (attr_index == -1)
8834                 return NULL;
8835
8836         attrs = mono_custom_attrs_construct (ainfo);
8837         if (attrs)
8838                 return mono_array_get (attrs, MonoObject*, attr_index);
8839         else
8840                 return NULL;
8841 }
8842
8843 /*
8844  * mono_reflection_get_custom_attrs_info:
8845  * @obj: a reflection object handle
8846  *
8847  * Return the custom attribute info for attributes defined for the
8848  * reflection handle @obj. The objects.
8849  *
8850  * FIXME this function leaks like a sieve for SRE objects.
8851  */
8852 MonoCustomAttrInfo*
8853 mono_reflection_get_custom_attrs_info (MonoObject *obj)
8854 {
8855         MonoClass *klass;
8856         MonoCustomAttrInfo *cinfo = NULL;
8857         
8858         klass = obj->vtable->klass;
8859         if (klass == mono_defaults.monotype_class) {
8860                 MonoType *type = mono_reflection_type_get_handle ((MonoReflectionType *)obj);
8861                 klass = mono_class_from_mono_type (type);
8862                 /*We cannot mono_class_init the class from which we'll load the custom attributes since this must work with broken types.*/
8863                 cinfo = mono_custom_attrs_from_class (klass);
8864         } else if (strcmp ("Assembly", klass->name) == 0 || strcmp ("MonoAssembly", klass->name) == 0) {
8865                 MonoReflectionAssembly *rassembly = (MonoReflectionAssembly*)obj;
8866                 cinfo = mono_custom_attrs_from_assembly (rassembly->assembly);
8867         } else if (strcmp ("Module", klass->name) == 0 || strcmp ("MonoModule", klass->name) == 0) {
8868                 MonoReflectionModule *module = (MonoReflectionModule*)obj;
8869                 cinfo = mono_custom_attrs_from_module (module->image);
8870         } else if (strcmp ("MonoProperty", klass->name) == 0) {
8871                 MonoReflectionProperty *rprop = (MonoReflectionProperty*)obj;
8872                 cinfo = mono_custom_attrs_from_property (rprop->property->parent, rprop->property);
8873         } else if (strcmp ("MonoEvent", klass->name) == 0) {
8874                 MonoReflectionMonoEvent *revent = (MonoReflectionMonoEvent*)obj;
8875                 cinfo = mono_custom_attrs_from_event (revent->event->parent, revent->event);
8876         } else if (strcmp ("MonoField", klass->name) == 0) {
8877                 MonoReflectionField *rfield = (MonoReflectionField*)obj;
8878                 cinfo = mono_custom_attrs_from_field (rfield->field->parent, rfield->field);
8879         } else if ((strcmp ("MonoMethod", klass->name) == 0) || (strcmp ("MonoCMethod", klass->name) == 0)) {
8880                 MonoReflectionMethod *rmethod = (MonoReflectionMethod*)obj;
8881                 cinfo = mono_custom_attrs_from_method (rmethod->method);
8882         } else if ((strcmp ("MonoGenericMethod", klass->name) == 0) || (strcmp ("MonoGenericCMethod", klass->name) == 0)) {
8883                 MonoReflectionMethod *rmethod = (MonoReflectionMethod*)obj;
8884                 cinfo = mono_custom_attrs_from_method (rmethod->method);
8885         } else if (strcmp ("ParameterInfo", klass->name) == 0 || strcmp ("MonoParameterInfo", klass->name) == 0) {
8886                 MonoReflectionParameter *param = (MonoReflectionParameter*)obj;
8887                 MonoClass *member_class = mono_object_class (param->MemberImpl);
8888                 if (mono_class_is_reflection_method_or_constructor (member_class)) {
8889                         MonoReflectionMethod *rmethod = (MonoReflectionMethod*)param->MemberImpl;
8890                         cinfo = mono_custom_attrs_from_param (rmethod->method, param->PositionImpl + 1);
8891                 } else if (is_sr_mono_property (member_class)) {
8892                         MonoReflectionProperty *prop = (MonoReflectionProperty *)param->MemberImpl;
8893                         MonoMethod *method;
8894                         if (!(method = prop->property->get))
8895                                 method = prop->property->set;
8896                         g_assert (method);
8897
8898                         cinfo = mono_custom_attrs_from_param (method, param->PositionImpl + 1);
8899                 } 
8900 #ifndef DISABLE_REFLECTION_EMIT
8901                 else if (is_sre_method_on_tb_inst (member_class)) {/*XXX This is a workaround for Compiler Context*/
8902                         MonoMethod *method = mono_reflection_method_on_tb_inst_get_handle ((MonoReflectionMethodOnTypeBuilderInst*)param->MemberImpl);
8903                         cinfo = mono_custom_attrs_from_param (method, param->PositionImpl + 1);
8904                 } else if (is_sre_ctor_on_tb_inst (member_class)) { /*XX This is a workaround for Compiler Context*/
8905                         MonoReflectionCtorOnTypeBuilderInst *c = (MonoReflectionCtorOnTypeBuilderInst*)param->MemberImpl;
8906                         MonoMethod *method = NULL;
8907                         if (is_sre_ctor_builder (mono_object_class (c->cb)))
8908                                 method = ((MonoReflectionCtorBuilder *)c->cb)->mhandle;
8909                         else if (is_sr_mono_cmethod (mono_object_class (c->cb)))
8910                                 method = ((MonoReflectionMethod *)c->cb)->method;
8911                         else
8912                                 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));
8913
8914                         cinfo = mono_custom_attrs_from_param (method, param->PositionImpl + 1);
8915                 } 
8916 #endif
8917                 else {
8918                         char *type_name = mono_type_get_full_name (member_class);
8919                         char *msg = g_strdup_printf ("Custom attributes on a ParamInfo with member %s are not supported", type_name);
8920                         MonoException *ex = mono_get_exception_not_supported  (msg);
8921                         g_free (type_name);
8922                         g_free (msg);
8923                         mono_raise_exception (ex);
8924                 }
8925         } else if (strcmp ("AssemblyBuilder", klass->name) == 0) {
8926                 MonoReflectionAssemblyBuilder *assemblyb = (MonoReflectionAssemblyBuilder*)obj;
8927                 cinfo = mono_custom_attrs_from_builders (NULL, assemblyb->assembly.assembly->image, assemblyb->cattrs);
8928         } else if (strcmp ("TypeBuilder", klass->name) == 0) {
8929                 MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder*)obj;
8930                 cinfo = mono_custom_attrs_from_builders (NULL, &tb->module->dynamic_image->image, tb->cattrs);
8931         } else if (strcmp ("ModuleBuilder", klass->name) == 0) {
8932                 MonoReflectionModuleBuilder *mb = (MonoReflectionModuleBuilder*)obj;
8933                 cinfo = mono_custom_attrs_from_builders (NULL, &mb->dynamic_image->image, mb->cattrs);
8934         } else if (strcmp ("ConstructorBuilder", klass->name) == 0) {
8935                 MonoReflectionCtorBuilder *cb = (MonoReflectionCtorBuilder*)obj;
8936                 cinfo = mono_custom_attrs_from_builders (NULL, cb->mhandle->klass->image, cb->cattrs);
8937         } else if (strcmp ("MethodBuilder", klass->name) == 0) {
8938                 MonoReflectionMethodBuilder *mb = (MonoReflectionMethodBuilder*)obj;
8939                 cinfo = mono_custom_attrs_from_builders (NULL, mb->mhandle->klass->image, mb->cattrs);
8940         } else if (strcmp ("FieldBuilder", klass->name) == 0) {
8941                 MonoReflectionFieldBuilder *fb = (MonoReflectionFieldBuilder*)obj;
8942                 cinfo = mono_custom_attrs_from_builders (NULL, &((MonoReflectionTypeBuilder*)fb->typeb)->module->dynamic_image->image, fb->cattrs);
8943         } else if (strcmp ("MonoGenericClass", klass->name) == 0) {
8944                 MonoReflectionGenericClass *gclass = (MonoReflectionGenericClass*)obj;
8945                 cinfo = mono_reflection_get_custom_attrs_info ((MonoObject*)gclass->generic_type);
8946         } else { /* handle other types here... */
8947                 g_error ("get custom attrs not yet supported for %s", klass->name);
8948         }
8949
8950         return cinfo;
8951 }
8952
8953 /*
8954  * mono_reflection_get_custom_attrs_by_type:
8955  * @obj: a reflection object handle
8956  *
8957  * Return an array with all the custom attributes defined of the
8958  * reflection handle @obj. If @attr_klass is non-NULL, only custom attributes 
8959  * of that type are returned. The objects are fully build. Return NULL if a loading error
8960  * occurs.
8961  */
8962 MonoArray*
8963 mono_reflection_get_custom_attrs_by_type (MonoObject *obj, MonoClass *attr_klass, MonoError *error)
8964 {
8965         MonoArray *result;
8966         MonoCustomAttrInfo *cinfo;
8967
8968         mono_error_init (error);
8969
8970         cinfo = mono_reflection_get_custom_attrs_info (obj);
8971         if (cinfo) {
8972                 result = mono_custom_attrs_construct_by_type (cinfo, attr_klass, error);
8973                 if (!cinfo->cached)
8974                         mono_custom_attrs_free (cinfo);
8975         } else {
8976                 if (mono_loader_get_last_error ())
8977                         return NULL;
8978                 result = mono_array_new_cached (mono_domain_get (), mono_defaults.attribute_class, 0);
8979         }
8980
8981         return result;
8982 }
8983
8984 /*
8985  * mono_reflection_get_custom_attrs:
8986  * @obj: a reflection object handle
8987  *
8988  * Return an array with all the custom attributes defined of the
8989  * reflection handle @obj. The objects are fully build. Return NULL if a loading error
8990  * occurs.
8991  */
8992 MonoArray*
8993 mono_reflection_get_custom_attrs (MonoObject *obj)
8994 {
8995         MonoError error;
8996
8997         return mono_reflection_get_custom_attrs_by_type (obj, NULL, &error);
8998 }
8999
9000 /*
9001  * mono_reflection_get_custom_attrs_data:
9002  * @obj: a reflection obj handle
9003  *
9004  * Returns an array of System.Reflection.CustomAttributeData,
9005  * which include information about attributes reflected on
9006  * types loaded using the Reflection Only methods
9007  */
9008 MonoArray*
9009 mono_reflection_get_custom_attrs_data (MonoObject *obj)
9010 {
9011         MonoArray *result;
9012         MonoCustomAttrInfo *cinfo;
9013
9014         cinfo = mono_reflection_get_custom_attrs_info (obj);
9015         if (cinfo) {
9016                 result = mono_custom_attrs_data_construct (cinfo);
9017                 if (!cinfo->cached)
9018                         mono_custom_attrs_free (cinfo);
9019         } else
9020                 result = mono_array_new (mono_domain_get (), mono_defaults.customattribute_data_class, 0);
9021
9022         return result;
9023 }
9024
9025 static MonoReflectionType*
9026 mono_reflection_type_get_underlying_system_type (MonoReflectionType* t)
9027 {
9028         static MonoMethod *method_get_underlying_system_type = NULL;
9029         MonoMethod *usertype_method;
9030
9031         if (!method_get_underlying_system_type)
9032                 method_get_underlying_system_type = mono_class_get_method_from_name (mono_defaults.systemtype_class, "get_UnderlyingSystemType", 0);
9033         usertype_method = mono_object_get_virtual_method ((MonoObject *) t, method_get_underlying_system_type);
9034         return (MonoReflectionType *) mono_runtime_invoke (usertype_method, t, NULL, NULL);
9035 }
9036
9037
9038 static gboolean
9039 is_corlib_type (MonoClass *class)
9040 {
9041         return class->image == mono_defaults.corlib;
9042 }
9043
9044 #define check_corlib_type_cached(_class, _namespace, _name) do { \
9045         static MonoClass *cached_class; \
9046         if (cached_class) \
9047                 return cached_class == _class; \
9048         if (is_corlib_type (_class) && !strcmp (_name, _class->name) && !strcmp (_namespace, _class->name_space)) { \
9049                 cached_class = _class; \
9050                 return TRUE; \
9051         } \
9052         return FALSE; \
9053 } while (0) \
9054
9055
9056 #ifndef DISABLE_REFLECTION_EMIT
9057 static gboolean
9058 is_sre_array (MonoClass *class)
9059 {
9060         check_corlib_type_cached (class, "System.Reflection.Emit", "ArrayType");
9061 }
9062
9063 static gboolean
9064 is_sre_byref (MonoClass *class)
9065 {
9066         check_corlib_type_cached (class, "System.Reflection.Emit", "ByRefType");
9067 }
9068
9069 static gboolean
9070 is_sre_pointer (MonoClass *class)
9071 {
9072         check_corlib_type_cached (class, "System.Reflection.Emit", "PointerType");
9073 }
9074
9075 static gboolean
9076 is_sre_generic_instance (MonoClass *class)
9077 {
9078         check_corlib_type_cached (class, "System.Reflection", "MonoGenericClass");
9079 }
9080
9081 static gboolean
9082 is_sre_type_builder (MonoClass *class)
9083 {
9084         check_corlib_type_cached (class, "System.Reflection.Emit", "TypeBuilder");
9085 }
9086
9087 static gboolean
9088 is_sre_method_builder (MonoClass *class)
9089 {
9090         check_corlib_type_cached (class, "System.Reflection.Emit", "MethodBuilder");
9091 }
9092
9093 static gboolean
9094 is_sre_ctor_builder (MonoClass *class)
9095 {
9096         check_corlib_type_cached (class, "System.Reflection.Emit", "ConstructorBuilder");
9097 }
9098
9099 static gboolean
9100 is_sre_field_builder (MonoClass *class)
9101 {
9102         check_corlib_type_cached (class, "System.Reflection.Emit", "FieldBuilder");
9103 }
9104
9105 static gboolean
9106 is_sre_method_on_tb_inst (MonoClass *class)
9107 {
9108         check_corlib_type_cached (class, "System.Reflection.Emit", "MethodOnTypeBuilderInst");
9109 }
9110
9111 static gboolean
9112 is_sre_ctor_on_tb_inst (MonoClass *class)
9113 {
9114         check_corlib_type_cached (class, "System.Reflection.Emit", "ConstructorOnTypeBuilderInst");
9115 }
9116
9117 MonoType*
9118 mono_reflection_type_get_handle (MonoReflectionType* ref)
9119 {
9120         MonoClass *class;
9121         if (!ref)
9122                 return NULL;
9123         if (ref->type)
9124                 return ref->type;
9125
9126         if (is_usertype (ref)) {
9127                 ref = mono_reflection_type_get_underlying_system_type (ref);
9128                 if (ref == NULL || is_usertype (ref))
9129                         return NULL;
9130                 if (ref->type)
9131                         return ref->type;
9132         }
9133
9134         class = mono_object_class (ref);
9135
9136         if (is_sre_array (class)) {
9137                 MonoType *res;
9138                 MonoReflectionArrayType *sre_array = (MonoReflectionArrayType*)ref;
9139                 MonoType *base = mono_reflection_type_get_handle (sre_array->element_type);
9140                 g_assert (base);
9141                 if (sre_array->rank == 0) //single dimentional array
9142                         res = &mono_array_class_get (mono_class_from_mono_type (base), 1)->byval_arg;
9143                 else
9144                         res = &mono_bounded_array_class_get (mono_class_from_mono_type (base), sre_array->rank, TRUE)->byval_arg;
9145                 sre_array->type.type = res;
9146                 return res;
9147         } else if (is_sre_byref (class)) {
9148                 MonoType *res;
9149                 MonoReflectionDerivedType *sre_byref = (MonoReflectionDerivedType*)ref;
9150                 MonoType *base = mono_reflection_type_get_handle (sre_byref->element_type);
9151                 g_assert (base);
9152                 res = &mono_class_from_mono_type (base)->this_arg;
9153                 sre_byref->type.type = res;
9154                 return res;
9155         } else if (is_sre_pointer (class)) {
9156                 MonoType *res;
9157                 MonoReflectionDerivedType *sre_pointer = (MonoReflectionDerivedType*)ref;
9158                 MonoType *base = mono_reflection_type_get_handle (sre_pointer->element_type);
9159                 g_assert (base);
9160                 res = &mono_ptr_class_get (base)->byval_arg;
9161                 sre_pointer->type.type = res;
9162                 return res;
9163         } else if (is_sre_generic_instance (class)) {
9164                 MonoType *res, **types;
9165                 MonoReflectionGenericClass *gclass = (MonoReflectionGenericClass*)ref;
9166                 int i, count;
9167
9168                 count = mono_array_length (gclass->type_arguments);
9169                 types = g_new0 (MonoType*, count);
9170                 for (i = 0; i < count; ++i) {
9171                         MonoReflectionType *t = mono_array_get (gclass->type_arguments, gpointer, i);
9172                         types [i] = mono_reflection_type_get_handle (t);
9173                         if (!types[i]) {
9174                                 g_free (types);
9175                                 return NULL;
9176                         }
9177                 }
9178
9179                 res = mono_reflection_bind_generic_parameters (gclass->generic_type, count, types);
9180                 g_free (types);
9181                 g_assert (res);
9182                 gclass->type.type = res;
9183                 return res;
9184         }
9185
9186         g_error ("Cannot handle corlib user type %s", mono_type_full_name (&mono_object_class(ref)->byval_arg));
9187         return NULL;
9188 }
9189
9190
9191
9192 void
9193 mono_reflection_create_unmanaged_type (MonoReflectionType *type)
9194 {
9195         mono_reflection_type_get_handle (type);
9196 }
9197
9198 void
9199 mono_reflection_register_with_runtime (MonoReflectionType *type)
9200 {
9201         MonoType *res = mono_reflection_type_get_handle (type);
9202         MonoDomain *domain = mono_object_domain ((MonoObject*)type);
9203         MonoClass *class;
9204
9205         if (!res)
9206                 mono_raise_exception (mono_get_exception_argument (NULL, "Invalid generic instantiation, one or more arguments are not proper user types"));
9207
9208         class = mono_class_from_mono_type (res);
9209
9210         mono_loader_lock (); /*same locking as mono_type_get_object*/
9211         mono_domain_lock (domain);
9212
9213         if (!class->image->dynamic) {
9214                 mono_class_setup_supertypes (class);
9215         } else {
9216                 if (!domain->type_hash)
9217                         domain->type_hash = mono_g_hash_table_new_type ((GHashFunc)mono_metadata_type_hash, 
9218                                         (GCompareFunc)mono_metadata_type_equal, MONO_HASH_VALUE_GC);
9219                 mono_g_hash_table_insert (domain->type_hash, res, type);
9220         }
9221         mono_domain_unlock (domain);
9222         mono_loader_unlock ();
9223 }
9224
9225 /**
9226  * LOCKING: Assumes the loader lock is held.
9227  */
9228 static MonoMethodSignature*
9229 parameters_to_signature (MonoImage *image, MonoArray *parameters) {
9230         MonoMethodSignature *sig;
9231         int count, i;
9232
9233         count = parameters? mono_array_length (parameters): 0;
9234
9235         sig = image_g_malloc0 (image, MONO_SIZEOF_METHOD_SIGNATURE + sizeof (MonoType*) * count);
9236         sig->param_count = count;
9237         sig->sentinelpos = -1; /* FIXME */
9238         for (i = 0; i < count; ++i)
9239                 sig->params [i] = mono_type_array_get_and_resolve (parameters, i);
9240         return sig;
9241 }
9242
9243 /**
9244  * LOCKING: Assumes the loader lock is held.
9245  */
9246 static MonoMethodSignature*
9247 ctor_builder_to_signature (MonoImage *image, MonoReflectionCtorBuilder *ctor) {
9248         MonoMethodSignature *sig;
9249
9250         sig = parameters_to_signature (image, ctor->parameters);
9251         sig->hasthis = ctor->attrs & METHOD_ATTRIBUTE_STATIC? 0: 1;
9252         sig->ret = &mono_defaults.void_class->byval_arg;
9253         return sig;
9254 }
9255
9256 /**
9257  * LOCKING: Assumes the loader lock is held.
9258  */
9259 static MonoMethodSignature*
9260 method_builder_to_signature (MonoImage *image, MonoReflectionMethodBuilder *method) {
9261         MonoMethodSignature *sig;
9262
9263         sig = parameters_to_signature (image, method->parameters);
9264         sig->hasthis = method->attrs & METHOD_ATTRIBUTE_STATIC? 0: 1;
9265         sig->ret = method->rtype? mono_reflection_type_get_handle ((MonoReflectionType*)method->rtype): &mono_defaults.void_class->byval_arg;
9266         sig->generic_param_count = method->generic_params ? mono_array_length (method->generic_params) : 0;
9267         return sig;
9268 }
9269
9270 static MonoMethodSignature*
9271 dynamic_method_to_signature (MonoReflectionDynamicMethod *method) {
9272         MonoMethodSignature *sig;
9273
9274         sig = parameters_to_signature (NULL, method->parameters);
9275         sig->hasthis = method->attrs & METHOD_ATTRIBUTE_STATIC? 0: 1;
9276         sig->ret = method->rtype? mono_reflection_type_get_handle (method->rtype): &mono_defaults.void_class->byval_arg;
9277         sig->generic_param_count = 0;
9278         return sig;
9279 }
9280
9281 static void
9282 get_prop_name_and_type (MonoObject *prop, char **name, MonoType **type)
9283 {
9284         MonoClass *klass = mono_object_class (prop);
9285         if (strcmp (klass->name, "PropertyBuilder") == 0) {
9286                 MonoReflectionPropertyBuilder *pb = (MonoReflectionPropertyBuilder *)prop;
9287                 *name = mono_string_to_utf8 (pb->name);
9288                 *type = mono_reflection_type_get_handle ((MonoReflectionType*)pb->type);
9289         } else {
9290                 MonoReflectionProperty *p = (MonoReflectionProperty *)prop;
9291                 *name = g_strdup (p->property->name);
9292                 if (p->property->get)
9293                         *type = mono_method_signature (p->property->get)->ret;
9294                 else
9295                         *type = mono_method_signature (p->property->set)->params [mono_method_signature (p->property->set)->param_count - 1];
9296         }
9297 }
9298
9299 static void
9300 get_field_name_and_type (MonoObject *field, char **name, MonoType **type)
9301 {
9302         MonoClass *klass = mono_object_class (field);
9303         if (strcmp (klass->name, "FieldBuilder") == 0) {
9304                 MonoReflectionFieldBuilder *fb = (MonoReflectionFieldBuilder *)field;
9305                 *name = mono_string_to_utf8 (fb->name);
9306                 *type = mono_reflection_type_get_handle ((MonoReflectionType*)fb->type);
9307         } else {
9308                 MonoReflectionField *f = (MonoReflectionField *)field;
9309                 *name = g_strdup (mono_field_get_name (f->field));
9310                 *type = f->field->type;
9311         }
9312 }
9313
9314 #else /* DISABLE_REFLECTION_EMIT */
9315
9316 void
9317 mono_reflection_register_with_runtime (MonoReflectionType *type)
9318 {
9319         /* This is empty */
9320 }
9321
9322 static gboolean
9323 is_sre_type_builder (MonoClass *class)
9324 {
9325         return FALSE;
9326 }
9327
9328 static gboolean
9329 is_sre_generic_instance (MonoClass *class)
9330 {
9331         return FALSE;
9332 }
9333
9334 static void
9335 init_type_builder_generics (MonoObject *type)
9336 {
9337 }
9338
9339 #endif /* !DISABLE_REFLECTION_EMIT */
9340
9341
9342 static gboolean
9343 is_sr_mono_field (MonoClass *class)
9344 {
9345         check_corlib_type_cached (class, "System.Reflection", "MonoField");
9346 }
9347
9348 static gboolean
9349 is_sr_mono_property (MonoClass *class)
9350 {
9351         check_corlib_type_cached (class, "System.Reflection", "MonoProperty");
9352 }
9353
9354 static gboolean
9355 is_sr_mono_method (MonoClass *class)
9356 {
9357         check_corlib_type_cached (class, "System.Reflection", "MonoMethod");
9358 }
9359
9360 static gboolean
9361 is_sr_mono_cmethod (MonoClass *class)
9362 {
9363         check_corlib_type_cached (class, "System.Reflection", "MonoCMethod");
9364 }
9365
9366 static gboolean
9367 is_sr_mono_generic_method (MonoClass *class)
9368 {
9369         check_corlib_type_cached (class, "System.Reflection", "MonoGenericMethod");
9370 }
9371
9372 static gboolean
9373 is_sr_mono_generic_cmethod (MonoClass *class)
9374 {
9375         check_corlib_type_cached (class, "System.Reflection", "MonoGenericCMethod");
9376 }
9377
9378 gboolean
9379 mono_class_is_reflection_method_or_constructor (MonoClass *class)
9380 {
9381         return is_sr_mono_method (class) || is_sr_mono_cmethod (class) || is_sr_mono_generic_method (class) || is_sr_mono_generic_cmethod (class);
9382 }
9383
9384 static gboolean
9385 is_usertype (MonoReflectionType *ref)
9386 {
9387         MonoClass *class = mono_object_class (ref);
9388         return class->image != mono_defaults.corlib || strcmp ("TypeDelegator", class->name) == 0;
9389 }
9390
9391 static MonoReflectionType*
9392 mono_reflection_type_resolve_user_types (MonoReflectionType *type)
9393 {
9394         if (!type || type->type)
9395                 return type;
9396
9397         if (is_usertype (type)) {
9398                 type = mono_reflection_type_get_underlying_system_type (type);
9399                 if (is_usertype (type))
9400                         mono_raise_exception (mono_get_exception_not_supported ("User defined subclasses of System.Type are not yet supported22"));
9401         }
9402
9403         return type;
9404 }
9405 /*
9406  * Encode a value in a custom attribute stream of bytes.
9407  * The value to encode is either supplied as an object in argument val
9408  * (valuetypes are boxed), or as a pointer to the data in the
9409  * argument argval.
9410  * @type represents the type of the value
9411  * @buffer is the start of the buffer
9412  * @p the current position in the buffer
9413  * @buflen contains the size of the buffer and is used to return the new buffer size
9414  * if this needs to be realloced.
9415  * @retbuffer and @retp return the start and the position of the buffer
9416  */
9417 static void
9418 encode_cattr_value (MonoAssembly *assembly, char *buffer, char *p, char **retbuffer, char **retp, guint32 *buflen, MonoType *type, MonoObject *arg, char *argval)
9419 {
9420         MonoTypeEnum simple_type;
9421         
9422         if ((p-buffer) + 10 >= *buflen) {
9423                 char *newbuf;
9424                 *buflen *= 2;
9425                 newbuf = g_realloc (buffer, *buflen);
9426                 p = newbuf + (p-buffer);
9427                 buffer = newbuf;
9428         }
9429         if (!argval)
9430                 argval = ((char*)arg + sizeof (MonoObject));
9431         simple_type = type->type;
9432 handle_enum:
9433         switch (simple_type) {
9434         case MONO_TYPE_BOOLEAN:
9435         case MONO_TYPE_U1:
9436         case MONO_TYPE_I1:
9437                 *p++ = *argval;
9438                 break;
9439         case MONO_TYPE_CHAR:
9440         case MONO_TYPE_U2:
9441         case MONO_TYPE_I2:
9442                 swap_with_size (p, argval, 2, 1);
9443                 p += 2;
9444                 break;
9445         case MONO_TYPE_U4:
9446         case MONO_TYPE_I4:
9447         case MONO_TYPE_R4:
9448                 swap_with_size (p, argval, 4, 1);
9449                 p += 4;
9450                 break;
9451         case MONO_TYPE_R8:
9452                 swap_with_size (p, argval, 8, 1);
9453                 p += 8;
9454                 break;
9455         case MONO_TYPE_U8:
9456         case MONO_TYPE_I8:
9457                 swap_with_size (p, argval, 8, 1);
9458                 p += 8;
9459                 break;
9460         case MONO_TYPE_VALUETYPE:
9461                 if (type->data.klass->enumtype) {
9462                         simple_type = mono_class_enum_basetype (type->data.klass)->type;
9463                         goto handle_enum;
9464                 } else {
9465                         g_warning ("generic valutype %s not handled in custom attr value decoding", type->data.klass->name);
9466                 }
9467                 break;
9468         case MONO_TYPE_STRING: {
9469                 char *str;
9470                 guint32 slen;
9471                 if (!arg) {
9472                         *p++ = 0xFF;
9473                         break;
9474                 }
9475                 str = mono_string_to_utf8 ((MonoString*)arg);
9476                 slen = strlen (str);
9477                 if ((p-buffer) + 10 + slen >= *buflen) {
9478                         char *newbuf;
9479                         *buflen *= 2;
9480                         *buflen += slen;
9481                         newbuf = g_realloc (buffer, *buflen);
9482                         p = newbuf + (p-buffer);
9483                         buffer = newbuf;
9484                 }
9485                 mono_metadata_encode_value (slen, p, &p);
9486                 memcpy (p, str, slen);
9487                 p += slen;
9488                 g_free (str);
9489                 break;
9490         }
9491         case MONO_TYPE_CLASS: {
9492                 char *str;
9493                 guint32 slen;
9494                 if (!arg) {
9495                         *p++ = 0xFF;
9496                         break;
9497                 }
9498 handle_type:
9499                 str = type_get_qualified_name (mono_reflection_type_get_handle ((MonoReflectionType*)arg), NULL);
9500                 slen = strlen (str);
9501                 if ((p-buffer) + 10 + slen >= *buflen) {
9502                         char *newbuf;
9503                         *buflen *= 2;
9504                         *buflen += slen;
9505                         newbuf = g_realloc (buffer, *buflen);
9506                         p = newbuf + (p-buffer);
9507                         buffer = newbuf;
9508                 }
9509                 mono_metadata_encode_value (slen, p, &p);
9510                 memcpy (p, str, slen);
9511                 p += slen;
9512                 g_free (str);
9513                 break;
9514         }
9515         case MONO_TYPE_SZARRAY: {
9516                 int len, i;
9517                 MonoClass *eclass, *arg_eclass;
9518
9519                 if (!arg) {
9520                         *p++ = 0xff; *p++ = 0xff; *p++ = 0xff; *p++ = 0xff;
9521                         break;
9522                 }
9523                 len = mono_array_length ((MonoArray*)arg);
9524                 *p++ = len & 0xff;
9525                 *p++ = (len >> 8) & 0xff;
9526                 *p++ = (len >> 16) & 0xff;
9527                 *p++ = (len >> 24) & 0xff;
9528                 *retp = p;
9529                 *retbuffer = buffer;
9530                 eclass = type->data.klass;
9531                 arg_eclass = mono_object_class (arg)->element_class;
9532
9533                 if (!eclass) {
9534                         /* Happens when we are called from the MONO_TYPE_OBJECT case below */
9535                         eclass = mono_defaults.object_class;
9536                 }
9537                 if (eclass == mono_defaults.object_class && arg_eclass->valuetype) {
9538                         char *elptr = mono_array_addr ((MonoArray*)arg, char, 0);
9539                         int elsize = mono_class_array_element_size (arg_eclass);
9540                         for (i = 0; i < len; ++i) {
9541                                 encode_cattr_value (assembly, buffer, p, &buffer, &p, buflen, &arg_eclass->byval_arg, NULL, elptr);
9542                                 elptr += elsize;
9543                         }
9544                 } else if (eclass->valuetype && arg_eclass->valuetype) {
9545                         char *elptr = mono_array_addr ((MonoArray*)arg, char, 0);
9546                         int elsize = mono_class_array_element_size (eclass);
9547                         for (i = 0; i < len; ++i) {
9548                                 encode_cattr_value (assembly, buffer, p, &buffer, &p, buflen, &eclass->byval_arg, NULL, elptr);
9549                                 elptr += elsize;
9550                         }
9551                 } else {
9552                         for (i = 0; i < len; ++i) {
9553                                 encode_cattr_value (assembly, buffer, p, &buffer, &p, buflen, &eclass->byval_arg, mono_array_get ((MonoArray*)arg, MonoObject*, i), NULL);
9554                         }
9555                 }
9556                 break;
9557         }
9558         case MONO_TYPE_OBJECT: {
9559                 MonoClass *klass;
9560                 char *str;
9561                 guint32 slen;
9562
9563                 /*
9564                  * The parameter type is 'object' but the type of the actual
9565                  * argument is not. So we have to add type information to the blob
9566                  * too. This is completely undocumented in the spec.
9567                  */
9568
9569                 if (arg == NULL) {
9570                         *p++ = MONO_TYPE_STRING;        // It's same hack as MS uses
9571                         *p++ = 0xFF;
9572                         break;
9573                 }
9574                 
9575                 klass = mono_object_class (arg);
9576
9577                 if (mono_object_isinst (arg, mono_defaults.systemtype_class)) {
9578                         *p++ = 0x50;
9579                         goto handle_type;
9580                 } else if (klass->enumtype) {
9581                         *p++ = 0x55;
9582                 } else if (klass == mono_defaults.string_class) {
9583                         simple_type = MONO_TYPE_STRING;
9584                         *p++ = 0x0E;
9585                         goto handle_enum;
9586                 } else if (klass->rank == 1) {
9587                         *p++ = 0x1D;
9588                         if (klass->element_class->byval_arg.type == MONO_TYPE_OBJECT)
9589                                 /* See Partition II, Appendix B3 */
9590                                 *p++ = 0x51;
9591                         else
9592                                 *p++ = klass->element_class->byval_arg.type;
9593                         encode_cattr_value (assembly, buffer, p, &buffer, &p, buflen, &klass->byval_arg, arg, NULL);
9594                         break;
9595                 } else if (klass->byval_arg.type >= MONO_TYPE_BOOLEAN && klass->byval_arg.type <= MONO_TYPE_R8) {
9596                         *p++ = simple_type = klass->byval_arg.type;
9597                         goto handle_enum;
9598                 } else {
9599                         g_error ("unhandled type in custom attr");
9600                 }
9601                 str = type_get_qualified_name (mono_class_get_type(klass), NULL);
9602                 slen = strlen (str);
9603                 if ((p-buffer) + 10 + slen >= *buflen) {
9604                         char *newbuf;
9605                         *buflen *= 2;
9606                         *buflen += slen;
9607                         newbuf = g_realloc (buffer, *buflen);
9608                         p = newbuf + (p-buffer);
9609                         buffer = newbuf;
9610                 }
9611                 mono_metadata_encode_value (slen, p, &p);
9612                 memcpy (p, str, slen);
9613                 p += slen;
9614                 g_free (str);
9615                 simple_type = mono_class_enum_basetype (klass)->type;
9616                 goto handle_enum;
9617         }
9618         default:
9619                 g_error ("type 0x%02x not yet supported in custom attr encoder", simple_type);
9620         }
9621         *retp = p;
9622         *retbuffer = buffer;
9623 }
9624
9625 static void
9626 encode_field_or_prop_type (MonoType *type, char *p, char **retp)
9627 {
9628         if (type->type == MONO_TYPE_VALUETYPE && type->data.klass->enumtype) {
9629                 char *str = type_get_qualified_name (type, NULL);
9630                 int slen = strlen (str);
9631
9632                 *p++ = 0x55;
9633                 /*
9634                  * This seems to be optional...
9635                  * *p++ = 0x80;
9636                  */
9637                 mono_metadata_encode_value (slen, p, &p);
9638                 memcpy (p, str, slen);
9639                 p += slen;
9640                 g_free (str);
9641         } else if (type->type == MONO_TYPE_OBJECT) {
9642                 *p++ = 0x51;
9643         } else if (type->type == MONO_TYPE_CLASS) {
9644                 /* it should be a type: encode_cattr_value () has the check */
9645                 *p++ = 0x50;
9646         } else {
9647                 mono_metadata_encode_value (type->type, p, &p);
9648                 if (type->type == MONO_TYPE_SZARRAY)
9649                         /* See the examples in Partition VI, Annex B */
9650                         encode_field_or_prop_type (&type->data.klass->byval_arg, p, &p);
9651         }
9652
9653         *retp = p;
9654 }
9655
9656 #ifndef DISABLE_REFLECTION_EMIT
9657 static void
9658 encode_named_val (MonoReflectionAssembly *assembly, char *buffer, char *p, char **retbuffer, char **retp, guint32 *buflen, MonoType *type, char *name, MonoObject *value)
9659 {
9660         int len;
9661         /* Preallocate a large enough buffer */
9662         if (type->type == MONO_TYPE_VALUETYPE && type->data.klass->enumtype) {
9663                 char *str = type_get_qualified_name (type, NULL);
9664                 len = strlen (str);
9665                 g_free (str);
9666         } else if (type->type == MONO_TYPE_SZARRAY && type->data.klass->enumtype) {
9667                 char *str = type_get_qualified_name (&type->data.klass->byval_arg, NULL);
9668                 len = strlen (str);
9669                 g_free (str);
9670         } else {
9671                 len = 0;
9672         }
9673         len += strlen (name);
9674
9675         if ((p-buffer) + 20 + len >= *buflen) {
9676                 char *newbuf;
9677                 *buflen *= 2;
9678                 *buflen += len;
9679                 newbuf = g_realloc (buffer, *buflen);
9680                 p = newbuf + (p-buffer);
9681                 buffer = newbuf;
9682         }
9683
9684         encode_field_or_prop_type (type, p, &p);
9685
9686         len = strlen (name);
9687         mono_metadata_encode_value (len, p, &p);
9688         memcpy (p, name, len);
9689         p += len;
9690         encode_cattr_value (assembly->assembly, buffer, p, &buffer, &p, buflen, type, value, NULL);
9691         *retp = p;
9692         *retbuffer = buffer;
9693 }
9694
9695 /*
9696  * mono_reflection_get_custom_attrs_blob:
9697  * @ctor: custom attribute constructor
9698  * @ctorArgs: arguments o the constructor
9699  * @properties:
9700  * @propValues:
9701  * @fields:
9702  * @fieldValues:
9703  * 
9704  * Creates the blob of data that needs to be saved in the metadata and that represents
9705  * the custom attributed described by @ctor, @ctorArgs etc.
9706  * Returns: a Byte array representing the blob of data.
9707  */
9708 MonoArray*
9709 mono_reflection_get_custom_attrs_blob (MonoReflectionAssembly *assembly, MonoObject *ctor, MonoArray *ctorArgs, MonoArray *properties, MonoArray *propValues, MonoArray *fields, MonoArray* fieldValues) 
9710 {
9711         MonoArray *result;
9712         MonoMethodSignature *sig;
9713         MonoObject *arg;
9714         char *buffer, *p;
9715         guint32 buflen, i;
9716
9717         MONO_ARCH_SAVE_REGS;
9718
9719         if (strcmp (ctor->vtable->klass->name, "MonoCMethod")) {
9720                 /* sig is freed later so allocate it in the heap */
9721                 sig = ctor_builder_to_signature (NULL, (MonoReflectionCtorBuilder*)ctor);
9722         } else {
9723                 sig = mono_method_signature (((MonoReflectionMethod*)ctor)->method);
9724         }
9725
9726         g_assert (mono_array_length (ctorArgs) == sig->param_count);
9727         buflen = 256;
9728         p = buffer = g_malloc (buflen);
9729         /* write the prolog */
9730         *p++ = 1;
9731         *p++ = 0;
9732         for (i = 0; i < sig->param_count; ++i) {
9733                 arg = mono_array_get (ctorArgs, MonoObject*, i);
9734                 encode_cattr_value (assembly->assembly, buffer, p, &buffer, &p, &buflen, sig->params [i], arg, NULL);
9735         }
9736         i = 0;
9737         if (properties)
9738                 i += mono_array_length (properties);
9739         if (fields)
9740                 i += mono_array_length (fields);
9741         *p++ = i & 0xff;
9742         *p++ = (i >> 8) & 0xff;
9743         if (properties) {
9744                 MonoObject *prop;
9745                 for (i = 0; i < mono_array_length (properties); ++i) {
9746                         MonoType *ptype;
9747                         char *pname;
9748
9749                         prop = mono_array_get (properties, gpointer, i);
9750                         get_prop_name_and_type (prop, &pname, &ptype);
9751                         *p++ = 0x54; /* PROPERTY signature */
9752                         encode_named_val (assembly, buffer, p, &buffer, &p, &buflen, ptype, pname, (MonoObject*)mono_array_get (propValues, gpointer, i));
9753                         g_free (pname);
9754                 }
9755         }
9756
9757         if (fields) {
9758                 MonoObject *field;
9759                 for (i = 0; i < mono_array_length (fields); ++i) {
9760                         MonoType *ftype;
9761                         char *fname;
9762
9763                         field = mono_array_get (fields, gpointer, i);
9764                         get_field_name_and_type (field, &fname, &ftype);
9765                         *p++ = 0x53; /* FIELD signature */
9766                         encode_named_val (assembly, buffer, p, &buffer, &p, &buflen, ftype, fname, (MonoObject*)mono_array_get (fieldValues, gpointer, i));
9767                         g_free (fname);
9768                 }
9769         }
9770
9771         g_assert (p - buffer <= buflen);
9772         buflen = p - buffer;
9773         result = mono_array_new (mono_domain_get (), mono_defaults.byte_class, buflen);
9774         p = mono_array_addr (result, char, 0);
9775         memcpy (p, buffer, buflen);
9776         g_free (buffer);
9777         if (strcmp (ctor->vtable->klass->name, "MonoCMethod"))
9778                 g_free (sig);
9779         return result;
9780 }
9781
9782 /*
9783  * mono_reflection_setup_internal_class:
9784  * @tb: a TypeBuilder object
9785  *
9786  * Creates a MonoClass that represents the TypeBuilder.
9787  * This is a trick that lets us simplify a lot of reflection code
9788  * (and will allow us to support Build and Run assemblies easier).
9789  */
9790 void
9791 mono_reflection_setup_internal_class (MonoReflectionTypeBuilder *tb)
9792 {
9793         MonoError error;
9794         MonoClass *klass, *parent;
9795
9796         MONO_ARCH_SAVE_REGS;
9797
9798         RESOLVE_TYPE (tb->parent);
9799
9800         mono_loader_lock ();
9801
9802         if (tb->parent) {
9803                 /* check so we can compile corlib correctly */
9804                 if (strcmp (mono_object_class (tb->parent)->name, "TypeBuilder") == 0) {
9805                         /* mono_class_setup_mono_type () guaranteess type->data.klass is valid */
9806                         parent = mono_reflection_type_get_handle ((MonoReflectionType*)tb->parent)->data.klass;
9807                 } else {
9808                         parent = mono_class_from_mono_type (mono_reflection_type_get_handle ((MonoReflectionType*)tb->parent));
9809                 }
9810         } else {
9811                 parent = NULL;
9812         }
9813         
9814         /* the type has already being created: it means we just have to change the parent */
9815         if (tb->type.type) {
9816                 klass = mono_class_from_mono_type (tb->type.type);
9817                 klass->parent = NULL;
9818                 /* fool mono_class_setup_parent */
9819                 klass->supertypes = NULL;
9820                 mono_class_setup_parent (klass, parent);
9821                 mono_class_setup_mono_type (klass);
9822                 mono_loader_unlock ();
9823                 return;
9824         }
9825
9826         klass = mono_image_alloc0 (&tb->module->dynamic_image->image, sizeof (MonoClass));
9827
9828         klass->image = &tb->module->dynamic_image->image;
9829
9830         klass->inited = 1; /* we lie to the runtime */
9831         klass->name = mono_string_to_utf8_image (klass->image, tb->name, &error);
9832         if (!mono_error_ok (&error))
9833                 goto failure;
9834         klass->name_space = mono_string_to_utf8_image (klass->image, tb->nspace, &error);
9835         if (!mono_error_ok (&error))
9836                 goto failure;
9837         klass->type_token = MONO_TOKEN_TYPE_DEF | tb->table_idx;
9838         klass->flags = tb->attrs;
9839         
9840         mono_profiler_class_event (klass, MONO_PROFILE_START_LOAD);
9841
9842         klass->element_class = klass;
9843
9844         if (mono_class_get_ref_info (klass) == NULL) {
9845
9846                 mono_class_set_ref_info (klass, tb);
9847
9848                 /* Put into cache so mono_class_get () will find it.
9849                 Skip nested types as those should not be available on the global scope. */
9850                 if (!tb->nesting_type) {
9851                         mono_image_add_to_name_cache (klass->image, klass->name_space, klass->name, tb->table_idx);
9852                 } else {
9853                         klass->image->reflection_info_unregister_classes =
9854                                 g_slist_prepend (klass->image->reflection_info_unregister_classes, klass);
9855                 }
9856         } else {
9857                 g_assert (mono_class_get_ref_info (klass) == tb);
9858         }
9859
9860         mono_g_hash_table_insert (tb->module->dynamic_image->tokens,
9861                 GUINT_TO_POINTER (MONO_TOKEN_TYPE_DEF | tb->table_idx), tb);
9862
9863         if (parent != NULL) {
9864                 mono_class_setup_parent (klass, parent);
9865         } else if (strcmp (klass->name, "Object") == 0 && strcmp (klass->name_space, "System") == 0) {
9866                 const char *old_n = klass->name;
9867                 /* trick to get relative numbering right when compiling corlib */
9868                 klass->name = "BuildingObject";
9869                 mono_class_setup_parent (klass, mono_defaults.object_class);
9870                 klass->name = old_n;
9871         }
9872
9873         if ((!strcmp (klass->name, "ValueType") && !strcmp (klass->name_space, "System")) ||
9874                         (!strcmp (klass->name, "Object") && !strcmp (klass->name_space, "System")) ||
9875                         (!strcmp (klass->name, "Enum") && !strcmp (klass->name_space, "System"))) {
9876                 klass->instance_size = sizeof (MonoObject);
9877                 klass->size_inited = 1;
9878                 mono_class_setup_vtable_general (klass, NULL, 0, NULL);
9879         }
9880
9881         mono_class_setup_mono_type (klass);
9882
9883         mono_class_setup_supertypes (klass);
9884
9885         /*
9886          * FIXME: handle interfaces.
9887          */
9888
9889         tb->type.type = &klass->byval_arg;
9890
9891         if (tb->nesting_type) {
9892                 g_assert (tb->nesting_type->type);
9893                 klass->nested_in = mono_class_from_mono_type (mono_reflection_type_get_handle (tb->nesting_type));
9894         }
9895
9896         /*g_print ("setup %s as %s (%p)\n", klass->name, ((MonoObject*)tb)->vtable->klass->name, tb);*/
9897
9898         mono_profiler_class_loaded (klass, MONO_PROFILE_OK);
9899         
9900         mono_loader_unlock ();
9901         return;
9902
9903 failure:
9904         mono_loader_unlock ();
9905         mono_error_raise_exception (&error);
9906 }
9907
9908 /*
9909  * mono_reflection_setup_generic_class:
9910  * @tb: a TypeBuilder object
9911  *
9912  * Setup the generic class before adding the first generic parameter.
9913  */
9914 void
9915 mono_reflection_setup_generic_class (MonoReflectionTypeBuilder *tb)
9916 {
9917 }
9918
9919 /*
9920  * mono_reflection_create_generic_class:
9921  * @tb: a TypeBuilder object
9922  *
9923  * Creates the generic class after all generic parameters have been added.
9924  */
9925 void
9926 mono_reflection_create_generic_class (MonoReflectionTypeBuilder *tb)
9927 {
9928         MonoClass *klass;
9929         int count, i;
9930
9931         MONO_ARCH_SAVE_REGS;
9932
9933         klass = mono_class_from_mono_type (tb->type.type);
9934
9935         count = tb->generic_params ? mono_array_length (tb->generic_params) : 0;
9936
9937         if (klass->generic_container || (count == 0))
9938                 return;
9939
9940         g_assert (tb->generic_container && (tb->generic_container->owner.klass == klass));
9941
9942         klass->generic_container = mono_image_alloc0 (klass->image, sizeof (MonoGenericContainer));
9943
9944         klass->generic_container->owner.klass = klass;
9945         klass->generic_container->type_argc = count;
9946         klass->generic_container->type_params = mono_image_alloc0 (klass->image, sizeof (MonoGenericParamFull) * count);
9947
9948         klass->is_generic = 1;
9949
9950         for (i = 0; i < count; i++) {
9951                 MonoReflectionGenericParam *gparam = mono_array_get (tb->generic_params, gpointer, i);
9952                 MonoGenericParamFull *param = (MonoGenericParamFull *) mono_reflection_type_get_handle ((MonoReflectionType*)gparam)->data.generic_param;
9953                 klass->generic_container->type_params [i] = *param;
9954                 /*Make sure we are a diferent type instance */
9955                 klass->generic_container->type_params [i].param.owner = klass->generic_container;
9956                 klass->generic_container->type_params [i].info.pklass = NULL;
9957                 klass->generic_container->type_params [i].info.flags = gparam->attrs;
9958
9959                 g_assert (klass->generic_container->type_params [i].param.owner);
9960         }
9961
9962         klass->generic_container->context.class_inst = mono_get_shared_generic_inst (klass->generic_container);
9963 }
9964
9965 /*
9966  * mono_reflection_create_internal_class:
9967  * @tb: a TypeBuilder object
9968  *
9969  * Actually create the MonoClass that is associated with the TypeBuilder.
9970  */
9971 void
9972 mono_reflection_create_internal_class (MonoReflectionTypeBuilder *tb)
9973 {
9974         MonoClass *klass;
9975
9976         MONO_ARCH_SAVE_REGS;
9977
9978         klass = mono_class_from_mono_type (tb->type.type);
9979
9980         mono_loader_lock ();
9981         if (klass->enumtype && mono_class_enum_basetype (klass) == NULL) {
9982                 MonoReflectionFieldBuilder *fb;
9983                 MonoClass *ec;
9984                 MonoType *enum_basetype;
9985
9986                 g_assert (tb->fields != NULL);
9987                 g_assert (mono_array_length (tb->fields) >= 1);
9988
9989                 fb = mono_array_get (tb->fields, MonoReflectionFieldBuilder*, 0);
9990
9991                 if (!mono_type_is_valid_enum_basetype (mono_reflection_type_get_handle ((MonoReflectionType*)fb->type))) {
9992                         mono_loader_unlock ();
9993                         return;
9994                 }
9995
9996                 enum_basetype = mono_reflection_type_get_handle ((MonoReflectionType*)fb->type);
9997                 klass->element_class = mono_class_from_mono_type (enum_basetype);
9998                 if (!klass->element_class)
9999                         klass->element_class = mono_class_from_mono_type (enum_basetype);
10000
10001                 /*
10002                  * get the element_class from the current corlib.
10003                  */
10004                 ec = default_class_from_mono_type (enum_basetype);
10005                 klass->instance_size = ec->instance_size;
10006                 klass->size_inited = 1;
10007                 /* 
10008                  * this is almost safe to do with enums and it's needed to be able
10009                  * to create objects of the enum type (for use in SetConstant).
10010                  */
10011                 /* FIXME: Does this mean enums can't have method overrides ? */
10012                 mono_class_setup_vtable_general (klass, NULL, 0, NULL);
10013         }
10014         mono_loader_unlock ();
10015 }
10016
10017 static MonoMarshalSpec*
10018 mono_marshal_spec_from_builder (MonoImage *image, MonoAssembly *assembly,
10019                                                                 MonoReflectionMarshal *minfo)
10020 {
10021         MonoMarshalSpec *res;
10022
10023         res = image_g_new0 (image, MonoMarshalSpec, 1);
10024         res->native = minfo->type;
10025
10026         switch (minfo->type) {
10027         case MONO_NATIVE_LPARRAY:
10028                 res->data.array_data.elem_type = minfo->eltype;
10029                 if (minfo->has_size) {
10030                         res->data.array_data.param_num = minfo->param_num;
10031                         res->data.array_data.num_elem = minfo->count;
10032                         res->data.array_data.elem_mult = minfo->param_num == -1 ? 0 : 1;
10033                 }
10034                 else {
10035                         res->data.array_data.param_num = -1;
10036                         res->data.array_data.num_elem = -1;
10037                         res->data.array_data.elem_mult = -1;
10038                 }
10039                 break;
10040
10041         case MONO_NATIVE_BYVALTSTR:
10042         case MONO_NATIVE_BYVALARRAY:
10043                 res->data.array_data.num_elem = minfo->count;
10044                 break;
10045
10046         case MONO_NATIVE_CUSTOM:
10047                 if (minfo->marshaltyperef)
10048                         res->data.custom_data.custom_name =
10049                                 type_get_fully_qualified_name (mono_reflection_type_get_handle ((MonoReflectionType*)minfo->marshaltyperef));
10050                 if (minfo->mcookie)
10051                         res->data.custom_data.cookie = mono_string_to_utf8 (minfo->mcookie);
10052                 break;
10053
10054         default:
10055                 break;
10056         }
10057
10058         return res;
10059 }
10060 #endif /* !DISABLE_REFLECTION_EMIT */
10061
10062 MonoReflectionMarshalAsAttribute*
10063 mono_reflection_marshal_as_attribute_from_marshal_spec (MonoDomain *domain, MonoClass *klass,
10064                                                                                    MonoMarshalSpec *spec)
10065 {
10066         static MonoClass *System_Reflection_Emit_MarshalAsAttribute;
10067         MonoReflectionMarshalAsAttribute *minfo;
10068         MonoType *mtype;
10069
10070         if (!System_Reflection_Emit_MarshalAsAttribute) {
10071                 System_Reflection_Emit_MarshalAsAttribute = mono_class_from_name (
10072                    mono_defaults.corlib, "System.Runtime.InteropServices", "MarshalAsAttribute");
10073                 g_assert (System_Reflection_Emit_MarshalAsAttribute);
10074         }
10075
10076         minfo = (MonoReflectionMarshalAsAttribute*)mono_object_new (domain, System_Reflection_Emit_MarshalAsAttribute);
10077         minfo->utype = spec->native;
10078
10079         switch (minfo->utype) {
10080         case MONO_NATIVE_LPARRAY:
10081                 minfo->array_subtype = spec->data.array_data.elem_type;
10082                 minfo->size_const = spec->data.array_data.num_elem;
10083                 if (spec->data.array_data.param_num != -1)
10084                         minfo->size_param_index = spec->data.array_data.param_num;
10085                 break;
10086
10087         case MONO_NATIVE_BYVALTSTR:
10088         case MONO_NATIVE_BYVALARRAY:
10089                 minfo->size_const = spec->data.array_data.num_elem;
10090                 break;
10091
10092         case MONO_NATIVE_CUSTOM:
10093                 if (spec->data.custom_data.custom_name) {
10094                         mtype = mono_reflection_type_from_name (spec->data.custom_data.custom_name, klass->image);
10095                         if (mtype)
10096                                 MONO_OBJECT_SETREF (minfo, marshal_type_ref, mono_type_get_object (domain, mtype));
10097
10098                         MONO_OBJECT_SETREF (minfo, marshal_type, mono_string_new (domain, spec->data.custom_data.custom_name));
10099                 }
10100                 if (spec->data.custom_data.cookie)
10101                         MONO_OBJECT_SETREF (minfo, marshal_cookie, mono_string_new (domain, spec->data.custom_data.cookie));
10102                 break;
10103
10104         default:
10105                 break;
10106         }
10107
10108         return minfo;
10109 }
10110
10111 #ifndef DISABLE_REFLECTION_EMIT
10112 static MonoMethod*
10113 reflection_methodbuilder_to_mono_method (MonoClass *klass,
10114                                          ReflectionMethodBuilder *rmb,
10115                                          MonoMethodSignature *sig)
10116 {
10117         MonoError error;
10118         MonoMethod *m;
10119         MonoMethodWrapper *wrapperm;
10120         MonoMarshalSpec **specs;
10121         MonoReflectionMethodAux *method_aux;
10122         MonoImage *image;
10123         gboolean dynamic;
10124         int i;
10125
10126         mono_error_init (&error);
10127         /*
10128          * Methods created using a MethodBuilder should have their memory allocated
10129          * inside the image mempool, while dynamic methods should have their memory
10130          * malloc'd.
10131          */
10132         dynamic = rmb->refs != NULL;
10133         image = dynamic ? NULL : klass->image;
10134
10135         if (!dynamic)
10136                 g_assert (!klass->generic_class);
10137
10138         mono_loader_lock ();
10139
10140         if ((rmb->attrs & METHOD_ATTRIBUTE_PINVOKE_IMPL) ||
10141                         (rmb->iattrs & METHOD_IMPL_ATTRIBUTE_INTERNAL_CALL))
10142                 m = (MonoMethod *)image_g_new0 (image, MonoMethodPInvoke, 1);
10143         else
10144                 m = (MonoMethod *)image_g_new0 (image, MonoMethodWrapper, 1);
10145
10146         wrapperm = (MonoMethodWrapper*)m;
10147
10148         m->dynamic = dynamic;
10149         m->slot = -1;
10150         m->flags = rmb->attrs;
10151         m->iflags = rmb->iattrs;
10152         m->name = mono_string_to_utf8_image_ignore (image, rmb->name);
10153         m->klass = klass;
10154         m->signature = sig;
10155         m->sre_method = TRUE;
10156         m->skip_visibility = rmb->skip_visibility;
10157         if (rmb->table_idx)
10158                 m->token = MONO_TOKEN_METHOD_DEF | (*rmb->table_idx);
10159
10160         if (m->iflags & METHOD_IMPL_ATTRIBUTE_INTERNAL_CALL) {
10161                 if (klass == mono_defaults.string_class && !strcmp (m->name, ".ctor"))
10162                         m->string_ctor = 1;
10163
10164                 m->signature->pinvoke = 1;
10165         } else if (m->flags & METHOD_ATTRIBUTE_PINVOKE_IMPL) {
10166                 m->signature->pinvoke = 1;
10167
10168                 method_aux = image_g_new0 (image, MonoReflectionMethodAux, 1);
10169
10170                 method_aux->dllentry = rmb->dllentry ? mono_string_to_utf8_image (image, rmb->dllentry, &error) : image_strdup (image, m->name);
10171                 g_assert (mono_error_ok (&error));
10172                 method_aux->dll = mono_string_to_utf8_image (image, rmb->dll, &error);
10173                 g_assert (mono_error_ok (&error));
10174                 
10175                 ((MonoMethodPInvoke*)m)->piflags = (rmb->native_cc << 8) | (rmb->charset ? (rmb->charset - 1) * 2 : 0) | rmb->extra_flags;
10176
10177                 if (klass->image->dynamic)
10178                         g_hash_table_insert (((MonoDynamicImage*)klass->image)->method_aux_hash, m, method_aux);
10179
10180                 mono_loader_unlock ();
10181
10182                 return m;
10183         } else if (!(m->flags & METHOD_ATTRIBUTE_ABSTRACT) &&
10184                            !(m->iflags & METHOD_IMPL_ATTRIBUTE_RUNTIME)) {
10185                 MonoMethodHeader *header;
10186                 guint32 code_size;
10187                 gint32 max_stack, i;
10188                 gint32 num_locals = 0;
10189                 gint32 num_clauses = 0;
10190                 guint8 *code;
10191
10192                 if (rmb->ilgen) {
10193                         code = mono_array_addr (rmb->ilgen->code, guint8, 0);
10194                         code_size = rmb->ilgen->code_len;
10195                         max_stack = rmb->ilgen->max_stack;
10196                         num_locals = rmb->ilgen->locals ? mono_array_length (rmb->ilgen->locals) : 0;
10197                         if (rmb->ilgen->ex_handlers)
10198                                 num_clauses = method_count_clauses (rmb->ilgen);
10199                 } else {
10200                         if (rmb->code) {
10201                                 code = mono_array_addr (rmb->code, guint8, 0);
10202                                 code_size = mono_array_length (rmb->code);
10203                                 /* we probably need to run a verifier on the code... */
10204                                 max_stack = 8; 
10205                         }
10206                         else {
10207                                 code = NULL;
10208                                 code_size = 0;
10209                                 max_stack = 8;
10210                         }
10211                 }
10212
10213                 header = image_g_malloc0 (image, MONO_SIZEOF_METHOD_HEADER + num_locals * sizeof (MonoType*));
10214                 header->code_size = code_size;
10215                 header->code = image_g_malloc (image, code_size);
10216                 memcpy ((char*)header->code, code, code_size);
10217                 header->max_stack = max_stack;
10218                 header->init_locals = rmb->init_locals;
10219                 header->num_locals = num_locals;
10220
10221                 for (i = 0; i < num_locals; ++i) {
10222                         MonoReflectionLocalBuilder *lb = 
10223                                 mono_array_get (rmb->ilgen->locals, MonoReflectionLocalBuilder*, i);
10224
10225                         header->locals [i] = image_g_new0 (image, MonoType, 1);
10226                         memcpy (header->locals [i], mono_reflection_type_get_handle ((MonoReflectionType*)lb->type), MONO_SIZEOF_TYPE);
10227                 }
10228
10229                 header->num_clauses = num_clauses;
10230                 if (num_clauses) {
10231                         header->clauses = method_encode_clauses (image, (MonoDynamicImage*)klass->image,
10232                                  rmb->ilgen, num_clauses);
10233                 }
10234
10235                 wrapperm->header = header;
10236         }
10237
10238         if (rmb->generic_params) {
10239                 int count = mono_array_length (rmb->generic_params);
10240                 MonoGenericContainer *container = rmb->generic_container;
10241
10242                 g_assert (container);
10243
10244                 container->type_argc = count;
10245                 container->type_params = image_g_new0 (image, MonoGenericParamFull, count);
10246                 container->owner.method = m;
10247
10248                 m->is_generic = TRUE;
10249                 mono_method_set_generic_container (m, container);
10250
10251                 for (i = 0; i < count; i++) {
10252                         MonoReflectionGenericParam *gp =
10253                                 mono_array_get (rmb->generic_params, MonoReflectionGenericParam*, i);
10254                         MonoGenericParamFull *param = (MonoGenericParamFull *) mono_reflection_type_get_handle ((MonoReflectionType*)gp)->data.generic_param;
10255                         container->type_params [i] = *param;
10256                 }
10257
10258                 /*
10259                  * The method signature might have pointers to generic parameters that belong to other methods.
10260                  * This is a valid SRE case, but the resulting method signature must be encoded using the proper
10261                  * generic parameters.
10262                  */
10263                 for (i = 0; i < m->signature->param_count; ++i) {
10264                         MonoType *t = m->signature->params [i];
10265                         if (t->type == MONO_TYPE_MVAR) {
10266                                 MonoGenericParam *gparam =  t->data.generic_param;
10267                                 if (gparam->num < count) {
10268                                         m->signature->params [i] = mono_metadata_type_dup (image, m->signature->params [i]);
10269                                         m->signature->params [i]->data.generic_param = mono_generic_container_get_param (container, gparam->num);
10270                                 }
10271
10272                         }
10273                 }
10274
10275                 if (klass->generic_container) {
10276                         container->parent = klass->generic_container;
10277                         container->context.class_inst = klass->generic_container->context.class_inst;
10278                 }
10279                 container->context.method_inst = mono_get_shared_generic_inst (container);
10280         }
10281
10282         if (rmb->refs) {
10283                 MonoMethodWrapper *mw = (MonoMethodWrapper*)m;
10284                 int i;
10285                 void **data;
10286
10287                 m->wrapper_type = MONO_WRAPPER_DYNAMIC_METHOD;
10288
10289                 mw->method_data = data = image_g_new (image, gpointer, rmb->nrefs + 1);
10290                 data [0] = GUINT_TO_POINTER (rmb->nrefs);
10291                 for (i = 0; i < rmb->nrefs; ++i)
10292                         data [i + 1] = rmb->refs [i];
10293         }
10294
10295         method_aux = NULL;
10296
10297         /* Parameter info */
10298         if (rmb->pinfo) {
10299                 if (!method_aux)
10300                         method_aux = image_g_new0 (image, MonoReflectionMethodAux, 1);
10301                 method_aux->param_names = image_g_new0 (image, char *, mono_method_signature (m)->param_count + 1);
10302                 for (i = 0; i <= m->signature->param_count; ++i) {
10303                         MonoReflectionParamBuilder *pb;
10304                         if ((pb = mono_array_get (rmb->pinfo, MonoReflectionParamBuilder*, i))) {
10305                                 if ((i > 0) && (pb->attrs)) {
10306                                         /* Make a copy since it might point to a shared type structure */
10307                                         m->signature->params [i - 1] = mono_metadata_type_dup (klass->image, m->signature->params [i - 1]);
10308                                         m->signature->params [i - 1]->attrs = pb->attrs;
10309                                 }
10310
10311                                 if (pb->attrs & PARAM_ATTRIBUTE_HAS_DEFAULT) {
10312                                         MonoDynamicImage *assembly;
10313                                         guint32 idx, def_type, len;
10314                                         char *p;
10315                                         const char *p2;
10316
10317                                         if (!method_aux->param_defaults) {
10318                                                 method_aux->param_defaults = image_g_new0 (image, guint8*, m->signature->param_count + 1);
10319                                                 method_aux->param_default_types = image_g_new0 (image, guint32, m->signature->param_count + 1);
10320                                         }
10321                                         assembly = (MonoDynamicImage*)klass->image;
10322                                         idx = encode_constant (assembly, pb->def_value, &def_type);
10323                                         /* Copy the data from the blob since it might get realloc-ed */
10324                                         p = assembly->blob.data + idx;
10325                                         len = mono_metadata_decode_blob_size (p, &p2);
10326                                         len += p2 - p;
10327                                         method_aux->param_defaults [i] = image_g_malloc (image, len);
10328                                         method_aux->param_default_types [i] = def_type;
10329                                         memcpy ((gpointer)method_aux->param_defaults [i], p, len);
10330                                 }
10331
10332                                 if (pb->name) {
10333                                         method_aux->param_names [i] = mono_string_to_utf8_image (image, pb->name, &error);
10334                                         g_assert (mono_error_ok (&error));
10335                                 }
10336                                 if (pb->cattrs) {
10337                                         if (!method_aux->param_cattr)
10338                                                 method_aux->param_cattr = image_g_new0 (image, MonoCustomAttrInfo*, m->signature->param_count + 1);
10339                                         method_aux->param_cattr [i] = mono_custom_attrs_from_builders (image, klass->image, pb->cattrs);
10340                                 }
10341                         }
10342                 }
10343         }
10344
10345         /* Parameter marshalling */
10346         specs = NULL;
10347         if (rmb->pinfo)         
10348                 for (i = 0; i < mono_array_length (rmb->pinfo); ++i) {
10349                         MonoReflectionParamBuilder *pb;
10350                         if ((pb = mono_array_get (rmb->pinfo, MonoReflectionParamBuilder*, i))) {
10351                                 if (pb->marshal_info) {
10352                                         if (specs == NULL)
10353                                                 specs = image_g_new0 (image, MonoMarshalSpec*, sig->param_count + 1);
10354                                         specs [pb->position] = 
10355                                                 mono_marshal_spec_from_builder (image, klass->image->assembly, pb->marshal_info);
10356                                 }
10357                         }
10358                 }
10359         if (specs != NULL) {
10360                 if (!method_aux)
10361                         method_aux = image_g_new0 (image, MonoReflectionMethodAux, 1);
10362                 method_aux->param_marshall = specs;
10363         }
10364
10365         if (klass->image->dynamic && method_aux)
10366                 g_hash_table_insert (((MonoDynamicImage*)klass->image)->method_aux_hash, m, method_aux);
10367
10368         mono_loader_unlock ();
10369
10370         return m;
10371 }       
10372
10373 static MonoMethod*
10374 ctorbuilder_to_mono_method (MonoClass *klass, MonoReflectionCtorBuilder* mb)
10375 {
10376         ReflectionMethodBuilder rmb;
10377         MonoMethodSignature *sig;
10378
10379         mono_loader_lock ();
10380         sig = ctor_builder_to_signature (klass->image, mb);
10381         mono_loader_unlock ();
10382
10383         reflection_methodbuilder_from_ctor_builder (&rmb, mb);
10384
10385         mb->mhandle = reflection_methodbuilder_to_mono_method (klass, &rmb, sig);
10386         mono_save_custom_attrs (klass->image, mb->mhandle, mb->cattrs);
10387
10388         /* If we are in a generic class, we might be called multiple times from inflate_method */
10389         if (!((MonoDynamicImage*)(MonoDynamicImage*)klass->image)->save && !klass->generic_container) {
10390                 /* ilgen is no longer needed */
10391                 mb->ilgen = NULL;
10392         }
10393
10394         return mb->mhandle;
10395 }
10396
10397 static MonoMethod*
10398 methodbuilder_to_mono_method (MonoClass *klass, MonoReflectionMethodBuilder* mb)
10399 {
10400         ReflectionMethodBuilder rmb;
10401         MonoMethodSignature *sig;
10402
10403         mono_loader_lock ();
10404         sig = method_builder_to_signature (klass->image, mb);
10405         mono_loader_unlock ();
10406
10407         reflection_methodbuilder_from_method_builder (&rmb, mb);
10408
10409         mb->mhandle = reflection_methodbuilder_to_mono_method (klass, &rmb, sig);
10410         mono_save_custom_attrs (klass->image, mb->mhandle, mb->cattrs);
10411
10412         /* If we are in a generic class, we might be called multiple times from inflate_method */
10413         if (!((MonoDynamicImage*)(MonoDynamicImage*)klass->image)->save && !klass->generic_container) {
10414                 /* ilgen is no longer needed */
10415                 mb->ilgen = NULL;
10416         }
10417         return mb->mhandle;
10418 }
10419
10420 static MonoClassField*
10421 fieldbuilder_to_mono_class_field (MonoClass *klass, MonoReflectionFieldBuilder* fb)
10422 {
10423         MonoClassField *field;
10424         MonoType *custom;
10425         MonoError error;
10426
10427         field = g_new0 (MonoClassField, 1);
10428
10429         field->name = mono_string_to_utf8_image (klass->image, fb->name, &error);
10430         g_assert (mono_error_ok (&error));
10431         if (fb->attrs || fb->modreq || fb->modopt) {
10432                 field->type = mono_metadata_type_dup (NULL, mono_reflection_type_get_handle ((MonoReflectionType*)fb->type));
10433                 field->type->attrs = fb->attrs;
10434
10435                 g_assert (klass->image->dynamic);
10436                 custom = add_custom_modifiers ((MonoDynamicImage*)klass->image, field->type, fb->modreq, fb->modopt);
10437                 g_free (field->type);
10438                 field->type = mono_metadata_type_dup (klass->image, custom);
10439                 g_free (custom);
10440         } else {
10441                 field->type = mono_reflection_type_get_handle ((MonoReflectionType*)fb->type);
10442         }
10443         if (fb->offset != -1)
10444                 field->offset = fb->offset;
10445         field->parent = klass;
10446         mono_save_custom_attrs (klass->image, field, fb->cattrs);
10447
10448         // FIXME: Can't store fb->def_value/RVA, is it needed for field_on_insts ?
10449
10450         return field;
10451 }
10452 #endif
10453
10454 MonoType*
10455 mono_reflection_bind_generic_parameters (MonoReflectionType *type, int type_argc, MonoType **types)
10456 {
10457         MonoClass *klass;
10458         MonoReflectionTypeBuilder *tb = NULL;
10459         gboolean is_dynamic = FALSE;
10460         MonoDomain *domain;
10461         MonoClass *geninst;
10462
10463         mono_loader_lock ();
10464
10465         domain = mono_object_domain (type);
10466
10467         if (is_sre_type_builder (mono_object_class (type))) {
10468                 tb = (MonoReflectionTypeBuilder *) type;
10469
10470                 is_dynamic = TRUE;
10471         } else if (is_sre_generic_instance (mono_object_class (type))) {
10472                 MonoReflectionGenericClass *rgi = (MonoReflectionGenericClass *) type;
10473                 MonoReflectionType *gtd = rgi->generic_type;
10474
10475                 if (is_sre_type_builder (mono_object_class (gtd))) {
10476                         tb = (MonoReflectionTypeBuilder *)gtd;
10477                         is_dynamic = TRUE;
10478                 }
10479         }
10480
10481         /* FIXME: fix the CreateGenericParameters protocol to avoid the two stage setup of TypeBuilders */
10482         if (tb && tb->generic_container)
10483                 mono_reflection_create_generic_class (tb);
10484
10485         klass = mono_class_from_mono_type (mono_reflection_type_get_handle (type));
10486         if (!klass->generic_container) {
10487                 mono_loader_unlock ();
10488                 return NULL;
10489         }
10490
10491         if (klass->wastypebuilder) {
10492                 tb = (MonoReflectionTypeBuilder *) mono_class_get_ref_info (klass);
10493
10494                 is_dynamic = TRUE;
10495         }
10496
10497         mono_loader_unlock ();
10498
10499         geninst = mono_class_bind_generic_parameters (klass, type_argc, types, is_dynamic);
10500
10501         return &geninst->byval_arg;
10502 }
10503
10504 MonoClass*
10505 mono_class_bind_generic_parameters (MonoClass *klass, int type_argc, MonoType **types, gboolean is_dynamic)
10506 {
10507         MonoGenericClass *gclass;
10508         MonoGenericInst *inst;
10509
10510         g_assert (klass->generic_container);
10511
10512         inst = mono_metadata_get_generic_inst (type_argc, types);
10513         gclass = mono_metadata_lookup_generic_class (klass, inst, is_dynamic);
10514
10515         return mono_generic_class_get_class (gclass);
10516 }
10517
10518 MonoReflectionMethod*
10519 mono_reflection_bind_generic_method_parameters (MonoReflectionMethod *rmethod, MonoArray *types)
10520 {
10521         MonoClass *klass;
10522         MonoMethod *method, *inflated;
10523         MonoMethodInflated *imethod;
10524         MonoGenericContext tmp_context;
10525         MonoGenericInst *ginst;
10526         MonoType **type_argv;
10527         int count, i;
10528
10529         MONO_ARCH_SAVE_REGS;
10530
10531         /*FIXME but this no longer should happen*/
10532         if (!strcmp (rmethod->object.vtable->klass->name, "MethodBuilder")) {
10533 #ifndef DISABLE_REFLECTION_EMIT
10534                 MonoReflectionMethodBuilder *mb = NULL;
10535                 MonoReflectionTypeBuilder *tb;
10536                 MonoClass *klass;
10537
10538                 mb = (MonoReflectionMethodBuilder *) rmethod;
10539                 tb = (MonoReflectionTypeBuilder *) mb->type;
10540                 klass = mono_class_from_mono_type (mono_reflection_type_get_handle ((MonoReflectionType*)tb));
10541
10542                 method = methodbuilder_to_mono_method (klass, mb);
10543 #else
10544                 g_assert_not_reached ();
10545                 method = NULL;
10546 #endif
10547         } else {
10548                 method = rmethod->method;
10549         }
10550
10551         klass = method->klass;
10552
10553         if (method->is_inflated)
10554                 method = ((MonoMethodInflated *) method)->declaring;
10555
10556         count = mono_method_signature (method)->generic_param_count;
10557         if (count != mono_array_length (types))
10558                 return NULL;
10559
10560         type_argv = g_new0 (MonoType *, count);
10561         for (i = 0; i < count; i++) {
10562                 MonoReflectionType *garg = mono_array_get (types, gpointer, i);
10563                 type_argv [i] = mono_reflection_type_get_handle (garg);
10564         }
10565         ginst = mono_metadata_get_generic_inst (count, type_argv);
10566         g_free (type_argv);
10567
10568         tmp_context.class_inst = klass->generic_class ? klass->generic_class->context.class_inst : NULL;
10569         tmp_context.method_inst = ginst;
10570
10571         inflated = mono_class_inflate_generic_method (method, &tmp_context);
10572         imethod = (MonoMethodInflated *) inflated;
10573
10574         /*FIXME but I think this is no longer necessary*/
10575         if (method->klass->image->dynamic) {
10576                 MonoDynamicImage *image = (MonoDynamicImage*)method->klass->image;
10577                 /*
10578                  * This table maps metadata structures representing inflated methods/fields
10579                  * to the reflection objects representing their generic definitions.
10580                  */
10581                 mono_loader_lock ();
10582                 mono_g_hash_table_insert (image->generic_def_objects, imethod, rmethod);
10583                 mono_loader_unlock ();
10584         }
10585
10586         if (!mono_verifier_is_method_valid_generic_instantiation (inflated))
10587                 mono_raise_exception (mono_get_exception_argument ("typeArguments", "Invalid generic arguments"));
10588         
10589         return mono_method_get_object (mono_object_domain (rmethod), inflated, NULL);
10590 }
10591
10592 #ifndef DISABLE_REFLECTION_EMIT
10593
10594 static MonoMethod *
10595 inflate_mono_method (MonoClass *klass, MonoMethod *method, MonoObject *obj)
10596 {
10597         MonoMethodInflated *imethod;
10598         MonoGenericContext *context;
10599         int i;
10600
10601         /*
10602          * With generic code sharing the klass might not be inflated.
10603          * This can happen because classes inflated with their own
10604          * type arguments are "normalized" to the uninflated class.
10605          */
10606         if (!klass->generic_class)
10607                 return method;
10608
10609         context = mono_class_get_context (klass);
10610
10611         if (klass->method.count && klass->methods) {
10612                 /* Find the already created inflated method */
10613                 for (i = 0; i < klass->method.count; ++i) {
10614                         g_assert (klass->methods [i]->is_inflated);
10615                         if (((MonoMethodInflated*)klass->methods [i])->declaring == method)
10616                                 break;
10617                 }
10618                 g_assert (i < klass->method.count);
10619                 imethod = (MonoMethodInflated*)klass->methods [i];
10620         } else {
10621                 imethod = (MonoMethodInflated *) mono_class_inflate_generic_method_full (method, klass, context);
10622         }
10623
10624         if (method->is_generic && method->klass->image->dynamic) {
10625                 MonoDynamicImage *image = (MonoDynamicImage*)method->klass->image;
10626
10627                 mono_loader_lock ();
10628                 mono_g_hash_table_insert (image->generic_def_objects, imethod, obj);
10629                 mono_loader_unlock ();
10630         }
10631         return (MonoMethod *) imethod;
10632 }
10633
10634 static MonoMethod *
10635 inflate_method (MonoReflectionType *type, MonoObject *obj)
10636 {
10637         MonoMethod *method;
10638         MonoClass *gklass;
10639
10640         MonoClass *type_class = mono_object_class (type);
10641
10642         if (is_sre_generic_instance (type_class)) {
10643                 MonoReflectionGenericClass *mgc = (MonoReflectionGenericClass*)type;
10644                 gklass = mono_class_from_mono_type (mono_reflection_type_get_handle ((MonoReflectionType*)mgc->generic_type));
10645         } else if (is_sre_type_builder (type_class)) {
10646                 gklass = mono_class_from_mono_type (mono_reflection_type_get_handle (type));
10647         } else if (type->type) {
10648                 gklass = mono_class_from_mono_type (type->type);
10649                 gklass = mono_class_get_generic_type_definition (gklass);
10650         } else {
10651                 g_error ("Can't handle type %s", mono_type_get_full_name (mono_object_class (type)));
10652         }
10653
10654         if (!strcmp (obj->vtable->klass->name, "MethodBuilder"))
10655                 if (((MonoReflectionMethodBuilder*)obj)->mhandle)
10656                         method = ((MonoReflectionMethodBuilder*)obj)->mhandle;
10657                 else
10658                         method = methodbuilder_to_mono_method (gklass, (MonoReflectionMethodBuilder *) obj);
10659         else if (!strcmp (obj->vtable->klass->name, "ConstructorBuilder"))
10660                 method = ctorbuilder_to_mono_method (gklass, (MonoReflectionCtorBuilder *) obj);
10661         else if (!strcmp (obj->vtable->klass->name, "MonoMethod") || !strcmp (obj->vtable->klass->name, "MonoCMethod"))
10662                 method = ((MonoReflectionMethod *) obj)->method;
10663         else {
10664                 method = NULL; /* prevent compiler warning */
10665                 g_error ("can't handle type %s", obj->vtable->klass->name);
10666         }
10667
10668         return inflate_mono_method (mono_class_from_mono_type (mono_reflection_type_get_handle ((MonoReflectionType*)type)), method, obj);
10669 }
10670
10671 /*TODO avoid saving custom attrs for generic classes as it's enough to have them on the generic type definition.*/
10672 void
10673 mono_reflection_generic_class_initialize (MonoReflectionGenericClass *type, MonoArray *fields)
10674 {
10675         MonoGenericClass *gclass;
10676         MonoDynamicGenericClass *dgclass;
10677         MonoClass *klass, *gklass;
10678         MonoType *gtype;
10679         int i;
10680
10681         MONO_ARCH_SAVE_REGS;
10682
10683         gtype = mono_reflection_type_get_handle ((MonoReflectionType*)type);
10684         klass = mono_class_from_mono_type (gtype);
10685         g_assert (gtype->type == MONO_TYPE_GENERICINST);
10686         gclass = gtype->data.generic_class;
10687
10688         if (!gclass->is_dynamic)
10689                 return;
10690
10691         dgclass = (MonoDynamicGenericClass *) gclass;
10692
10693         if (dgclass->initialized)
10694                 return;
10695
10696         gklass = gclass->container_class;
10697         mono_class_init (gklass);
10698
10699         dgclass->count_fields = fields ? mono_array_length (fields) : 0;
10700
10701         dgclass->fields = mono_image_set_new0 (gclass->owner, MonoClassField, dgclass->count_fields);
10702         dgclass->field_objects = mono_image_set_new0 (gclass->owner, MonoObject*, dgclass->count_fields);
10703         dgclass->field_generic_types = mono_image_set_new0 (gclass->owner, MonoType*, dgclass->count_fields);
10704
10705         for (i = 0; i < dgclass->count_fields; i++) {
10706                 MonoObject *obj = mono_array_get (fields, gpointer, i);
10707                 MonoClassField *field, *inflated_field = NULL;
10708
10709                 if (!strcmp (obj->vtable->klass->name, "FieldBuilder"))
10710                         inflated_field = field = fieldbuilder_to_mono_class_field (klass, (MonoReflectionFieldBuilder *) obj);
10711                 else if (!strcmp (obj->vtable->klass->name, "MonoField"))
10712                         field = ((MonoReflectionField *) obj)->field;
10713                 else {
10714                         field = NULL; /* prevent compiler warning */
10715                         g_assert_not_reached ();
10716                 }
10717
10718                 dgclass->fields [i] = *field;
10719                 dgclass->fields [i].parent = klass;
10720                 dgclass->fields [i].type = mono_class_inflate_generic_type (
10721                         field->type, mono_generic_class_get_context ((MonoGenericClass *) dgclass));
10722                 dgclass->field_generic_types [i] = field->type;
10723                 MONO_GC_REGISTER_ROOT_IF_MOVING (dgclass->field_objects [i]);
10724                 dgclass->field_objects [i] = obj;
10725
10726                 if (inflated_field) {
10727                         g_free (inflated_field);
10728                 } else {
10729                         dgclass->fields [i].name = mono_image_set_strdup (gclass->owner, dgclass->fields [i].name);
10730                 }
10731         }
10732
10733         dgclass->initialized = TRUE;
10734 }
10735
10736 void
10737 mono_reflection_free_dynamic_generic_class (MonoGenericClass *gclass)
10738 {
10739         MonoDynamicGenericClass *dgclass;
10740         int i;
10741
10742         g_assert (gclass->is_dynamic);
10743
10744         dgclass = (MonoDynamicGenericClass *)gclass;
10745
10746         for (i = 0; i < dgclass->count_fields; ++i) {
10747                 MonoClassField *field = dgclass->fields + i;
10748                 mono_metadata_free_type (field->type);
10749                 MONO_GC_UNREGISTER_ROOT_IF_MOVING (dgclass->field_objects [i]);
10750         }
10751 }
10752
10753 static void
10754 fix_partial_generic_class (MonoClass *klass)
10755 {
10756         MonoClass *gklass = klass->generic_class->container_class;
10757         MonoDynamicGenericClass *dgclass;
10758         int i;
10759
10760         if (klass->wastypebuilder)
10761                 return;
10762
10763         dgclass = (MonoDynamicGenericClass *)  klass->generic_class;
10764         if (klass->parent != gklass->parent) {
10765                 MonoError error;
10766                 MonoType *parent_type = mono_class_inflate_generic_type_checked (&gklass->parent->byval_arg, &klass->generic_class->context, &error);
10767                 if (mono_error_ok (&error)) {
10768                         MonoClass *parent = mono_class_from_mono_type (parent_type);
10769                         mono_metadata_free_type (parent_type);
10770                         if (parent != klass->parent) {
10771                                 /*fool mono_class_setup_parent*/
10772                                 klass->supertypes = NULL;
10773                                 mono_class_setup_parent (klass, parent);
10774                         }
10775                 } else {
10776                         mono_class_set_failure (klass, MONO_EXCEPTION_TYPE_LOAD, NULL);
10777                         mono_error_cleanup (&error);
10778                         if (gklass->wastypebuilder)
10779                                 klass->wastypebuilder = TRUE;
10780                         return;
10781                 }
10782         }
10783
10784         if (!dgclass->initialized)
10785                 return;
10786
10787         if (klass->method.count != gklass->method.count) {
10788                 klass->method.count = gklass->method.count;
10789                 klass->methods = mono_image_alloc (klass->image, sizeof (MonoMethod*) * (klass->method.count + 1));
10790
10791                 for (i = 0; i < klass->method.count; i++) {
10792                         klass->methods [i] = mono_class_inflate_generic_method_full (
10793                                 gklass->methods [i], klass, mono_class_get_context (klass));
10794                 }
10795         }
10796
10797         if (klass->interface_count && klass->interface_count != gklass->interface_count) {
10798                 klass->interface_count = gklass->interface_count;
10799                 klass->interfaces = mono_image_alloc (klass->image, sizeof (MonoClass*) * gklass->interface_count);
10800                 klass->interfaces_packed = NULL; /*make setup_interface_offsets happy*/
10801
10802                 for (i = 0; i < gklass->interface_count; ++i) {
10803                         MonoType *iface_type = mono_class_inflate_generic_type (&gklass->interfaces [i]->byval_arg, mono_class_get_context (klass));
10804                         klass->interfaces [i] = mono_class_from_mono_type (iface_type);
10805                         mono_metadata_free_type (iface_type);
10806
10807                         ensure_runtime_vtable (klass->interfaces [i]);
10808                 }
10809                 klass->interfaces_inited = 1;
10810         }
10811
10812         if (klass->field.count != gklass->field.count) {
10813                 klass->field.count = gklass->field.count;
10814                 klass->fields = image_g_new0 (klass->image, MonoClassField, klass->field.count);
10815
10816                 for (i = 0; i < klass->field.count; i++) {
10817                         klass->fields [i] = gklass->fields [i];
10818                         klass->fields [i].parent = klass;
10819                         klass->fields [i].type = mono_class_inflate_generic_type (gklass->fields [i].type, mono_class_get_context (klass));
10820                 }
10821         }
10822
10823         /*We can only finish with this klass once it's parent has as well*/
10824         if (gklass->wastypebuilder)
10825                 klass->wastypebuilder = TRUE;
10826         return;
10827 }
10828
10829 static void
10830 ensure_generic_class_runtime_vtable (MonoClass *klass)
10831 {
10832         MonoClass *gklass = klass->generic_class->container_class;
10833
10834         ensure_runtime_vtable (gklass); 
10835
10836         fix_partial_generic_class (klass);
10837 }
10838
10839 static void
10840 ensure_runtime_vtable (MonoClass *klass)
10841 {
10842         MonoReflectionTypeBuilder *tb = mono_class_get_ref_info (klass);
10843         int i, num, j;
10844
10845         if (!klass->image->dynamic || (!tb && !klass->generic_class) || klass->wastypebuilder)
10846                 return;
10847         if (klass->parent)
10848                 ensure_runtime_vtable (klass->parent);
10849
10850         if (tb) {
10851                 num = tb->ctors? mono_array_length (tb->ctors): 0;
10852                 num += tb->num_methods;
10853                 klass->method.count = num;
10854                 klass->methods = mono_image_alloc (klass->image, sizeof (MonoMethod*) * num);
10855                 num = tb->ctors? mono_array_length (tb->ctors): 0;
10856                 for (i = 0; i < num; ++i)
10857                         klass->methods [i] = ctorbuilder_to_mono_method (klass, mono_array_get (tb->ctors, MonoReflectionCtorBuilder*, i));
10858                 num = tb->num_methods;
10859                 j = i;
10860                 for (i = 0; i < num; ++i)
10861                         klass->methods [j++] = methodbuilder_to_mono_method (klass, mono_array_get (tb->methods, MonoReflectionMethodBuilder*, i));
10862         
10863                 if (tb->interfaces) {
10864                         klass->interface_count = mono_array_length (tb->interfaces);
10865                         klass->interfaces = mono_image_alloc (klass->image, sizeof (MonoClass*) * klass->interface_count);
10866                         for (i = 0; i < klass->interface_count; ++i) {
10867                                 MonoType *iface = mono_type_array_get_and_resolve (tb->interfaces, i);
10868                                 klass->interfaces [i] = mono_class_from_mono_type (iface);
10869                                 ensure_runtime_vtable (klass->interfaces [i]);
10870                         }
10871                         klass->interfaces_inited = 1;
10872                 }
10873         } else if (klass->generic_class){
10874                 ensure_generic_class_runtime_vtable (klass);
10875         }
10876
10877         if (klass->flags & TYPE_ATTRIBUTE_INTERFACE) {
10878                 int slot_num = 0;
10879                 for (i = 0; i < klass->method.count; ++i) {
10880                         MonoMethod *im = klass->methods [i];
10881                         if (!(im->flags & METHOD_ATTRIBUTE_STATIC))
10882                                 im->slot = slot_num++;
10883                 }
10884                 
10885                 klass->interfaces_packed = NULL; /*make setup_interface_offsets happy*/
10886                 mono_class_setup_interface_offsets (klass);
10887                 mono_class_setup_interface_id (klass);
10888         }
10889
10890         /*
10891          * The generic vtable is needed even if image->run is not set since some
10892          * runtime code like ves_icall_Type_GetMethodsByName depends on 
10893          * method->slot being defined.
10894          */
10895
10896         /* 
10897          * tb->methods could not be freed since it is used for determining 
10898          * overrides during dynamic vtable construction.
10899          */
10900 }
10901
10902 static MonoMethod*
10903 mono_reflection_method_get_handle (MonoObject *method)
10904 {
10905         MonoClass *class = mono_object_class (method);
10906         if (is_sr_mono_method (class) || is_sr_mono_generic_method (class)) {
10907                 MonoReflectionMethod *sr_method = (MonoReflectionMethod*)method;
10908                 return sr_method->method;
10909         }
10910         if (is_sre_method_builder (class)) {
10911                 MonoReflectionMethodBuilder *mb = (MonoReflectionMethodBuilder*)method;
10912                 return mb->mhandle;
10913         }
10914         if (is_sre_method_on_tb_inst (class)) {
10915                 MonoReflectionMethodOnTypeBuilderInst *m = (MonoReflectionMethodOnTypeBuilderInst*)method;
10916                 MonoMethod *result;
10917                 /*FIXME move this to a proper method and unify with resolve_object*/
10918                 if (m->method_args) {
10919                         result = mono_reflection_method_on_tb_inst_get_handle (m);
10920                 } else {
10921                         MonoType *type = mono_reflection_type_get_handle ((MonoReflectionType*)m->inst);
10922                         MonoClass *inflated_klass = mono_class_from_mono_type (type);
10923                         MonoMethod *mono_method;
10924
10925                         if (is_sre_method_builder (mono_object_class (m->mb)))
10926                                 mono_method = ((MonoReflectionMethodBuilder *)m->mb)->mhandle;
10927                         else if (is_sr_mono_method (mono_object_class (m->mb)))
10928                                 mono_method = ((MonoReflectionMethod *)m->mb)->method;
10929                         else
10930                                 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)));
10931
10932                         result = inflate_mono_method (inflated_klass, mono_method, (MonoObject*)m->mb);
10933                 }
10934                 return result;
10935         }
10936
10937         g_error ("Can't handle methods of type %s:%s", class->name_space, class->name);
10938         return NULL;
10939 }
10940
10941 void
10942 mono_reflection_get_dynamic_overrides (MonoClass *klass, MonoMethod ***overrides, int *num_overrides)
10943 {
10944         MonoReflectionTypeBuilder *tb;
10945         int i, j, onum;
10946         MonoReflectionMethod *m;
10947
10948         *overrides = NULL;
10949         *num_overrides = 0;
10950
10951         g_assert (klass->image->dynamic);
10952
10953         if (!mono_class_get_ref_info (klass))
10954                 return;
10955
10956         g_assert (strcmp (((MonoObject*)mono_class_get_ref_info (klass))->vtable->klass->name, "TypeBuilder") == 0);
10957
10958         tb = (MonoReflectionTypeBuilder*)mono_class_get_ref_info (klass);
10959
10960         onum = 0;
10961         if (tb->methods) {
10962                 for (i = 0; i < tb->num_methods; ++i) {
10963                         MonoReflectionMethodBuilder *mb = 
10964                                 mono_array_get (tb->methods, MonoReflectionMethodBuilder*, i);
10965                         if (mb->override_methods)
10966                                 onum += mono_array_length (mb->override_methods);
10967                 }
10968         }
10969
10970         if (onum) {
10971                 *overrides = g_new0 (MonoMethod*, onum * 2);
10972
10973                 onum = 0;
10974                 for (i = 0; i < tb->num_methods; ++i) {
10975                         MonoReflectionMethodBuilder *mb = 
10976                                 mono_array_get (tb->methods, MonoReflectionMethodBuilder*, i);
10977                         if (mb->override_methods) {
10978                                 for (j = 0; j < mono_array_length (mb->override_methods); ++j) {
10979                                         m = mono_array_get (mb->override_methods, MonoReflectionMethod*, j);
10980
10981                                         (*overrides) [onum * 2] = mono_reflection_method_get_handle ((MonoObject*)m);
10982                                         (*overrides) [onum * 2 + 1] = mb->mhandle;
10983
10984                                         g_assert (mb->mhandle);
10985
10986                                         onum ++;
10987                                 }
10988                         }
10989                 }
10990         }
10991
10992         *num_overrides = onum;
10993 }
10994
10995 static void
10996 typebuilder_setup_fields (MonoClass *klass, MonoError *error)
10997 {
10998         MonoReflectionTypeBuilder *tb = mono_class_get_ref_info (klass);
10999         MonoReflectionFieldBuilder *fb;
11000         MonoClassField *field;
11001         MonoImage *image = klass->image;
11002         const char *p, *p2;
11003         int i;
11004         guint32 len, idx, real_size = 0;
11005
11006         klass->field.count = tb->num_fields;
11007         klass->field.first = 0;
11008
11009         mono_error_init (error);
11010
11011         if (tb->class_size) {
11012                 if ((tb->packing_size & 0xfffffff0) != 0) {
11013                         char *err_msg = g_strdup_printf ("Could not load struct '%s' with packing size %d >= 16", klass->name, tb->packing_size);
11014                         mono_class_set_failure (klass, MONO_EXCEPTION_TYPE_LOAD, err_msg);
11015                         return;
11016                 }
11017                 klass->packing_size = tb->packing_size;
11018                 real_size = klass->instance_size + tb->class_size;
11019         }
11020
11021         if (!klass->field.count) {
11022                 klass->instance_size = MAX (klass->instance_size, real_size);
11023                 return;
11024         }
11025         
11026         klass->fields = image_g_new0 (image, MonoClassField, klass->field.count);
11027         mono_class_alloc_ext (klass);
11028         klass->ext->field_def_values = image_g_new0 (image, MonoFieldDefaultValue, klass->field.count);
11029         /*
11030         This is, guess what, a hack.
11031         The issue is that the runtime doesn't know how to setup the fields of a typebuider and crash.
11032         On the static path no field class is resolved, only types are built. This is the right thing to do
11033         but we suck.
11034         Setting size_inited is harmless because we're doing the same job as mono_class_setup_fields anyway.
11035         */
11036         klass->size_inited = 1;
11037
11038         for (i = 0; i < klass->field.count; ++i) {
11039                 MonoArray *rva_data;
11040                 fb = mono_array_get (tb->fields, gpointer, i);
11041                 field = &klass->fields [i];
11042                 field->name = mono_string_to_utf8_image (image, fb->name, error);
11043                 if (!mono_error_ok (error))
11044                         return;
11045                 if (fb->attrs) {
11046                         field->type = mono_metadata_type_dup (klass->image, mono_reflection_type_get_handle ((MonoReflectionType*)fb->type));
11047                         field->type->attrs = fb->attrs;
11048                 } else {
11049                         field->type = mono_reflection_type_get_handle ((MonoReflectionType*)fb->type);
11050                 }
11051
11052                 if ((fb->attrs & FIELD_ATTRIBUTE_HAS_FIELD_RVA) && (rva_data = fb->rva_data)) {
11053                         char *base = mono_array_addr (rva_data, char, 0);
11054                         size_t size = mono_array_length (rva_data);
11055                         char *data = mono_image_alloc (klass->image, size);
11056                         memcpy (data, base, size);
11057                         klass->ext->field_def_values [i].data = data;
11058                 }
11059                 if (fb->offset != -1)
11060                         field->offset = fb->offset;
11061                 field->parent = klass;
11062                 fb->handle = field;
11063                 mono_save_custom_attrs (klass->image, field, fb->cattrs);
11064
11065                 if (klass->enumtype && !(field->type->attrs & FIELD_ATTRIBUTE_STATIC)) {
11066                         klass->cast_class = klass->element_class = mono_class_from_mono_type (field->type);
11067                 }
11068                 if (fb->def_value) {
11069                         MonoDynamicImage *assembly = (MonoDynamicImage*)klass->image;
11070                         field->type->attrs |= FIELD_ATTRIBUTE_HAS_DEFAULT;
11071                         idx = encode_constant (assembly, fb->def_value, &klass->ext->field_def_values [i].def_type);
11072                         /* Copy the data from the blob since it might get realloc-ed */
11073                         p = assembly->blob.data + idx;
11074                         len = mono_metadata_decode_blob_size (p, &p2);
11075                         len += p2 - p;
11076                         klass->ext->field_def_values [i].data = mono_image_alloc (image, len);
11077                         memcpy ((gpointer)klass->ext->field_def_values [i].data, p, len);
11078                 }
11079         }
11080
11081         klass->instance_size = MAX (klass->instance_size, real_size);
11082         mono_class_layout_fields (klass);
11083 }
11084
11085 static void
11086 typebuilder_setup_properties (MonoClass *klass, MonoError *error)
11087 {
11088         MonoReflectionTypeBuilder *tb = mono_class_get_ref_info (klass);
11089         MonoReflectionPropertyBuilder *pb;
11090         MonoImage *image = klass->image;
11091         MonoProperty *properties;
11092         int i;
11093
11094         mono_error_init (error);
11095
11096         if (!klass->ext)
11097                 klass->ext = image_g_new0 (image, MonoClassExt, 1);
11098
11099         klass->ext->property.count = tb->properties ? mono_array_length (tb->properties) : 0;
11100         klass->ext->property.first = 0;
11101
11102         properties = image_g_new0 (image, MonoProperty, klass->ext->property.count);
11103         klass->ext->properties = properties;
11104         for (i = 0; i < klass->ext->property.count; ++i) {
11105                 pb = mono_array_get (tb->properties, MonoReflectionPropertyBuilder*, i);
11106                 properties [i].parent = klass;
11107                 properties [i].attrs = pb->attrs;
11108                 properties [i].name = mono_string_to_utf8_image (image, pb->name, error);
11109                 if (!mono_error_ok (error))
11110                         return;
11111                 if (pb->get_method)
11112                         properties [i].get = pb->get_method->mhandle;
11113                 if (pb->set_method)
11114                         properties [i].set = pb->set_method->mhandle;
11115
11116                 mono_save_custom_attrs (klass->image, &properties [i], pb->cattrs);
11117                 if (pb->def_value) {
11118                         guint32 len, idx;
11119                         const char *p, *p2;
11120                         MonoDynamicImage *assembly = (MonoDynamicImage*)klass->image;
11121                         if (!klass->ext->prop_def_values)
11122                                 klass->ext->prop_def_values = image_g_new0 (image, MonoFieldDefaultValue, klass->ext->property.count);
11123                         properties [i].attrs |= PROPERTY_ATTRIBUTE_HAS_DEFAULT;
11124                         idx = encode_constant (assembly, pb->def_value, &klass->ext->prop_def_values [i].def_type);
11125                         /* Copy the data from the blob since it might get realloc-ed */
11126                         p = assembly->blob.data + idx;
11127                         len = mono_metadata_decode_blob_size (p, &p2);
11128                         len += p2 - p;
11129                         klass->ext->prop_def_values [i].data = mono_image_alloc (image, len);
11130                         memcpy ((gpointer)klass->ext->prop_def_values [i].data, p, len);
11131                 }
11132         }
11133 }
11134
11135 MonoReflectionEvent *
11136 mono_reflection_event_builder_get_event_info (MonoReflectionTypeBuilder *tb, MonoReflectionEventBuilder *eb)
11137 {
11138         MonoEvent *event = g_new0 (MonoEvent, 1);
11139         MonoClass *klass;
11140
11141         klass = mono_class_from_mono_type (mono_reflection_type_get_handle ((MonoReflectionType*)tb));
11142
11143         event->parent = klass;
11144         event->attrs = eb->attrs;
11145         event->name = mono_string_to_utf8 (eb->name);
11146         if (eb->add_method)
11147                 event->add = eb->add_method->mhandle;
11148         if (eb->remove_method)
11149                 event->remove = eb->remove_method->mhandle;
11150         if (eb->raise_method)
11151                 event->raise = eb->raise_method->mhandle;
11152
11153 #ifndef MONO_SMALL_CONFIG
11154         if (eb->other_methods) {
11155                 int j;
11156                 event->other = g_new0 (MonoMethod*, mono_array_length (eb->other_methods) + 1);
11157                 for (j = 0; j < mono_array_length (eb->other_methods); ++j) {
11158                         MonoReflectionMethodBuilder *mb = 
11159                                 mono_array_get (eb->other_methods,
11160                                                 MonoReflectionMethodBuilder*, j);
11161                         event->other [j] = mb->mhandle;
11162                 }
11163         }
11164 #endif
11165
11166         return mono_event_get_object (mono_object_domain (tb), klass, event);
11167 }
11168
11169 static void
11170 typebuilder_setup_events (MonoClass *klass, MonoError *error)
11171 {
11172         MonoReflectionTypeBuilder *tb = mono_class_get_ref_info (klass);
11173         MonoReflectionEventBuilder *eb;
11174         MonoImage *image = klass->image;
11175         MonoEvent *events;
11176         int i;
11177
11178         mono_error_init (error);
11179
11180         if (!klass->ext)
11181                 klass->ext = image_g_new0 (image, MonoClassExt, 1);
11182
11183         klass->ext->event.count = tb->events ? mono_array_length (tb->events) : 0;
11184         klass->ext->event.first = 0;
11185
11186         events = image_g_new0 (image, MonoEvent, klass->ext->event.count);
11187         klass->ext->events = events;
11188         for (i = 0; i < klass->ext->event.count; ++i) {
11189                 eb = mono_array_get (tb->events, MonoReflectionEventBuilder*, i);
11190                 events [i].parent = klass;
11191                 events [i].attrs = eb->attrs;
11192                 events [i].name = mono_string_to_utf8_image (image, eb->name, error);
11193                 if (!mono_error_ok (error))
11194                         return;
11195                 if (eb->add_method)
11196                         events [i].add = eb->add_method->mhandle;
11197                 if (eb->remove_method)
11198                         events [i].remove = eb->remove_method->mhandle;
11199                 if (eb->raise_method)
11200                         events [i].raise = eb->raise_method->mhandle;
11201
11202 #ifndef MONO_SMALL_CONFIG
11203                 if (eb->other_methods) {
11204                         int j;
11205                         events [i].other = image_g_new0 (image, MonoMethod*, mono_array_length (eb->other_methods) + 1);
11206                         for (j = 0; j < mono_array_length (eb->other_methods); ++j) {
11207                                 MonoReflectionMethodBuilder *mb = 
11208                                         mono_array_get (eb->other_methods,
11209                                                                         MonoReflectionMethodBuilder*, j);
11210                                 events [i].other [j] = mb->mhandle;
11211                         }
11212                 }
11213 #endif
11214                 mono_save_custom_attrs (klass->image, &events [i], eb->cattrs);
11215         }
11216 }
11217
11218 static gboolean
11219 remove_instantiations_of_and_ensure_contents (gpointer key,
11220                                                   gpointer value,
11221                                                   gpointer user_data)
11222 {
11223         MonoType *type = (MonoType*)key;
11224         MonoClass *klass = (MonoClass*)user_data;
11225
11226         if ((type->type == MONO_TYPE_GENERICINST) && (type->data.generic_class->container_class == klass)) {
11227                 fix_partial_generic_class (mono_class_from_mono_type (type)); //Ensure it's safe to use it.
11228                 return TRUE;
11229         } else
11230                 return FALSE;
11231 }
11232
11233 static void
11234 check_array_for_usertypes (MonoArray *arr)
11235 {
11236         int i;
11237
11238         if (!arr)
11239                 return;
11240
11241         for (i = 0; i < mono_array_length (arr); ++i)
11242                 RESOLVE_ARRAY_TYPE_ELEMENT (arr, i);
11243 }
11244
11245 MonoReflectionType*
11246 mono_reflection_create_runtime_class (MonoReflectionTypeBuilder *tb)
11247 {
11248         MonoError error;
11249         MonoClass *klass;
11250         MonoDomain* domain;
11251         MonoReflectionType* res;
11252         int i, j;
11253
11254         MONO_ARCH_SAVE_REGS;
11255
11256         domain = mono_object_domain (tb);
11257         klass = mono_class_from_mono_type (tb->type.type);
11258
11259         /*
11260          * Check for user defined Type subclasses.
11261          */
11262         RESOLVE_TYPE (tb->parent);
11263         check_array_for_usertypes (tb->interfaces);
11264         if (tb->fields) {
11265                 for (i = 0; i < mono_array_length (tb->fields); ++i) {
11266                         MonoReflectionFieldBuilder *fb = mono_array_get (tb->fields, gpointer, i);
11267                         if (fb) {
11268                                 RESOLVE_TYPE (fb->type);
11269                                 check_array_for_usertypes (fb->modreq);
11270                                 check_array_for_usertypes (fb->modopt);
11271                                 if (fb->marshal_info && fb->marshal_info->marshaltyperef)
11272                                         RESOLVE_TYPE (fb->marshal_info->marshaltyperef);
11273                         }
11274                 }
11275         }
11276         if (tb->methods) {
11277                 for (i = 0; i < mono_array_length (tb->methods); ++i) {
11278                         MonoReflectionMethodBuilder *mb = mono_array_get (tb->methods, gpointer, i);
11279                         if (mb) {
11280                                 RESOLVE_TYPE (mb->rtype);
11281                                 check_array_for_usertypes (mb->return_modreq);
11282                                 check_array_for_usertypes (mb->return_modopt);
11283                                 check_array_for_usertypes (mb->parameters);
11284                                 if (mb->param_modreq)
11285                                         for (j = 0; j < mono_array_length (mb->param_modreq); ++j)
11286                                                 check_array_for_usertypes (mono_array_get (mb->param_modreq, MonoArray*, j));
11287                                 if (mb->param_modopt)
11288                                         for (j = 0; j < mono_array_length (mb->param_modopt); ++j)
11289                                                 check_array_for_usertypes (mono_array_get (mb->param_modopt, MonoArray*, j));
11290                         }
11291                 }
11292         }
11293         if (tb->ctors) {
11294                 for (i = 0; i < mono_array_length (tb->ctors); ++i) {
11295                         MonoReflectionCtorBuilder *mb = mono_array_get (tb->ctors, gpointer, i);
11296                         if (mb) {
11297                                 check_array_for_usertypes (mb->parameters);
11298                                 if (mb->param_modreq)
11299                                         for (j = 0; j < mono_array_length (mb->param_modreq); ++j)
11300                                                 check_array_for_usertypes (mono_array_get (mb->param_modreq, MonoArray*, j));
11301                                 if (mb->param_modopt)
11302                                         for (j = 0; j < mono_array_length (mb->param_modopt); ++j)
11303                                                 check_array_for_usertypes (mono_array_get (mb->param_modopt, MonoArray*, j));
11304                         }
11305                 }
11306         }
11307
11308         mono_save_custom_attrs (klass->image, klass, tb->cattrs);
11309
11310         /* 
11311          * we need to lock the domain because the lock will be taken inside
11312          * So, we need to keep the locking order correct.
11313          */
11314         mono_loader_lock ();
11315         mono_domain_lock (domain);
11316         if (klass->wastypebuilder) {
11317                 mono_domain_unlock (domain);
11318                 mono_loader_unlock ();
11319                 return mono_type_get_object (mono_object_domain (tb), &klass->byval_arg);
11320         }
11321         /*
11322          * Fields to set in klass:
11323          * the various flags: delegate/unicode/contextbound etc.
11324          */
11325         klass->flags = tb->attrs;
11326         klass->has_cctor = 1;
11327         klass->has_finalize = 1;
11328         klass->has_finalize_inited = 1;
11329
11330         /* fool mono_class_setup_parent */
11331         klass->supertypes = NULL;
11332         mono_class_setup_parent (klass, klass->parent);
11333         mono_class_setup_mono_type (klass);
11334
11335 #if 0
11336         if (!((MonoDynamicImage*)klass->image)->run) {
11337                 if (klass->generic_container) {
11338                         /* FIXME: The code below can't handle generic classes */
11339                         klass->wastypebuilder = TRUE;
11340                         mono_loader_unlock ();
11341                         mono_domain_unlock (domain);
11342                         return mono_type_get_object (mono_object_domain (tb), &klass->byval_arg);
11343                 }
11344         }
11345 #endif
11346
11347         /* enums are done right away */
11348         if (!klass->enumtype)
11349                 ensure_runtime_vtable (klass);
11350
11351         if (tb->subtypes) {
11352                 for (i = 0; i < mono_array_length (tb->subtypes); ++i) {
11353                         MonoReflectionTypeBuilder *subtb = mono_array_get (tb->subtypes, MonoReflectionTypeBuilder*, i);
11354                         mono_class_alloc_ext (klass);
11355                         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)));
11356                 }
11357         }
11358
11359         klass->nested_classes_inited = TRUE;
11360
11361         /* fields and object layout */
11362         if (klass->parent) {
11363                 if (!klass->parent->size_inited)
11364                         mono_class_init (klass->parent);
11365                 klass->instance_size = klass->parent->instance_size;
11366                 klass->sizes.class_size = 0;
11367                 klass->min_align = klass->parent->min_align;
11368                 /* if the type has no fields we won't call the field_setup
11369                  * routine which sets up klass->has_references.
11370                  */
11371                 klass->has_references |= klass->parent->has_references;
11372         } else {
11373                 klass->instance_size = sizeof (MonoObject);
11374                 klass->min_align = 1;
11375         }
11376
11377         /* FIXME: handle packing_size and instance_size */
11378         typebuilder_setup_fields (klass, &error);
11379         if (!mono_error_ok (&error))
11380                 goto failure;
11381         typebuilder_setup_properties (klass, &error);
11382         if (!mono_error_ok (&error))
11383                 goto failure;
11384
11385         typebuilder_setup_events (klass, &error);
11386         if (!mono_error_ok (&error))
11387                 goto failure;
11388
11389         klass->wastypebuilder = TRUE;
11390
11391         /* 
11392          * If we are a generic TypeBuilder, there might be instantiations in the type cache
11393          * which have type System.Reflection.MonoGenericClass, but after the type is created, 
11394          * we want to return normal System.MonoType objects, so clear these out from the cache.
11395          *
11396          * Together with this we must ensure the contents of all instances to match the created type.
11397          */
11398         if (domain->type_hash && klass->generic_container)
11399                 mono_g_hash_table_foreach_remove (domain->type_hash, remove_instantiations_of_and_ensure_contents, klass);
11400
11401         mono_domain_unlock (domain);
11402         mono_loader_unlock ();
11403
11404         if (klass->enumtype && !mono_class_is_valid_enum (klass)) {
11405                 mono_class_set_failure (klass, MONO_EXCEPTION_TYPE_LOAD, NULL);
11406                 mono_raise_exception (mono_get_exception_type_load (tb->name, NULL));
11407         }
11408
11409         res = mono_type_get_object (mono_object_domain (tb), &klass->byval_arg);
11410         g_assert (res != (MonoReflectionType*)tb);
11411
11412         return res;
11413
11414 failure:
11415         mono_class_set_failure (klass, MONO_EXCEPTION_TYPE_LOAD, NULL);
11416         klass->wastypebuilder = TRUE;
11417         mono_domain_unlock (domain);
11418         mono_loader_unlock ();
11419         mono_error_raise_exception (&error);
11420         return NULL;
11421 }
11422
11423 void
11424 mono_reflection_initialize_generic_parameter (MonoReflectionGenericParam *gparam)
11425 {
11426         MonoGenericParamFull *param;
11427         MonoImage *image;
11428         MonoClass *pklass;
11429         MonoError error;
11430
11431         MONO_ARCH_SAVE_REGS;
11432
11433         image = &gparam->tbuilder->module->dynamic_image->image;
11434
11435         param = mono_image_new0 (image, MonoGenericParamFull, 1);
11436
11437         param->info.name = mono_string_to_utf8_image (image, gparam->name, &error);
11438         g_assert (mono_error_ok (&error));
11439         param->param.num = gparam->index;
11440
11441         if (gparam->mbuilder) {
11442                 if (!gparam->mbuilder->generic_container) {
11443                         MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder *)gparam->mbuilder->type;
11444                         MonoClass *klass = mono_class_from_mono_type (mono_reflection_type_get_handle ((MonoReflectionType*)tb));
11445                         gparam->mbuilder->generic_container = mono_image_alloc0 (klass->image, sizeof (MonoGenericContainer));
11446                         gparam->mbuilder->generic_container->is_method = TRUE;
11447                         /* 
11448                          * Cannot set owner.method, since the MonoMethod is not created yet.
11449                          * Set the image field instead, so type_in_image () works.
11450                          */
11451                         gparam->mbuilder->generic_container->image = klass->image;
11452                 }
11453                 param->param.owner = gparam->mbuilder->generic_container;
11454         } else if (gparam->tbuilder) {
11455                 if (!gparam->tbuilder->generic_container) {
11456                         MonoClass *klass = mono_class_from_mono_type (mono_reflection_type_get_handle ((MonoReflectionType*)gparam->tbuilder));
11457                         gparam->tbuilder->generic_container = mono_image_alloc0 (klass->image, sizeof (MonoGenericContainer));
11458                         gparam->tbuilder->generic_container->owner.klass = klass;
11459                 }
11460                 param->param.owner = gparam->tbuilder->generic_container;
11461         }
11462
11463         pklass = mono_class_from_generic_parameter ((MonoGenericParam *) param, image, gparam->mbuilder != NULL);
11464
11465         gparam->type.type = &pklass->byval_arg;
11466
11467         mono_class_set_ref_info (pklass, gparam);
11468         mono_image_lock (image);
11469         image->reflection_info_unregister_classes = g_slist_prepend (image->reflection_info_unregister_classes, pklass);
11470         mono_image_unlock (image);
11471 }
11472
11473 MonoArray *
11474 mono_reflection_sighelper_get_signature_local (MonoReflectionSigHelper *sig)
11475 {
11476         MonoReflectionModuleBuilder *module = sig->module;
11477         MonoDynamicImage *assembly = module != NULL ? module->dynamic_image : NULL;
11478         guint32 na = sig->arguments ? mono_array_length (sig->arguments) : 0;
11479         guint32 buflen, i;
11480         MonoArray *result;
11481         SigBuffer buf;
11482
11483         check_array_for_usertypes (sig->arguments);
11484
11485         sigbuffer_init (&buf, 32);
11486
11487         sigbuffer_add_value (&buf, 0x07);
11488         sigbuffer_add_value (&buf, na);
11489         if (assembly != NULL){
11490                 for (i = 0; i < na; ++i) {
11491                         MonoReflectionType *type = mono_array_get (sig->arguments, MonoReflectionType*, i);
11492                         encode_reflection_type (assembly, type, &buf);
11493                 }
11494         }
11495
11496         buflen = buf.p - buf.buf;
11497         result = mono_array_new (mono_domain_get (), mono_defaults.byte_class, buflen);
11498         memcpy (mono_array_addr (result, char, 0), buf.buf, buflen);
11499         sigbuffer_free (&buf);
11500
11501         return result;
11502 }
11503
11504 MonoArray *
11505 mono_reflection_sighelper_get_signature_field (MonoReflectionSigHelper *sig)
11506 {
11507         MonoDynamicImage *assembly = sig->module->dynamic_image;
11508         guint32 na = sig->arguments ? mono_array_length (sig->arguments) : 0;
11509         guint32 buflen, i;
11510         MonoArray *result;
11511         SigBuffer buf;
11512
11513         check_array_for_usertypes (sig->arguments);
11514
11515         sigbuffer_init (&buf, 32);
11516
11517         sigbuffer_add_value (&buf, 0x06);
11518         for (i = 0; i < na; ++i) {
11519                 MonoReflectionType *type = mono_array_get (sig->arguments, MonoReflectionType*, i);
11520                 encode_reflection_type (assembly, type, &buf);
11521         }
11522
11523         buflen = buf.p - buf.buf;
11524         result = mono_array_new (mono_domain_get (), mono_defaults.byte_class, buflen);
11525         memcpy (mono_array_addr (result, char, 0), buf.buf, buflen);
11526         sigbuffer_free (&buf);
11527
11528         return result;
11529 }
11530
11531 typedef struct {
11532         MonoMethod *handle;
11533         MonoDomain *domain;
11534 } DynamicMethodReleaseData;
11535
11536 /*
11537  * The runtime automatically clean up those after finalization.
11538 */      
11539 static MonoReferenceQueue *dynamic_method_queue;
11540
11541 static void
11542 free_dynamic_method (void *dynamic_method)
11543 {
11544         DynamicMethodReleaseData *data = dynamic_method;
11545
11546         mono_runtime_free_method (data->domain, data->handle);
11547         g_free (data);
11548 }
11549
11550 void 
11551 mono_reflection_create_dynamic_method (MonoReflectionDynamicMethod *mb)
11552 {
11553         MonoReferenceQueue *queue;
11554         MonoMethod *handle;
11555         DynamicMethodReleaseData *release_data;
11556         ReflectionMethodBuilder rmb;
11557         MonoMethodSignature *sig;
11558         MonoClass *klass;
11559         GSList *l;
11560         int i;
11561
11562         if (mono_runtime_is_shutting_down ())
11563                 mono_raise_exception (mono_get_exception_invalid_operation (""));
11564
11565         if (!(queue = dynamic_method_queue)) {
11566                 mono_loader_lock ();
11567                 if (!(queue = dynamic_method_queue))
11568                         queue = dynamic_method_queue = mono_gc_reference_queue_new (free_dynamic_method);
11569                 mono_loader_unlock ();
11570         }
11571
11572         sig = dynamic_method_to_signature (mb);
11573
11574         reflection_methodbuilder_from_dynamic_method (&rmb, mb);
11575
11576         /*
11577          * Resolve references.
11578          */
11579         /* 
11580          * Every second entry in the refs array is reserved for storing handle_class,
11581          * which is needed by the ldtoken implementation in the JIT.
11582          */
11583         rmb.nrefs = mb->nrefs;
11584         rmb.refs = g_new0 (gpointer, mb->nrefs + 1);
11585         for (i = 0; i < mb->nrefs; i += 2) {
11586                 MonoClass *handle_class;
11587                 gpointer ref;
11588                 MonoObject *obj = mono_array_get (mb->refs, MonoObject*, i);
11589
11590                 if (strcmp (obj->vtable->klass->name, "DynamicMethod") == 0) {
11591                         MonoReflectionDynamicMethod *method = (MonoReflectionDynamicMethod*)obj;
11592                         /*
11593                          * The referenced DynamicMethod should already be created by the managed
11594                          * code, except in the case of circular references. In that case, we store
11595                          * method in the refs array, and fix it up later when the referenced 
11596                          * DynamicMethod is created.
11597                          */
11598                         if (method->mhandle) {
11599                                 ref = method->mhandle;
11600                         } else {
11601                                 /* FIXME: GC object stored in unmanaged memory */
11602                                 ref = method;
11603
11604                                 /* FIXME: GC object stored in unmanaged memory */
11605                                 method->referenced_by = g_slist_append (method->referenced_by, mb);
11606                         }
11607                         handle_class = mono_defaults.methodhandle_class;
11608                 } else {
11609                         MonoException *ex = NULL;
11610                         ref = resolve_object (mb->module->image, obj, &handle_class, NULL);
11611                         if (!ref)
11612                                 ex = mono_get_exception_type_load (NULL, NULL);
11613                         else if (mono_security_core_clr_enabled ())
11614                                 ex = mono_security_core_clr_ensure_dynamic_method_resolved_object (ref, handle_class);
11615
11616                         if (ex) {
11617                                 g_free (rmb.refs);
11618                                 mono_raise_exception (ex);
11619                                 return;
11620                         }
11621                 }
11622
11623                 rmb.refs [i] = ref; /* FIXME: GC object stored in unmanaged memory (change also resolve_object() signature) */
11624                 rmb.refs [i + 1] = handle_class;
11625         }               
11626
11627         klass = mb->owner ? mono_class_from_mono_type (mono_reflection_type_get_handle ((MonoReflectionType*)mb->owner)) : mono_defaults.object_class;
11628
11629         mb->mhandle = handle = reflection_methodbuilder_to_mono_method (klass, &rmb, sig);
11630         release_data = g_new (DynamicMethodReleaseData, 1);
11631         release_data->handle = handle;
11632         release_data->domain = mono_object_get_domain ((MonoObject*)mb);
11633         if (!mono_gc_reference_queue_add (queue, (MonoObject*)mb, release_data))
11634                 g_free (release_data);
11635
11636         /* Fix up refs entries pointing at us */
11637         for (l = mb->referenced_by; l; l = l->next) {
11638                 MonoReflectionDynamicMethod *method = (MonoReflectionDynamicMethod*)l->data;
11639                 MonoMethodWrapper *wrapper = (MonoMethodWrapper*)method->mhandle;
11640                 gpointer *data;
11641                 
11642                 g_assert (method->mhandle);
11643
11644                 data = (gpointer*)wrapper->method_data;
11645                 for (i = 0; i < GPOINTER_TO_UINT (data [0]); i += 2) {
11646                         if ((data [i + 1] == mb) && (data [i + 1 + 1] == mono_defaults.methodhandle_class))
11647                                 data [i + 1] = mb->mhandle;
11648                 }
11649         }
11650         g_slist_free (mb->referenced_by);
11651
11652         g_free (rmb.refs);
11653
11654         /* ilgen is no longer needed */
11655         mb->ilgen = NULL;
11656 }
11657
11658 #endif /* DISABLE_REFLECTION_EMIT */
11659
11660 /**
11661  * 
11662  * mono_reflection_is_valid_dynamic_token:
11663  * 
11664  * Returns TRUE if token is valid.
11665  * 
11666  */
11667 gboolean
11668 mono_reflection_is_valid_dynamic_token (MonoDynamicImage *image, guint32 token)
11669 {
11670         return mono_g_hash_table_lookup (image->tokens, GUINT_TO_POINTER (token)) != NULL;
11671 }
11672
11673 MonoMethodSignature *
11674 mono_reflection_lookup_signature (MonoImage *image, MonoMethod *method, guint32 token)
11675 {
11676         MonoMethodSignature *sig;
11677         g_assert (image->dynamic);
11678
11679         sig = g_hash_table_lookup (((MonoDynamicImage*)image)->vararg_aux_hash, GUINT_TO_POINTER (token));
11680         if (sig)
11681                 return sig;
11682
11683         return mono_method_signature (method);
11684 }
11685
11686 #ifndef DISABLE_REFLECTION_EMIT
11687
11688 /**
11689  * mono_reflection_lookup_dynamic_token:
11690  *
11691  * Finish the Builder object pointed to by TOKEN and return the corresponding
11692  * runtime structure. If HANDLE_CLASS is not NULL, it is set to the class required by 
11693  * mono_ldtoken. If valid_token is TRUE, assert if it is not found in the token->object
11694  * mapping table.
11695  *
11696  * LOCKING: Take the loader lock
11697  */
11698 gpointer
11699 mono_reflection_lookup_dynamic_token (MonoImage *image, guint32 token, gboolean valid_token, MonoClass **handle_class, MonoGenericContext *context)
11700 {
11701         MonoDynamicImage *assembly = (MonoDynamicImage*)image;
11702         MonoObject *obj;
11703         MonoClass *klass;
11704
11705         mono_loader_lock ();
11706         obj = mono_g_hash_table_lookup (assembly->tokens, GUINT_TO_POINTER (token));
11707         mono_loader_unlock ();
11708         if (!obj) {
11709                 if (valid_token)
11710                         g_error ("Could not find required dynamic token 0x%08x", token);
11711                 else
11712                         return NULL;
11713         }
11714
11715         if (!handle_class)
11716                 handle_class = &klass;
11717         return resolve_object (image, obj, handle_class, context);
11718 }
11719
11720 /*
11721  * ensure_complete_type:
11722  *
11723  *   Ensure that KLASS is completed if it is a dynamic type, or references
11724  * dynamic types.
11725  */
11726 static void
11727 ensure_complete_type (MonoClass *klass)
11728 {
11729         if (klass->image->dynamic && !klass->wastypebuilder && mono_class_get_ref_info (klass)) {
11730                 MonoReflectionTypeBuilder *tb = mono_class_get_ref_info (klass);
11731
11732                 mono_domain_try_type_resolve (mono_domain_get (), NULL, (MonoObject*)tb);
11733
11734                 // Asserting here could break a lot of code
11735                 //g_assert (klass->wastypebuilder);
11736         }
11737
11738         if (klass->generic_class) {
11739                 MonoGenericInst *inst = klass->generic_class->context.class_inst;
11740                 int i;
11741
11742                 for (i = 0; i < inst->type_argc; ++i) {
11743                         ensure_complete_type (mono_class_from_mono_type (inst->type_argv [i]));
11744                 }
11745         }
11746 }
11747
11748 static gpointer
11749 resolve_object (MonoImage *image, MonoObject *obj, MonoClass **handle_class, MonoGenericContext *context)
11750 {
11751         gpointer result = NULL;
11752
11753         if (strcmp (obj->vtable->klass->name, "String") == 0) {
11754                 result = mono_string_intern ((MonoString*)obj);
11755                 *handle_class = mono_defaults.string_class;
11756                 g_assert (result);
11757         } else if (strcmp (obj->vtable->klass->name, "MonoType") == 0) {
11758                 MonoType *type = mono_reflection_type_get_handle ((MonoReflectionType*)obj);
11759                 MonoClass *mc = mono_class_from_mono_type (type);
11760                 if (!mono_class_init (mc))
11761                         mono_raise_exception (mono_class_get_exception_for_failure (mc));
11762
11763                 if (context) {
11764                         MonoType *inflated = mono_class_inflate_generic_type (type, context);
11765                         result = mono_class_from_mono_type (inflated);
11766                         mono_metadata_free_type (inflated);
11767                 } else {
11768                         result = mono_class_from_mono_type (type);
11769                 }
11770                 *handle_class = mono_defaults.typehandle_class;
11771                 g_assert (result);
11772         } else if (strcmp (obj->vtable->klass->name, "MonoMethod") == 0 ||
11773                    strcmp (obj->vtable->klass->name, "MonoCMethod") == 0 ||
11774                    strcmp (obj->vtable->klass->name, "MonoGenericCMethod") == 0 ||
11775                    strcmp (obj->vtable->klass->name, "MonoGenericMethod") == 0) {
11776                 result = ((MonoReflectionMethod*)obj)->method;
11777                 if (context)
11778                         result = mono_class_inflate_generic_method (result, context);
11779                 *handle_class = mono_defaults.methodhandle_class;
11780                 g_assert (result);
11781         } else if (strcmp (obj->vtable->klass->name, "MethodBuilder") == 0) {
11782                 MonoReflectionMethodBuilder *mb = (MonoReflectionMethodBuilder*)obj;
11783                 result = mb->mhandle;
11784                 if (!result) {
11785                         /* Type is not yet created */
11786                         MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder*)mb->type;
11787
11788                         mono_domain_try_type_resolve (mono_domain_get (), NULL, (MonoObject*)tb);
11789
11790                         /*
11791                          * Hopefully this has been filled in by calling CreateType() on the
11792                          * TypeBuilder.
11793                          */
11794                         /*
11795                          * TODO: This won't work if the application finishes another 
11796                          * TypeBuilder instance instead of this one.
11797                          */
11798                         result = mb->mhandle;
11799                 }
11800                 if (context)
11801                         result = mono_class_inflate_generic_method (result, context);
11802                 *handle_class = mono_defaults.methodhandle_class;
11803         } else if (strcmp (obj->vtable->klass->name, "ConstructorBuilder") == 0) {
11804                 MonoReflectionCtorBuilder *cb = (MonoReflectionCtorBuilder*)obj;
11805
11806                 result = cb->mhandle;
11807                 if (!result) {
11808                         MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder*)cb->type;
11809
11810                         mono_domain_try_type_resolve (mono_domain_get (), NULL, (MonoObject*)tb);
11811                         result = cb->mhandle;
11812                 }
11813                 if (context)
11814                         result = mono_class_inflate_generic_method (result, context);
11815                 *handle_class = mono_defaults.methodhandle_class;
11816         } else if (strcmp (obj->vtable->klass->name, "MonoField") == 0) {
11817                 MonoClassField *field = ((MonoReflectionField*)obj)->field;
11818
11819                 ensure_complete_type (field->parent);
11820                 if (context) {
11821                         MonoType *inflated = mono_class_inflate_generic_type (&field->parent->byval_arg, context);
11822                         MonoClass *class = mono_class_from_mono_type (inflated);
11823                         MonoClassField *inflated_field;
11824                         gpointer iter = NULL;
11825                         mono_metadata_free_type (inflated);
11826                         while ((inflated_field = mono_class_get_fields (class, &iter))) {
11827                                 if (!strcmp (field->name, inflated_field->name))
11828                                         break;
11829                         }
11830                         g_assert (inflated_field && !strcmp (field->name, inflated_field->name));
11831                         result = inflated_field;
11832                 } else {
11833                         result = field;
11834                 }
11835                 *handle_class = mono_defaults.fieldhandle_class;
11836                 g_assert (result);
11837         } else if (strcmp (obj->vtable->klass->name, "FieldBuilder") == 0) {
11838                 MonoReflectionFieldBuilder *fb = (MonoReflectionFieldBuilder*)obj;
11839                 result = fb->handle;
11840
11841                 if (!result) {
11842                         MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder*)fb->typeb;
11843
11844                         mono_domain_try_type_resolve (mono_domain_get (), NULL, (MonoObject*)tb);
11845                         result = fb->handle;
11846                 }
11847
11848                 if (fb->handle && fb->handle->parent->generic_container) {
11849                         MonoClass *klass = fb->handle->parent;
11850                         MonoType *type = mono_class_inflate_generic_type (&klass->byval_arg, context);
11851                         MonoClass *inflated = mono_class_from_mono_type (type);
11852
11853                         result = mono_class_get_field_from_name (inflated, mono_field_get_name (fb->handle));
11854                         g_assert (result);
11855                         mono_metadata_free_type (type);
11856                 }
11857                 *handle_class = mono_defaults.fieldhandle_class;
11858         } else if (strcmp (obj->vtable->klass->name, "TypeBuilder") == 0) {
11859                 MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder*)obj;
11860                 MonoType *type = mono_reflection_type_get_handle ((MonoReflectionType*)tb); 
11861                 MonoClass *klass;
11862
11863                 klass = type->data.klass;
11864                 if (klass->wastypebuilder) {
11865                         /* Already created */
11866                         result = klass;
11867                 }
11868                 else {
11869                         mono_domain_try_type_resolve (mono_domain_get (), NULL, (MonoObject*)tb);
11870                         result = type->data.klass;
11871                         g_assert (result);
11872                 }
11873                 *handle_class = mono_defaults.typehandle_class;
11874         } else if (strcmp (obj->vtable->klass->name, "SignatureHelper") == 0) {
11875                 MonoReflectionSigHelper *helper = (MonoReflectionSigHelper*)obj;
11876                 MonoMethodSignature *sig;
11877                 int nargs, i;
11878
11879                 if (helper->arguments)
11880                         nargs = mono_array_length (helper->arguments);
11881                 else
11882                         nargs = 0;
11883
11884                 sig = mono_metadata_signature_alloc (image, nargs);
11885                 sig->explicit_this = helper->call_conv & 64 ? 1 : 0;
11886                 sig->hasthis = helper->call_conv & 32 ? 1 : 0;
11887
11888                 if (helper->unmanaged_call_conv) { /* unmanaged */
11889                         sig->call_convention = helper->unmanaged_call_conv - 1;
11890                         sig->pinvoke = TRUE;
11891                 } else if (helper->call_conv & 0x02) {
11892                         sig->call_convention = MONO_CALL_VARARG;
11893                 } else {
11894                         sig->call_convention = MONO_CALL_DEFAULT;
11895                 }
11896
11897                 sig->param_count = nargs;
11898                 /* TODO: Copy type ? */
11899                 sig->ret = helper->return_type->type;
11900                 for (i = 0; i < nargs; ++i)
11901                         sig->params [i] = mono_type_array_get_and_resolve (helper->arguments, i);
11902
11903                 result = sig;
11904                 *handle_class = NULL;
11905         } else if (strcmp (obj->vtable->klass->name, "DynamicMethod") == 0) {
11906                 MonoReflectionDynamicMethod *method = (MonoReflectionDynamicMethod*)obj;
11907                 /* Already created by the managed code */
11908                 g_assert (method->mhandle);
11909                 result = method->mhandle;
11910                 *handle_class = mono_defaults.methodhandle_class;
11911         } else if (strcmp (obj->vtable->klass->name, "GenericTypeParameterBuilder") == 0) {
11912                 MonoType *type = mono_reflection_type_get_handle ((MonoReflectionType*)obj);
11913                 type = mono_class_inflate_generic_type (type, context);
11914                 result = mono_class_from_mono_type (type);
11915                 *handle_class = mono_defaults.typehandle_class;
11916                 g_assert (result);
11917                 mono_metadata_free_type (type);
11918         } else if (strcmp (obj->vtable->klass->name, "MonoGenericClass") == 0) {
11919                 MonoType *type = mono_reflection_type_get_handle ((MonoReflectionType*)obj);
11920                 type = mono_class_inflate_generic_type (type, context);
11921                 result = mono_class_from_mono_type (type);
11922                 *handle_class = mono_defaults.typehandle_class;
11923                 g_assert (result);
11924                 mono_metadata_free_type (type);
11925         } else if (strcmp (obj->vtable->klass->name, "FieldOnTypeBuilderInst") == 0) {
11926                 MonoReflectionFieldOnTypeBuilderInst *f = (MonoReflectionFieldOnTypeBuilderInst*)obj;
11927                 MonoClass *inflated;
11928                 MonoType *type;
11929                 MonoClassField *field;
11930
11931                 if (is_sre_field_builder (mono_object_class (f->fb)))
11932                         field = ((MonoReflectionFieldBuilder*)f->fb)->handle;
11933                 else if (is_sr_mono_field (mono_object_class (f->fb)))
11934                         field = ((MonoReflectionField*)f->fb)->field;
11935                 else
11936                         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)));
11937
11938                 type = mono_class_inflate_generic_type (mono_reflection_type_get_handle ((MonoReflectionType*)f->inst), context);
11939                 inflated = mono_class_from_mono_type (type);
11940
11941                 result = field = mono_class_get_field_from_name (inflated, mono_field_get_name (field));
11942                 ensure_complete_type (field->parent);
11943                 g_assert (result);
11944                 mono_metadata_free_type (type);
11945                 *handle_class = mono_defaults.fieldhandle_class;
11946         } else if (strcmp (obj->vtable->klass->name, "ConstructorOnTypeBuilderInst") == 0) {
11947                 MonoReflectionCtorOnTypeBuilderInst *c = (MonoReflectionCtorOnTypeBuilderInst*)obj;
11948                 MonoType *type = mono_class_inflate_generic_type (mono_reflection_type_get_handle ((MonoReflectionType*)c->inst), context);
11949                 MonoClass *inflated_klass = mono_class_from_mono_type (type);
11950                 MonoMethod *method;
11951
11952                 if (is_sre_ctor_builder (mono_object_class (c->cb)))
11953                         method = ((MonoReflectionCtorBuilder *)c->cb)->mhandle;
11954                 else if (is_sr_mono_cmethod (mono_object_class (c->cb)))
11955                         method = ((MonoReflectionMethod *)c->cb)->method;
11956                 else
11957                         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)));
11958
11959                 result = inflate_mono_method (inflated_klass, method, (MonoObject*)c->cb);
11960                 *handle_class = mono_defaults.methodhandle_class;
11961                 mono_metadata_free_type (type);
11962         } else if (strcmp (obj->vtable->klass->name, "MethodOnTypeBuilderInst") == 0) {
11963                 MonoReflectionMethodOnTypeBuilderInst *m = (MonoReflectionMethodOnTypeBuilderInst*)obj;
11964                 if (m->method_args) {
11965                         result = mono_reflection_method_on_tb_inst_get_handle (m);
11966                         if (context)
11967                                 result = mono_class_inflate_generic_method (result, context);
11968                 } else {
11969                         MonoType *type = mono_class_inflate_generic_type (mono_reflection_type_get_handle ((MonoReflectionType*)m->inst), context);
11970                         MonoClass *inflated_klass = mono_class_from_mono_type (type);
11971                         MonoMethod *method;
11972
11973                         if (is_sre_method_builder (mono_object_class (m->mb)))
11974                                 method = ((MonoReflectionMethodBuilder *)m->mb)->mhandle;
11975                         else if (is_sr_mono_method (mono_object_class (m->mb)))
11976                                 method = ((MonoReflectionMethod *)m->mb)->method;
11977                         else
11978                                 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)));
11979
11980                         result = inflate_mono_method (inflated_klass, method, (MonoObject*)m->mb);
11981                         mono_metadata_free_type (type);
11982                 }
11983                 *handle_class = mono_defaults.methodhandle_class;
11984         } else if (strcmp (obj->vtable->klass->name, "MonoArrayMethod") == 0) {
11985                 MonoReflectionArrayMethod *m = (MonoReflectionArrayMethod*)obj;
11986                 MonoType *mtype;
11987                 MonoClass *klass;
11988                 MonoMethod *method;
11989                 gpointer iter;
11990                 char *name;
11991
11992                 mtype = mono_reflection_type_get_handle (m->parent);
11993                 klass = mono_class_from_mono_type (mtype);
11994
11995                 /* Find the method */
11996
11997                 name = mono_string_to_utf8 (m->name);
11998                 iter = NULL;
11999                 while ((method = mono_class_get_methods (klass, &iter))) {
12000                         if (!strcmp (method->name, name))
12001                                 break;
12002                 }
12003                 g_free (name);
12004
12005                 // FIXME:
12006                 g_assert (method);
12007                 // FIXME: Check parameters/return value etc. match
12008
12009                 result = method;
12010                 *handle_class = mono_defaults.methodhandle_class;
12011         } else if (is_sre_array (mono_object_get_class(obj)) ||
12012                                 is_sre_byref (mono_object_get_class(obj)) ||
12013                                 is_sre_pointer (mono_object_get_class(obj))) {
12014                 MonoReflectionType *ref_type = (MonoReflectionType *)obj;
12015                 MonoType *type = mono_reflection_type_get_handle (ref_type);
12016
12017                 if (context) {
12018                         MonoType *inflated = mono_class_inflate_generic_type (type, context);
12019                         result = mono_class_from_mono_type (inflated);
12020                         mono_metadata_free_type (inflated);
12021                 } else {
12022                         result = mono_class_from_mono_type (type);
12023                 }
12024                 *handle_class = mono_defaults.typehandle_class;
12025         } else {
12026                 g_print ("%s\n", obj->vtable->klass->name);
12027                 g_assert_not_reached ();
12028         }
12029         return result;
12030 }
12031
12032 #else /* DISABLE_REFLECTION_EMIT */
12033
12034 MonoArray*
12035 mono_reflection_get_custom_attrs_blob (MonoReflectionAssembly *assembly, MonoObject *ctor, MonoArray *ctorArgs, MonoArray *properties, MonoArray *propValues, MonoArray *fields, MonoArray* fieldValues) 
12036 {
12037         g_assert_not_reached ();
12038         return NULL;
12039 }
12040
12041 void
12042 mono_reflection_setup_internal_class (MonoReflectionTypeBuilder *tb)
12043 {
12044         g_assert_not_reached ();
12045 }
12046
12047 void
12048 mono_reflection_setup_generic_class (MonoReflectionTypeBuilder *tb)
12049 {
12050         g_assert_not_reached ();
12051 }
12052
12053 void
12054 mono_reflection_create_generic_class (MonoReflectionTypeBuilder *tb)
12055 {
12056         g_assert_not_reached ();
12057 }
12058
12059 void
12060 mono_reflection_create_internal_class (MonoReflectionTypeBuilder *tb)
12061 {
12062         g_assert_not_reached ();
12063 }
12064
12065 void
12066 mono_image_basic_init (MonoReflectionAssemblyBuilder *assemblyb)
12067 {
12068         g_error ("This mono runtime was configured with --enable-minimal=reflection_emit, so System.Reflection.Emit is not supported.");
12069 }
12070
12071 void
12072 mono_image_module_basic_init (MonoReflectionModuleBuilder *moduleb)
12073 {
12074         g_assert_not_reached ();
12075 }
12076
12077 void
12078 mono_image_set_wrappers_type (MonoReflectionModuleBuilder *moduleb, MonoReflectionType *type)
12079 {
12080         g_assert_not_reached ();
12081 }
12082
12083 MonoReflectionModule *
12084 mono_image_load_module_dynamic (MonoReflectionAssemblyBuilder *ab, MonoString *fileName)
12085 {
12086         g_assert_not_reached ();
12087         return NULL;
12088 }
12089
12090 guint32
12091 mono_image_insert_string (MonoReflectionModuleBuilder *module, MonoString *str)
12092 {
12093         g_assert_not_reached ();
12094         return 0;
12095 }
12096
12097 guint32
12098 mono_image_create_method_token (MonoDynamicImage *assembly, MonoObject *obj, MonoArray *opt_param_types)
12099 {
12100         g_assert_not_reached ();
12101         return 0;
12102 }
12103
12104 guint32
12105 mono_image_create_token (MonoDynamicImage *assembly, MonoObject *obj, 
12106                                                  gboolean create_open_instance, gboolean register_token)
12107 {
12108         g_assert_not_reached ();
12109         return 0;
12110 }
12111
12112 void
12113 mono_image_register_token (MonoDynamicImage *assembly, guint32 token, MonoObject *obj)
12114 {
12115 }
12116
12117 void
12118 mono_reflection_generic_class_initialize (MonoReflectionGenericClass *type, MonoArray *fields)
12119 {
12120         g_assert_not_reached ();
12121 }
12122
12123 void
12124 mono_reflection_get_dynamic_overrides (MonoClass *klass, MonoMethod ***overrides, int *num_overrides)
12125 {
12126         *overrides = NULL;
12127         *num_overrides = 0;
12128 }
12129
12130 MonoReflectionEvent *
12131 mono_reflection_event_builder_get_event_info (MonoReflectionTypeBuilder *tb, MonoReflectionEventBuilder *eb)
12132 {
12133         g_assert_not_reached ();
12134         return NULL;
12135 }
12136
12137 MonoReflectionType*
12138 mono_reflection_create_runtime_class (MonoReflectionTypeBuilder *tb)
12139 {
12140         g_assert_not_reached ();
12141         return NULL;
12142 }
12143
12144 void
12145 mono_reflection_initialize_generic_parameter (MonoReflectionGenericParam *gparam)
12146 {
12147         g_assert_not_reached ();
12148 }
12149
12150 MonoArray *
12151 mono_reflection_sighelper_get_signature_local (MonoReflectionSigHelper *sig)
12152 {
12153         g_assert_not_reached ();
12154         return NULL;
12155 }
12156
12157 MonoArray *
12158 mono_reflection_sighelper_get_signature_field (MonoReflectionSigHelper *sig)
12159 {
12160         g_assert_not_reached ();
12161         return NULL;
12162 }
12163
12164 void 
12165 mono_reflection_create_dynamic_method (MonoReflectionDynamicMethod *mb)
12166 {
12167 }
12168
12169 gpointer
12170 mono_reflection_lookup_dynamic_token (MonoImage *image, guint32 token, gboolean valid_token, MonoClass **handle_class, MonoGenericContext *context)
12171 {
12172         return NULL;
12173 }
12174
12175 MonoType*
12176 mono_reflection_type_get_handle (MonoReflectionType* ref)
12177 {
12178         if (!ref)
12179                 return NULL;
12180         return ref->type;
12181 }
12182
12183 void
12184 mono_reflection_free_dynamic_generic_class (MonoGenericClass *gclass)
12185 {
12186         g_assert_not_reached ();
12187 }
12188
12189 #endif /* DISABLE_REFLECTION_EMIT */
12190
12191 /* SECURITY_ACTION_* are defined in mono/metadata/tabledefs.h */
12192 const static guint32 declsec_flags_map[] = {
12193         0x00000000,                                     /* empty */
12194         MONO_DECLSEC_FLAG_REQUEST,                      /* SECURITY_ACTION_REQUEST                      (x01) */
12195         MONO_DECLSEC_FLAG_DEMAND,                       /* SECURITY_ACTION_DEMAND                       (x02) */
12196         MONO_DECLSEC_FLAG_ASSERT,                       /* SECURITY_ACTION_ASSERT                       (x03) */
12197         MONO_DECLSEC_FLAG_DENY,                         /* SECURITY_ACTION_DENY                         (x04) */
12198         MONO_DECLSEC_FLAG_PERMITONLY,                   /* SECURITY_ACTION_PERMITONLY                   (x05) */
12199         MONO_DECLSEC_FLAG_LINKDEMAND,                   /* SECURITY_ACTION_LINKDEMAND                   (x06) */
12200         MONO_DECLSEC_FLAG_INHERITANCEDEMAND,            /* SECURITY_ACTION_INHERITANCEDEMAND            (x07) */
12201         MONO_DECLSEC_FLAG_REQUEST_MINIMUM,              /* SECURITY_ACTION_REQUEST_MINIMUM              (x08) */
12202         MONO_DECLSEC_FLAG_REQUEST_OPTIONAL,             /* SECURITY_ACTION_REQUEST_OPTIONAL             (x09) */
12203         MONO_DECLSEC_FLAG_REQUEST_REFUSE,               /* SECURITY_ACTION_REQUEST_REFUSE               (x0A) */
12204         MONO_DECLSEC_FLAG_PREJIT_GRANT,                 /* SECURITY_ACTION_PREJIT_GRANT                 (x0B) */
12205         MONO_DECLSEC_FLAG_PREJIT_DENY,                  /* SECURITY_ACTION_PREJIT_DENY                  (x0C) */
12206         MONO_DECLSEC_FLAG_NONCAS_DEMAND,                /* SECURITY_ACTION_NONCAS_DEMAND                (x0D) */
12207         MONO_DECLSEC_FLAG_NONCAS_LINKDEMAND,            /* SECURITY_ACTION_NONCAS_LINKDEMAND            (x0E) */
12208         MONO_DECLSEC_FLAG_NONCAS_INHERITANCEDEMAND,     /* SECURITY_ACTION_NONCAS_INHERITANCEDEMAND     (x0F) */
12209         MONO_DECLSEC_FLAG_LINKDEMAND_CHOICE,            /* SECURITY_ACTION_LINKDEMAND_CHOICE            (x10) */
12210         MONO_DECLSEC_FLAG_INHERITANCEDEMAND_CHOICE,     /* SECURITY_ACTION_INHERITANCEDEMAND_CHOICE     (x11) */
12211         MONO_DECLSEC_FLAG_DEMAND_CHOICE,                /* SECURITY_ACTION_DEMAND_CHOICE                (x12) */
12212 };
12213
12214 /*
12215  * Returns flags that includes all available security action associated to the handle.
12216  * @token: metadata token (either for a class or a method)
12217  * @image: image where resides the metadata.
12218  */
12219 static guint32
12220 mono_declsec_get_flags (MonoImage *image, guint32 token)
12221 {
12222         int index = mono_metadata_declsec_from_index (image, token);
12223         MonoTableInfo *t = &image->tables [MONO_TABLE_DECLSECURITY];
12224         guint32 result = 0;
12225         guint32 action;
12226         int i;
12227
12228         /* HasSecurity can be present for other, not specially encoded, attributes,
12229            e.g. SuppressUnmanagedCodeSecurityAttribute */
12230         if (index < 0)
12231                 return 0;
12232
12233         for (i = index; i < t->rows; i++) {
12234                 guint32 cols [MONO_DECL_SECURITY_SIZE];
12235
12236                 mono_metadata_decode_row (t, i, cols, MONO_DECL_SECURITY_SIZE);
12237                 if (cols [MONO_DECL_SECURITY_PARENT] != token)
12238                         break;
12239
12240                 action = cols [MONO_DECL_SECURITY_ACTION];
12241                 if ((action >= MONO_DECLSEC_ACTION_MIN) && (action <= MONO_DECLSEC_ACTION_MAX)) {
12242                         result |= declsec_flags_map [action];
12243                 } else {
12244                         g_assert_not_reached ();
12245                 }
12246         }
12247         return result;
12248 }
12249
12250 /*
12251  * Get the security actions (in the form of flags) associated with the specified method.
12252  *
12253  * @method: The method for which we want the declarative security flags.
12254  * Return the declarative security flags for the method (only).
12255  *
12256  * Note: To keep MonoMethod size down we do not cache the declarative security flags
12257  *       (except for the stack modifiers which are kept in the MonoJitInfo structure)
12258  */
12259 guint32
12260 mono_declsec_flags_from_method (MonoMethod *method)
12261 {
12262         if (method->flags & METHOD_ATTRIBUTE_HAS_SECURITY) {
12263                 /* FIXME: No cache (for the moment) */
12264                 guint32 idx = mono_method_get_index (method);
12265                 idx <<= MONO_HAS_DECL_SECURITY_BITS;
12266                 idx |= MONO_HAS_DECL_SECURITY_METHODDEF;
12267                 return mono_declsec_get_flags (method->klass->image, idx);
12268         }
12269         return 0;
12270 }
12271
12272 /*
12273  * Get the security actions (in the form of flags) associated with the specified class.
12274  *
12275  * @klass: The class for which we want the declarative security flags.
12276  * Return the declarative security flags for the class.
12277  *
12278  * Note: We cache the flags inside the MonoClass structure as this will get 
12279  *       called very often (at least for each method).
12280  */
12281 guint32
12282 mono_declsec_flags_from_class (MonoClass *klass)
12283 {
12284         if (klass->flags & TYPE_ATTRIBUTE_HAS_SECURITY) {
12285                 if (!klass->ext || !klass->ext->declsec_flags) {
12286                         guint32 idx;
12287
12288                         idx = mono_metadata_token_index (klass->type_token);
12289                         idx <<= MONO_HAS_DECL_SECURITY_BITS;
12290                         idx |= MONO_HAS_DECL_SECURITY_TYPEDEF;
12291                         mono_loader_lock ();
12292                         mono_class_alloc_ext (klass);
12293                         mono_loader_unlock ();
12294                         /* we cache the flags on classes */
12295                         klass->ext->declsec_flags = mono_declsec_get_flags (klass->image, idx);
12296                 }
12297                 return klass->ext->declsec_flags;
12298         }
12299         return 0;
12300 }
12301
12302 /*
12303  * Get the security actions (in the form of flags) associated with the specified assembly.
12304  *
12305  * @assembly: The assembly for which we want the declarative security flags.
12306  * Return the declarative security flags for the assembly.
12307  */
12308 guint32
12309 mono_declsec_flags_from_assembly (MonoAssembly *assembly)
12310 {
12311         guint32 idx = 1; /* there is only one assembly */
12312         idx <<= MONO_HAS_DECL_SECURITY_BITS;
12313         idx |= MONO_HAS_DECL_SECURITY_ASSEMBLY;
12314         return mono_declsec_get_flags (assembly->image, idx);
12315 }
12316
12317
12318 /*
12319  * Fill actions for the specific index (which may either be an encoded class token or
12320  * an encoded method token) from the metadata image.
12321  * Returns TRUE if some actions requiring code generation are present, FALSE otherwise.
12322  */
12323 static MonoBoolean
12324 fill_actions_from_index (MonoImage *image, guint32 token, MonoDeclSecurityActions* actions,
12325         guint32 id_std, guint32 id_noncas, guint32 id_choice)
12326 {
12327         MonoBoolean result = FALSE;
12328         MonoTableInfo *t;
12329         guint32 cols [MONO_DECL_SECURITY_SIZE];
12330         int index = mono_metadata_declsec_from_index (image, token);
12331         int i;
12332
12333         t  = &image->tables [MONO_TABLE_DECLSECURITY];
12334         for (i = index; i < t->rows; i++) {
12335                 mono_metadata_decode_row (t, i, cols, MONO_DECL_SECURITY_SIZE);
12336
12337                 if (cols [MONO_DECL_SECURITY_PARENT] != token)
12338                         return result;
12339
12340                 /* if present only replace (class) permissions with method permissions */
12341                 /* if empty accept either class or method permissions */
12342                 if (cols [MONO_DECL_SECURITY_ACTION] == id_std) {
12343                         if (!actions->demand.blob) {
12344                                 const char *blob = mono_metadata_blob_heap (image, cols [MONO_DECL_SECURITY_PERMISSIONSET]);
12345                                 actions->demand.index = cols [MONO_DECL_SECURITY_PERMISSIONSET];
12346                                 actions->demand.blob = (char*) (blob + 2);
12347                                 actions->demand.size = mono_metadata_decode_blob_size (blob, &blob);
12348                                 result = TRUE;
12349                         }
12350                 } else if (cols [MONO_DECL_SECURITY_ACTION] == id_noncas) {
12351                         if (!actions->noncasdemand.blob) {
12352                                 const char *blob = mono_metadata_blob_heap (image, cols [MONO_DECL_SECURITY_PERMISSIONSET]);
12353                                 actions->noncasdemand.index = cols [MONO_DECL_SECURITY_PERMISSIONSET];
12354                                 actions->noncasdemand.blob = (char*) (blob + 2);
12355                                 actions->noncasdemand.size = mono_metadata_decode_blob_size (blob, &blob);
12356                                 result = TRUE;
12357                         }
12358                 } else if (cols [MONO_DECL_SECURITY_ACTION] == id_choice) {
12359                         if (!actions->demandchoice.blob) {
12360                                 const char *blob = mono_metadata_blob_heap (image, cols [MONO_DECL_SECURITY_PERMISSIONSET]);
12361                                 actions->demandchoice.index = cols [MONO_DECL_SECURITY_PERMISSIONSET];
12362                                 actions->demandchoice.blob = (char*) (blob + 2);
12363                                 actions->demandchoice.size = mono_metadata_decode_blob_size (blob, &blob);
12364                                 result = TRUE;
12365                         }
12366                 }
12367         }
12368
12369         return result;
12370 }
12371
12372 static MonoBoolean
12373 mono_declsec_get_class_demands_params (MonoClass *klass, MonoDeclSecurityActions* demands, 
12374         guint32 id_std, guint32 id_noncas, guint32 id_choice)
12375 {
12376         guint32 idx = mono_metadata_token_index (klass->type_token);
12377         idx <<= MONO_HAS_DECL_SECURITY_BITS;
12378         idx |= MONO_HAS_DECL_SECURITY_TYPEDEF;
12379         return fill_actions_from_index (klass->image, idx, demands, id_std, id_noncas, id_choice);
12380 }
12381
12382 static MonoBoolean
12383 mono_declsec_get_method_demands_params (MonoMethod *method, MonoDeclSecurityActions* demands, 
12384         guint32 id_std, guint32 id_noncas, guint32 id_choice)
12385 {
12386         guint32 idx = mono_method_get_index (method);
12387         idx <<= MONO_HAS_DECL_SECURITY_BITS;
12388         idx |= MONO_HAS_DECL_SECURITY_METHODDEF;
12389         return fill_actions_from_index (method->klass->image, idx, demands, id_std, id_noncas, id_choice);
12390 }
12391
12392 /*
12393  * Collect all actions (that requires to generate code in mini) assigned for
12394  * the specified method.
12395  * Note: Don't use the content of actions if the function return FALSE.
12396  */
12397 MonoBoolean
12398 mono_declsec_get_demands (MonoMethod *method, MonoDeclSecurityActions* demands)
12399 {
12400         guint32 mask = MONO_DECLSEC_FLAG_DEMAND | MONO_DECLSEC_FLAG_NONCAS_DEMAND | 
12401                 MONO_DECLSEC_FLAG_DEMAND_CHOICE;
12402         MonoBoolean result = FALSE;
12403         guint32 flags;
12404
12405         /* quick exit if no declarative security is present in the metadata */
12406         if (!method->klass->image->tables [MONO_TABLE_DECLSECURITY].rows)
12407                 return FALSE;
12408
12409         /* we want the original as the wrapper is "free" of the security informations */
12410         if (method->wrapper_type == MONO_WRAPPER_MANAGED_TO_NATIVE || method->wrapper_type == MONO_WRAPPER_MANAGED_TO_MANAGED) {
12411                 method = mono_marshal_method_from_wrapper (method);
12412                 if (!method)
12413                         return FALSE;
12414         }
12415
12416         /* First we look for method-level attributes */
12417         if (method->flags & METHOD_ATTRIBUTE_HAS_SECURITY) {
12418                 mono_class_init (method->klass);
12419                 memset (demands, 0, sizeof (MonoDeclSecurityActions));
12420
12421                 result = mono_declsec_get_method_demands_params (method, demands, 
12422                         SECURITY_ACTION_DEMAND, SECURITY_ACTION_NONCASDEMAND, SECURITY_ACTION_DEMANDCHOICE);
12423         }
12424
12425         /* Here we use (or create) the class declarative cache to look for demands */
12426         flags = mono_declsec_flags_from_class (method->klass);
12427         if (flags & mask) {
12428                 if (!result) {
12429                         mono_class_init (method->klass);
12430                         memset (demands, 0, sizeof (MonoDeclSecurityActions));
12431                 }
12432                 result |= mono_declsec_get_class_demands_params (method->klass, demands, 
12433                         SECURITY_ACTION_DEMAND, SECURITY_ACTION_NONCASDEMAND, SECURITY_ACTION_DEMANDCHOICE);
12434         }
12435
12436         /* The boolean return value is used as a shortcut in case nothing needs to
12437            be generated (e.g. LinkDemand[Choice] and InheritanceDemand[Choice]) */
12438         return result;
12439 }
12440
12441
12442 /*
12443  * Collect all Link actions: LinkDemand, NonCasLinkDemand and LinkDemandChoice (2.0).
12444  *
12445  * Note: Don't use the content of actions if the function return FALSE.
12446  */
12447 MonoBoolean
12448 mono_declsec_get_linkdemands (MonoMethod *method, MonoDeclSecurityActions* klass, MonoDeclSecurityActions *cmethod)
12449 {
12450         MonoBoolean result = FALSE;
12451         guint32 flags;
12452
12453         /* quick exit if no declarative security is present in the metadata */
12454         if (!method->klass->image->tables [MONO_TABLE_DECLSECURITY].rows)
12455                 return FALSE;
12456
12457         /* we want the original as the wrapper is "free" of the security informations */
12458         if (method->wrapper_type == MONO_WRAPPER_MANAGED_TO_NATIVE || method->wrapper_type == MONO_WRAPPER_MANAGED_TO_MANAGED) {
12459                 method = mono_marshal_method_from_wrapper (method);
12460                 if (!method)
12461                         return FALSE;
12462         }
12463
12464         /* results are independant - zeroize both */
12465         memset (cmethod, 0, sizeof (MonoDeclSecurityActions));
12466         memset (klass, 0, sizeof (MonoDeclSecurityActions));
12467
12468         /* First we look for method-level attributes */
12469         if (method->flags & METHOD_ATTRIBUTE_HAS_SECURITY) {
12470                 mono_class_init (method->klass);
12471
12472                 result = mono_declsec_get_method_demands_params (method, cmethod, 
12473                         SECURITY_ACTION_LINKDEMAND, SECURITY_ACTION_NONCASLINKDEMAND, SECURITY_ACTION_LINKDEMANDCHOICE);
12474         }
12475
12476         /* Here we use (or create) the class declarative cache to look for demands */
12477         flags = mono_declsec_flags_from_class (method->klass);
12478         if (flags & (MONO_DECLSEC_FLAG_LINKDEMAND | MONO_DECLSEC_FLAG_NONCAS_LINKDEMAND | MONO_DECLSEC_FLAG_LINKDEMAND_CHOICE)) {
12479                 mono_class_init (method->klass);
12480
12481                 result |= mono_declsec_get_class_demands_params (method->klass, klass, 
12482                         SECURITY_ACTION_LINKDEMAND, SECURITY_ACTION_NONCASLINKDEMAND, SECURITY_ACTION_LINKDEMANDCHOICE);
12483         }
12484
12485         return result;
12486 }
12487
12488 /*
12489  * Collect all Inherit actions: InheritanceDemand, NonCasInheritanceDemand and InheritanceDemandChoice (2.0).
12490  *
12491  * @klass       The inherited class - this is the class that provides the security check (attributes)
12492  * @demans      
12493  * return TRUE if inheritance demands (any kind) are present, FALSE otherwise.
12494  * 
12495  * Note: Don't use the content of actions if the function return FALSE.
12496  */
12497 MonoBoolean
12498 mono_declsec_get_inheritdemands_class (MonoClass *klass, MonoDeclSecurityActions* demands)
12499 {
12500         MonoBoolean result = FALSE;
12501         guint32 flags;
12502
12503         /* quick exit if no declarative security is present in the metadata */
12504         if (!klass->image->tables [MONO_TABLE_DECLSECURITY].rows)
12505                 return FALSE;
12506
12507         /* Here we use (or create) the class declarative cache to look for demands */
12508         flags = mono_declsec_flags_from_class (klass);
12509         if (flags & (MONO_DECLSEC_FLAG_INHERITANCEDEMAND | MONO_DECLSEC_FLAG_NONCAS_INHERITANCEDEMAND | MONO_DECLSEC_FLAG_INHERITANCEDEMAND_CHOICE)) {
12510                 mono_class_init (klass);
12511                 memset (demands, 0, sizeof (MonoDeclSecurityActions));
12512
12513                 result |= mono_declsec_get_class_demands_params (klass, demands, 
12514                         SECURITY_ACTION_INHERITDEMAND, SECURITY_ACTION_NONCASINHERITANCE, SECURITY_ACTION_INHERITDEMANDCHOICE);
12515         }
12516
12517         return result;
12518 }
12519
12520 /*
12521  * Collect all Inherit actions: InheritanceDemand, NonCasInheritanceDemand and InheritanceDemandChoice (2.0).
12522  *
12523  * Note: Don't use the content of actions if the function return FALSE.
12524  */
12525 MonoBoolean
12526 mono_declsec_get_inheritdemands_method (MonoMethod *method, MonoDeclSecurityActions* demands)
12527 {
12528         /* quick exit if no declarative security is present in the metadata */
12529         if (!method->klass->image->tables [MONO_TABLE_DECLSECURITY].rows)
12530                 return FALSE;
12531
12532         /* we want the original as the wrapper is "free" of the security informations */
12533         if (method->wrapper_type == MONO_WRAPPER_MANAGED_TO_NATIVE || method->wrapper_type == MONO_WRAPPER_MANAGED_TO_MANAGED) {
12534                 method = mono_marshal_method_from_wrapper (method);
12535                 if (!method)
12536                         return FALSE;
12537         }
12538
12539         if (method->flags & METHOD_ATTRIBUTE_HAS_SECURITY) {
12540                 mono_class_init (method->klass);
12541                 memset (demands, 0, sizeof (MonoDeclSecurityActions));
12542
12543                 return mono_declsec_get_method_demands_params (method, demands, 
12544                         SECURITY_ACTION_INHERITDEMAND, SECURITY_ACTION_NONCASINHERITANCE, SECURITY_ACTION_INHERITDEMANDCHOICE);
12545         }
12546         return FALSE;
12547 }
12548
12549
12550 static MonoBoolean
12551 get_declsec_action (MonoImage *image, guint32 token, guint32 action, MonoDeclSecurityEntry *entry)
12552 {
12553         guint32 cols [MONO_DECL_SECURITY_SIZE];
12554         MonoTableInfo *t;
12555         int i;
12556
12557         int index = mono_metadata_declsec_from_index (image, token);
12558         if (index == -1)
12559                 return FALSE;
12560
12561         t =  &image->tables [MONO_TABLE_DECLSECURITY];
12562         for (i = index; i < t->rows; i++) {
12563                 mono_metadata_decode_row (t, i, cols, MONO_DECL_SECURITY_SIZE);
12564
12565                 /* shortcut - index are ordered */
12566                 if (token != cols [MONO_DECL_SECURITY_PARENT])
12567                         return FALSE;
12568
12569                 if (cols [MONO_DECL_SECURITY_ACTION] == action) {
12570                         const char *metadata = mono_metadata_blob_heap (image, cols [MONO_DECL_SECURITY_PERMISSIONSET]);
12571                         entry->blob = (char*) (metadata + 2);
12572                         entry->size = mono_metadata_decode_blob_size (metadata, &metadata);
12573                         return TRUE;
12574                 }
12575         }
12576
12577         return FALSE;
12578 }
12579
12580 MonoBoolean
12581 mono_declsec_get_method_action (MonoMethod *method, guint32 action, MonoDeclSecurityEntry *entry)
12582 {
12583         if (method->flags & METHOD_ATTRIBUTE_HAS_SECURITY) {
12584                 guint32 idx = mono_method_get_index (method);
12585                 idx <<= MONO_HAS_DECL_SECURITY_BITS;
12586                 idx |= MONO_HAS_DECL_SECURITY_METHODDEF;
12587                 return get_declsec_action (method->klass->image, idx, action, entry);
12588         }
12589         return FALSE;
12590 }
12591
12592 MonoBoolean
12593 mono_declsec_get_class_action (MonoClass *klass, guint32 action, MonoDeclSecurityEntry *entry)
12594 {
12595         /* use cache */
12596         guint32 flags = mono_declsec_flags_from_class (klass);
12597         if (declsec_flags_map [action] & flags) {
12598                 guint32 idx = mono_metadata_token_index (klass->type_token);
12599                 idx <<= MONO_HAS_DECL_SECURITY_BITS;
12600                 idx |= MONO_HAS_DECL_SECURITY_TYPEDEF;
12601                 return get_declsec_action (klass->image, idx, action, entry);
12602         }
12603         return FALSE;
12604 }
12605
12606 MonoBoolean
12607 mono_declsec_get_assembly_action (MonoAssembly *assembly, guint32 action, MonoDeclSecurityEntry *entry)
12608 {
12609         guint32 idx = 1; /* there is only one assembly */
12610         idx <<= MONO_HAS_DECL_SECURITY_BITS;
12611         idx |= MONO_HAS_DECL_SECURITY_ASSEMBLY;
12612
12613         return get_declsec_action (assembly->image, idx, action, entry);
12614 }
12615
12616 gboolean
12617 mono_reflection_call_is_assignable_to (MonoClass *klass, MonoClass *oklass)
12618 {
12619         MonoObject *res, *exc;
12620         void *params [1];
12621         static MonoClass *System_Reflection_Emit_TypeBuilder = NULL;
12622         static MonoMethod *method = NULL;
12623
12624         if (!System_Reflection_Emit_TypeBuilder) {
12625                 System_Reflection_Emit_TypeBuilder = mono_class_from_name (mono_defaults.corlib, "System.Reflection.Emit", "TypeBuilder");
12626                 g_assert (System_Reflection_Emit_TypeBuilder);
12627         }
12628         if (method == NULL) {
12629                 method = mono_class_get_method_from_name (System_Reflection_Emit_TypeBuilder, "IsAssignableTo", 1);
12630                 g_assert (method);
12631         }
12632
12633         /* 
12634          * The result of mono_type_get_object () might be a System.MonoType but we
12635          * need a TypeBuilder so use mono_class_get_ref_info (klass).
12636          */
12637         g_assert (mono_class_get_ref_info (klass));
12638         g_assert (!strcmp (((MonoObject*)(mono_class_get_ref_info (klass)))->vtable->klass->name, "TypeBuilder"));
12639
12640         params [0] = mono_type_get_object (mono_domain_get (), &oklass->byval_arg);
12641
12642         res = mono_runtime_invoke (method, (MonoObject*)(mono_class_get_ref_info (klass)), params, &exc);
12643         if (exc)
12644                 return FALSE;
12645         else
12646                 return *(MonoBoolean*)mono_object_unbox (res);
12647 }
12648
12649 /**
12650  * mono_reflection_type_get_type:
12651  * @reftype: the System.Type object
12652  *
12653  * Returns the MonoType* associated with the C# System.Type object @reftype.
12654  */
12655 MonoType*
12656 mono_reflection_type_get_type (MonoReflectionType *reftype)
12657 {
12658         g_assert (reftype);
12659
12660         return mono_reflection_type_get_handle (reftype);
12661 }
12662