Merge pull request #950 from ermshiperete/bug-xamarin-2787
[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 void
5260 mono_dynamic_image_free_image (MonoDynamicImage *image)
5261 {
5262         /* See create_dynamic_mono_image () */
5263 #if HAVE_BOEHM_GC
5264         /* Allocated using GC_MALLOC */
5265 #else
5266         g_free (image);
5267 #endif
5268 }
5269
5270 #ifndef DISABLE_REFLECTION_EMIT
5271
5272 /*
5273  * mono_image_basic_init:
5274  * @assembly: an assembly builder object
5275  *
5276  * Create the MonoImage that represents the assembly builder and setup some
5277  * of the helper hash table and the basic metadata streams.
5278  */
5279 void
5280 mono_image_basic_init (MonoReflectionAssemblyBuilder *assemblyb)
5281 {
5282         MonoDynamicAssembly *assembly;
5283         MonoDynamicImage *image;
5284         MonoDomain *domain = mono_object_domain (assemblyb);
5285         
5286         MONO_ARCH_SAVE_REGS;
5287
5288         if (assemblyb->dynamic_assembly)
5289                 return;
5290
5291 #if HAVE_BOEHM_GC
5292         /* assembly->assembly.image might be GC allocated */
5293         assembly = assemblyb->dynamic_assembly = GC_MALLOC (sizeof (MonoDynamicAssembly));
5294 #else
5295         assembly = assemblyb->dynamic_assembly = g_new0 (MonoDynamicAssembly, 1);
5296 #endif
5297
5298         mono_profiler_assembly_event (&assembly->assembly, MONO_PROFILE_START_LOAD);
5299         
5300         assembly->assembly.ref_count = 1;
5301         assembly->assembly.dynamic = TRUE;
5302         assembly->assembly.corlib_internal = assemblyb->corlib_internal;
5303         assemblyb->assembly.assembly = (MonoAssembly*)assembly;
5304         assembly->assembly.basedir = mono_string_to_utf8 (assemblyb->dir);
5305         if (assemblyb->culture)
5306                 assembly->assembly.aname.culture = mono_string_to_utf8 (assemblyb->culture);
5307         else
5308                 assembly->assembly.aname.culture = g_strdup ("");
5309
5310         if (assemblyb->version) {
5311                         char *vstr = mono_string_to_utf8 (assemblyb->version);
5312                         char **version = g_strsplit (vstr, ".", 4);
5313                         char **parts = version;
5314                         assembly->assembly.aname.major = atoi (*parts++);
5315                         assembly->assembly.aname.minor = atoi (*parts++);
5316                         assembly->assembly.aname.build = *parts != NULL ? atoi (*parts++) : 0;
5317                         assembly->assembly.aname.revision = *parts != NULL ? atoi (*parts) : 0;
5318
5319                         g_strfreev (version);
5320                         g_free (vstr);
5321         } else {
5322                         assembly->assembly.aname.major = 0;
5323                         assembly->assembly.aname.minor = 0;
5324                         assembly->assembly.aname.build = 0;
5325                         assembly->assembly.aname.revision = 0;
5326         }
5327
5328         assembly->run = assemblyb->access != 2;
5329         assembly->save = assemblyb->access != 1;
5330         assembly->domain = domain;
5331
5332         image = create_dynamic_mono_image (assembly, mono_string_to_utf8 (assemblyb->name), g_strdup ("RefEmit_YouForgotToDefineAModule"));
5333         image->initial_image = TRUE;
5334         assembly->assembly.aname.name = image->image.name;
5335         assembly->assembly.image = &image->image;
5336         if (assemblyb->pktoken && assemblyb->pktoken->max_length) {
5337                 /* -1 to correct for the trailing NULL byte */
5338                 if (assemblyb->pktoken->max_length != MONO_PUBLIC_KEY_TOKEN_LENGTH - 1) {
5339                         g_error ("Public key token length invalid for assembly %s: %i", assembly->assembly.aname.name, assemblyb->pktoken->max_length);
5340                 }
5341                 memcpy (&assembly->assembly.aname.public_key_token, mono_array_addr (assemblyb->pktoken, guint8, 0), assemblyb->pktoken->max_length);           
5342         }
5343
5344         mono_domain_assemblies_lock (domain);
5345         domain->domain_assemblies = g_slist_append (domain->domain_assemblies, assembly);
5346         mono_domain_assemblies_unlock (domain);
5347
5348         register_assembly (mono_object_domain (assemblyb), &assemblyb->assembly, &assembly->assembly);
5349         
5350         mono_profiler_assembly_loaded (&assembly->assembly, MONO_PROFILE_OK);
5351         
5352         mono_assembly_invoke_load_hook ((MonoAssembly*)assembly);
5353 }
5354
5355 #endif /* !DISABLE_REFLECTION_EMIT */
5356
5357 #ifndef DISABLE_REFLECTION_EMIT_SAVE
5358
5359 static int
5360 calc_section_size (MonoDynamicImage *assembly)
5361 {
5362         int nsections = 0;
5363
5364         /* alignment constraints */
5365         mono_image_add_stream_zero (&assembly->code, 4 - (assembly->code.index % 4));
5366         g_assert ((assembly->code.index % 4) == 0);
5367         assembly->meta_size += 3;
5368         assembly->meta_size &= ~3;
5369         mono_image_add_stream_zero (&assembly->resources, 4 - (assembly->resources.index % 4));
5370         g_assert ((assembly->resources.index % 4) == 0);
5371
5372         assembly->sections [MONO_SECTION_TEXT].size = assembly->meta_size + assembly->code.index + assembly->resources.index + assembly->strong_name_size;
5373         assembly->sections [MONO_SECTION_TEXT].attrs = SECT_FLAGS_HAS_CODE | SECT_FLAGS_MEM_EXECUTE | SECT_FLAGS_MEM_READ;
5374         nsections++;
5375
5376         if (assembly->win32_res) {
5377                 guint32 res_size = (assembly->win32_res_size + 3) & ~3;
5378
5379                 assembly->sections [MONO_SECTION_RSRC].size = res_size;
5380                 assembly->sections [MONO_SECTION_RSRC].attrs = SECT_FLAGS_HAS_INITIALIZED_DATA | SECT_FLAGS_MEM_READ;
5381                 nsections++;
5382         }
5383
5384         assembly->sections [MONO_SECTION_RELOC].size = 12;
5385         assembly->sections [MONO_SECTION_RELOC].attrs = SECT_FLAGS_MEM_READ | SECT_FLAGS_MEM_DISCARDABLE | SECT_FLAGS_HAS_INITIALIZED_DATA;
5386         nsections++;
5387
5388         return nsections;
5389 }
5390
5391 typedef struct {
5392         guint32 id;
5393         guint32 offset;
5394         GSList *children;
5395         MonoReflectionWin32Resource *win32_res; /* Only for leaf nodes */
5396 } ResTreeNode;
5397
5398 static int
5399 resource_tree_compare_by_id (gconstpointer a, gconstpointer b)
5400 {
5401         ResTreeNode *t1 = (ResTreeNode*)a;
5402         ResTreeNode *t2 = (ResTreeNode*)b;
5403
5404         return t1->id - t2->id;
5405 }
5406
5407 /*
5408  * resource_tree_create:
5409  *
5410  *  Organize the resources into a resource tree.
5411  */
5412 static ResTreeNode *
5413 resource_tree_create (MonoArray *win32_resources)
5414 {
5415         ResTreeNode *tree, *res_node, *type_node, *lang_node;
5416         GSList *l;
5417         int i;
5418
5419         tree = g_new0 (ResTreeNode, 1);
5420         
5421         for (i = 0; i < mono_array_length (win32_resources); ++i) {
5422                 MonoReflectionWin32Resource *win32_res =
5423                         (MonoReflectionWin32Resource*)mono_array_addr (win32_resources, MonoReflectionWin32Resource, i);
5424
5425                 /* Create node */
5426
5427                 /* FIXME: BUG: this stores managed references in unmanaged memory */
5428                 lang_node = g_new0 (ResTreeNode, 1);
5429                 lang_node->id = win32_res->lang_id;
5430                 lang_node->win32_res = win32_res;
5431
5432                 /* Create type node if neccesary */
5433                 type_node = NULL;
5434                 for (l = tree->children; l; l = l->next)
5435                         if (((ResTreeNode*)(l->data))->id == win32_res->res_type) {
5436                                 type_node = (ResTreeNode*)l->data;
5437                                 break;
5438                         }
5439
5440                 if (!type_node) {
5441                         type_node = g_new0 (ResTreeNode, 1);
5442                         type_node->id = win32_res->res_type;
5443
5444                         /* 
5445                          * The resource types have to be sorted otherwise
5446                          * Windows Explorer can't display the version information.
5447                          */
5448                         tree->children = g_slist_insert_sorted (tree->children, 
5449                                 type_node, resource_tree_compare_by_id);
5450                 }
5451
5452                 /* Create res node if neccesary */
5453                 res_node = NULL;
5454                 for (l = type_node->children; l; l = l->next)
5455                         if (((ResTreeNode*)(l->data))->id == win32_res->res_id) {
5456                                 res_node = (ResTreeNode*)l->data;
5457                                 break;
5458                         }
5459
5460                 if (!res_node) {
5461                         res_node = g_new0 (ResTreeNode, 1);
5462                         res_node->id = win32_res->res_id;
5463                         type_node->children = g_slist_append (type_node->children, res_node);
5464                 }
5465
5466                 res_node->children = g_slist_append (res_node->children, lang_node);
5467         }
5468
5469         return tree;
5470 }
5471
5472 /*
5473  * resource_tree_encode:
5474  * 
5475  *   Encode the resource tree into the format used in the PE file.
5476  */
5477 static void
5478 resource_tree_encode (ResTreeNode *node, char *begin, char *p, char **endbuf)
5479 {
5480         char *entries;
5481         MonoPEResourceDir dir;
5482         MonoPEResourceDirEntry dir_entry;
5483         MonoPEResourceDataEntry data_entry;
5484         GSList *l;
5485         guint32 res_id_entries;
5486
5487         /*
5488          * For the format of the resource directory, see the article
5489          * "An In-Depth Look into the Win32 Portable Executable File Format" by
5490          * Matt Pietrek
5491          */
5492
5493         memset (&dir, 0, sizeof (dir));
5494         memset (&dir_entry, 0, sizeof (dir_entry));
5495         memset (&data_entry, 0, sizeof (data_entry));
5496
5497         g_assert (sizeof (dir) == 16);
5498         g_assert (sizeof (dir_entry) == 8);
5499         g_assert (sizeof (data_entry) == 16);
5500
5501         node->offset = p - begin;
5502
5503         /* IMAGE_RESOURCE_DIRECTORY */
5504         res_id_entries = g_slist_length (node->children);
5505         dir.res_id_entries = GUINT16_TO_LE (res_id_entries);
5506
5507         memcpy (p, &dir, sizeof (dir));
5508         p += sizeof (dir);
5509
5510         /* Reserve space for entries */
5511         entries = p;
5512         p += sizeof (dir_entry) * res_id_entries;
5513
5514         /* Write children */
5515         for (l = node->children; l; l = l->next) {
5516                 ResTreeNode *child = (ResTreeNode*)l->data;
5517
5518                 if (child->win32_res) {
5519                         guint32 size;
5520
5521                         child->offset = p - begin;
5522
5523                         /* IMAGE_RESOURCE_DATA_ENTRY */
5524                         data_entry.rde_data_offset = GUINT32_TO_LE (p - begin + sizeof (data_entry));
5525                         size = mono_array_length (child->win32_res->res_data);
5526                         data_entry.rde_size = GUINT32_TO_LE (size);
5527
5528                         memcpy (p, &data_entry, sizeof (data_entry));
5529                         p += sizeof (data_entry);
5530
5531                         memcpy (p, mono_array_addr (child->win32_res->res_data, char, 0), size);
5532                         p += size;
5533                 } else {
5534                         resource_tree_encode (child, begin, p, &p);
5535                 }
5536         }
5537
5538         /* IMAGE_RESOURCE_ENTRY */
5539         for (l = node->children; l; l = l->next) {
5540                 ResTreeNode *child = (ResTreeNode*)l->data;
5541
5542                 MONO_PE_RES_DIR_ENTRY_SET_NAME (dir_entry, FALSE, child->id);
5543                 MONO_PE_RES_DIR_ENTRY_SET_DIR (dir_entry, !child->win32_res, child->offset);
5544
5545                 memcpy (entries, &dir_entry, sizeof (dir_entry));
5546                 entries += sizeof (dir_entry);
5547         }
5548
5549         *endbuf = p;
5550 }
5551
5552 static void
5553 resource_tree_free (ResTreeNode * node)
5554 {
5555         GSList * list;
5556         for (list = node->children; list; list = list->next)
5557                 resource_tree_free ((ResTreeNode*)list->data);
5558         g_slist_free(node->children);
5559         g_free (node);
5560 }
5561
5562 static void
5563 assembly_add_win32_resources (MonoDynamicImage *assembly, MonoReflectionAssemblyBuilder *assemblyb)
5564 {
5565         char *buf;
5566         char *p;
5567         guint32 size, i;
5568         MonoReflectionWin32Resource *win32_res;
5569         ResTreeNode *tree;
5570
5571         if (!assemblyb->win32_resources)
5572                 return;
5573
5574         /*
5575          * Resources are stored in a three level tree inside the PE file.
5576          * - level one contains a node for each type of resource
5577          * - level two contains a node for each resource
5578          * - level three contains a node for each instance of a resource for a
5579          *   specific language.
5580          */
5581
5582         tree = resource_tree_create (assemblyb->win32_resources);
5583
5584         /* Estimate the size of the encoded tree */
5585         size = 0;
5586         for (i = 0; i < mono_array_length (assemblyb->win32_resources); ++i) {
5587                 win32_res = (MonoReflectionWin32Resource*)mono_array_addr (assemblyb->win32_resources, MonoReflectionWin32Resource, i);
5588                 size += mono_array_length (win32_res->res_data);
5589         }
5590         /* Directory structure */
5591         size += mono_array_length (assemblyb->win32_resources) * 256;
5592         p = buf = g_malloc (size);
5593
5594         resource_tree_encode (tree, p, p, &p);
5595
5596         g_assert (p - buf <= size);
5597
5598         assembly->win32_res = g_malloc (p - buf);
5599         assembly->win32_res_size = p - buf;
5600         memcpy (assembly->win32_res, buf, p - buf);
5601
5602         g_free (buf);
5603         resource_tree_free (tree);
5604 }
5605
5606 static void
5607 fixup_resource_directory (char *res_section, char *p, guint32 rva)
5608 {
5609         MonoPEResourceDir *dir = (MonoPEResourceDir*)p;
5610         int i;
5611
5612         p += sizeof (MonoPEResourceDir);
5613         for (i = 0; i < GUINT16_FROM_LE (dir->res_named_entries) + GUINT16_FROM_LE (dir->res_id_entries); ++i) {
5614                 MonoPEResourceDirEntry *dir_entry = (MonoPEResourceDirEntry*)p;
5615                 char *child = res_section + MONO_PE_RES_DIR_ENTRY_DIR_OFFSET (*dir_entry);
5616                 if (MONO_PE_RES_DIR_ENTRY_IS_DIR (*dir_entry)) {
5617                         fixup_resource_directory (res_section, child, rva);
5618                 } else {
5619                         MonoPEResourceDataEntry *data_entry = (MonoPEResourceDataEntry*)child;
5620                         data_entry->rde_data_offset = GUINT32_TO_LE (GUINT32_FROM_LE (data_entry->rde_data_offset) + rva);
5621                 }
5622
5623                 p += sizeof (MonoPEResourceDirEntry);
5624         }
5625 }
5626
5627 static void
5628 checked_write_file (HANDLE f, gconstpointer buffer, guint32 numbytes)
5629 {
5630         guint32 dummy;
5631         if (!WriteFile (f, buffer, numbytes, &dummy, NULL))
5632                 g_error ("WriteFile returned %d\n", GetLastError ());
5633 }
5634
5635 /*
5636  * mono_image_create_pefile:
5637  * @mb: a module builder object
5638  * 
5639  * This function creates the PE-COFF header, the image sections, the CLI header  * etc. all the data is written in
5640  * assembly->pefile where it can be easily retrieved later in chunks.
5641  */
5642 void
5643 mono_image_create_pefile (MonoReflectionModuleBuilder *mb, HANDLE file)
5644 {
5645         MonoMSDOSHeader *msdos;
5646         MonoDotNetHeader *header;
5647         MonoSectionTable *section;
5648         MonoCLIHeader *cli_header;
5649         guint32 size, image_size, virtual_base, text_offset;
5650         guint32 header_start, section_start, file_offset, virtual_offset;
5651         MonoDynamicImage *assembly;
5652         MonoReflectionAssemblyBuilder *assemblyb;
5653         MonoDynamicStream pefile_stream = {0};
5654         MonoDynamicStream *pefile = &pefile_stream;
5655         int i, nsections;
5656         guint32 *rva, value;
5657         guchar *p;
5658         static const unsigned char msheader[] = {
5659                 0x4d, 0x5a, 0x90, 0x00, 0x03, 0x00, 0x00, 0x00,  0x04, 0x00, 0x00, 0x00, 0xff, 0xff, 0x00, 0x00,
5660                 0xb8, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,  0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
5661                 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
5662                 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,  0x00, 0x00, 0x00, 0x00, 0x80, 0x00, 0x00, 0x00,
5663                 0x0e, 0x1f, 0xba, 0x0e, 0x00, 0xb4, 0x09, 0xcd,  0x21, 0xb8, 0x01, 0x4c, 0xcd, 0x21, 0x54, 0x68,
5664                 0x69, 0x73, 0x20, 0x70, 0x72, 0x6f, 0x67, 0x72,  0x61, 0x6d, 0x20, 0x63, 0x61, 0x6e, 0x6e, 0x6f,
5665                 0x74, 0x20, 0x62, 0x65, 0x20, 0x72, 0x75, 0x6e,  0x20, 0x69, 0x6e, 0x20, 0x44, 0x4f, 0x53, 0x20,
5666                 0x6d, 0x6f, 0x64, 0x65, 0x2e, 0x0d, 0x0d, 0x0a,  0x24, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
5667         };
5668
5669         assemblyb = mb->assemblyb;
5670
5671         mono_image_basic_init (assemblyb);
5672         assembly = mb->dynamic_image;
5673
5674         assembly->pe_kind = assemblyb->pe_kind;
5675         assembly->machine = assemblyb->machine;
5676         ((MonoDynamicImage*)assemblyb->dynamic_assembly->assembly.image)->pe_kind = assemblyb->pe_kind;
5677         ((MonoDynamicImage*)assemblyb->dynamic_assembly->assembly.image)->machine = assemblyb->machine;
5678         
5679         mono_image_build_metadata (mb);
5680
5681         if (mb->is_main && assemblyb->resources) {
5682                 int len = mono_array_length (assemblyb->resources);
5683                 for (i = 0; i < len; ++i)
5684                         assembly_add_resource (mb, assembly, (MonoReflectionResource*)mono_array_addr (assemblyb->resources, MonoReflectionResource, i));
5685         }
5686
5687         if (mb->resources) {
5688                 int len = mono_array_length (mb->resources);
5689                 for (i = 0; i < len; ++i)
5690                         assembly_add_resource (mb, assembly, (MonoReflectionResource*)mono_array_addr (mb->resources, MonoReflectionResource, i));
5691         }
5692
5693         build_compressed_metadata (assembly);
5694
5695         if (mb->is_main)
5696                 assembly_add_win32_resources (assembly, assemblyb);
5697
5698         nsections = calc_section_size (assembly);
5699         
5700         /* The DOS header and stub */
5701         g_assert (sizeof (MonoMSDOSHeader) == sizeof (msheader));
5702         mono_image_add_stream_data (pefile, (char*)msheader, sizeof (msheader));
5703
5704         /* the dotnet header */
5705         header_start = mono_image_add_stream_zero (pefile, sizeof (MonoDotNetHeader));
5706
5707         /* the section tables */
5708         section_start = mono_image_add_stream_zero (pefile, sizeof (MonoSectionTable) * nsections);
5709
5710         file_offset = section_start + sizeof (MonoSectionTable) * nsections;
5711         virtual_offset = VIRT_ALIGN;
5712         image_size = 0;
5713
5714         for (i = 0; i < MONO_SECTION_MAX; ++i) {
5715                 if (!assembly->sections [i].size)
5716                         continue;
5717                 /* align offsets */
5718                 file_offset += FILE_ALIGN - 1;
5719                 file_offset &= ~(FILE_ALIGN - 1);
5720                 virtual_offset += VIRT_ALIGN - 1;
5721                 virtual_offset &= ~(VIRT_ALIGN - 1);
5722
5723                 assembly->sections [i].offset = file_offset;
5724                 assembly->sections [i].rva = virtual_offset;
5725
5726                 file_offset += assembly->sections [i].size;
5727                 virtual_offset += assembly->sections [i].size;
5728                 image_size += (assembly->sections [i].size + VIRT_ALIGN - 1) & ~(VIRT_ALIGN - 1);
5729         }
5730
5731         file_offset += FILE_ALIGN - 1;
5732         file_offset &= ~(FILE_ALIGN - 1);
5733
5734         image_size += section_start + sizeof (MonoSectionTable) * nsections;
5735
5736         /* back-patch info */
5737         msdos = (MonoMSDOSHeader*)pefile->data;
5738         msdos->pe_offset = GUINT32_FROM_LE (sizeof (MonoMSDOSHeader));
5739
5740         header = (MonoDotNetHeader*)(pefile->data + header_start);
5741         header->pesig [0] = 'P';
5742         header->pesig [1] = 'E';
5743         
5744         header->coff.coff_machine = GUINT16_FROM_LE (assemblyb->machine);
5745         header->coff.coff_sections = GUINT16_FROM_LE (nsections);
5746         header->coff.coff_time = GUINT32_FROM_LE (time (NULL));
5747         header->coff.coff_opt_header_size = GUINT16_FROM_LE (sizeof (MonoDotNetHeader) - sizeof (MonoCOFFHeader) - 4);
5748         if (assemblyb->pekind == 1) {
5749                 /* it's a dll */
5750                 header->coff.coff_attributes = GUINT16_FROM_LE (0x210e);
5751         } else {
5752                 /* it's an exe */
5753                 header->coff.coff_attributes = GUINT16_FROM_LE (0x010e);
5754         }
5755
5756         virtual_base = 0x400000; /* FIXME: 0x10000000 if a DLL */
5757
5758         header->pe.pe_magic = GUINT16_FROM_LE (0x10B);
5759         header->pe.pe_major = 6;
5760         header->pe.pe_minor = 0;
5761         size = assembly->sections [MONO_SECTION_TEXT].size;
5762         size += FILE_ALIGN - 1;
5763         size &= ~(FILE_ALIGN - 1);
5764         header->pe.pe_code_size = GUINT32_FROM_LE(size);
5765         size = assembly->sections [MONO_SECTION_RSRC].size;
5766         size += FILE_ALIGN - 1;
5767         size &= ~(FILE_ALIGN - 1);
5768         header->pe.pe_data_size = GUINT32_FROM_LE(size);
5769         g_assert (START_TEXT_RVA == assembly->sections [MONO_SECTION_TEXT].rva);
5770         header->pe.pe_rva_code_base = GUINT32_FROM_LE (assembly->sections [MONO_SECTION_TEXT].rva);
5771         header->pe.pe_rva_data_base = GUINT32_FROM_LE (assembly->sections [MONO_SECTION_RSRC].rva);
5772         /* pe_rva_entry_point always at the beginning of the text section */
5773         header->pe.pe_rva_entry_point = GUINT32_FROM_LE (assembly->sections [MONO_SECTION_TEXT].rva);
5774
5775         header->nt.pe_image_base = GUINT32_FROM_LE (virtual_base);
5776         header->nt.pe_section_align = GUINT32_FROM_LE (VIRT_ALIGN);
5777         header->nt.pe_file_alignment = GUINT32_FROM_LE (FILE_ALIGN);
5778         header->nt.pe_os_major = GUINT16_FROM_LE (4);
5779         header->nt.pe_os_minor = GUINT16_FROM_LE (0);
5780         header->nt.pe_subsys_major = GUINT16_FROM_LE (4);
5781         size = section_start;
5782         size += FILE_ALIGN - 1;
5783         size &= ~(FILE_ALIGN - 1);
5784         header->nt.pe_header_size = GUINT32_FROM_LE (size);
5785         size = image_size;
5786         size += VIRT_ALIGN - 1;
5787         size &= ~(VIRT_ALIGN - 1);
5788         header->nt.pe_image_size = GUINT32_FROM_LE (size);
5789
5790         /*
5791         // Translate the PEFileKind value to the value expected by the Windows loader
5792         */
5793         {
5794                 short kind;
5795
5796                 /*
5797                 // PEFileKinds.Dll == 1
5798                 // PEFileKinds.ConsoleApplication == 2
5799                 // PEFileKinds.WindowApplication == 3
5800                 //
5801                 // need to get:
5802                 //     IMAGE_SUBSYSTEM_WINDOWS_GUI 2 // Image runs in the Windows GUI subsystem.
5803                 //     IMAGE_SUBSYSTEM_WINDOWS_CUI 3 // Image runs in the Windows character subsystem.
5804                 */
5805                 if (assemblyb->pekind == 3)
5806                         kind = 2;
5807                 else
5808                         kind = 3;
5809                 
5810                 header->nt.pe_subsys_required = GUINT16_FROM_LE (kind);
5811         }    
5812         header->nt.pe_stack_reserve = GUINT32_FROM_LE (0x00100000);
5813         header->nt.pe_stack_commit = GUINT32_FROM_LE (0x00001000);
5814         header->nt.pe_heap_reserve = GUINT32_FROM_LE (0x00100000);
5815         header->nt.pe_heap_commit = GUINT32_FROM_LE (0x00001000);
5816         header->nt.pe_loader_flags = GUINT32_FROM_LE (0);
5817         header->nt.pe_data_dir_count = GUINT32_FROM_LE (16);
5818
5819         /* fill data directory entries */
5820
5821         header->datadir.pe_resource_table.size = GUINT32_FROM_LE (assembly->sections [MONO_SECTION_RSRC].size);
5822         header->datadir.pe_resource_table.rva = GUINT32_FROM_LE (assembly->sections [MONO_SECTION_RSRC].rva);
5823
5824         header->datadir.pe_reloc_table.size = GUINT32_FROM_LE (assembly->sections [MONO_SECTION_RELOC].size);
5825         header->datadir.pe_reloc_table.rva = GUINT32_FROM_LE (assembly->sections [MONO_SECTION_RELOC].rva);
5826
5827         header->datadir.pe_cli_header.size = GUINT32_FROM_LE (72);
5828         header->datadir.pe_cli_header.rva = GUINT32_FROM_LE (assembly->text_rva + assembly->cli_header_offset);
5829         header->datadir.pe_iat.size = GUINT32_FROM_LE (8);
5830         header->datadir.pe_iat.rva = GUINT32_FROM_LE (assembly->text_rva + assembly->iat_offset);
5831         /* patch entrypoint name */
5832         if (assemblyb->pekind == 1)
5833                 memcpy (assembly->code.data + assembly->imp_names_offset + 2, "_CorDllMain", 12);
5834         else
5835                 memcpy (assembly->code.data + assembly->imp_names_offset + 2, "_CorExeMain", 12);
5836         /* patch imported function RVA name */
5837         rva = (guint32*)(assembly->code.data + assembly->iat_offset);
5838         *rva = GUINT32_FROM_LE (assembly->text_rva + assembly->imp_names_offset);
5839
5840         /* the import table */
5841         header->datadir.pe_import_table.size = GUINT32_FROM_LE (79); /* FIXME: magic number? */
5842         header->datadir.pe_import_table.rva = GUINT32_FROM_LE (assembly->text_rva + assembly->idt_offset);
5843         /* patch imported dll RVA name and other entries in the dir */
5844         rva = (guint32*)(assembly->code.data + assembly->idt_offset + G_STRUCT_OFFSET (MonoIDT, name_rva));
5845         *rva = GUINT32_FROM_LE (assembly->text_rva + assembly->imp_names_offset + 14); /* 14 is hint+strlen+1 of func name */
5846         rva = (guint32*)(assembly->code.data + assembly->idt_offset + G_STRUCT_OFFSET (MonoIDT, import_address_table_rva));
5847         *rva = GUINT32_FROM_LE (assembly->text_rva + assembly->iat_offset);
5848         rva = (guint32*)(assembly->code.data + assembly->idt_offset + G_STRUCT_OFFSET (MonoIDT, import_lookup_table));
5849         *rva = GUINT32_FROM_LE (assembly->text_rva + assembly->ilt_offset);
5850
5851         p = (guchar*)(assembly->code.data + assembly->ilt_offset);
5852         value = (assembly->text_rva + assembly->imp_names_offset);
5853         *p++ = (value) & 0xff;
5854         *p++ = (value >> 8) & (0xff);
5855         *p++ = (value >> 16) & (0xff);
5856         *p++ = (value >> 24) & (0xff);
5857
5858         /* the CLI header info */
5859         cli_header = (MonoCLIHeader*)(assembly->code.data + assembly->cli_header_offset);
5860         cli_header->ch_size = GUINT32_FROM_LE (72);
5861         cli_header->ch_runtime_major = GUINT16_FROM_LE (2);
5862         cli_header->ch_runtime_minor = GUINT16_FROM_LE (5);
5863         cli_header->ch_flags = GUINT32_FROM_LE (assemblyb->pe_kind);
5864         if (assemblyb->entry_point) {
5865                 guint32 table_idx = 0;
5866                 if (!strcmp (assemblyb->entry_point->object.vtable->klass->name, "MethodBuilder")) {
5867                         MonoReflectionMethodBuilder *methodb = (MonoReflectionMethodBuilder*)assemblyb->entry_point;
5868                         table_idx = methodb->table_idx;
5869                 } else {
5870                         table_idx = GPOINTER_TO_UINT (g_hash_table_lookup (assembly->method_to_table_idx, assemblyb->entry_point->method));
5871                 }
5872                 cli_header->ch_entry_point = GUINT32_FROM_LE (table_idx | MONO_TOKEN_METHOD_DEF);
5873         } else {
5874                 cli_header->ch_entry_point = GUINT32_FROM_LE (0);
5875         }
5876         /* The embedded managed resources */
5877         text_offset = assembly->text_rva + assembly->code.index;
5878         cli_header->ch_resources.rva = GUINT32_FROM_LE (text_offset);
5879         cli_header->ch_resources.size = GUINT32_FROM_LE (assembly->resources.index);
5880         text_offset += assembly->resources.index;
5881         cli_header->ch_metadata.rva = GUINT32_FROM_LE (text_offset);
5882         cli_header->ch_metadata.size = GUINT32_FROM_LE (assembly->meta_size);
5883         text_offset += assembly->meta_size;
5884         if (assembly->strong_name_size) {
5885                 cli_header->ch_strong_name.rva = GUINT32_FROM_LE (text_offset);
5886                 cli_header->ch_strong_name.size = GUINT32_FROM_LE (assembly->strong_name_size);
5887                 text_offset += assembly->strong_name_size;
5888         }
5889
5890         /* write the section tables and section content */
5891         section = (MonoSectionTable*)(pefile->data + section_start);
5892         for (i = 0; i < MONO_SECTION_MAX; ++i) {
5893                 static const char section_names [][7] = {
5894                         ".text", ".rsrc", ".reloc"
5895                 };
5896                 if (!assembly->sections [i].size)
5897                         continue;
5898                 strcpy (section->st_name, section_names [i]);
5899                 /*g_print ("output section %s (%d), size: %d\n", section->st_name, i, assembly->sections [i].size);*/
5900                 section->st_virtual_address = GUINT32_FROM_LE (assembly->sections [i].rva);
5901                 section->st_virtual_size = GUINT32_FROM_LE (assembly->sections [i].size);
5902                 section->st_raw_data_size = GUINT32_FROM_LE (GUINT32_TO_LE (section->st_virtual_size) + (FILE_ALIGN - 1));
5903                 section->st_raw_data_size &= GUINT32_FROM_LE (~(FILE_ALIGN - 1));
5904                 section->st_raw_data_ptr = GUINT32_FROM_LE (assembly->sections [i].offset);
5905                 section->st_flags = GUINT32_FROM_LE (assembly->sections [i].attrs);
5906                 section ++;
5907         }
5908         
5909         checked_write_file (file, pefile->data, pefile->index);
5910         
5911         mono_dynamic_stream_reset (pefile);
5912         
5913         for (i = 0; i < MONO_SECTION_MAX; ++i) {
5914                 if (!assembly->sections [i].size)
5915                         continue;
5916                 
5917                 if (SetFilePointer (file, assembly->sections [i].offset, NULL, FILE_BEGIN) == INVALID_SET_FILE_POINTER)
5918                         g_error ("SetFilePointer returned %d\n", GetLastError ());
5919                 
5920                 switch (i) {
5921                 case MONO_SECTION_TEXT:
5922                         /* patch entry point */
5923                         p = (guchar*)(assembly->code.data + 2);
5924                         value = (virtual_base + assembly->text_rva + assembly->iat_offset);
5925                         *p++ = (value) & 0xff;
5926                         *p++ = (value >> 8) & 0xff;
5927                         *p++ = (value >> 16) & 0xff;
5928                         *p++ = (value >> 24) & 0xff;
5929                 
5930                         checked_write_file (file, assembly->code.data, assembly->code.index);
5931                         checked_write_file (file, assembly->resources.data, assembly->resources.index);
5932                         checked_write_file (file, assembly->image.raw_metadata, assembly->meta_size);
5933                         checked_write_file (file, assembly->strong_name, assembly->strong_name_size);
5934                                 
5935
5936                         g_free (assembly->image.raw_metadata);
5937                         break;
5938                 case MONO_SECTION_RELOC: {
5939                         struct {
5940                                 guint32 page_rva;
5941                                 guint32 block_size;
5942                                 guint16 type_and_offset;
5943                                 guint16 term;
5944                         } reloc;
5945                         
5946                         g_assert (sizeof (reloc) == 12);
5947                         
5948                         reloc.page_rva = GUINT32_FROM_LE (assembly->text_rva);
5949                         reloc.block_size = GUINT32_FROM_LE (12);
5950                         
5951                         /* 
5952                          * the entrypoint is always at the start of the text section 
5953                          * 3 is IMAGE_REL_BASED_HIGHLOW
5954                          * 2 is patch_size_rva - text_rva
5955                          */
5956                         reloc.type_and_offset = GUINT16_FROM_LE ((3 << 12) + (2));
5957                         reloc.term = 0;
5958                         
5959                         checked_write_file (file, &reloc, sizeof (reloc));
5960                         
5961                         break;
5962                 }
5963                 case MONO_SECTION_RSRC:
5964                         if (assembly->win32_res) {
5965
5966                                 /* Fixup the offsets in the IMAGE_RESOURCE_DATA_ENTRY structures */
5967                                 fixup_resource_directory (assembly->win32_res, assembly->win32_res, assembly->sections [i].rva);
5968                                 checked_write_file (file, assembly->win32_res, assembly->win32_res_size);
5969                         }
5970                         break;
5971                 default:
5972                         g_assert_not_reached ();
5973                 }
5974         }
5975         
5976         /* check that the file is properly padded */
5977         if (SetFilePointer (file, file_offset, NULL, FILE_BEGIN) == INVALID_SET_FILE_POINTER)
5978                 g_error ("SetFilePointer returned %d\n", GetLastError ());
5979         if (! SetEndOfFile (file))
5980                 g_error ("SetEndOfFile returned %d\n", GetLastError ());
5981         
5982         mono_dynamic_stream_reset (&assembly->code);
5983         mono_dynamic_stream_reset (&assembly->us);
5984         mono_dynamic_stream_reset (&assembly->blob);
5985         mono_dynamic_stream_reset (&assembly->guid);
5986         mono_dynamic_stream_reset (&assembly->sheap);
5987
5988         g_hash_table_foreach (assembly->blob_cache, (GHFunc)g_free, NULL);
5989         g_hash_table_destroy (assembly->blob_cache);
5990         assembly->blob_cache = NULL;
5991 }
5992
5993 #else /* DISABLE_REFLECTION_EMIT_SAVE */
5994
5995 void
5996 mono_image_create_pefile (MonoReflectionModuleBuilder *mb, HANDLE file)
5997 {
5998         g_assert_not_reached ();
5999 }
6000
6001 #endif /* DISABLE_REFLECTION_EMIT_SAVE */
6002
6003 #ifndef DISABLE_REFLECTION_EMIT
6004
6005 MonoReflectionModule *
6006 mono_image_load_module_dynamic (MonoReflectionAssemblyBuilder *ab, MonoString *fileName)
6007 {
6008         char *name;
6009         MonoImage *image;
6010         MonoImageOpenStatus status;
6011         MonoDynamicAssembly *assembly;
6012         guint32 module_count;
6013         MonoImage **new_modules;
6014         gboolean *new_modules_loaded;
6015         
6016         name = mono_string_to_utf8 (fileName);
6017
6018         image = mono_image_open (name, &status);
6019         if (!image) {
6020                 MonoException *exc;
6021                 if (status == MONO_IMAGE_ERROR_ERRNO)
6022                         exc = mono_get_exception_file_not_found (fileName);
6023                 else
6024                         exc = mono_get_exception_bad_image_format (name);
6025                 g_free (name);
6026                 mono_raise_exception (exc);
6027         }
6028
6029         g_free (name);
6030
6031         assembly = ab->dynamic_assembly;
6032         image->assembly = (MonoAssembly*)assembly;
6033
6034         module_count = image->assembly->image->module_count;
6035         new_modules = g_new0 (MonoImage *, module_count + 1);
6036         new_modules_loaded = g_new0 (gboolean, module_count + 1);
6037
6038         if (image->assembly->image->modules)
6039                 memcpy (new_modules, image->assembly->image->modules, module_count * sizeof (MonoImage *));
6040         if (image->assembly->image->modules_loaded)
6041                 memcpy (new_modules_loaded, image->assembly->image->modules_loaded, module_count * sizeof (gboolean));
6042         new_modules [module_count] = image;
6043         new_modules_loaded [module_count] = TRUE;
6044         mono_image_addref (image);
6045
6046         g_free (image->assembly->image->modules);
6047         image->assembly->image->modules = new_modules;
6048         image->assembly->image->modules_loaded = new_modules_loaded;
6049         image->assembly->image->module_count ++;
6050
6051         mono_assembly_load_references (image, &status);
6052         if (status) {
6053                 mono_image_close (image);
6054                 mono_raise_exception (mono_get_exception_file_not_found (fileName));
6055         }
6056
6057         return mono_module_get_object (mono_domain_get (), image);
6058 }
6059
6060 #endif /* DISABLE_REFLECTION_EMIT */
6061
6062 /*
6063  * We need to return always the same object for MethodInfo, FieldInfo etc..
6064  * but we need to consider the reflected type.
6065  * type uses a different hash, since it uses custom hash/equal functions.
6066  */
6067
6068 typedef struct {
6069         gpointer item;
6070         MonoClass *refclass;
6071 } ReflectedEntry;
6072
6073 static gboolean
6074 reflected_equal (gconstpointer a, gconstpointer b) {
6075         const ReflectedEntry *ea = a;
6076         const ReflectedEntry *eb = b;
6077
6078         return (ea->item == eb->item) && (ea->refclass == eb->refclass);
6079 }
6080
6081 static guint
6082 reflected_hash (gconstpointer a) {
6083         const ReflectedEntry *ea = a;
6084         return mono_aligned_addr_hash (ea->item);
6085 }
6086
6087 #define CHECK_OBJECT(t,p,k)     \
6088         do {    \
6089                 t _obj; \
6090                 ReflectedEntry e;       \
6091                 e.item = (p);   \
6092                 e.refclass = (k);       \
6093                 mono_domain_lock (domain);      \
6094                 if (!domain->refobject_hash)    \
6095                         domain->refobject_hash = mono_g_hash_table_new_type (reflected_hash, reflected_equal, MONO_HASH_VALUE_GC);      \
6096                 if ((_obj = mono_g_hash_table_lookup (domain->refobject_hash, &e))) {   \
6097                         mono_domain_unlock (domain);    \
6098                         return _obj;    \
6099                 }       \
6100         mono_domain_unlock (domain); \
6101         } while (0)
6102
6103 #ifdef HAVE_BOEHM_GC
6104 /* ReflectedEntry doesn't need to be GC tracked */
6105 #define ALLOC_REFENTRY g_new0 (ReflectedEntry, 1)
6106 #define FREE_REFENTRY(entry) g_free ((entry))
6107 #define REFENTRY_REQUIRES_CLEANUP
6108 #else
6109 #define ALLOC_REFENTRY mono_mempool_alloc (domain->mp, sizeof (ReflectedEntry))
6110 /* FIXME: */
6111 #define FREE_REFENTRY(entry)
6112 #endif
6113
6114 #define CACHE_OBJECT(t,p,o,k)   \
6115         do {    \
6116                 t _obj; \
6117         ReflectedEntry pe; \
6118         pe.item = (p); \
6119         pe.refclass = (k); \
6120         mono_domain_lock (domain); \
6121                 if (!domain->refobject_hash)    \
6122                         domain->refobject_hash = mono_g_hash_table_new_type (reflected_hash, reflected_equal, MONO_HASH_VALUE_GC);      \
6123         _obj = mono_g_hash_table_lookup (domain->refobject_hash, &pe); \
6124         if (!_obj) { \
6125                     ReflectedEntry *e = ALLOC_REFENTRY;         \
6126                     e->item = (p);      \
6127                     e->refclass = (k);  \
6128                     mono_g_hash_table_insert (domain->refobject_hash, e,o);     \
6129             _obj = o; \
6130         } \
6131                 mono_domain_unlock (domain);    \
6132         return _obj; \
6133         } while (0)
6134
6135 static void
6136 clear_cached_object (MonoDomain *domain, gpointer o, MonoClass *klass)
6137 {
6138         mono_domain_lock (domain);
6139         if (domain->refobject_hash) {
6140         ReflectedEntry pe;
6141                 gpointer orig_pe, orig_value;
6142
6143                 pe.item = o;
6144                 pe.refclass = klass;
6145                 if (mono_g_hash_table_lookup_extended (domain->refobject_hash, &pe, &orig_pe, &orig_value)) {
6146                         mono_g_hash_table_remove (domain->refobject_hash, &pe);
6147                         FREE_REFENTRY (orig_pe);
6148                 }
6149         }
6150         mono_domain_unlock (domain);
6151 }
6152
6153 #ifdef REFENTRY_REQUIRES_CLEANUP
6154 static void
6155 cleanup_refobject_hash (gpointer key, gpointer value, gpointer user_data)
6156 {
6157         FREE_REFENTRY (key);
6158 }
6159 #endif
6160
6161 void
6162 mono_reflection_cleanup_domain (MonoDomain *domain)
6163 {
6164         if (domain->refobject_hash) {
6165 /*let's avoid scanning the whole hashtable if not needed*/
6166 #ifdef REFENTRY_REQUIRES_CLEANUP
6167                 mono_g_hash_table_foreach (domain->refobject_hash, cleanup_refobject_hash, NULL);
6168 #endif
6169                 mono_g_hash_table_destroy (domain->refobject_hash);
6170                 domain->refobject_hash = NULL;
6171         }
6172 }
6173
6174 #ifndef DISABLE_REFLECTION_EMIT
6175 static gpointer
6176 register_assembly (MonoDomain *domain, MonoReflectionAssembly *res, MonoAssembly *assembly)
6177 {
6178         CACHE_OBJECT (MonoReflectionAssembly *, assembly, res, NULL);
6179 }
6180
6181 static gpointer
6182 register_module (MonoDomain *domain, MonoReflectionModuleBuilder *res, MonoDynamicImage *module)
6183 {
6184         CACHE_OBJECT (MonoReflectionModuleBuilder *, module, res, NULL);
6185 }
6186
6187 void
6188 mono_image_module_basic_init (MonoReflectionModuleBuilder *moduleb)
6189 {
6190         MonoDynamicImage *image = moduleb->dynamic_image;
6191         MonoReflectionAssemblyBuilder *ab = moduleb->assemblyb;
6192         if (!image) {
6193                 MonoError error;
6194                 int module_count;
6195                 MonoImage **new_modules;
6196                 MonoImage *ass;
6197                 char *name, *fqname;
6198                 /*
6199                  * FIXME: we already created an image in mono_image_basic_init (), but
6200                  * we don't know which module it belongs to, since that is only 
6201                  * determined at assembly save time.
6202                  */
6203                 /*image = (MonoDynamicImage*)ab->dynamic_assembly->assembly.image; */
6204                 name = mono_string_to_utf8 (ab->name);
6205                 fqname = mono_string_to_utf8_checked (moduleb->module.fqname, &error);
6206                 if (!mono_error_ok (&error)) {
6207                         g_free (name);
6208                         mono_error_raise_exception (&error);
6209                 }
6210                 image = create_dynamic_mono_image (ab->dynamic_assembly, name, fqname);
6211
6212                 moduleb->module.image = &image->image;
6213                 moduleb->dynamic_image = image;
6214                 register_module (mono_object_domain (moduleb), moduleb, image);
6215
6216                 /* register the module with the assembly */
6217                 ass = ab->dynamic_assembly->assembly.image;
6218                 module_count = ass->module_count;
6219                 new_modules = g_new0 (MonoImage *, module_count + 1);
6220
6221                 if (ass->modules)
6222                         memcpy (new_modules, ass->modules, module_count * sizeof (MonoImage *));
6223                 new_modules [module_count] = &image->image;
6224                 mono_image_addref (&image->image);
6225
6226                 g_free (ass->modules);
6227                 ass->modules = new_modules;
6228                 ass->module_count ++;
6229         }
6230 }
6231
6232 void
6233 mono_image_set_wrappers_type (MonoReflectionModuleBuilder *moduleb, MonoReflectionType *type)
6234 {
6235         MonoDynamicImage *image = moduleb->dynamic_image;
6236
6237         g_assert (type->type);
6238         image->wrappers_type = mono_class_from_mono_type (type->type);
6239 }
6240
6241 #endif
6242
6243 /*
6244  * mono_assembly_get_object:
6245  * @domain: an app domain
6246  * @assembly: an assembly
6247  *
6248  * Return an System.Reflection.Assembly object representing the MonoAssembly @assembly.
6249  */
6250 MonoReflectionAssembly*
6251 mono_assembly_get_object (MonoDomain *domain, MonoAssembly *assembly)
6252 {
6253         static MonoClass *assembly_type;
6254         MonoReflectionAssembly *res;
6255         
6256         CHECK_OBJECT (MonoReflectionAssembly *, assembly, NULL);
6257         if (!assembly_type) {
6258                 MonoClass *class = mono_class_from_name (mono_defaults.corlib, "System.Reflection", "MonoAssembly");
6259                 if (class == NULL)
6260                         class = mono_class_from_name (mono_defaults.corlib, "System.Reflection", "Assembly");
6261                 g_assert (class);
6262                 assembly_type = class;
6263         }
6264         res = (MonoReflectionAssembly *)mono_object_new (domain, assembly_type);
6265         res->assembly = assembly;
6266
6267         CACHE_OBJECT (MonoReflectionAssembly *, assembly, res, NULL);
6268 }
6269
6270
6271
6272 MonoReflectionModule*   
6273 mono_module_get_object   (MonoDomain *domain, MonoImage *image)
6274 {
6275         static MonoClass *module_type;
6276         MonoReflectionModule *res;
6277         char* basename;
6278         
6279         CHECK_OBJECT (MonoReflectionModule *, image, NULL);
6280         if (!module_type) {
6281                 MonoClass *class = mono_class_from_name (mono_defaults.corlib, "System.Reflection", "MonoModule");
6282                 if (class == NULL)
6283                         class = mono_class_from_name (mono_defaults.corlib, "System.Reflection", "Module");
6284                 g_assert (class);
6285                 module_type = class;
6286         }
6287         res = (MonoReflectionModule *)mono_object_new (domain, module_type);
6288
6289         res->image = image;
6290         MONO_OBJECT_SETREF (res, assembly, (MonoReflectionAssembly *) mono_assembly_get_object(domain, image->assembly));
6291
6292         MONO_OBJECT_SETREF (res, fqname, mono_string_new (domain, image->name));
6293         basename = g_path_get_basename (image->name);
6294         MONO_OBJECT_SETREF (res, name, mono_string_new (domain, basename));
6295         MONO_OBJECT_SETREF (res, scopename, mono_string_new (domain, image->module_name));
6296         
6297         g_free (basename);
6298
6299         if (image->assembly->image == image) {
6300                 res->token = mono_metadata_make_token (MONO_TABLE_MODULE, 1);
6301         } else {
6302                 int i;
6303                 res->token = 0;
6304                 if (image->assembly->image->modules) {
6305                         for (i = 0; i < image->assembly->image->module_count; i++) {
6306                                 if (image->assembly->image->modules [i] == image)
6307                                         res->token = mono_metadata_make_token (MONO_TABLE_MODULEREF, i + 1);
6308                         }
6309                         g_assert (res->token);
6310                 }
6311         }
6312
6313         CACHE_OBJECT (MonoReflectionModule *, image, res, NULL);
6314 }
6315
6316 MonoReflectionModule*   
6317 mono_module_file_get_object (MonoDomain *domain, MonoImage *image, int table_index)
6318 {
6319         static MonoClass *module_type;
6320         MonoReflectionModule *res;
6321         MonoTableInfo *table;
6322         guint32 cols [MONO_FILE_SIZE];
6323         const char *name;
6324         guint32 i, name_idx;
6325         const char *val;
6326         
6327         if (!module_type) {
6328                 MonoClass *class = mono_class_from_name (mono_defaults.corlib, "System.Reflection", "MonoModule");
6329                 if (class == NULL)
6330                         class = mono_class_from_name (mono_defaults.corlib, "System.Reflection", "Module");
6331                 g_assert (class);
6332                 module_type = class;
6333         }
6334         res = (MonoReflectionModule *)mono_object_new (domain, module_type);
6335
6336         table = &image->tables [MONO_TABLE_FILE];
6337         g_assert (table_index < table->rows);
6338         mono_metadata_decode_row (table, table_index, cols, MONO_FILE_SIZE);
6339
6340         res->image = NULL;
6341         MONO_OBJECT_SETREF (res, assembly, (MonoReflectionAssembly *) mono_assembly_get_object(domain, image->assembly));
6342         name = mono_metadata_string_heap (image, cols [MONO_FILE_NAME]);
6343
6344         /* Check whenever the row has a corresponding row in the moduleref table */
6345         table = &image->tables [MONO_TABLE_MODULEREF];
6346         for (i = 0; i < table->rows; ++i) {
6347                 name_idx = mono_metadata_decode_row_col (table, i, MONO_MODULEREF_NAME);
6348                 val = mono_metadata_string_heap (image, name_idx);
6349                 if (strcmp (val, name) == 0)
6350                         res->image = image->modules [i];
6351         }
6352
6353         MONO_OBJECT_SETREF (res, fqname, mono_string_new (domain, name));
6354         MONO_OBJECT_SETREF (res, name, mono_string_new (domain, name));
6355         MONO_OBJECT_SETREF (res, scopename, mono_string_new (domain, name));
6356         res->is_resource = cols [MONO_FILE_FLAGS] && FILE_CONTAINS_NO_METADATA;
6357         res->token = mono_metadata_make_token (MONO_TABLE_FILE, table_index + 1);
6358
6359         return res;
6360 }
6361
6362 static gboolean
6363 verify_safe_for_managed_space (MonoType *type)
6364 {
6365         switch (type->type) {
6366 #ifdef DEBUG_HARDER
6367         case MONO_TYPE_ARRAY:
6368                 return verify_safe_for_managed_space (&type->data.array->eklass->byval_arg);
6369         case MONO_TYPE_PTR:
6370                 return verify_safe_for_managed_space (type->data.type);
6371         case MONO_TYPE_SZARRAY:
6372                 return verify_safe_for_managed_space (&type->data.klass->byval_arg);
6373         case MONO_TYPE_GENERICINST: {
6374                 MonoGenericInst *inst = type->data.generic_class->inst;
6375                 int i;
6376                 if (!inst->is_open)
6377                         break;
6378                 for (i = 0; i < inst->type_argc; ++i)
6379                         if (!verify_safe_for_managed_space (inst->type_argv [i]))
6380                                 return FALSE;
6381                 break;
6382         }
6383 #endif
6384         case MONO_TYPE_VAR:
6385         case MONO_TYPE_MVAR:
6386                 return TRUE;
6387         }
6388         return TRUE;
6389 }
6390
6391 static MonoType*
6392 mono_type_normalize (MonoType *type)
6393 {
6394         int i;
6395         MonoGenericClass *gclass;
6396         MonoGenericInst *ginst;
6397         MonoClass *gtd;
6398         MonoGenericContainer *gcontainer;
6399         MonoType **argv = NULL;
6400         gboolean is_denorm_gtd = TRUE, requires_rebind = FALSE;
6401
6402         if (type->type != MONO_TYPE_GENERICINST)
6403                 return type;
6404
6405         gclass = type->data.generic_class;
6406         ginst = gclass->context.class_inst;
6407         if (!ginst->is_open)
6408                 return type;
6409
6410         gtd = gclass->container_class;
6411         gcontainer = gtd->generic_container;
6412         argv = g_newa (MonoType*, ginst->type_argc);
6413
6414         for (i = 0; i < ginst->type_argc; ++i) {
6415                 MonoType *t = ginst->type_argv [i], *norm;
6416                 if (t->type != MONO_TYPE_VAR || t->data.generic_param->num != i || t->data.generic_param->owner != gcontainer)
6417                         is_denorm_gtd = FALSE;
6418                 norm = mono_type_normalize (t);
6419                 argv [i] = norm;
6420                 if (norm != t)
6421                         requires_rebind = TRUE;
6422         }
6423
6424         if (is_denorm_gtd)
6425                 return type->byref == gtd->byval_arg.byref ? &gtd->byval_arg : &gtd->this_arg;
6426
6427         if (requires_rebind) {
6428                 MonoClass *klass = mono_class_bind_generic_parameters (gtd, ginst->type_argc, argv, gclass->is_dynamic);
6429                 return type->byref == klass->byval_arg.byref ? &klass->byval_arg : &klass->this_arg;
6430         }
6431
6432         return type;
6433 }
6434 /*
6435  * mono_type_get_object:
6436  * @domain: an app domain
6437  * @type: a type
6438  *
6439  * Return an System.MonoType object representing the type @type.
6440  */
6441 MonoReflectionType*
6442 mono_type_get_object (MonoDomain *domain, MonoType *type)
6443 {
6444         MonoType *norm_type;
6445         MonoReflectionType *res;
6446         MonoClass *klass = mono_class_from_mono_type (type);
6447
6448         /*we must avoid using @type as it might have come
6449          * from a mono_metadata_type_dup and the caller
6450          * expects that is can be freed.
6451          * Using the right type from 
6452          */
6453         type = klass->byval_arg.byref == type->byref ? &klass->byval_arg : &klass->this_arg;
6454
6455         /* void is very common */
6456         if (type->type == MONO_TYPE_VOID && domain->typeof_void)
6457                 return (MonoReflectionType*)domain->typeof_void;
6458
6459         /*
6460          * If the vtable of the given class was already created, we can use
6461          * the MonoType from there and avoid all locking and hash table lookups.
6462          * 
6463          * We cannot do this for TypeBuilders as mono_reflection_create_runtime_class expects
6464          * that the resulting object is different.   
6465          */
6466         if (type == &klass->byval_arg && !klass->image->dynamic) {
6467                 MonoVTable *vtable = mono_class_try_get_vtable (domain, klass);
6468                 if (vtable && vtable->type)
6469                         return vtable->type;
6470         }
6471
6472         mono_loader_lock (); /*FIXME mono_class_init and mono_class_vtable acquire it*/
6473         mono_domain_lock (domain);
6474         if (!domain->type_hash)
6475                 domain->type_hash = mono_g_hash_table_new_type ((GHashFunc)mono_metadata_type_hash, 
6476                                 (GCompareFunc)mono_metadata_type_equal, MONO_HASH_VALUE_GC);
6477         if ((res = mono_g_hash_table_lookup (domain->type_hash, type))) {
6478                 mono_domain_unlock (domain);
6479                 mono_loader_unlock ();
6480                 return res;
6481         }
6482
6483         /*Types must be normalized so a generic instance of the GTD get's the same inner type.
6484          * For example in: Foo<A,B>; Bar<A> : Foo<A, Bar<A>>
6485          * The second Bar will be encoded a generic instance of Bar with <A> as parameter.
6486          * On all other places, Bar<A> will be encoded as the GTD itself. This is an implementation
6487          * artifact of how generics are encoded and should be transparent to managed code so we
6488          * need to weed out this diference when retrieving managed System.Type objects.
6489          */
6490         norm_type = mono_type_normalize (type);
6491         if (norm_type != type) {
6492                 res = mono_type_get_object (domain, norm_type);
6493                 mono_g_hash_table_insert (domain->type_hash, type, res);
6494                 mono_domain_unlock (domain);
6495                 mono_loader_unlock ();
6496                 return res;
6497         }
6498
6499         /* This MonoGenericClass hack is no longer necessary. Let's leave it here until we finish with the 2-stage type-builder setup.*/
6500         if ((type->type == MONO_TYPE_GENERICINST) && type->data.generic_class->is_dynamic && !type->data.generic_class->container_class->wastypebuilder)
6501                 g_assert (0);
6502
6503         if (!verify_safe_for_managed_space (type)) {
6504                 mono_domain_unlock (domain);
6505                 mono_loader_unlock ();
6506                 mono_raise_exception (mono_get_exception_invalid_operation ("This type cannot be propagated to managed space"));
6507         }
6508
6509         if (mono_class_get_ref_info (klass) && !klass->wastypebuilder) {
6510                 gboolean is_type_done = TRUE;
6511                 /* Generic parameters have reflection_info set but they are not finished together with their enclosing type.
6512                  * We must ensure that once a type is finished we don't return a GenericTypeParameterBuilder.
6513                  * We can't simply close the types as this will interfere with other parts of the generics machinery.
6514                 */
6515                 if (klass->byval_arg.type == MONO_TYPE_MVAR || klass->byval_arg.type == MONO_TYPE_VAR) {
6516                         MonoGenericParam *gparam = klass->byval_arg.data.generic_param;
6517
6518                         if (gparam->owner && gparam->owner->is_method) {
6519                                 MonoMethod *method = gparam->owner->owner.method;
6520                                 if (method && mono_class_get_generic_type_definition (method->klass)->wastypebuilder)
6521                                         is_type_done = FALSE;
6522                         } else if (gparam->owner && !gparam->owner->is_method) {
6523                                 MonoClass *klass = gparam->owner->owner.klass;
6524                                 if (klass && mono_class_get_generic_type_definition (klass)->wastypebuilder)
6525                                         is_type_done = FALSE;
6526                         }
6527                 } 
6528
6529                 /* g_assert_not_reached (); */
6530                 /* should this be considered an error condition? */
6531                 if (is_type_done && !type->byref) {
6532                         mono_domain_unlock (domain);
6533                         mono_loader_unlock ();
6534                         return mono_class_get_ref_info (klass);
6535                 }
6536         }
6537         /* This is stored in vtables/JITted code so it has to be pinned */
6538         res = (MonoReflectionType *)mono_object_new_pinned (domain, mono_defaults.monotype_class);
6539         res->type = type;
6540         mono_g_hash_table_insert (domain->type_hash, type, res);
6541
6542         if (type->type == MONO_TYPE_VOID)
6543                 domain->typeof_void = (MonoObject*)res;
6544
6545         mono_domain_unlock (domain);
6546         mono_loader_unlock ();
6547         return res;
6548 }
6549
6550 /*
6551  * mono_method_get_object:
6552  * @domain: an app domain
6553  * @method: a method
6554  * @refclass: the reflected type (can be NULL)
6555  *
6556  * Return an System.Reflection.MonoMethod object representing the method @method.
6557  */
6558 MonoReflectionMethod*
6559 mono_method_get_object (MonoDomain *domain, MonoMethod *method, MonoClass *refclass)
6560 {
6561         /*
6562          * We use the same C representation for methods and constructors, but the type 
6563          * name in C# is different.
6564          */
6565         static MonoClass *System_Reflection_MonoMethod = NULL;
6566         static MonoClass *System_Reflection_MonoCMethod = NULL;
6567         static MonoClass *System_Reflection_MonoGenericMethod = NULL;
6568         static MonoClass *System_Reflection_MonoGenericCMethod = NULL;
6569         MonoClass *klass;
6570         MonoReflectionMethod *ret;
6571
6572         if (method->is_inflated) {
6573                 MonoReflectionGenericMethod *gret;
6574
6575                 refclass = method->klass;
6576                 CHECK_OBJECT (MonoReflectionMethod *, method, refclass);
6577                 if ((*method->name == '.') && (!strcmp (method->name, ".ctor") || !strcmp (method->name, ".cctor"))) {
6578                         if (!System_Reflection_MonoGenericCMethod)
6579                                 System_Reflection_MonoGenericCMethod = mono_class_from_name (mono_defaults.corlib, "System.Reflection", "MonoGenericCMethod");
6580                         klass = System_Reflection_MonoGenericCMethod;
6581                 } else {
6582                         if (!System_Reflection_MonoGenericMethod)
6583                                 System_Reflection_MonoGenericMethod = mono_class_from_name (mono_defaults.corlib, "System.Reflection", "MonoGenericMethod");
6584                         klass = System_Reflection_MonoGenericMethod;
6585                 }
6586                 gret = (MonoReflectionGenericMethod*)mono_object_new (domain, klass);
6587                 gret->method.method = method;
6588                 MONO_OBJECT_SETREF (gret, method.name, mono_string_new (domain, method->name));
6589                 MONO_OBJECT_SETREF (gret, method.reftype, mono_type_get_object (domain, &refclass->byval_arg));
6590                 CACHE_OBJECT (MonoReflectionMethod *, method, (MonoReflectionMethod*)gret, refclass);
6591         }
6592
6593         if (!refclass)
6594                 refclass = method->klass;
6595
6596         CHECK_OBJECT (MonoReflectionMethod *, method, refclass);
6597         if (*method->name == '.' && (strcmp (method->name, ".ctor") == 0 || strcmp (method->name, ".cctor") == 0)) {
6598                 if (!System_Reflection_MonoCMethod)
6599                         System_Reflection_MonoCMethod = mono_class_from_name (mono_defaults.corlib, "System.Reflection", "MonoCMethod");
6600                 klass = System_Reflection_MonoCMethod;
6601         }
6602         else {
6603                 if (!System_Reflection_MonoMethod)
6604                         System_Reflection_MonoMethod = mono_class_from_name (mono_defaults.corlib, "System.Reflection", "MonoMethod");
6605                 klass = System_Reflection_MonoMethod;
6606         }
6607         ret = (MonoReflectionMethod*)mono_object_new (domain, klass);
6608         ret->method = method;
6609         MONO_OBJECT_SETREF (ret, reftype, mono_type_get_object (domain, &refclass->byval_arg));
6610         CACHE_OBJECT (MonoReflectionMethod *, method, ret, refclass);
6611 }
6612
6613 /*
6614  * mono_method_clear_object:
6615  *
6616  *   Clear the cached reflection objects for the dynamic method METHOD.
6617  */
6618 void
6619 mono_method_clear_object (MonoDomain *domain, MonoMethod *method)
6620 {
6621         MonoClass *klass;
6622         g_assert (method->dynamic);
6623
6624         klass = method->klass;
6625         while (klass) {
6626                 clear_cached_object (domain, method, klass);
6627                 klass = klass->parent;
6628         }
6629         /* Added by mono_param_get_objects () */
6630         clear_cached_object (domain, &(method->signature), NULL);
6631         klass = method->klass;
6632         while (klass) {
6633                 clear_cached_object (domain, &(method->signature), klass);
6634                 klass = klass->parent;
6635         }
6636 }
6637
6638 /*
6639  * mono_field_get_object:
6640  * @domain: an app domain
6641  * @klass: a type
6642  * @field: a field
6643  *
6644  * Return an System.Reflection.MonoField object representing the field @field
6645  * in class @klass.
6646  */
6647 MonoReflectionField*
6648 mono_field_get_object (MonoDomain *domain, MonoClass *klass, MonoClassField *field)
6649 {
6650         MonoReflectionField *res;
6651         static MonoClass *monofield_klass;
6652
6653         CHECK_OBJECT (MonoReflectionField *, field, klass);
6654         if (!monofield_klass)
6655                 monofield_klass = mono_class_from_name (mono_defaults.corlib, "System.Reflection", "MonoField");
6656         res = (MonoReflectionField *)mono_object_new (domain, monofield_klass);
6657         res->klass = klass;
6658         res->field = field;
6659         MONO_OBJECT_SETREF (res, name, mono_string_new (domain, mono_field_get_name (field)));
6660
6661         if (is_field_on_inst (field)) {
6662                 res->attrs = get_field_on_inst_generic_type (field)->attrs;
6663                 MONO_OBJECT_SETREF (res, type, mono_type_get_object (domain, field->type));
6664         } else {
6665                 if (field->type)
6666                         MONO_OBJECT_SETREF (res, type, mono_type_get_object (domain, field->type));
6667                 res->attrs = mono_field_get_flags (field);
6668         }
6669         CACHE_OBJECT (MonoReflectionField *, field, res, klass);
6670 }
6671
6672 /*
6673  * mono_property_get_object:
6674  * @domain: an app domain
6675  * @klass: a type
6676  * @property: a property
6677  *
6678  * Return an System.Reflection.MonoProperty object representing the property @property
6679  * in class @klass.
6680  */
6681 MonoReflectionProperty*
6682 mono_property_get_object (MonoDomain *domain, MonoClass *klass, MonoProperty *property)
6683 {
6684         MonoReflectionProperty *res;
6685         static MonoClass *monoproperty_klass;
6686
6687         CHECK_OBJECT (MonoReflectionProperty *, property, klass);
6688         if (!monoproperty_klass)
6689                 monoproperty_klass = mono_class_from_name (mono_defaults.corlib, "System.Reflection", "MonoProperty");
6690         res = (MonoReflectionProperty *)mono_object_new (domain, monoproperty_klass);
6691         res->klass = klass;
6692         res->property = property;
6693         CACHE_OBJECT (MonoReflectionProperty *, property, res, klass);
6694 }
6695
6696 /*
6697  * mono_event_get_object:
6698  * @domain: an app domain
6699  * @klass: a type
6700  * @event: a event
6701  *
6702  * Return an System.Reflection.MonoEvent object representing the event @event
6703  * in class @klass.
6704  */
6705 MonoReflectionEvent*
6706 mono_event_get_object (MonoDomain *domain, MonoClass *klass, MonoEvent *event)
6707 {
6708         MonoReflectionEvent *res;
6709         MonoReflectionMonoEvent *mono_event;
6710         static MonoClass *monoevent_klass;
6711
6712         CHECK_OBJECT (MonoReflectionEvent *, event, klass);
6713         if (!monoevent_klass)
6714                 monoevent_klass = mono_class_from_name (mono_defaults.corlib, "System.Reflection", "MonoEvent");
6715         mono_event = (MonoReflectionMonoEvent *)mono_object_new (domain, monoevent_klass);
6716         mono_event->klass = klass;
6717         mono_event->event = event;
6718         res = (MonoReflectionEvent*)mono_event;
6719         CACHE_OBJECT (MonoReflectionEvent *, event, res, klass);
6720 }
6721
6722 /**
6723  * mono_get_reflection_missing_object:
6724  * @domain: Domain where the object lives
6725  *
6726  * Returns the System.Reflection.Missing.Value singleton object
6727  * (of type System.Reflection.Missing).
6728  *
6729  * Used as the value for ParameterInfo.DefaultValue when Optional
6730  * is present
6731  */
6732 static MonoObject *
6733 mono_get_reflection_missing_object (MonoDomain *domain)
6734 {
6735         MonoObject *obj;
6736         static MonoClassField *missing_value_field = NULL;
6737         
6738         if (!missing_value_field) {
6739                 MonoClass *missing_klass;
6740                 missing_klass = mono_class_from_name (mono_defaults.corlib, "System.Reflection", "Missing");
6741                 mono_class_init (missing_klass);
6742                 missing_value_field = mono_class_get_field_from_name (missing_klass, "Value");
6743                 g_assert (missing_value_field);
6744         }
6745         obj = mono_field_get_value_object (domain, missing_value_field, NULL); 
6746         g_assert (obj);
6747         return obj;
6748 }
6749
6750 static MonoObject*
6751 get_dbnull (MonoDomain *domain, MonoObject **dbnull)
6752 {
6753         if (!*dbnull)
6754                 *dbnull = mono_get_dbnull_object (domain);
6755         return *dbnull;
6756 }
6757
6758 static MonoObject*
6759 get_reflection_missing (MonoDomain *domain, MonoObject **reflection_missing)
6760 {
6761         if (!*reflection_missing)
6762                 *reflection_missing = mono_get_reflection_missing_object (domain);
6763         return *reflection_missing;
6764 }
6765
6766 /*
6767  * mono_param_get_objects:
6768  * @domain: an app domain
6769  * @method: a method
6770  *
6771  * Return an System.Reflection.ParameterInfo array object representing the parameters
6772  * in the method @method.
6773  */
6774 MonoArray*
6775 mono_param_get_objects_internal (MonoDomain *domain, MonoMethod *method, MonoClass *refclass)
6776 {
6777         static MonoClass *System_Reflection_ParameterInfo;
6778         static MonoClass *System_Reflection_ParameterInfo_array;
6779         MonoError error;
6780         MonoArray *res = NULL;
6781         MonoReflectionMethod *member = NULL;
6782         MonoReflectionParameter *param = NULL;
6783         char **names, **blobs = NULL;
6784         guint32 *types = NULL;
6785         MonoType *type = NULL;
6786         MonoObject *dbnull = NULL;
6787         MonoObject *missing = NULL;
6788         MonoMarshalSpec **mspecs;
6789         MonoMethodSignature *sig;
6790         MonoVTable *pinfo_vtable;
6791         int i;
6792
6793         if (!System_Reflection_ParameterInfo_array) {
6794                 MonoClass *klass;
6795
6796                 klass = mono_class_from_name (mono_defaults.corlib, "System.Reflection", "MonoParameterInfo");
6797                 if (!klass)
6798                         klass = mono_class_from_name (mono_defaults.corlib, "System.Reflection", "ParameterInfo");
6799
6800                 mono_memory_barrier ();
6801                 System_Reflection_ParameterInfo = klass; 
6802
6803         
6804                 klass = mono_array_class_get (klass, 1);
6805                 mono_memory_barrier ();
6806                 System_Reflection_ParameterInfo_array = klass;
6807         }
6808
6809         sig = mono_method_signature_checked (method, &error);
6810         if (!mono_error_ok (&error))
6811                 mono_error_raise_exception (&error);
6812
6813         if (!sig->param_count)
6814                 return mono_array_new_specific (mono_class_vtable (domain, System_Reflection_ParameterInfo_array), 0);
6815
6816         /* Note: the cache is based on the address of the signature into the method
6817          * since we already cache MethodInfos with the method as keys.
6818          */
6819         CHECK_OBJECT (MonoArray*, &(method->signature), refclass);
6820
6821         member = mono_method_get_object (domain, method, refclass);
6822         names = g_new (char *, sig->param_count);
6823         mono_method_get_param_names (method, (const char **) names);
6824
6825         mspecs = g_new (MonoMarshalSpec*, sig->param_count + 1);
6826         mono_method_get_marshal_info (method, mspecs);
6827
6828         res = mono_array_new_specific (mono_class_vtable (domain, System_Reflection_ParameterInfo_array), sig->param_count);
6829         pinfo_vtable = mono_class_vtable (domain, System_Reflection_ParameterInfo);
6830         for (i = 0; i < sig->param_count; ++i) {
6831                 param = (MonoReflectionParameter *)mono_object_new_specific (pinfo_vtable);
6832                 MONO_OBJECT_SETREF (param, ClassImpl, mono_type_get_object (domain, sig->params [i]));
6833                 MONO_OBJECT_SETREF (param, MemberImpl, (MonoObject*)member);
6834                 MONO_OBJECT_SETREF (param, NameImpl, mono_string_new (domain, names [i]));
6835                 param->PositionImpl = i;
6836                 param->AttrsImpl = sig->params [i]->attrs;
6837
6838                 if (!(param->AttrsImpl & PARAM_ATTRIBUTE_HAS_DEFAULT)) {
6839                         if (param->AttrsImpl & PARAM_ATTRIBUTE_OPTIONAL)
6840                                 MONO_OBJECT_SETREF (param, DefaultValueImpl, get_reflection_missing (domain, &missing));
6841                         else
6842                                 MONO_OBJECT_SETREF (param, DefaultValueImpl, get_dbnull (domain, &dbnull));
6843                 } else {
6844
6845                         if (!blobs) {
6846                                 blobs = g_new0 (char *, sig->param_count);
6847                                 types = g_new0 (guint32, sig->param_count);
6848                                 get_default_param_value_blobs (method, blobs, types); 
6849                         }
6850
6851                         /* Build MonoType for the type from the Constant Table */
6852                         if (!type)
6853                                 type = g_new0 (MonoType, 1);
6854                         type->type = types [i];
6855                         type->data.klass = NULL;
6856                         if (types [i] == MONO_TYPE_CLASS)
6857                                 type->data.klass = mono_defaults.object_class;
6858                         else if ((sig->params [i]->type == MONO_TYPE_VALUETYPE) && sig->params [i]->data.klass->enumtype) {
6859                                 /* For enums, types [i] contains the base type */
6860
6861                                         type->type = MONO_TYPE_VALUETYPE;
6862                                         type->data.klass = mono_class_from_mono_type (sig->params [i]);
6863                         } else
6864                                 type->data.klass = mono_class_from_mono_type (type);
6865
6866                         MONO_OBJECT_SETREF (param, DefaultValueImpl, mono_get_object_from_blob (domain, type, blobs [i]));
6867
6868                         /* Type in the Constant table is MONO_TYPE_CLASS for nulls */
6869                         if (types [i] != MONO_TYPE_CLASS && !param->DefaultValueImpl) {
6870                                 if (param->AttrsImpl & PARAM_ATTRIBUTE_OPTIONAL)
6871                                         MONO_OBJECT_SETREF (param, DefaultValueImpl, get_reflection_missing (domain, &missing));
6872                                 else
6873                                         MONO_OBJECT_SETREF (param, DefaultValueImpl, get_dbnull (domain, &dbnull));
6874                         }
6875                         
6876                 }
6877
6878                 if (mspecs [i + 1])
6879                         MONO_OBJECT_SETREF (param, MarshalAsImpl, (MonoObject*)mono_reflection_marshal_as_attribute_from_marshal_spec (domain, method->klass, mspecs [i + 1]));
6880                 
6881                 mono_array_setref (res, i, param);
6882         }
6883         g_free (names);
6884         g_free (blobs);
6885         g_free (types);
6886         g_free (type);
6887
6888         for (i = mono_method_signature (method)->param_count; i >= 0; i--)
6889                 if (mspecs [i])
6890                         mono_metadata_free_marshal_spec (mspecs [i]);
6891         g_free (mspecs);
6892         
6893         CACHE_OBJECT (MonoArray *, &(method->signature), res, refclass);
6894 }
6895
6896 MonoArray*
6897 mono_param_get_objects (MonoDomain *domain, MonoMethod *method)
6898 {
6899         return mono_param_get_objects_internal (domain, method, NULL);
6900 }
6901
6902 /*
6903  * mono_method_body_get_object:
6904  * @domain: an app domain
6905  * @method: a method
6906  *
6907  * Return an System.Reflection.MethodBody object representing the method @method.
6908  */
6909 MonoReflectionMethodBody*
6910 mono_method_body_get_object (MonoDomain *domain, MonoMethod *method)
6911 {
6912         static MonoClass *System_Reflection_MethodBody = NULL;
6913         static MonoClass *System_Reflection_LocalVariableInfo = NULL;
6914         static MonoClass *System_Reflection_ExceptionHandlingClause = NULL;
6915         MonoReflectionMethodBody *ret;
6916         MonoMethodHeader *header;
6917         MonoImage *image;
6918         guint32 method_rva, local_var_sig_token;
6919     char *ptr;
6920         unsigned char format, flags;
6921         int i;
6922
6923         /* for compatibility with .net */
6924     if (method->dynamic)
6925         mono_raise_exception (mono_get_exception_invalid_operation (NULL));
6926
6927         if (!System_Reflection_MethodBody)
6928                 System_Reflection_MethodBody = mono_class_from_name (mono_defaults.corlib, "System.Reflection", "MethodBody");
6929         if (!System_Reflection_LocalVariableInfo)
6930                 System_Reflection_LocalVariableInfo = mono_class_from_name (mono_defaults.corlib, "System.Reflection", "LocalVariableInfo");
6931         if (!System_Reflection_ExceptionHandlingClause)
6932                 System_Reflection_ExceptionHandlingClause = mono_class_from_name (mono_defaults.corlib, "System.Reflection", "ExceptionHandlingClause");
6933
6934         CHECK_OBJECT (MonoReflectionMethodBody *, method, NULL);
6935
6936         if ((method->flags & METHOD_ATTRIBUTE_PINVOKE_IMPL) ||
6937                 (method->flags & METHOD_ATTRIBUTE_ABSTRACT) ||
6938             (method->iflags & METHOD_IMPL_ATTRIBUTE_INTERNAL_CALL) ||
6939             (method->iflags & METHOD_IMPL_ATTRIBUTE_RUNTIME))
6940                 return NULL;
6941
6942         image = method->klass->image;
6943         header = mono_method_get_header (method);
6944
6945         if (!image->dynamic) {
6946                 /* Obtain local vars signature token */
6947                 method_rva = mono_metadata_decode_row_col (&image->tables [MONO_TABLE_METHOD], mono_metadata_token_index (method->token) - 1, MONO_METHOD_RVA);
6948                 ptr = mono_image_rva_map (image, method_rva);
6949                 flags = *(const unsigned char *) ptr;
6950                 format = flags & METHOD_HEADER_FORMAT_MASK;
6951                 switch (format){
6952                 case METHOD_HEADER_TINY_FORMAT:
6953                         local_var_sig_token = 0;
6954                         break;
6955                 case METHOD_HEADER_FAT_FORMAT:
6956                         ptr += 2;
6957                         ptr += 2;
6958                         ptr += 4;
6959                         local_var_sig_token = read32 (ptr);
6960                         break;
6961                 default:
6962                         g_assert_not_reached ();
6963                 }
6964         } else
6965                 local_var_sig_token = 0; //FIXME
6966
6967         ret = (MonoReflectionMethodBody*)mono_object_new (domain, System_Reflection_MethodBody);
6968
6969         ret->init_locals = header->init_locals;
6970         ret->max_stack = header->max_stack;
6971         ret->local_var_sig_token = local_var_sig_token;
6972         MONO_OBJECT_SETREF (ret, il, mono_array_new_cached (domain, mono_defaults.byte_class, header->code_size));
6973         memcpy (mono_array_addr (ret->il, guint8, 0), header->code, header->code_size);
6974
6975         /* Locals */
6976         MONO_OBJECT_SETREF (ret, locals, mono_array_new_cached (domain, System_Reflection_LocalVariableInfo, header->num_locals));
6977         for (i = 0; i < header->num_locals; ++i) {
6978                 MonoReflectionLocalVariableInfo *info = (MonoReflectionLocalVariableInfo*)mono_object_new (domain, System_Reflection_LocalVariableInfo);
6979                 MONO_OBJECT_SETREF (info, local_type, mono_type_get_object (domain, header->locals [i]));
6980                 info->is_pinned = header->locals [i]->pinned;
6981                 info->local_index = i;
6982                 mono_array_setref (ret->locals, i, info);
6983         }
6984
6985         /* Exceptions */
6986         MONO_OBJECT_SETREF (ret, clauses, mono_array_new_cached (domain, System_Reflection_ExceptionHandlingClause, header->num_clauses));
6987         for (i = 0; i < header->num_clauses; ++i) {
6988                 MonoReflectionExceptionHandlingClause *info = (MonoReflectionExceptionHandlingClause*)mono_object_new (domain, System_Reflection_ExceptionHandlingClause);
6989                 MonoExceptionClause *clause = &header->clauses [i];
6990
6991                 info->flags = clause->flags;
6992                 info->try_offset = clause->try_offset;
6993                 info->try_length = clause->try_len;
6994                 info->handler_offset = clause->handler_offset;
6995                 info->handler_length = clause->handler_len;
6996                 if (clause->flags == MONO_EXCEPTION_CLAUSE_FILTER)
6997                         info->filter_offset = clause->data.filter_offset;
6998                 else if (clause->data.catch_class)
6999                         MONO_OBJECT_SETREF (info, catch_type, mono_type_get_object (mono_domain_get (), &clause->data.catch_class->byval_arg));
7000
7001                 mono_array_setref (ret->clauses, i, info);
7002         }
7003
7004         mono_metadata_free_mh (header);
7005         CACHE_OBJECT (MonoReflectionMethodBody *, method, ret, NULL);
7006         return ret;
7007 }
7008
7009 /**
7010  * mono_get_dbnull_object:
7011  * @domain: Domain where the object lives
7012  *
7013  * Returns the System.DBNull.Value singleton object
7014  *
7015  * Used as the value for ParameterInfo.DefaultValue 
7016  */
7017 MonoObject *
7018 mono_get_dbnull_object (MonoDomain *domain)
7019 {
7020         MonoObject *obj;
7021         static MonoClassField *dbnull_value_field = NULL;
7022         
7023         if (!dbnull_value_field) {
7024                 MonoClass *dbnull_klass;
7025                 dbnull_klass = mono_class_from_name (mono_defaults.corlib, "System", "DBNull");
7026                 mono_class_init (dbnull_klass);
7027                 dbnull_value_field = mono_class_get_field_from_name (dbnull_klass, "Value");
7028                 g_assert (dbnull_value_field);
7029         }
7030         obj = mono_field_get_value_object (domain, dbnull_value_field, NULL); 
7031         g_assert (obj);
7032         return obj;
7033 }
7034
7035 static void
7036 get_default_param_value_blobs (MonoMethod *method, char **blobs, guint32 *types)
7037 {
7038         guint32 param_index, i, lastp, crow = 0;
7039         guint32 param_cols [MONO_PARAM_SIZE], const_cols [MONO_CONSTANT_SIZE];
7040         gint32 idx;
7041
7042         MonoClass *klass = method->klass;
7043         MonoImage *image = klass->image;
7044         MonoMethodSignature *methodsig = mono_method_signature (method);
7045
7046         MonoTableInfo *constt;
7047         MonoTableInfo *methodt;
7048         MonoTableInfo *paramt;
7049
7050         if (!methodsig->param_count)
7051                 return;
7052
7053         mono_class_init (klass);
7054
7055         if (klass->image->dynamic) {
7056                 MonoReflectionMethodAux *aux;
7057                 if (method->is_inflated)
7058                         method = ((MonoMethodInflated*)method)->declaring;
7059                 aux = g_hash_table_lookup (((MonoDynamicImage*)method->klass->image)->method_aux_hash, method);
7060                 if (aux && aux->param_defaults) {
7061                         memcpy (blobs, &(aux->param_defaults [1]), methodsig->param_count * sizeof (char*));
7062                         memcpy (types, &(aux->param_default_types [1]), methodsig->param_count * sizeof (guint32));
7063                 }
7064                 return;
7065         }
7066
7067         methodt = &klass->image->tables [MONO_TABLE_METHOD];
7068         paramt = &klass->image->tables [MONO_TABLE_PARAM];
7069         constt = &image->tables [MONO_TABLE_CONSTANT];
7070
7071         idx = mono_method_get_index (method) - 1;
7072         g_assert (idx != -1);
7073
7074         param_index = mono_metadata_decode_row_col (methodt, idx, MONO_METHOD_PARAMLIST);
7075         if (idx + 1 < methodt->rows)
7076                 lastp = mono_metadata_decode_row_col (methodt, idx + 1, MONO_METHOD_PARAMLIST);
7077         else
7078                 lastp = paramt->rows + 1;
7079
7080         for (i = param_index; i < lastp; ++i) {
7081                 guint32 paramseq;
7082
7083                 mono_metadata_decode_row (paramt, i - 1, param_cols, MONO_PARAM_SIZE);
7084                 paramseq = param_cols [MONO_PARAM_SEQUENCE];
7085
7086                 if (!(param_cols [MONO_PARAM_FLAGS] & PARAM_ATTRIBUTE_HAS_DEFAULT))
7087                         continue;
7088
7089                 crow = mono_metadata_get_constant_index (image, MONO_TOKEN_PARAM_DEF | i, crow + 1);
7090                 if (!crow) {
7091                         continue;
7092                 }
7093         
7094                 mono_metadata_decode_row (constt, crow - 1, const_cols, MONO_CONSTANT_SIZE);
7095                 blobs [paramseq - 1] = (gpointer) mono_metadata_blob_heap (image, const_cols [MONO_CONSTANT_VALUE]);
7096                 types [paramseq - 1] = const_cols [MONO_CONSTANT_TYPE];
7097         }
7098
7099         return;
7100 }
7101
7102 MonoObject *
7103 mono_get_object_from_blob (MonoDomain *domain, MonoType *type, const char *blob)
7104 {
7105         void *retval;
7106         MonoClass *klass;
7107         MonoObject *object;
7108         MonoType *basetype = type;
7109
7110         if (!blob)
7111                 return NULL;
7112         
7113         klass = mono_class_from_mono_type (type);
7114         if (klass->valuetype) {
7115                 object = mono_object_new (domain, klass);
7116                 retval = ((gchar *) object + sizeof (MonoObject));
7117                 if (klass->enumtype)
7118                         basetype = mono_class_enum_basetype (klass);
7119         } else {
7120                 retval = &object;
7121         }
7122                         
7123         if (!mono_get_constant_value_from_blob (domain, basetype->type,  blob, retval))
7124                 return object;
7125         else
7126                 return NULL;
7127 }
7128
7129 static int
7130 assembly_name_to_aname (MonoAssemblyName *assembly, char *p) {
7131         int found_sep;
7132         char *s;
7133         gboolean quoted = FALSE;
7134
7135         memset (assembly, 0, sizeof (MonoAssemblyName));
7136         assembly->culture = "";
7137         memset (assembly->public_key_token, 0, MONO_PUBLIC_KEY_TOKEN_LENGTH);
7138
7139         if (*p == '"') {
7140                 quoted = TRUE;
7141                 p++;
7142         }
7143         assembly->name = p;
7144         while (*p && (isalnum (*p) || *p == '.' || *p == '-' || *p == '_' || *p == '$' || *p == '@' || g_ascii_isspace (*p)))
7145                 p++;
7146         if (quoted) {
7147                 if (*p != '"')
7148                         return 1;
7149                 *p = 0;
7150                 p++;
7151         }
7152         if (*p != ',')
7153                 return 1;
7154         *p = 0;
7155         /* Remove trailing whitespace */
7156         s = p - 1;
7157         while (*s && g_ascii_isspace (*s))
7158                 *s-- = 0;
7159         p ++;
7160         while (g_ascii_isspace (*p))
7161                 p++;
7162         while (*p) {
7163                 if (*p == 'V' && g_ascii_strncasecmp (p, "Version=", 8) == 0) {
7164                         p += 8;
7165                         assembly->major = strtoul (p, &s, 10);
7166                         if (s == p || *s != '.')
7167                                 return 1;
7168                         p = ++s;
7169                         assembly->minor = strtoul (p, &s, 10);
7170                         if (s == p || *s != '.')
7171                                 return 1;
7172                         p = ++s;
7173                         assembly->build = strtoul (p, &s, 10);
7174                         if (s == p || *s != '.')
7175                                 return 1;
7176                         p = ++s;
7177                         assembly->revision = strtoul (p, &s, 10);
7178                         if (s == p)
7179                                 return 1;
7180                         p = s;
7181                 } else if (*p == 'C' && g_ascii_strncasecmp (p, "Culture=", 8) == 0) {
7182                         p += 8;
7183                         if (g_ascii_strncasecmp (p, "neutral", 7) == 0) {
7184                                 assembly->culture = "";
7185                                 p += 7;
7186                         } else {
7187                                 assembly->culture = p;
7188                                 while (*p && *p != ',') {
7189                                         p++;
7190                                 }
7191                         }
7192                 } else if (*p == 'P' && g_ascii_strncasecmp (p, "PublicKeyToken=", 15) == 0) {
7193                         p += 15;
7194                         if (strncmp (p, "null", 4) == 0) {
7195                                 p += 4;
7196                         } else {
7197                                 int len;
7198                                 gchar *start = p;
7199                                 while (*p && *p != ',') {
7200                                         p++;
7201                                 }
7202                                 len = (p - start + 1);
7203                                 if (len > MONO_PUBLIC_KEY_TOKEN_LENGTH)
7204                                         len = MONO_PUBLIC_KEY_TOKEN_LENGTH;
7205                                 g_strlcpy ((char*)assembly->public_key_token, start, len);
7206                         }
7207                 } else {
7208                         while (*p && *p != ',')
7209                                 p++;
7210                 }
7211                 found_sep = 0;
7212                 while (g_ascii_isspace (*p) || *p == ',') {
7213                         *p++ = 0;
7214                         found_sep = 1;
7215                         continue;
7216                 }
7217                 /* failed */
7218                 if (!found_sep)
7219                         return 1;
7220         }
7221
7222         return 0;
7223 }
7224
7225 /*
7226  * mono_reflection_parse_type:
7227  * @name: type name
7228  *
7229  * Parse a type name as accepted by the GetType () method and output the info
7230  * extracted in the info structure.
7231  * the name param will be mangled, so, make a copy before passing it to this function.
7232  * The fields in info will be valid until the memory pointed to by name is valid.
7233  *
7234  * See also mono_type_get_name () below.
7235  *
7236  * Returns: 0 on parse error.
7237  */
7238 static int
7239 _mono_reflection_parse_type (char *name, char **endptr, gboolean is_recursed,
7240                              MonoTypeNameParse *info)
7241 {
7242         char *start, *p, *w, *last_point, *startn;
7243         int in_modifiers = 0;
7244         int isbyref = 0, rank = 0;
7245
7246         start = p = w = name;
7247
7248         //FIXME could we just zero the whole struct? memset (&info, 0, sizeof (MonoTypeNameParse))
7249         memset (&info->assembly, 0, sizeof (MonoAssemblyName));
7250         info->name = info->name_space = NULL;
7251         info->nested = NULL;
7252         info->modifiers = NULL;
7253         info->type_arguments = NULL;
7254
7255         /* last_point separates the namespace from the name */
7256         last_point = NULL;
7257         /* Skips spaces */
7258         while (*p == ' ') p++, start++, w++, name++;
7259
7260         while (*p) {
7261                 switch (*p) {
7262                 case '+':
7263                         *p = 0; /* NULL terminate the name */
7264                         startn = p + 1;
7265                         info->nested = g_list_append (info->nested, startn);
7266                         /* we have parsed the nesting namespace + name */
7267                         if (info->name)
7268                                 break;
7269                         if (last_point) {
7270                                 info->name_space = start;
7271                                 *last_point = 0;
7272                                 info->name = last_point + 1;
7273                         } else {
7274                                 info->name_space = (char *)"";
7275                                 info->name = start;
7276                         }
7277                         break;
7278                 case '.':
7279                         last_point = p;
7280                         break;
7281                 case '\\':
7282                         ++p;
7283                         break;
7284                 case '&':
7285                 case '*':
7286                 case '[':
7287                 case ',':
7288                 case ']':
7289                         in_modifiers = 1;
7290                         break;
7291                 default:
7292                         break;
7293                 }
7294                 if (in_modifiers)
7295                         break;
7296                 // *w++ = *p++;
7297                 p++;
7298         }
7299         
7300         if (!info->name) {
7301                 if (last_point) {
7302                         info->name_space = start;
7303                         *last_point = 0;
7304                         info->name = last_point + 1;
7305                 } else {
7306                         info->name_space = (char *)"";
7307                         info->name = start;
7308                 }
7309         }
7310         while (*p) {
7311                 switch (*p) {
7312                 case '&':
7313                         if (isbyref) /* only one level allowed by the spec */
7314                                 return 0;
7315                         isbyref = 1;
7316                         info->modifiers = g_list_append (info->modifiers, GUINT_TO_POINTER (0));
7317                         *p++ = 0;
7318                         break;
7319                 case '*':
7320                         info->modifiers = g_list_append (info->modifiers, GUINT_TO_POINTER (-1));
7321                         *p++ = 0;
7322                         break;
7323                 case '[':
7324                         //Decide if it's an array of a generic argument list
7325                         *p++ = 0;
7326
7327                         if (!*p) //XXX test
7328                                 return 0;
7329                         if (*p  == ',' || *p == '*' || *p == ']') { //array
7330                                 rank = 1;
7331                                 while (*p) {
7332                                         if (*p == ']')
7333                                                 break;
7334                                         if (*p == ',')
7335                                                 rank++;
7336                                         else if (*p == '*') /* '*' means unknown lower bound */
7337                                                 info->modifiers = g_list_append (info->modifiers, GUINT_TO_POINTER (-2));
7338                                         else
7339                                                 return 0;
7340                                         ++p;
7341                                 }
7342                                 if (*p++ != ']')
7343                                         return 0;
7344                                 info->modifiers = g_list_append (info->modifiers, GUINT_TO_POINTER (rank));
7345                         } else {
7346                                 if (rank) /* generic args after array spec*/ //XXX test
7347                                         return 0;
7348                                 info->type_arguments = g_ptr_array_new ();
7349                                 while (*p) {
7350                                         MonoTypeNameParse *subinfo = g_new0 (MonoTypeNameParse, 1);
7351                                         gboolean fqname = FALSE;
7352
7353                                         g_ptr_array_add (info->type_arguments, subinfo);
7354
7355                                         if (*p == '[') {
7356                                                 p++;
7357                                                 fqname = TRUE;
7358                                         }
7359
7360                                         if (!_mono_reflection_parse_type (p, &p, TRUE, subinfo))
7361                                                 return 0;
7362
7363                                         /*MS is lenient on [] delimited parameters that aren't fqn - and F# uses them.*/
7364                                         if (fqname && (*p != ']')) {
7365                                                 char *aname;
7366
7367                                                 if (*p != ',')
7368                                                         return 0;
7369                                                 *p++ = 0;
7370
7371                                                 aname = p;
7372                                                 while (*p && (*p != ']'))
7373                                                         p++;
7374
7375                                                 if (*p != ']')
7376                                                         return 0;
7377
7378                                                 *p++ = 0;
7379                                                 while (*aname) {
7380                                                         if (g_ascii_isspace (*aname)) {
7381                                                                 ++aname;
7382                                                                 continue;
7383                                                         }
7384                                                         break;
7385                                                 }
7386                                                 if (!*aname ||
7387                                                     !assembly_name_to_aname (&subinfo->assembly, aname))
7388                                                         return 0;
7389                                         } else if (fqname && (*p == ']')) {
7390                                                 *p++ = 0;
7391                                         }
7392                                         if (*p == ']') {
7393                                                 *p++ = 0;
7394                                                 break;
7395                                         } else if (!*p) {
7396                                                 return 0;
7397                                         }
7398                                         *p++ = 0;
7399                                 }
7400                         }
7401                         break;
7402                 case ']':
7403                         if (is_recursed)
7404                                 goto end;
7405                         return 0;
7406                 case ',':
7407                         if (is_recursed)
7408                                 goto end;
7409                         *p++ = 0;
7410                         while (*p) {
7411                                 if (g_ascii_isspace (*p)) {
7412                                         ++p;
7413                                         continue;
7414                                 }
7415                                 break;
7416                         }
7417                         if (!*p)
7418                                 return 0; /* missing assembly name */
7419                         if (!assembly_name_to_aname (&info->assembly, p))
7420                                 return 0;
7421                         break;
7422                 default:
7423                         return 0;
7424                 }
7425                 if (info->assembly.name)
7426                         break;
7427         }
7428         // *w = 0; /* terminate class name */
7429  end:
7430         if (!info->name || !*info->name)
7431                 return 0;
7432         if (endptr)
7433                 *endptr = p;
7434         /* add other consistency checks */
7435         return 1;
7436 }
7437
7438 int
7439 mono_reflection_parse_type (char *name, MonoTypeNameParse *info)
7440 {
7441         return _mono_reflection_parse_type (name, NULL, FALSE, info);
7442 }
7443
7444 static MonoType*
7445 _mono_reflection_get_type_from_info (MonoTypeNameParse *info, MonoImage *image, gboolean ignorecase)
7446 {
7447         gboolean type_resolve = FALSE;
7448         MonoType *type;
7449         MonoImage *rootimage = image;
7450
7451         if (info->assembly.name) {
7452                 MonoAssembly *assembly = mono_assembly_loaded (&info->assembly);
7453                 if (!assembly && image && image->assembly && mono_assembly_names_equal (&info->assembly, &image->assembly->aname))
7454                         /* 
7455                          * This could happen in the AOT compiler case when the search hook is not
7456                          * installed.
7457                          */
7458                         assembly = image->assembly;
7459                 if (!assembly) {
7460                         /* then we must load the assembly ourselve - see #60439 */
7461                         assembly = mono_assembly_load (&info->assembly, NULL, NULL);
7462                         if (!assembly)
7463                                 return NULL;
7464                 }
7465                 image = assembly->image;
7466         } else if (!image) {
7467                 image = mono_defaults.corlib;
7468         }
7469
7470         type = mono_reflection_get_type_with_rootimage (rootimage, image, info, ignorecase, &type_resolve);
7471         if (type == NULL && !info->assembly.name && image != mono_defaults.corlib) {
7472                 image = mono_defaults.corlib;
7473                 type = mono_reflection_get_type_with_rootimage (rootimage, image, info, ignorecase, &type_resolve);
7474         }
7475
7476         return type;
7477 }
7478
7479 static MonoType*
7480 mono_reflection_get_type_internal (MonoImage *rootimage, MonoImage* image, MonoTypeNameParse *info, gboolean ignorecase)
7481 {
7482         MonoClass *klass;
7483         GList *mod;
7484         int modval;
7485         gboolean bounded = FALSE;
7486         
7487         if (!image)
7488                 image = mono_defaults.corlib;
7489
7490         if (ignorecase)
7491                 klass = mono_class_from_name_case (image, info->name_space, info->name);
7492         else
7493                 klass = mono_class_from_name (image, info->name_space, info->name);
7494         if (!klass)
7495                 return NULL;
7496         for (mod = info->nested; mod; mod = mod->next) {
7497                 gpointer iter = NULL;
7498                 MonoClass *parent;
7499
7500                 parent = klass;
7501                 mono_class_init (parent);
7502
7503                 while ((klass = mono_class_get_nested_types (parent, &iter))) {
7504                         if (ignorecase) {
7505                                 if (mono_utf8_strcasecmp (klass->name, mod->data) == 0)
7506                                         break;
7507                         } else {
7508                                 if (strcmp (klass->name, mod->data) == 0)
7509                                         break;
7510                         }
7511                 }
7512                 if (!klass)
7513                         break;
7514         }
7515         if (!klass)
7516                 return NULL;
7517
7518         if (info->type_arguments) {
7519                 MonoType **type_args = g_new0 (MonoType *, info->type_arguments->len);
7520                 MonoReflectionType *the_type;
7521                 MonoType *instance;
7522                 int i;
7523
7524                 for (i = 0; i < info->type_arguments->len; i++) {
7525                         MonoTypeNameParse *subinfo = g_ptr_array_index (info->type_arguments, i);
7526
7527                         type_args [i] = _mono_reflection_get_type_from_info (subinfo, rootimage, ignorecase);
7528                         if (!type_args [i]) {
7529                                 g_free (type_args);
7530                                 return NULL;
7531                         }
7532                 }
7533
7534                 the_type = mono_type_get_object (mono_domain_get (), &klass->byval_arg);
7535
7536                 instance = mono_reflection_bind_generic_parameters (
7537                         the_type, info->type_arguments->len, type_args);
7538
7539                 g_free (type_args);
7540                 if (!instance)
7541                         return NULL;
7542
7543                 klass = mono_class_from_mono_type (instance);
7544         }
7545
7546         for (mod = info->modifiers; mod; mod = mod->next) {
7547                 modval = GPOINTER_TO_UINT (mod->data);
7548                 if (!modval) { /* byref: must be last modifier */
7549                         return &klass->this_arg;
7550                 } else if (modval == -1) {
7551                         klass = mono_ptr_class_get (&klass->byval_arg);
7552                 } else if (modval == -2) {
7553                         bounded = TRUE;
7554                 } else { /* array rank */
7555                         klass = mono_bounded_array_class_get (klass, modval, bounded);
7556                 }
7557         }
7558
7559         return &klass->byval_arg;
7560 }
7561
7562 /*
7563  * mono_reflection_get_type:
7564  * @image: a metadata context
7565  * @info: type description structure
7566  * @ignorecase: flag for case-insensitive string compares
7567  * @type_resolve: whenever type resolve was already tried
7568  *
7569  * Build a MonoType from the type description in @info.
7570  * 
7571  */
7572
7573 MonoType*
7574 mono_reflection_get_type (MonoImage* image, MonoTypeNameParse *info, gboolean ignorecase, gboolean *type_resolve) {
7575         return mono_reflection_get_type_with_rootimage(image, image, info, ignorecase, type_resolve);
7576 }
7577
7578 static MonoType*
7579 mono_reflection_get_type_internal_dynamic (MonoImage *rootimage, MonoAssembly *assembly, MonoTypeNameParse *info, gboolean ignorecase)
7580 {
7581         MonoReflectionAssemblyBuilder *abuilder;
7582         MonoType *type;
7583         int i;
7584
7585         g_assert (assembly->dynamic);
7586         abuilder = (MonoReflectionAssemblyBuilder*)mono_assembly_get_object (((MonoDynamicAssembly*)assembly)->domain, assembly);
7587
7588         /* Enumerate all modules */
7589
7590         type = NULL;
7591         if (abuilder->modules) {
7592                 for (i = 0; i < mono_array_length (abuilder->modules); ++i) {
7593                         MonoReflectionModuleBuilder *mb = mono_array_get (abuilder->modules, MonoReflectionModuleBuilder*, i);
7594                         type = mono_reflection_get_type_internal (rootimage, &mb->dynamic_image->image, info, ignorecase);
7595                         if (type)
7596                                 break;
7597                 }
7598         }
7599
7600         if (!type && abuilder->loaded_modules) {
7601                 for (i = 0; i < mono_array_length (abuilder->loaded_modules); ++i) {
7602                         MonoReflectionModule *mod = mono_array_get (abuilder->loaded_modules, MonoReflectionModule*, i);
7603                         type = mono_reflection_get_type_internal (rootimage, mod->image, info, ignorecase);
7604                         if (type)
7605                                 break;
7606                 }
7607         }
7608
7609         return type;
7610 }
7611         
7612 MonoType*
7613 mono_reflection_get_type_with_rootimage (MonoImage *rootimage, MonoImage* image, MonoTypeNameParse *info, gboolean ignorecase, gboolean *type_resolve)
7614 {
7615         MonoType *type;
7616         MonoReflectionAssembly *assembly;
7617         GString *fullName;
7618         GList *mod;
7619
7620         if (image && image->dynamic)
7621                 type = mono_reflection_get_type_internal_dynamic (rootimage, image->assembly, info, ignorecase);
7622         else
7623                 type = mono_reflection_get_type_internal (rootimage, image, info, ignorecase);
7624         if (type)
7625                 return type;
7626         if (!mono_domain_has_type_resolve (mono_domain_get ()))
7627                 return NULL;
7628
7629         if (type_resolve) {
7630                 if (*type_resolve) 
7631                         return NULL;
7632                 else
7633                         *type_resolve = TRUE;
7634         }
7635         
7636         /* Reconstruct the type name */
7637         fullName = g_string_new ("");
7638         if (info->name_space && (info->name_space [0] != '\0'))
7639                 g_string_printf (fullName, "%s.%s", info->name_space, info->name);
7640         else
7641                 g_string_printf (fullName, "%s", info->name);
7642         for (mod = info->nested; mod; mod = mod->next)
7643                 g_string_append_printf (fullName, "+%s", (char*)mod->data);
7644
7645         assembly = mono_domain_try_type_resolve ( mono_domain_get (), fullName->str, NULL);
7646         if (assembly) {
7647                 if (assembly->assembly->dynamic)
7648                         type = mono_reflection_get_type_internal_dynamic (rootimage, assembly->assembly, info, ignorecase);
7649                 else
7650                         type = mono_reflection_get_type_internal (rootimage, assembly->assembly->image, 
7651                                                                                                           info, ignorecase);
7652         }
7653         g_string_free (fullName, TRUE);
7654         return type;
7655 }
7656
7657 void
7658 mono_reflection_free_type_info (MonoTypeNameParse *info)
7659 {
7660         g_list_free (info->modifiers);
7661         g_list_free (info->nested);
7662
7663         if (info->type_arguments) {
7664                 int i;
7665
7666                 for (i = 0; i < info->type_arguments->len; i++) {
7667                         MonoTypeNameParse *subinfo = g_ptr_array_index (info->type_arguments, i);
7668
7669                         mono_reflection_free_type_info (subinfo);
7670                         /*We free the subinfo since it is allocated by _mono_reflection_parse_type*/
7671                         g_free (subinfo);
7672                 }
7673
7674                 g_ptr_array_free (info->type_arguments, TRUE);
7675         }
7676 }
7677
7678 /*
7679  * mono_reflection_type_from_name:
7680  * @name: type name.
7681  * @image: a metadata context (can be NULL).
7682  *
7683  * Retrieves a MonoType from its @name. If the name is not fully qualified,
7684  * it defaults to get the type from @image or, if @image is NULL or loading
7685  * from it fails, uses corlib.
7686  * 
7687  */
7688 MonoType*
7689 mono_reflection_type_from_name (char *name, MonoImage *image)
7690 {
7691         MonoType *type = NULL;
7692         MonoTypeNameParse info;
7693         char *tmp;
7694
7695         /* Make a copy since parse_type modifies its argument */
7696         tmp = g_strdup (name);
7697         
7698         /*g_print ("requested type %s\n", str);*/
7699         if (mono_reflection_parse_type (tmp, &info)) {
7700                 type = _mono_reflection_get_type_from_info (&info, image, FALSE);
7701         }
7702
7703         g_free (tmp);
7704         mono_reflection_free_type_info (&info);
7705         return type;
7706 }
7707
7708 /*
7709  * mono_reflection_get_token:
7710  *
7711  *   Return the metadata token of OBJ which should be an object
7712  * representing a metadata element.
7713  */
7714 guint32
7715 mono_reflection_get_token (MonoObject *obj)
7716 {
7717         MonoClass *klass;
7718         guint32 token = 0;
7719
7720         klass = obj->vtable->klass;
7721
7722         if (strcmp (klass->name, "MethodBuilder") == 0) {
7723                 MonoReflectionMethodBuilder *mb = (MonoReflectionMethodBuilder *)obj;
7724
7725                 token = mb->table_idx | MONO_TOKEN_METHOD_DEF;
7726         } else if (strcmp (klass->name, "ConstructorBuilder") == 0) {
7727                 MonoReflectionCtorBuilder *mb = (MonoReflectionCtorBuilder *)obj;
7728
7729                 token = mb->table_idx | MONO_TOKEN_METHOD_DEF;
7730         } else if (strcmp (klass->name, "FieldBuilder") == 0) {
7731                 MonoReflectionFieldBuilder *fb = (MonoReflectionFieldBuilder *)obj;
7732
7733                 token = fb->table_idx | MONO_TOKEN_FIELD_DEF;
7734         } else if (strcmp (klass->name, "TypeBuilder") == 0) {
7735                 MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder *)obj;
7736                 token = tb->table_idx | MONO_TOKEN_TYPE_DEF;
7737         } else if (strcmp (klass->name, "MonoType") == 0) {
7738                 MonoType *type = mono_reflection_type_get_handle ((MonoReflectionType*)obj);
7739                 MonoClass *mc = mono_class_from_mono_type (type);
7740                 if (!mono_class_init (mc))
7741                         mono_raise_exception (mono_class_get_exception_for_failure (mc));
7742
7743                 token = mc->type_token;
7744         } else if (strcmp (klass->name, "MonoCMethod") == 0 ||
7745                    strcmp (klass->name, "MonoMethod") == 0 ||
7746                    strcmp (klass->name, "MonoGenericMethod") == 0 ||
7747                    strcmp (klass->name, "MonoGenericCMethod") == 0) {
7748                 MonoReflectionMethod *m = (MonoReflectionMethod *)obj;
7749                 if (m->method->is_inflated) {
7750                         MonoMethodInflated *inflated = (MonoMethodInflated *) m->method;
7751                         return inflated->declaring->token;
7752                 } else {
7753                         token = m->method->token;
7754                 }
7755         } else if (strcmp (klass->name, "MonoField") == 0) {
7756                 MonoReflectionField *f = (MonoReflectionField*)obj;
7757
7758                 if (is_field_on_inst (f->field)) {
7759                         MonoDynamicGenericClass *dgclass = (MonoDynamicGenericClass*)f->field->parent->generic_class;
7760                         int field_index = f->field - dgclass->fields;
7761                         MonoObject *obj;
7762
7763                         g_assert (field_index >= 0 && field_index < dgclass->count_fields);
7764                         obj = dgclass->field_objects [field_index];
7765                         return mono_reflection_get_token (obj);
7766                 }
7767                 token = mono_class_get_field_token (f->field);
7768         } else if (strcmp (klass->name, "MonoProperty") == 0) {
7769                 MonoReflectionProperty *p = (MonoReflectionProperty*)obj;
7770
7771                 token = mono_class_get_property_token (p->property);
7772         } else if (strcmp (klass->name, "MonoEvent") == 0) {
7773                 MonoReflectionMonoEvent *p = (MonoReflectionMonoEvent*)obj;
7774
7775                 token = mono_class_get_event_token (p->event);
7776         } else if (strcmp (klass->name, "ParameterInfo") == 0 || strcmp (klass->name, "MonoParameterInfo") == 0) {
7777                 MonoReflectionParameter *p = (MonoReflectionParameter*)obj;
7778                 MonoClass *member_class = mono_object_class (p->MemberImpl);
7779                 g_assert (mono_class_is_reflection_method_or_constructor (member_class));
7780
7781                 token = mono_method_get_param_token (((MonoReflectionMethod*)p->MemberImpl)->method, p->PositionImpl);
7782         } else if (strcmp (klass->name, "Module") == 0 || strcmp (klass->name, "MonoModule") == 0) {
7783                 MonoReflectionModule *m = (MonoReflectionModule*)obj;
7784
7785                 token = m->token;
7786         } else if (strcmp (klass->name, "Assembly") == 0 || strcmp (klass->name, "MonoAssembly") == 0) {
7787                 token = mono_metadata_make_token (MONO_TABLE_ASSEMBLY, 1);
7788         } else {
7789                 gchar *msg = g_strdup_printf ("MetadataToken is not supported for type '%s.%s'", klass->name_space, klass->name);
7790                 MonoException *ex = mono_get_exception_not_implemented (msg);
7791                 g_free (msg);
7792                 mono_raise_exception (ex);
7793         }
7794
7795         return token;
7796 }
7797
7798 static MonoClass*
7799 load_cattr_enum_type (MonoImage *image, const char *p, const char **end)
7800 {
7801         char *n;
7802         MonoType *t;
7803         int slen = mono_metadata_decode_value (p, &p);
7804         n = g_memdup (p, slen + 1);
7805         n [slen] = 0;
7806         t = mono_reflection_type_from_name (n, image);
7807         if (!t)
7808                 g_error ("Cannot load type '%s'", n);
7809         g_free (n);
7810         p += slen;
7811         *end = p;
7812         return mono_class_from_mono_type (t);
7813 }
7814
7815 static void*
7816 load_cattr_value (MonoImage *image, MonoType *t, const char *p, const char **end)
7817 {
7818         int slen, type = t->type;
7819         MonoClass *tklass = t->data.klass;
7820
7821 handle_enum:
7822         switch (type) {
7823         case MONO_TYPE_U1:
7824         case MONO_TYPE_I1:
7825         case MONO_TYPE_BOOLEAN: {
7826                 MonoBoolean *bval = g_malloc (sizeof (MonoBoolean));
7827                 *bval = *p;
7828                 *end = p + 1;
7829                 return bval;
7830         }
7831         case MONO_TYPE_CHAR:
7832         case MONO_TYPE_U2:
7833         case MONO_TYPE_I2: {
7834                 guint16 *val = g_malloc (sizeof (guint16));
7835                 *val = read16 (p);
7836                 *end = p + 2;
7837                 return val;
7838         }
7839 #if SIZEOF_VOID_P == 4
7840         case MONO_TYPE_U:
7841         case MONO_TYPE_I:
7842 #endif
7843         case MONO_TYPE_R4:
7844         case MONO_TYPE_U4:
7845         case MONO_TYPE_I4: {
7846                 guint32 *val = g_malloc (sizeof (guint32));
7847                 *val = read32 (p);
7848                 *end = p + 4;
7849                 return val;
7850         }
7851 #if SIZEOF_VOID_P == 8
7852         case MONO_TYPE_U: /* error out instead? this should probably not happen */
7853         case MONO_TYPE_I:
7854 #endif
7855         case MONO_TYPE_U8:
7856         case MONO_TYPE_I8: {
7857                 guint64 *val = g_malloc (sizeof (guint64));
7858                 *val = read64 (p);
7859                 *end = p + 8;
7860                 return val;
7861         }
7862         case MONO_TYPE_R8: {
7863                 double *val = g_malloc (sizeof (double));
7864                 readr8 (p, val);
7865                 *end = p + 8;
7866                 return val;
7867         }
7868         case MONO_TYPE_VALUETYPE:
7869                 if (t->data.klass->enumtype) {
7870                         type = mono_class_enum_basetype (t->data.klass)->type;
7871                         goto handle_enum;
7872                 } else {
7873                         MonoClass *k =  t->data.klass;
7874                         
7875                         if (mono_is_corlib_image (k->image) && strcmp (k->name_space, "System") == 0 && strcmp (k->name, "DateTime") == 0){
7876                                 guint64 *val = g_malloc (sizeof (guint64));
7877                                 *val = read64 (p);
7878                                 *end = p + 8;
7879                                 return val;
7880                         }
7881                 }
7882                 g_error ("generic valutype %s not handled in custom attr value decoding", t->data.klass->name);
7883                 break;
7884                 
7885         case MONO_TYPE_STRING:
7886                 if (*p == (char)0xFF) {
7887                         *end = p + 1;
7888                         return NULL;
7889                 }
7890                 slen = mono_metadata_decode_value (p, &p);
7891                 *end = p + slen;
7892                 return mono_string_new_len (mono_domain_get (), p, slen);
7893         case MONO_TYPE_CLASS: {
7894                 char *n;
7895                 MonoType *t;
7896                 if (*p == (char)0xFF) {
7897                         *end = p + 1;
7898                         return NULL;
7899                 }
7900 handle_type:
7901                 slen = mono_metadata_decode_value (p, &p);
7902                 n = g_memdup (p, slen + 1);
7903                 n [slen] = 0;
7904                 t = mono_reflection_type_from_name (n, image);
7905                 if (!t)
7906                         g_warning ("Cannot load type '%s'", n);
7907                 g_free (n);
7908                 *end = p + slen;
7909                 if (t)
7910                         return mono_type_get_object (mono_domain_get (), t);
7911                 else
7912                         return NULL;
7913         }
7914         case MONO_TYPE_OBJECT: {
7915                 char subt = *p++;
7916                 MonoObject *obj;
7917                 MonoClass *subc = NULL;
7918                 void *val;
7919
7920                 if (subt == 0x50) {
7921                         goto handle_type;
7922                 } else if (subt == 0x0E) {
7923                         type = MONO_TYPE_STRING;
7924                         goto handle_enum;
7925                 } else if (subt == 0x1D) {
7926                         MonoType simple_type = {{0}};
7927                         int etype = *p;
7928                         p ++;
7929
7930                         type = MONO_TYPE_SZARRAY;
7931                         if (etype == 0x50) {
7932                                 tklass = mono_defaults.systemtype_class;
7933                         } else if (etype == 0x55) {
7934                                 tklass = load_cattr_enum_type (image, p, &p);
7935                         } else {
7936                                 if (etype == 0x51)
7937                                         /* See Partition II, Appendix B3 */
7938                                         etype = MONO_TYPE_OBJECT;
7939                                 simple_type.type = etype;
7940                                 tklass = mono_class_from_mono_type (&simple_type);
7941                         }
7942                         goto handle_enum;
7943                 } else if (subt == 0x55) {
7944                         char *n;
7945                         MonoType *t;
7946                         slen = mono_metadata_decode_value (p, &p);
7947                         n = g_memdup (p, slen + 1);
7948                         n [slen] = 0;
7949                         t = mono_reflection_type_from_name (n, image);
7950                         if (!t)
7951                                 g_error ("Cannot load type '%s'", n);
7952                         g_free (n);
7953                         p += slen;
7954                         subc = mono_class_from_mono_type (t);
7955                 } else if (subt >= MONO_TYPE_BOOLEAN && subt <= MONO_TYPE_R8) {
7956                         MonoType simple_type = {{0}};
7957                         simple_type.type = subt;
7958                         subc = mono_class_from_mono_type (&simple_type);
7959                 } else {
7960                         g_error ("Unknown type 0x%02x for object type encoding in custom attr", subt);
7961                 }
7962                 val = load_cattr_value (image, &subc->byval_arg, p, end);
7963                 obj = mono_object_new (mono_domain_get (), subc);
7964                 g_assert (!subc->has_references);
7965                 mono_gc_memmove_atomic ((char*)obj + sizeof (MonoObject), val, mono_class_value_size (subc, NULL));
7966                 g_free (val);
7967                 return obj;
7968         }
7969         case MONO_TYPE_SZARRAY: {
7970                 MonoArray *arr;
7971                 guint32 i, alen, basetype;
7972                 alen = read32 (p);
7973                 p += 4;
7974                 if (alen == 0xffffffff) {
7975                         *end = p;
7976                         return NULL;
7977                 }
7978                 arr = mono_array_new (mono_domain_get(), tklass, alen);
7979                 basetype = tklass->byval_arg.type;
7980                 if (basetype == MONO_TYPE_VALUETYPE && tklass->enumtype)
7981                         basetype = mono_class_enum_basetype (tklass)->type;
7982                 switch (basetype)
7983                 {
7984                         case MONO_TYPE_U1:
7985                         case MONO_TYPE_I1:
7986                         case MONO_TYPE_BOOLEAN:
7987                                 for (i = 0; i < alen; i++) {
7988                                         MonoBoolean val = *p++;
7989                                         mono_array_set (arr, MonoBoolean, i, val);
7990                                 }
7991                                 break;
7992                         case MONO_TYPE_CHAR:
7993                         case MONO_TYPE_U2:
7994                         case MONO_TYPE_I2:
7995                                 for (i = 0; i < alen; i++) {
7996                                         guint16 val = read16 (p);
7997                                         mono_array_set (arr, guint16, i, val);
7998                                         p += 2;
7999                                 }
8000                                 break;
8001                         case MONO_TYPE_R4:
8002                         case MONO_TYPE_U4:
8003                         case MONO_TYPE_I4:
8004                                 for (i = 0; i < alen; i++) {
8005                                         guint32 val = read32 (p);
8006                                         mono_array_set (arr, guint32, i, val);
8007                                         p += 4;
8008                                 }
8009                                 break;
8010                         case MONO_TYPE_R8:
8011                                 for (i = 0; i < alen; i++) {
8012                                         double val;
8013                                         readr8 (p, &val);
8014                                         mono_array_set (arr, double, i, val);
8015                                         p += 8;
8016                                 }
8017                                 break;
8018                         case MONO_TYPE_U8:
8019                         case MONO_TYPE_I8:
8020                                 for (i = 0; i < alen; i++) {
8021                                         guint64 val = read64 (p);
8022                                         mono_array_set (arr, guint64, i, val);
8023                                         p += 8;
8024                                 }
8025                                 break;
8026                         case MONO_TYPE_CLASS:
8027                         case MONO_TYPE_OBJECT:
8028                         case MONO_TYPE_STRING:
8029                         case MONO_TYPE_SZARRAY:
8030                                 for (i = 0; i < alen; i++) {
8031                                         MonoObject *item = load_cattr_value (image, &tklass->byval_arg, p, &p);
8032                                         mono_array_setref (arr, i, item);
8033                                 }
8034                                 break;
8035                         default:
8036                                 g_error ("Type 0x%02x not handled in custom attr array decoding", basetype);
8037                 }
8038                 *end=p;
8039                 return arr;
8040         }
8041         default:
8042                 g_error ("Type 0x%02x not handled in custom attr value decoding", type);
8043         }
8044         return NULL;
8045 }
8046
8047 static MonoObject*
8048 create_cattr_typed_arg (MonoType *t, MonoObject *val)
8049 {
8050         static MonoClass *klass;
8051         static MonoMethod *ctor;
8052         MonoObject *retval;
8053         void *params [2], *unboxed;
8054
8055         if (!klass)
8056                 klass = mono_class_from_name (mono_defaults.corlib, "System.Reflection", "CustomAttributeTypedArgument");
8057         if (!ctor)
8058                 ctor = mono_class_get_method_from_name (klass, ".ctor", 2);
8059         
8060         params [0] = mono_type_get_object (mono_domain_get (), t);
8061         params [1] = val;
8062         retval = mono_object_new (mono_domain_get (), klass);
8063         unboxed = mono_object_unbox (retval);
8064         mono_runtime_invoke (ctor, unboxed, params, NULL);
8065
8066         return retval;
8067 }
8068
8069 static MonoObject*
8070 create_cattr_named_arg (void *minfo, MonoObject *typedarg)
8071 {
8072         static MonoClass *klass;
8073         static MonoMethod *ctor;
8074         MonoObject *retval;
8075         void *unboxed, *params [2];
8076
8077         if (!klass)
8078                 klass = mono_class_from_name (mono_defaults.corlib, "System.Reflection", "CustomAttributeNamedArgument");
8079         if (!ctor)
8080                 ctor = mono_class_get_method_from_name (klass, ".ctor", 2);
8081
8082         params [0] = minfo;
8083         params [1] = typedarg;
8084         retval = mono_object_new (mono_domain_get (), klass);
8085         unboxed = mono_object_unbox (retval);
8086         mono_runtime_invoke (ctor, unboxed, params, NULL);
8087
8088         return retval;
8089 }
8090
8091 static gboolean
8092 type_is_reference (MonoType *type)
8093 {
8094         switch (type->type) {
8095         case MONO_TYPE_BOOLEAN:
8096         case MONO_TYPE_CHAR:
8097         case MONO_TYPE_U:
8098         case MONO_TYPE_I:
8099         case MONO_TYPE_U1:
8100         case MONO_TYPE_I1:
8101         case MONO_TYPE_U2:
8102         case MONO_TYPE_I2:
8103         case MONO_TYPE_U4:
8104         case MONO_TYPE_I4:
8105         case MONO_TYPE_U8:
8106         case MONO_TYPE_I8:
8107         case MONO_TYPE_R8:
8108         case MONO_TYPE_R4:
8109         case MONO_TYPE_VALUETYPE:
8110                 return FALSE;
8111         default:
8112                 return TRUE;
8113         }
8114 }
8115
8116 static void
8117 free_param_data (MonoMethodSignature *sig, void **params) {
8118         int i;
8119         for (i = 0; i < sig->param_count; ++i) {
8120                 if (!type_is_reference (sig->params [i]))
8121                         g_free (params [i]);
8122         }
8123 }
8124
8125 /*
8126  * Find the field index in the metadata FieldDef table.
8127  */
8128 static guint32
8129 find_field_index (MonoClass *klass, MonoClassField *field) {
8130         int i;
8131
8132         for (i = 0; i < klass->field.count; ++i) {
8133                 if (field == &klass->fields [i])
8134                         return klass->field.first + 1 + i;
8135         }
8136         return 0;
8137 }
8138
8139 /*
8140  * Find the property index in the metadata Property table.
8141  */
8142 static guint32
8143 find_property_index (MonoClass *klass, MonoProperty *property) {
8144         int i;
8145
8146         for (i = 0; i < klass->ext->property.count; ++i) {
8147                 if (property == &klass->ext->properties [i])
8148                         return klass->ext->property.first + 1 + i;
8149         }
8150         return 0;
8151 }
8152
8153 /*
8154  * Find the event index in the metadata Event table.
8155  */
8156 static guint32
8157 find_event_index (MonoClass *klass, MonoEvent *event) {
8158         int i;
8159
8160         for (i = 0; i < klass->ext->event.count; ++i) {
8161                 if (event == &klass->ext->events [i])
8162                         return klass->ext->event.first + 1 + i;
8163         }
8164         return 0;
8165 }
8166
8167 static MonoObject*
8168 create_custom_attr (MonoImage *image, MonoMethod *method, const guchar *data, guint32 len, MonoError *error)
8169 {
8170         const char *p = (const char*)data;
8171         const char *named;
8172         guint32 i, j, num_named;
8173         MonoObject *attr;
8174         void *params_buf [32];
8175         void **params;
8176         MonoMethodSignature *sig;
8177
8178         mono_error_init (error);
8179
8180         mono_class_init (method->klass);
8181
8182         if (!mono_verifier_verify_cattr_content (image, method, data, len, NULL)) {
8183                 mono_error_set_generic_error (error, "System.Reflection", "CustomAttributeFormatException", "Binary format of the specified custom attribute was invalid.");
8184                 return NULL;
8185         }
8186
8187         if (len == 0) {
8188                 attr = mono_object_new (mono_domain_get (), method->klass);
8189                 mono_runtime_invoke (method, attr, NULL, NULL);
8190                 return attr;
8191         }
8192
8193         if (len < 2 || read16 (p) != 0x0001) /* Prolog */
8194                 return NULL;
8195
8196         /*g_print ("got attr %s\n", method->klass->name);*/
8197
8198         sig = mono_method_signature (method);
8199         if (sig->param_count < 32)
8200                 params = params_buf;
8201         else
8202                 /* Allocate using GC so it gets GC tracking */
8203                 params = mono_gc_alloc_fixed (sig->param_count * sizeof (void*), NULL);
8204
8205         /* skip prolog */
8206         p += 2;
8207         for (i = 0; i < mono_method_signature (method)->param_count; ++i) {
8208                 params [i] = load_cattr_value (image, mono_method_signature (method)->params [i], p, &p);
8209         }
8210
8211         named = p;
8212         attr = mono_object_new (mono_domain_get (), method->klass);
8213         mono_runtime_invoke (method, attr, params, NULL);
8214         free_param_data (method->signature, params);
8215         num_named = read16 (named);
8216         named += 2;
8217         for (j = 0; j < num_named; j++) {
8218                 gint name_len;
8219                 char *name, named_type, data_type;
8220                 named_type = *named++;
8221                 data_type = *named++; /* type of data */
8222                 if (data_type == MONO_TYPE_SZARRAY)
8223                         data_type = *named++;
8224                 if (data_type == MONO_TYPE_ENUM) {
8225                         gint type_len;
8226                         char *type_name;
8227                         type_len = mono_metadata_decode_blob_size (named, &named);
8228                         type_name = g_malloc (type_len + 1);
8229                         memcpy (type_name, named, type_len);
8230                         type_name [type_len] = 0;
8231                         named += type_len;
8232                         /* FIXME: lookup the type and check type consistency */
8233                         g_free (type_name);
8234                 }
8235                 name_len = mono_metadata_decode_blob_size (named, &named);
8236                 name = g_malloc (name_len + 1);
8237                 memcpy (name, named, name_len);
8238                 name [name_len] = 0;
8239                 named += name_len;
8240                 if (named_type == 0x53) {
8241                         MonoClassField *field = mono_class_get_field_from_name (mono_object_class (attr), name);
8242                         void *val = load_cattr_value (image, field->type, named, &named);
8243                         mono_field_set_value (attr, field, val);
8244                         if (!type_is_reference (field->type))
8245                                 g_free (val);
8246                 } else if (named_type == 0x54) {
8247                         MonoProperty *prop;
8248                         void *pparams [1];
8249                         MonoType *prop_type;
8250
8251                         prop = mono_class_get_property_from_name (mono_object_class (attr), name);
8252                         /* can we have more that 1 arg in a custom attr named property? */
8253                         prop_type = prop->get? mono_method_signature (prop->get)->ret :
8254                              mono_method_signature (prop->set)->params [mono_method_signature (prop->set)->param_count - 1];
8255                         pparams [0] = load_cattr_value (image, prop_type, named, &named);
8256                         mono_property_set_value (prop, attr, pparams, NULL);
8257                         if (!type_is_reference (prop_type))
8258                                 g_free (pparams [0]);
8259                 }
8260                 g_free (name);
8261         }
8262
8263         if (params != params_buf)
8264                 mono_gc_free_fixed (params);
8265
8266         return attr;
8267 }
8268         
8269 /*
8270  * mono_reflection_create_custom_attr_data_args:
8271  *
8272  *   Create an array of typed and named arguments from the cattr blob given by DATA.
8273  * TYPED_ARGS and NAMED_ARGS will contain the objects representing the arguments,
8274  * NAMED_ARG_INFO will contain information about the named arguments.
8275  */
8276 void
8277 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)
8278 {
8279         MonoArray *typedargs, *namedargs;
8280         MonoClass *attrklass;
8281         MonoDomain *domain;
8282         const char *p = (const char*)data;
8283         const char *named;
8284         guint32 i, j, num_named;
8285         CattrNamedArg *arginfo = NULL;
8286
8287         *typed_args = NULL;
8288         *named_args = NULL;
8289         *named_arg_info = NULL;
8290
8291         mono_error_init (error);
8292
8293         if (!mono_verifier_verify_cattr_content (image, method, data, len, NULL)) {
8294                 mono_error_set_generic_error (error, "System.Reflection", "CustomAttributeFormatException", "Binary format of the specified custom attribute was invalid.");
8295                 return;
8296         }
8297
8298         mono_class_init (method->klass);
8299         
8300         domain = mono_domain_get ();
8301
8302         if (len < 2 || read16 (p) != 0x0001) /* Prolog */
8303                 return;
8304
8305         typedargs = mono_array_new (domain, mono_get_object_class (), mono_method_signature (method)->param_count);
8306         
8307         /* skip prolog */
8308         p += 2;
8309         for (i = 0; i < mono_method_signature (method)->param_count; ++i) {
8310                 MonoObject *obj;
8311                 void *val;
8312
8313                 val = load_cattr_value (image, mono_method_signature (method)->params [i], p, &p);
8314                 obj = type_is_reference (mono_method_signature (method)->params [i]) ? 
8315                         val : mono_value_box (domain, mono_class_from_mono_type (mono_method_signature (method)->params [i]), val);
8316                 mono_array_setref (typedargs, i, obj);
8317
8318                 if (!type_is_reference (mono_method_signature (method)->params [i]))
8319                         g_free (val);
8320         }
8321
8322         named = p;
8323         num_named = read16 (named);
8324         namedargs = mono_array_new (domain, mono_get_object_class (), num_named);
8325         named += 2;
8326         attrklass = method->klass;
8327
8328         arginfo = g_new0 (CattrNamedArg, num_named);
8329         *named_arg_info = arginfo;
8330
8331         for (j = 0; j < num_named; j++) {
8332                 gint name_len;
8333                 char *name, named_type, data_type;
8334                 named_type = *named++;
8335                 data_type = *named++; /* type of data */
8336                 if (data_type == MONO_TYPE_SZARRAY)
8337                         data_type = *named++;
8338                 if (data_type == MONO_TYPE_ENUM) {
8339                         gint type_len;
8340                         char *type_name;
8341                         type_len = mono_metadata_decode_blob_size (named, &named);
8342                         if (ADDP_IS_GREATER_OR_OVF ((const guchar*)named, type_len, data + len))
8343                                 goto fail;
8344
8345                         type_name = g_malloc (type_len + 1);
8346                         memcpy (type_name, named, type_len);
8347                         type_name [type_len] = 0;
8348                         named += type_len;
8349                         /* FIXME: lookup the type and check type consistency */
8350                         g_free (type_name);
8351                 }
8352                 name_len = mono_metadata_decode_blob_size (named, &named);
8353                 if (ADDP_IS_GREATER_OR_OVF ((const guchar*)named, name_len, data + len))
8354                         goto fail;
8355                 name = g_malloc (name_len + 1);
8356                 memcpy (name, named, name_len);
8357                 name [name_len] = 0;
8358                 named += name_len;
8359                 if (named_type == 0x53) {
8360                         MonoObject *obj;
8361                         MonoClassField *field = mono_class_get_field_from_name (attrklass, name);
8362                         void *val;
8363
8364                         arginfo [j].type = field->type;
8365                         arginfo [j].field = field;
8366
8367                         val = load_cattr_value (image, field->type, named, &named);
8368                         obj = type_is_reference (field->type) ? val : mono_value_box (domain, mono_class_from_mono_type (field->type), val);
8369                         mono_array_setref (namedargs, j, obj);
8370                         if (!type_is_reference (field->type))
8371                                 g_free (val);
8372                 } else if (named_type == 0x54) {
8373                         MonoObject *obj;
8374                         MonoType *prop_type;
8375                         MonoProperty *prop = mono_class_get_property_from_name (attrklass, name);
8376                         void *val;
8377
8378                         prop_type = prop->get? mono_method_signature (prop->get)->ret :
8379                              mono_method_signature (prop->set)->params [mono_method_signature (prop->set)->param_count - 1];
8380
8381                         arginfo [j].type = prop_type;
8382                         arginfo [j].prop = prop;
8383
8384                         val = load_cattr_value (image, prop_type, named, &named);
8385                         obj = type_is_reference (prop_type) ? val : mono_value_box (domain, mono_class_from_mono_type (prop_type), val);
8386                         mono_array_setref (namedargs, j, obj);
8387                         if (!type_is_reference (prop_type))
8388                                 g_free (val);
8389                 }
8390                 g_free (name);
8391         }
8392
8393         *typed_args = typedargs;
8394         *named_args = namedargs;
8395         return;
8396 fail:
8397         mono_error_set_generic_error (error, "System.Reflection", "CustomAttributeFormatException", "Binary format of the specified custom attribute was invalid.");
8398         g_free (arginfo);
8399         *named_arg_info = NULL;
8400 }
8401
8402 void
8403 mono_reflection_resolve_custom_attribute_data (MonoReflectionMethod *ref_method, MonoReflectionAssembly *assembly, gpointer data, guint32 len, MonoArray **ctor_args, MonoArray **named_args)
8404 {
8405         MonoDomain *domain;
8406         MonoArray *typedargs, *namedargs;
8407         MonoImage *image;
8408         MonoMethod *method;
8409         CattrNamedArg *arginfo = NULL;
8410         MonoError error;
8411         int i;
8412
8413         *ctor_args = NULL;
8414         *named_args = NULL;
8415
8416         if (len == 0)
8417                 return;
8418
8419         image = assembly->assembly->image;
8420         method = ref_method->method;
8421         domain = mono_object_domain (ref_method);
8422
8423         if (!mono_class_init (method->klass))
8424                 mono_raise_exception (mono_class_get_exception_for_failure (method->klass));
8425
8426         mono_reflection_create_custom_attr_data_args (image, method, data, len, &typedargs, &namedargs, &arginfo, &error);
8427         if (!mono_error_ok (&error))
8428                 mono_error_raise_exception (&error);
8429         if (mono_loader_get_last_error ())
8430                 mono_raise_exception (mono_loader_error_prepare_exception (mono_loader_get_last_error ()));
8431
8432         if (!typedargs || !namedargs) {
8433                 g_free (arginfo);
8434                 return;
8435         }
8436
8437         for (i = 0; i < mono_method_signature (method)->param_count; ++i) {
8438                 MonoObject *obj = mono_array_get (typedargs, MonoObject*, i);
8439                 MonoObject *typedarg;
8440
8441                 typedarg = create_cattr_typed_arg (mono_method_signature (method)->params [i], obj);
8442                 mono_array_setref (typedargs, i, typedarg);
8443         }
8444
8445         for (i = 0; i < mono_array_length (namedargs); ++i) {
8446                 MonoObject *obj = mono_array_get (namedargs, MonoObject*, i);
8447                 MonoObject *typedarg, *namedarg, *minfo;
8448
8449                 if (arginfo [i].prop)
8450                         minfo = (MonoObject*)mono_property_get_object (domain, NULL, arginfo [i].prop);
8451                 else
8452                         minfo = (MonoObject*)mono_field_get_object (domain, NULL, arginfo [i].field);
8453
8454                 typedarg = create_cattr_typed_arg (arginfo [i].type, obj);
8455                 namedarg = create_cattr_named_arg (minfo, typedarg);
8456
8457                 mono_array_setref (namedargs, i, namedarg);
8458         }
8459
8460         *ctor_args = typedargs;
8461         *named_args = namedargs;
8462         g_free (arginfo);
8463 }
8464
8465 static MonoObject*
8466 create_custom_attr_data (MonoImage *image, MonoCustomAttrEntry *cattr)
8467 {
8468         static MonoMethod *ctor;
8469         MonoDomain *domain;
8470         MonoObject *attr;
8471         void *params [4];
8472
8473         g_assert (image->assembly);
8474
8475         if (!ctor)
8476                 ctor = mono_class_get_method_from_name (mono_defaults.customattribute_data_class, ".ctor", 4);
8477
8478         domain = mono_domain_get ();
8479         attr = mono_object_new (domain, mono_defaults.customattribute_data_class);
8480         params [0] = mono_method_get_object (domain, cattr->ctor, NULL);
8481         params [1] = mono_assembly_get_object (domain, image->assembly);
8482         params [2] = (gpointer)&cattr->data;
8483         params [3] = &cattr->data_size;
8484         mono_runtime_invoke (ctor, attr, params, NULL);
8485         return attr;
8486 }
8487
8488 static MonoArray*
8489 mono_custom_attrs_construct_by_type (MonoCustomAttrInfo *cinfo, MonoClass *attr_klass, MonoError *error)
8490 {
8491         MonoArray *result;
8492         MonoObject *attr;
8493         int i, n;
8494
8495         mono_error_init (error);
8496
8497         n = 0;
8498         for (i = 0; i < cinfo->num_attrs; ++i) {
8499                 if (!attr_klass || mono_class_is_assignable_from (attr_klass, cinfo->attrs [i].ctor->klass))
8500                         n ++;
8501         }
8502
8503         result = mono_array_new_cached (mono_domain_get (), mono_defaults.attribute_class, n);
8504         n = 0;
8505         for (i = 0; i < cinfo->num_attrs; ++i) {
8506                 if (!cinfo->attrs [i].ctor)
8507                         /* The cattr type is not finished yet */
8508                         /* We should include the type name but cinfo doesn't contain it */
8509                         mono_raise_exception (mono_get_exception_type_load (NULL, NULL));
8510                 if (!attr_klass || mono_class_is_assignable_from (attr_klass, cinfo->attrs [i].ctor->klass)) {
8511                         attr = create_custom_attr (cinfo->image, cinfo->attrs [i].ctor, cinfo->attrs [i].data, cinfo->attrs [i].data_size, error);
8512                         if (!mono_error_ok (error))
8513                                 return result;
8514                         mono_array_setref (result, n, attr);
8515                         n ++;
8516                 }
8517         }
8518         return result;
8519 }
8520
8521 MonoArray*
8522 mono_custom_attrs_construct (MonoCustomAttrInfo *cinfo)
8523 {
8524         MonoError error;
8525
8526         return mono_custom_attrs_construct_by_type (cinfo, NULL, &error);
8527 }
8528
8529 static MonoArray*
8530 mono_custom_attrs_data_construct (MonoCustomAttrInfo *cinfo)
8531 {
8532         MonoArray *result;
8533         MonoObject *attr;
8534         int i;
8535         
8536         result = mono_array_new (mono_domain_get (), mono_defaults.customattribute_data_class, cinfo->num_attrs);
8537         for (i = 0; i < cinfo->num_attrs; ++i) {
8538                 attr = create_custom_attr_data (cinfo->image, &cinfo->attrs [i]);
8539                 mono_array_setref (result, i, attr);
8540         }
8541         return result;
8542 }
8543
8544 /**
8545  * mono_custom_attrs_from_index:
8546  *
8547  * Returns: NULL if no attributes are found or if a loading error occurs.
8548  */
8549 MonoCustomAttrInfo*
8550 mono_custom_attrs_from_index (MonoImage *image, guint32 idx)
8551 {
8552         guint32 mtoken, i, len;
8553         guint32 cols [MONO_CUSTOM_ATTR_SIZE];
8554         MonoTableInfo *ca;
8555         MonoCustomAttrInfo *ainfo;
8556         GList *tmp, *list = NULL;
8557         const char *data;
8558
8559         ca = &image->tables [MONO_TABLE_CUSTOMATTRIBUTE];
8560
8561         i = mono_metadata_custom_attrs_from_index (image, idx);
8562         if (!i)
8563                 return NULL;
8564         i --;
8565         while (i < ca->rows) {
8566                 if (mono_metadata_decode_row_col (ca, i, MONO_CUSTOM_ATTR_PARENT) != idx)
8567                         break;
8568                 list = g_list_prepend (list, GUINT_TO_POINTER (i));
8569                 ++i;
8570         }
8571         len = g_list_length (list);
8572         if (!len)
8573                 return NULL;
8574         ainfo = g_malloc0 (MONO_SIZEOF_CUSTOM_ATTR_INFO + sizeof (MonoCustomAttrEntry) * len);
8575         ainfo->num_attrs = len;
8576         ainfo->image = image;
8577         for (i = 0, tmp = list; i < len; ++i, tmp = tmp->next) {
8578                 mono_metadata_decode_row (ca, GPOINTER_TO_UINT (tmp->data), cols, MONO_CUSTOM_ATTR_SIZE);
8579                 mtoken = cols [MONO_CUSTOM_ATTR_TYPE] >> MONO_CUSTOM_ATTR_TYPE_BITS;
8580                 switch (cols [MONO_CUSTOM_ATTR_TYPE] & MONO_CUSTOM_ATTR_TYPE_MASK) {
8581                 case MONO_CUSTOM_ATTR_TYPE_METHODDEF:
8582                         mtoken |= MONO_TOKEN_METHOD_DEF;
8583                         break;
8584                 case MONO_CUSTOM_ATTR_TYPE_MEMBERREF:
8585                         mtoken |= MONO_TOKEN_MEMBER_REF;
8586                         break;
8587                 default:
8588                         g_error ("Unknown table for custom attr type %08x", cols [MONO_CUSTOM_ATTR_TYPE]);
8589                         break;
8590                 }
8591                 ainfo->attrs [i].ctor = mono_get_method (image, mtoken, NULL);
8592                 if (!ainfo->attrs [i].ctor) {
8593                         g_warning ("Can't find custom attr constructor image: %s mtoken: 0x%08x", image->name, mtoken);
8594                         g_list_free (list);
8595                         g_free (ainfo);
8596                         return NULL;
8597                 }
8598
8599                 if (!mono_verifier_verify_cattr_blob (image, cols [MONO_CUSTOM_ATTR_VALUE], NULL)) {
8600                         /*FIXME raising an exception here doesn't make any sense*/
8601                         g_warning ("Invalid custom attribute blob on image %s for index %x", image->name, idx);
8602                         g_list_free (list);
8603                         g_free (ainfo);
8604                         return NULL;
8605                 }
8606                 data = mono_metadata_blob_heap (image, cols [MONO_CUSTOM_ATTR_VALUE]);
8607                 ainfo->attrs [i].data_size = mono_metadata_decode_value (data, &data);
8608                 ainfo->attrs [i].data = (guchar*)data;
8609         }
8610         g_list_free (list);
8611
8612         return ainfo;
8613 }
8614
8615 MonoCustomAttrInfo*
8616 mono_custom_attrs_from_method (MonoMethod *method)
8617 {
8618         guint32 idx;
8619
8620         /*
8621          * An instantiated method has the same cattrs as the generic method definition.
8622          *
8623          * LAMESPEC: The .NET SRE throws an exception for instantiations of generic method builders
8624          *           Note that this stanza is not necessary for non-SRE types, but it's a micro-optimization
8625          */
8626         if (method->is_inflated)
8627                 method = ((MonoMethodInflated *) method)->declaring;
8628         
8629         if (method->dynamic || method->klass->image->dynamic)
8630                 return lookup_custom_attr (method->klass->image, method);
8631
8632         if (!method->token)
8633                 /* Synthetic methods */
8634                 return NULL;
8635
8636         idx = mono_method_get_index (method);
8637         idx <<= MONO_CUSTOM_ATTR_BITS;
8638         idx |= MONO_CUSTOM_ATTR_METHODDEF;
8639         return mono_custom_attrs_from_index (method->klass->image, idx);
8640 }
8641
8642 MonoCustomAttrInfo*
8643 mono_custom_attrs_from_class (MonoClass *klass)
8644 {
8645         guint32 idx;
8646
8647         if (klass->generic_class)
8648                 klass = klass->generic_class->container_class;
8649
8650         if (klass->image->dynamic)
8651                 return lookup_custom_attr (klass->image, klass);
8652
8653         if (klass->byval_arg.type == MONO_TYPE_VAR || klass->byval_arg.type == MONO_TYPE_MVAR) {
8654                 idx = mono_metadata_token_index (klass->sizes.generic_param_token);
8655                 idx <<= MONO_CUSTOM_ATTR_BITS;
8656                 idx |= MONO_CUSTOM_ATTR_GENERICPAR;
8657         } else {
8658                 idx = mono_metadata_token_index (klass->type_token);
8659                 idx <<= MONO_CUSTOM_ATTR_BITS;
8660                 idx |= MONO_CUSTOM_ATTR_TYPEDEF;
8661         }
8662         return mono_custom_attrs_from_index (klass->image, idx);
8663 }
8664
8665 MonoCustomAttrInfo*
8666 mono_custom_attrs_from_assembly (MonoAssembly *assembly)
8667 {
8668         guint32 idx;
8669         
8670         if (assembly->image->dynamic)
8671                 return lookup_custom_attr (assembly->image, assembly);
8672         idx = 1; /* there is only one assembly */
8673         idx <<= MONO_CUSTOM_ATTR_BITS;
8674         idx |= MONO_CUSTOM_ATTR_ASSEMBLY;
8675         return mono_custom_attrs_from_index (assembly->image, idx);
8676 }
8677
8678 static MonoCustomAttrInfo*
8679 mono_custom_attrs_from_module (MonoImage *image)
8680 {
8681         guint32 idx;
8682         
8683         if (image->dynamic)
8684                 return lookup_custom_attr (image, image);
8685         idx = 1; /* there is only one module */
8686         idx <<= MONO_CUSTOM_ATTR_BITS;
8687         idx |= MONO_CUSTOM_ATTR_MODULE;
8688         return mono_custom_attrs_from_index (image, idx);
8689 }
8690
8691 MonoCustomAttrInfo*
8692 mono_custom_attrs_from_property (MonoClass *klass, MonoProperty *property)
8693 {
8694         guint32 idx;
8695         
8696         if (klass->image->dynamic) {
8697                 property = mono_metadata_get_corresponding_property_from_generic_type_definition (property);
8698                 return lookup_custom_attr (klass->image, property);
8699         }
8700         idx = find_property_index (klass, property);
8701         idx <<= MONO_CUSTOM_ATTR_BITS;
8702         idx |= MONO_CUSTOM_ATTR_PROPERTY;
8703         return mono_custom_attrs_from_index (klass->image, idx);
8704 }
8705
8706 MonoCustomAttrInfo*
8707 mono_custom_attrs_from_event (MonoClass *klass, MonoEvent *event)
8708 {
8709         guint32 idx;
8710         
8711         if (klass->image->dynamic) {
8712                 event = mono_metadata_get_corresponding_event_from_generic_type_definition (event);
8713                 return lookup_custom_attr (klass->image, event);
8714         }
8715         idx = find_event_index (klass, event);
8716         idx <<= MONO_CUSTOM_ATTR_BITS;
8717         idx |= MONO_CUSTOM_ATTR_EVENT;
8718         return mono_custom_attrs_from_index (klass->image, idx);
8719 }
8720
8721 MonoCustomAttrInfo*
8722 mono_custom_attrs_from_field (MonoClass *klass, MonoClassField *field)
8723 {
8724         guint32 idx;
8725         if (klass->image->dynamic) {
8726                 field = mono_metadata_get_corresponding_field_from_generic_type_definition (field);
8727                 return lookup_custom_attr (klass->image, field);
8728         }
8729         idx = find_field_index (klass, field);
8730         idx <<= MONO_CUSTOM_ATTR_BITS;
8731         idx |= MONO_CUSTOM_ATTR_FIELDDEF;
8732         return mono_custom_attrs_from_index (klass->image, idx);
8733 }
8734
8735 /**
8736  * mono_custom_attrs_from_param:
8737  * @method: handle to the method that we want to retrieve custom parameter information from
8738  * @param: parameter number, where zero represent the return value, and one is the first parameter in the method
8739  *
8740  * The result must be released with mono_custom_attrs_free().
8741  *
8742  * Returns: the custom attribute object for the specified parameter, or NULL if there are none.
8743  */
8744 MonoCustomAttrInfo*
8745 mono_custom_attrs_from_param (MonoMethod *method, guint32 param)
8746 {
8747         MonoTableInfo *ca;
8748         guint32 i, idx, method_index;
8749         guint32 param_list, param_last, param_pos, found;
8750         MonoImage *image;
8751         MonoReflectionMethodAux *aux;
8752
8753         /*
8754          * An instantiated method has the same cattrs as the generic method definition.
8755          *
8756          * LAMESPEC: The .NET SRE throws an exception for instantiations of generic method builders
8757          *           Note that this stanza is not necessary for non-SRE types, but it's a micro-optimization
8758          */
8759         if (method->is_inflated)
8760                 method = ((MonoMethodInflated *) method)->declaring;
8761
8762         if (method->klass->image->dynamic) {
8763                 MonoCustomAttrInfo *res, *ainfo;
8764                 int size;
8765
8766                 aux = g_hash_table_lookup (((MonoDynamicImage*)method->klass->image)->method_aux_hash, method);
8767                 if (!aux || !aux->param_cattr)
8768                         return NULL;
8769
8770                 /* Need to copy since it will be freed later */
8771                 ainfo = aux->param_cattr [param];
8772                 if (!ainfo)
8773                         return NULL;
8774                 size = MONO_SIZEOF_CUSTOM_ATTR_INFO + sizeof (MonoCustomAttrEntry) * ainfo->num_attrs;
8775                 res = g_malloc0 (size);
8776                 memcpy (res, ainfo, size);
8777                 return res;
8778         }
8779
8780         image = method->klass->image;
8781         method_index = mono_method_get_index (method);
8782         if (!method_index)
8783                 return NULL;
8784         ca = &image->tables [MONO_TABLE_METHOD];
8785
8786         param_list = mono_metadata_decode_row_col (ca, method_index - 1, MONO_METHOD_PARAMLIST);
8787         if (method_index == ca->rows) {
8788                 ca = &image->tables [MONO_TABLE_PARAM];
8789                 param_last = ca->rows + 1;
8790         } else {
8791                 param_last = mono_metadata_decode_row_col (ca, method_index, MONO_METHOD_PARAMLIST);
8792                 ca = &image->tables [MONO_TABLE_PARAM];
8793         }
8794         found = FALSE;
8795         for (i = param_list; i < param_last; ++i) {
8796                 param_pos = mono_metadata_decode_row_col (ca, i - 1, MONO_PARAM_SEQUENCE);
8797                 if (param_pos == param) {
8798                         found = TRUE;
8799                         break;
8800                 }
8801         }
8802         if (!found)
8803                 return NULL;
8804         idx = i;
8805         idx <<= MONO_CUSTOM_ATTR_BITS;
8806         idx |= MONO_CUSTOM_ATTR_PARAMDEF;
8807         return mono_custom_attrs_from_index (image, idx);
8808 }
8809
8810 gboolean
8811 mono_custom_attrs_has_attr (MonoCustomAttrInfo *ainfo, MonoClass *attr_klass)
8812 {
8813         int i;
8814         MonoClass *klass;
8815         for (i = 0; i < ainfo->num_attrs; ++i) {
8816                 klass = ainfo->attrs [i].ctor->klass;
8817                 if (mono_class_has_parent (klass, attr_klass) || (MONO_CLASS_IS_INTERFACE (attr_klass) && mono_class_is_assignable_from (attr_klass, klass)))
8818                         return TRUE;
8819         }
8820         return FALSE;
8821 }
8822
8823 MonoObject*
8824 mono_custom_attrs_get_attr (MonoCustomAttrInfo *ainfo, MonoClass *attr_klass)
8825 {
8826         int i, attr_index;
8827         MonoClass *klass;
8828         MonoArray *attrs;
8829
8830         attr_index = -1;
8831         for (i = 0; i < ainfo->num_attrs; ++i) {
8832                 klass = ainfo->attrs [i].ctor->klass;
8833                 if (mono_class_has_parent (klass, attr_klass)) {
8834                         attr_index = i;
8835                         break;
8836                 }
8837         }
8838         if (attr_index == -1)
8839                 return NULL;
8840
8841         attrs = mono_custom_attrs_construct (ainfo);
8842         if (attrs)
8843                 return mono_array_get (attrs, MonoObject*, attr_index);
8844         else
8845                 return NULL;
8846 }
8847
8848 /*
8849  * mono_reflection_get_custom_attrs_info:
8850  * @obj: a reflection object handle
8851  *
8852  * Return the custom attribute info for attributes defined for the
8853  * reflection handle @obj. The objects.
8854  *
8855  * FIXME this function leaks like a sieve for SRE objects.
8856  */
8857 MonoCustomAttrInfo*
8858 mono_reflection_get_custom_attrs_info (MonoObject *obj)
8859 {
8860         MonoClass *klass;
8861         MonoCustomAttrInfo *cinfo = NULL;
8862         
8863         klass = obj->vtable->klass;
8864         if (klass == mono_defaults.monotype_class) {
8865                 MonoType *type = mono_reflection_type_get_handle ((MonoReflectionType *)obj);
8866                 klass = mono_class_from_mono_type (type);
8867                 /*We cannot mono_class_init the class from which we'll load the custom attributes since this must work with broken types.*/
8868                 cinfo = mono_custom_attrs_from_class (klass);
8869         } else if (strcmp ("Assembly", klass->name) == 0 || strcmp ("MonoAssembly", klass->name) == 0) {
8870                 MonoReflectionAssembly *rassembly = (MonoReflectionAssembly*)obj;
8871                 cinfo = mono_custom_attrs_from_assembly (rassembly->assembly);
8872         } else if (strcmp ("Module", klass->name) == 0 || strcmp ("MonoModule", klass->name) == 0) {
8873                 MonoReflectionModule *module = (MonoReflectionModule*)obj;
8874                 cinfo = mono_custom_attrs_from_module (module->image);
8875         } else if (strcmp ("MonoProperty", klass->name) == 0) {
8876                 MonoReflectionProperty *rprop = (MonoReflectionProperty*)obj;
8877                 cinfo = mono_custom_attrs_from_property (rprop->property->parent, rprop->property);
8878         } else if (strcmp ("MonoEvent", klass->name) == 0) {
8879                 MonoReflectionMonoEvent *revent = (MonoReflectionMonoEvent*)obj;
8880                 cinfo = mono_custom_attrs_from_event (revent->event->parent, revent->event);
8881         } else if (strcmp ("MonoField", klass->name) == 0) {
8882                 MonoReflectionField *rfield = (MonoReflectionField*)obj;
8883                 cinfo = mono_custom_attrs_from_field (rfield->field->parent, rfield->field);
8884         } else if ((strcmp ("MonoMethod", klass->name) == 0) || (strcmp ("MonoCMethod", klass->name) == 0)) {
8885                 MonoReflectionMethod *rmethod = (MonoReflectionMethod*)obj;
8886                 cinfo = mono_custom_attrs_from_method (rmethod->method);
8887         } else if ((strcmp ("MonoGenericMethod", klass->name) == 0) || (strcmp ("MonoGenericCMethod", klass->name) == 0)) {
8888                 MonoReflectionMethod *rmethod = (MonoReflectionMethod*)obj;
8889                 cinfo = mono_custom_attrs_from_method (rmethod->method);
8890         } else if (strcmp ("ParameterInfo", klass->name) == 0 || strcmp ("MonoParameterInfo", klass->name) == 0) {
8891                 MonoReflectionParameter *param = (MonoReflectionParameter*)obj;
8892                 MonoClass *member_class = mono_object_class (param->MemberImpl);
8893                 if (mono_class_is_reflection_method_or_constructor (member_class)) {
8894                         MonoReflectionMethod *rmethod = (MonoReflectionMethod*)param->MemberImpl;
8895                         cinfo = mono_custom_attrs_from_param (rmethod->method, param->PositionImpl + 1);
8896                 } else if (is_sr_mono_property (member_class)) {
8897                         MonoReflectionProperty *prop = (MonoReflectionProperty *)param->MemberImpl;
8898                         MonoMethod *method;
8899                         if (!(method = prop->property->get))
8900                                 method = prop->property->set;
8901                         g_assert (method);
8902
8903                         cinfo = mono_custom_attrs_from_param (method, param->PositionImpl + 1);
8904                 } 
8905 #ifndef DISABLE_REFLECTION_EMIT
8906                 else if (is_sre_method_on_tb_inst (member_class)) {/*XXX This is a workaround for Compiler Context*/
8907                         MonoMethod *method = mono_reflection_method_on_tb_inst_get_handle ((MonoReflectionMethodOnTypeBuilderInst*)param->MemberImpl);
8908                         cinfo = mono_custom_attrs_from_param (method, param->PositionImpl + 1);
8909                 } else if (is_sre_ctor_on_tb_inst (member_class)) { /*XX This is a workaround for Compiler Context*/
8910                         MonoReflectionCtorOnTypeBuilderInst *c = (MonoReflectionCtorOnTypeBuilderInst*)param->MemberImpl;
8911                         MonoMethod *method = NULL;
8912                         if (is_sre_ctor_builder (mono_object_class (c->cb)))
8913                                 method = ((MonoReflectionCtorBuilder *)c->cb)->mhandle;
8914                         else if (is_sr_mono_cmethod (mono_object_class (c->cb)))
8915                                 method = ((MonoReflectionMethod *)c->cb)->method;
8916                         else
8917                                 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));
8918
8919                         cinfo = mono_custom_attrs_from_param (method, param->PositionImpl + 1);
8920                 } 
8921 #endif
8922                 else {
8923                         char *type_name = mono_type_get_full_name (member_class);
8924                         char *msg = g_strdup_printf ("Custom attributes on a ParamInfo with member %s are not supported", type_name);
8925                         MonoException *ex = mono_get_exception_not_supported  (msg);
8926                         g_free (type_name);
8927                         g_free (msg);
8928                         mono_raise_exception (ex);
8929                 }
8930         } else if (strcmp ("AssemblyBuilder", klass->name) == 0) {
8931                 MonoReflectionAssemblyBuilder *assemblyb = (MonoReflectionAssemblyBuilder*)obj;
8932                 cinfo = mono_custom_attrs_from_builders (NULL, assemblyb->assembly.assembly->image, assemblyb->cattrs);
8933         } else if (strcmp ("TypeBuilder", klass->name) == 0) {
8934                 MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder*)obj;
8935                 cinfo = mono_custom_attrs_from_builders (NULL, &tb->module->dynamic_image->image, tb->cattrs);
8936         } else if (strcmp ("ModuleBuilder", klass->name) == 0) {
8937                 MonoReflectionModuleBuilder *mb = (MonoReflectionModuleBuilder*)obj;
8938                 cinfo = mono_custom_attrs_from_builders (NULL, &mb->dynamic_image->image, mb->cattrs);
8939         } else if (strcmp ("ConstructorBuilder", klass->name) == 0) {
8940                 MonoReflectionCtorBuilder *cb = (MonoReflectionCtorBuilder*)obj;
8941                 cinfo = mono_custom_attrs_from_builders (NULL, cb->mhandle->klass->image, cb->cattrs);
8942         } else if (strcmp ("MethodBuilder", klass->name) == 0) {
8943                 MonoReflectionMethodBuilder *mb = (MonoReflectionMethodBuilder*)obj;
8944                 cinfo = mono_custom_attrs_from_builders (NULL, mb->mhandle->klass->image, mb->cattrs);
8945         } else if (strcmp ("FieldBuilder", klass->name) == 0) {
8946                 MonoReflectionFieldBuilder *fb = (MonoReflectionFieldBuilder*)obj;
8947                 cinfo = mono_custom_attrs_from_builders (NULL, &((MonoReflectionTypeBuilder*)fb->typeb)->module->dynamic_image->image, fb->cattrs);
8948         } else if (strcmp ("MonoGenericClass", klass->name) == 0) {
8949                 MonoReflectionGenericClass *gclass = (MonoReflectionGenericClass*)obj;
8950                 cinfo = mono_reflection_get_custom_attrs_info ((MonoObject*)gclass->generic_type);
8951         } else { /* handle other types here... */
8952                 g_error ("get custom attrs not yet supported for %s", klass->name);
8953         }
8954
8955         return cinfo;
8956 }
8957
8958 /*
8959  * mono_reflection_get_custom_attrs_by_type:
8960  * @obj: a reflection object handle
8961  *
8962  * Return an array with all the custom attributes defined of the
8963  * reflection handle @obj. If @attr_klass is non-NULL, only custom attributes 
8964  * of that type are returned. The objects are fully build. Return NULL if a loading error
8965  * occurs.
8966  */
8967 MonoArray*
8968 mono_reflection_get_custom_attrs_by_type (MonoObject *obj, MonoClass *attr_klass, MonoError *error)
8969 {
8970         MonoArray *result;
8971         MonoCustomAttrInfo *cinfo;
8972
8973         mono_error_init (error);
8974
8975         cinfo = mono_reflection_get_custom_attrs_info (obj);
8976         if (cinfo) {
8977                 result = mono_custom_attrs_construct_by_type (cinfo, attr_klass, error);
8978                 if (!cinfo->cached)
8979                         mono_custom_attrs_free (cinfo);
8980         } else {
8981                 if (mono_loader_get_last_error ())
8982                         return NULL;
8983                 result = mono_array_new_cached (mono_domain_get (), mono_defaults.attribute_class, 0);
8984         }
8985
8986         return result;
8987 }
8988
8989 /*
8990  * mono_reflection_get_custom_attrs:
8991  * @obj: a reflection object handle
8992  *
8993  * Return an array with all the custom attributes defined of the
8994  * reflection handle @obj. The objects are fully build. Return NULL if a loading error
8995  * occurs.
8996  */
8997 MonoArray*
8998 mono_reflection_get_custom_attrs (MonoObject *obj)
8999 {
9000         MonoError error;
9001
9002         return mono_reflection_get_custom_attrs_by_type (obj, NULL, &error);
9003 }
9004
9005 /*
9006  * mono_reflection_get_custom_attrs_data:
9007  * @obj: a reflection obj handle
9008  *
9009  * Returns an array of System.Reflection.CustomAttributeData,
9010  * which include information about attributes reflected on
9011  * types loaded using the Reflection Only methods
9012  */
9013 MonoArray*
9014 mono_reflection_get_custom_attrs_data (MonoObject *obj)
9015 {
9016         MonoArray *result;
9017         MonoCustomAttrInfo *cinfo;
9018
9019         cinfo = mono_reflection_get_custom_attrs_info (obj);
9020         if (cinfo) {
9021                 result = mono_custom_attrs_data_construct (cinfo);
9022                 if (!cinfo->cached)
9023                         mono_custom_attrs_free (cinfo);
9024         } else
9025                 result = mono_array_new (mono_domain_get (), mono_defaults.customattribute_data_class, 0);
9026
9027         return result;
9028 }
9029
9030 static MonoReflectionType*
9031 mono_reflection_type_get_underlying_system_type (MonoReflectionType* t)
9032 {
9033         static MonoMethod *method_get_underlying_system_type = NULL;
9034         MonoMethod *usertype_method;
9035
9036         if (!method_get_underlying_system_type)
9037                 method_get_underlying_system_type = mono_class_get_method_from_name (mono_defaults.systemtype_class, "get_UnderlyingSystemType", 0);
9038         usertype_method = mono_object_get_virtual_method ((MonoObject *) t, method_get_underlying_system_type);
9039         return (MonoReflectionType *) mono_runtime_invoke (usertype_method, t, NULL, NULL);
9040 }
9041
9042
9043 static gboolean
9044 is_corlib_type (MonoClass *class)
9045 {
9046         return class->image == mono_defaults.corlib;
9047 }
9048
9049 #define check_corlib_type_cached(_class, _namespace, _name) do { \
9050         static MonoClass *cached_class; \
9051         if (cached_class) \
9052                 return cached_class == _class; \
9053         if (is_corlib_type (_class) && !strcmp (_name, _class->name) && !strcmp (_namespace, _class->name_space)) { \
9054                 cached_class = _class; \
9055                 return TRUE; \
9056         } \
9057         return FALSE; \
9058 } while (0) \
9059
9060
9061 #ifndef DISABLE_REFLECTION_EMIT
9062 static gboolean
9063 is_sre_array (MonoClass *class)
9064 {
9065         check_corlib_type_cached (class, "System.Reflection.Emit", "ArrayType");
9066 }
9067
9068 static gboolean
9069 is_sre_byref (MonoClass *class)
9070 {
9071         check_corlib_type_cached (class, "System.Reflection.Emit", "ByRefType");
9072 }
9073
9074 static gboolean
9075 is_sre_pointer (MonoClass *class)
9076 {
9077         check_corlib_type_cached (class, "System.Reflection.Emit", "PointerType");
9078 }
9079
9080 static gboolean
9081 is_sre_generic_instance (MonoClass *class)
9082 {
9083         check_corlib_type_cached (class, "System.Reflection", "MonoGenericClass");
9084 }
9085
9086 static gboolean
9087 is_sre_type_builder (MonoClass *class)
9088 {
9089         check_corlib_type_cached (class, "System.Reflection.Emit", "TypeBuilder");
9090 }
9091
9092 static gboolean
9093 is_sre_method_builder (MonoClass *class)
9094 {
9095         check_corlib_type_cached (class, "System.Reflection.Emit", "MethodBuilder");
9096 }
9097
9098 static gboolean
9099 is_sre_ctor_builder (MonoClass *class)
9100 {
9101         check_corlib_type_cached (class, "System.Reflection.Emit", "ConstructorBuilder");
9102 }
9103
9104 static gboolean
9105 is_sre_field_builder (MonoClass *class)
9106 {
9107         check_corlib_type_cached (class, "System.Reflection.Emit", "FieldBuilder");
9108 }
9109
9110 static gboolean
9111 is_sre_method_on_tb_inst (MonoClass *class)
9112 {
9113         check_corlib_type_cached (class, "System.Reflection.Emit", "MethodOnTypeBuilderInst");
9114 }
9115
9116 static gboolean
9117 is_sre_ctor_on_tb_inst (MonoClass *class)
9118 {
9119         check_corlib_type_cached (class, "System.Reflection.Emit", "ConstructorOnTypeBuilderInst");
9120 }
9121
9122 MonoType*
9123 mono_reflection_type_get_handle (MonoReflectionType* ref)
9124 {
9125         MonoClass *class;
9126         if (!ref)
9127                 return NULL;
9128         if (ref->type)
9129                 return ref->type;
9130
9131         if (is_usertype (ref)) {
9132                 ref = mono_reflection_type_get_underlying_system_type (ref);
9133                 if (ref == NULL || is_usertype (ref))
9134                         return NULL;
9135                 if (ref->type)
9136                         return ref->type;
9137         }
9138
9139         class = mono_object_class (ref);
9140
9141         if (is_sre_array (class)) {
9142                 MonoType *res;
9143                 MonoReflectionArrayType *sre_array = (MonoReflectionArrayType*)ref;
9144                 MonoType *base = mono_reflection_type_get_handle (sre_array->element_type);
9145                 g_assert (base);
9146                 if (sre_array->rank == 0) //single dimentional array
9147                         res = &mono_array_class_get (mono_class_from_mono_type (base), 1)->byval_arg;
9148                 else
9149                         res = &mono_bounded_array_class_get (mono_class_from_mono_type (base), sre_array->rank, TRUE)->byval_arg;
9150                 sre_array->type.type = res;
9151                 return res;
9152         } else if (is_sre_byref (class)) {
9153                 MonoType *res;
9154                 MonoReflectionDerivedType *sre_byref = (MonoReflectionDerivedType*)ref;
9155                 MonoType *base = mono_reflection_type_get_handle (sre_byref->element_type);
9156                 g_assert (base);
9157                 res = &mono_class_from_mono_type (base)->this_arg;
9158                 sre_byref->type.type = res;
9159                 return res;
9160         } else if (is_sre_pointer (class)) {
9161                 MonoType *res;
9162                 MonoReflectionDerivedType *sre_pointer = (MonoReflectionDerivedType*)ref;
9163                 MonoType *base = mono_reflection_type_get_handle (sre_pointer->element_type);
9164                 g_assert (base);
9165                 res = &mono_ptr_class_get (base)->byval_arg;
9166                 sre_pointer->type.type = res;
9167                 return res;
9168         } else if (is_sre_generic_instance (class)) {
9169                 MonoType *res, **types;
9170                 MonoReflectionGenericClass *gclass = (MonoReflectionGenericClass*)ref;
9171                 int i, count;
9172
9173                 count = mono_array_length (gclass->type_arguments);
9174                 types = g_new0 (MonoType*, count);
9175                 for (i = 0; i < count; ++i) {
9176                         MonoReflectionType *t = mono_array_get (gclass->type_arguments, gpointer, i);
9177                         types [i] = mono_reflection_type_get_handle (t);
9178                         if (!types[i]) {
9179                                 g_free (types);
9180                                 return NULL;
9181                         }
9182                 }
9183
9184                 res = mono_reflection_bind_generic_parameters (gclass->generic_type, count, types);
9185                 g_free (types);
9186                 g_assert (res);
9187                 gclass->type.type = res;
9188                 return res;
9189         }
9190
9191         g_error ("Cannot handle corlib user type %s", mono_type_full_name (&mono_object_class(ref)->byval_arg));
9192         return NULL;
9193 }
9194
9195
9196
9197 void
9198 mono_reflection_create_unmanaged_type (MonoReflectionType *type)
9199 {
9200         mono_reflection_type_get_handle (type);
9201 }
9202
9203 void
9204 mono_reflection_register_with_runtime (MonoReflectionType *type)
9205 {
9206         MonoType *res = mono_reflection_type_get_handle (type);
9207         MonoDomain *domain = mono_object_domain ((MonoObject*)type);
9208         MonoClass *class;
9209
9210         if (!res)
9211                 mono_raise_exception (mono_get_exception_argument (NULL, "Invalid generic instantiation, one or more arguments are not proper user types"));
9212
9213         class = mono_class_from_mono_type (res);
9214
9215         mono_loader_lock (); /*same locking as mono_type_get_object*/
9216         mono_domain_lock (domain);
9217
9218         if (!class->image->dynamic) {
9219                 mono_class_setup_supertypes (class);
9220         } else {
9221                 if (!domain->type_hash)
9222                         domain->type_hash = mono_g_hash_table_new_type ((GHashFunc)mono_metadata_type_hash, 
9223                                         (GCompareFunc)mono_metadata_type_equal, MONO_HASH_VALUE_GC);
9224                 mono_g_hash_table_insert (domain->type_hash, res, type);
9225         }
9226         mono_domain_unlock (domain);
9227         mono_loader_unlock ();
9228 }
9229
9230 /**
9231  * LOCKING: Assumes the loader lock is held.
9232  */
9233 static MonoMethodSignature*
9234 parameters_to_signature (MonoImage *image, MonoArray *parameters) {
9235         MonoMethodSignature *sig;
9236         int count, i;
9237
9238         count = parameters? mono_array_length (parameters): 0;
9239
9240         sig = image_g_malloc0 (image, MONO_SIZEOF_METHOD_SIGNATURE + sizeof (MonoType*) * count);
9241         sig->param_count = count;
9242         sig->sentinelpos = -1; /* FIXME */
9243         for (i = 0; i < count; ++i)
9244                 sig->params [i] = mono_type_array_get_and_resolve (parameters, i);
9245         return sig;
9246 }
9247
9248 /**
9249  * LOCKING: Assumes the loader lock is held.
9250  */
9251 static MonoMethodSignature*
9252 ctor_builder_to_signature (MonoImage *image, MonoReflectionCtorBuilder *ctor) {
9253         MonoMethodSignature *sig;
9254
9255         sig = parameters_to_signature (image, ctor->parameters);
9256         sig->hasthis = ctor->attrs & METHOD_ATTRIBUTE_STATIC? 0: 1;
9257         sig->ret = &mono_defaults.void_class->byval_arg;
9258         return sig;
9259 }
9260
9261 /**
9262  * LOCKING: Assumes the loader lock is held.
9263  */
9264 static MonoMethodSignature*
9265 method_builder_to_signature (MonoImage *image, MonoReflectionMethodBuilder *method) {
9266         MonoMethodSignature *sig;
9267
9268         sig = parameters_to_signature (image, method->parameters);
9269         sig->hasthis = method->attrs & METHOD_ATTRIBUTE_STATIC? 0: 1;
9270         sig->ret = method->rtype? mono_reflection_type_get_handle ((MonoReflectionType*)method->rtype): &mono_defaults.void_class->byval_arg;
9271         sig->generic_param_count = method->generic_params ? mono_array_length (method->generic_params) : 0;
9272         return sig;
9273 }
9274
9275 static MonoMethodSignature*
9276 dynamic_method_to_signature (MonoReflectionDynamicMethod *method) {
9277         MonoMethodSignature *sig;
9278
9279         sig = parameters_to_signature (NULL, method->parameters);
9280         sig->hasthis = method->attrs & METHOD_ATTRIBUTE_STATIC? 0: 1;
9281         sig->ret = method->rtype? mono_reflection_type_get_handle (method->rtype): &mono_defaults.void_class->byval_arg;
9282         sig->generic_param_count = 0;
9283         return sig;
9284 }
9285
9286 static void
9287 get_prop_name_and_type (MonoObject *prop, char **name, MonoType **type)
9288 {
9289         MonoClass *klass = mono_object_class (prop);
9290         if (strcmp (klass->name, "PropertyBuilder") == 0) {
9291                 MonoReflectionPropertyBuilder *pb = (MonoReflectionPropertyBuilder *)prop;
9292                 *name = mono_string_to_utf8 (pb->name);
9293                 *type = mono_reflection_type_get_handle ((MonoReflectionType*)pb->type);
9294         } else {
9295                 MonoReflectionProperty *p = (MonoReflectionProperty *)prop;
9296                 *name = g_strdup (p->property->name);
9297                 if (p->property->get)
9298                         *type = mono_method_signature (p->property->get)->ret;
9299                 else
9300                         *type = mono_method_signature (p->property->set)->params [mono_method_signature (p->property->set)->param_count - 1];
9301         }
9302 }
9303
9304 static void
9305 get_field_name_and_type (MonoObject *field, char **name, MonoType **type)
9306 {
9307         MonoClass *klass = mono_object_class (field);
9308         if (strcmp (klass->name, "FieldBuilder") == 0) {
9309                 MonoReflectionFieldBuilder *fb = (MonoReflectionFieldBuilder *)field;
9310                 *name = mono_string_to_utf8 (fb->name);
9311                 *type = mono_reflection_type_get_handle ((MonoReflectionType*)fb->type);
9312         } else {
9313                 MonoReflectionField *f = (MonoReflectionField *)field;
9314                 *name = g_strdup (mono_field_get_name (f->field));
9315                 *type = f->field->type;
9316         }
9317 }
9318
9319 #else /* DISABLE_REFLECTION_EMIT */
9320
9321 void
9322 mono_reflection_register_with_runtime (MonoReflectionType *type)
9323 {
9324         /* This is empty */
9325 }
9326
9327 static gboolean
9328 is_sre_type_builder (MonoClass *class)
9329 {
9330         return FALSE;
9331 }
9332
9333 static gboolean
9334 is_sre_generic_instance (MonoClass *class)
9335 {
9336         return FALSE;
9337 }
9338
9339 static void
9340 init_type_builder_generics (MonoObject *type)
9341 {
9342 }
9343
9344 #endif /* !DISABLE_REFLECTION_EMIT */
9345
9346
9347 static gboolean
9348 is_sr_mono_field (MonoClass *class)
9349 {
9350         check_corlib_type_cached (class, "System.Reflection", "MonoField");
9351 }
9352
9353 static gboolean
9354 is_sr_mono_property (MonoClass *class)
9355 {
9356         check_corlib_type_cached (class, "System.Reflection", "MonoProperty");
9357 }
9358
9359 static gboolean
9360 is_sr_mono_method (MonoClass *class)
9361 {
9362         check_corlib_type_cached (class, "System.Reflection", "MonoMethod");
9363 }
9364
9365 static gboolean
9366 is_sr_mono_cmethod (MonoClass *class)
9367 {
9368         check_corlib_type_cached (class, "System.Reflection", "MonoCMethod");
9369 }
9370
9371 static gboolean
9372 is_sr_mono_generic_method (MonoClass *class)
9373 {
9374         check_corlib_type_cached (class, "System.Reflection", "MonoGenericMethod");
9375 }
9376
9377 static gboolean
9378 is_sr_mono_generic_cmethod (MonoClass *class)
9379 {
9380         check_corlib_type_cached (class, "System.Reflection", "MonoGenericCMethod");
9381 }
9382
9383 gboolean
9384 mono_class_is_reflection_method_or_constructor (MonoClass *class)
9385 {
9386         return is_sr_mono_method (class) || is_sr_mono_cmethod (class) || is_sr_mono_generic_method (class) || is_sr_mono_generic_cmethod (class);
9387 }
9388
9389 static gboolean
9390 is_usertype (MonoReflectionType *ref)
9391 {
9392         MonoClass *class = mono_object_class (ref);
9393         return class->image != mono_defaults.corlib || strcmp ("TypeDelegator", class->name) == 0;
9394 }
9395
9396 static MonoReflectionType*
9397 mono_reflection_type_resolve_user_types (MonoReflectionType *type)
9398 {
9399         if (!type || type->type)
9400                 return type;
9401
9402         if (is_usertype (type)) {
9403                 type = mono_reflection_type_get_underlying_system_type (type);
9404                 if (is_usertype (type))
9405                         mono_raise_exception (mono_get_exception_not_supported ("User defined subclasses of System.Type are not yet supported22"));
9406         }
9407
9408         return type;
9409 }
9410 /*
9411  * Encode a value in a custom attribute stream of bytes.
9412  * The value to encode is either supplied as an object in argument val
9413  * (valuetypes are boxed), or as a pointer to the data in the
9414  * argument argval.
9415  * @type represents the type of the value
9416  * @buffer is the start of the buffer
9417  * @p the current position in the buffer
9418  * @buflen contains the size of the buffer and is used to return the new buffer size
9419  * if this needs to be realloced.
9420  * @retbuffer and @retp return the start and the position of the buffer
9421  */
9422 static void
9423 encode_cattr_value (MonoAssembly *assembly, char *buffer, char *p, char **retbuffer, char **retp, guint32 *buflen, MonoType *type, MonoObject *arg, char *argval)
9424 {
9425         MonoTypeEnum simple_type;
9426         
9427         if ((p-buffer) + 10 >= *buflen) {
9428                 char *newbuf;
9429                 *buflen *= 2;
9430                 newbuf = g_realloc (buffer, *buflen);
9431                 p = newbuf + (p-buffer);
9432                 buffer = newbuf;
9433         }
9434         if (!argval)
9435                 argval = ((char*)arg + sizeof (MonoObject));
9436         simple_type = type->type;
9437 handle_enum:
9438         switch (simple_type) {
9439         case MONO_TYPE_BOOLEAN:
9440         case MONO_TYPE_U1:
9441         case MONO_TYPE_I1:
9442                 *p++ = *argval;
9443                 break;
9444         case MONO_TYPE_CHAR:
9445         case MONO_TYPE_U2:
9446         case MONO_TYPE_I2:
9447                 swap_with_size (p, argval, 2, 1);
9448                 p += 2;
9449                 break;
9450         case MONO_TYPE_U4:
9451         case MONO_TYPE_I4:
9452         case MONO_TYPE_R4:
9453                 swap_with_size (p, argval, 4, 1);
9454                 p += 4;
9455                 break;
9456         case MONO_TYPE_R8:
9457                 swap_with_size (p, argval, 8, 1);
9458                 p += 8;
9459                 break;
9460         case MONO_TYPE_U8:
9461         case MONO_TYPE_I8:
9462                 swap_with_size (p, argval, 8, 1);
9463                 p += 8;
9464                 break;
9465         case MONO_TYPE_VALUETYPE:
9466                 if (type->data.klass->enumtype) {
9467                         simple_type = mono_class_enum_basetype (type->data.klass)->type;
9468                         goto handle_enum;
9469                 } else {
9470                         g_warning ("generic valutype %s not handled in custom attr value decoding", type->data.klass->name);
9471                 }
9472                 break;
9473         case MONO_TYPE_STRING: {
9474                 char *str;
9475                 guint32 slen;
9476                 if (!arg) {
9477                         *p++ = 0xFF;
9478                         break;
9479                 }
9480                 str = mono_string_to_utf8 ((MonoString*)arg);
9481                 slen = strlen (str);
9482                 if ((p-buffer) + 10 + slen >= *buflen) {
9483                         char *newbuf;
9484                         *buflen *= 2;
9485                         *buflen += slen;
9486                         newbuf = g_realloc (buffer, *buflen);
9487                         p = newbuf + (p-buffer);
9488                         buffer = newbuf;
9489                 }
9490                 mono_metadata_encode_value (slen, p, &p);
9491                 memcpy (p, str, slen);
9492                 p += slen;
9493                 g_free (str);
9494                 break;
9495         }
9496         case MONO_TYPE_CLASS: {
9497                 char *str;
9498                 guint32 slen;
9499                 if (!arg) {
9500                         *p++ = 0xFF;
9501                         break;
9502                 }
9503 handle_type:
9504                 str = type_get_qualified_name (mono_reflection_type_get_handle ((MonoReflectionType*)arg), NULL);
9505                 slen = strlen (str);
9506                 if ((p-buffer) + 10 + slen >= *buflen) {
9507                         char *newbuf;
9508                         *buflen *= 2;
9509                         *buflen += slen;
9510                         newbuf = g_realloc (buffer, *buflen);
9511                         p = newbuf + (p-buffer);
9512                         buffer = newbuf;
9513                 }
9514                 mono_metadata_encode_value (slen, p, &p);
9515                 memcpy (p, str, slen);
9516                 p += slen;
9517                 g_free (str);
9518                 break;
9519         }
9520         case MONO_TYPE_SZARRAY: {
9521                 int len, i;
9522                 MonoClass *eclass, *arg_eclass;
9523
9524                 if (!arg) {
9525                         *p++ = 0xff; *p++ = 0xff; *p++ = 0xff; *p++ = 0xff;
9526                         break;
9527                 }
9528                 len = mono_array_length ((MonoArray*)arg);
9529                 *p++ = len & 0xff;
9530                 *p++ = (len >> 8) & 0xff;
9531                 *p++ = (len >> 16) & 0xff;
9532                 *p++ = (len >> 24) & 0xff;
9533                 *retp = p;
9534                 *retbuffer = buffer;
9535                 eclass = type->data.klass;
9536                 arg_eclass = mono_object_class (arg)->element_class;
9537
9538                 if (!eclass) {
9539                         /* Happens when we are called from the MONO_TYPE_OBJECT case below */
9540                         eclass = mono_defaults.object_class;
9541                 }
9542                 if (eclass == mono_defaults.object_class && arg_eclass->valuetype) {
9543                         char *elptr = mono_array_addr ((MonoArray*)arg, char, 0);
9544                         int elsize = mono_class_array_element_size (arg_eclass);
9545                         for (i = 0; i < len; ++i) {
9546                                 encode_cattr_value (assembly, buffer, p, &buffer, &p, buflen, &arg_eclass->byval_arg, NULL, elptr);
9547                                 elptr += elsize;
9548                         }
9549                 } else if (eclass->valuetype && arg_eclass->valuetype) {
9550                         char *elptr = mono_array_addr ((MonoArray*)arg, char, 0);
9551                         int elsize = mono_class_array_element_size (eclass);
9552                         for (i = 0; i < len; ++i) {
9553                                 encode_cattr_value (assembly, buffer, p, &buffer, &p, buflen, &eclass->byval_arg, NULL, elptr);
9554                                 elptr += elsize;
9555                         }
9556                 } else {
9557                         for (i = 0; i < len; ++i) {
9558                                 encode_cattr_value (assembly, buffer, p, &buffer, &p, buflen, &eclass->byval_arg, mono_array_get ((MonoArray*)arg, MonoObject*, i), NULL);
9559                         }
9560                 }
9561                 break;
9562         }
9563         case MONO_TYPE_OBJECT: {
9564                 MonoClass *klass;
9565                 char *str;
9566                 guint32 slen;
9567
9568                 /*
9569                  * The parameter type is 'object' but the type of the actual
9570                  * argument is not. So we have to add type information to the blob
9571                  * too. This is completely undocumented in the spec.
9572                  */
9573
9574                 if (arg == NULL) {
9575                         *p++ = MONO_TYPE_STRING;        // It's same hack as MS uses
9576                         *p++ = 0xFF;
9577                         break;
9578                 }
9579                 
9580                 klass = mono_object_class (arg);
9581
9582                 if (mono_object_isinst (arg, mono_defaults.systemtype_class)) {
9583                         *p++ = 0x50;
9584                         goto handle_type;
9585                 } else if (klass->enumtype) {
9586                         *p++ = 0x55;
9587                 } else if (klass == mono_defaults.string_class) {
9588                         simple_type = MONO_TYPE_STRING;
9589                         *p++ = 0x0E;
9590                         goto handle_enum;
9591                 } else if (klass->rank == 1) {
9592                         *p++ = 0x1D;
9593                         if (klass->element_class->byval_arg.type == MONO_TYPE_OBJECT)
9594                                 /* See Partition II, Appendix B3 */
9595                                 *p++ = 0x51;
9596                         else
9597                                 *p++ = klass->element_class->byval_arg.type;
9598                         encode_cattr_value (assembly, buffer, p, &buffer, &p, buflen, &klass->byval_arg, arg, NULL);
9599                         break;
9600                 } else if (klass->byval_arg.type >= MONO_TYPE_BOOLEAN && klass->byval_arg.type <= MONO_TYPE_R8) {
9601                         *p++ = simple_type = klass->byval_arg.type;
9602                         goto handle_enum;
9603                 } else {
9604                         g_error ("unhandled type in custom attr");
9605                 }
9606                 str = type_get_qualified_name (mono_class_get_type(klass), NULL);
9607                 slen = strlen (str);
9608                 if ((p-buffer) + 10 + slen >= *buflen) {
9609                         char *newbuf;
9610                         *buflen *= 2;
9611                         *buflen += slen;
9612                         newbuf = g_realloc (buffer, *buflen);
9613                         p = newbuf + (p-buffer);
9614                         buffer = newbuf;
9615                 }
9616                 mono_metadata_encode_value (slen, p, &p);
9617                 memcpy (p, str, slen);
9618                 p += slen;
9619                 g_free (str);
9620                 simple_type = mono_class_enum_basetype (klass)->type;
9621                 goto handle_enum;
9622         }
9623         default:
9624                 g_error ("type 0x%02x not yet supported in custom attr encoder", simple_type);
9625         }
9626         *retp = p;
9627         *retbuffer = buffer;
9628 }
9629
9630 static void
9631 encode_field_or_prop_type (MonoType *type, char *p, char **retp)
9632 {
9633         if (type->type == MONO_TYPE_VALUETYPE && type->data.klass->enumtype) {
9634                 char *str = type_get_qualified_name (type, NULL);
9635                 int slen = strlen (str);
9636
9637                 *p++ = 0x55;
9638                 /*
9639                  * This seems to be optional...
9640                  * *p++ = 0x80;
9641                  */
9642                 mono_metadata_encode_value (slen, p, &p);
9643                 memcpy (p, str, slen);
9644                 p += slen;
9645                 g_free (str);
9646         } else if (type->type == MONO_TYPE_OBJECT) {
9647                 *p++ = 0x51;
9648         } else if (type->type == MONO_TYPE_CLASS) {
9649                 /* it should be a type: encode_cattr_value () has the check */
9650                 *p++ = 0x50;
9651         } else {
9652                 mono_metadata_encode_value (type->type, p, &p);
9653                 if (type->type == MONO_TYPE_SZARRAY)
9654                         /* See the examples in Partition VI, Annex B */
9655                         encode_field_or_prop_type (&type->data.klass->byval_arg, p, &p);
9656         }
9657
9658         *retp = p;
9659 }
9660
9661 #ifndef DISABLE_REFLECTION_EMIT
9662 static void
9663 encode_named_val (MonoReflectionAssembly *assembly, char *buffer, char *p, char **retbuffer, char **retp, guint32 *buflen, MonoType *type, char *name, MonoObject *value)
9664 {
9665         int len;
9666         /* Preallocate a large enough buffer */
9667         if (type->type == MONO_TYPE_VALUETYPE && type->data.klass->enumtype) {
9668                 char *str = type_get_qualified_name (type, NULL);
9669                 len = strlen (str);
9670                 g_free (str);
9671         } else if (type->type == MONO_TYPE_SZARRAY && type->data.klass->enumtype) {
9672                 char *str = type_get_qualified_name (&type->data.klass->byval_arg, NULL);
9673                 len = strlen (str);
9674                 g_free (str);
9675         } else {
9676                 len = 0;
9677         }
9678         len += strlen (name);
9679
9680         if ((p-buffer) + 20 + len >= *buflen) {
9681                 char *newbuf;
9682                 *buflen *= 2;
9683                 *buflen += len;
9684                 newbuf = g_realloc (buffer, *buflen);
9685                 p = newbuf + (p-buffer);
9686                 buffer = newbuf;
9687         }
9688
9689         encode_field_or_prop_type (type, p, &p);
9690
9691         len = strlen (name);
9692         mono_metadata_encode_value (len, p, &p);
9693         memcpy (p, name, len);
9694         p += len;
9695         encode_cattr_value (assembly->assembly, buffer, p, &buffer, &p, buflen, type, value, NULL);
9696         *retp = p;
9697         *retbuffer = buffer;
9698 }
9699
9700 /*
9701  * mono_reflection_get_custom_attrs_blob:
9702  * @ctor: custom attribute constructor
9703  * @ctorArgs: arguments o the constructor
9704  * @properties:
9705  * @propValues:
9706  * @fields:
9707  * @fieldValues:
9708  * 
9709  * Creates the blob of data that needs to be saved in the metadata and that represents
9710  * the custom attributed described by @ctor, @ctorArgs etc.
9711  * Returns: a Byte array representing the blob of data.
9712  */
9713 MonoArray*
9714 mono_reflection_get_custom_attrs_blob (MonoReflectionAssembly *assembly, MonoObject *ctor, MonoArray *ctorArgs, MonoArray *properties, MonoArray *propValues, MonoArray *fields, MonoArray* fieldValues) 
9715 {
9716         MonoArray *result;
9717         MonoMethodSignature *sig;
9718         MonoObject *arg;
9719         char *buffer, *p;
9720         guint32 buflen, i;
9721
9722         MONO_ARCH_SAVE_REGS;
9723
9724         if (strcmp (ctor->vtable->klass->name, "MonoCMethod")) {
9725                 /* sig is freed later so allocate it in the heap */
9726                 sig = ctor_builder_to_signature (NULL, (MonoReflectionCtorBuilder*)ctor);
9727         } else {
9728                 sig = mono_method_signature (((MonoReflectionMethod*)ctor)->method);
9729         }
9730
9731         g_assert (mono_array_length (ctorArgs) == sig->param_count);
9732         buflen = 256;
9733         p = buffer = g_malloc (buflen);
9734         /* write the prolog */
9735         *p++ = 1;
9736         *p++ = 0;
9737         for (i = 0; i < sig->param_count; ++i) {
9738                 arg = mono_array_get (ctorArgs, MonoObject*, i);
9739                 encode_cattr_value (assembly->assembly, buffer, p, &buffer, &p, &buflen, sig->params [i], arg, NULL);
9740         }
9741         i = 0;
9742         if (properties)
9743                 i += mono_array_length (properties);
9744         if (fields)
9745                 i += mono_array_length (fields);
9746         *p++ = i & 0xff;
9747         *p++ = (i >> 8) & 0xff;
9748         if (properties) {
9749                 MonoObject *prop;
9750                 for (i = 0; i < mono_array_length (properties); ++i) {
9751                         MonoType *ptype;
9752                         char *pname;
9753
9754                         prop = mono_array_get (properties, gpointer, i);
9755                         get_prop_name_and_type (prop, &pname, &ptype);
9756                         *p++ = 0x54; /* PROPERTY signature */
9757                         encode_named_val (assembly, buffer, p, &buffer, &p, &buflen, ptype, pname, (MonoObject*)mono_array_get (propValues, gpointer, i));
9758                         g_free (pname);
9759                 }
9760         }
9761
9762         if (fields) {
9763                 MonoObject *field;
9764                 for (i = 0; i < mono_array_length (fields); ++i) {
9765                         MonoType *ftype;
9766                         char *fname;
9767
9768                         field = mono_array_get (fields, gpointer, i);
9769                         get_field_name_and_type (field, &fname, &ftype);
9770                         *p++ = 0x53; /* FIELD signature */
9771                         encode_named_val (assembly, buffer, p, &buffer, &p, &buflen, ftype, fname, (MonoObject*)mono_array_get (fieldValues, gpointer, i));
9772                         g_free (fname);
9773                 }
9774         }
9775
9776         g_assert (p - buffer <= buflen);
9777         buflen = p - buffer;
9778         result = mono_array_new (mono_domain_get (), mono_defaults.byte_class, buflen);
9779         p = mono_array_addr (result, char, 0);
9780         memcpy (p, buffer, buflen);
9781         g_free (buffer);
9782         if (strcmp (ctor->vtable->klass->name, "MonoCMethod"))
9783                 g_free (sig);
9784         return result;
9785 }
9786
9787 /*
9788  * mono_reflection_setup_internal_class:
9789  * @tb: a TypeBuilder object
9790  *
9791  * Creates a MonoClass that represents the TypeBuilder.
9792  * This is a trick that lets us simplify a lot of reflection code
9793  * (and will allow us to support Build and Run assemblies easier).
9794  */
9795 void
9796 mono_reflection_setup_internal_class (MonoReflectionTypeBuilder *tb)
9797 {
9798         MonoError error;
9799         MonoClass *klass, *parent;
9800
9801         MONO_ARCH_SAVE_REGS;
9802
9803         RESOLVE_TYPE (tb->parent);
9804
9805         mono_loader_lock ();
9806
9807         if (tb->parent) {
9808                 /* check so we can compile corlib correctly */
9809                 if (strcmp (mono_object_class (tb->parent)->name, "TypeBuilder") == 0) {
9810                         /* mono_class_setup_mono_type () guaranteess type->data.klass is valid */
9811                         parent = mono_reflection_type_get_handle ((MonoReflectionType*)tb->parent)->data.klass;
9812                 } else {
9813                         parent = mono_class_from_mono_type (mono_reflection_type_get_handle ((MonoReflectionType*)tb->parent));
9814                 }
9815         } else {
9816                 parent = NULL;
9817         }
9818         
9819         /* the type has already being created: it means we just have to change the parent */
9820         if (tb->type.type) {
9821                 klass = mono_class_from_mono_type (tb->type.type);
9822                 klass->parent = NULL;
9823                 /* fool mono_class_setup_parent */
9824                 klass->supertypes = NULL;
9825                 mono_class_setup_parent (klass, parent);
9826                 mono_class_setup_mono_type (klass);
9827                 mono_loader_unlock ();
9828                 return;
9829         }
9830
9831         klass = mono_image_alloc0 (&tb->module->dynamic_image->image, sizeof (MonoClass));
9832
9833         klass->image = &tb->module->dynamic_image->image;
9834
9835         klass->inited = 1; /* we lie to the runtime */
9836         klass->name = mono_string_to_utf8_image (klass->image, tb->name, &error);
9837         if (!mono_error_ok (&error))
9838                 goto failure;
9839         klass->name_space = mono_string_to_utf8_image (klass->image, tb->nspace, &error);
9840         if (!mono_error_ok (&error))
9841                 goto failure;
9842         klass->type_token = MONO_TOKEN_TYPE_DEF | tb->table_idx;
9843         klass->flags = tb->attrs;
9844         
9845         mono_profiler_class_event (klass, MONO_PROFILE_START_LOAD);
9846
9847         klass->element_class = klass;
9848
9849         if (mono_class_get_ref_info (klass) == NULL) {
9850
9851                 mono_class_set_ref_info (klass, tb);
9852
9853                 /* Put into cache so mono_class_get () will find it.
9854                 Skip nested types as those should not be available on the global scope. */
9855                 if (!tb->nesting_type)
9856                         mono_image_add_to_name_cache (klass->image, klass->name_space, klass->name, tb->table_idx);
9857
9858                 /*
9859                 We must register all types as we cannot rely on the name_cache hashtable since we find the class
9860                 by performing a mono_class_get which does the full resolution.
9861
9862                 Working around this semantics would require us to write a lot of code for no clear advantage.
9863                 */
9864                 mono_image_append_class_to_reflection_info_set (klass);
9865         } else {
9866                 g_assert (mono_class_get_ref_info (klass) == tb);
9867         }
9868
9869         mono_g_hash_table_insert (tb->module->dynamic_image->tokens,
9870                 GUINT_TO_POINTER (MONO_TOKEN_TYPE_DEF | tb->table_idx), tb);
9871
9872         if (parent != NULL) {
9873                 mono_class_setup_parent (klass, parent);
9874         } else if (strcmp (klass->name, "Object") == 0 && strcmp (klass->name_space, "System") == 0) {
9875                 const char *old_n = klass->name;
9876                 /* trick to get relative numbering right when compiling corlib */
9877                 klass->name = "BuildingObject";
9878                 mono_class_setup_parent (klass, mono_defaults.object_class);
9879                 klass->name = old_n;
9880         }
9881
9882         if ((!strcmp (klass->name, "ValueType") && !strcmp (klass->name_space, "System")) ||
9883                         (!strcmp (klass->name, "Object") && !strcmp (klass->name_space, "System")) ||
9884                         (!strcmp (klass->name, "Enum") && !strcmp (klass->name_space, "System"))) {
9885                 klass->instance_size = sizeof (MonoObject);
9886                 klass->size_inited = 1;
9887                 mono_class_setup_vtable_general (klass, NULL, 0, NULL);
9888         }
9889
9890         mono_class_setup_mono_type (klass);
9891
9892         mono_class_setup_supertypes (klass);
9893
9894         /*
9895          * FIXME: handle interfaces.
9896          */
9897
9898         tb->type.type = &klass->byval_arg;
9899
9900         if (tb->nesting_type) {
9901                 g_assert (tb->nesting_type->type);
9902                 klass->nested_in = mono_class_from_mono_type (mono_reflection_type_get_handle (tb->nesting_type));
9903         }
9904
9905         /*g_print ("setup %s as %s (%p)\n", klass->name, ((MonoObject*)tb)->vtable->klass->name, tb);*/
9906
9907         mono_profiler_class_loaded (klass, MONO_PROFILE_OK);
9908         
9909         mono_loader_unlock ();
9910         return;
9911
9912 failure:
9913         mono_loader_unlock ();
9914         mono_error_raise_exception (&error);
9915 }
9916
9917 /*
9918  * mono_reflection_setup_generic_class:
9919  * @tb: a TypeBuilder object
9920  *
9921  * Setup the generic class before adding the first generic parameter.
9922  */
9923 void
9924 mono_reflection_setup_generic_class (MonoReflectionTypeBuilder *tb)
9925 {
9926 }
9927
9928 /*
9929  * mono_reflection_create_generic_class:
9930  * @tb: a TypeBuilder object
9931  *
9932  * Creates the generic class after all generic parameters have been added.
9933  */
9934 void
9935 mono_reflection_create_generic_class (MonoReflectionTypeBuilder *tb)
9936 {
9937         MonoClass *klass;
9938         int count, i;
9939
9940         MONO_ARCH_SAVE_REGS;
9941
9942         klass = mono_class_from_mono_type (tb->type.type);
9943
9944         count = tb->generic_params ? mono_array_length (tb->generic_params) : 0;
9945
9946         if (klass->generic_container || (count == 0))
9947                 return;
9948
9949         g_assert (tb->generic_container && (tb->generic_container->owner.klass == klass));
9950
9951         klass->generic_container = mono_image_alloc0 (klass->image, sizeof (MonoGenericContainer));
9952
9953         klass->generic_container->owner.klass = klass;
9954         klass->generic_container->type_argc = count;
9955         klass->generic_container->type_params = mono_image_alloc0 (klass->image, sizeof (MonoGenericParamFull) * count);
9956
9957         klass->is_generic = 1;
9958
9959         for (i = 0; i < count; i++) {
9960                 MonoReflectionGenericParam *gparam = mono_array_get (tb->generic_params, gpointer, i);
9961                 MonoGenericParamFull *param = (MonoGenericParamFull *) mono_reflection_type_get_handle ((MonoReflectionType*)gparam)->data.generic_param;
9962                 klass->generic_container->type_params [i] = *param;
9963                 /*Make sure we are a diferent type instance */
9964                 klass->generic_container->type_params [i].param.owner = klass->generic_container;
9965                 klass->generic_container->type_params [i].info.pklass = NULL;
9966                 klass->generic_container->type_params [i].info.flags = gparam->attrs;
9967
9968                 g_assert (klass->generic_container->type_params [i].param.owner);
9969         }
9970
9971         klass->generic_container->context.class_inst = mono_get_shared_generic_inst (klass->generic_container);
9972 }
9973
9974 /*
9975  * mono_reflection_create_internal_class:
9976  * @tb: a TypeBuilder object
9977  *
9978  * Actually create the MonoClass that is associated with the TypeBuilder.
9979  */
9980 void
9981 mono_reflection_create_internal_class (MonoReflectionTypeBuilder *tb)
9982 {
9983         MonoClass *klass;
9984
9985         MONO_ARCH_SAVE_REGS;
9986
9987         klass = mono_class_from_mono_type (tb->type.type);
9988
9989         mono_loader_lock ();
9990         if (klass->enumtype && mono_class_enum_basetype (klass) == NULL) {
9991                 MonoReflectionFieldBuilder *fb;
9992                 MonoClass *ec;
9993                 MonoType *enum_basetype;
9994
9995                 g_assert (tb->fields != NULL);
9996                 g_assert (mono_array_length (tb->fields) >= 1);
9997
9998                 fb = mono_array_get (tb->fields, MonoReflectionFieldBuilder*, 0);
9999
10000                 if (!mono_type_is_valid_enum_basetype (mono_reflection_type_get_handle ((MonoReflectionType*)fb->type))) {
10001                         mono_loader_unlock ();
10002                         return;
10003                 }
10004
10005                 enum_basetype = mono_reflection_type_get_handle ((MonoReflectionType*)fb->type);
10006                 klass->element_class = mono_class_from_mono_type (enum_basetype);
10007                 if (!klass->element_class)
10008                         klass->element_class = mono_class_from_mono_type (enum_basetype);
10009
10010                 /*
10011                  * get the element_class from the current corlib.
10012                  */
10013                 ec = default_class_from_mono_type (enum_basetype);
10014                 klass->instance_size = ec->instance_size;
10015                 klass->size_inited = 1;
10016                 /* 
10017                  * this is almost safe to do with enums and it's needed to be able
10018                  * to create objects of the enum type (for use in SetConstant).
10019                  */
10020                 /* FIXME: Does this mean enums can't have method overrides ? */
10021                 mono_class_setup_vtable_general (klass, NULL, 0, NULL);
10022         }
10023         mono_loader_unlock ();
10024 }
10025
10026 static MonoMarshalSpec*
10027 mono_marshal_spec_from_builder (MonoImage *image, MonoAssembly *assembly,
10028                                                                 MonoReflectionMarshal *minfo)
10029 {
10030         MonoMarshalSpec *res;
10031
10032         res = image_g_new0 (image, MonoMarshalSpec, 1);
10033         res->native = minfo->type;
10034
10035         switch (minfo->type) {
10036         case MONO_NATIVE_LPARRAY:
10037                 res->data.array_data.elem_type = minfo->eltype;
10038                 if (minfo->has_size) {
10039                         res->data.array_data.param_num = minfo->param_num;
10040                         res->data.array_data.num_elem = minfo->count;
10041                         res->data.array_data.elem_mult = minfo->param_num == -1 ? 0 : 1;
10042                 }
10043                 else {
10044                         res->data.array_data.param_num = -1;
10045                         res->data.array_data.num_elem = -1;
10046                         res->data.array_data.elem_mult = -1;
10047                 }
10048                 break;
10049
10050         case MONO_NATIVE_BYVALTSTR:
10051         case MONO_NATIVE_BYVALARRAY:
10052                 res->data.array_data.num_elem = minfo->count;
10053                 break;
10054
10055         case MONO_NATIVE_CUSTOM:
10056                 if (minfo->marshaltyperef)
10057                         res->data.custom_data.custom_name =
10058                                 type_get_fully_qualified_name (mono_reflection_type_get_handle ((MonoReflectionType*)minfo->marshaltyperef));
10059                 if (minfo->mcookie)
10060                         res->data.custom_data.cookie = mono_string_to_utf8 (minfo->mcookie);
10061                 break;
10062
10063         default:
10064                 break;
10065         }
10066
10067         return res;
10068 }
10069 #endif /* !DISABLE_REFLECTION_EMIT */
10070
10071 MonoReflectionMarshalAsAttribute*
10072 mono_reflection_marshal_as_attribute_from_marshal_spec (MonoDomain *domain, MonoClass *klass,
10073                                                                                    MonoMarshalSpec *spec)
10074 {
10075         static MonoClass *System_Reflection_Emit_MarshalAsAttribute;
10076         MonoReflectionMarshalAsAttribute *minfo;
10077         MonoType *mtype;
10078
10079         if (!System_Reflection_Emit_MarshalAsAttribute) {
10080                 System_Reflection_Emit_MarshalAsAttribute = mono_class_from_name (
10081                    mono_defaults.corlib, "System.Runtime.InteropServices", "MarshalAsAttribute");
10082                 g_assert (System_Reflection_Emit_MarshalAsAttribute);
10083         }
10084
10085         minfo = (MonoReflectionMarshalAsAttribute*)mono_object_new (domain, System_Reflection_Emit_MarshalAsAttribute);
10086         minfo->utype = spec->native;
10087
10088         switch (minfo->utype) {
10089         case MONO_NATIVE_LPARRAY:
10090                 minfo->array_subtype = spec->data.array_data.elem_type;
10091                 minfo->size_const = spec->data.array_data.num_elem;
10092                 if (spec->data.array_data.param_num != -1)
10093                         minfo->size_param_index = spec->data.array_data.param_num;
10094                 break;
10095
10096         case MONO_NATIVE_BYVALTSTR:
10097         case MONO_NATIVE_BYVALARRAY:
10098                 minfo->size_const = spec->data.array_data.num_elem;
10099                 break;
10100
10101         case MONO_NATIVE_CUSTOM:
10102                 if (spec->data.custom_data.custom_name) {
10103                         mtype = mono_reflection_type_from_name (spec->data.custom_data.custom_name, klass->image);
10104                         if (mtype)
10105                                 MONO_OBJECT_SETREF (minfo, marshal_type_ref, mono_type_get_object (domain, mtype));
10106
10107                         MONO_OBJECT_SETREF (minfo, marshal_type, mono_string_new (domain, spec->data.custom_data.custom_name));
10108                 }
10109                 if (spec->data.custom_data.cookie)
10110                         MONO_OBJECT_SETREF (minfo, marshal_cookie, mono_string_new (domain, spec->data.custom_data.cookie));
10111                 break;
10112
10113         default:
10114                 break;
10115         }
10116
10117         return minfo;
10118 }
10119
10120 #ifndef DISABLE_REFLECTION_EMIT
10121 static MonoMethod*
10122 reflection_methodbuilder_to_mono_method (MonoClass *klass,
10123                                          ReflectionMethodBuilder *rmb,
10124                                          MonoMethodSignature *sig)
10125 {
10126         MonoError error;
10127         MonoMethod *m;
10128         MonoMethodWrapper *wrapperm;
10129         MonoMarshalSpec **specs;
10130         MonoReflectionMethodAux *method_aux;
10131         MonoImage *image;
10132         gboolean dynamic;
10133         int i;
10134
10135         mono_error_init (&error);
10136         /*
10137          * Methods created using a MethodBuilder should have their memory allocated
10138          * inside the image mempool, while dynamic methods should have their memory
10139          * malloc'd.
10140          */
10141         dynamic = rmb->refs != NULL;
10142         image = dynamic ? NULL : klass->image;
10143
10144         if (!dynamic)
10145                 g_assert (!klass->generic_class);
10146
10147         mono_loader_lock ();
10148
10149         if ((rmb->attrs & METHOD_ATTRIBUTE_PINVOKE_IMPL) ||
10150                         (rmb->iattrs & METHOD_IMPL_ATTRIBUTE_INTERNAL_CALL))
10151                 m = (MonoMethod *)image_g_new0 (image, MonoMethodPInvoke, 1);
10152         else
10153                 m = (MonoMethod *)image_g_new0 (image, MonoMethodWrapper, 1);
10154
10155         wrapperm = (MonoMethodWrapper*)m;
10156
10157         m->dynamic = dynamic;
10158         m->slot = -1;
10159         m->flags = rmb->attrs;
10160         m->iflags = rmb->iattrs;
10161         m->name = mono_string_to_utf8_image_ignore (image, rmb->name);
10162         m->klass = klass;
10163         m->signature = sig;
10164         m->sre_method = TRUE;
10165         m->skip_visibility = rmb->skip_visibility;
10166         if (rmb->table_idx)
10167                 m->token = MONO_TOKEN_METHOD_DEF | (*rmb->table_idx);
10168
10169         if (m->iflags & METHOD_IMPL_ATTRIBUTE_INTERNAL_CALL) {
10170                 if (klass == mono_defaults.string_class && !strcmp (m->name, ".ctor"))
10171                         m->string_ctor = 1;
10172
10173                 m->signature->pinvoke = 1;
10174         } else if (m->flags & METHOD_ATTRIBUTE_PINVOKE_IMPL) {
10175                 m->signature->pinvoke = 1;
10176
10177                 method_aux = image_g_new0 (image, MonoReflectionMethodAux, 1);
10178
10179                 method_aux->dllentry = rmb->dllentry ? mono_string_to_utf8_image (image, rmb->dllentry, &error) : image_strdup (image, m->name);
10180                 g_assert (mono_error_ok (&error));
10181                 method_aux->dll = mono_string_to_utf8_image (image, rmb->dll, &error);
10182                 g_assert (mono_error_ok (&error));
10183                 
10184                 ((MonoMethodPInvoke*)m)->piflags = (rmb->native_cc << 8) | (rmb->charset ? (rmb->charset - 1) * 2 : 0) | rmb->extra_flags;
10185
10186                 if (klass->image->dynamic)
10187                         g_hash_table_insert (((MonoDynamicImage*)klass->image)->method_aux_hash, m, method_aux);
10188
10189                 mono_loader_unlock ();
10190
10191                 return m;
10192         } else if (!(m->flags & METHOD_ATTRIBUTE_ABSTRACT) &&
10193                            !(m->iflags & METHOD_IMPL_ATTRIBUTE_RUNTIME)) {
10194                 MonoMethodHeader *header;
10195                 guint32 code_size;
10196                 gint32 max_stack, i;
10197                 gint32 num_locals = 0;
10198                 gint32 num_clauses = 0;
10199                 guint8 *code;
10200
10201                 if (rmb->ilgen) {
10202                         code = mono_array_addr (rmb->ilgen->code, guint8, 0);
10203                         code_size = rmb->ilgen->code_len;
10204                         max_stack = rmb->ilgen->max_stack;
10205                         num_locals = rmb->ilgen->locals ? mono_array_length (rmb->ilgen->locals) : 0;
10206                         if (rmb->ilgen->ex_handlers)
10207                                 num_clauses = method_count_clauses (rmb->ilgen);
10208                 } else {
10209                         if (rmb->code) {
10210                                 code = mono_array_addr (rmb->code, guint8, 0);
10211                                 code_size = mono_array_length (rmb->code);
10212                                 /* we probably need to run a verifier on the code... */
10213                                 max_stack = 8; 
10214                         }
10215                         else {
10216                                 code = NULL;
10217                                 code_size = 0;
10218                                 max_stack = 8;
10219                         }
10220                 }
10221
10222                 header = image_g_malloc0 (image, MONO_SIZEOF_METHOD_HEADER + num_locals * sizeof (MonoType*));
10223                 header->code_size = code_size;
10224                 header->code = image_g_malloc (image, code_size);
10225                 memcpy ((char*)header->code, code, code_size);
10226                 header->max_stack = max_stack;
10227                 header->init_locals = rmb->init_locals;
10228                 header->num_locals = num_locals;
10229
10230                 for (i = 0; i < num_locals; ++i) {
10231                         MonoReflectionLocalBuilder *lb = 
10232                                 mono_array_get (rmb->ilgen->locals, MonoReflectionLocalBuilder*, i);
10233
10234                         header->locals [i] = image_g_new0 (image, MonoType, 1);
10235                         memcpy (header->locals [i], mono_reflection_type_get_handle ((MonoReflectionType*)lb->type), MONO_SIZEOF_TYPE);
10236                 }
10237
10238                 header->num_clauses = num_clauses;
10239                 if (num_clauses) {
10240                         header->clauses = method_encode_clauses (image, (MonoDynamicImage*)klass->image,
10241                                  rmb->ilgen, num_clauses);
10242                 }
10243
10244                 wrapperm->header = header;
10245         }
10246
10247         if (rmb->generic_params) {
10248                 int count = mono_array_length (rmb->generic_params);
10249                 MonoGenericContainer *container = rmb->generic_container;
10250
10251                 g_assert (container);
10252
10253                 container->type_argc = count;
10254                 container->type_params = image_g_new0 (image, MonoGenericParamFull, count);
10255                 container->owner.method = m;
10256
10257                 m->is_generic = TRUE;
10258                 mono_method_set_generic_container (m, container);
10259
10260                 for (i = 0; i < count; i++) {
10261                         MonoReflectionGenericParam *gp =
10262                                 mono_array_get (rmb->generic_params, MonoReflectionGenericParam*, i);
10263                         MonoGenericParamFull *param = (MonoGenericParamFull *) mono_reflection_type_get_handle ((MonoReflectionType*)gp)->data.generic_param;
10264                         container->type_params [i] = *param;
10265                 }
10266
10267                 /*
10268                  * The method signature might have pointers to generic parameters that belong to other methods.
10269                  * This is a valid SRE case, but the resulting method signature must be encoded using the proper
10270                  * generic parameters.
10271                  */
10272                 for (i = 0; i < m->signature->param_count; ++i) {
10273                         MonoType *t = m->signature->params [i];
10274                         if (t->type == MONO_TYPE_MVAR) {
10275                                 MonoGenericParam *gparam =  t->data.generic_param;
10276                                 if (gparam->num < count) {
10277                                         m->signature->params [i] = mono_metadata_type_dup (image, m->signature->params [i]);
10278                                         m->signature->params [i]->data.generic_param = mono_generic_container_get_param (container, gparam->num);
10279                                 }
10280
10281                         }
10282                 }
10283
10284                 if (klass->generic_container) {
10285                         container->parent = klass->generic_container;
10286                         container->context.class_inst = klass->generic_container->context.class_inst;
10287                 }
10288                 container->context.method_inst = mono_get_shared_generic_inst (container);
10289         }
10290
10291         if (rmb->refs) {
10292                 MonoMethodWrapper *mw = (MonoMethodWrapper*)m;
10293                 int i;
10294                 void **data;
10295
10296                 m->wrapper_type = MONO_WRAPPER_DYNAMIC_METHOD;
10297
10298                 mw->method_data = data = image_g_new (image, gpointer, rmb->nrefs + 1);
10299                 data [0] = GUINT_TO_POINTER (rmb->nrefs);
10300                 for (i = 0; i < rmb->nrefs; ++i)
10301                         data [i + 1] = rmb->refs [i];
10302         }
10303
10304         method_aux = NULL;
10305
10306         /* Parameter info */
10307         if (rmb->pinfo) {
10308                 if (!method_aux)
10309                         method_aux = image_g_new0 (image, MonoReflectionMethodAux, 1);
10310                 method_aux->param_names = image_g_new0 (image, char *, mono_method_signature (m)->param_count + 1);
10311                 for (i = 0; i <= m->signature->param_count; ++i) {
10312                         MonoReflectionParamBuilder *pb;
10313                         if ((pb = mono_array_get (rmb->pinfo, MonoReflectionParamBuilder*, i))) {
10314                                 if ((i > 0) && (pb->attrs)) {
10315                                         /* Make a copy since it might point to a shared type structure */
10316                                         m->signature->params [i - 1] = mono_metadata_type_dup (klass->image, m->signature->params [i - 1]);
10317                                         m->signature->params [i - 1]->attrs = pb->attrs;
10318                                 }
10319
10320                                 if (pb->attrs & PARAM_ATTRIBUTE_HAS_DEFAULT) {
10321                                         MonoDynamicImage *assembly;
10322                                         guint32 idx, def_type, len;
10323                                         char *p;
10324                                         const char *p2;
10325
10326                                         if (!method_aux->param_defaults) {
10327                                                 method_aux->param_defaults = image_g_new0 (image, guint8*, m->signature->param_count + 1);
10328                                                 method_aux->param_default_types = image_g_new0 (image, guint32, m->signature->param_count + 1);
10329                                         }
10330                                         assembly = (MonoDynamicImage*)klass->image;
10331                                         idx = encode_constant (assembly, pb->def_value, &def_type);
10332                                         /* Copy the data from the blob since it might get realloc-ed */
10333                                         p = assembly->blob.data + idx;
10334                                         len = mono_metadata_decode_blob_size (p, &p2);
10335                                         len += p2 - p;
10336                                         method_aux->param_defaults [i] = image_g_malloc (image, len);
10337                                         method_aux->param_default_types [i] = def_type;
10338                                         memcpy ((gpointer)method_aux->param_defaults [i], p, len);
10339                                 }
10340
10341                                 if (pb->name) {
10342                                         method_aux->param_names [i] = mono_string_to_utf8_image (image, pb->name, &error);
10343                                         g_assert (mono_error_ok (&error));
10344                                 }
10345                                 if (pb->cattrs) {
10346                                         if (!method_aux->param_cattr)
10347                                                 method_aux->param_cattr = image_g_new0 (image, MonoCustomAttrInfo*, m->signature->param_count + 1);
10348                                         method_aux->param_cattr [i] = mono_custom_attrs_from_builders (image, klass->image, pb->cattrs);
10349                                 }
10350                         }
10351                 }
10352         }
10353
10354         /* Parameter marshalling */
10355         specs = NULL;
10356         if (rmb->pinfo)         
10357                 for (i = 0; i < mono_array_length (rmb->pinfo); ++i) {
10358                         MonoReflectionParamBuilder *pb;
10359                         if ((pb = mono_array_get (rmb->pinfo, MonoReflectionParamBuilder*, i))) {
10360                                 if (pb->marshal_info) {
10361                                         if (specs == NULL)
10362                                                 specs = image_g_new0 (image, MonoMarshalSpec*, sig->param_count + 1);
10363                                         specs [pb->position] = 
10364                                                 mono_marshal_spec_from_builder (image, klass->image->assembly, pb->marshal_info);
10365                                 }
10366                         }
10367                 }
10368         if (specs != NULL) {
10369                 if (!method_aux)
10370                         method_aux = image_g_new0 (image, MonoReflectionMethodAux, 1);
10371                 method_aux->param_marshall = specs;
10372         }
10373
10374         if (klass->image->dynamic && method_aux)
10375                 g_hash_table_insert (((MonoDynamicImage*)klass->image)->method_aux_hash, m, method_aux);
10376
10377         mono_loader_unlock ();
10378
10379         return m;
10380 }       
10381
10382 static MonoMethod*
10383 ctorbuilder_to_mono_method (MonoClass *klass, MonoReflectionCtorBuilder* mb)
10384 {
10385         ReflectionMethodBuilder rmb;
10386         MonoMethodSignature *sig;
10387
10388         mono_loader_lock ();
10389         sig = ctor_builder_to_signature (klass->image, mb);
10390         mono_loader_unlock ();
10391
10392         reflection_methodbuilder_from_ctor_builder (&rmb, mb);
10393
10394         mb->mhandle = reflection_methodbuilder_to_mono_method (klass, &rmb, sig);
10395         mono_save_custom_attrs (klass->image, mb->mhandle, mb->cattrs);
10396
10397         /* If we are in a generic class, we might be called multiple times from inflate_method */
10398         if (!((MonoDynamicImage*)(MonoDynamicImage*)klass->image)->save && !klass->generic_container) {
10399                 /* ilgen is no longer needed */
10400                 mb->ilgen = NULL;
10401         }
10402
10403         return mb->mhandle;
10404 }
10405
10406 static MonoMethod*
10407 methodbuilder_to_mono_method (MonoClass *klass, MonoReflectionMethodBuilder* mb)
10408 {
10409         ReflectionMethodBuilder rmb;
10410         MonoMethodSignature *sig;
10411
10412         mono_loader_lock ();
10413         sig = method_builder_to_signature (klass->image, mb);
10414         mono_loader_unlock ();
10415
10416         reflection_methodbuilder_from_method_builder (&rmb, mb);
10417
10418         mb->mhandle = reflection_methodbuilder_to_mono_method (klass, &rmb, sig);
10419         mono_save_custom_attrs (klass->image, mb->mhandle, mb->cattrs);
10420
10421         /* If we are in a generic class, we might be called multiple times from inflate_method */
10422         if (!((MonoDynamicImage*)(MonoDynamicImage*)klass->image)->save && !klass->generic_container) {
10423                 /* ilgen is no longer needed */
10424                 mb->ilgen = NULL;
10425         }
10426         return mb->mhandle;
10427 }
10428
10429 static MonoClassField*
10430 fieldbuilder_to_mono_class_field (MonoClass *klass, MonoReflectionFieldBuilder* fb)
10431 {
10432         MonoClassField *field;
10433         MonoType *custom;
10434         MonoError error;
10435
10436         field = g_new0 (MonoClassField, 1);
10437
10438         field->name = mono_string_to_utf8_image (klass->image, fb->name, &error);
10439         g_assert (mono_error_ok (&error));
10440         if (fb->attrs || fb->modreq || fb->modopt) {
10441                 field->type = mono_metadata_type_dup (NULL, mono_reflection_type_get_handle ((MonoReflectionType*)fb->type));
10442                 field->type->attrs = fb->attrs;
10443
10444                 g_assert (klass->image->dynamic);
10445                 custom = add_custom_modifiers ((MonoDynamicImage*)klass->image, field->type, fb->modreq, fb->modopt);
10446                 g_free (field->type);
10447                 field->type = mono_metadata_type_dup (klass->image, custom);
10448                 g_free (custom);
10449         } else {
10450                 field->type = mono_reflection_type_get_handle ((MonoReflectionType*)fb->type);
10451         }
10452         if (fb->offset != -1)
10453                 field->offset = fb->offset;
10454         field->parent = klass;
10455         mono_save_custom_attrs (klass->image, field, fb->cattrs);
10456
10457         // FIXME: Can't store fb->def_value/RVA, is it needed for field_on_insts ?
10458
10459         return field;
10460 }
10461 #endif
10462
10463 MonoType*
10464 mono_reflection_bind_generic_parameters (MonoReflectionType *type, int type_argc, MonoType **types)
10465 {
10466         MonoClass *klass;
10467         MonoReflectionTypeBuilder *tb = NULL;
10468         gboolean is_dynamic = FALSE;
10469         MonoDomain *domain;
10470         MonoClass *geninst;
10471
10472         mono_loader_lock ();
10473
10474         domain = mono_object_domain (type);
10475
10476         if (is_sre_type_builder (mono_object_class (type))) {
10477                 tb = (MonoReflectionTypeBuilder *) type;
10478
10479                 is_dynamic = TRUE;
10480         } else if (is_sre_generic_instance (mono_object_class (type))) {
10481                 MonoReflectionGenericClass *rgi = (MonoReflectionGenericClass *) type;
10482                 MonoReflectionType *gtd = rgi->generic_type;
10483
10484                 if (is_sre_type_builder (mono_object_class (gtd))) {
10485                         tb = (MonoReflectionTypeBuilder *)gtd;
10486                         is_dynamic = TRUE;
10487                 }
10488         }
10489
10490         /* FIXME: fix the CreateGenericParameters protocol to avoid the two stage setup of TypeBuilders */
10491         if (tb && tb->generic_container)
10492                 mono_reflection_create_generic_class (tb);
10493
10494         klass = mono_class_from_mono_type (mono_reflection_type_get_handle (type));
10495         if (!klass->generic_container) {
10496                 mono_loader_unlock ();
10497                 return NULL;
10498         }
10499
10500         if (klass->wastypebuilder) {
10501                 tb = (MonoReflectionTypeBuilder *) mono_class_get_ref_info (klass);
10502
10503                 is_dynamic = TRUE;
10504         }
10505
10506         mono_loader_unlock ();
10507
10508         geninst = mono_class_bind_generic_parameters (klass, type_argc, types, is_dynamic);
10509
10510         return &geninst->byval_arg;
10511 }
10512
10513 MonoClass*
10514 mono_class_bind_generic_parameters (MonoClass *klass, int type_argc, MonoType **types, gboolean is_dynamic)
10515 {
10516         MonoGenericClass *gclass;
10517         MonoGenericInst *inst;
10518
10519         g_assert (klass->generic_container);
10520
10521         inst = mono_metadata_get_generic_inst (type_argc, types);
10522         gclass = mono_metadata_lookup_generic_class (klass, inst, is_dynamic);
10523
10524         return mono_generic_class_get_class (gclass);
10525 }
10526
10527 MonoReflectionMethod*
10528 mono_reflection_bind_generic_method_parameters (MonoReflectionMethod *rmethod, MonoArray *types)
10529 {
10530         MonoClass *klass;
10531         MonoMethod *method, *inflated;
10532         MonoMethodInflated *imethod;
10533         MonoGenericContext tmp_context;
10534         MonoGenericInst *ginst;
10535         MonoType **type_argv;
10536         int count, i;
10537
10538         MONO_ARCH_SAVE_REGS;
10539
10540         /*FIXME but this no longer should happen*/
10541         if (!strcmp (rmethod->object.vtable->klass->name, "MethodBuilder")) {
10542 #ifndef DISABLE_REFLECTION_EMIT
10543                 MonoReflectionMethodBuilder *mb = NULL;
10544                 MonoReflectionTypeBuilder *tb;
10545                 MonoClass *klass;
10546
10547                 mb = (MonoReflectionMethodBuilder *) rmethod;
10548                 tb = (MonoReflectionTypeBuilder *) mb->type;
10549                 klass = mono_class_from_mono_type (mono_reflection_type_get_handle ((MonoReflectionType*)tb));
10550
10551                 method = methodbuilder_to_mono_method (klass, mb);
10552 #else
10553                 g_assert_not_reached ();
10554                 method = NULL;
10555 #endif
10556         } else {
10557                 method = rmethod->method;
10558         }
10559
10560         klass = method->klass;
10561
10562         if (method->is_inflated)
10563                 method = ((MonoMethodInflated *) method)->declaring;
10564
10565         count = mono_method_signature (method)->generic_param_count;
10566         if (count != mono_array_length (types))
10567                 return NULL;
10568
10569         type_argv = g_new0 (MonoType *, count);
10570         for (i = 0; i < count; i++) {
10571                 MonoReflectionType *garg = mono_array_get (types, gpointer, i);
10572                 type_argv [i] = mono_reflection_type_get_handle (garg);
10573         }
10574         ginst = mono_metadata_get_generic_inst (count, type_argv);
10575         g_free (type_argv);
10576
10577         tmp_context.class_inst = klass->generic_class ? klass->generic_class->context.class_inst : NULL;
10578         tmp_context.method_inst = ginst;
10579
10580         inflated = mono_class_inflate_generic_method (method, &tmp_context);
10581         imethod = (MonoMethodInflated *) inflated;
10582
10583         /*FIXME but I think this is no longer necessary*/
10584         if (method->klass->image->dynamic) {
10585                 MonoDynamicImage *image = (MonoDynamicImage*)method->klass->image;
10586                 /*
10587                  * This table maps metadata structures representing inflated methods/fields
10588                  * to the reflection objects representing their generic definitions.
10589                  */
10590                 mono_image_lock ((MonoImage*)image);
10591                 mono_g_hash_table_insert (image->generic_def_objects, imethod, rmethod);
10592                 mono_image_unlock ((MonoImage*)image);
10593         }
10594
10595         if (!mono_verifier_is_method_valid_generic_instantiation (inflated))
10596                 mono_raise_exception (mono_get_exception_argument ("typeArguments", "Invalid generic arguments"));
10597         
10598         return mono_method_get_object (mono_object_domain (rmethod), inflated, NULL);
10599 }
10600
10601 #ifndef DISABLE_REFLECTION_EMIT
10602
10603 static MonoMethod *
10604 inflate_mono_method (MonoClass *klass, MonoMethod *method, MonoObject *obj)
10605 {
10606         MonoMethodInflated *imethod;
10607         MonoGenericContext *context;
10608         int i;
10609
10610         /*
10611          * With generic code sharing the klass might not be inflated.
10612          * This can happen because classes inflated with their own
10613          * type arguments are "normalized" to the uninflated class.
10614          */
10615         if (!klass->generic_class)
10616                 return method;
10617
10618         context = mono_class_get_context (klass);
10619
10620         if (klass->method.count && klass->methods) {
10621                 /* Find the already created inflated method */
10622                 for (i = 0; i < klass->method.count; ++i) {
10623                         g_assert (klass->methods [i]->is_inflated);
10624                         if (((MonoMethodInflated*)klass->methods [i])->declaring == method)
10625                                 break;
10626                 }
10627                 g_assert (i < klass->method.count);
10628                 imethod = (MonoMethodInflated*)klass->methods [i];
10629         } else {
10630                 imethod = (MonoMethodInflated *) mono_class_inflate_generic_method_full (method, klass, context);
10631         }
10632
10633         if (method->is_generic && method->klass->image->dynamic) {
10634                 MonoDynamicImage *image = (MonoDynamicImage*)method->klass->image;
10635
10636                 mono_image_lock ((MonoImage*)image);
10637                 mono_g_hash_table_insert (image->generic_def_objects, imethod, obj);
10638                 mono_image_unlock ((MonoImage*)image);
10639         }
10640         return (MonoMethod *) imethod;
10641 }
10642
10643 static MonoMethod *
10644 inflate_method (MonoReflectionType *type, MonoObject *obj)
10645 {
10646         MonoMethod *method;
10647         MonoClass *gklass;
10648
10649         MonoClass *type_class = mono_object_class (type);
10650
10651         if (is_sre_generic_instance (type_class)) {
10652                 MonoReflectionGenericClass *mgc = (MonoReflectionGenericClass*)type;
10653                 gklass = mono_class_from_mono_type (mono_reflection_type_get_handle ((MonoReflectionType*)mgc->generic_type));
10654         } else if (is_sre_type_builder (type_class)) {
10655                 gklass = mono_class_from_mono_type (mono_reflection_type_get_handle (type));
10656         } else if (type->type) {
10657                 gklass = mono_class_from_mono_type (type->type);
10658                 gklass = mono_class_get_generic_type_definition (gklass);
10659         } else {
10660                 g_error ("Can't handle type %s", mono_type_get_full_name (mono_object_class (type)));
10661         }
10662
10663         if (!strcmp (obj->vtable->klass->name, "MethodBuilder"))
10664                 if (((MonoReflectionMethodBuilder*)obj)->mhandle)
10665                         method = ((MonoReflectionMethodBuilder*)obj)->mhandle;
10666                 else
10667                         method = methodbuilder_to_mono_method (gklass, (MonoReflectionMethodBuilder *) obj);
10668         else if (!strcmp (obj->vtable->klass->name, "ConstructorBuilder"))
10669                 method = ctorbuilder_to_mono_method (gklass, (MonoReflectionCtorBuilder *) obj);
10670         else if (!strcmp (obj->vtable->klass->name, "MonoMethod") || !strcmp (obj->vtable->klass->name, "MonoCMethod"))
10671                 method = ((MonoReflectionMethod *) obj)->method;
10672         else {
10673                 method = NULL; /* prevent compiler warning */
10674                 g_error ("can't handle type %s", obj->vtable->klass->name);
10675         }
10676
10677         return inflate_mono_method (mono_class_from_mono_type (mono_reflection_type_get_handle ((MonoReflectionType*)type)), method, obj);
10678 }
10679
10680 /*TODO avoid saving custom attrs for generic classes as it's enough to have them on the generic type definition.*/
10681 void
10682 mono_reflection_generic_class_initialize (MonoReflectionGenericClass *type, MonoArray *fields)
10683 {
10684         MonoGenericClass *gclass;
10685         MonoDynamicGenericClass *dgclass;
10686         MonoClass *klass, *gklass;
10687         MonoType *gtype;
10688         int i;
10689
10690         MONO_ARCH_SAVE_REGS;
10691
10692         gtype = mono_reflection_type_get_handle ((MonoReflectionType*)type);
10693         klass = mono_class_from_mono_type (gtype);
10694         g_assert (gtype->type == MONO_TYPE_GENERICINST);
10695         gclass = gtype->data.generic_class;
10696
10697         if (!gclass->is_dynamic)
10698                 return;
10699
10700         dgclass = (MonoDynamicGenericClass *) gclass;
10701
10702         if (dgclass->initialized)
10703                 return;
10704
10705         gklass = gclass->container_class;
10706         mono_class_init (gklass);
10707
10708         dgclass->count_fields = fields ? mono_array_length (fields) : 0;
10709
10710         dgclass->fields = mono_image_set_new0 (gclass->owner, MonoClassField, dgclass->count_fields);
10711         dgclass->field_objects = mono_image_set_new0 (gclass->owner, MonoObject*, dgclass->count_fields);
10712         dgclass->field_generic_types = mono_image_set_new0 (gclass->owner, MonoType*, dgclass->count_fields);
10713
10714         for (i = 0; i < dgclass->count_fields; i++) {
10715                 MonoObject *obj = mono_array_get (fields, gpointer, i);
10716                 MonoClassField *field, *inflated_field = NULL;
10717
10718                 if (!strcmp (obj->vtable->klass->name, "FieldBuilder"))
10719                         inflated_field = field = fieldbuilder_to_mono_class_field (klass, (MonoReflectionFieldBuilder *) obj);
10720                 else if (!strcmp (obj->vtable->klass->name, "MonoField"))
10721                         field = ((MonoReflectionField *) obj)->field;
10722                 else {
10723                         field = NULL; /* prevent compiler warning */
10724                         g_assert_not_reached ();
10725                 }
10726
10727                 dgclass->fields [i] = *field;
10728                 dgclass->fields [i].parent = klass;
10729                 dgclass->fields [i].type = mono_class_inflate_generic_type (
10730                         field->type, mono_generic_class_get_context ((MonoGenericClass *) dgclass));
10731                 dgclass->field_generic_types [i] = field->type;
10732                 MONO_GC_REGISTER_ROOT_IF_MOVING (dgclass->field_objects [i]);
10733                 dgclass->field_objects [i] = obj;
10734
10735                 if (inflated_field) {
10736                         g_free (inflated_field);
10737                 } else {
10738                         dgclass->fields [i].name = mono_image_set_strdup (gclass->owner, dgclass->fields [i].name);
10739                 }
10740         }
10741
10742         dgclass->initialized = TRUE;
10743 }
10744
10745 void
10746 mono_reflection_free_dynamic_generic_class (MonoGenericClass *gclass)
10747 {
10748         MonoDynamicGenericClass *dgclass;
10749         int i;
10750
10751         g_assert (gclass->is_dynamic);
10752
10753         dgclass = (MonoDynamicGenericClass *)gclass;
10754
10755         for (i = 0; i < dgclass->count_fields; ++i) {
10756                 MonoClassField *field = dgclass->fields + i;
10757                 mono_metadata_free_type (field->type);
10758                 MONO_GC_UNREGISTER_ROOT_IF_MOVING (dgclass->field_objects [i]);
10759         }
10760 }
10761
10762 static void
10763 fix_partial_generic_class (MonoClass *klass)
10764 {
10765         MonoClass *gklass = klass->generic_class->container_class;
10766         MonoDynamicGenericClass *dgclass;
10767         int i;
10768
10769         if (klass->wastypebuilder)
10770                 return;
10771
10772         dgclass = (MonoDynamicGenericClass *)  klass->generic_class;
10773         if (klass->parent != gklass->parent) {
10774                 MonoError error;
10775                 MonoType *parent_type = mono_class_inflate_generic_type_checked (&gklass->parent->byval_arg, &klass->generic_class->context, &error);
10776                 if (mono_error_ok (&error)) {
10777                         MonoClass *parent = mono_class_from_mono_type (parent_type);
10778                         mono_metadata_free_type (parent_type);
10779                         if (parent != klass->parent) {
10780                                 /*fool mono_class_setup_parent*/
10781                                 klass->supertypes = NULL;
10782                                 mono_class_setup_parent (klass, parent);
10783                         }
10784                 } else {
10785                         mono_class_set_failure (klass, MONO_EXCEPTION_TYPE_LOAD, NULL);
10786                         mono_error_cleanup (&error);
10787                         if (gklass->wastypebuilder)
10788                                 klass->wastypebuilder = TRUE;
10789                         return;
10790                 }
10791         }
10792
10793         if (!dgclass->initialized)
10794                 return;
10795
10796         if (klass->method.count != gklass->method.count) {
10797                 klass->method.count = gklass->method.count;
10798                 klass->methods = mono_image_alloc (klass->image, sizeof (MonoMethod*) * (klass->method.count + 1));
10799
10800                 for (i = 0; i < klass->method.count; i++) {
10801                         klass->methods [i] = mono_class_inflate_generic_method_full (
10802                                 gklass->methods [i], klass, mono_class_get_context (klass));
10803                 }
10804         }
10805
10806         if (klass->interface_count && klass->interface_count != gklass->interface_count) {
10807                 klass->interface_count = gklass->interface_count;
10808                 klass->interfaces = mono_image_alloc (klass->image, sizeof (MonoClass*) * gklass->interface_count);
10809                 klass->interfaces_packed = NULL; /*make setup_interface_offsets happy*/
10810
10811                 for (i = 0; i < gklass->interface_count; ++i) {
10812                         MonoType *iface_type = mono_class_inflate_generic_type (&gklass->interfaces [i]->byval_arg, mono_class_get_context (klass));
10813                         klass->interfaces [i] = mono_class_from_mono_type (iface_type);
10814                         mono_metadata_free_type (iface_type);
10815
10816                         ensure_runtime_vtable (klass->interfaces [i]);
10817                 }
10818                 klass->interfaces_inited = 1;
10819         }
10820
10821         if (klass->field.count != gklass->field.count) {
10822                 klass->field.count = gklass->field.count;
10823                 klass->fields = image_g_new0 (klass->image, MonoClassField, klass->field.count);
10824
10825                 for (i = 0; i < klass->field.count; i++) {
10826                         klass->fields [i] = gklass->fields [i];
10827                         klass->fields [i].parent = klass;
10828                         klass->fields [i].type = mono_class_inflate_generic_type (gklass->fields [i].type, mono_class_get_context (klass));
10829                 }
10830         }
10831
10832         /*We can only finish with this klass once it's parent has as well*/
10833         if (gklass->wastypebuilder)
10834                 klass->wastypebuilder = TRUE;
10835         return;
10836 }
10837
10838 static void
10839 ensure_generic_class_runtime_vtable (MonoClass *klass)
10840 {
10841         MonoClass *gklass = klass->generic_class->container_class;
10842
10843         ensure_runtime_vtable (gklass); 
10844
10845         fix_partial_generic_class (klass);
10846 }
10847
10848 static void
10849 ensure_runtime_vtable (MonoClass *klass)
10850 {
10851         MonoReflectionTypeBuilder *tb = mono_class_get_ref_info (klass);
10852         int i, num, j;
10853
10854         if (!klass->image->dynamic || (!tb && !klass->generic_class) || klass->wastypebuilder)
10855                 return;
10856         if (klass->parent)
10857                 ensure_runtime_vtable (klass->parent);
10858
10859         if (tb) {
10860                 num = tb->ctors? mono_array_length (tb->ctors): 0;
10861                 num += tb->num_methods;
10862                 klass->method.count = num;
10863                 klass->methods = mono_image_alloc (klass->image, sizeof (MonoMethod*) * num);
10864                 num = tb->ctors? mono_array_length (tb->ctors): 0;
10865                 for (i = 0; i < num; ++i)
10866                         klass->methods [i] = ctorbuilder_to_mono_method (klass, mono_array_get (tb->ctors, MonoReflectionCtorBuilder*, i));
10867                 num = tb->num_methods;
10868                 j = i;
10869                 for (i = 0; i < num; ++i)
10870                         klass->methods [j++] = methodbuilder_to_mono_method (klass, mono_array_get (tb->methods, MonoReflectionMethodBuilder*, i));
10871         
10872                 if (tb->interfaces) {
10873                         klass->interface_count = mono_array_length (tb->interfaces);
10874                         klass->interfaces = mono_image_alloc (klass->image, sizeof (MonoClass*) * klass->interface_count);
10875                         for (i = 0; i < klass->interface_count; ++i) {
10876                                 MonoType *iface = mono_type_array_get_and_resolve (tb->interfaces, i);
10877                                 klass->interfaces [i] = mono_class_from_mono_type (iface);
10878                                 ensure_runtime_vtable (klass->interfaces [i]);
10879                         }
10880                         klass->interfaces_inited = 1;
10881                 }
10882         } else if (klass->generic_class){
10883                 ensure_generic_class_runtime_vtable (klass);
10884         }
10885
10886         if (klass->flags & TYPE_ATTRIBUTE_INTERFACE) {
10887                 int slot_num = 0;
10888                 for (i = 0; i < klass->method.count; ++i) {
10889                         MonoMethod *im = klass->methods [i];
10890                         if (!(im->flags & METHOD_ATTRIBUTE_STATIC))
10891                                 im->slot = slot_num++;
10892                 }
10893                 
10894                 klass->interfaces_packed = NULL; /*make setup_interface_offsets happy*/
10895                 mono_class_setup_interface_offsets (klass);
10896                 mono_class_setup_interface_id (klass);
10897         }
10898
10899         /*
10900          * The generic vtable is needed even if image->run is not set since some
10901          * runtime code like ves_icall_Type_GetMethodsByName depends on 
10902          * method->slot being defined.
10903          */
10904
10905         /* 
10906          * tb->methods could not be freed since it is used for determining 
10907          * overrides during dynamic vtable construction.
10908          */
10909 }
10910
10911 static MonoMethod*
10912 mono_reflection_method_get_handle (MonoObject *method)
10913 {
10914         MonoClass *class = mono_object_class (method);
10915         if (is_sr_mono_method (class) || is_sr_mono_generic_method (class)) {
10916                 MonoReflectionMethod *sr_method = (MonoReflectionMethod*)method;
10917                 return sr_method->method;
10918         }
10919         if (is_sre_method_builder (class)) {
10920                 MonoReflectionMethodBuilder *mb = (MonoReflectionMethodBuilder*)method;
10921                 return mb->mhandle;
10922         }
10923         if (is_sre_method_on_tb_inst (class)) {
10924                 MonoReflectionMethodOnTypeBuilderInst *m = (MonoReflectionMethodOnTypeBuilderInst*)method;
10925                 MonoMethod *result;
10926                 /*FIXME move this to a proper method and unify with resolve_object*/
10927                 if (m->method_args) {
10928                         result = mono_reflection_method_on_tb_inst_get_handle (m);
10929                 } else {
10930                         MonoType *type = mono_reflection_type_get_handle ((MonoReflectionType*)m->inst);
10931                         MonoClass *inflated_klass = mono_class_from_mono_type (type);
10932                         MonoMethod *mono_method;
10933
10934                         if (is_sre_method_builder (mono_object_class (m->mb)))
10935                                 mono_method = ((MonoReflectionMethodBuilder *)m->mb)->mhandle;
10936                         else if (is_sr_mono_method (mono_object_class (m->mb)))
10937                                 mono_method = ((MonoReflectionMethod *)m->mb)->method;
10938                         else
10939                                 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)));
10940
10941                         result = inflate_mono_method (inflated_klass, mono_method, (MonoObject*)m->mb);
10942                 }
10943                 return result;
10944         }
10945
10946         g_error ("Can't handle methods of type %s:%s", class->name_space, class->name);
10947         return NULL;
10948 }
10949
10950 void
10951 mono_reflection_get_dynamic_overrides (MonoClass *klass, MonoMethod ***overrides, int *num_overrides)
10952 {
10953         MonoReflectionTypeBuilder *tb;
10954         int i, j, onum;
10955         MonoReflectionMethod *m;
10956
10957         *overrides = NULL;
10958         *num_overrides = 0;
10959
10960         g_assert (klass->image->dynamic);
10961
10962         if (!mono_class_get_ref_info (klass))
10963                 return;
10964
10965         g_assert (strcmp (((MonoObject*)mono_class_get_ref_info (klass))->vtable->klass->name, "TypeBuilder") == 0);
10966
10967         tb = (MonoReflectionTypeBuilder*)mono_class_get_ref_info (klass);
10968
10969         onum = 0;
10970         if (tb->methods) {
10971                 for (i = 0; i < tb->num_methods; ++i) {
10972                         MonoReflectionMethodBuilder *mb = 
10973                                 mono_array_get (tb->methods, MonoReflectionMethodBuilder*, i);
10974                         if (mb->override_methods)
10975                                 onum += mono_array_length (mb->override_methods);
10976                 }
10977         }
10978
10979         if (onum) {
10980                 *overrides = g_new0 (MonoMethod*, onum * 2);
10981
10982                 onum = 0;
10983                 for (i = 0; i < tb->num_methods; ++i) {
10984                         MonoReflectionMethodBuilder *mb = 
10985                                 mono_array_get (tb->methods, MonoReflectionMethodBuilder*, i);
10986                         if (mb->override_methods) {
10987                                 for (j = 0; j < mono_array_length (mb->override_methods); ++j) {
10988                                         m = mono_array_get (mb->override_methods, MonoReflectionMethod*, j);
10989
10990                                         (*overrides) [onum * 2] = mono_reflection_method_get_handle ((MonoObject*)m);
10991                                         (*overrides) [onum * 2 + 1] = mb->mhandle;
10992
10993                                         g_assert (mb->mhandle);
10994
10995                                         onum ++;
10996                                 }
10997                         }
10998                 }
10999         }
11000
11001         *num_overrides = onum;
11002 }
11003
11004 static void
11005 typebuilder_setup_fields (MonoClass *klass, MonoError *error)
11006 {
11007         MonoReflectionTypeBuilder *tb = mono_class_get_ref_info (klass);
11008         MonoReflectionFieldBuilder *fb;
11009         MonoClassField *field;
11010         MonoImage *image = klass->image;
11011         const char *p, *p2;
11012         int i;
11013         guint32 len, idx, real_size = 0;
11014
11015         klass->field.count = tb->num_fields;
11016         klass->field.first = 0;
11017
11018         mono_error_init (error);
11019
11020         if (tb->class_size) {
11021                 if ((tb->packing_size & 0xfffffff0) != 0) {
11022                         char *err_msg = g_strdup_printf ("Could not load struct '%s' with packing size %d >= 16", klass->name, tb->packing_size);
11023                         mono_class_set_failure (klass, MONO_EXCEPTION_TYPE_LOAD, err_msg);
11024                         return;
11025                 }
11026                 klass->packing_size = tb->packing_size;
11027                 real_size = klass->instance_size + tb->class_size;
11028         }
11029
11030         if (!klass->field.count) {
11031                 klass->instance_size = MAX (klass->instance_size, real_size);
11032                 return;
11033         }
11034         
11035         klass->fields = image_g_new0 (image, MonoClassField, klass->field.count);
11036         mono_class_alloc_ext (klass);
11037         klass->ext->field_def_values = image_g_new0 (image, MonoFieldDefaultValue, klass->field.count);
11038         /*
11039         This is, guess what, a hack.
11040         The issue is that the runtime doesn't know how to setup the fields of a typebuider and crash.
11041         On the static path no field class is resolved, only types are built. This is the right thing to do
11042         but we suck.
11043         Setting size_inited is harmless because we're doing the same job as mono_class_setup_fields anyway.
11044         */
11045         klass->size_inited = 1;
11046
11047         for (i = 0; i < klass->field.count; ++i) {
11048                 MonoArray *rva_data;
11049                 fb = mono_array_get (tb->fields, gpointer, i);
11050                 field = &klass->fields [i];
11051                 field->name = mono_string_to_utf8_image (image, fb->name, error);
11052                 if (!mono_error_ok (error))
11053                         return;
11054                 if (fb->attrs) {
11055                         field->type = mono_metadata_type_dup (klass->image, mono_reflection_type_get_handle ((MonoReflectionType*)fb->type));
11056                         field->type->attrs = fb->attrs;
11057                 } else {
11058                         field->type = mono_reflection_type_get_handle ((MonoReflectionType*)fb->type);
11059                 }
11060
11061                 if ((fb->attrs & FIELD_ATTRIBUTE_HAS_FIELD_RVA) && (rva_data = fb->rva_data)) {
11062                         char *base = mono_array_addr (rva_data, char, 0);
11063                         size_t size = mono_array_length (rva_data);
11064                         char *data = mono_image_alloc (klass->image, size);
11065                         memcpy (data, base, size);
11066                         klass->ext->field_def_values [i].data = data;
11067                 }
11068                 if (fb->offset != -1)
11069                         field->offset = fb->offset;
11070                 field->parent = klass;
11071                 fb->handle = field;
11072                 mono_save_custom_attrs (klass->image, field, fb->cattrs);
11073
11074                 if (klass->enumtype && !(field->type->attrs & FIELD_ATTRIBUTE_STATIC)) {
11075                         klass->cast_class = klass->element_class = mono_class_from_mono_type (field->type);
11076                 }
11077                 if (fb->def_value) {
11078                         MonoDynamicImage *assembly = (MonoDynamicImage*)klass->image;
11079                         field->type->attrs |= FIELD_ATTRIBUTE_HAS_DEFAULT;
11080                         idx = encode_constant (assembly, fb->def_value, &klass->ext->field_def_values [i].def_type);
11081                         /* Copy the data from the blob since it might get realloc-ed */
11082                         p = assembly->blob.data + idx;
11083                         len = mono_metadata_decode_blob_size (p, &p2);
11084                         len += p2 - p;
11085                         klass->ext->field_def_values [i].data = mono_image_alloc (image, len);
11086                         memcpy ((gpointer)klass->ext->field_def_values [i].data, p, len);
11087                 }
11088         }
11089
11090         klass->instance_size = MAX (klass->instance_size, real_size);
11091         mono_class_layout_fields (klass);
11092 }
11093
11094 static void
11095 typebuilder_setup_properties (MonoClass *klass, MonoError *error)
11096 {
11097         MonoReflectionTypeBuilder *tb = mono_class_get_ref_info (klass);
11098         MonoReflectionPropertyBuilder *pb;
11099         MonoImage *image = klass->image;
11100         MonoProperty *properties;
11101         int i;
11102
11103         mono_error_init (error);
11104
11105         if (!klass->ext)
11106                 klass->ext = image_g_new0 (image, MonoClassExt, 1);
11107
11108         klass->ext->property.count = tb->properties ? mono_array_length (tb->properties) : 0;
11109         klass->ext->property.first = 0;
11110
11111         properties = image_g_new0 (image, MonoProperty, klass->ext->property.count);
11112         klass->ext->properties = properties;
11113         for (i = 0; i < klass->ext->property.count; ++i) {
11114                 pb = mono_array_get (tb->properties, MonoReflectionPropertyBuilder*, i);
11115                 properties [i].parent = klass;
11116                 properties [i].attrs = pb->attrs;
11117                 properties [i].name = mono_string_to_utf8_image (image, pb->name, error);
11118                 if (!mono_error_ok (error))
11119                         return;
11120                 if (pb->get_method)
11121                         properties [i].get = pb->get_method->mhandle;
11122                 if (pb->set_method)
11123                         properties [i].set = pb->set_method->mhandle;
11124
11125                 mono_save_custom_attrs (klass->image, &properties [i], pb->cattrs);
11126                 if (pb->def_value) {
11127                         guint32 len, idx;
11128                         const char *p, *p2;
11129                         MonoDynamicImage *assembly = (MonoDynamicImage*)klass->image;
11130                         if (!klass->ext->prop_def_values)
11131                                 klass->ext->prop_def_values = image_g_new0 (image, MonoFieldDefaultValue, klass->ext->property.count);
11132                         properties [i].attrs |= PROPERTY_ATTRIBUTE_HAS_DEFAULT;
11133                         idx = encode_constant (assembly, pb->def_value, &klass->ext->prop_def_values [i].def_type);
11134                         /* Copy the data from the blob since it might get realloc-ed */
11135                         p = assembly->blob.data + idx;
11136                         len = mono_metadata_decode_blob_size (p, &p2);
11137                         len += p2 - p;
11138                         klass->ext->prop_def_values [i].data = mono_image_alloc (image, len);
11139                         memcpy ((gpointer)klass->ext->prop_def_values [i].data, p, len);
11140                 }
11141         }
11142 }
11143
11144 MonoReflectionEvent *
11145 mono_reflection_event_builder_get_event_info (MonoReflectionTypeBuilder *tb, MonoReflectionEventBuilder *eb)
11146 {
11147         MonoEvent *event = g_new0 (MonoEvent, 1);
11148         MonoClass *klass;
11149
11150         klass = mono_class_from_mono_type (mono_reflection_type_get_handle ((MonoReflectionType*)tb));
11151
11152         event->parent = klass;
11153         event->attrs = eb->attrs;
11154         event->name = mono_string_to_utf8 (eb->name);
11155         if (eb->add_method)
11156                 event->add = eb->add_method->mhandle;
11157         if (eb->remove_method)
11158                 event->remove = eb->remove_method->mhandle;
11159         if (eb->raise_method)
11160                 event->raise = eb->raise_method->mhandle;
11161
11162 #ifndef MONO_SMALL_CONFIG
11163         if (eb->other_methods) {
11164                 int j;
11165                 event->other = g_new0 (MonoMethod*, mono_array_length (eb->other_methods) + 1);
11166                 for (j = 0; j < mono_array_length (eb->other_methods); ++j) {
11167                         MonoReflectionMethodBuilder *mb = 
11168                                 mono_array_get (eb->other_methods,
11169                                                 MonoReflectionMethodBuilder*, j);
11170                         event->other [j] = mb->mhandle;
11171                 }
11172         }
11173 #endif
11174
11175         return mono_event_get_object (mono_object_domain (tb), klass, event);
11176 }
11177
11178 static void
11179 typebuilder_setup_events (MonoClass *klass, MonoError *error)
11180 {
11181         MonoReflectionTypeBuilder *tb = mono_class_get_ref_info (klass);
11182         MonoReflectionEventBuilder *eb;
11183         MonoImage *image = klass->image;
11184         MonoEvent *events;
11185         int i;
11186
11187         mono_error_init (error);
11188
11189         if (!klass->ext)
11190                 klass->ext = image_g_new0 (image, MonoClassExt, 1);
11191
11192         klass->ext->event.count = tb->events ? mono_array_length (tb->events) : 0;
11193         klass->ext->event.first = 0;
11194
11195         events = image_g_new0 (image, MonoEvent, klass->ext->event.count);
11196         klass->ext->events = events;
11197         for (i = 0; i < klass->ext->event.count; ++i) {
11198                 eb = mono_array_get (tb->events, MonoReflectionEventBuilder*, i);
11199                 events [i].parent = klass;
11200                 events [i].attrs = eb->attrs;
11201                 events [i].name = mono_string_to_utf8_image (image, eb->name, error);
11202                 if (!mono_error_ok (error))
11203                         return;
11204                 if (eb->add_method)
11205                         events [i].add = eb->add_method->mhandle;
11206                 if (eb->remove_method)
11207                         events [i].remove = eb->remove_method->mhandle;
11208                 if (eb->raise_method)
11209                         events [i].raise = eb->raise_method->mhandle;
11210
11211 #ifndef MONO_SMALL_CONFIG
11212                 if (eb->other_methods) {
11213                         int j;
11214                         events [i].other = image_g_new0 (image, MonoMethod*, mono_array_length (eb->other_methods) + 1);
11215                         for (j = 0; j < mono_array_length (eb->other_methods); ++j) {
11216                                 MonoReflectionMethodBuilder *mb = 
11217                                         mono_array_get (eb->other_methods,
11218                                                                         MonoReflectionMethodBuilder*, j);
11219                                 events [i].other [j] = mb->mhandle;
11220                         }
11221                 }
11222 #endif
11223                 mono_save_custom_attrs (klass->image, &events [i], eb->cattrs);
11224         }
11225 }
11226
11227 static gboolean
11228 remove_instantiations_of_and_ensure_contents (gpointer key,
11229                                                   gpointer value,
11230                                                   gpointer user_data)
11231 {
11232         MonoType *type = (MonoType*)key;
11233         MonoClass *klass = (MonoClass*)user_data;
11234
11235         if ((type->type == MONO_TYPE_GENERICINST) && (type->data.generic_class->container_class == klass)) {
11236                 fix_partial_generic_class (mono_class_from_mono_type (type)); //Ensure it's safe to use it.
11237                 return TRUE;
11238         } else
11239                 return FALSE;
11240 }
11241
11242 static void
11243 check_array_for_usertypes (MonoArray *arr)
11244 {
11245         int i;
11246
11247         if (!arr)
11248                 return;
11249
11250         for (i = 0; i < mono_array_length (arr); ++i)
11251                 RESOLVE_ARRAY_TYPE_ELEMENT (arr, i);
11252 }
11253
11254 MonoReflectionType*
11255 mono_reflection_create_runtime_class (MonoReflectionTypeBuilder *tb)
11256 {
11257         MonoError error;
11258         MonoClass *klass;
11259         MonoDomain* domain;
11260         MonoReflectionType* res;
11261         int i, j;
11262
11263         MONO_ARCH_SAVE_REGS;
11264
11265         domain = mono_object_domain (tb);
11266         klass = mono_class_from_mono_type (tb->type.type);
11267
11268         /*
11269          * Check for user defined Type subclasses.
11270          */
11271         RESOLVE_TYPE (tb->parent);
11272         check_array_for_usertypes (tb->interfaces);
11273         if (tb->fields) {
11274                 for (i = 0; i < mono_array_length (tb->fields); ++i) {
11275                         MonoReflectionFieldBuilder *fb = mono_array_get (tb->fields, gpointer, i);
11276                         if (fb) {
11277                                 RESOLVE_TYPE (fb->type);
11278                                 check_array_for_usertypes (fb->modreq);
11279                                 check_array_for_usertypes (fb->modopt);
11280                                 if (fb->marshal_info && fb->marshal_info->marshaltyperef)
11281                                         RESOLVE_TYPE (fb->marshal_info->marshaltyperef);
11282                         }
11283                 }
11284         }
11285         if (tb->methods) {
11286                 for (i = 0; i < mono_array_length (tb->methods); ++i) {
11287                         MonoReflectionMethodBuilder *mb = mono_array_get (tb->methods, gpointer, i);
11288                         if (mb) {
11289                                 RESOLVE_TYPE (mb->rtype);
11290                                 check_array_for_usertypes (mb->return_modreq);
11291                                 check_array_for_usertypes (mb->return_modopt);
11292                                 check_array_for_usertypes (mb->parameters);
11293                                 if (mb->param_modreq)
11294                                         for (j = 0; j < mono_array_length (mb->param_modreq); ++j)
11295                                                 check_array_for_usertypes (mono_array_get (mb->param_modreq, MonoArray*, j));
11296                                 if (mb->param_modopt)
11297                                         for (j = 0; j < mono_array_length (mb->param_modopt); ++j)
11298                                                 check_array_for_usertypes (mono_array_get (mb->param_modopt, MonoArray*, j));
11299                         }
11300                 }
11301         }
11302         if (tb->ctors) {
11303                 for (i = 0; i < mono_array_length (tb->ctors); ++i) {
11304                         MonoReflectionCtorBuilder *mb = mono_array_get (tb->ctors, gpointer, i);
11305                         if (mb) {
11306                                 check_array_for_usertypes (mb->parameters);
11307                                 if (mb->param_modreq)
11308                                         for (j = 0; j < mono_array_length (mb->param_modreq); ++j)
11309                                                 check_array_for_usertypes (mono_array_get (mb->param_modreq, MonoArray*, j));
11310                                 if (mb->param_modopt)
11311                                         for (j = 0; j < mono_array_length (mb->param_modopt); ++j)
11312                                                 check_array_for_usertypes (mono_array_get (mb->param_modopt, MonoArray*, j));
11313                         }
11314                 }
11315         }
11316
11317         mono_save_custom_attrs (klass->image, klass, tb->cattrs);
11318
11319         /* 
11320          * we need to lock the domain because the lock will be taken inside
11321          * So, we need to keep the locking order correct.
11322          */
11323         mono_loader_lock ();
11324         mono_domain_lock (domain);
11325         if (klass->wastypebuilder) {
11326                 mono_domain_unlock (domain);
11327                 mono_loader_unlock ();
11328                 return mono_type_get_object (mono_object_domain (tb), &klass->byval_arg);
11329         }
11330         /*
11331          * Fields to set in klass:
11332          * the various flags: delegate/unicode/contextbound etc.
11333          */
11334         klass->flags = tb->attrs;
11335         klass->has_cctor = 1;
11336         klass->has_finalize = 1;
11337         klass->has_finalize_inited = 1;
11338
11339         /* fool mono_class_setup_parent */
11340         klass->supertypes = NULL;
11341         mono_class_setup_parent (klass, klass->parent);
11342         mono_class_setup_mono_type (klass);
11343
11344 #if 0
11345         if (!((MonoDynamicImage*)klass->image)->run) {
11346                 if (klass->generic_container) {
11347                         /* FIXME: The code below can't handle generic classes */
11348                         klass->wastypebuilder = TRUE;
11349                         mono_loader_unlock ();
11350                         mono_domain_unlock (domain);
11351                         return mono_type_get_object (mono_object_domain (tb), &klass->byval_arg);
11352                 }
11353         }
11354 #endif
11355
11356         /* enums are done right away */
11357         if (!klass->enumtype)
11358                 ensure_runtime_vtable (klass);
11359
11360         if (tb->subtypes) {
11361                 for (i = 0; i < mono_array_length (tb->subtypes); ++i) {
11362                         MonoReflectionTypeBuilder *subtb = mono_array_get (tb->subtypes, MonoReflectionTypeBuilder*, i);
11363                         mono_class_alloc_ext (klass);
11364                         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)));
11365                 }
11366         }
11367
11368         klass->nested_classes_inited = TRUE;
11369
11370         /* fields and object layout */
11371         if (klass->parent) {
11372                 if (!klass->parent->size_inited)
11373                         mono_class_init (klass->parent);
11374                 klass->instance_size = klass->parent->instance_size;
11375                 klass->sizes.class_size = 0;
11376                 klass->min_align = klass->parent->min_align;
11377                 /* if the type has no fields we won't call the field_setup
11378                  * routine which sets up klass->has_references.
11379                  */
11380                 klass->has_references |= klass->parent->has_references;
11381         } else {
11382                 klass->instance_size = sizeof (MonoObject);
11383                 klass->min_align = 1;
11384         }
11385
11386         /* FIXME: handle packing_size and instance_size */
11387         typebuilder_setup_fields (klass, &error);
11388         if (!mono_error_ok (&error))
11389                 goto failure;
11390         typebuilder_setup_properties (klass, &error);
11391         if (!mono_error_ok (&error))
11392                 goto failure;
11393
11394         typebuilder_setup_events (klass, &error);
11395         if (!mono_error_ok (&error))
11396                 goto failure;
11397
11398         klass->wastypebuilder = TRUE;
11399
11400         /* 
11401          * If we are a generic TypeBuilder, there might be instantiations in the type cache
11402          * which have type System.Reflection.MonoGenericClass, but after the type is created, 
11403          * we want to return normal System.MonoType objects, so clear these out from the cache.
11404          *
11405          * Together with this we must ensure the contents of all instances to match the created type.
11406          */
11407         if (domain->type_hash && klass->generic_container)
11408                 mono_g_hash_table_foreach_remove (domain->type_hash, remove_instantiations_of_and_ensure_contents, klass);
11409
11410         mono_domain_unlock (domain);
11411         mono_loader_unlock ();
11412
11413         if (klass->enumtype && !mono_class_is_valid_enum (klass)) {
11414                 mono_class_set_failure (klass, MONO_EXCEPTION_TYPE_LOAD, NULL);
11415                 mono_raise_exception (mono_get_exception_type_load (tb->name, NULL));
11416         }
11417
11418         res = mono_type_get_object (mono_object_domain (tb), &klass->byval_arg);
11419         g_assert (res != (MonoReflectionType*)tb);
11420
11421         return res;
11422
11423 failure:
11424         mono_class_set_failure (klass, MONO_EXCEPTION_TYPE_LOAD, NULL);
11425         klass->wastypebuilder = TRUE;
11426         mono_domain_unlock (domain);
11427         mono_loader_unlock ();
11428         mono_error_raise_exception (&error);
11429         return NULL;
11430 }
11431
11432 void
11433 mono_reflection_initialize_generic_parameter (MonoReflectionGenericParam *gparam)
11434 {
11435         MonoGenericParamFull *param;
11436         MonoImage *image;
11437         MonoClass *pklass;
11438         MonoError error;
11439
11440         MONO_ARCH_SAVE_REGS;
11441
11442         image = &gparam->tbuilder->module->dynamic_image->image;
11443
11444         param = mono_image_new0 (image, MonoGenericParamFull, 1);
11445
11446         param->info.name = mono_string_to_utf8_image (image, gparam->name, &error);
11447         g_assert (mono_error_ok (&error));
11448         param->param.num = gparam->index;
11449
11450         if (gparam->mbuilder) {
11451                 if (!gparam->mbuilder->generic_container) {
11452                         MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder *)gparam->mbuilder->type;
11453                         MonoClass *klass = mono_class_from_mono_type (mono_reflection_type_get_handle ((MonoReflectionType*)tb));
11454                         gparam->mbuilder->generic_container = mono_image_alloc0 (klass->image, sizeof (MonoGenericContainer));
11455                         gparam->mbuilder->generic_container->is_method = TRUE;
11456                         /* 
11457                          * Cannot set owner.method, since the MonoMethod is not created yet.
11458                          * Set the image field instead, so type_in_image () works.
11459                          */
11460                         gparam->mbuilder->generic_container->image = klass->image;
11461                 }
11462                 param->param.owner = gparam->mbuilder->generic_container;
11463         } else if (gparam->tbuilder) {
11464                 if (!gparam->tbuilder->generic_container) {
11465                         MonoClass *klass = mono_class_from_mono_type (mono_reflection_type_get_handle ((MonoReflectionType*)gparam->tbuilder));
11466                         gparam->tbuilder->generic_container = mono_image_alloc0 (klass->image, sizeof (MonoGenericContainer));
11467                         gparam->tbuilder->generic_container->owner.klass = klass;
11468                 }
11469                 param->param.owner = gparam->tbuilder->generic_container;
11470         }
11471
11472         pklass = mono_class_from_generic_parameter ((MonoGenericParam *) param, image, gparam->mbuilder != NULL);
11473
11474         gparam->type.type = &pklass->byval_arg;
11475
11476         mono_class_set_ref_info (pklass, gparam);
11477         mono_image_append_class_to_reflection_info_set (pklass);
11478 }
11479
11480 MonoArray *
11481 mono_reflection_sighelper_get_signature_local (MonoReflectionSigHelper *sig)
11482 {
11483         MonoReflectionModuleBuilder *module = sig->module;
11484         MonoDynamicImage *assembly = module != NULL ? module->dynamic_image : NULL;
11485         guint32 na = sig->arguments ? mono_array_length (sig->arguments) : 0;
11486         guint32 buflen, i;
11487         MonoArray *result;
11488         SigBuffer buf;
11489
11490         check_array_for_usertypes (sig->arguments);
11491
11492         sigbuffer_init (&buf, 32);
11493
11494         sigbuffer_add_value (&buf, 0x07);
11495         sigbuffer_add_value (&buf, na);
11496         if (assembly != NULL){
11497                 for (i = 0; i < na; ++i) {
11498                         MonoReflectionType *type = mono_array_get (sig->arguments, MonoReflectionType*, i);
11499                         encode_reflection_type (assembly, type, &buf);
11500                 }
11501         }
11502
11503         buflen = buf.p - buf.buf;
11504         result = mono_array_new (mono_domain_get (), mono_defaults.byte_class, buflen);
11505         memcpy (mono_array_addr (result, char, 0), buf.buf, buflen);
11506         sigbuffer_free (&buf);
11507
11508         return result;
11509 }
11510
11511 MonoArray *
11512 mono_reflection_sighelper_get_signature_field (MonoReflectionSigHelper *sig)
11513 {
11514         MonoDynamicImage *assembly = sig->module->dynamic_image;
11515         guint32 na = sig->arguments ? mono_array_length (sig->arguments) : 0;
11516         guint32 buflen, i;
11517         MonoArray *result;
11518         SigBuffer buf;
11519
11520         check_array_for_usertypes (sig->arguments);
11521
11522         sigbuffer_init (&buf, 32);
11523
11524         sigbuffer_add_value (&buf, 0x06);
11525         for (i = 0; i < na; ++i) {
11526                 MonoReflectionType *type = mono_array_get (sig->arguments, MonoReflectionType*, i);
11527                 encode_reflection_type (assembly, type, &buf);
11528         }
11529
11530         buflen = buf.p - buf.buf;
11531         result = mono_array_new (mono_domain_get (), mono_defaults.byte_class, buflen);
11532         memcpy (mono_array_addr (result, char, 0), buf.buf, buflen);
11533         sigbuffer_free (&buf);
11534
11535         return result;
11536 }
11537
11538 typedef struct {
11539         MonoMethod *handle;
11540         MonoDomain *domain;
11541 } DynamicMethodReleaseData;
11542
11543 /*
11544  * The runtime automatically clean up those after finalization.
11545 */      
11546 static MonoReferenceQueue *dynamic_method_queue;
11547
11548 static void
11549 free_dynamic_method (void *dynamic_method)
11550 {
11551         DynamicMethodReleaseData *data = dynamic_method;
11552
11553         mono_runtime_free_method (data->domain, data->handle);
11554         g_free (data);
11555 }
11556
11557 void 
11558 mono_reflection_create_dynamic_method (MonoReflectionDynamicMethod *mb)
11559 {
11560         MonoReferenceQueue *queue;
11561         MonoMethod *handle;
11562         DynamicMethodReleaseData *release_data;
11563         ReflectionMethodBuilder rmb;
11564         MonoMethodSignature *sig;
11565         MonoClass *klass;
11566         GSList *l;
11567         int i;
11568
11569         if (mono_runtime_is_shutting_down ())
11570                 mono_raise_exception (mono_get_exception_invalid_operation (""));
11571
11572         if (!(queue = dynamic_method_queue)) {
11573                 mono_loader_lock ();
11574                 if (!(queue = dynamic_method_queue))
11575                         queue = dynamic_method_queue = mono_gc_reference_queue_new (free_dynamic_method);
11576                 mono_loader_unlock ();
11577         }
11578
11579         sig = dynamic_method_to_signature (mb);
11580
11581         reflection_methodbuilder_from_dynamic_method (&rmb, mb);
11582
11583         /*
11584          * Resolve references.
11585          */
11586         /* 
11587          * Every second entry in the refs array is reserved for storing handle_class,
11588          * which is needed by the ldtoken implementation in the JIT.
11589          */
11590         rmb.nrefs = mb->nrefs;
11591         rmb.refs = g_new0 (gpointer, mb->nrefs + 1);
11592         for (i = 0; i < mb->nrefs; i += 2) {
11593                 MonoClass *handle_class;
11594                 gpointer ref;
11595                 MonoObject *obj = mono_array_get (mb->refs, MonoObject*, i);
11596
11597                 if (strcmp (obj->vtable->klass->name, "DynamicMethod") == 0) {
11598                         MonoReflectionDynamicMethod *method = (MonoReflectionDynamicMethod*)obj;
11599                         /*
11600                          * The referenced DynamicMethod should already be created by the managed
11601                          * code, except in the case of circular references. In that case, we store
11602                          * method in the refs array, and fix it up later when the referenced 
11603                          * DynamicMethod is created.
11604                          */
11605                         if (method->mhandle) {
11606                                 ref = method->mhandle;
11607                         } else {
11608                                 /* FIXME: GC object stored in unmanaged memory */
11609                                 ref = method;
11610
11611                                 /* FIXME: GC object stored in unmanaged memory */
11612                                 method->referenced_by = g_slist_append (method->referenced_by, mb);
11613                         }
11614                         handle_class = mono_defaults.methodhandle_class;
11615                 } else {
11616                         MonoException *ex = NULL;
11617                         ref = resolve_object (mb->module->image, obj, &handle_class, NULL);
11618                         if (!ref)
11619                                 ex = mono_get_exception_type_load (NULL, NULL);
11620                         else if (mono_security_core_clr_enabled ())
11621                                 ex = mono_security_core_clr_ensure_dynamic_method_resolved_object (ref, handle_class);
11622
11623                         if (ex) {
11624                                 g_free (rmb.refs);
11625                                 mono_raise_exception (ex);
11626                                 return;
11627                         }
11628                 }
11629
11630                 rmb.refs [i] = ref; /* FIXME: GC object stored in unmanaged memory (change also resolve_object() signature) */
11631                 rmb.refs [i + 1] = handle_class;
11632         }               
11633
11634         klass = mb->owner ? mono_class_from_mono_type (mono_reflection_type_get_handle ((MonoReflectionType*)mb->owner)) : mono_defaults.object_class;
11635
11636         mb->mhandle = handle = reflection_methodbuilder_to_mono_method (klass, &rmb, sig);
11637         release_data = g_new (DynamicMethodReleaseData, 1);
11638         release_data->handle = handle;
11639         release_data->domain = mono_object_get_domain ((MonoObject*)mb);
11640         if (!mono_gc_reference_queue_add (queue, (MonoObject*)mb, release_data))
11641                 g_free (release_data);
11642
11643         /* Fix up refs entries pointing at us */
11644         for (l = mb->referenced_by; l; l = l->next) {
11645                 MonoReflectionDynamicMethod *method = (MonoReflectionDynamicMethod*)l->data;
11646                 MonoMethodWrapper *wrapper = (MonoMethodWrapper*)method->mhandle;
11647                 gpointer *data;
11648                 
11649                 g_assert (method->mhandle);
11650
11651                 data = (gpointer*)wrapper->method_data;
11652                 for (i = 0; i < GPOINTER_TO_UINT (data [0]); i += 2) {
11653                         if ((data [i + 1] == mb) && (data [i + 1 + 1] == mono_defaults.methodhandle_class))
11654                                 data [i + 1] = mb->mhandle;
11655                 }
11656         }
11657         g_slist_free (mb->referenced_by);
11658
11659         g_free (rmb.refs);
11660
11661         /* ilgen is no longer needed */
11662         mb->ilgen = NULL;
11663 }
11664
11665 #endif /* DISABLE_REFLECTION_EMIT */
11666
11667 /**
11668  * 
11669  * mono_reflection_is_valid_dynamic_token:
11670  * 
11671  * Returns TRUE if token is valid.
11672  * 
11673  */
11674 gboolean
11675 mono_reflection_is_valid_dynamic_token (MonoDynamicImage *image, guint32 token)
11676 {
11677         return mono_g_hash_table_lookup (image->tokens, GUINT_TO_POINTER (token)) != NULL;
11678 }
11679
11680 MonoMethodSignature *
11681 mono_reflection_lookup_signature (MonoImage *image, MonoMethod *method, guint32 token)
11682 {
11683         MonoMethodSignature *sig;
11684         g_assert (image->dynamic);
11685
11686         sig = g_hash_table_lookup (((MonoDynamicImage*)image)->vararg_aux_hash, GUINT_TO_POINTER (token));
11687         if (sig)
11688                 return sig;
11689
11690         return mono_method_signature (method);
11691 }
11692
11693 #ifndef DISABLE_REFLECTION_EMIT
11694
11695 /**
11696  * mono_reflection_lookup_dynamic_token:
11697  *
11698  * Finish the Builder object pointed to by TOKEN and return the corresponding
11699  * runtime structure. If HANDLE_CLASS is not NULL, it is set to the class required by 
11700  * mono_ldtoken. If valid_token is TRUE, assert if it is not found in the token->object
11701  * mapping table.
11702  *
11703  * LOCKING: Take the loader lock
11704  */
11705 gpointer
11706 mono_reflection_lookup_dynamic_token (MonoImage *image, guint32 token, gboolean valid_token, MonoClass **handle_class, MonoGenericContext *context)
11707 {
11708         MonoDynamicImage *assembly = (MonoDynamicImage*)image;
11709         MonoObject *obj;
11710         MonoClass *klass;
11711
11712         mono_loader_lock ();
11713         obj = mono_g_hash_table_lookup (assembly->tokens, GUINT_TO_POINTER (token));
11714         mono_loader_unlock ();
11715         if (!obj) {
11716                 if (valid_token)
11717                         g_error ("Could not find required dynamic token 0x%08x", token);
11718                 else
11719                         return NULL;
11720         }
11721
11722         if (!handle_class)
11723                 handle_class = &klass;
11724         return resolve_object (image, obj, handle_class, context);
11725 }
11726
11727 /*
11728  * ensure_complete_type:
11729  *
11730  *   Ensure that KLASS is completed if it is a dynamic type, or references
11731  * dynamic types.
11732  */
11733 static void
11734 ensure_complete_type (MonoClass *klass)
11735 {
11736         if (klass->image->dynamic && !klass->wastypebuilder && mono_class_get_ref_info (klass)) {
11737                 MonoReflectionTypeBuilder *tb = mono_class_get_ref_info (klass);
11738
11739                 mono_domain_try_type_resolve (mono_domain_get (), NULL, (MonoObject*)tb);
11740
11741                 // Asserting here could break a lot of code
11742                 //g_assert (klass->wastypebuilder);
11743         }
11744
11745         if (klass->generic_class) {
11746                 MonoGenericInst *inst = klass->generic_class->context.class_inst;
11747                 int i;
11748
11749                 for (i = 0; i < inst->type_argc; ++i) {
11750                         ensure_complete_type (mono_class_from_mono_type (inst->type_argv [i]));
11751                 }
11752         }
11753 }
11754
11755 static gpointer
11756 resolve_object (MonoImage *image, MonoObject *obj, MonoClass **handle_class, MonoGenericContext *context)
11757 {
11758         gpointer result = NULL;
11759
11760         if (strcmp (obj->vtable->klass->name, "String") == 0) {
11761                 result = mono_string_intern ((MonoString*)obj);
11762                 *handle_class = mono_defaults.string_class;
11763                 g_assert (result);
11764         } else if (strcmp (obj->vtable->klass->name, "MonoType") == 0) {
11765                 MonoType *type = mono_reflection_type_get_handle ((MonoReflectionType*)obj);
11766                 MonoClass *mc = mono_class_from_mono_type (type);
11767                 if (!mono_class_init (mc))
11768                         mono_raise_exception (mono_class_get_exception_for_failure (mc));
11769
11770                 if (context) {
11771                         MonoType *inflated = mono_class_inflate_generic_type (type, context);
11772                         result = mono_class_from_mono_type (inflated);
11773                         mono_metadata_free_type (inflated);
11774                 } else {
11775                         result = mono_class_from_mono_type (type);
11776                 }
11777                 *handle_class = mono_defaults.typehandle_class;
11778                 g_assert (result);
11779         } else if (strcmp (obj->vtable->klass->name, "MonoMethod") == 0 ||
11780                    strcmp (obj->vtable->klass->name, "MonoCMethod") == 0 ||
11781                    strcmp (obj->vtable->klass->name, "MonoGenericCMethod") == 0 ||
11782                    strcmp (obj->vtable->klass->name, "MonoGenericMethod") == 0) {
11783                 result = ((MonoReflectionMethod*)obj)->method;
11784                 if (context)
11785                         result = mono_class_inflate_generic_method (result, context);
11786                 *handle_class = mono_defaults.methodhandle_class;
11787                 g_assert (result);
11788         } else if (strcmp (obj->vtable->klass->name, "MethodBuilder") == 0) {
11789                 MonoReflectionMethodBuilder *mb = (MonoReflectionMethodBuilder*)obj;
11790                 result = mb->mhandle;
11791                 if (!result) {
11792                         /* Type is not yet created */
11793                         MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder*)mb->type;
11794
11795                         mono_domain_try_type_resolve (mono_domain_get (), NULL, (MonoObject*)tb);
11796
11797                         /*
11798                          * Hopefully this has been filled in by calling CreateType() on the
11799                          * TypeBuilder.
11800                          */
11801                         /*
11802                          * TODO: This won't work if the application finishes another 
11803                          * TypeBuilder instance instead of this one.
11804                          */
11805                         result = mb->mhandle;
11806                 }
11807                 if (context)
11808                         result = mono_class_inflate_generic_method (result, context);
11809                 *handle_class = mono_defaults.methodhandle_class;
11810         } else if (strcmp (obj->vtable->klass->name, "ConstructorBuilder") == 0) {
11811                 MonoReflectionCtorBuilder *cb = (MonoReflectionCtorBuilder*)obj;
11812
11813                 result = cb->mhandle;
11814                 if (!result) {
11815                         MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder*)cb->type;
11816
11817                         mono_domain_try_type_resolve (mono_domain_get (), NULL, (MonoObject*)tb);
11818                         result = cb->mhandle;
11819                 }
11820                 if (context)
11821                         result = mono_class_inflate_generic_method (result, context);
11822                 *handle_class = mono_defaults.methodhandle_class;
11823         } else if (strcmp (obj->vtable->klass->name, "MonoField") == 0) {
11824                 MonoClassField *field = ((MonoReflectionField*)obj)->field;
11825
11826                 ensure_complete_type (field->parent);
11827                 if (context) {
11828                         MonoType *inflated = mono_class_inflate_generic_type (&field->parent->byval_arg, context);
11829                         MonoClass *class = mono_class_from_mono_type (inflated);
11830                         MonoClassField *inflated_field;
11831                         gpointer iter = NULL;
11832                         mono_metadata_free_type (inflated);
11833                         while ((inflated_field = mono_class_get_fields (class, &iter))) {
11834                                 if (!strcmp (field->name, inflated_field->name))
11835                                         break;
11836                         }
11837                         g_assert (inflated_field && !strcmp (field->name, inflated_field->name));
11838                         result = inflated_field;
11839                 } else {
11840                         result = field;
11841                 }
11842                 *handle_class = mono_defaults.fieldhandle_class;
11843                 g_assert (result);
11844         } else if (strcmp (obj->vtable->klass->name, "FieldBuilder") == 0) {
11845                 MonoReflectionFieldBuilder *fb = (MonoReflectionFieldBuilder*)obj;
11846                 result = fb->handle;
11847
11848                 if (!result) {
11849                         MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder*)fb->typeb;
11850
11851                         mono_domain_try_type_resolve (mono_domain_get (), NULL, (MonoObject*)tb);
11852                         result = fb->handle;
11853                 }
11854
11855                 if (fb->handle && fb->handle->parent->generic_container) {
11856                         MonoClass *klass = fb->handle->parent;
11857                         MonoType *type = mono_class_inflate_generic_type (&klass->byval_arg, context);
11858                         MonoClass *inflated = mono_class_from_mono_type (type);
11859
11860                         result = mono_class_get_field_from_name (inflated, mono_field_get_name (fb->handle));
11861                         g_assert (result);
11862                         mono_metadata_free_type (type);
11863                 }
11864                 *handle_class = mono_defaults.fieldhandle_class;
11865         } else if (strcmp (obj->vtable->klass->name, "TypeBuilder") == 0) {
11866                 MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder*)obj;
11867                 MonoType *type = mono_reflection_type_get_handle ((MonoReflectionType*)tb); 
11868                 MonoClass *klass;
11869
11870                 klass = type->data.klass;
11871                 if (klass->wastypebuilder) {
11872                         /* Already created */
11873                         result = klass;
11874                 }
11875                 else {
11876                         mono_domain_try_type_resolve (mono_domain_get (), NULL, (MonoObject*)tb);
11877                         result = type->data.klass;
11878                         g_assert (result);
11879                 }
11880                 *handle_class = mono_defaults.typehandle_class;
11881         } else if (strcmp (obj->vtable->klass->name, "SignatureHelper") == 0) {
11882                 MonoReflectionSigHelper *helper = (MonoReflectionSigHelper*)obj;
11883                 MonoMethodSignature *sig;
11884                 int nargs, i;
11885
11886                 if (helper->arguments)
11887                         nargs = mono_array_length (helper->arguments);
11888                 else
11889                         nargs = 0;
11890
11891                 sig = mono_metadata_signature_alloc (image, nargs);
11892                 sig->explicit_this = helper->call_conv & 64 ? 1 : 0;
11893                 sig->hasthis = helper->call_conv & 32 ? 1 : 0;
11894
11895                 if (helper->unmanaged_call_conv) { /* unmanaged */
11896                         sig->call_convention = helper->unmanaged_call_conv - 1;
11897                         sig->pinvoke = TRUE;
11898                 } else if (helper->call_conv & 0x02) {
11899                         sig->call_convention = MONO_CALL_VARARG;
11900                 } else {
11901                         sig->call_convention = MONO_CALL_DEFAULT;
11902                 }
11903
11904                 sig->param_count = nargs;
11905                 /* TODO: Copy type ? */
11906                 sig->ret = helper->return_type->type;
11907                 for (i = 0; i < nargs; ++i)
11908                         sig->params [i] = mono_type_array_get_and_resolve (helper->arguments, i);
11909
11910                 result = sig;
11911                 *handle_class = NULL;
11912         } else if (strcmp (obj->vtable->klass->name, "DynamicMethod") == 0) {
11913                 MonoReflectionDynamicMethod *method = (MonoReflectionDynamicMethod*)obj;
11914                 /* Already created by the managed code */
11915                 g_assert (method->mhandle);
11916                 result = method->mhandle;
11917                 *handle_class = mono_defaults.methodhandle_class;
11918         } else if (strcmp (obj->vtable->klass->name, "GenericTypeParameterBuilder") == 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, "MonoGenericClass") == 0) {
11926                 MonoType *type = mono_reflection_type_get_handle ((MonoReflectionType*)obj);
11927                 type = mono_class_inflate_generic_type (type, context);
11928                 result = mono_class_from_mono_type (type);
11929                 *handle_class = mono_defaults.typehandle_class;
11930                 g_assert (result);
11931                 mono_metadata_free_type (type);
11932         } else if (strcmp (obj->vtable->klass->name, "FieldOnTypeBuilderInst") == 0) {
11933                 MonoReflectionFieldOnTypeBuilderInst *f = (MonoReflectionFieldOnTypeBuilderInst*)obj;
11934                 MonoClass *inflated;
11935                 MonoType *type;
11936                 MonoClassField *field;
11937
11938                 if (is_sre_field_builder (mono_object_class (f->fb)))
11939                         field = ((MonoReflectionFieldBuilder*)f->fb)->handle;
11940                 else if (is_sr_mono_field (mono_object_class (f->fb)))
11941                         field = ((MonoReflectionField*)f->fb)->field;
11942                 else
11943                         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)));
11944
11945                 type = mono_class_inflate_generic_type (mono_reflection_type_get_handle ((MonoReflectionType*)f->inst), context);
11946                 inflated = mono_class_from_mono_type (type);
11947
11948                 result = field = mono_class_get_field_from_name (inflated, mono_field_get_name (field));
11949                 ensure_complete_type (field->parent);
11950                 g_assert (result);
11951                 mono_metadata_free_type (type);
11952                 *handle_class = mono_defaults.fieldhandle_class;
11953         } else if (strcmp (obj->vtable->klass->name, "ConstructorOnTypeBuilderInst") == 0) {
11954                 MonoReflectionCtorOnTypeBuilderInst *c = (MonoReflectionCtorOnTypeBuilderInst*)obj;
11955                 MonoType *type = mono_class_inflate_generic_type (mono_reflection_type_get_handle ((MonoReflectionType*)c->inst), context);
11956                 MonoClass *inflated_klass = mono_class_from_mono_type (type);
11957                 MonoMethod *method;
11958
11959                 if (is_sre_ctor_builder (mono_object_class (c->cb)))
11960                         method = ((MonoReflectionCtorBuilder *)c->cb)->mhandle;
11961                 else if (is_sr_mono_cmethod (mono_object_class (c->cb)))
11962                         method = ((MonoReflectionMethod *)c->cb)->method;
11963                 else
11964                         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)));
11965
11966                 result = inflate_mono_method (inflated_klass, method, (MonoObject*)c->cb);
11967                 *handle_class = mono_defaults.methodhandle_class;
11968                 mono_metadata_free_type (type);
11969         } else if (strcmp (obj->vtable->klass->name, "MethodOnTypeBuilderInst") == 0) {
11970                 MonoReflectionMethodOnTypeBuilderInst *m = (MonoReflectionMethodOnTypeBuilderInst*)obj;
11971                 if (m->method_args) {
11972                         result = mono_reflection_method_on_tb_inst_get_handle (m);
11973                         if (context)
11974                                 result = mono_class_inflate_generic_method (result, context);
11975                 } else {
11976                         MonoType *type = mono_class_inflate_generic_type (mono_reflection_type_get_handle ((MonoReflectionType*)m->inst), context);
11977                         MonoClass *inflated_klass = mono_class_from_mono_type (type);
11978                         MonoMethod *method;
11979
11980                         if (is_sre_method_builder (mono_object_class (m->mb)))
11981                                 method = ((MonoReflectionMethodBuilder *)m->mb)->mhandle;
11982                         else if (is_sr_mono_method (mono_object_class (m->mb)))
11983                                 method = ((MonoReflectionMethod *)m->mb)->method;
11984                         else
11985                                 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)));
11986
11987                         result = inflate_mono_method (inflated_klass, method, (MonoObject*)m->mb);
11988                         mono_metadata_free_type (type);
11989                 }
11990                 *handle_class = mono_defaults.methodhandle_class;
11991         } else if (strcmp (obj->vtable->klass->name, "MonoArrayMethod") == 0) {
11992                 MonoReflectionArrayMethod *m = (MonoReflectionArrayMethod*)obj;
11993                 MonoType *mtype;
11994                 MonoClass *klass;
11995                 MonoMethod *method;
11996                 gpointer iter;
11997                 char *name;
11998
11999                 mtype = mono_reflection_type_get_handle (m->parent);
12000                 klass = mono_class_from_mono_type (mtype);
12001
12002                 /* Find the method */
12003
12004                 name = mono_string_to_utf8 (m->name);
12005                 iter = NULL;
12006                 while ((method = mono_class_get_methods (klass, &iter))) {
12007                         if (!strcmp (method->name, name))
12008                                 break;
12009                 }
12010                 g_free (name);
12011
12012                 // FIXME:
12013                 g_assert (method);
12014                 // FIXME: Check parameters/return value etc. match
12015
12016                 result = method;
12017                 *handle_class = mono_defaults.methodhandle_class;
12018         } else if (is_sre_array (mono_object_get_class(obj)) ||
12019                                 is_sre_byref (mono_object_get_class(obj)) ||
12020                                 is_sre_pointer (mono_object_get_class(obj))) {
12021                 MonoReflectionType *ref_type = (MonoReflectionType *)obj;
12022                 MonoType *type = mono_reflection_type_get_handle (ref_type);
12023
12024                 if (context) {
12025                         MonoType *inflated = mono_class_inflate_generic_type (type, context);
12026                         result = mono_class_from_mono_type (inflated);
12027                         mono_metadata_free_type (inflated);
12028                 } else {
12029                         result = mono_class_from_mono_type (type);
12030                 }
12031                 *handle_class = mono_defaults.typehandle_class;
12032         } else {
12033                 g_print ("%s\n", obj->vtable->klass->name);
12034                 g_assert_not_reached ();
12035         }
12036         return result;
12037 }
12038
12039 #else /* DISABLE_REFLECTION_EMIT */
12040
12041 MonoArray*
12042 mono_reflection_get_custom_attrs_blob (MonoReflectionAssembly *assembly, MonoObject *ctor, MonoArray *ctorArgs, MonoArray *properties, MonoArray *propValues, MonoArray *fields, MonoArray* fieldValues) 
12043 {
12044         g_assert_not_reached ();
12045         return NULL;
12046 }
12047
12048 void
12049 mono_reflection_setup_internal_class (MonoReflectionTypeBuilder *tb)
12050 {
12051         g_assert_not_reached ();
12052 }
12053
12054 void
12055 mono_reflection_setup_generic_class (MonoReflectionTypeBuilder *tb)
12056 {
12057         g_assert_not_reached ();
12058 }
12059
12060 void
12061 mono_reflection_create_generic_class (MonoReflectionTypeBuilder *tb)
12062 {
12063         g_assert_not_reached ();
12064 }
12065
12066 void
12067 mono_reflection_create_internal_class (MonoReflectionTypeBuilder *tb)
12068 {
12069         g_assert_not_reached ();
12070 }
12071
12072 void
12073 mono_image_basic_init (MonoReflectionAssemblyBuilder *assemblyb)
12074 {
12075         g_error ("This mono runtime was configured with --enable-minimal=reflection_emit, so System.Reflection.Emit is not supported.");
12076 }
12077
12078 void
12079 mono_image_module_basic_init (MonoReflectionModuleBuilder *moduleb)
12080 {
12081         g_assert_not_reached ();
12082 }
12083
12084 void
12085 mono_image_set_wrappers_type (MonoReflectionModuleBuilder *moduleb, MonoReflectionType *type)
12086 {
12087         g_assert_not_reached ();
12088 }
12089
12090 MonoReflectionModule *
12091 mono_image_load_module_dynamic (MonoReflectionAssemblyBuilder *ab, MonoString *fileName)
12092 {
12093         g_assert_not_reached ();
12094         return NULL;
12095 }
12096
12097 guint32
12098 mono_image_insert_string (MonoReflectionModuleBuilder *module, MonoString *str)
12099 {
12100         g_assert_not_reached ();
12101         return 0;
12102 }
12103
12104 guint32
12105 mono_image_create_method_token (MonoDynamicImage *assembly, MonoObject *obj, MonoArray *opt_param_types)
12106 {
12107         g_assert_not_reached ();
12108         return 0;
12109 }
12110
12111 guint32
12112 mono_image_create_token (MonoDynamicImage *assembly, MonoObject *obj, 
12113                                                  gboolean create_open_instance, gboolean register_token)
12114 {
12115         g_assert_not_reached ();
12116         return 0;
12117 }
12118
12119 void
12120 mono_image_register_token (MonoDynamicImage *assembly, guint32 token, MonoObject *obj)
12121 {
12122 }
12123
12124 void
12125 mono_reflection_generic_class_initialize (MonoReflectionGenericClass *type, MonoArray *fields)
12126 {
12127         g_assert_not_reached ();
12128 }
12129
12130 void
12131 mono_reflection_get_dynamic_overrides (MonoClass *klass, MonoMethod ***overrides, int *num_overrides)
12132 {
12133         *overrides = NULL;
12134         *num_overrides = 0;
12135 }
12136
12137 MonoReflectionEvent *
12138 mono_reflection_event_builder_get_event_info (MonoReflectionTypeBuilder *tb, MonoReflectionEventBuilder *eb)
12139 {
12140         g_assert_not_reached ();
12141         return NULL;
12142 }
12143
12144 MonoReflectionType*
12145 mono_reflection_create_runtime_class (MonoReflectionTypeBuilder *tb)
12146 {
12147         g_assert_not_reached ();
12148         return NULL;
12149 }
12150
12151 void
12152 mono_reflection_initialize_generic_parameter (MonoReflectionGenericParam *gparam)
12153 {
12154         g_assert_not_reached ();
12155 }
12156
12157 MonoArray *
12158 mono_reflection_sighelper_get_signature_local (MonoReflectionSigHelper *sig)
12159 {
12160         g_assert_not_reached ();
12161         return NULL;
12162 }
12163
12164 MonoArray *
12165 mono_reflection_sighelper_get_signature_field (MonoReflectionSigHelper *sig)
12166 {
12167         g_assert_not_reached ();
12168         return NULL;
12169 }
12170
12171 void 
12172 mono_reflection_create_dynamic_method (MonoReflectionDynamicMethod *mb)
12173 {
12174 }
12175
12176 gpointer
12177 mono_reflection_lookup_dynamic_token (MonoImage *image, guint32 token, gboolean valid_token, MonoClass **handle_class, MonoGenericContext *context)
12178 {
12179         return NULL;
12180 }
12181
12182 MonoType*
12183 mono_reflection_type_get_handle (MonoReflectionType* ref)
12184 {
12185         if (!ref)
12186                 return NULL;
12187         return ref->type;
12188 }
12189
12190 void
12191 mono_reflection_free_dynamic_generic_class (MonoGenericClass *gclass)
12192 {
12193         g_assert_not_reached ();
12194 }
12195
12196 #endif /* DISABLE_REFLECTION_EMIT */
12197
12198 /* SECURITY_ACTION_* are defined in mono/metadata/tabledefs.h */
12199 const static guint32 declsec_flags_map[] = {
12200         0x00000000,                                     /* empty */
12201         MONO_DECLSEC_FLAG_REQUEST,                      /* SECURITY_ACTION_REQUEST                      (x01) */
12202         MONO_DECLSEC_FLAG_DEMAND,                       /* SECURITY_ACTION_DEMAND                       (x02) */
12203         MONO_DECLSEC_FLAG_ASSERT,                       /* SECURITY_ACTION_ASSERT                       (x03) */
12204         MONO_DECLSEC_FLAG_DENY,                         /* SECURITY_ACTION_DENY                         (x04) */
12205         MONO_DECLSEC_FLAG_PERMITONLY,                   /* SECURITY_ACTION_PERMITONLY                   (x05) */
12206         MONO_DECLSEC_FLAG_LINKDEMAND,                   /* SECURITY_ACTION_LINKDEMAND                   (x06) */
12207         MONO_DECLSEC_FLAG_INHERITANCEDEMAND,            /* SECURITY_ACTION_INHERITANCEDEMAND            (x07) */
12208         MONO_DECLSEC_FLAG_REQUEST_MINIMUM,              /* SECURITY_ACTION_REQUEST_MINIMUM              (x08) */
12209         MONO_DECLSEC_FLAG_REQUEST_OPTIONAL,             /* SECURITY_ACTION_REQUEST_OPTIONAL             (x09) */
12210         MONO_DECLSEC_FLAG_REQUEST_REFUSE,               /* SECURITY_ACTION_REQUEST_REFUSE               (x0A) */
12211         MONO_DECLSEC_FLAG_PREJIT_GRANT,                 /* SECURITY_ACTION_PREJIT_GRANT                 (x0B) */
12212         MONO_DECLSEC_FLAG_PREJIT_DENY,                  /* SECURITY_ACTION_PREJIT_DENY                  (x0C) */
12213         MONO_DECLSEC_FLAG_NONCAS_DEMAND,                /* SECURITY_ACTION_NONCAS_DEMAND                (x0D) */
12214         MONO_DECLSEC_FLAG_NONCAS_LINKDEMAND,            /* SECURITY_ACTION_NONCAS_LINKDEMAND            (x0E) */
12215         MONO_DECLSEC_FLAG_NONCAS_INHERITANCEDEMAND,     /* SECURITY_ACTION_NONCAS_INHERITANCEDEMAND     (x0F) */
12216         MONO_DECLSEC_FLAG_LINKDEMAND_CHOICE,            /* SECURITY_ACTION_LINKDEMAND_CHOICE            (x10) */
12217         MONO_DECLSEC_FLAG_INHERITANCEDEMAND_CHOICE,     /* SECURITY_ACTION_INHERITANCEDEMAND_CHOICE     (x11) */
12218         MONO_DECLSEC_FLAG_DEMAND_CHOICE,                /* SECURITY_ACTION_DEMAND_CHOICE                (x12) */
12219 };
12220
12221 /*
12222  * Returns flags that includes all available security action associated to the handle.
12223  * @token: metadata token (either for a class or a method)
12224  * @image: image where resides the metadata.
12225  */
12226 static guint32
12227 mono_declsec_get_flags (MonoImage *image, guint32 token)
12228 {
12229         int index = mono_metadata_declsec_from_index (image, token);
12230         MonoTableInfo *t = &image->tables [MONO_TABLE_DECLSECURITY];
12231         guint32 result = 0;
12232         guint32 action;
12233         int i;
12234
12235         /* HasSecurity can be present for other, not specially encoded, attributes,
12236            e.g. SuppressUnmanagedCodeSecurityAttribute */
12237         if (index < 0)
12238                 return 0;
12239
12240         for (i = index; i < t->rows; i++) {
12241                 guint32 cols [MONO_DECL_SECURITY_SIZE];
12242
12243                 mono_metadata_decode_row (t, i, cols, MONO_DECL_SECURITY_SIZE);
12244                 if (cols [MONO_DECL_SECURITY_PARENT] != token)
12245                         break;
12246
12247                 action = cols [MONO_DECL_SECURITY_ACTION];
12248                 if ((action >= MONO_DECLSEC_ACTION_MIN) && (action <= MONO_DECLSEC_ACTION_MAX)) {
12249                         result |= declsec_flags_map [action];
12250                 } else {
12251                         g_assert_not_reached ();
12252                 }
12253         }
12254         return result;
12255 }
12256
12257 /*
12258  * Get the security actions (in the form of flags) associated with the specified method.
12259  *
12260  * @method: The method for which we want the declarative security flags.
12261  * Return the declarative security flags for the method (only).
12262  *
12263  * Note: To keep MonoMethod size down we do not cache the declarative security flags
12264  *       (except for the stack modifiers which are kept in the MonoJitInfo structure)
12265  */
12266 guint32
12267 mono_declsec_flags_from_method (MonoMethod *method)
12268 {
12269         if (method->flags & METHOD_ATTRIBUTE_HAS_SECURITY) {
12270                 /* FIXME: No cache (for the moment) */
12271                 guint32 idx = mono_method_get_index (method);
12272                 idx <<= MONO_HAS_DECL_SECURITY_BITS;
12273                 idx |= MONO_HAS_DECL_SECURITY_METHODDEF;
12274                 return mono_declsec_get_flags (method->klass->image, idx);
12275         }
12276         return 0;
12277 }
12278
12279 /*
12280  * Get the security actions (in the form of flags) associated with the specified class.
12281  *
12282  * @klass: The class for which we want the declarative security flags.
12283  * Return the declarative security flags for the class.
12284  *
12285  * Note: We cache the flags inside the MonoClass structure as this will get 
12286  *       called very often (at least for each method).
12287  */
12288 guint32
12289 mono_declsec_flags_from_class (MonoClass *klass)
12290 {
12291         if (klass->flags & TYPE_ATTRIBUTE_HAS_SECURITY) {
12292                 if (!klass->ext || !klass->ext->declsec_flags) {
12293                         guint32 idx;
12294
12295                         idx = mono_metadata_token_index (klass->type_token);
12296                         idx <<= MONO_HAS_DECL_SECURITY_BITS;
12297                         idx |= MONO_HAS_DECL_SECURITY_TYPEDEF;
12298                         mono_loader_lock ();
12299                         mono_class_alloc_ext (klass);
12300                         mono_loader_unlock ();
12301                         /* we cache the flags on classes */
12302                         klass->ext->declsec_flags = mono_declsec_get_flags (klass->image, idx);
12303                 }
12304                 return klass->ext->declsec_flags;
12305         }
12306         return 0;
12307 }
12308
12309 /*
12310  * Get the security actions (in the form of flags) associated with the specified assembly.
12311  *
12312  * @assembly: The assembly for which we want the declarative security flags.
12313  * Return the declarative security flags for the assembly.
12314  */
12315 guint32
12316 mono_declsec_flags_from_assembly (MonoAssembly *assembly)
12317 {
12318         guint32 idx = 1; /* there is only one assembly */
12319         idx <<= MONO_HAS_DECL_SECURITY_BITS;
12320         idx |= MONO_HAS_DECL_SECURITY_ASSEMBLY;
12321         return mono_declsec_get_flags (assembly->image, idx);
12322 }
12323
12324
12325 /*
12326  * Fill actions for the specific index (which may either be an encoded class token or
12327  * an encoded method token) from the metadata image.
12328  * Returns TRUE if some actions requiring code generation are present, FALSE otherwise.
12329  */
12330 static MonoBoolean
12331 fill_actions_from_index (MonoImage *image, guint32 token, MonoDeclSecurityActions* actions,
12332         guint32 id_std, guint32 id_noncas, guint32 id_choice)
12333 {
12334         MonoBoolean result = FALSE;
12335         MonoTableInfo *t;
12336         guint32 cols [MONO_DECL_SECURITY_SIZE];
12337         int index = mono_metadata_declsec_from_index (image, token);
12338         int i;
12339
12340         t  = &image->tables [MONO_TABLE_DECLSECURITY];
12341         for (i = index; i < t->rows; i++) {
12342                 mono_metadata_decode_row (t, i, cols, MONO_DECL_SECURITY_SIZE);
12343
12344                 if (cols [MONO_DECL_SECURITY_PARENT] != token)
12345                         return result;
12346
12347                 /* if present only replace (class) permissions with method permissions */
12348                 /* if empty accept either class or method permissions */
12349                 if (cols [MONO_DECL_SECURITY_ACTION] == id_std) {
12350                         if (!actions->demand.blob) {
12351                                 const char *blob = mono_metadata_blob_heap (image, cols [MONO_DECL_SECURITY_PERMISSIONSET]);
12352                                 actions->demand.index = cols [MONO_DECL_SECURITY_PERMISSIONSET];
12353                                 actions->demand.blob = (char*) (blob + 2);
12354                                 actions->demand.size = mono_metadata_decode_blob_size (blob, &blob);
12355                                 result = TRUE;
12356                         }
12357                 } else if (cols [MONO_DECL_SECURITY_ACTION] == id_noncas) {
12358                         if (!actions->noncasdemand.blob) {
12359                                 const char *blob = mono_metadata_blob_heap (image, cols [MONO_DECL_SECURITY_PERMISSIONSET]);
12360                                 actions->noncasdemand.index = cols [MONO_DECL_SECURITY_PERMISSIONSET];
12361                                 actions->noncasdemand.blob = (char*) (blob + 2);
12362                                 actions->noncasdemand.size = mono_metadata_decode_blob_size (blob, &blob);
12363                                 result = TRUE;
12364                         }
12365                 } else if (cols [MONO_DECL_SECURITY_ACTION] == id_choice) {
12366                         if (!actions->demandchoice.blob) {
12367                                 const char *blob = mono_metadata_blob_heap (image, cols [MONO_DECL_SECURITY_PERMISSIONSET]);
12368                                 actions->demandchoice.index = cols [MONO_DECL_SECURITY_PERMISSIONSET];
12369                                 actions->demandchoice.blob = (char*) (blob + 2);
12370                                 actions->demandchoice.size = mono_metadata_decode_blob_size (blob, &blob);
12371                                 result = TRUE;
12372                         }
12373                 }
12374         }
12375
12376         return result;
12377 }
12378
12379 static MonoBoolean
12380 mono_declsec_get_class_demands_params (MonoClass *klass, MonoDeclSecurityActions* demands, 
12381         guint32 id_std, guint32 id_noncas, guint32 id_choice)
12382 {
12383         guint32 idx = mono_metadata_token_index (klass->type_token);
12384         idx <<= MONO_HAS_DECL_SECURITY_BITS;
12385         idx |= MONO_HAS_DECL_SECURITY_TYPEDEF;
12386         return fill_actions_from_index (klass->image, idx, demands, id_std, id_noncas, id_choice);
12387 }
12388
12389 static MonoBoolean
12390 mono_declsec_get_method_demands_params (MonoMethod *method, MonoDeclSecurityActions* demands, 
12391         guint32 id_std, guint32 id_noncas, guint32 id_choice)
12392 {
12393         guint32 idx = mono_method_get_index (method);
12394         idx <<= MONO_HAS_DECL_SECURITY_BITS;
12395         idx |= MONO_HAS_DECL_SECURITY_METHODDEF;
12396         return fill_actions_from_index (method->klass->image, idx, demands, id_std, id_noncas, id_choice);
12397 }
12398
12399 /*
12400  * Collect all actions (that requires to generate code in mini) assigned for
12401  * the specified method.
12402  * Note: Don't use the content of actions if the function return FALSE.
12403  */
12404 MonoBoolean
12405 mono_declsec_get_demands (MonoMethod *method, MonoDeclSecurityActions* demands)
12406 {
12407         guint32 mask = MONO_DECLSEC_FLAG_DEMAND | MONO_DECLSEC_FLAG_NONCAS_DEMAND | 
12408                 MONO_DECLSEC_FLAG_DEMAND_CHOICE;
12409         MonoBoolean result = FALSE;
12410         guint32 flags;
12411
12412         /* quick exit if no declarative security is present in the metadata */
12413         if (!method->klass->image->tables [MONO_TABLE_DECLSECURITY].rows)
12414                 return FALSE;
12415
12416         /* we want the original as the wrapper is "free" of the security informations */
12417         if (method->wrapper_type == MONO_WRAPPER_MANAGED_TO_NATIVE || method->wrapper_type == MONO_WRAPPER_MANAGED_TO_MANAGED) {
12418                 method = mono_marshal_method_from_wrapper (method);
12419                 if (!method)
12420                         return FALSE;
12421         }
12422
12423         /* First we look for method-level attributes */
12424         if (method->flags & METHOD_ATTRIBUTE_HAS_SECURITY) {
12425                 mono_class_init (method->klass);
12426                 memset (demands, 0, sizeof (MonoDeclSecurityActions));
12427
12428                 result = mono_declsec_get_method_demands_params (method, demands, 
12429                         SECURITY_ACTION_DEMAND, SECURITY_ACTION_NONCASDEMAND, SECURITY_ACTION_DEMANDCHOICE);
12430         }
12431
12432         /* Here we use (or create) the class declarative cache to look for demands */
12433         flags = mono_declsec_flags_from_class (method->klass);
12434         if (flags & mask) {
12435                 if (!result) {
12436                         mono_class_init (method->klass);
12437                         memset (demands, 0, sizeof (MonoDeclSecurityActions));
12438                 }
12439                 result |= mono_declsec_get_class_demands_params (method->klass, demands, 
12440                         SECURITY_ACTION_DEMAND, SECURITY_ACTION_NONCASDEMAND, SECURITY_ACTION_DEMANDCHOICE);
12441         }
12442
12443         /* The boolean return value is used as a shortcut in case nothing needs to
12444            be generated (e.g. LinkDemand[Choice] and InheritanceDemand[Choice]) */
12445         return result;
12446 }
12447
12448
12449 /*
12450  * Collect all Link actions: LinkDemand, NonCasLinkDemand and LinkDemandChoice (2.0).
12451  *
12452  * Note: Don't use the content of actions if the function return FALSE.
12453  */
12454 MonoBoolean
12455 mono_declsec_get_linkdemands (MonoMethod *method, MonoDeclSecurityActions* klass, MonoDeclSecurityActions *cmethod)
12456 {
12457         MonoBoolean result = FALSE;
12458         guint32 flags;
12459
12460         /* quick exit if no declarative security is present in the metadata */
12461         if (!method->klass->image->tables [MONO_TABLE_DECLSECURITY].rows)
12462                 return FALSE;
12463
12464         /* we want the original as the wrapper is "free" of the security informations */
12465         if (method->wrapper_type == MONO_WRAPPER_MANAGED_TO_NATIVE || method->wrapper_type == MONO_WRAPPER_MANAGED_TO_MANAGED) {
12466                 method = mono_marshal_method_from_wrapper (method);
12467                 if (!method)
12468                         return FALSE;
12469         }
12470
12471         /* results are independant - zeroize both */
12472         memset (cmethod, 0, sizeof (MonoDeclSecurityActions));
12473         memset (klass, 0, sizeof (MonoDeclSecurityActions));
12474
12475         /* First we look for method-level attributes */
12476         if (method->flags & METHOD_ATTRIBUTE_HAS_SECURITY) {
12477                 mono_class_init (method->klass);
12478
12479                 result = mono_declsec_get_method_demands_params (method, cmethod, 
12480                         SECURITY_ACTION_LINKDEMAND, SECURITY_ACTION_NONCASLINKDEMAND, SECURITY_ACTION_LINKDEMANDCHOICE);
12481         }
12482
12483         /* Here we use (or create) the class declarative cache to look for demands */
12484         flags = mono_declsec_flags_from_class (method->klass);
12485         if (flags & (MONO_DECLSEC_FLAG_LINKDEMAND | MONO_DECLSEC_FLAG_NONCAS_LINKDEMAND | MONO_DECLSEC_FLAG_LINKDEMAND_CHOICE)) {
12486                 mono_class_init (method->klass);
12487
12488                 result |= mono_declsec_get_class_demands_params (method->klass, klass, 
12489                         SECURITY_ACTION_LINKDEMAND, SECURITY_ACTION_NONCASLINKDEMAND, SECURITY_ACTION_LINKDEMANDCHOICE);
12490         }
12491
12492         return result;
12493 }
12494
12495 /*
12496  * Collect all Inherit actions: InheritanceDemand, NonCasInheritanceDemand and InheritanceDemandChoice (2.0).
12497  *
12498  * @klass       The inherited class - this is the class that provides the security check (attributes)
12499  * @demans      
12500  * return TRUE if inheritance demands (any kind) are present, FALSE otherwise.
12501  * 
12502  * Note: Don't use the content of actions if the function return FALSE.
12503  */
12504 MonoBoolean
12505 mono_declsec_get_inheritdemands_class (MonoClass *klass, MonoDeclSecurityActions* demands)
12506 {
12507         MonoBoolean result = FALSE;
12508         guint32 flags;
12509
12510         /* quick exit if no declarative security is present in the metadata */
12511         if (!klass->image->tables [MONO_TABLE_DECLSECURITY].rows)
12512                 return FALSE;
12513
12514         /* Here we use (or create) the class declarative cache to look for demands */
12515         flags = mono_declsec_flags_from_class (klass);
12516         if (flags & (MONO_DECLSEC_FLAG_INHERITANCEDEMAND | MONO_DECLSEC_FLAG_NONCAS_INHERITANCEDEMAND | MONO_DECLSEC_FLAG_INHERITANCEDEMAND_CHOICE)) {
12517                 mono_class_init (klass);
12518                 memset (demands, 0, sizeof (MonoDeclSecurityActions));
12519
12520                 result |= mono_declsec_get_class_demands_params (klass, demands, 
12521                         SECURITY_ACTION_INHERITDEMAND, SECURITY_ACTION_NONCASINHERITANCE, SECURITY_ACTION_INHERITDEMANDCHOICE);
12522         }
12523
12524         return result;
12525 }
12526
12527 /*
12528  * Collect all Inherit actions: InheritanceDemand, NonCasInheritanceDemand and InheritanceDemandChoice (2.0).
12529  *
12530  * Note: Don't use the content of actions if the function return FALSE.
12531  */
12532 MonoBoolean
12533 mono_declsec_get_inheritdemands_method (MonoMethod *method, MonoDeclSecurityActions* demands)
12534 {
12535         /* quick exit if no declarative security is present in the metadata */
12536         if (!method->klass->image->tables [MONO_TABLE_DECLSECURITY].rows)
12537                 return FALSE;
12538
12539         /* we want the original as the wrapper is "free" of the security informations */
12540         if (method->wrapper_type == MONO_WRAPPER_MANAGED_TO_NATIVE || method->wrapper_type == MONO_WRAPPER_MANAGED_TO_MANAGED) {
12541                 method = mono_marshal_method_from_wrapper (method);
12542                 if (!method)
12543                         return FALSE;
12544         }
12545
12546         if (method->flags & METHOD_ATTRIBUTE_HAS_SECURITY) {
12547                 mono_class_init (method->klass);
12548                 memset (demands, 0, sizeof (MonoDeclSecurityActions));
12549
12550                 return mono_declsec_get_method_demands_params (method, demands, 
12551                         SECURITY_ACTION_INHERITDEMAND, SECURITY_ACTION_NONCASINHERITANCE, SECURITY_ACTION_INHERITDEMANDCHOICE);
12552         }
12553         return FALSE;
12554 }
12555
12556
12557 static MonoBoolean
12558 get_declsec_action (MonoImage *image, guint32 token, guint32 action, MonoDeclSecurityEntry *entry)
12559 {
12560         guint32 cols [MONO_DECL_SECURITY_SIZE];
12561         MonoTableInfo *t;
12562         int i;
12563
12564         int index = mono_metadata_declsec_from_index (image, token);
12565         if (index == -1)
12566                 return FALSE;
12567
12568         t =  &image->tables [MONO_TABLE_DECLSECURITY];
12569         for (i = index; i < t->rows; i++) {
12570                 mono_metadata_decode_row (t, i, cols, MONO_DECL_SECURITY_SIZE);
12571
12572                 /* shortcut - index are ordered */
12573                 if (token != cols [MONO_DECL_SECURITY_PARENT])
12574                         return FALSE;
12575
12576                 if (cols [MONO_DECL_SECURITY_ACTION] == action) {
12577                         const char *metadata = mono_metadata_blob_heap (image, cols [MONO_DECL_SECURITY_PERMISSIONSET]);
12578                         entry->blob = (char*) (metadata + 2);
12579                         entry->size = mono_metadata_decode_blob_size (metadata, &metadata);
12580                         return TRUE;
12581                 }
12582         }
12583
12584         return FALSE;
12585 }
12586
12587 MonoBoolean
12588 mono_declsec_get_method_action (MonoMethod *method, guint32 action, MonoDeclSecurityEntry *entry)
12589 {
12590         if (method->flags & METHOD_ATTRIBUTE_HAS_SECURITY) {
12591                 guint32 idx = mono_method_get_index (method);
12592                 idx <<= MONO_HAS_DECL_SECURITY_BITS;
12593                 idx |= MONO_HAS_DECL_SECURITY_METHODDEF;
12594                 return get_declsec_action (method->klass->image, idx, action, entry);
12595         }
12596         return FALSE;
12597 }
12598
12599 MonoBoolean
12600 mono_declsec_get_class_action (MonoClass *klass, guint32 action, MonoDeclSecurityEntry *entry)
12601 {
12602         /* use cache */
12603         guint32 flags = mono_declsec_flags_from_class (klass);
12604         if (declsec_flags_map [action] & flags) {
12605                 guint32 idx = mono_metadata_token_index (klass->type_token);
12606                 idx <<= MONO_HAS_DECL_SECURITY_BITS;
12607                 idx |= MONO_HAS_DECL_SECURITY_TYPEDEF;
12608                 return get_declsec_action (klass->image, idx, action, entry);
12609         }
12610         return FALSE;
12611 }
12612
12613 MonoBoolean
12614 mono_declsec_get_assembly_action (MonoAssembly *assembly, guint32 action, MonoDeclSecurityEntry *entry)
12615 {
12616         guint32 idx = 1; /* there is only one assembly */
12617         idx <<= MONO_HAS_DECL_SECURITY_BITS;
12618         idx |= MONO_HAS_DECL_SECURITY_ASSEMBLY;
12619
12620         return get_declsec_action (assembly->image, idx, action, entry);
12621 }
12622
12623 gboolean
12624 mono_reflection_call_is_assignable_to (MonoClass *klass, MonoClass *oklass)
12625 {
12626         MonoObject *res, *exc;
12627         void *params [1];
12628         static MonoClass *System_Reflection_Emit_TypeBuilder = NULL;
12629         static MonoMethod *method = NULL;
12630
12631         if (!System_Reflection_Emit_TypeBuilder) {
12632                 System_Reflection_Emit_TypeBuilder = mono_class_from_name (mono_defaults.corlib, "System.Reflection.Emit", "TypeBuilder");
12633                 g_assert (System_Reflection_Emit_TypeBuilder);
12634         }
12635         if (method == NULL) {
12636                 method = mono_class_get_method_from_name (System_Reflection_Emit_TypeBuilder, "IsAssignableTo", 1);
12637                 g_assert (method);
12638         }
12639
12640         /* 
12641          * The result of mono_type_get_object () might be a System.MonoType but we
12642          * need a TypeBuilder so use mono_class_get_ref_info (klass).
12643          */
12644         g_assert (mono_class_get_ref_info (klass));
12645         g_assert (!strcmp (((MonoObject*)(mono_class_get_ref_info (klass)))->vtable->klass->name, "TypeBuilder"));
12646
12647         params [0] = mono_type_get_object (mono_domain_get (), &oklass->byval_arg);
12648
12649         res = mono_runtime_invoke (method, (MonoObject*)(mono_class_get_ref_info (klass)), params, &exc);
12650         if (exc)
12651                 return FALSE;
12652         else
12653                 return *(MonoBoolean*)mono_object_unbox (res);
12654 }
12655
12656 /**
12657  * mono_reflection_type_get_type:
12658  * @reftype: the System.Type object
12659  *
12660  * Returns the MonoType* associated with the C# System.Type object @reftype.
12661  */
12662 MonoType*
12663 mono_reflection_type_get_type (MonoReflectionType *reftype)
12664 {
12665         g_assert (reftype);
12666
12667         return mono_reflection_type_get_handle (reftype);
12668 }
12669