Merge branch 'master' into msbuilddll2
[mono.git] / mono / metadata / reflection.c
1 /*
2  * reflection.c: Routines for creating an image at runtime.
3  * 
4  * Author:
5  *   Paolo Molaro (lupus@ximian.com)
6  *
7  * Copyright 2001-2003 Ximian, Inc (http://www.ximian.com)
8  * Copyright 2004-2009 Novell, Inc (http://www.novell.com)
9  * Copyright 2011 Rodrigo Kumpera
10  *
11  */
12 #include <config.h>
13 #include "mono/utils/mono-digest.h"
14 #include "mono/utils/mono-membar.h"
15 #include "mono/metadata/reflection.h"
16 #include "mono/metadata/tabledefs.h"
17 #include "mono/metadata/metadata-internals.h"
18 #include <mono/metadata/profiler-private.h>
19 #include "mono/metadata/class-internals.h"
20 #include "mono/metadata/gc-internal.h"
21 #include "mono/metadata/tokentype.h"
22 #include "mono/metadata/domain-internals.h"
23 #include "mono/metadata/opcodes.h"
24 #include "mono/metadata/assembly.h"
25 #include "mono/metadata/object-internals.h"
26 #include <mono/metadata/exception.h>
27 #include <mono/metadata/marshal.h>
28 #include <mono/metadata/security-manager.h>
29 #include <stdio.h>
30 #include <glib.h>
31 #include <errno.h>
32 #include <time.h>
33 #include <string.h>
34 #include <ctype.h>
35 #include "image.h"
36 #include "cil-coff.h"
37 #include "mono-endian.h"
38 #include <mono/metadata/gc-internal.h>
39 #include <mono/metadata/mempool-internals.h>
40 #include <mono/metadata/security-core-clr.h>
41 #include <mono/metadata/debug-helpers.h>
42 #include <mono/metadata/verify-internals.h>
43 #include <mono/metadata/mono-ptr-array.h>
44 #include <mono/utils/mono-string.h>
45 #include <mono/utils/mono-error-internals.h>
46
47 static gboolean is_usertype (MonoReflectionType *ref);
48 static MonoReflectionType *mono_reflection_type_resolve_user_types (MonoReflectionType *type);
49
50 typedef struct {
51         char *p;
52         char *buf;
53         char *end;
54 } SigBuffer;
55
56 #define TEXT_OFFSET 512
57 #define CLI_H_SIZE 136
58 #define FILE_ALIGN 512
59 #define VIRT_ALIGN 8192
60 #define START_TEXT_RVA  0x00002000
61
62 typedef struct {
63         MonoReflectionILGen *ilgen;
64         MonoReflectionType *rtype;
65         MonoArray *parameters;
66         MonoArray *generic_params;
67         MonoGenericContainer *generic_container;
68         MonoArray *pinfo;
69         MonoArray *opt_types;
70         guint32 attrs;
71         guint32 iattrs;
72         guint32 call_conv;
73         guint32 *table_idx; /* note: it's a pointer */
74         MonoArray *code;
75         MonoObject *type;
76         MonoString *name;
77         MonoBoolean init_locals;
78         MonoBoolean skip_visibility;
79         MonoArray *return_modreq;
80         MonoArray *return_modopt;
81         MonoArray *param_modreq;
82         MonoArray *param_modopt;
83         MonoArray *permissions;
84         MonoMethod *mhandle;
85         guint32 nrefs;
86         gpointer *refs;
87         /* for PInvoke */
88         int charset, extra_flags, native_cc;
89         MonoString *dll, *dllentry;
90 } ReflectionMethodBuilder;
91
92 typedef struct {
93         guint32 owner;
94         MonoReflectionGenericParam *gparam;
95 } GenericParamTableEntry;
96
97 const unsigned char table_sizes [MONO_TABLE_NUM] = {
98         MONO_MODULE_SIZE,
99         MONO_TYPEREF_SIZE,
100         MONO_TYPEDEF_SIZE,
101         0,
102         MONO_FIELD_SIZE,
103         0,
104         MONO_METHOD_SIZE,
105         0,
106         MONO_PARAM_SIZE,
107         MONO_INTERFACEIMPL_SIZE,
108         MONO_MEMBERREF_SIZE,    /* 0x0A */
109         MONO_CONSTANT_SIZE,
110         MONO_CUSTOM_ATTR_SIZE,
111         MONO_FIELD_MARSHAL_SIZE,
112         MONO_DECL_SECURITY_SIZE,
113         MONO_CLASS_LAYOUT_SIZE,
114         MONO_FIELD_LAYOUT_SIZE, /* 0x10 */
115         MONO_STAND_ALONE_SIGNATURE_SIZE,
116         MONO_EVENT_MAP_SIZE,
117         0,
118         MONO_EVENT_SIZE,
119         MONO_PROPERTY_MAP_SIZE,
120         0,
121         MONO_PROPERTY_SIZE,
122         MONO_METHOD_SEMA_SIZE,
123         MONO_METHODIMPL_SIZE,
124         MONO_MODULEREF_SIZE,    /* 0x1A */
125         MONO_TYPESPEC_SIZE,
126         MONO_IMPLMAP_SIZE,      
127         MONO_FIELD_RVA_SIZE,
128         0,
129         0,
130         MONO_ASSEMBLY_SIZE,     /* 0x20 */
131         MONO_ASSEMBLY_PROCESSOR_SIZE,
132         MONO_ASSEMBLYOS_SIZE,
133         MONO_ASSEMBLYREF_SIZE,
134         MONO_ASSEMBLYREFPROC_SIZE,
135         MONO_ASSEMBLYREFOS_SIZE,
136         MONO_FILE_SIZE,
137         MONO_EXP_TYPE_SIZE,
138         MONO_MANIFEST_SIZE,
139         MONO_NESTED_CLASS_SIZE,
140
141         MONO_GENERICPARAM_SIZE, /* 0x2A */
142         MONO_METHODSPEC_SIZE,
143         MONO_GENPARCONSTRAINT_SIZE
144
145 };
146
147 #ifndef DISABLE_REFLECTION_EMIT
148 static guint32 mono_image_get_methodref_token (MonoDynamicImage *assembly, MonoMethod *method, gboolean create_typespec);
149 static guint32 mono_image_get_methodbuilder_token (MonoDynamicImage *assembly, MonoReflectionMethodBuilder *mb, gboolean create_open_instance);
150 static guint32 mono_image_get_ctorbuilder_token (MonoDynamicImage *assembly, MonoReflectionCtorBuilder *cb);
151 static guint32 mono_image_get_sighelper_token (MonoDynamicImage *assembly, MonoReflectionSigHelper *helper);
152 static void    ensure_runtime_vtable (MonoClass *klass);
153 static gpointer resolve_object (MonoImage *image, MonoObject *obj, MonoClass **handle_class, MonoGenericContext *context);
154 static guint32 mono_image_get_methodref_token_for_methodbuilder (MonoDynamicImage *assembly, MonoReflectionMethodBuilder *method);
155 static guint32 encode_generic_method_sig (MonoDynamicImage *assembly, MonoGenericContext *context);
156 static gpointer register_assembly (MonoDomain *domain, MonoReflectionAssembly *res, MonoAssembly *assembly);
157 static void reflection_methodbuilder_from_method_builder (ReflectionMethodBuilder *rmb, MonoReflectionMethodBuilder *mb);
158 static void reflection_methodbuilder_from_ctor_builder (ReflectionMethodBuilder *rmb, MonoReflectionCtorBuilder *mb);
159 static guint32 create_generic_typespec (MonoDynamicImage *assembly, MonoReflectionTypeBuilder *tb);
160 #endif
161
162 static guint32 mono_image_typedef_or_ref (MonoDynamicImage *assembly, MonoType *type);
163 static guint32 mono_image_typedef_or_ref_full (MonoDynamicImage *assembly, MonoType *type, gboolean try_typespec);
164 static void    mono_image_get_generic_param_info (MonoReflectionGenericParam *gparam, guint32 owner, MonoDynamicImage *assembly);
165 static guint32 encode_marshal_blob (MonoDynamicImage *assembly, MonoReflectionMarshal *minfo);
166 static guint32 encode_constant (MonoDynamicImage *assembly, MonoObject *val, guint32 *ret_type);
167 static char*   type_get_qualified_name (MonoType *type, MonoAssembly *ass);
168 static void    encode_type (MonoDynamicImage *assembly, MonoType *type, SigBuffer *buf);
169 static void get_default_param_value_blobs (MonoMethod *method, char **blobs, guint32 *types);
170 static MonoReflectionType *mono_reflection_type_get_underlying_system_type (MonoReflectionType* t);
171 static MonoType* mono_reflection_get_type_with_rootimage (MonoImage *rootimage, MonoImage* image, MonoTypeNameParse *info, gboolean ignorecase, gboolean *type_resolve);
172 static MonoReflectionType* mono_reflection_type_resolve_user_types (MonoReflectionType *type);
173 static gboolean is_sre_array (MonoClass *class);
174 static gboolean is_sre_byref (MonoClass *class);
175 static gboolean is_sre_pointer (MonoClass *class);
176 static gboolean is_sre_type_builder (MonoClass *class);
177 static gboolean is_sre_method_builder (MonoClass *class);
178 static gboolean is_sre_ctor_builder (MonoClass *class);
179 static gboolean is_sre_field_builder (MonoClass *class);
180 static gboolean is_sr_mono_method (MonoClass *class);
181 static gboolean is_sr_mono_cmethod (MonoClass *class);
182 static gboolean is_sr_mono_generic_method (MonoClass *class);
183 static gboolean is_sr_mono_generic_cmethod (MonoClass *class);
184 static gboolean is_sr_mono_field (MonoClass *class);
185 static gboolean is_sr_mono_property (MonoClass *class);
186 static gboolean is_sre_method_on_tb_inst (MonoClass *class);
187 static gboolean is_sre_ctor_on_tb_inst (MonoClass *class);
188
189 static guint32 mono_image_get_methodspec_token (MonoDynamicImage *assembly, MonoMethod *method);
190 static guint32 mono_image_get_inflated_method_token (MonoDynamicImage *assembly, MonoMethod *m);
191 static MonoMethod * inflate_method (MonoReflectionType *type, MonoObject *obj);
192
193 static guint32 create_typespec (MonoDynamicImage *assembly, MonoType *type);
194 static void init_type_builder_generics (MonoObject *type);
195
196 #define RESOLVE_TYPE(type) do { type = (void*)mono_reflection_type_resolve_user_types ((MonoReflectionType*)type); } while (0)
197 #define RESOLVE_ARRAY_TYPE_ELEMENT(array, index) do {   \
198         MonoReflectionType *__type = mono_array_get (array, MonoReflectionType*, index);        \
199         __type = mono_reflection_type_resolve_user_types (__type);      \
200         mono_array_set (arr, MonoReflectionType*, index, __type);       \
201 } while (0)
202
203 #define mono_type_array_get_and_resolve(array, index) mono_reflection_type_get_handle ((MonoReflectionType*)mono_array_get (array, gpointer, index))
204
205 #define CHECK_ADD4_OVERFLOW_UN(a, b) ((guint32)(0xFFFFFFFFU) - (guint32)(b) < (guint32)(a))
206 #define CHECK_ADD8_OVERFLOW_UN(a, b) ((guint64)(0xFFFFFFFFFFFFFFFFUL) - (guint64)(b) < (guint64)(a))
207
208 #if SIZEOF_VOID_P == 4
209 #define CHECK_ADDP_OVERFLOW_UN(a,b) CHECK_ADD4_OVERFLOW_UN(a, b)
210 #else
211 #define CHECK_ADDP_OVERFLOW_UN(a,b) CHECK_ADD8_OVERFLOW_UN(a, b)
212 #endif
213
214 #define ADDP_IS_GREATER_OR_OVF(a, b, c) (((a) + (b) > (c)) || CHECK_ADDP_OVERFLOW_UN (a, b))
215 #define ADD_IS_GREATER_OR_OVF(a, b, c) (((a) + (b) > (c)) || CHECK_ADD4_OVERFLOW_UN (a, b))
216
217
218 void
219 mono_reflection_init (void)
220 {
221 }
222
223 static void
224 sigbuffer_init (SigBuffer *buf, int size)
225 {
226         buf->buf = g_malloc (size);
227         buf->p = buf->buf;
228         buf->end = buf->buf + size;
229 }
230
231 static void
232 sigbuffer_make_room (SigBuffer *buf, int size)
233 {
234         if (buf->end - buf->p < size) {
235                 int new_size = buf->end - buf->buf + size + 32;
236                 char *p = g_realloc (buf->buf, new_size);
237                 size = buf->p - buf->buf;
238                 buf->buf = p;
239                 buf->p = p + size;
240                 buf->end = buf->buf + new_size;
241         }
242 }
243
244 static void
245 sigbuffer_add_value (SigBuffer *buf, guint32 val)
246 {
247         sigbuffer_make_room (buf, 6);
248         mono_metadata_encode_value (val, buf->p, &buf->p);
249 }
250
251 static void
252 sigbuffer_add_byte (SigBuffer *buf, guint8 val)
253 {
254         sigbuffer_make_room (buf, 1);
255         buf->p [0] = val;
256         buf->p++;
257 }
258
259 static void
260 sigbuffer_add_mem (SigBuffer *buf, char *p, guint32 size)
261 {
262         sigbuffer_make_room (buf, size);
263         memcpy (buf->p, p, size);
264         buf->p += size;
265 }
266
267 static void
268 sigbuffer_free (SigBuffer *buf)
269 {
270         g_free (buf->buf);
271 }
272
273 #ifndef DISABLE_REFLECTION_EMIT
274 /**
275  * mp_g_alloc:
276  *
277  * Allocate memory from the @image mempool if it is non-NULL. Otherwise, allocate memory
278  * from the C heap.
279  */
280 static gpointer
281 image_g_malloc (MonoImage *image, guint size)
282 {
283         if (image)
284                 return mono_image_alloc (image, size);
285         else
286                 return g_malloc (size);
287 }
288 #endif /* !DISABLE_REFLECTION_EMIT */
289
290 /**
291  * image_g_alloc0:
292  *
293  * Allocate memory from the @image mempool if it is non-NULL. Otherwise, allocate memory
294  * from the C heap.
295  */
296 static gpointer
297 image_g_malloc0 (MonoImage *image, guint size)
298 {
299         if (image)
300                 return mono_image_alloc0 (image, size);
301         else
302                 return g_malloc0 (size);
303 }
304
305 #ifndef DISABLE_REFLECTION_EMIT
306 static char*
307 image_strdup (MonoImage *image, const char *s)
308 {
309         if (image)
310                 return mono_image_strdup (image, s);
311         else
312                 return g_strdup (s);
313 }
314 #endif
315
316 #define image_g_new(image,struct_type, n_structs)               \
317     ((struct_type *) image_g_malloc (image, ((gsize) sizeof (struct_type)) * ((gsize) (n_structs))))
318
319 #define image_g_new0(image,struct_type, n_structs)              \
320     ((struct_type *) image_g_malloc0 (image, ((gsize) sizeof (struct_type)) * ((gsize) (n_structs))))
321
322
323 static void
324 alloc_table (MonoDynamicTable *table, guint nrows)
325 {
326         table->rows = nrows;
327         g_assert (table->columns);
328         if (nrows + 1 >= table->alloc_rows) {
329                 while (nrows + 1 >= table->alloc_rows) {
330                         if (table->alloc_rows == 0)
331                                 table->alloc_rows = 16;
332                         else
333                                 table->alloc_rows *= 2;
334                 }
335
336                 table->values = g_renew (guint32, table->values, (table->alloc_rows) * table->columns);
337         }
338 }
339
340 static void
341 make_room_in_stream (MonoDynamicStream *stream, int size)
342 {
343         if (size <= stream->alloc_size)
344                 return;
345         
346         while (stream->alloc_size <= size) {
347                 if (stream->alloc_size < 4096)
348                         stream->alloc_size = 4096;
349                 else
350                         stream->alloc_size *= 2;
351         }
352         
353         stream->data = g_realloc (stream->data, stream->alloc_size);
354 }
355
356 static guint32
357 string_heap_insert (MonoDynamicStream *sh, const char *str)
358 {
359         guint32 idx;
360         guint32 len;
361         gpointer oldkey, oldval;
362
363         if (g_hash_table_lookup_extended (sh->hash, str, &oldkey, &oldval))
364                 return GPOINTER_TO_UINT (oldval);
365
366         len = strlen (str) + 1;
367         idx = sh->index;
368         
369         make_room_in_stream (sh, idx + len);
370
371         /*
372          * We strdup the string even if we already copy them in sh->data
373          * so that the string pointers in the hash remain valid even if
374          * we need to realloc sh->data. We may want to avoid that later.
375          */
376         g_hash_table_insert (sh->hash, g_strdup (str), GUINT_TO_POINTER (idx));
377         memcpy (sh->data + idx, str, len);
378         sh->index += len;
379         return idx;
380 }
381
382 static guint32
383 string_heap_insert_mstring (MonoDynamicStream *sh, MonoString *str)
384 {
385         char *name = mono_string_to_utf8 (str);
386         guint32 idx;
387         idx = string_heap_insert (sh, name);
388         g_free (name);
389         return idx;
390 }
391
392 #ifndef DISABLE_REFLECTION_EMIT
393 static void
394 string_heap_init (MonoDynamicStream *sh)
395 {
396         sh->index = 0;
397         sh->alloc_size = 4096;
398         sh->data = g_malloc (4096);
399         sh->hash = g_hash_table_new_full (g_str_hash, g_str_equal, g_free, NULL);
400         string_heap_insert (sh, "");
401 }
402 #endif
403
404 static guint32
405 mono_image_add_stream_data (MonoDynamicStream *stream, const char *data, guint32 len)
406 {
407         guint32 idx;
408         
409         make_room_in_stream (stream, stream->index + len);
410         memcpy (stream->data + stream->index, data, len);
411         idx = stream->index;
412         stream->index += len;
413         /* 
414          * align index? Not without adding an additional param that controls it since
415          * we may store a blob value in pieces.
416          */
417         return idx;
418 }
419
420 static guint32
421 mono_image_add_stream_zero (MonoDynamicStream *stream, guint32 len)
422 {
423         guint32 idx;
424         
425         make_room_in_stream (stream, stream->index + len);
426         memset (stream->data + stream->index, 0, len);
427         idx = stream->index;
428         stream->index += len;
429         return idx;
430 }
431
432 static void
433 stream_data_align (MonoDynamicStream *stream)
434 {
435         char buf [4] = {0};
436         guint32 count = stream->index % 4;
437
438         /* we assume the stream data will be aligned */
439         if (count)
440                 mono_image_add_stream_data (stream, buf, 4 - count);
441 }
442
443 #ifndef DISABLE_REFLECTION_EMIT
444 static int
445 mono_blob_entry_hash (const char* str)
446 {
447         guint len, h;
448         const char *end;
449         len = mono_metadata_decode_blob_size (str, &str);
450         if (len > 0) {
451                 end = str + len;
452                 h = *str;
453                 for (str += 1; str < end; str++)
454                         h = (h << 5) - h + *str;
455                 return h;
456         } else {
457                 return 0;
458         }
459 }
460
461 static gboolean
462 mono_blob_entry_equal (const char *str1, const char *str2) {
463         int len, len2;
464         const char *end1;
465         const char *end2;
466         len = mono_metadata_decode_blob_size (str1, &end1);
467         len2 = mono_metadata_decode_blob_size (str2, &end2);
468         if (len != len2)
469                 return 0;
470         return memcmp (end1, end2, len) == 0;
471 }
472 #endif
473 static guint32
474 add_to_blob_cached (MonoDynamicImage *assembly, char *b1, int s1, char *b2, int s2)
475 {
476         guint32 idx;
477         char *copy;
478         gpointer oldkey, oldval;
479
480         copy = g_malloc (s1+s2);
481         memcpy (copy, b1, s1);
482         memcpy (copy + s1, b2, s2);
483         if (g_hash_table_lookup_extended (assembly->blob_cache, copy, &oldkey, &oldval)) {
484                 g_free (copy);
485                 idx = GPOINTER_TO_UINT (oldval);
486         } else {
487                 idx = mono_image_add_stream_data (&assembly->blob, b1, s1);
488                 mono_image_add_stream_data (&assembly->blob, b2, s2);
489                 g_hash_table_insert (assembly->blob_cache, copy, GUINT_TO_POINTER (idx));
490         }
491         return idx;
492 }
493
494 static guint32
495 sigbuffer_add_to_blob_cached (MonoDynamicImage *assembly, SigBuffer *buf)
496 {
497         char blob_size [8];
498         char *b = blob_size;
499         guint32 size = buf->p - buf->buf;
500         /* store length */
501         g_assert (size <= (buf->end - buf->buf));
502         mono_metadata_encode_value (size, b, &b);
503         return add_to_blob_cached (assembly, blob_size, b-blob_size, buf->buf, size);
504 }
505
506 /*
507  * Copy len * nelem bytes from val to dest, swapping bytes to LE if necessary.
508  * dest may be misaligned.
509  */
510 static void
511 swap_with_size (char *dest, const char* val, int len, int nelem) {
512 #if G_BYTE_ORDER != G_LITTLE_ENDIAN
513         int elem;
514
515         for (elem = 0; elem < nelem; ++elem) {
516                 switch (len) {
517                 case 1:
518                         *dest = *val;
519                         break;
520                 case 2:
521                         dest [0] = val [1];
522                         dest [1] = val [0];
523                         break;
524                 case 4:
525                         dest [0] = val [3];
526                         dest [1] = val [2];
527                         dest [2] = val [1];
528                         dest [3] = val [0];
529                         break;
530                 case 8:
531                         dest [0] = val [7];
532                         dest [1] = val [6];
533                         dest [2] = val [5];
534                         dest [3] = val [4];
535                         dest [4] = val [3];
536                         dest [5] = val [2];
537                         dest [6] = val [1];
538                         dest [7] = val [0];
539                         break;
540                 default:
541                         g_assert_not_reached ();
542                 }
543                 dest += len;
544                 val += len;
545         }
546 #else
547         memcpy (dest, val, len * nelem);
548 #endif
549 }
550
551 static guint32
552 add_mono_string_to_blob_cached (MonoDynamicImage *assembly, MonoString *str)
553 {
554         char blob_size [64];
555         char *b = blob_size;
556         guint32 idx = 0, len;
557
558         len = str->length * 2;
559         mono_metadata_encode_value (len, b, &b);
560 #if G_BYTE_ORDER != G_LITTLE_ENDIAN
561         {
562                 char *swapped = g_malloc (2 * mono_string_length (str));
563                 const char *p = (const char*)mono_string_chars (str);
564
565                 swap_with_size (swapped, p, 2, mono_string_length (str));
566                 idx = add_to_blob_cached (assembly, blob_size, b-blob_size, swapped, len);
567                 g_free (swapped);
568         }
569 #else
570         idx = add_to_blob_cached (assembly, blob_size, b-blob_size, (char*)mono_string_chars (str), len);
571 #endif
572         return idx;
573 }
574
575 #ifndef DISABLE_REFLECTION_EMIT
576 static MonoClass *
577 default_class_from_mono_type (MonoType *type)
578 {
579         switch (type->type) {
580         case MONO_TYPE_OBJECT:
581                 return mono_defaults.object_class;
582         case MONO_TYPE_VOID:
583                 return mono_defaults.void_class;
584         case MONO_TYPE_BOOLEAN:
585                 return mono_defaults.boolean_class;
586         case MONO_TYPE_CHAR:
587                 return mono_defaults.char_class;
588         case MONO_TYPE_I1:
589                 return mono_defaults.sbyte_class;
590         case MONO_TYPE_U1:
591                 return mono_defaults.byte_class;
592         case MONO_TYPE_I2:
593                 return mono_defaults.int16_class;
594         case MONO_TYPE_U2:
595                 return mono_defaults.uint16_class;
596         case MONO_TYPE_I4:
597                 return mono_defaults.int32_class;
598         case MONO_TYPE_U4:
599                 return mono_defaults.uint32_class;
600         case MONO_TYPE_I:
601                 return mono_defaults.int_class;
602         case MONO_TYPE_U:
603                 return mono_defaults.uint_class;
604         case MONO_TYPE_I8:
605                 return mono_defaults.int64_class;
606         case MONO_TYPE_U8:
607                 return mono_defaults.uint64_class;
608         case MONO_TYPE_R4:
609                 return mono_defaults.single_class;
610         case MONO_TYPE_R8:
611                 return mono_defaults.double_class;
612         case MONO_TYPE_STRING:
613                 return mono_defaults.string_class;
614         default:
615                 g_warning ("default_class_from_mono_type: implement me 0x%02x\n", type->type);
616                 g_assert_not_reached ();
617         }
618         
619         return NULL;
620 }
621 #endif
622
623 /*
624  * mono_class_get_ref_info:
625  *
626  *   Return the type builder/generic param builder corresponding to KLASS, if it exists.
627  */
628 gpointer
629 mono_class_get_ref_info (MonoClass *klass)
630 {
631         if (klass->ref_info_handle == 0)
632                 return NULL;
633         else
634                 return mono_gchandle_get_target (klass->ref_info_handle);
635 }
636
637 void
638 mono_class_set_ref_info (MonoClass *klass, gpointer obj)
639 {
640         klass->ref_info_handle = mono_gchandle_new ((MonoObject*)obj, FALSE);
641         g_assert (klass->ref_info_handle != 0);
642 }
643
644 void
645 mono_class_free_ref_info (MonoClass *klass)
646 {
647         if (klass->ref_info_handle) {
648                 mono_gchandle_free (klass->ref_info_handle);
649                 klass->ref_info_handle = 0;
650         }
651 }
652
653 static void
654 encode_generic_class (MonoDynamicImage *assembly, MonoGenericClass *gclass, SigBuffer *buf)
655 {
656         int i;
657         MonoGenericInst *class_inst;
658         MonoClass *klass;
659
660         g_assert (gclass);
661
662         class_inst = gclass->context.class_inst;
663
664         sigbuffer_add_value (buf, MONO_TYPE_GENERICINST);
665         klass = gclass->container_class;
666         sigbuffer_add_value (buf, klass->byval_arg.type);
667         sigbuffer_add_value (buf, mono_image_typedef_or_ref_full (assembly, &klass->byval_arg, FALSE));
668
669         sigbuffer_add_value (buf, class_inst->type_argc);
670         for (i = 0; i < class_inst->type_argc; ++i)
671                 encode_type (assembly, class_inst->type_argv [i], buf);
672
673 }
674
675 static void
676 encode_type (MonoDynamicImage *assembly, MonoType *type, SigBuffer *buf)
677 {
678         if (!type) {
679                 g_assert_not_reached ();
680                 return;
681         }
682                 
683         if (type->byref)
684                 sigbuffer_add_value (buf, MONO_TYPE_BYREF);
685
686         switch (type->type){
687         case MONO_TYPE_VOID:
688         case MONO_TYPE_BOOLEAN:
689         case MONO_TYPE_CHAR:
690         case MONO_TYPE_I1:
691         case MONO_TYPE_U1:
692         case MONO_TYPE_I2:
693         case MONO_TYPE_U2:
694         case MONO_TYPE_I4:
695         case MONO_TYPE_U4:
696         case MONO_TYPE_I8:
697         case MONO_TYPE_U8:
698         case MONO_TYPE_R4:
699         case MONO_TYPE_R8:
700         case MONO_TYPE_I:
701         case MONO_TYPE_U:
702         case MONO_TYPE_STRING:
703         case MONO_TYPE_OBJECT:
704         case MONO_TYPE_TYPEDBYREF:
705                 sigbuffer_add_value (buf, type->type);
706                 break;
707         case MONO_TYPE_PTR:
708                 sigbuffer_add_value (buf, type->type);
709                 encode_type (assembly, type->data.type, buf);
710                 break;
711         case MONO_TYPE_SZARRAY:
712                 sigbuffer_add_value (buf, type->type);
713                 encode_type (assembly, &type->data.klass->byval_arg, buf);
714                 break;
715         case MONO_TYPE_VALUETYPE:
716         case MONO_TYPE_CLASS: {
717                 MonoClass *k = mono_class_from_mono_type (type);
718
719                 if (k->generic_container) {
720                         MonoGenericClass *gclass = mono_metadata_lookup_generic_class (k, k->generic_container->context.class_inst, TRUE);
721                         encode_generic_class (assembly, gclass, buf);
722                 } else {
723                         /*
724                          * Make sure we use the correct type.
725                          */
726                         sigbuffer_add_value (buf, k->byval_arg.type);
727                         /*
728                          * ensure only non-byref gets passed to mono_image_typedef_or_ref(),
729                          * otherwise two typerefs could point to the same type, leading to
730                          * verification errors.
731                          */
732                         sigbuffer_add_value (buf, mono_image_typedef_or_ref (assembly, &k->byval_arg));
733                 }
734                 break;
735         }
736         case MONO_TYPE_ARRAY:
737                 sigbuffer_add_value (buf, type->type);
738                 encode_type (assembly, &type->data.array->eklass->byval_arg, buf);
739                 sigbuffer_add_value (buf, type->data.array->rank);
740                 sigbuffer_add_value (buf, 0); /* FIXME: set to 0 for now */
741                 sigbuffer_add_value (buf, 0);
742                 break;
743         case MONO_TYPE_GENERICINST:
744                 encode_generic_class (assembly, type->data.generic_class, buf);
745                 break;
746         case MONO_TYPE_VAR:
747         case MONO_TYPE_MVAR:
748                 sigbuffer_add_value (buf, type->type);
749                 sigbuffer_add_value (buf, mono_type_get_generic_param_num (type));
750                 break;
751         default:
752                 g_error ("need to encode type %x", type->type);
753         }
754 }
755
756 static void
757 encode_reflection_type (MonoDynamicImage *assembly, MonoReflectionType *type, SigBuffer *buf)
758 {
759         if (!type) {
760                 sigbuffer_add_value (buf, MONO_TYPE_VOID);
761                 return;
762         }
763
764         encode_type (assembly, mono_reflection_type_get_handle (type), buf);
765 }
766
767 static void
768 encode_custom_modifiers (MonoDynamicImage *assembly, MonoArray *modreq, MonoArray *modopt, SigBuffer *buf)
769 {
770         int i;
771
772         if (modreq) {
773                 for (i = 0; i < mono_array_length (modreq); ++i) {
774                         MonoType *mod = mono_type_array_get_and_resolve (modreq, i);
775                         sigbuffer_add_byte (buf, MONO_TYPE_CMOD_REQD);
776                         sigbuffer_add_value (buf, mono_image_typedef_or_ref (assembly, mod));
777                 }
778         }
779         if (modopt) {
780                 for (i = 0; i < mono_array_length (modopt); ++i) {
781                         MonoType *mod = mono_type_array_get_and_resolve (modopt, i);
782                         sigbuffer_add_byte (buf, MONO_TYPE_CMOD_OPT);
783                         sigbuffer_add_value (buf, mono_image_typedef_or_ref (assembly, mod));
784                 }
785         }
786 }
787
788 #ifndef DISABLE_REFLECTION_EMIT
789 static guint32
790 method_encode_signature (MonoDynamicImage *assembly, MonoMethodSignature *sig)
791 {
792         SigBuffer buf;
793         int i;
794         guint32 nparams =  sig->param_count;
795         guint32 idx;
796
797         if (!assembly->save)
798                 return 0;
799
800         sigbuffer_init (&buf, 32);
801         /*
802          * FIXME: vararg, explicit_this, differenc call_conv values...
803          */
804         idx = sig->call_convention;
805         if (sig->hasthis)
806                 idx |= 0x20; /* hasthis */
807         if (sig->generic_param_count)
808                 idx |= 0x10; /* generic */
809         sigbuffer_add_byte (&buf, idx);
810         if (sig->generic_param_count)
811                 sigbuffer_add_value (&buf, sig->generic_param_count);
812         sigbuffer_add_value (&buf, nparams);
813         encode_type (assembly, sig->ret, &buf);
814         for (i = 0; i < nparams; ++i) {
815                 if (i == sig->sentinelpos)
816                         sigbuffer_add_byte (&buf, MONO_TYPE_SENTINEL);
817                 encode_type (assembly, sig->params [i], &buf);
818         }
819         idx = sigbuffer_add_to_blob_cached (assembly, &buf);
820         sigbuffer_free (&buf);
821         return idx;
822 }
823 #endif
824
825 static guint32
826 method_builder_encode_signature (MonoDynamicImage *assembly, ReflectionMethodBuilder *mb)
827 {
828         /*
829          * FIXME: reuse code from method_encode_signature().
830          */
831         SigBuffer buf;
832         int i;
833         guint32 nparams =  mb->parameters ? mono_array_length (mb->parameters): 0;
834         guint32 ngparams = mb->generic_params ? mono_array_length (mb->generic_params): 0;
835         guint32 notypes = mb->opt_types ? mono_array_length (mb->opt_types): 0;
836         guint32 idx;
837
838         sigbuffer_init (&buf, 32);
839         /* LAMESPEC: all the call conv spec is foobared */
840         idx = mb->call_conv & 0x60; /* has-this, explicit-this */
841         if (mb->call_conv & 2)
842                 idx |= 0x5; /* vararg */
843         if (!(mb->attrs & METHOD_ATTRIBUTE_STATIC))
844                 idx |= 0x20; /* hasthis */
845         if (ngparams)
846                 idx |= 0x10; /* generic */
847         sigbuffer_add_byte (&buf, idx);
848         if (ngparams)
849                 sigbuffer_add_value (&buf, ngparams);
850         sigbuffer_add_value (&buf, nparams + notypes);
851         encode_custom_modifiers (assembly, mb->return_modreq, mb->return_modopt, &buf);
852         encode_reflection_type (assembly, mb->rtype, &buf);
853         for (i = 0; i < nparams; ++i) {
854                 MonoArray *modreq = NULL;
855                 MonoArray *modopt = NULL;
856                 MonoReflectionType *pt;
857
858                 if (mb->param_modreq && (i < mono_array_length (mb->param_modreq)))
859                         modreq = mono_array_get (mb->param_modreq, MonoArray*, i);
860                 if (mb->param_modopt && (i < mono_array_length (mb->param_modopt)))
861                         modopt = mono_array_get (mb->param_modopt, MonoArray*, i);
862                 encode_custom_modifiers (assembly, modreq, modopt, &buf);
863                 pt = mono_array_get (mb->parameters, MonoReflectionType*, i);
864                 encode_reflection_type (assembly, pt, &buf);
865         }
866         if (notypes)
867                 sigbuffer_add_byte (&buf, MONO_TYPE_SENTINEL);
868         for (i = 0; i < notypes; ++i) {
869                 MonoReflectionType *pt;
870
871                 pt = mono_array_get (mb->opt_types, MonoReflectionType*, i);
872                 encode_reflection_type (assembly, pt, &buf);
873         }
874
875         idx = sigbuffer_add_to_blob_cached (assembly, &buf);
876         sigbuffer_free (&buf);
877         return idx;
878 }
879
880 static guint32
881 encode_locals (MonoDynamicImage *assembly, MonoReflectionILGen *ilgen)
882 {
883         MonoDynamicTable *table;
884         guint32 *values;
885         guint32 idx, sig_idx;
886         guint nl = mono_array_length (ilgen->locals);
887         SigBuffer buf;
888         int i;
889
890         sigbuffer_init (&buf, 32);
891         sigbuffer_add_value (&buf, 0x07);
892         sigbuffer_add_value (&buf, nl);
893         for (i = 0; i < nl; ++i) {
894                 MonoReflectionLocalBuilder *lb = mono_array_get (ilgen->locals, MonoReflectionLocalBuilder*, i);
895                 
896                 if (lb->is_pinned)
897                         sigbuffer_add_value (&buf, MONO_TYPE_PINNED);
898                 
899                 encode_reflection_type (assembly, (MonoReflectionType*)lb->type, &buf);
900         }
901         sig_idx = sigbuffer_add_to_blob_cached (assembly, &buf);
902         sigbuffer_free (&buf);
903
904         if (assembly->standalonesig_cache == NULL)
905                 assembly->standalonesig_cache = g_hash_table_new (NULL, NULL);
906         idx = GPOINTER_TO_UINT (g_hash_table_lookup (assembly->standalonesig_cache, GUINT_TO_POINTER (sig_idx)));
907         if (idx)
908                 return idx;
909
910         table = &assembly->tables [MONO_TABLE_STANDALONESIG];
911         idx = table->next_idx ++;
912         table->rows ++;
913         alloc_table (table, table->rows);
914         values = table->values + idx * MONO_STAND_ALONE_SIGNATURE_SIZE;
915
916         values [MONO_STAND_ALONE_SIGNATURE] = sig_idx;
917
918         g_hash_table_insert (assembly->standalonesig_cache, GUINT_TO_POINTER (sig_idx), GUINT_TO_POINTER (idx));
919
920         return idx;
921 }
922
923 static guint32
924 method_count_clauses (MonoReflectionILGen *ilgen)
925 {
926         guint32 num_clauses = 0;
927         int i;
928
929         MonoILExceptionInfo *ex_info;
930         for (i = 0; i < mono_array_length (ilgen->ex_handlers); ++i) {
931                 ex_info = (MonoILExceptionInfo*)mono_array_addr (ilgen->ex_handlers, MonoILExceptionInfo, i);
932                 if (ex_info->handlers)
933                         num_clauses += mono_array_length (ex_info->handlers);
934                 else
935                         num_clauses++;
936         }
937
938         return num_clauses;
939 }
940
941 #ifndef DISABLE_REFLECTION_EMIT
942 static MonoExceptionClause*
943 method_encode_clauses (MonoImage *image, MonoDynamicImage *assembly, MonoReflectionILGen *ilgen, guint32 num_clauses)
944 {
945         MonoExceptionClause *clauses;
946         MonoExceptionClause *clause;
947         MonoILExceptionInfo *ex_info;
948         MonoILExceptionBlock *ex_block;
949         guint32 finally_start;
950         int i, j, clause_index;;
951
952         clauses = image_g_new0 (image, MonoExceptionClause, num_clauses);
953
954         clause_index = 0;
955         for (i = mono_array_length (ilgen->ex_handlers) - 1; i >= 0; --i) {
956                 ex_info = (MonoILExceptionInfo*)mono_array_addr (ilgen->ex_handlers, MonoILExceptionInfo, i);
957                 finally_start = ex_info->start + ex_info->len;
958                 if (!ex_info->handlers)
959                         continue;
960                 for (j = 0; j < mono_array_length (ex_info->handlers); ++j) {
961                         ex_block = (MonoILExceptionBlock*)mono_array_addr (ex_info->handlers, MonoILExceptionBlock, j);
962                         clause = &(clauses [clause_index]);
963
964                         clause->flags = ex_block->type;
965                         clause->try_offset = ex_info->start;
966
967                         if (ex_block->type == MONO_EXCEPTION_CLAUSE_FINALLY)
968                                 clause->try_len = finally_start - ex_info->start;
969                         else
970                                 clause->try_len = ex_info->len;
971                         clause->handler_offset = ex_block->start;
972                         clause->handler_len = ex_block->len;
973                         if (ex_block->extype) {
974                                 clause->data.catch_class = mono_class_from_mono_type (mono_reflection_type_get_handle ((MonoReflectionType*)ex_block->extype));
975                         } else {
976                                 if (ex_block->type == MONO_EXCEPTION_CLAUSE_FILTER)
977                                         clause->data.filter_offset = ex_block->filter_offset;
978                                 else
979                                         clause->data.filter_offset = 0;
980                         }
981                         finally_start = ex_block->start + ex_block->len;
982
983                         clause_index ++;
984                 }
985         }
986
987         return clauses;
988 }
989 #endif /* !DISABLE_REFLECTION_EMIT */
990
991 static guint32
992 method_encode_code (MonoDynamicImage *assembly, ReflectionMethodBuilder *mb)
993 {
994         char flags = 0;
995         guint32 idx;
996         guint32 code_size;
997         gint32 max_stack, i;
998         gint32 num_locals = 0;
999         gint32 num_exception = 0;
1000         gint maybe_small;
1001         guint32 fat_flags;
1002         char fat_header [12];
1003         guint32 int_value;
1004         guint16 short_value;
1005         guint32 local_sig = 0;
1006         guint32 header_size = 12;
1007         MonoArray *code;
1008
1009         if ((mb->attrs & (METHOD_ATTRIBUTE_PINVOKE_IMPL | METHOD_ATTRIBUTE_ABSTRACT)) ||
1010                         (mb->iattrs & (METHOD_IMPL_ATTRIBUTE_INTERNAL_CALL | METHOD_IMPL_ATTRIBUTE_RUNTIME)))
1011                 return 0;
1012
1013         /*if (mb->name)
1014                 g_print ("Encode method %s\n", mono_string_to_utf8 (mb->name));*/
1015         if (mb->ilgen) {
1016                 code = mb->ilgen->code;
1017                 code_size = mb->ilgen->code_len;
1018                 max_stack = mb->ilgen->max_stack;
1019                 num_locals = mb->ilgen->locals ? mono_array_length (mb->ilgen->locals) : 0;
1020                 if (mb->ilgen->ex_handlers)
1021                         num_exception = method_count_clauses (mb->ilgen);
1022         } else {
1023                 code = mb->code;
1024                 if (code == NULL){
1025                         char *name = mono_string_to_utf8 (mb->name);
1026                         char *str = g_strdup_printf ("Method %s does not have any IL associated", name);
1027                         MonoException *exception = mono_get_exception_argument (NULL, "a method does not have any IL associated");
1028                         g_free (str);
1029                         g_free (name);
1030                         mono_raise_exception (exception);
1031                 }
1032
1033                 code_size = mono_array_length (code);
1034                 max_stack = 8; /* we probably need to run a verifier on the code... */
1035         }
1036
1037         stream_data_align (&assembly->code);
1038
1039         /* check for exceptions, maxstack, locals */
1040         maybe_small = (max_stack <= 8) && (!num_locals) && (!num_exception);
1041         if (maybe_small) {
1042                 if (code_size < 64 && !(code_size & 1)) {
1043                         flags = (code_size << 2) | 0x2;
1044                 } else if (code_size < 32 && (code_size & 1)) {
1045                         flags = (code_size << 2) | 0x6; /* LAMESPEC: see metadata.c */
1046                 } else {
1047                         goto fat_header;
1048                 }
1049                 idx = mono_image_add_stream_data (&assembly->code, &flags, 1);
1050                 /* add to the fixup todo list */
1051                 if (mb->ilgen && mb->ilgen->num_token_fixups)
1052                         mono_g_hash_table_insert (assembly->token_fixups, mb->ilgen, GUINT_TO_POINTER (idx + 1));
1053                 mono_image_add_stream_data (&assembly->code, mono_array_addr (code, char, 0), code_size);
1054                 return assembly->text_rva + idx;
1055         } 
1056 fat_header:
1057         if (num_locals)
1058                 local_sig = MONO_TOKEN_SIGNATURE | encode_locals (assembly, mb->ilgen);
1059         /* 
1060          * FIXME: need to set also the header size in fat_flags.
1061          * (and more sects and init locals flags)
1062          */
1063         fat_flags =  0x03;
1064         if (num_exception)
1065                 fat_flags |= METHOD_HEADER_MORE_SECTS;
1066         if (mb->init_locals)
1067                 fat_flags |= METHOD_HEADER_INIT_LOCALS;
1068         fat_header [0] = fat_flags;
1069         fat_header [1] = (header_size / 4 ) << 4;
1070         short_value = GUINT16_TO_LE (max_stack);
1071         memcpy (fat_header + 2, &short_value, 2);
1072         int_value = GUINT32_TO_LE (code_size);
1073         memcpy (fat_header + 4, &int_value, 4);
1074         int_value = GUINT32_TO_LE (local_sig);
1075         memcpy (fat_header + 8, &int_value, 4);
1076         idx = mono_image_add_stream_data (&assembly->code, fat_header, 12);
1077         /* add to the fixup todo list */
1078         if (mb->ilgen && mb->ilgen->num_token_fixups)
1079                 mono_g_hash_table_insert (assembly->token_fixups, mb->ilgen, GUINT_TO_POINTER (idx + 12));
1080         
1081         mono_image_add_stream_data (&assembly->code, mono_array_addr (code, char, 0), code_size);
1082         if (num_exception) {
1083                 unsigned char sheader [4];
1084                 MonoILExceptionInfo * ex_info;
1085                 MonoILExceptionBlock * ex_block;
1086                 int j;
1087
1088                 stream_data_align (&assembly->code);
1089                 /* always use fat format for now */
1090                 sheader [0] = METHOD_HEADER_SECTION_FAT_FORMAT | METHOD_HEADER_SECTION_EHTABLE;
1091                 num_exception *= 6 * sizeof (guint32);
1092                 num_exception += 4; /* include the size of the header */
1093                 sheader [1] = num_exception & 0xff;
1094                 sheader [2] = (num_exception >> 8) & 0xff;
1095                 sheader [3] = (num_exception >> 16) & 0xff;
1096                 mono_image_add_stream_data (&assembly->code, (char*)sheader, 4);
1097                 /* fat header, so we are already aligned */
1098                 /* reverse order */
1099                 for (i = mono_array_length (mb->ilgen->ex_handlers) - 1; i >= 0; --i) {
1100                         ex_info = (MonoILExceptionInfo *)mono_array_addr (mb->ilgen->ex_handlers, MonoILExceptionInfo, i);
1101                         if (ex_info->handlers) {
1102                                 int finally_start = ex_info->start + ex_info->len;
1103                                 for (j = 0; j < mono_array_length (ex_info->handlers); ++j) {
1104                                         guint32 val;
1105                                         ex_block = (MonoILExceptionBlock*)mono_array_addr (ex_info->handlers, MonoILExceptionBlock, j);
1106                                         /* the flags */
1107                                         val = GUINT32_TO_LE (ex_block->type);
1108                                         mono_image_add_stream_data (&assembly->code, (char*)&val, sizeof (guint32));
1109                                         /* try offset */
1110                                         val = GUINT32_TO_LE (ex_info->start);
1111                                         mono_image_add_stream_data (&assembly->code, (char*)&val, sizeof (guint32));
1112                                         /* need fault, too, probably */
1113                                         if (ex_block->type == MONO_EXCEPTION_CLAUSE_FINALLY)
1114                                                 val = GUINT32_TO_LE (finally_start - ex_info->start);
1115                                         else
1116                                                 val = GUINT32_TO_LE (ex_info->len);
1117                                         mono_image_add_stream_data (&assembly->code, (char*)&val, sizeof (guint32));
1118                                         /* handler offset */
1119                                         val = GUINT32_TO_LE (ex_block->start);
1120                                         mono_image_add_stream_data (&assembly->code, (char*)&val, sizeof (guint32));
1121                                         /* handler len */
1122                                         val = GUINT32_TO_LE (ex_block->len);
1123                                         mono_image_add_stream_data (&assembly->code, (char*)&val, sizeof (guint32));
1124                                         finally_start = ex_block->start + ex_block->len;
1125                                         if (ex_block->extype) {
1126                                                 val = mono_metadata_token_from_dor (mono_image_typedef_or_ref (assembly, mono_reflection_type_get_handle ((MonoReflectionType*)ex_block->extype)));
1127                                         } else {
1128                                                 if (ex_block->type == MONO_EXCEPTION_CLAUSE_FILTER)
1129                                                         val = ex_block->filter_offset;
1130                                                 else
1131                                                         val = 0;
1132                                         }
1133                                         val = GUINT32_TO_LE (val);
1134                                         mono_image_add_stream_data (&assembly->code, (char*)&val, sizeof (guint32));
1135                                         /*g_print ("out clause %d: from %d len=%d, handler at %d, %d, finally_start=%d, ex_info->start=%d, ex_info->len=%d, ex_block->type=%d, j=%d, i=%d\n", 
1136                                                         clause.flags, clause.try_offset, clause.try_len, clause.handler_offset, clause.handler_len, finally_start, ex_info->start, ex_info->len, ex_block->type, j, i);*/
1137                                 }
1138                         } else {
1139                                 g_error ("No clauses for ex info block %d", i);
1140                         }
1141                 }
1142         }
1143         return assembly->text_rva + idx;
1144 }
1145
1146 static guint32
1147 find_index_in_table (MonoDynamicImage *assembly, int table_idx, int col, guint32 token)
1148 {
1149         int i;
1150         MonoDynamicTable *table;
1151         guint32 *values;
1152         
1153         table = &assembly->tables [table_idx];
1154
1155         g_assert (col < table->columns);
1156
1157         values = table->values + table->columns;
1158         for (i = 1; i <= table->rows; ++i) {
1159                 if (values [col] == token)
1160                         return i;
1161                 values += table->columns;
1162         }
1163         return 0;
1164 }
1165
1166 /*
1167  * LOCKING: Acquires the loader lock. 
1168  */
1169 static MonoCustomAttrInfo*
1170 lookup_custom_attr (MonoImage *image, gpointer member)
1171 {
1172         MonoCustomAttrInfo* res;
1173
1174         res = mono_image_property_lookup (image, member, MONO_PROP_DYNAMIC_CATTR);
1175
1176         if (!res)
1177                 return NULL;
1178
1179         res = g_memdup (res, MONO_SIZEOF_CUSTOM_ATTR_INFO + sizeof (MonoCustomAttrEntry) * res->num_attrs);
1180         res->cached = 0;
1181         return res;
1182 }
1183
1184 static gboolean
1185 custom_attr_visible (MonoImage *image, MonoReflectionCustomAttr *cattr)
1186 {
1187         /* FIXME: Need to do more checks */
1188         if (cattr->ctor->method && (cattr->ctor->method->klass->image != image)) {
1189                 int visibility = cattr->ctor->method->klass->flags & TYPE_ATTRIBUTE_VISIBILITY_MASK;
1190
1191                 if ((visibility != TYPE_ATTRIBUTE_PUBLIC) && (visibility != TYPE_ATTRIBUTE_NESTED_PUBLIC))
1192                         return FALSE;
1193         }
1194
1195         return TRUE;
1196 }
1197
1198 static MonoCustomAttrInfo*
1199 mono_custom_attrs_from_builders (MonoImage *alloc_img, MonoImage *image, MonoArray *cattrs)
1200 {
1201         int i, index, count, not_visible;
1202         MonoCustomAttrInfo *ainfo;
1203         MonoReflectionCustomAttr *cattr;
1204
1205         if (!cattrs)
1206                 return NULL;
1207         /* FIXME: check in assembly the Run flag is set */
1208
1209         count = mono_array_length (cattrs);
1210
1211         /* Skip nonpublic attributes since MS.NET seems to do the same */
1212         /* FIXME: This needs to be done more globally */
1213         not_visible = 0;
1214         for (i = 0; i < count; ++i) {
1215                 cattr = (MonoReflectionCustomAttr*)mono_array_get (cattrs, gpointer, i);
1216                 if (!custom_attr_visible (image, cattr))
1217                         not_visible ++;
1218         }
1219         count -= not_visible;
1220
1221         ainfo = image_g_malloc0 (alloc_img, MONO_SIZEOF_CUSTOM_ATTR_INFO + sizeof (MonoCustomAttrEntry) * count);
1222
1223         ainfo->image = image;
1224         ainfo->num_attrs = count;
1225         ainfo->cached = alloc_img != NULL;
1226         index = 0;
1227         for (i = 0; i < count; ++i) {
1228                 cattr = (MonoReflectionCustomAttr*)mono_array_get (cattrs, gpointer, i);
1229                 if (custom_attr_visible (image, cattr)) {
1230                         unsigned char *saved = mono_image_alloc (image, mono_array_length (cattr->data));
1231                         memcpy (saved, mono_array_addr (cattr->data, char, 0), mono_array_length (cattr->data));
1232                         ainfo->attrs [index].ctor = cattr->ctor->method;
1233                         ainfo->attrs [index].data = saved;
1234                         ainfo->attrs [index].data_size = mono_array_length (cattr->data);
1235                         index ++;
1236                 }
1237         }
1238
1239         return ainfo;
1240 }
1241
1242 #ifndef DISABLE_REFLECTION_EMIT
1243 /*
1244  * LOCKING: Acquires the loader lock. 
1245  */
1246 static void
1247 mono_save_custom_attrs (MonoImage *image, void *obj, MonoArray *cattrs)
1248 {
1249         MonoCustomAttrInfo *ainfo, *tmp;
1250
1251         if (!cattrs || !mono_array_length (cattrs))
1252                 return;
1253
1254         ainfo = mono_custom_attrs_from_builders (image, image, cattrs);
1255
1256         mono_loader_lock ();
1257         tmp = mono_image_property_lookup (image, obj, MONO_PROP_DYNAMIC_CATTR);
1258         if (tmp)
1259                 mono_custom_attrs_free (tmp);
1260         mono_image_property_insert (image, obj, MONO_PROP_DYNAMIC_CATTR, ainfo);
1261         mono_loader_unlock ();
1262
1263 }
1264 #endif
1265
1266 void
1267 mono_custom_attrs_free (MonoCustomAttrInfo *ainfo)
1268 {
1269         if (!ainfo->cached)
1270                 g_free (ainfo);
1271 }
1272
1273 /*
1274  * idx is the table index of the object
1275  * type is one of MONO_CUSTOM_ATTR_*
1276  */
1277 static void
1278 mono_image_add_cattrs (MonoDynamicImage *assembly, guint32 idx, guint32 type, MonoArray *cattrs)
1279 {
1280         MonoDynamicTable *table;
1281         MonoReflectionCustomAttr *cattr;
1282         guint32 *values;
1283         guint32 count, i, token;
1284         char blob_size [6];
1285         char *p = blob_size;
1286         
1287         /* it is legal to pass a NULL cattrs: we avoid to use the if in a lot of places */
1288         if (!cattrs)
1289                 return;
1290         count = mono_array_length (cattrs);
1291         table = &assembly->tables [MONO_TABLE_CUSTOMATTRIBUTE];
1292         table->rows += count;
1293         alloc_table (table, table->rows);
1294         values = table->values + table->next_idx * MONO_CUSTOM_ATTR_SIZE;
1295         idx <<= MONO_CUSTOM_ATTR_BITS;
1296         idx |= type;
1297         for (i = 0; i < count; ++i) {
1298                 cattr = (MonoReflectionCustomAttr*)mono_array_get (cattrs, gpointer, i);
1299                 values [MONO_CUSTOM_ATTR_PARENT] = idx;
1300                 token = mono_image_create_token (assembly, (MonoObject*)cattr->ctor, FALSE, FALSE);
1301                 type = mono_metadata_token_index (token);
1302                 type <<= MONO_CUSTOM_ATTR_TYPE_BITS;
1303                 switch (mono_metadata_token_table (token)) {
1304                 case MONO_TABLE_METHOD:
1305                         type |= MONO_CUSTOM_ATTR_TYPE_METHODDEF;
1306                         /*
1307                          * fixup_cattrs () needs to fix this up. We can't use image->tokens, since it contains the old token for the
1308                          * method, not the one returned by mono_image_create_token ().
1309                          */
1310                         mono_g_hash_table_insert (assembly->remapped_tokens, GUINT_TO_POINTER (token), cattr->ctor);
1311                         break;
1312                 case MONO_TABLE_MEMBERREF:
1313                         type |= MONO_CUSTOM_ATTR_TYPE_MEMBERREF;
1314                         break;
1315                 default:
1316                         g_warning ("got wrong token in custom attr");
1317                         continue;
1318                 }
1319                 values [MONO_CUSTOM_ATTR_TYPE] = type;
1320                 p = blob_size;
1321                 mono_metadata_encode_value (mono_array_length (cattr->data), p, &p);
1322                 values [MONO_CUSTOM_ATTR_VALUE] = add_to_blob_cached (assembly, blob_size, p - blob_size,
1323                         mono_array_addr (cattr->data, char, 0), mono_array_length (cattr->data));
1324                 values += MONO_CUSTOM_ATTR_SIZE;
1325                 ++table->next_idx;
1326         }
1327 }
1328
1329 static void
1330 mono_image_add_decl_security (MonoDynamicImage *assembly, guint32 parent_token, MonoArray *permissions)
1331 {
1332         MonoDynamicTable *table;
1333         guint32 *values;
1334         guint32 count, i, idx;
1335         MonoReflectionPermissionSet *perm;
1336
1337         if (!permissions)
1338                 return;
1339
1340         count = mono_array_length (permissions);
1341         table = &assembly->tables [MONO_TABLE_DECLSECURITY];
1342         table->rows += count;
1343         alloc_table (table, table->rows);
1344
1345         for (i = 0; i < mono_array_length (permissions); ++i) {
1346                 perm = (MonoReflectionPermissionSet*)mono_array_addr (permissions, MonoReflectionPermissionSet, i);
1347
1348                 values = table->values + table->next_idx * MONO_DECL_SECURITY_SIZE;
1349
1350                 idx = mono_metadata_token_index (parent_token);
1351                 idx <<= MONO_HAS_DECL_SECURITY_BITS;
1352                 switch (mono_metadata_token_table (parent_token)) {
1353                 case MONO_TABLE_TYPEDEF:
1354                         idx |= MONO_HAS_DECL_SECURITY_TYPEDEF;
1355                         break;
1356                 case MONO_TABLE_METHOD:
1357                         idx |= MONO_HAS_DECL_SECURITY_METHODDEF;
1358                         break;
1359                 case MONO_TABLE_ASSEMBLY:
1360                         idx |= MONO_HAS_DECL_SECURITY_ASSEMBLY;
1361                         break;
1362                 default:
1363                         g_assert_not_reached ();
1364                 }
1365
1366                 values [MONO_DECL_SECURITY_ACTION] = perm->action;
1367                 values [MONO_DECL_SECURITY_PARENT] = idx;
1368                 values [MONO_DECL_SECURITY_PERMISSIONSET] = add_mono_string_to_blob_cached (assembly, perm->pset);
1369
1370                 ++table->next_idx;
1371         }
1372 }
1373
1374 /*
1375  * Fill in the MethodDef and ParamDef tables for a method.
1376  * This is used for both normal methods and constructors.
1377  */
1378 static void
1379 mono_image_basic_method (ReflectionMethodBuilder *mb, MonoDynamicImage *assembly)
1380 {
1381         MonoDynamicTable *table;
1382         guint32 *values;
1383         guint i, count;
1384
1385         /* room in this table is already allocated */
1386         table = &assembly->tables [MONO_TABLE_METHOD];
1387         *mb->table_idx = table->next_idx ++;
1388         g_hash_table_insert (assembly->method_to_table_idx, mb->mhandle, GUINT_TO_POINTER ((*mb->table_idx)));
1389         values = table->values + *mb->table_idx * MONO_METHOD_SIZE;
1390         values [MONO_METHOD_NAME] = string_heap_insert_mstring (&assembly->sheap, mb->name);
1391         values [MONO_METHOD_FLAGS] = mb->attrs;
1392         values [MONO_METHOD_IMPLFLAGS] = mb->iattrs;
1393         values [MONO_METHOD_SIGNATURE] = method_builder_encode_signature (assembly, mb);
1394         values [MONO_METHOD_RVA] = method_encode_code (assembly, mb);
1395         
1396         table = &assembly->tables [MONO_TABLE_PARAM];
1397         values [MONO_METHOD_PARAMLIST] = table->next_idx;
1398
1399         mono_image_add_decl_security (assembly, 
1400                 mono_metadata_make_token (MONO_TABLE_METHOD, *mb->table_idx), mb->permissions);
1401
1402         if (mb->pinfo) {
1403                 MonoDynamicTable *mtable;
1404                 guint32 *mvalues;
1405                 
1406                 mtable = &assembly->tables [MONO_TABLE_FIELDMARSHAL];
1407                 mvalues = mtable->values + mtable->next_idx * MONO_FIELD_MARSHAL_SIZE;
1408                 
1409                 count = 0;
1410                 for (i = 0; i < mono_array_length (mb->pinfo); ++i) {
1411                         if (mono_array_get (mb->pinfo, gpointer, i))
1412                                 count++;
1413                 }
1414                 table->rows += count;
1415                 alloc_table (table, table->rows);
1416                 values = table->values + table->next_idx * MONO_PARAM_SIZE;
1417                 for (i = 0; i < mono_array_length (mb->pinfo); ++i) {
1418                         MonoReflectionParamBuilder *pb;
1419                         if ((pb = mono_array_get (mb->pinfo, MonoReflectionParamBuilder*, i))) {
1420                                 values [MONO_PARAM_FLAGS] = pb->attrs;
1421                                 values [MONO_PARAM_SEQUENCE] = i;
1422                                 if (pb->name != NULL) {
1423                                         values [MONO_PARAM_NAME] = string_heap_insert_mstring (&assembly->sheap, pb->name);
1424                                 } else {
1425                                         values [MONO_PARAM_NAME] = 0;
1426                                 }
1427                                 values += MONO_PARAM_SIZE;
1428                                 if (pb->marshal_info) {
1429                                         mtable->rows++;
1430                                         alloc_table (mtable, mtable->rows);
1431                                         mvalues = mtable->values + mtable->rows * MONO_FIELD_MARSHAL_SIZE;
1432                                         mvalues [MONO_FIELD_MARSHAL_PARENT] = (table->next_idx << MONO_HAS_FIELD_MARSHAL_BITS) | MONO_HAS_FIELD_MARSHAL_PARAMDEF;
1433                                         mvalues [MONO_FIELD_MARSHAL_NATIVE_TYPE] = encode_marshal_blob (assembly, pb->marshal_info);
1434                                 }
1435                                 pb->table_idx = table->next_idx++;
1436                                 if (pb->attrs & PARAM_ATTRIBUTE_HAS_DEFAULT) {
1437                                         guint32 field_type = 0;
1438                                         mtable = &assembly->tables [MONO_TABLE_CONSTANT];
1439                                         mtable->rows ++;
1440                                         alloc_table (mtable, mtable->rows);
1441                                         mvalues = mtable->values + mtable->rows * MONO_CONSTANT_SIZE;
1442                                         mvalues [MONO_CONSTANT_PARENT] = MONO_HASCONSTANT_PARAM | (pb->table_idx << MONO_HASCONSTANT_BITS);
1443                                         mvalues [MONO_CONSTANT_VALUE] = encode_constant (assembly, pb->def_value, &field_type);
1444                                         mvalues [MONO_CONSTANT_TYPE] = field_type;
1445                                         mvalues [MONO_CONSTANT_PADDING] = 0;
1446                                 }
1447                         }
1448                 }
1449         }
1450 }
1451
1452 #ifndef DISABLE_REFLECTION_EMIT
1453 static void
1454 reflection_methodbuilder_from_method_builder (ReflectionMethodBuilder *rmb, MonoReflectionMethodBuilder *mb)
1455 {
1456         memset (rmb, 0, sizeof (ReflectionMethodBuilder));
1457
1458         rmb->ilgen = mb->ilgen;
1459         rmb->rtype = mono_reflection_type_resolve_user_types ((MonoReflectionType*)mb->rtype);
1460         rmb->parameters = mb->parameters;
1461         rmb->generic_params = mb->generic_params;
1462         rmb->generic_container = mb->generic_container;
1463         rmb->opt_types = NULL;
1464         rmb->pinfo = mb->pinfo;
1465         rmb->attrs = mb->attrs;
1466         rmb->iattrs = mb->iattrs;
1467         rmb->call_conv = mb->call_conv;
1468         rmb->code = mb->code;
1469         rmb->type = mb->type;
1470         rmb->name = mb->name;
1471         rmb->table_idx = &mb->table_idx;
1472         rmb->init_locals = mb->init_locals;
1473         rmb->skip_visibility = FALSE;
1474         rmb->return_modreq = mb->return_modreq;
1475         rmb->return_modopt = mb->return_modopt;
1476         rmb->param_modreq = mb->param_modreq;
1477         rmb->param_modopt = mb->param_modopt;
1478         rmb->permissions = mb->permissions;
1479         rmb->mhandle = mb->mhandle;
1480         rmb->nrefs = 0;
1481         rmb->refs = NULL;
1482
1483         if (mb->dll) {
1484                 rmb->charset = mb->charset;
1485                 rmb->extra_flags = mb->extra_flags;
1486                 rmb->native_cc = mb->native_cc;
1487                 rmb->dllentry = mb->dllentry;
1488                 rmb->dll = mb->dll;
1489         }
1490 }
1491
1492 static void
1493 reflection_methodbuilder_from_ctor_builder (ReflectionMethodBuilder *rmb, MonoReflectionCtorBuilder *mb)
1494 {
1495         const char *name = mb->attrs & METHOD_ATTRIBUTE_STATIC ? ".cctor": ".ctor";
1496
1497         memset (rmb, 0, sizeof (ReflectionMethodBuilder));
1498
1499         rmb->ilgen = mb->ilgen;
1500         rmb->rtype = mono_type_get_object (mono_domain_get (), &mono_defaults.void_class->byval_arg);
1501         rmb->parameters = mb->parameters;
1502         rmb->generic_params = NULL;
1503         rmb->generic_container = NULL;
1504         rmb->opt_types = NULL;
1505         rmb->pinfo = mb->pinfo;
1506         rmb->attrs = mb->attrs;
1507         rmb->iattrs = mb->iattrs;
1508         rmb->call_conv = mb->call_conv;
1509         rmb->code = NULL;
1510         rmb->type = mb->type;
1511         rmb->name = mono_string_new (mono_domain_get (), name);
1512         rmb->table_idx = &mb->table_idx;
1513         rmb->init_locals = mb->init_locals;
1514         rmb->skip_visibility = FALSE;
1515         rmb->return_modreq = NULL;
1516         rmb->return_modopt = NULL;
1517         rmb->param_modreq = mb->param_modreq;
1518         rmb->param_modopt = mb->param_modopt;
1519         rmb->permissions = mb->permissions;
1520         rmb->mhandle = mb->mhandle;
1521         rmb->nrefs = 0;
1522         rmb->refs = NULL;
1523 }
1524
1525 static void
1526 reflection_methodbuilder_from_dynamic_method (ReflectionMethodBuilder *rmb, MonoReflectionDynamicMethod *mb)
1527 {
1528         memset (rmb, 0, sizeof (ReflectionMethodBuilder));
1529
1530         rmb->ilgen = mb->ilgen;
1531         rmb->rtype = mb->rtype;
1532         rmb->parameters = mb->parameters;
1533         rmb->generic_params = NULL;
1534         rmb->generic_container = NULL;
1535         rmb->opt_types = NULL;
1536         rmb->pinfo = NULL;
1537         rmb->attrs = mb->attrs;
1538         rmb->iattrs = 0;
1539         rmb->call_conv = mb->call_conv;
1540         rmb->code = NULL;
1541         rmb->type = (MonoObject *) mb->owner;
1542         rmb->name = mb->name;
1543         rmb->table_idx = NULL;
1544         rmb->init_locals = mb->init_locals;
1545         rmb->skip_visibility = mb->skip_visibility;
1546         rmb->return_modreq = NULL;
1547         rmb->return_modopt = NULL;
1548         rmb->param_modreq = NULL;
1549         rmb->param_modopt = NULL;
1550         rmb->permissions = NULL;
1551         rmb->mhandle = mb->mhandle;
1552         rmb->nrefs = 0;
1553         rmb->refs = NULL;
1554 }       
1555 #endif
1556
1557 static void
1558 mono_image_add_methodimpl (MonoDynamicImage *assembly, MonoReflectionMethodBuilder *mb)
1559 {
1560         MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder *)mb->type;
1561         MonoDynamicTable *table;
1562         guint32 *values;
1563         guint32 tok;
1564         MonoReflectionMethod *m;
1565         int i;
1566
1567         if (!mb->override_methods)
1568                 return;
1569
1570         for (i = 0; i < mono_array_length (mb->override_methods); ++i) {
1571                 m = mono_array_get (mb->override_methods, MonoReflectionMethod*, i);
1572
1573                 table = &assembly->tables [MONO_TABLE_METHODIMPL];
1574                 table->rows ++;
1575                 alloc_table (table, table->rows);
1576                 values = table->values + table->rows * MONO_METHODIMPL_SIZE;
1577                 values [MONO_METHODIMPL_CLASS] = tb->table_idx;
1578                 values [MONO_METHODIMPL_BODY] = MONO_METHODDEFORREF_METHODDEF | (mb->table_idx << MONO_METHODDEFORREF_BITS);
1579
1580                 tok = mono_image_create_token (assembly, (MonoObject*)m, FALSE, FALSE);
1581                 switch (mono_metadata_token_table (tok)) {
1582                 case MONO_TABLE_MEMBERREF:
1583                         tok = (mono_metadata_token_index (tok) << MONO_METHODDEFORREF_BITS ) | MONO_METHODDEFORREF_METHODREF;
1584                         break;
1585                 case MONO_TABLE_METHOD:
1586                         tok = (mono_metadata_token_index (tok) << MONO_METHODDEFORREF_BITS ) | MONO_METHODDEFORREF_METHODDEF;
1587                         break;
1588                 default:
1589                         g_assert_not_reached ();
1590                 }
1591                 values [MONO_METHODIMPL_DECLARATION] = tok;
1592         }
1593 }
1594
1595 #ifndef DISABLE_REFLECTION_EMIT
1596 static void
1597 mono_image_get_method_info (MonoReflectionMethodBuilder *mb, MonoDynamicImage *assembly)
1598 {
1599         MonoDynamicTable *table;
1600         guint32 *values;
1601         ReflectionMethodBuilder rmb;
1602         int i;
1603
1604         reflection_methodbuilder_from_method_builder (&rmb, mb);
1605
1606         mono_image_basic_method (&rmb, assembly);
1607         mb->table_idx = *rmb.table_idx;
1608
1609         if (mb->dll) { /* It's a P/Invoke method */
1610                 guint32 moduleref;
1611                 /* map CharSet values to on-disk values */
1612                 int ncharset = (mb->charset ? (mb->charset - 1) * 2 : 0);
1613                 int extra_flags = mb->extra_flags;
1614                 table = &assembly->tables [MONO_TABLE_IMPLMAP];
1615                 table->rows ++;
1616                 alloc_table (table, table->rows);
1617                 values = table->values + table->rows * MONO_IMPLMAP_SIZE;
1618                 
1619                 values [MONO_IMPLMAP_FLAGS] = (mb->native_cc << 8) | ncharset | extra_flags;
1620                 values [MONO_IMPLMAP_MEMBER] = (mb->table_idx << 1) | 1; /* memberforwarded: method */
1621                 if (mb->dllentry)
1622                         values [MONO_IMPLMAP_NAME] = string_heap_insert_mstring (&assembly->sheap, mb->dllentry);
1623                 else
1624                         values [MONO_IMPLMAP_NAME] = string_heap_insert_mstring (&assembly->sheap, mb->name);
1625                 moduleref = string_heap_insert_mstring (&assembly->sheap, mb->dll);
1626                 if (!(values [MONO_IMPLMAP_SCOPE] = find_index_in_table (assembly, MONO_TABLE_MODULEREF, MONO_MODULEREF_NAME, moduleref))) {
1627                         table = &assembly->tables [MONO_TABLE_MODULEREF];
1628                         table->rows ++;
1629                         alloc_table (table, table->rows);
1630                         table->values [table->rows * MONO_MODULEREF_SIZE + MONO_MODULEREF_NAME] = moduleref;
1631                         values [MONO_IMPLMAP_SCOPE] = table->rows;
1632                 }
1633         }
1634
1635         if (mb->generic_params) {
1636                 table = &assembly->tables [MONO_TABLE_GENERICPARAM];
1637                 table->rows += mono_array_length (mb->generic_params);
1638                 alloc_table (table, table->rows);
1639                 for (i = 0; i < mono_array_length (mb->generic_params); ++i) {
1640                         guint32 owner = MONO_TYPEORMETHOD_METHOD | (mb->table_idx << MONO_TYPEORMETHOD_BITS);
1641
1642                         mono_image_get_generic_param_info (
1643                                 mono_array_get (mb->generic_params, gpointer, i), owner, assembly);
1644                 }
1645         }
1646
1647 }
1648
1649 static void
1650 mono_image_get_ctor_info (MonoDomain *domain, MonoReflectionCtorBuilder *mb, MonoDynamicImage *assembly)
1651 {
1652         ReflectionMethodBuilder rmb;
1653
1654         reflection_methodbuilder_from_ctor_builder (&rmb, mb);
1655
1656         mono_image_basic_method (&rmb, assembly);
1657         mb->table_idx = *rmb.table_idx;
1658 }
1659 #endif
1660
1661 static char*
1662 type_get_fully_qualified_name (MonoType *type)
1663 {
1664         return mono_type_get_name_full (type, MONO_TYPE_NAME_FORMAT_ASSEMBLY_QUALIFIED);
1665 }
1666
1667 static char*
1668 type_get_qualified_name (MonoType *type, MonoAssembly *ass) {
1669         MonoClass *klass;
1670         MonoAssembly *ta;
1671
1672         klass = mono_class_from_mono_type (type);
1673         if (!klass) 
1674                 return mono_type_get_name_full (type, MONO_TYPE_NAME_FORMAT_REFLECTION);
1675         ta = klass->image->assembly;
1676         if (ta->dynamic || (ta == ass)) {
1677                 if (klass->generic_class || klass->generic_container)
1678                         /* For generic type definitions, we want T, while REFLECTION returns T<K> */
1679                         return mono_type_get_name_full (type, MONO_TYPE_NAME_FORMAT_FULL_NAME);
1680                 else
1681                         return mono_type_get_name_full (type, MONO_TYPE_NAME_FORMAT_REFLECTION);
1682         }
1683
1684         return mono_type_get_name_full (type, MONO_TYPE_NAME_FORMAT_ASSEMBLY_QUALIFIED);
1685 }
1686
1687 #ifndef DISABLE_REFLECTION_EMIT
1688 /*field_image is the image to which the eventual custom mods have been encoded against*/
1689 static guint32
1690 fieldref_encode_signature (MonoDynamicImage *assembly, MonoImage *field_image, MonoType *type)
1691 {
1692         SigBuffer buf;
1693         guint32 idx, i, token;
1694
1695         if (!assembly->save)
1696                 return 0;
1697
1698         sigbuffer_init (&buf, 32);
1699         
1700         sigbuffer_add_value (&buf, 0x06);
1701         /* encode custom attributes before the type */
1702         if (type->num_mods) {
1703                 for (i = 0; i < type->num_mods; ++i) {
1704                         if (field_image) {
1705                                 MonoClass *class = mono_class_get (field_image, type->modifiers [i].token);
1706                                 g_assert (class);
1707                                 token = mono_image_typedef_or_ref (assembly, &class->byval_arg);
1708                         } else {
1709                                 token = type->modifiers [i].token;
1710                         }
1711
1712                         if (type->modifiers [i].required)
1713                                 sigbuffer_add_byte (&buf, MONO_TYPE_CMOD_REQD);
1714                         else
1715                                 sigbuffer_add_byte (&buf, MONO_TYPE_CMOD_OPT);
1716
1717                         sigbuffer_add_value (&buf, token);
1718                 }
1719         }
1720         encode_type (assembly, type, &buf);
1721         idx = sigbuffer_add_to_blob_cached (assembly, &buf);
1722         sigbuffer_free (&buf);
1723         return idx;
1724 }
1725 #endif
1726
1727 static guint32
1728 field_encode_signature (MonoDynamicImage *assembly, MonoReflectionFieldBuilder *fb)
1729 {
1730         SigBuffer buf;
1731         guint32 idx;
1732         guint32 typespec = 0;
1733         MonoType *type;
1734         MonoClass *class;
1735
1736         init_type_builder_generics (fb->type);
1737
1738         type = mono_reflection_type_get_handle ((MonoReflectionType*)fb->type);
1739         class = mono_class_from_mono_type (type);
1740
1741         sigbuffer_init (&buf, 32);
1742         
1743         sigbuffer_add_value (&buf, 0x06);
1744         encode_custom_modifiers (assembly, fb->modreq, fb->modopt, &buf);
1745         /* encode custom attributes before the type */
1746
1747         if (class->generic_container)
1748                 typespec = create_typespec (assembly, type);
1749
1750         if (typespec) {
1751                 MonoGenericClass *gclass;
1752                 gclass = mono_metadata_lookup_generic_class (class, class->generic_container->context.class_inst, TRUE);
1753                 encode_generic_class (assembly, gclass, &buf);
1754         } else {
1755                 encode_type (assembly, type, &buf);
1756         }
1757         idx = sigbuffer_add_to_blob_cached (assembly, &buf);
1758         sigbuffer_free (&buf);
1759         return idx;
1760 }
1761
1762 static guint32
1763 encode_constant (MonoDynamicImage *assembly, MonoObject *val, guint32 *ret_type) {
1764         char blob_size [64];
1765         char *b = blob_size;
1766         char *p, *box_val;
1767         char* buf;
1768         guint32 idx = 0, len = 0, dummy = 0;
1769
1770         p = buf = g_malloc (64);
1771         if (!val) {
1772                 *ret_type = MONO_TYPE_CLASS;
1773                 len = 4;
1774                 box_val = (char*)&dummy;
1775         } else {
1776                 box_val = ((char*)val) + sizeof (MonoObject);
1777                 *ret_type = val->vtable->klass->byval_arg.type;
1778         }
1779 handle_enum:
1780         switch (*ret_type) {
1781         case MONO_TYPE_BOOLEAN:
1782         case MONO_TYPE_U1:
1783         case MONO_TYPE_I1:
1784                 len = 1;
1785                 break;
1786         case MONO_TYPE_CHAR:
1787         case MONO_TYPE_U2:
1788         case MONO_TYPE_I2:
1789                 len = 2;
1790                 break;
1791         case MONO_TYPE_U4:
1792         case MONO_TYPE_I4:
1793         case MONO_TYPE_R4:
1794                 len = 4;
1795                 break;
1796         case MONO_TYPE_U8:
1797         case MONO_TYPE_I8:
1798                 len = 8;
1799                 break;
1800         case MONO_TYPE_R8:
1801                 len = 8;
1802                 break;
1803         case MONO_TYPE_VALUETYPE: {
1804                 MonoClass *klass = val->vtable->klass;
1805                 
1806                 if (klass->enumtype) {
1807                         *ret_type = mono_class_enum_basetype (klass)->type;
1808                         goto handle_enum;
1809                 } else if (mono_is_corlib_image (klass->image) && strcmp (klass->name_space, "System") == 0 && strcmp (klass->name, "DateTime") == 0) {
1810                         len = 8;
1811                 } else 
1812                         g_error ("we can't encode valuetypes, we should have never reached this line");
1813                 break;
1814         }
1815         case MONO_TYPE_CLASS:
1816                 break;
1817         case MONO_TYPE_STRING: {
1818                 MonoString *str = (MonoString*)val;
1819                 /* there is no signature */
1820                 len = str->length * 2;
1821                 mono_metadata_encode_value (len, b, &b);
1822 #if G_BYTE_ORDER != G_LITTLE_ENDIAN
1823                 {
1824                         char *swapped = g_malloc (2 * mono_string_length (str));
1825                         const char *p = (const char*)mono_string_chars (str);
1826
1827                         swap_with_size (swapped, p, 2, mono_string_length (str));
1828                         idx = add_to_blob_cached (assembly, blob_size, b-blob_size, swapped, len);
1829                         g_free (swapped);
1830                 }
1831 #else
1832                 idx = add_to_blob_cached (assembly, blob_size, b-blob_size, (char*)mono_string_chars (str), len);
1833 #endif
1834
1835                 g_free (buf);
1836                 return idx;
1837         }
1838         case MONO_TYPE_GENERICINST:
1839                 *ret_type = val->vtable->klass->generic_class->container_class->byval_arg.type;
1840                 goto handle_enum;
1841         default:
1842                 g_error ("we don't encode constant type 0x%02x yet", *ret_type);
1843         }
1844
1845         /* there is no signature */
1846         mono_metadata_encode_value (len, b, &b);
1847 #if G_BYTE_ORDER != G_LITTLE_ENDIAN
1848         idx = mono_image_add_stream_data (&assembly->blob, blob_size, b-blob_size);
1849         swap_with_size (blob_size, box_val, len, 1);
1850         mono_image_add_stream_data (&assembly->blob, blob_size, len);
1851 #else
1852         idx = add_to_blob_cached (assembly, blob_size, b-blob_size, box_val, len);
1853 #endif
1854
1855         g_free (buf);
1856         return idx;
1857 }
1858
1859 static guint32
1860 encode_marshal_blob (MonoDynamicImage *assembly, MonoReflectionMarshal *minfo) {
1861         char *str;
1862         SigBuffer buf;
1863         guint32 idx, len;
1864
1865         sigbuffer_init (&buf, 32);
1866
1867         sigbuffer_add_value (&buf, minfo->type);
1868
1869         switch (minfo->type) {
1870         case MONO_NATIVE_BYVALTSTR:
1871         case MONO_NATIVE_BYVALARRAY:
1872                 sigbuffer_add_value (&buf, minfo->count);
1873                 break;
1874         case MONO_NATIVE_LPARRAY:
1875                 if (minfo->eltype || minfo->has_size) {
1876                         sigbuffer_add_value (&buf, minfo->eltype);
1877                         if (minfo->has_size) {
1878                                 sigbuffer_add_value (&buf, minfo->param_num != -1? minfo->param_num: 0);
1879                                 sigbuffer_add_value (&buf, minfo->count != -1? minfo->count: 0);
1880
1881                                 /* LAMESPEC: ElemMult is undocumented */
1882                                 sigbuffer_add_value (&buf, minfo->param_num != -1? 1: 0);
1883                         }
1884                 }
1885                 break;
1886         case MONO_NATIVE_SAFEARRAY:
1887                 if (minfo->eltype)
1888                         sigbuffer_add_value (&buf, minfo->eltype);
1889                 break;
1890         case MONO_NATIVE_CUSTOM:
1891                 if (minfo->guid) {
1892                         str = mono_string_to_utf8 (minfo->guid);
1893                         len = strlen (str);
1894                         sigbuffer_add_value (&buf, len);
1895                         sigbuffer_add_mem (&buf, str, len);
1896                         g_free (str);
1897                 } else {
1898                         sigbuffer_add_value (&buf, 0);
1899                 }
1900                 /* native type name */
1901                 sigbuffer_add_value (&buf, 0);
1902                 /* custom marshaler type name */
1903                 if (minfo->marshaltype || minfo->marshaltyperef) {
1904                         if (minfo->marshaltyperef)
1905                                 str = type_get_fully_qualified_name (mono_reflection_type_get_handle ((MonoReflectionType*)minfo->marshaltyperef));
1906                         else
1907                                 str = mono_string_to_utf8 (minfo->marshaltype);
1908                         len = strlen (str);
1909                         sigbuffer_add_value (&buf, len);
1910                         sigbuffer_add_mem (&buf, str, len);
1911                         g_free (str);
1912                 } else {
1913                         /* FIXME: Actually a bug, since this field is required.  Punting for now ... */
1914                         sigbuffer_add_value (&buf, 0);
1915                 }
1916                 if (minfo->mcookie) {
1917                         str = mono_string_to_utf8 (minfo->mcookie);
1918                         len = strlen (str);
1919                         sigbuffer_add_value (&buf, len);
1920                         sigbuffer_add_mem (&buf, str, len);
1921                         g_free (str);
1922                 } else {
1923                         sigbuffer_add_value (&buf, 0);
1924                 }
1925                 break;
1926         default:
1927                 break;
1928         }
1929         idx = sigbuffer_add_to_blob_cached (assembly, &buf);
1930         sigbuffer_free (&buf);
1931         return idx;
1932 }
1933
1934 static void
1935 mono_image_get_field_info (MonoReflectionFieldBuilder *fb, MonoDynamicImage *assembly)
1936 {
1937         MonoDynamicTable *table;
1938         guint32 *values;
1939
1940         /* maybe this fixup should be done in the C# code */
1941         if (fb->attrs & FIELD_ATTRIBUTE_LITERAL)
1942                 fb->attrs |= FIELD_ATTRIBUTE_HAS_DEFAULT;
1943         table = &assembly->tables [MONO_TABLE_FIELD];
1944         fb->table_idx = table->next_idx ++;
1945         g_hash_table_insert (assembly->field_to_table_idx, fb->handle, GUINT_TO_POINTER (fb->table_idx));
1946         values = table->values + fb->table_idx * MONO_FIELD_SIZE;
1947         values [MONO_FIELD_NAME] = string_heap_insert_mstring (&assembly->sheap, fb->name);
1948         values [MONO_FIELD_FLAGS] = fb->attrs;
1949         values [MONO_FIELD_SIGNATURE] = field_encode_signature (assembly, fb);
1950
1951         if (fb->offset != -1) {
1952                 table = &assembly->tables [MONO_TABLE_FIELDLAYOUT];
1953                 table->rows ++;
1954                 alloc_table (table, table->rows);
1955                 values = table->values + table->rows * MONO_FIELD_LAYOUT_SIZE;
1956                 values [MONO_FIELD_LAYOUT_FIELD] = fb->table_idx;
1957                 values [MONO_FIELD_LAYOUT_OFFSET] = fb->offset;
1958         }
1959         if (fb->attrs & FIELD_ATTRIBUTE_LITERAL) {
1960                 guint32 field_type = 0;
1961                 table = &assembly->tables [MONO_TABLE_CONSTANT];
1962                 table->rows ++;
1963                 alloc_table (table, table->rows);
1964                 values = table->values + table->rows * MONO_CONSTANT_SIZE;
1965                 values [MONO_CONSTANT_PARENT] = MONO_HASCONSTANT_FIEDDEF | (fb->table_idx << MONO_HASCONSTANT_BITS);
1966                 values [MONO_CONSTANT_VALUE] = encode_constant (assembly, fb->def_value, &field_type);
1967                 values [MONO_CONSTANT_TYPE] = field_type;
1968                 values [MONO_CONSTANT_PADDING] = 0;
1969         }
1970         if (fb->attrs & FIELD_ATTRIBUTE_HAS_FIELD_RVA) {
1971                 guint32 rva_idx;
1972                 table = &assembly->tables [MONO_TABLE_FIELDRVA];
1973                 table->rows ++;
1974                 alloc_table (table, table->rows);
1975                 values = table->values + table->rows * MONO_FIELD_RVA_SIZE;
1976                 values [MONO_FIELD_RVA_FIELD] = fb->table_idx;
1977                 /*
1978                  * We store it in the code section because it's simpler for now.
1979                  */
1980                 if (fb->rva_data) {
1981                         if (mono_array_length (fb->rva_data) >= 10)
1982                                 stream_data_align (&assembly->code);
1983                         rva_idx = mono_image_add_stream_data (&assembly->code, mono_array_addr (fb->rva_data, char, 0), mono_array_length (fb->rva_data));
1984                 } else
1985                         rva_idx = mono_image_add_stream_zero (&assembly->code, mono_class_value_size (fb->handle->parent, NULL));
1986                 values [MONO_FIELD_RVA_RVA] = rva_idx + assembly->text_rva;
1987         }
1988         if (fb->marshal_info) {
1989                 table = &assembly->tables [MONO_TABLE_FIELDMARSHAL];
1990                 table->rows ++;
1991                 alloc_table (table, table->rows);
1992                 values = table->values + table->rows * MONO_FIELD_MARSHAL_SIZE;
1993                 values [MONO_FIELD_MARSHAL_PARENT] = (fb->table_idx << MONO_HAS_FIELD_MARSHAL_BITS) | MONO_HAS_FIELD_MARSHAL_FIELDSREF;
1994                 values [MONO_FIELD_MARSHAL_NATIVE_TYPE] = encode_marshal_blob (assembly, fb->marshal_info);
1995         }
1996 }
1997
1998 static guint32
1999 property_encode_signature (MonoDynamicImage *assembly, MonoReflectionPropertyBuilder *fb)
2000 {
2001         SigBuffer buf;
2002         guint32 nparams = 0;
2003         MonoReflectionMethodBuilder *mb = fb->get_method;
2004         MonoReflectionMethodBuilder *smb = fb->set_method;
2005         guint32 idx, i;
2006
2007         if (mb && mb->parameters)
2008                 nparams = mono_array_length (mb->parameters);
2009         if (!mb && smb && smb->parameters)
2010                 nparams = mono_array_length (smb->parameters) - 1;
2011         sigbuffer_init (&buf, 32);
2012         if (fb->call_conv & 0x20)
2013                 sigbuffer_add_byte (&buf, 0x28);
2014         else
2015                 sigbuffer_add_byte (&buf, 0x08);
2016         sigbuffer_add_value (&buf, nparams);
2017         if (mb) {
2018                 encode_reflection_type (assembly, (MonoReflectionType*)mb->rtype, &buf);
2019                 for (i = 0; i < nparams; ++i) {
2020                         MonoReflectionType *pt = mono_array_get (mb->parameters, MonoReflectionType*, i);
2021                         encode_reflection_type (assembly, pt, &buf);
2022                 }
2023         } else if (smb && smb->parameters) {
2024                 /* the property type is the last param */
2025                 encode_reflection_type (assembly, mono_array_get (smb->parameters, MonoReflectionType*, nparams), &buf);
2026                 for (i = 0; i < nparams; ++i) {
2027                         MonoReflectionType *pt = mono_array_get (smb->parameters, MonoReflectionType*, i);
2028                         encode_reflection_type (assembly, pt, &buf);
2029                 }
2030         } else {
2031                 encode_reflection_type (assembly, (MonoReflectionType*)fb->type, &buf);
2032         }
2033
2034         idx = sigbuffer_add_to_blob_cached (assembly, &buf);
2035         sigbuffer_free (&buf);
2036         return idx;
2037 }
2038
2039 static void
2040 mono_image_get_property_info (MonoReflectionPropertyBuilder *pb, MonoDynamicImage *assembly)
2041 {
2042         MonoDynamicTable *table;
2043         guint32 *values;
2044         guint num_methods = 0;
2045         guint32 semaidx;
2046
2047         /* 
2048          * we need to set things in the following tables:
2049          * PROPERTYMAP (info already filled in _get_type_info ())
2050          * PROPERTY    (rows already preallocated in _get_type_info ())
2051          * METHOD      (method info already done with the generic method code)
2052          * METHODSEMANTICS
2053          * CONSTANT
2054          */
2055         table = &assembly->tables [MONO_TABLE_PROPERTY];
2056         pb->table_idx = table->next_idx ++;
2057         values = table->values + pb->table_idx * MONO_PROPERTY_SIZE;
2058         values [MONO_PROPERTY_NAME] = string_heap_insert_mstring (&assembly->sheap, pb->name);
2059         values [MONO_PROPERTY_FLAGS] = pb->attrs;
2060         values [MONO_PROPERTY_TYPE] = property_encode_signature (assembly, pb);
2061
2062         /* FIXME: we still don't handle 'other' methods */
2063         if (pb->get_method) num_methods ++;
2064         if (pb->set_method) num_methods ++;
2065
2066         table = &assembly->tables [MONO_TABLE_METHODSEMANTICS];
2067         table->rows += num_methods;
2068         alloc_table (table, table->rows);
2069
2070         if (pb->get_method) {
2071                 semaidx = table->next_idx ++;
2072                 values = table->values + semaidx * MONO_METHOD_SEMA_SIZE;
2073                 values [MONO_METHOD_SEMA_SEMANTICS] = METHOD_SEMANTIC_GETTER;
2074                 values [MONO_METHOD_SEMA_METHOD] = pb->get_method->table_idx;
2075                 values [MONO_METHOD_SEMA_ASSOCIATION] = (pb->table_idx << MONO_HAS_SEMANTICS_BITS) | MONO_HAS_SEMANTICS_PROPERTY;
2076         }
2077         if (pb->set_method) {
2078                 semaidx = table->next_idx ++;
2079                 values = table->values + semaidx * MONO_METHOD_SEMA_SIZE;
2080                 values [MONO_METHOD_SEMA_SEMANTICS] = METHOD_SEMANTIC_SETTER;
2081                 values [MONO_METHOD_SEMA_METHOD] = pb->set_method->table_idx;
2082                 values [MONO_METHOD_SEMA_ASSOCIATION] = (pb->table_idx << MONO_HAS_SEMANTICS_BITS) | MONO_HAS_SEMANTICS_PROPERTY;
2083         }
2084         if (pb->attrs & PROPERTY_ATTRIBUTE_HAS_DEFAULT) {
2085                 guint32 field_type = 0;
2086                 table = &assembly->tables [MONO_TABLE_CONSTANT];
2087                 table->rows ++;
2088                 alloc_table (table, table->rows);
2089                 values = table->values + table->rows * MONO_CONSTANT_SIZE;
2090                 values [MONO_CONSTANT_PARENT] = MONO_HASCONSTANT_PROPERTY | (pb->table_idx << MONO_HASCONSTANT_BITS);
2091                 values [MONO_CONSTANT_VALUE] = encode_constant (assembly, pb->def_value, &field_type);
2092                 values [MONO_CONSTANT_TYPE] = field_type;
2093                 values [MONO_CONSTANT_PADDING] = 0;
2094         }
2095 }
2096
2097 static void
2098 mono_image_get_event_info (MonoReflectionEventBuilder *eb, MonoDynamicImage *assembly)
2099 {
2100         MonoDynamicTable *table;
2101         guint32 *values;
2102         guint num_methods = 0;
2103         guint32 semaidx;
2104
2105         /* 
2106          * we need to set things in the following tables:
2107          * EVENTMAP (info already filled in _get_type_info ())
2108          * EVENT    (rows already preallocated in _get_type_info ())
2109          * METHOD      (method info already done with the generic method code)
2110          * METHODSEMANTICS
2111          */
2112         table = &assembly->tables [MONO_TABLE_EVENT];
2113         eb->table_idx = table->next_idx ++;
2114         values = table->values + eb->table_idx * MONO_EVENT_SIZE;
2115         values [MONO_EVENT_NAME] = string_heap_insert_mstring (&assembly->sheap, eb->name);
2116         values [MONO_EVENT_FLAGS] = eb->attrs;
2117         values [MONO_EVENT_TYPE] = mono_image_typedef_or_ref (assembly, mono_reflection_type_get_handle (eb->type));
2118
2119         /*
2120          * FIXME: we still don't handle 'other' methods 
2121          */
2122         if (eb->add_method) num_methods ++;
2123         if (eb->remove_method) num_methods ++;
2124         if (eb->raise_method) num_methods ++;
2125
2126         table = &assembly->tables [MONO_TABLE_METHODSEMANTICS];
2127         table->rows += num_methods;
2128         alloc_table (table, table->rows);
2129
2130         if (eb->add_method) {
2131                 semaidx = table->next_idx ++;
2132                 values = table->values + semaidx * MONO_METHOD_SEMA_SIZE;
2133                 values [MONO_METHOD_SEMA_SEMANTICS] = METHOD_SEMANTIC_ADD_ON;
2134                 values [MONO_METHOD_SEMA_METHOD] = eb->add_method->table_idx;
2135                 values [MONO_METHOD_SEMA_ASSOCIATION] = (eb->table_idx << MONO_HAS_SEMANTICS_BITS) | MONO_HAS_SEMANTICS_EVENT;
2136         }
2137         if (eb->remove_method) {
2138                 semaidx = table->next_idx ++;
2139                 values = table->values + semaidx * MONO_METHOD_SEMA_SIZE;
2140                 values [MONO_METHOD_SEMA_SEMANTICS] = METHOD_SEMANTIC_REMOVE_ON;
2141                 values [MONO_METHOD_SEMA_METHOD] = eb->remove_method->table_idx;
2142                 values [MONO_METHOD_SEMA_ASSOCIATION] = (eb->table_idx << MONO_HAS_SEMANTICS_BITS) | MONO_HAS_SEMANTICS_EVENT;
2143         }
2144         if (eb->raise_method) {
2145                 semaidx = table->next_idx ++;
2146                 values = table->values + semaidx * MONO_METHOD_SEMA_SIZE;
2147                 values [MONO_METHOD_SEMA_SEMANTICS] = METHOD_SEMANTIC_FIRE;
2148                 values [MONO_METHOD_SEMA_METHOD] = eb->raise_method->table_idx;
2149                 values [MONO_METHOD_SEMA_ASSOCIATION] = (eb->table_idx << MONO_HAS_SEMANTICS_BITS) | MONO_HAS_SEMANTICS_EVENT;
2150         }
2151 }
2152
2153 static void
2154 encode_constraints (MonoReflectionGenericParam *gparam, guint32 owner, MonoDynamicImage *assembly)
2155 {
2156         MonoDynamicTable *table;
2157         guint32 num_constraints, i;
2158         guint32 *values;
2159         guint32 table_idx;
2160
2161         table = &assembly->tables [MONO_TABLE_GENERICPARAMCONSTRAINT];
2162         num_constraints = gparam->iface_constraints ?
2163                 mono_array_length (gparam->iface_constraints) : 0;
2164         table->rows += num_constraints;
2165         if (gparam->base_type)
2166                 table->rows++;
2167         alloc_table (table, table->rows);
2168
2169         if (gparam->base_type) {
2170                 table_idx = table->next_idx ++;
2171                 values = table->values + table_idx * MONO_GENPARCONSTRAINT_SIZE;
2172
2173                 values [MONO_GENPARCONSTRAINT_GENERICPAR] = owner;
2174                 values [MONO_GENPARCONSTRAINT_CONSTRAINT] = mono_image_typedef_or_ref (
2175                         assembly, mono_reflection_type_get_handle (gparam->base_type));
2176         }
2177
2178         for (i = 0; i < num_constraints; i++) {
2179                 MonoReflectionType *constraint = mono_array_get (
2180                         gparam->iface_constraints, gpointer, i);
2181
2182                 table_idx = table->next_idx ++;
2183                 values = table->values + table_idx * MONO_GENPARCONSTRAINT_SIZE;
2184
2185                 values [MONO_GENPARCONSTRAINT_GENERICPAR] = owner;
2186                 values [MONO_GENPARCONSTRAINT_CONSTRAINT] = mono_image_typedef_or_ref (
2187                         assembly, mono_reflection_type_get_handle (constraint));
2188         }
2189 }
2190
2191 static void
2192 mono_image_get_generic_param_info (MonoReflectionGenericParam *gparam, guint32 owner, MonoDynamicImage *assembly)
2193 {
2194         GenericParamTableEntry *entry;
2195
2196         /*
2197          * The GenericParam table must be sorted according to the `owner' field.
2198          * We need to do this sorting prior to writing the GenericParamConstraint
2199          * table, since we have to use the final GenericParam table indices there
2200          * and they must also be sorted.
2201          */
2202
2203         entry = g_new0 (GenericParamTableEntry, 1);
2204         entry->owner = owner;
2205         /* FIXME: track where gen_params should be freed and remove the GC root as well */
2206         MONO_GC_REGISTER_ROOT_IF_MOVING (entry->gparam);
2207         entry->gparam = gparam;
2208         
2209         g_ptr_array_add (assembly->gen_params, entry);
2210 }
2211
2212 static void
2213 write_generic_param_entry (MonoDynamicImage *assembly, GenericParamTableEntry *entry)
2214 {
2215         MonoDynamicTable *table;
2216         MonoGenericParam *param;
2217         guint32 *values;
2218         guint32 table_idx;
2219
2220         table = &assembly->tables [MONO_TABLE_GENERICPARAM];
2221         table_idx = table->next_idx ++;
2222         values = table->values + table_idx * MONO_GENERICPARAM_SIZE;
2223
2224         param = mono_reflection_type_get_handle ((MonoReflectionType*)entry->gparam)->data.generic_param;
2225
2226         values [MONO_GENERICPARAM_OWNER] = entry->owner;
2227         values [MONO_GENERICPARAM_FLAGS] = entry->gparam->attrs;
2228         values [MONO_GENERICPARAM_NUMBER] = mono_generic_param_num (param);
2229         values [MONO_GENERICPARAM_NAME] = string_heap_insert (&assembly->sheap, mono_generic_param_info (param)->name);
2230
2231         mono_image_add_cattrs (assembly, table_idx, MONO_CUSTOM_ATTR_GENERICPAR, entry->gparam->cattrs);
2232
2233         encode_constraints (entry->gparam, table_idx, assembly);
2234 }
2235
2236 static guint32
2237 resolution_scope_from_image (MonoDynamicImage *assembly, MonoImage *image)
2238 {
2239         MonoDynamicTable *table;
2240         guint32 token;
2241         guint32 *values;
2242         guint32 cols [MONO_ASSEMBLY_SIZE];
2243         const char *pubkey;
2244         guint32 publen;
2245
2246         if ((token = GPOINTER_TO_UINT (g_hash_table_lookup (assembly->handleref, image))))
2247                 return token;
2248
2249         if (image->assembly->dynamic && (image->assembly == assembly->image.assembly)) {
2250                 table = &assembly->tables [MONO_TABLE_MODULEREF];
2251                 token = table->next_idx ++;
2252                 table->rows ++;
2253                 alloc_table (table, table->rows);
2254                 values = table->values + token * MONO_MODULEREF_SIZE;
2255                 values [MONO_MODULEREF_NAME] = string_heap_insert (&assembly->sheap, image->module_name);
2256
2257                 token <<= MONO_RESOLTION_SCOPE_BITS;
2258                 token |= MONO_RESOLTION_SCOPE_MODULEREF;
2259                 g_hash_table_insert (assembly->handleref, image, GUINT_TO_POINTER (token));
2260
2261                 return token;
2262         }
2263         
2264         if (image->assembly->dynamic)
2265                 /* FIXME: */
2266                 memset (cols, 0, sizeof (cols));
2267         else {
2268                 /* image->assembly->image is the manifest module */
2269                 image = image->assembly->image;
2270                 mono_metadata_decode_row (&image->tables [MONO_TABLE_ASSEMBLY], 0, cols, MONO_ASSEMBLY_SIZE);
2271         }
2272
2273         table = &assembly->tables [MONO_TABLE_ASSEMBLYREF];
2274         token = table->next_idx ++;
2275         table->rows ++;
2276         alloc_table (table, table->rows);
2277         values = table->values + token * MONO_ASSEMBLYREF_SIZE;
2278         values [MONO_ASSEMBLYREF_NAME] = string_heap_insert (&assembly->sheap, image->assembly_name);
2279         values [MONO_ASSEMBLYREF_MAJOR_VERSION] = cols [MONO_ASSEMBLY_MAJOR_VERSION];
2280         values [MONO_ASSEMBLYREF_MINOR_VERSION] = cols [MONO_ASSEMBLY_MINOR_VERSION];
2281         values [MONO_ASSEMBLYREF_BUILD_NUMBER] = cols [MONO_ASSEMBLY_BUILD_NUMBER];
2282         values [MONO_ASSEMBLYREF_REV_NUMBER] = cols [MONO_ASSEMBLY_REV_NUMBER];
2283         values [MONO_ASSEMBLYREF_FLAGS] = 0;
2284         values [MONO_ASSEMBLYREF_CULTURE] = 0;
2285         values [MONO_ASSEMBLYREF_HASH_VALUE] = 0;
2286
2287         if (strcmp ("", image->assembly->aname.culture)) {
2288                 values [MONO_ASSEMBLYREF_CULTURE] = string_heap_insert (&assembly->sheap,
2289                                 image->assembly->aname.culture);
2290         }
2291
2292         if ((pubkey = mono_image_get_public_key (image, &publen))) {
2293                 guchar pubtoken [9];
2294                 pubtoken [0] = 8;
2295                 mono_digest_get_public_token (pubtoken + 1, (guchar*)pubkey, publen);
2296                 values [MONO_ASSEMBLYREF_PUBLIC_KEY] = mono_image_add_stream_data (&assembly->blob, (char*)pubtoken, 9);
2297         } else {
2298                 values [MONO_ASSEMBLYREF_PUBLIC_KEY] = 0;
2299         }
2300         token <<= MONO_RESOLTION_SCOPE_BITS;
2301         token |= MONO_RESOLTION_SCOPE_ASSEMBLYREF;
2302         g_hash_table_insert (assembly->handleref, image, GUINT_TO_POINTER (token));
2303         return token;
2304 }
2305
2306 static guint32
2307 create_typespec (MonoDynamicImage *assembly, MonoType *type)
2308 {
2309         MonoDynamicTable *table;
2310         guint32 *values;
2311         guint32 token;
2312         SigBuffer buf;
2313
2314         if ((token = GPOINTER_TO_UINT (g_hash_table_lookup (assembly->typespec, type))))
2315                 return token;
2316
2317         sigbuffer_init (&buf, 32);
2318         switch (type->type) {
2319         case MONO_TYPE_FNPTR:
2320         case MONO_TYPE_PTR:
2321         case MONO_TYPE_SZARRAY:
2322         case MONO_TYPE_ARRAY:
2323         case MONO_TYPE_VAR:
2324         case MONO_TYPE_MVAR:
2325         case MONO_TYPE_GENERICINST:
2326                 encode_type (assembly, type, &buf);
2327                 break;
2328         case MONO_TYPE_CLASS:
2329         case MONO_TYPE_VALUETYPE: {
2330                 MonoClass *k = mono_class_from_mono_type (type);
2331                 if (!k || !k->generic_container) {
2332                         sigbuffer_free (&buf);
2333                         return 0;
2334                 }
2335                 encode_type (assembly, type, &buf);
2336                 break;
2337         }
2338         default:
2339                 sigbuffer_free (&buf);
2340                 return 0;
2341         }
2342
2343         table = &assembly->tables [MONO_TABLE_TYPESPEC];
2344         if (assembly->save) {
2345                 token = sigbuffer_add_to_blob_cached (assembly, &buf);
2346                 alloc_table (table, table->rows + 1);
2347                 values = table->values + table->next_idx * MONO_TYPESPEC_SIZE;
2348                 values [MONO_TYPESPEC_SIGNATURE] = token;
2349         }
2350         sigbuffer_free (&buf);
2351
2352         token = MONO_TYPEDEFORREF_TYPESPEC | (table->next_idx << MONO_TYPEDEFORREF_BITS);
2353         g_hash_table_insert (assembly->typespec, type, GUINT_TO_POINTER(token));
2354         table->next_idx ++;
2355         return token;
2356 }
2357
2358 static guint32
2359 mono_image_typedef_or_ref_full (MonoDynamicImage *assembly, MonoType *type, gboolean try_typespec)
2360 {
2361         MonoDynamicTable *table;
2362         guint32 *values;
2363         guint32 token, scope, enclosing;
2364         MonoClass *klass;
2365
2366         /* if the type requires a typespec, we must try that first*/
2367         if (try_typespec && (token = create_typespec (assembly, type)))
2368                 return token;
2369         token = GPOINTER_TO_UINT (g_hash_table_lookup (assembly->typeref, type));
2370         if (token)
2371                 return token;
2372         klass = mono_class_from_mono_type (type);
2373         if (!klass)
2374                 klass = mono_class_from_mono_type (type);
2375
2376         /*
2377          * If it's in the same module and not a generic type parameter:
2378          */
2379         if ((klass->image == &assembly->image) && (type->type != MONO_TYPE_VAR) && 
2380                         (type->type != MONO_TYPE_MVAR)) {
2381                 MonoReflectionTypeBuilder *tb = mono_class_get_ref_info (klass);
2382                 token = MONO_TYPEDEFORREF_TYPEDEF | (tb->table_idx << MONO_TYPEDEFORREF_BITS);
2383                 mono_g_hash_table_insert (assembly->tokens, GUINT_TO_POINTER (token), mono_class_get_ref_info (klass));
2384                 return token;
2385         }
2386
2387         if (klass->nested_in) {
2388                 enclosing = mono_image_typedef_or_ref_full (assembly, &klass->nested_in->byval_arg, FALSE);
2389                 /* get the typeref idx of the enclosing type */
2390                 enclosing >>= MONO_TYPEDEFORREF_BITS;
2391                 scope = (enclosing << MONO_RESOLTION_SCOPE_BITS) | MONO_RESOLTION_SCOPE_TYPEREF;
2392         } else {
2393                 scope = resolution_scope_from_image (assembly, klass->image);
2394         }
2395         table = &assembly->tables [MONO_TABLE_TYPEREF];
2396         if (assembly->save) {
2397                 alloc_table (table, table->rows + 1);
2398                 values = table->values + table->next_idx * MONO_TYPEREF_SIZE;
2399                 values [MONO_TYPEREF_SCOPE] = scope;
2400                 values [MONO_TYPEREF_NAME] = string_heap_insert (&assembly->sheap, klass->name);
2401                 values [MONO_TYPEREF_NAMESPACE] = string_heap_insert (&assembly->sheap, klass->name_space);
2402         }
2403         token = MONO_TYPEDEFORREF_TYPEREF | (table->next_idx << MONO_TYPEDEFORREF_BITS); /* typeref */
2404         g_hash_table_insert (assembly->typeref, type, GUINT_TO_POINTER(token));
2405         table->next_idx ++;
2406         mono_g_hash_table_insert (assembly->tokens, GUINT_TO_POINTER (token), mono_class_get_ref_info (klass));
2407         return token;
2408 }
2409
2410 /*
2411  * Despite the name, we handle also TypeSpec (with the above helper).
2412  */
2413 static guint32
2414 mono_image_typedef_or_ref (MonoDynamicImage *assembly, MonoType *type)
2415 {
2416         return mono_image_typedef_or_ref_full (assembly, type, TRUE);
2417 }
2418
2419 #ifndef DISABLE_REFLECTION_EMIT
2420 static guint32
2421 mono_image_add_memberef_row (MonoDynamicImage *assembly, guint32 parent, const char *name, guint32 sig)
2422 {
2423         MonoDynamicTable *table;
2424         guint32 *values;
2425         guint32 token, pclass;
2426
2427         switch (parent & MONO_TYPEDEFORREF_MASK) {
2428         case MONO_TYPEDEFORREF_TYPEREF:
2429                 pclass = MONO_MEMBERREF_PARENT_TYPEREF;
2430                 break;
2431         case MONO_TYPEDEFORREF_TYPESPEC:
2432                 pclass = MONO_MEMBERREF_PARENT_TYPESPEC;
2433                 break;
2434         case MONO_TYPEDEFORREF_TYPEDEF:
2435                 pclass = MONO_MEMBERREF_PARENT_TYPEDEF;
2436                 break;
2437         default:
2438                 g_warning ("unknown typeref or def token 0x%08x for %s", parent, name);
2439                 return 0;
2440         }
2441         /* extract the index */
2442         parent >>= MONO_TYPEDEFORREF_BITS;
2443
2444         table = &assembly->tables [MONO_TABLE_MEMBERREF];
2445
2446         if (assembly->save) {
2447                 alloc_table (table, table->rows + 1);
2448                 values = table->values + table->next_idx * MONO_MEMBERREF_SIZE;
2449                 values [MONO_MEMBERREF_CLASS] = pclass | (parent << MONO_MEMBERREF_PARENT_BITS);
2450                 values [MONO_MEMBERREF_NAME] = string_heap_insert (&assembly->sheap, name);
2451                 values [MONO_MEMBERREF_SIGNATURE] = sig;
2452         }
2453
2454         token = MONO_TOKEN_MEMBER_REF | table->next_idx;
2455         table->next_idx ++;
2456
2457         return token;
2458 }
2459
2460 /*
2461  * Insert a memberef row into the metadata: the token that point to the memberref
2462  * is returned. Caching is done in the caller (mono_image_get_methodref_token() or
2463  * mono_image_get_fieldref_token()).
2464  * The sig param is an index to an already built signature.
2465  */
2466 static guint32
2467 mono_image_get_memberref_token (MonoDynamicImage *assembly, MonoType *type, const char *name, guint32 sig)
2468 {
2469         guint32 parent = mono_image_typedef_or_ref (assembly, type);
2470         return mono_image_add_memberef_row (assembly, parent, name, sig);
2471 }
2472
2473
2474 static guint32
2475 mono_image_get_methodref_token (MonoDynamicImage *assembly, MonoMethod *method, gboolean create_typespec)
2476 {
2477         guint32 token;
2478         MonoMethodSignature *sig;
2479         
2480         create_typespec = create_typespec && method->is_generic && method->klass->image != &assembly->image;
2481
2482         if (create_typespec) {
2483                 token = GPOINTER_TO_UINT (g_hash_table_lookup (assembly->handleref, GUINT_TO_POINTER (GPOINTER_TO_UINT (method) + 1)));
2484                 if (token)
2485                         return token;
2486         } 
2487
2488         token = GPOINTER_TO_UINT (g_hash_table_lookup (assembly->handleref, method));
2489         if (token && !create_typespec)
2490                 return token;
2491
2492         g_assert (!method->is_inflated);
2493         if (!token) {
2494                 /*
2495                  * A methodref signature can't contain an unmanaged calling convention.
2496                  */
2497                 sig = mono_metadata_signature_dup (mono_method_signature (method));
2498                 if ((sig->call_convention != MONO_CALL_DEFAULT) && (sig->call_convention != MONO_CALL_VARARG))
2499                         sig->call_convention = MONO_CALL_DEFAULT;
2500                 token = mono_image_get_memberref_token (assembly, &method->klass->byval_arg,
2501                         method->name,  method_encode_signature (assembly, sig));
2502                 g_free (sig);
2503                 g_hash_table_insert (assembly->handleref, method, GUINT_TO_POINTER(token));
2504         }
2505
2506         if (create_typespec) {
2507                 MonoDynamicTable *table = &assembly->tables [MONO_TABLE_METHODSPEC];
2508                 g_assert (mono_metadata_token_table (token) == MONO_TABLE_MEMBERREF);
2509                 token = (mono_metadata_token_index (token) << MONO_METHODDEFORREF_BITS) | MONO_METHODDEFORREF_METHODREF;
2510
2511                 if (assembly->save) {
2512                         guint32 *values;
2513
2514                         alloc_table (table, table->rows + 1);
2515                         values = table->values + table->next_idx * MONO_METHODSPEC_SIZE;
2516                         values [MONO_METHODSPEC_METHOD] = token;
2517                         values [MONO_METHODSPEC_SIGNATURE] = encode_generic_method_sig (assembly, &mono_method_get_generic_container (method)->context);
2518                 }
2519
2520                 token = MONO_TOKEN_METHOD_SPEC | table->next_idx;
2521                 table->next_idx ++;
2522                 /*methodspec and memberef tokens are diferent, */
2523                 g_hash_table_insert (assembly->handleref, GUINT_TO_POINTER (GPOINTER_TO_UINT (method) + 1), GUINT_TO_POINTER (token));
2524                 return token;
2525         }
2526         return token;
2527 }
2528
2529 static guint32
2530 mono_image_get_methodref_token_for_methodbuilder (MonoDynamicImage *assembly, MonoReflectionMethodBuilder *method)
2531 {
2532         guint32 token, parent, sig;
2533         ReflectionMethodBuilder rmb;
2534         char *name;
2535         MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder *)method->type;
2536         
2537         token = GPOINTER_TO_UINT (g_hash_table_lookup (assembly->handleref, method));
2538         if (token)
2539                 return token;
2540
2541         name = mono_string_to_utf8 (method->name);
2542         reflection_methodbuilder_from_method_builder (&rmb, method);
2543
2544         /*
2545          * A methodref signature can't contain an unmanaged calling convention.
2546          * Since some flags are encoded as part of call_conv, we need to check against it.
2547         */
2548         if ((rmb.call_conv & ~0x60) != MONO_CALL_DEFAULT && (rmb.call_conv & ~0x60) != MONO_CALL_VARARG)
2549                 rmb.call_conv = (rmb.call_conv & 0x60) | MONO_CALL_DEFAULT;
2550
2551         sig = method_builder_encode_signature (assembly, &rmb);
2552
2553         if (tb->generic_params)
2554                 parent = create_generic_typespec (assembly, tb);
2555         else
2556                 parent = mono_image_typedef_or_ref (assembly, mono_reflection_type_get_handle ((MonoReflectionType*)rmb.type));
2557
2558         token = mono_image_add_memberef_row (assembly, parent, name, sig);
2559
2560         g_free (name);
2561         g_hash_table_insert (assembly->handleref, method, GUINT_TO_POINTER(token));
2562         return token;
2563 }
2564
2565 static guint32
2566 mono_image_get_varargs_method_token (MonoDynamicImage *assembly, guint32 original,
2567                                      const gchar *name, guint32 sig)
2568 {
2569         MonoDynamicTable *table;
2570         guint32 token;
2571         guint32 *values;
2572         
2573         table = &assembly->tables [MONO_TABLE_MEMBERREF];
2574
2575         if (assembly->save) {
2576                 alloc_table (table, table->rows + 1);
2577                 values = table->values + table->next_idx * MONO_MEMBERREF_SIZE;
2578                 values [MONO_MEMBERREF_CLASS] = original;
2579                 values [MONO_MEMBERREF_NAME] = string_heap_insert (&assembly->sheap, name);
2580                 values [MONO_MEMBERREF_SIGNATURE] = sig;
2581         }
2582
2583         token = MONO_TOKEN_MEMBER_REF | table->next_idx;
2584         table->next_idx ++;
2585
2586         return token;
2587 }
2588
2589 static guint32
2590 encode_generic_method_definition_sig (MonoDynamicImage *assembly, MonoReflectionMethodBuilder *mb)
2591 {
2592         SigBuffer buf;
2593         int i;
2594         guint32 nparams = mono_array_length (mb->generic_params);
2595         guint32 idx;
2596
2597         if (!assembly->save)
2598                 return 0;
2599
2600         sigbuffer_init (&buf, 32);
2601
2602         sigbuffer_add_value (&buf, 0xa);
2603         sigbuffer_add_value (&buf, nparams);
2604
2605         for (i = 0; i < nparams; i++) {
2606                 sigbuffer_add_value (&buf, MONO_TYPE_MVAR);
2607                 sigbuffer_add_value (&buf, i);
2608         }
2609
2610         idx = sigbuffer_add_to_blob_cached (assembly, &buf);
2611         sigbuffer_free (&buf);
2612         return idx;
2613 }
2614
2615 static guint32
2616 mono_image_get_methodspec_token_for_generic_method_definition (MonoDynamicImage *assembly, MonoReflectionMethodBuilder *mb)
2617 {
2618         MonoDynamicTable *table;
2619         guint32 *values;
2620         guint32 token, mtoken = 0;
2621
2622         token = GPOINTER_TO_UINT (mono_g_hash_table_lookup (assembly->methodspec, mb));
2623         if (token)
2624                 return token;
2625
2626         table = &assembly->tables [MONO_TABLE_METHODSPEC];
2627
2628         mtoken = mono_image_get_methodref_token_for_methodbuilder (assembly, mb);
2629         switch (mono_metadata_token_table (mtoken)) {
2630         case MONO_TABLE_MEMBERREF:
2631                 mtoken = (mono_metadata_token_index (mtoken) << MONO_METHODDEFORREF_BITS) | MONO_METHODDEFORREF_METHODREF;
2632                 break;
2633         case MONO_TABLE_METHOD:
2634                 mtoken = (mono_metadata_token_index (mtoken) << MONO_METHODDEFORREF_BITS) | MONO_METHODDEFORREF_METHODDEF;
2635                 break;
2636         default:
2637                 g_assert_not_reached ();
2638         }
2639
2640         if (assembly->save) {
2641                 alloc_table (table, table->rows + 1);
2642                 values = table->values + table->next_idx * MONO_METHODSPEC_SIZE;
2643                 values [MONO_METHODSPEC_METHOD] = mtoken;
2644                 values [MONO_METHODSPEC_SIGNATURE] = encode_generic_method_definition_sig (assembly, mb);
2645         }
2646
2647         token = MONO_TOKEN_METHOD_SPEC | table->next_idx;
2648         table->next_idx ++;
2649
2650         mono_g_hash_table_insert (assembly->methodspec, mb, GUINT_TO_POINTER(token));
2651         return token;
2652 }
2653
2654 static guint32
2655 mono_image_get_methodbuilder_token (MonoDynamicImage *assembly, MonoReflectionMethodBuilder *mb, gboolean create_methodspec)
2656 {
2657         guint32 token;
2658
2659         if (mb->generic_params && create_methodspec) 
2660                 return mono_image_get_methodspec_token_for_generic_method_definition (assembly, mb);
2661
2662         token = GPOINTER_TO_UINT (mono_g_hash_table_lookup (assembly->handleref_managed, mb));
2663         if (token)
2664                 return token;
2665
2666         token = mono_image_get_methodref_token_for_methodbuilder (assembly, mb);
2667         mono_g_hash_table_insert (assembly->handleref_managed, mb, GUINT_TO_POINTER(token));
2668         return token;
2669 }
2670
2671 static guint32
2672 mono_image_get_ctorbuilder_token (MonoDynamicImage *assembly, MonoReflectionCtorBuilder *mb)
2673 {
2674         guint32 token, parent, sig;
2675         ReflectionMethodBuilder rmb;
2676         char *name;
2677         MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder *)mb->type;
2678         
2679         token = GPOINTER_TO_UINT (mono_g_hash_table_lookup (assembly->handleref_managed, mb));
2680         if (token)
2681                 return token;
2682
2683         reflection_methodbuilder_from_ctor_builder (&rmb, mb);
2684
2685         if (tb->generic_params)
2686                 parent = create_generic_typespec (assembly, tb);
2687         else
2688                 parent = mono_image_typedef_or_ref (assembly, mono_reflection_type_get_handle ((MonoReflectionType*)tb));
2689         
2690         name = mono_string_to_utf8 (rmb.name);
2691         sig = method_builder_encode_signature (assembly, &rmb);
2692
2693         token = mono_image_add_memberef_row (assembly, parent, name, sig);
2694
2695         g_free (name);
2696         mono_g_hash_table_insert (assembly->handleref_managed, mb, GUINT_TO_POINTER(token));
2697         return token;
2698 }
2699 #endif
2700
2701 static gboolean
2702 is_field_on_inst (MonoClassField *field)
2703 {
2704         return (field->parent->generic_class && field->parent->generic_class->is_dynamic && ((MonoDynamicGenericClass*)field->parent->generic_class)->fields);
2705 }
2706
2707 /*
2708  * If FIELD is a field of a MonoDynamicGenericClass, return its non-inflated type.
2709  */
2710 static MonoType*
2711 get_field_on_inst_generic_type (MonoClassField *field)
2712 {
2713         MonoClass *class, *gtd;
2714         MonoDynamicGenericClass *dgclass;
2715         int field_index;
2716
2717         g_assert (is_field_on_inst (field));
2718
2719         dgclass = (MonoDynamicGenericClass*)field->parent->generic_class;
2720
2721         if (field >= dgclass->fields && field - dgclass->fields < dgclass->count_fields) {
2722                 field_index = field - dgclass->fields;
2723                 return dgclass->field_generic_types [field_index];              
2724         }
2725
2726         class = field->parent;
2727         gtd = class->generic_class->container_class;
2728
2729         if (field >= class->fields && field - class->fields < class->field.count) {
2730                 field_index = field - class->fields;
2731                 return gtd->fields [field_index].type;
2732         }
2733
2734         g_assert_not_reached ();
2735         return 0;
2736 }
2737
2738 #ifndef DISABLE_REFLECTION_EMIT
2739 static guint32
2740 mono_image_get_fieldref_token (MonoDynamicImage *assembly, MonoObject *f, MonoClassField *field)
2741 {
2742         MonoType *type;
2743         guint32 token;
2744
2745         g_assert (field);
2746         g_assert (field->parent);
2747
2748         token = GPOINTER_TO_UINT (mono_g_hash_table_lookup (assembly->handleref_managed, f));
2749         if (token)
2750                 return token;
2751
2752         if (field->parent->generic_class && field->parent->generic_class->container_class && field->parent->generic_class->container_class->fields) {
2753                 int index = field - field->parent->fields;
2754                 type = mono_field_get_type (&field->parent->generic_class->container_class->fields [index]);
2755         } else {
2756                 if (is_field_on_inst (field))
2757                         type = get_field_on_inst_generic_type (field);
2758                 else
2759                         type = mono_field_get_type (field);
2760         }
2761         token = mono_image_get_memberref_token (assembly, &field->parent->byval_arg,
2762                                                                                         mono_field_get_name (field),
2763                                                                                         fieldref_encode_signature (assembly, field->parent->image, type));
2764         mono_g_hash_table_insert (assembly->handleref_managed, f, GUINT_TO_POINTER(token));
2765         return token;
2766 }
2767
2768 static guint32
2769 mono_image_get_field_on_inst_token (MonoDynamicImage *assembly, MonoReflectionFieldOnTypeBuilderInst *f)
2770 {
2771         guint32 token;
2772         MonoClass *klass;
2773         MonoGenericClass *gclass;
2774         MonoDynamicGenericClass *dgclass;
2775         MonoType *type;
2776         char *name;
2777
2778         token = GPOINTER_TO_UINT (mono_g_hash_table_lookup (assembly->handleref_managed, f));
2779         if (token)
2780                 return token;
2781         if (is_sre_field_builder (mono_object_class (f->fb))) {
2782                 MonoReflectionFieldBuilder *fb = (MonoReflectionFieldBuilder *)f->fb;
2783                 type = mono_reflection_type_get_handle ((MonoReflectionType*)f->inst);
2784                 klass = mono_class_from_mono_type (type);
2785                 gclass = type->data.generic_class;
2786                 g_assert (gclass->is_dynamic);
2787                 dgclass = (MonoDynamicGenericClass *) gclass;
2788
2789                 name = mono_string_to_utf8 (fb->name);
2790                 token = mono_image_get_memberref_token (assembly, &klass->byval_arg, name, 
2791                                                                                                 field_encode_signature (assembly, fb));
2792                 g_free (name);          
2793         } else if (is_sr_mono_field (mono_object_class (f->fb))) {
2794                 guint32 sig;
2795                 MonoClassField *field = ((MonoReflectionField *)f->fb)->field;
2796
2797                 type = mono_reflection_type_get_handle ((MonoReflectionType*)f->inst);
2798                 klass = mono_class_from_mono_type (type);
2799
2800                 sig = fieldref_encode_signature (assembly, field->parent->image, field->type);
2801                 token = mono_image_get_memberref_token (assembly, &klass->byval_arg, field->name, sig);
2802         } else {
2803                 char *name = mono_type_get_full_name (mono_object_class (f->fb));
2804                 g_error ("mono_image_get_field_on_inst_token: don't know how to handle %s", name);
2805         }
2806
2807         mono_g_hash_table_insert (assembly->handleref_managed, f, GUINT_TO_POINTER (token));
2808         return token;
2809 }
2810
2811 static guint32
2812 mono_image_get_ctor_on_inst_token (MonoDynamicImage *assembly, MonoReflectionCtorOnTypeBuilderInst *c, gboolean create_methodspec)
2813 {
2814         guint32 sig, token;
2815         MonoClass *klass;
2816         MonoGenericClass *gclass;
2817         MonoType *type;
2818
2819         /* A ctor cannot be a generic method, so we can ignore create_methodspec */
2820
2821         token = GPOINTER_TO_UINT (mono_g_hash_table_lookup (assembly->handleref_managed, c));
2822         if (token)
2823                 return token;
2824
2825         if (is_sre_ctor_builder (mono_object_class (c->cb))) {
2826                 MonoReflectionCtorBuilder *cb = (MonoReflectionCtorBuilder *)c->cb;
2827                 MonoDynamicGenericClass *dgclass;
2828                 ReflectionMethodBuilder rmb;
2829                 char *name;
2830
2831                 type = mono_reflection_type_get_handle ((MonoReflectionType*)c->inst);
2832                 klass = mono_class_from_mono_type (type);
2833
2834                 gclass = type->data.generic_class;
2835                 g_assert (gclass->is_dynamic);
2836                 dgclass = (MonoDynamicGenericClass *) gclass;
2837
2838                 reflection_methodbuilder_from_ctor_builder (&rmb, cb);
2839
2840                 name = mono_string_to_utf8 (rmb.name);
2841
2842                 sig = method_builder_encode_signature (assembly, &rmb);
2843
2844                 token = mono_image_get_memberref_token (assembly, &klass->byval_arg, name, sig);
2845                 g_free (name);
2846         } else if (is_sr_mono_cmethod (mono_object_class (c->cb))) {
2847                 MonoMethod *mm = ((MonoReflectionMethod *)c->cb)->method;
2848
2849                 type = mono_reflection_type_get_handle ((MonoReflectionType*)c->inst);
2850                 klass = mono_class_from_mono_type (type);
2851
2852                 sig = method_encode_signature (assembly, mono_method_signature (mm));
2853                 token = mono_image_get_memberref_token (assembly, &klass->byval_arg, mm->name, sig);
2854         } else {
2855                 char *name = mono_type_get_full_name (mono_object_class (c->cb));
2856                 g_error ("mono_image_get_method_on_inst_token: don't know how to handle %s", name);
2857         }
2858
2859
2860         mono_g_hash_table_insert (assembly->handleref_managed, c, GUINT_TO_POINTER (token));
2861         return token;
2862 }
2863
2864 static MonoMethod*
2865 mono_reflection_method_on_tb_inst_get_handle (MonoReflectionMethodOnTypeBuilderInst *m)
2866 {
2867         MonoClass *klass;
2868         MonoGenericContext tmp_context;
2869         MonoType **type_argv;
2870         MonoGenericInst *ginst;
2871         MonoMethod *method, *inflated;
2872         int count, i;
2873
2874         init_type_builder_generics ((MonoObject*)m->inst);
2875
2876         method = inflate_method (m->inst, (MonoObject*)m->mb);
2877
2878         klass = method->klass;
2879
2880         if (m->method_args == NULL)
2881                 return method;
2882
2883         if (method->is_inflated)
2884                 method = ((MonoMethodInflated *) method)->declaring;
2885
2886         count = mono_array_length (m->method_args);
2887
2888         type_argv = g_new0 (MonoType *, count);
2889         for (i = 0; i < count; i++) {
2890                 MonoReflectionType *garg = mono_array_get (m->method_args, gpointer, i);
2891                 type_argv [i] = mono_reflection_type_get_handle (garg);
2892         }
2893         ginst = mono_metadata_get_generic_inst (count, type_argv);
2894         g_free (type_argv);
2895
2896         tmp_context.class_inst = klass->generic_class ? klass->generic_class->context.class_inst : NULL;
2897         tmp_context.method_inst = ginst;
2898
2899         inflated = mono_class_inflate_generic_method (method, &tmp_context);
2900         return inflated;
2901 }
2902
2903 static guint32
2904 mono_image_get_method_on_inst_token (MonoDynamicImage *assembly, MonoReflectionMethodOnTypeBuilderInst *m, gboolean create_methodspec)
2905 {
2906         guint32 sig, token = 0;
2907         MonoType *type;
2908         MonoClass *klass;
2909
2910         if (m->method_args) {
2911                 MonoMethod *inflated;
2912
2913                 inflated = mono_reflection_method_on_tb_inst_get_handle (m);
2914                 if (create_methodspec)
2915                         token = mono_image_get_methodspec_token (assembly, inflated);
2916                 else
2917                         token = mono_image_get_inflated_method_token (assembly, inflated);
2918                 return token;
2919         }
2920
2921         token = GPOINTER_TO_UINT (mono_g_hash_table_lookup (assembly->handleref_managed, m));
2922         if (token)
2923                 return token;
2924
2925         if (is_sre_method_builder (mono_object_class (m->mb))) {
2926                 MonoReflectionMethodBuilder *mb = (MonoReflectionMethodBuilder *)m->mb;
2927                 MonoGenericClass *gclass;
2928                 ReflectionMethodBuilder rmb;
2929                 char *name;
2930
2931                 type = mono_reflection_type_get_handle ((MonoReflectionType*)m->inst);
2932                 klass = mono_class_from_mono_type (type);
2933                 gclass = type->data.generic_class;
2934                 g_assert (gclass->is_dynamic);
2935
2936                 reflection_methodbuilder_from_method_builder (&rmb, mb);
2937
2938                 name = mono_string_to_utf8 (rmb.name);
2939
2940                 sig = method_builder_encode_signature (assembly, &rmb);
2941
2942                 token = mono_image_get_memberref_token (assembly, &klass->byval_arg, name, sig);
2943                 g_free (name);          
2944         } else if (is_sr_mono_method (mono_object_class (m->mb))) {
2945                 MonoMethod *mm = ((MonoReflectionMethod *)m->mb)->method;
2946
2947                 type = mono_reflection_type_get_handle ((MonoReflectionType*)m->inst);
2948                 klass = mono_class_from_mono_type (type);
2949
2950                 sig = method_encode_signature (assembly, mono_method_signature (mm));
2951                 token = mono_image_get_memberref_token (assembly, &klass->byval_arg, mm->name, sig);
2952         } else {
2953                 char *name = mono_type_get_full_name (mono_object_class (m->mb));
2954                 g_error ("mono_image_get_method_on_inst_token: don't know how to handle %s", name);
2955         }
2956
2957         mono_g_hash_table_insert (assembly->handleref_managed, m, GUINT_TO_POINTER (token));
2958         return token;
2959 }
2960
2961 static guint32
2962 encode_generic_method_sig (MonoDynamicImage *assembly, MonoGenericContext *context)
2963 {
2964         SigBuffer buf;
2965         int i;
2966         guint32 nparams = context->method_inst->type_argc;
2967         guint32 idx;
2968
2969         if (!assembly->save)
2970                 return 0;
2971
2972         sigbuffer_init (&buf, 32);
2973         /*
2974          * FIXME: vararg, explicit_this, differenc call_conv values...
2975          */
2976         sigbuffer_add_value (&buf, 0xa); /* FIXME FIXME FIXME */
2977         sigbuffer_add_value (&buf, nparams);
2978
2979         for (i = 0; i < nparams; i++)
2980                 encode_type (assembly, context->method_inst->type_argv [i], &buf);
2981
2982         idx = sigbuffer_add_to_blob_cached (assembly, &buf);
2983         sigbuffer_free (&buf);
2984         return idx;
2985 }
2986
2987 static guint32
2988 method_encode_methodspec (MonoDynamicImage *assembly, MonoMethod *method)
2989 {
2990         MonoDynamicTable *table;
2991         guint32 *values;
2992         guint32 token, mtoken = 0, sig;
2993         MonoMethodInflated *imethod;
2994         MonoMethod *declaring;
2995
2996         table = &assembly->tables [MONO_TABLE_METHODSPEC];
2997
2998         g_assert (method->is_inflated);
2999         imethod = (MonoMethodInflated *) method;
3000         declaring = imethod->declaring;
3001
3002         sig = method_encode_signature (assembly, mono_method_signature (declaring));
3003         mtoken = mono_image_get_memberref_token (assembly, &method->klass->byval_arg, declaring->name, sig);
3004
3005         if (!mono_method_signature (declaring)->generic_param_count)
3006                 return mtoken;
3007
3008         switch (mono_metadata_token_table (mtoken)) {
3009         case MONO_TABLE_MEMBERREF:
3010                 mtoken = (mono_metadata_token_index (mtoken) << MONO_METHODDEFORREF_BITS) | MONO_METHODDEFORREF_METHODREF;
3011                 break;
3012         case MONO_TABLE_METHOD:
3013                 mtoken = (mono_metadata_token_index (mtoken) << MONO_METHODDEFORREF_BITS) | MONO_METHODDEFORREF_METHODDEF;
3014                 break;
3015         default:
3016                 g_assert_not_reached ();
3017         }
3018
3019         sig = encode_generic_method_sig (assembly, mono_method_get_context (method));
3020
3021         if (assembly->save) {
3022                 alloc_table (table, table->rows + 1);
3023                 values = table->values + table->next_idx * MONO_METHODSPEC_SIZE;
3024                 values [MONO_METHODSPEC_METHOD] = mtoken;
3025                 values [MONO_METHODSPEC_SIGNATURE] = sig;
3026         }
3027
3028         token = MONO_TOKEN_METHOD_SPEC | table->next_idx;
3029         table->next_idx ++;
3030
3031         return token;
3032 }
3033
3034 static guint32
3035 mono_image_get_methodspec_token (MonoDynamicImage *assembly, MonoMethod *method)
3036 {
3037         MonoMethodInflated *imethod;
3038         guint32 token;
3039         
3040         token = GPOINTER_TO_UINT (g_hash_table_lookup (assembly->handleref, method));
3041         if (token)
3042                 return token;
3043
3044         g_assert (method->is_inflated);
3045         imethod = (MonoMethodInflated *) method;
3046
3047         if (mono_method_signature (imethod->declaring)->generic_param_count) {
3048                 token = method_encode_methodspec (assembly, method);
3049         } else {
3050                 guint32 sig = method_encode_signature (
3051                         assembly, mono_method_signature (imethod->declaring));
3052                 token = mono_image_get_memberref_token (
3053                         assembly, &method->klass->byval_arg, method->name, sig);
3054         }
3055
3056         g_hash_table_insert (assembly->handleref, method, GUINT_TO_POINTER(token));
3057         return token;
3058 }
3059
3060 static guint32
3061 mono_image_get_inflated_method_token (MonoDynamicImage *assembly, MonoMethod *m)
3062 {
3063         MonoMethodInflated *imethod = (MonoMethodInflated *) m;
3064         guint32 sig, token;
3065
3066         sig = method_encode_signature (assembly, mono_method_signature (imethod->declaring));
3067         token = mono_image_get_memberref_token (
3068                 assembly, &m->klass->byval_arg, m->name, sig);
3069
3070         return token;
3071 }
3072
3073 static guint32
3074 create_generic_typespec (MonoDynamicImage *assembly, MonoReflectionTypeBuilder *tb)
3075 {
3076         MonoDynamicTable *table;
3077         MonoClass *klass;
3078         MonoType *type;
3079         guint32 *values;
3080         guint32 token;
3081         SigBuffer buf;
3082         int count, i;
3083
3084         /*
3085          * We're creating a TypeSpec for the TypeBuilder of a generic type declaration,
3086          * ie. what we'd normally use as the generic type in a TypeSpec signature.
3087          * Because of this, we must not insert it into the `typeref' hash table.
3088          */
3089         type = mono_reflection_type_get_handle ((MonoReflectionType*)tb);
3090         token = GPOINTER_TO_UINT (g_hash_table_lookup (assembly->typespec, type));
3091         if (token)
3092                 return token;
3093
3094         sigbuffer_init (&buf, 32);
3095
3096         g_assert (tb->generic_params);
3097         klass = mono_class_from_mono_type (type);
3098
3099         if (tb->generic_container)
3100                 mono_reflection_create_generic_class (tb);
3101
3102         sigbuffer_add_value (&buf, MONO_TYPE_GENERICINST);
3103         g_assert (klass->generic_container);
3104         sigbuffer_add_value (&buf, klass->byval_arg.type);
3105         sigbuffer_add_value (&buf, mono_image_typedef_or_ref_full (assembly, &klass->byval_arg, FALSE));
3106
3107         count = mono_array_length (tb->generic_params);
3108         sigbuffer_add_value (&buf, count);
3109         for (i = 0; i < count; i++) {
3110                 MonoReflectionGenericParam *gparam;
3111
3112                 gparam = mono_array_get (tb->generic_params, MonoReflectionGenericParam *, i);
3113
3114                 encode_type (assembly, mono_reflection_type_get_handle ((MonoReflectionType*)gparam), &buf);
3115         }
3116
3117         table = &assembly->tables [MONO_TABLE_TYPESPEC];
3118
3119         if (assembly->save) {
3120                 token = sigbuffer_add_to_blob_cached (assembly, &buf);
3121                 alloc_table (table, table->rows + 1);
3122                 values = table->values + table->next_idx * MONO_TYPESPEC_SIZE;
3123                 values [MONO_TYPESPEC_SIGNATURE] = token;
3124         }
3125         sigbuffer_free (&buf);
3126
3127         token = MONO_TYPEDEFORREF_TYPESPEC | (table->next_idx << MONO_TYPEDEFORREF_BITS);
3128         g_hash_table_insert (assembly->typespec, type, GUINT_TO_POINTER(token));
3129         table->next_idx ++;
3130         return token;
3131 }
3132
3133 /*
3134  * Return a copy of TYPE, adding the custom modifiers in MODREQ and MODOPT.
3135  */
3136 static MonoType*
3137 add_custom_modifiers (MonoDynamicImage *assembly, MonoType *type, MonoArray *modreq, MonoArray *modopt)
3138 {
3139         int i, count, len, pos;
3140         MonoType *t;
3141
3142         count = 0;
3143         if (modreq)
3144                 count += mono_array_length (modreq);
3145         if (modopt)
3146                 count += mono_array_length (modopt);
3147
3148         if (count == 0)
3149                 return mono_metadata_type_dup (NULL, type);
3150
3151         len = MONO_SIZEOF_TYPE + ((gint32)count) * sizeof (MonoCustomMod);
3152         t = g_malloc (len);
3153         memcpy (t, type, MONO_SIZEOF_TYPE);
3154
3155         t->num_mods = count;
3156         pos = 0;
3157         if (modreq) {
3158                 for (i = 0; i < mono_array_length (modreq); ++i) {
3159                         MonoType *mod = mono_type_array_get_and_resolve (modreq, i);
3160                         t->modifiers [pos].required = 1;
3161                         t->modifiers [pos].token = mono_image_typedef_or_ref (assembly, mod);
3162                         pos ++;
3163                 }
3164         }
3165         if (modopt) {
3166                 for (i = 0; i < mono_array_length (modopt); ++i) {
3167                         MonoType *mod = mono_type_array_get_and_resolve (modopt, i);
3168                         t->modifiers [pos].required = 0;
3169                         t->modifiers [pos].token = mono_image_typedef_or_ref (assembly, mod);
3170                         pos ++;
3171                 }
3172         }
3173
3174         return t;
3175 }
3176
3177 static void
3178 init_type_builder_generics (MonoObject *type)
3179 {
3180         MonoReflectionTypeBuilder *tb;
3181
3182         if (!is_sre_type_builder(mono_object_class (type)))
3183                 return;
3184         tb = (MonoReflectionTypeBuilder *)type;
3185
3186         if (tb && tb->generic_container)
3187                 mono_reflection_create_generic_class (tb);
3188 }
3189
3190 static guint32
3191 mono_image_get_generic_field_token (MonoDynamicImage *assembly, MonoReflectionFieldBuilder *fb)
3192 {
3193         MonoDynamicTable *table;
3194         MonoClass *klass;
3195         MonoType *custom = NULL, *type;
3196         guint32 *values;
3197         guint32 token, pclass, parent, sig;
3198         gchar *name;
3199
3200         token = GPOINTER_TO_UINT (mono_g_hash_table_lookup (assembly->handleref_managed, fb));
3201         if (token)
3202                 return token;
3203
3204         klass = mono_class_from_mono_type (mono_reflection_type_get_handle (fb->typeb));
3205         name = mono_string_to_utf8 (fb->name);
3206
3207         /*FIXME this is one more layer of ugliness due how types are created.*/
3208         init_type_builder_generics (fb->type);
3209
3210         /* fb->type does not include the custom modifiers */
3211         /* FIXME: We should do this in one place when a fieldbuilder is created */
3212         type = mono_reflection_type_get_handle ((MonoReflectionType*)fb->type);
3213         if (fb->modreq || fb->modopt)
3214                 type = custom = add_custom_modifiers (assembly, type, fb->modreq, fb->modopt);
3215
3216         sig = fieldref_encode_signature (assembly, NULL, type);
3217         g_free (custom);
3218
3219         parent = create_generic_typespec (assembly, (MonoReflectionTypeBuilder *) fb->typeb);
3220         g_assert ((parent & MONO_TYPEDEFORREF_MASK) == MONO_TYPEDEFORREF_TYPESPEC);
3221         
3222         pclass = MONO_MEMBERREF_PARENT_TYPESPEC;
3223         parent >>= MONO_TYPEDEFORREF_BITS;
3224
3225         table = &assembly->tables [MONO_TABLE_MEMBERREF];
3226
3227         if (assembly->save) {
3228                 alloc_table (table, table->rows + 1);
3229                 values = table->values + table->next_idx * MONO_MEMBERREF_SIZE;
3230                 values [MONO_MEMBERREF_CLASS] = pclass | (parent << MONO_MEMBERREF_PARENT_BITS);
3231                 values [MONO_MEMBERREF_NAME] = string_heap_insert (&assembly->sheap, name);
3232                 values [MONO_MEMBERREF_SIGNATURE] = sig;
3233         }
3234
3235         token = MONO_TOKEN_MEMBER_REF | table->next_idx;
3236         table->next_idx ++;
3237         mono_g_hash_table_insert (assembly->handleref_managed, fb, GUINT_TO_POINTER(token));
3238         g_free (name);
3239         return token;
3240 }
3241
3242 static guint32
3243 mono_reflection_encode_sighelper (MonoDynamicImage *assembly, MonoReflectionSigHelper *helper)
3244 {
3245         SigBuffer buf;
3246         guint32 nargs;
3247         guint32 size;
3248         guint32 i, idx;
3249
3250         if (!assembly->save)
3251                 return 0;
3252
3253         /* FIXME: this means SignatureHelper.SignatureHelpType.HELPER_METHOD */
3254         g_assert (helper->type == 2);
3255
3256         if (helper->arguments)
3257                 nargs = mono_array_length (helper->arguments);
3258         else
3259                 nargs = 0;
3260
3261         size = 10 + (nargs * 10);
3262         
3263         sigbuffer_init (&buf, 32);
3264
3265         /* Encode calling convention */
3266         /* Change Any to Standard */
3267         if ((helper->call_conv & 0x03) == 0x03)
3268                 helper->call_conv = 0x01;
3269         /* explicit_this implies has_this */
3270         if (helper->call_conv & 0x40)
3271                 helper->call_conv &= 0x20;
3272
3273         if (helper->call_conv == 0) { /* Unmanaged */
3274                 idx = helper->unmanaged_call_conv - 1;
3275         } else {
3276                 /* Managed */
3277                 idx = helper->call_conv & 0x60; /* has_this + explicit_this */
3278                 if (helper->call_conv & 0x02) /* varargs */
3279                         idx += 0x05;
3280         }
3281
3282         sigbuffer_add_byte (&buf, idx);
3283         sigbuffer_add_value (&buf, nargs);
3284         encode_reflection_type (assembly, helper->return_type, &buf);
3285         for (i = 0; i < nargs; ++i) {
3286                 MonoArray *modreqs = NULL;
3287                 MonoArray *modopts = NULL;
3288                 MonoReflectionType *pt;
3289
3290                 if (helper->modreqs && (i < mono_array_length (helper->modreqs)))
3291                         modreqs = mono_array_get (helper->modreqs, MonoArray*, i);
3292                 if (helper->modopts && (i < mono_array_length (helper->modopts)))
3293                         modopts = mono_array_get (helper->modopts, MonoArray*, i);
3294
3295                 encode_custom_modifiers (assembly, modreqs, modopts, &buf);
3296                 pt = mono_array_get (helper->arguments, MonoReflectionType*, i);
3297                 encode_reflection_type (assembly, pt, &buf);
3298         }
3299         idx = sigbuffer_add_to_blob_cached (assembly, &buf);
3300         sigbuffer_free (&buf);
3301
3302         return idx;
3303 }
3304
3305 static guint32 
3306 mono_image_get_sighelper_token (MonoDynamicImage *assembly, MonoReflectionSigHelper *helper)
3307 {
3308         guint32 idx;
3309         MonoDynamicTable *table;
3310         guint32 *values;
3311
3312         table = &assembly->tables [MONO_TABLE_STANDALONESIG];
3313         idx = table->next_idx ++;
3314         table->rows ++;
3315         alloc_table (table, table->rows);
3316         values = table->values + idx * MONO_STAND_ALONE_SIGNATURE_SIZE;
3317
3318         values [MONO_STAND_ALONE_SIGNATURE] =
3319                 mono_reflection_encode_sighelper (assembly, helper);
3320
3321         return idx;
3322 }
3323
3324 static int
3325 reflection_cc_to_file (int call_conv) {
3326         switch (call_conv & 0x3) {
3327         case 0:
3328         case 1: return MONO_CALL_DEFAULT;
3329         case 2: return MONO_CALL_VARARG;
3330         default:
3331                 g_assert_not_reached ();
3332         }
3333         return 0;
3334 }
3335 #endif /* !DISABLE_REFLECTION_EMIT */
3336
3337 typedef struct {
3338         MonoType *parent;
3339         MonoMethodSignature *sig;
3340         char *name;
3341         guint32 token;
3342 } ArrayMethod;
3343
3344 #ifndef DISABLE_REFLECTION_EMIT
3345 static guint32
3346 mono_image_get_array_token (MonoDynamicImage *assembly, MonoReflectionArrayMethod *m)
3347 {
3348         guint32 nparams, i;
3349         GList *tmp;
3350         char *name;
3351         MonoMethodSignature *sig;
3352         ArrayMethod *am;
3353         MonoType *mtype;
3354
3355         name = mono_string_to_utf8 (m->name);
3356         nparams = mono_array_length (m->parameters);
3357         sig = g_malloc0 (MONO_SIZEOF_METHOD_SIGNATURE + sizeof (MonoType*) * nparams);
3358         sig->hasthis = 1;
3359         sig->sentinelpos = -1;
3360         sig->call_convention = reflection_cc_to_file (m->call_conv);
3361         sig->param_count = nparams;
3362         sig->ret = m->ret ? mono_reflection_type_get_handle (m->ret): &mono_defaults.void_class->byval_arg;
3363         mtype = mono_reflection_type_get_handle (m->parent);
3364         for (i = 0; i < nparams; ++i)
3365                 sig->params [i] = mono_type_array_get_and_resolve (m->parameters, i);
3366
3367         for (tmp = assembly->array_methods; tmp; tmp = tmp->next) {
3368                 am = tmp->data;
3369                 if (strcmp (name, am->name) == 0 && 
3370                                 mono_metadata_type_equal (am->parent, mtype) &&
3371                                 mono_metadata_signature_equal (am->sig, sig)) {
3372                         g_free (name);
3373                         g_free (sig);
3374                         m->table_idx = am->token & 0xffffff;
3375                         return am->token;
3376                 }
3377         }
3378         am = g_new0 (ArrayMethod, 1);
3379         am->name = name;
3380         am->sig = sig;
3381         am->parent = mtype;
3382         am->token = mono_image_get_memberref_token (assembly, am->parent, name,
3383                 method_encode_signature (assembly, sig));
3384         assembly->array_methods = g_list_prepend (assembly->array_methods, am);
3385         m->table_idx = am->token & 0xffffff;
3386         return am->token;
3387 }
3388
3389 /*
3390  * Insert into the metadata tables all the info about the TypeBuilder tb.
3391  * Data in the tables is inserted in a predefined order, since some tables need to be sorted.
3392  */
3393 static void
3394 mono_image_get_type_info (MonoDomain *domain, MonoReflectionTypeBuilder *tb, MonoDynamicImage *assembly)
3395 {
3396         MonoDynamicTable *table;
3397         guint *values;
3398         int i, is_object = 0, is_system = 0;
3399         char *n;
3400
3401         table = &assembly->tables [MONO_TABLE_TYPEDEF];
3402         values = table->values + tb->table_idx * MONO_TYPEDEF_SIZE;
3403         values [MONO_TYPEDEF_FLAGS] = tb->attrs;
3404         n = mono_string_to_utf8 (tb->name);
3405         if (strcmp (n, "Object") == 0)
3406                 is_object++;
3407         values [MONO_TYPEDEF_NAME] = string_heap_insert (&assembly->sheap, n);
3408         g_free (n);
3409         n = mono_string_to_utf8 (tb->nspace);
3410         if (strcmp (n, "System") == 0)
3411                 is_system++;
3412         values [MONO_TYPEDEF_NAMESPACE] = string_heap_insert (&assembly->sheap, n);
3413         g_free (n);
3414         if (tb->parent && !(is_system && is_object) && 
3415                         !(tb->attrs & TYPE_ATTRIBUTE_INTERFACE)) { /* interfaces don't have a parent */
3416                 values [MONO_TYPEDEF_EXTENDS] = mono_image_typedef_or_ref (assembly, mono_reflection_type_get_handle ((MonoReflectionType*)tb->parent));
3417         } else {
3418                 values [MONO_TYPEDEF_EXTENDS] = 0;
3419         }
3420         values [MONO_TYPEDEF_FIELD_LIST] = assembly->tables [MONO_TABLE_FIELD].next_idx;
3421         values [MONO_TYPEDEF_METHOD_LIST] = assembly->tables [MONO_TABLE_METHOD].next_idx;
3422
3423         /*
3424          * if we have explicitlayout or sequentiallayouts, output data in the
3425          * ClassLayout table.
3426          */
3427         if (((tb->attrs & TYPE_ATTRIBUTE_LAYOUT_MASK) != TYPE_ATTRIBUTE_AUTO_LAYOUT) &&
3428                         ((tb->class_size > 0) || (tb->packing_size > 0))) {
3429                 table = &assembly->tables [MONO_TABLE_CLASSLAYOUT];
3430                 table->rows++;
3431                 alloc_table (table, table->rows);
3432                 values = table->values + table->rows * MONO_CLASS_LAYOUT_SIZE;
3433                 values [MONO_CLASS_LAYOUT_PARENT] = tb->table_idx;
3434                 values [MONO_CLASS_LAYOUT_CLASS_SIZE] = tb->class_size;
3435                 values [MONO_CLASS_LAYOUT_PACKING_SIZE] = tb->packing_size;
3436         }
3437
3438         /* handle interfaces */
3439         if (tb->interfaces) {
3440                 table = &assembly->tables [MONO_TABLE_INTERFACEIMPL];
3441                 i = table->rows;
3442                 table->rows += mono_array_length (tb->interfaces);
3443                 alloc_table (table, table->rows);
3444                 values = table->values + (i + 1) * MONO_INTERFACEIMPL_SIZE;
3445                 for (i = 0; i < mono_array_length (tb->interfaces); ++i) {
3446                         MonoReflectionType* iface = (MonoReflectionType*) mono_array_get (tb->interfaces, gpointer, i);
3447                         values [MONO_INTERFACEIMPL_CLASS] = tb->table_idx;
3448                         values [MONO_INTERFACEIMPL_INTERFACE] = mono_image_typedef_or_ref (assembly, mono_reflection_type_get_handle (iface));
3449                         values += MONO_INTERFACEIMPL_SIZE;
3450                 }
3451         }
3452
3453         /* handle fields */
3454         if (tb->fields) {
3455                 table = &assembly->tables [MONO_TABLE_FIELD];
3456                 table->rows += tb->num_fields;
3457                 alloc_table (table, table->rows);
3458                 for (i = 0; i < tb->num_fields; ++i)
3459                         mono_image_get_field_info (
3460                                 mono_array_get (tb->fields, MonoReflectionFieldBuilder*, i), assembly);
3461         }
3462
3463         /* handle constructors */
3464         if (tb->ctors) {
3465                 table = &assembly->tables [MONO_TABLE_METHOD];
3466                 table->rows += mono_array_length (tb->ctors);
3467                 alloc_table (table, table->rows);
3468                 for (i = 0; i < mono_array_length (tb->ctors); ++i)
3469                         mono_image_get_ctor_info (domain,
3470                                 mono_array_get (tb->ctors, MonoReflectionCtorBuilder*, i), assembly);
3471         }
3472
3473         /* handle methods */
3474         if (tb->methods) {
3475                 table = &assembly->tables [MONO_TABLE_METHOD];
3476                 table->rows += tb->num_methods;
3477                 alloc_table (table, table->rows);
3478                 for (i = 0; i < tb->num_methods; ++i)
3479                         mono_image_get_method_info (
3480                                 mono_array_get (tb->methods, MonoReflectionMethodBuilder*, i), assembly);
3481         }
3482
3483         /* Do the same with properties etc.. */
3484         if (tb->events && mono_array_length (tb->events)) {
3485                 table = &assembly->tables [MONO_TABLE_EVENT];
3486                 table->rows += mono_array_length (tb->events);
3487                 alloc_table (table, table->rows);
3488                 table = &assembly->tables [MONO_TABLE_EVENTMAP];
3489                 table->rows ++;
3490                 alloc_table (table, table->rows);
3491                 values = table->values + table->rows * MONO_EVENT_MAP_SIZE;
3492                 values [MONO_EVENT_MAP_PARENT] = tb->table_idx;
3493                 values [MONO_EVENT_MAP_EVENTLIST] = assembly->tables [MONO_TABLE_EVENT].next_idx;
3494                 for (i = 0; i < mono_array_length (tb->events); ++i)
3495                         mono_image_get_event_info (
3496                                 mono_array_get (tb->events, MonoReflectionEventBuilder*, i), assembly);
3497         }
3498         if (tb->properties && mono_array_length (tb->properties)) {
3499                 table = &assembly->tables [MONO_TABLE_PROPERTY];
3500                 table->rows += mono_array_length (tb->properties);
3501                 alloc_table (table, table->rows);
3502                 table = &assembly->tables [MONO_TABLE_PROPERTYMAP];
3503                 table->rows ++;
3504                 alloc_table (table, table->rows);
3505                 values = table->values + table->rows * MONO_PROPERTY_MAP_SIZE;
3506                 values [MONO_PROPERTY_MAP_PARENT] = tb->table_idx;
3507                 values [MONO_PROPERTY_MAP_PROPERTY_LIST] = assembly->tables [MONO_TABLE_PROPERTY].next_idx;
3508                 for (i = 0; i < mono_array_length (tb->properties); ++i)
3509                         mono_image_get_property_info (
3510                                 mono_array_get (tb->properties, MonoReflectionPropertyBuilder*, i), assembly);
3511         }
3512
3513         /* handle generic parameters */
3514         if (tb->generic_params) {
3515                 table = &assembly->tables [MONO_TABLE_GENERICPARAM];
3516                 table->rows += mono_array_length (tb->generic_params);
3517                 alloc_table (table, table->rows);
3518                 for (i = 0; i < mono_array_length (tb->generic_params); ++i) {
3519                         guint32 owner = MONO_TYPEORMETHOD_TYPE | (tb->table_idx << MONO_TYPEORMETHOD_BITS);
3520
3521                         mono_image_get_generic_param_info (
3522                                 mono_array_get (tb->generic_params, MonoReflectionGenericParam*, i), owner, assembly);
3523                 }
3524         }
3525
3526         mono_image_add_decl_security (assembly, 
3527                 mono_metadata_make_token (MONO_TABLE_TYPEDEF, tb->table_idx), tb->permissions);
3528
3529         if (tb->subtypes) {
3530                 MonoDynamicTable *ntable;
3531                 
3532                 ntable = &assembly->tables [MONO_TABLE_NESTEDCLASS];
3533                 ntable->rows += mono_array_length (tb->subtypes);
3534                 alloc_table (ntable, ntable->rows);
3535                 values = ntable->values + ntable->next_idx * MONO_NESTED_CLASS_SIZE;
3536
3537                 for (i = 0; i < mono_array_length (tb->subtypes); ++i) {
3538                         MonoReflectionTypeBuilder *subtype = mono_array_get (tb->subtypes, MonoReflectionTypeBuilder*, i);
3539
3540                         values [MONO_NESTED_CLASS_NESTED] = subtype->table_idx;
3541                         values [MONO_NESTED_CLASS_ENCLOSING] = tb->table_idx;
3542                         /*g_print ("nesting %s (%d) in %s (%d) (rows %d/%d)\n",
3543                                 mono_string_to_utf8 (subtype->name), subtype->table_idx,
3544                                 mono_string_to_utf8 (tb->name), tb->table_idx,
3545                                 ntable->next_idx, ntable->rows);*/
3546                         values += MONO_NESTED_CLASS_SIZE;
3547                         ntable->next_idx++;
3548                 }
3549         }
3550 }
3551 #endif
3552
3553 static void
3554 collect_types (MonoPtrArray *types, MonoReflectionTypeBuilder *type)
3555 {
3556         int i;
3557
3558         mono_ptr_array_append (*types, type);
3559
3560         if (!type->subtypes)
3561                 return;
3562
3563         for (i = 0; i < mono_array_length (type->subtypes); ++i) {
3564                 MonoReflectionTypeBuilder *subtype = mono_array_get (type->subtypes, MonoReflectionTypeBuilder*, i);
3565                 collect_types (types, subtype);
3566         }
3567 }
3568
3569 static gint
3570 compare_types_by_table_idx (MonoReflectionTypeBuilder **type1, MonoReflectionTypeBuilder **type2)
3571 {
3572         if ((*type1)->table_idx < (*type2)->table_idx)
3573                 return -1;
3574         else
3575                 if ((*type1)->table_idx > (*type2)->table_idx)
3576                         return 1;
3577         else
3578                 return 0;
3579 }
3580
3581 static void
3582 params_add_cattrs (MonoDynamicImage *assembly, MonoArray *pinfo) {
3583         int i;
3584
3585         if (!pinfo)
3586                 return;
3587         for (i = 0; i < mono_array_length (pinfo); ++i) {
3588                 MonoReflectionParamBuilder *pb;
3589                 pb = mono_array_get (pinfo, MonoReflectionParamBuilder *, i);
3590                 if (!pb)
3591                         continue;
3592                 mono_image_add_cattrs (assembly, pb->table_idx, MONO_CUSTOM_ATTR_PARAMDEF, pb->cattrs);
3593         }
3594 }
3595
3596 static void
3597 type_add_cattrs (MonoDynamicImage *assembly, MonoReflectionTypeBuilder *tb) {
3598         int i;
3599         
3600         mono_image_add_cattrs (assembly, tb->table_idx, MONO_CUSTOM_ATTR_TYPEDEF, tb->cattrs);
3601         if (tb->fields) {
3602                 for (i = 0; i < tb->num_fields; ++i) {
3603                         MonoReflectionFieldBuilder* fb;
3604                         fb = mono_array_get (tb->fields, MonoReflectionFieldBuilder*, i);
3605                         mono_image_add_cattrs (assembly, fb->table_idx, MONO_CUSTOM_ATTR_FIELDDEF, fb->cattrs);
3606                 }
3607         }
3608         if (tb->events) {
3609                 for (i = 0; i < mono_array_length (tb->events); ++i) {
3610                         MonoReflectionEventBuilder* eb;
3611                         eb = mono_array_get (tb->events, MonoReflectionEventBuilder*, i);
3612                         mono_image_add_cattrs (assembly, eb->table_idx, MONO_CUSTOM_ATTR_EVENT, eb->cattrs);
3613                 }
3614         }
3615         if (tb->properties) {
3616                 for (i = 0; i < mono_array_length (tb->properties); ++i) {
3617                         MonoReflectionPropertyBuilder* pb;
3618                         pb = mono_array_get (tb->properties, MonoReflectionPropertyBuilder*, i);
3619                         mono_image_add_cattrs (assembly, pb->table_idx, MONO_CUSTOM_ATTR_PROPERTY, pb->cattrs);
3620                 }
3621         }
3622         if (tb->ctors) {
3623                 for (i = 0; i < mono_array_length (tb->ctors); ++i) {
3624                         MonoReflectionCtorBuilder* cb;
3625                         cb = mono_array_get (tb->ctors, MonoReflectionCtorBuilder*, i);
3626                         mono_image_add_cattrs (assembly, cb->table_idx, MONO_CUSTOM_ATTR_METHODDEF, cb->cattrs);
3627                         params_add_cattrs (assembly, cb->pinfo);
3628                 }
3629         }
3630
3631         if (tb->methods) {
3632                 for (i = 0; i < tb->num_methods; ++i) {
3633                         MonoReflectionMethodBuilder* mb;
3634                         mb = mono_array_get (tb->methods, MonoReflectionMethodBuilder*, i);
3635                         mono_image_add_cattrs (assembly, mb->table_idx, MONO_CUSTOM_ATTR_METHODDEF, mb->cattrs);
3636                         params_add_cattrs (assembly, mb->pinfo);
3637                 }
3638         }
3639
3640         if (tb->subtypes) {
3641                 for (i = 0; i < mono_array_length (tb->subtypes); ++i)
3642                         type_add_cattrs (assembly, mono_array_get (tb->subtypes, MonoReflectionTypeBuilder*, i));
3643         }
3644 }
3645
3646 static void
3647 module_add_cattrs (MonoDynamicImage *assembly, MonoReflectionModuleBuilder *moduleb)
3648 {
3649         int i;
3650         
3651         mono_image_add_cattrs (assembly, moduleb->table_idx, MONO_CUSTOM_ATTR_MODULE, moduleb->cattrs);
3652
3653         if (moduleb->global_methods) {
3654                 for (i = 0; i < mono_array_length (moduleb->global_methods); ++i) {
3655                         MonoReflectionMethodBuilder* mb = mono_array_get (moduleb->global_methods, MonoReflectionMethodBuilder*, i);
3656                         mono_image_add_cattrs (assembly, mb->table_idx, MONO_CUSTOM_ATTR_METHODDEF, mb->cattrs);
3657                         params_add_cattrs (assembly, mb->pinfo);
3658                 }
3659         }
3660
3661         if (moduleb->global_fields) {
3662                 for (i = 0; i < mono_array_length (moduleb->global_fields); ++i) {
3663                         MonoReflectionFieldBuilder *fb = mono_array_get (moduleb->global_fields, MonoReflectionFieldBuilder*, i);
3664                         mono_image_add_cattrs (assembly, fb->table_idx, MONO_CUSTOM_ATTR_FIELDDEF, fb->cattrs);
3665                 }
3666         }
3667         
3668         if (moduleb->types) {
3669                 for (i = 0; i < moduleb->num_types; ++i)
3670                         type_add_cattrs (assembly, mono_array_get (moduleb->types, MonoReflectionTypeBuilder*, i));
3671         }
3672 }
3673
3674 static void
3675 mono_image_fill_file_table (MonoDomain *domain, MonoReflectionModule *module, MonoDynamicImage *assembly)
3676 {
3677         MonoDynamicTable *table;
3678         guint32 *values;
3679         char blob_size [6];
3680         guchar hash [20];
3681         char *b = blob_size;
3682         char *dir, *path;
3683
3684         table = &assembly->tables [MONO_TABLE_FILE];
3685         table->rows++;
3686         alloc_table (table, table->rows);
3687         values = table->values + table->next_idx * MONO_FILE_SIZE;
3688         values [MONO_FILE_FLAGS] = FILE_CONTAINS_METADATA;
3689         values [MONO_FILE_NAME] = string_heap_insert (&assembly->sheap, module->image->module_name);
3690         if (module->image->dynamic) {
3691                 /* This depends on the fact that the main module is emitted last */
3692                 dir = mono_string_to_utf8 (((MonoReflectionModuleBuilder*)module)->assemblyb->dir);
3693                 path = g_strdup_printf ("%s%c%s", dir, G_DIR_SEPARATOR, module->image->module_name);
3694         } else {
3695                 dir = NULL;
3696                 path = g_strdup (module->image->name);
3697         }
3698         mono_sha1_get_digest_from_file (path, hash);
3699         g_free (dir);
3700         g_free (path);
3701         mono_metadata_encode_value (20, b, &b);
3702         values [MONO_FILE_HASH_VALUE] = mono_image_add_stream_data (&assembly->blob, blob_size, b-blob_size);
3703         mono_image_add_stream_data (&assembly->blob, (char*)hash, 20);
3704         table->next_idx ++;
3705 }
3706
3707 static void
3708 mono_image_fill_module_table (MonoDomain *domain, MonoReflectionModuleBuilder *mb, MonoDynamicImage *assembly)
3709 {
3710         MonoDynamicTable *table;
3711         int i;
3712
3713         table = &assembly->tables [MONO_TABLE_MODULE];
3714         mb->table_idx = table->next_idx ++;
3715         table->values [mb->table_idx * MONO_MODULE_SIZE + MONO_MODULE_NAME] = string_heap_insert_mstring (&assembly->sheap, mb->module.name);
3716         i = mono_image_add_stream_data (&assembly->guid, mono_array_addr (mb->guid, char, 0), 16);
3717         i /= 16;
3718         ++i;
3719         table->values [mb->table_idx * MONO_MODULE_SIZE + MONO_MODULE_GENERATION] = 0;
3720         table->values [mb->table_idx * MONO_MODULE_SIZE + MONO_MODULE_MVID] = i;
3721         table->values [mb->table_idx * MONO_MODULE_SIZE + MONO_MODULE_ENC] = 0;
3722         table->values [mb->table_idx * MONO_MODULE_SIZE + MONO_MODULE_ENCBASE] = 0;
3723 }
3724
3725 static guint32
3726 mono_image_fill_export_table_from_class (MonoDomain *domain, MonoClass *klass,
3727         guint32 module_index, guint32 parent_index, MonoDynamicImage *assembly)
3728 {
3729         MonoDynamicTable *table;
3730         guint32 *values;
3731         guint32 visib, res;
3732
3733         visib = klass->flags & TYPE_ATTRIBUTE_VISIBILITY_MASK;
3734         if (! ((visib & TYPE_ATTRIBUTE_PUBLIC) || (visib & TYPE_ATTRIBUTE_NESTED_PUBLIC)))
3735                 return 0;
3736
3737         table = &assembly->tables [MONO_TABLE_EXPORTEDTYPE];
3738         table->rows++;
3739         alloc_table (table, table->rows);
3740         values = table->values + table->next_idx * MONO_EXP_TYPE_SIZE;
3741
3742         values [MONO_EXP_TYPE_FLAGS] = klass->flags;
3743         values [MONO_EXP_TYPE_TYPEDEF] = klass->type_token;
3744         if (klass->nested_in)
3745                 values [MONO_EXP_TYPE_IMPLEMENTATION] = (parent_index << MONO_IMPLEMENTATION_BITS) + MONO_IMPLEMENTATION_EXP_TYPE;
3746         else
3747                 values [MONO_EXP_TYPE_IMPLEMENTATION] = (module_index << MONO_IMPLEMENTATION_BITS) + MONO_IMPLEMENTATION_FILE;
3748         values [MONO_EXP_TYPE_NAME] = string_heap_insert (&assembly->sheap, klass->name);
3749         values [MONO_EXP_TYPE_NAMESPACE] = string_heap_insert (&assembly->sheap, klass->name_space);
3750
3751         res = table->next_idx;
3752
3753         table->next_idx ++;
3754
3755         /* Emit nested types */
3756         if (klass->ext && klass->ext->nested_classes) {
3757                 GList *tmp;
3758
3759                 for (tmp = klass->ext->nested_classes; tmp; tmp = tmp->next)
3760                         mono_image_fill_export_table_from_class (domain, tmp->data, module_index, table->next_idx - 1, assembly);
3761         }
3762
3763         return res;
3764 }
3765
3766 static void
3767 mono_image_fill_export_table (MonoDomain *domain, MonoReflectionTypeBuilder *tb,
3768         guint32 module_index, guint32 parent_index, MonoDynamicImage *assembly)
3769 {
3770         MonoClass *klass;
3771         guint32 idx, i;
3772
3773         klass = mono_class_from_mono_type (mono_reflection_type_get_handle ((MonoReflectionType*)tb));
3774
3775         klass->type_token = mono_metadata_make_token (MONO_TABLE_TYPEDEF, tb->table_idx);
3776
3777         idx = mono_image_fill_export_table_from_class (domain, klass, module_index, 
3778                                                                                                    parent_index, assembly);
3779
3780         /* 
3781          * Emit nested types
3782          * We need to do this ourselves since klass->nested_classes is not set up.
3783          */
3784         if (tb->subtypes) {
3785                 for (i = 0; i < mono_array_length (tb->subtypes); ++i)
3786                         mono_image_fill_export_table (domain, mono_array_get (tb->subtypes, MonoReflectionTypeBuilder*, i), module_index, idx, assembly);
3787         }
3788 }
3789
3790 static void
3791 mono_image_fill_export_table_from_module (MonoDomain *domain, MonoReflectionModule *module,
3792         guint32 module_index, MonoDynamicImage *assembly)
3793 {
3794         MonoImage *image = module->image;
3795         MonoTableInfo  *t;
3796         guint32 i;
3797
3798         t = &image->tables [MONO_TABLE_TYPEDEF];
3799
3800         for (i = 0; i < t->rows; ++i) {
3801                 MonoClass *klass = mono_class_get (image, mono_metadata_make_token (MONO_TABLE_TYPEDEF, i + 1));
3802
3803                 if (klass->flags & TYPE_ATTRIBUTE_PUBLIC)
3804                         mono_image_fill_export_table_from_class (domain, klass, module_index, 0, assembly);
3805         }
3806 }
3807
3808 static void
3809 add_exported_type (MonoReflectionAssemblyBuilder *assemblyb, MonoDynamicImage *assembly, MonoClass *klass, guint32 parent_index)
3810 {
3811         MonoDynamicTable *table;
3812         guint32 *values;
3813         guint32 scope, scope_idx, impl, current_idx;
3814         gboolean forwarder = TRUE;
3815         gpointer iter = NULL;
3816         MonoClass *nested;
3817
3818         if (klass->nested_in) {
3819                 impl = (parent_index << MONO_IMPLEMENTATION_BITS) + MONO_IMPLEMENTATION_EXP_TYPE;
3820                 forwarder = FALSE;
3821         } else {
3822                 scope = resolution_scope_from_image (assembly, klass->image);
3823                 g_assert ((scope & MONO_RESOLTION_SCOPE_MASK) == MONO_RESOLTION_SCOPE_ASSEMBLYREF);
3824                 scope_idx = scope >> MONO_RESOLTION_SCOPE_BITS;
3825                 impl = (scope_idx << MONO_IMPLEMENTATION_BITS) + MONO_IMPLEMENTATION_ASSEMBLYREF;
3826         }
3827
3828         table = &assembly->tables [MONO_TABLE_EXPORTEDTYPE];
3829
3830         table->rows++;
3831         alloc_table (table, table->rows);
3832         current_idx = table->next_idx;
3833         values = table->values + current_idx * MONO_EXP_TYPE_SIZE;
3834
3835         values [MONO_EXP_TYPE_FLAGS] = forwarder ? TYPE_ATTRIBUTE_FORWARDER : 0;
3836         values [MONO_EXP_TYPE_TYPEDEF] = 0;
3837         values [MONO_EXP_TYPE_IMPLEMENTATION] = impl;
3838         values [MONO_EXP_TYPE_NAME] = string_heap_insert (&assembly->sheap, klass->name);
3839         values [MONO_EXP_TYPE_NAMESPACE] = string_heap_insert (&assembly->sheap, klass->name_space);
3840
3841         table->next_idx++;
3842
3843         while ((nested = mono_class_get_nested_types (klass, &iter)))
3844                 add_exported_type (assemblyb, assembly, nested, current_idx);
3845 }
3846
3847 static void
3848 mono_image_fill_export_table_from_type_forwarders (MonoReflectionAssemblyBuilder *assemblyb, MonoDynamicImage *assembly)
3849 {
3850         MonoClass *klass;
3851         int i;
3852
3853         if (!assemblyb->type_forwarders)
3854                 return;
3855
3856         for (i = 0; i < mono_array_length (assemblyb->type_forwarders); ++i) {
3857                 MonoReflectionType *t = mono_array_get (assemblyb->type_forwarders, MonoReflectionType *, i);
3858                 MonoType *type;
3859                 if (!t)
3860                         continue;
3861
3862                 type = mono_reflection_type_get_handle (t);
3863                 g_assert (type);
3864
3865                 klass = mono_class_from_mono_type (type);
3866
3867                 add_exported_type (assemblyb, assembly, klass, 0);
3868         }
3869 }
3870
3871 #define align_pointer(base,p)\
3872         do {\
3873                 guint32 __diff = (unsigned char*)(p)-(unsigned char*)(base);\
3874                 if (__diff & 3)\
3875                         (p) += 4 - (__diff & 3);\
3876         } while (0)
3877
3878 static int
3879 compare_constants (const void *a, const void *b)
3880 {
3881         const guint32 *a_values = a;
3882         const guint32 *b_values = b;
3883         return a_values [MONO_CONSTANT_PARENT] - b_values [MONO_CONSTANT_PARENT];
3884 }
3885
3886 static int
3887 compare_semantics (const void *a, const void *b)
3888 {
3889         const guint32 *a_values = a;
3890         const guint32 *b_values = b;
3891         int assoc = a_values [MONO_METHOD_SEMA_ASSOCIATION] - b_values [MONO_METHOD_SEMA_ASSOCIATION];
3892         if (assoc)
3893                 return assoc;
3894         return a_values [MONO_METHOD_SEMA_SEMANTICS] - b_values [MONO_METHOD_SEMA_SEMANTICS];
3895 }
3896
3897 static int
3898 compare_custom_attrs (const void *a, const void *b)
3899 {
3900         const guint32 *a_values = a;
3901         const guint32 *b_values = b;
3902
3903         return a_values [MONO_CUSTOM_ATTR_PARENT] - b_values [MONO_CUSTOM_ATTR_PARENT];
3904 }
3905
3906 static int
3907 compare_field_marshal (const void *a, const void *b)
3908 {
3909         const guint32 *a_values = a;
3910         const guint32 *b_values = b;
3911
3912         return a_values [MONO_FIELD_MARSHAL_PARENT] - b_values [MONO_FIELD_MARSHAL_PARENT];
3913 }
3914
3915 static int
3916 compare_nested (const void *a, const void *b)
3917 {
3918         const guint32 *a_values = a;
3919         const guint32 *b_values = b;
3920
3921         return a_values [MONO_NESTED_CLASS_NESTED] - b_values [MONO_NESTED_CLASS_NESTED];
3922 }
3923
3924 static int
3925 compare_genericparam (const void *a, const void *b)
3926 {
3927         const GenericParamTableEntry **a_entry = (const GenericParamTableEntry **) a;
3928         const GenericParamTableEntry **b_entry = (const GenericParamTableEntry **) b;
3929
3930         if ((*b_entry)->owner == (*a_entry)->owner)
3931                 return 
3932                         mono_type_get_generic_param_num (mono_reflection_type_get_handle ((MonoReflectionType*)(*a_entry)->gparam)) -
3933                         mono_type_get_generic_param_num (mono_reflection_type_get_handle ((MonoReflectionType*)(*b_entry)->gparam));
3934         else
3935                 return (*a_entry)->owner - (*b_entry)->owner;
3936 }
3937
3938 static int
3939 compare_declsecurity_attrs (const void *a, const void *b)
3940 {
3941         const guint32 *a_values = a;
3942         const guint32 *b_values = b;
3943
3944         return a_values [MONO_DECL_SECURITY_PARENT] - b_values [MONO_DECL_SECURITY_PARENT];
3945 }
3946
3947 static int
3948 compare_interface_impl (const void *a, const void *b)
3949 {
3950         const guint32 *a_values = a;
3951         const guint32 *b_values = b;
3952
3953         int klass = a_values [MONO_INTERFACEIMPL_CLASS] - b_values [MONO_INTERFACEIMPL_CLASS];
3954         if (klass)
3955                 return klass;
3956
3957         return a_values [MONO_INTERFACEIMPL_INTERFACE] - b_values [MONO_INTERFACEIMPL_INTERFACE];
3958 }
3959
3960 static void
3961 pad_heap (MonoDynamicStream *sh)
3962 {
3963         if (sh->index & 3) {
3964                 int sz = 4 - (sh->index & 3);
3965                 memset (sh->data + sh->index, 0, sz);
3966                 sh->index += sz;
3967         }
3968 }
3969
3970 struct StreamDesc {
3971         const char *name;
3972         MonoDynamicStream *stream;
3973 };
3974
3975 /*
3976  * build_compressed_metadata() fills in the blob of data that represents the 
3977  * raw metadata as it will be saved in the PE file. The five streams are output 
3978  * and the metadata tables are comnpressed from the guint32 array representation, 
3979  * to the compressed on-disk format.
3980  */
3981 static void
3982 build_compressed_metadata (MonoDynamicImage *assembly)
3983 {
3984         MonoDynamicTable *table;
3985         int i;
3986         guint64 valid_mask = 0;
3987         guint64 sorted_mask;
3988         guint32 heapt_size = 0;
3989         guint32 meta_size = 256; /* allow for header and other stuff */
3990         guint32 table_offset;
3991         guint32 ntables = 0;
3992         guint64 *int64val;
3993         guint32 *int32val;
3994         guint16 *int16val;
3995         MonoImage *meta;
3996         unsigned char *p;
3997         struct StreamDesc stream_desc [5];
3998
3999         qsort (assembly->gen_params->pdata, assembly->gen_params->len, sizeof (gpointer), compare_genericparam);
4000         for (i = 0; i < assembly->gen_params->len; i++){
4001                 GenericParamTableEntry *entry = g_ptr_array_index (assembly->gen_params, i);
4002                 write_generic_param_entry (assembly, entry);
4003         }
4004
4005         stream_desc [0].name  = "#~";
4006         stream_desc [0].stream = &assembly->tstream;
4007         stream_desc [1].name  = "#Strings";
4008         stream_desc [1].stream = &assembly->sheap;
4009         stream_desc [2].name  = "#US";
4010         stream_desc [2].stream = &assembly->us;
4011         stream_desc [3].name  = "#Blob";
4012         stream_desc [3].stream = &assembly->blob;
4013         stream_desc [4].name  = "#GUID";
4014         stream_desc [4].stream = &assembly->guid;
4015         
4016         /* tables that are sorted */
4017         sorted_mask = ((guint64)1 << MONO_TABLE_CONSTANT) | ((guint64)1 << MONO_TABLE_FIELDMARSHAL)
4018                 | ((guint64)1 << MONO_TABLE_METHODSEMANTICS) | ((guint64)1 << MONO_TABLE_CLASSLAYOUT)
4019                 | ((guint64)1 << MONO_TABLE_FIELDLAYOUT) | ((guint64)1 << MONO_TABLE_FIELDRVA)
4020                 | ((guint64)1 << MONO_TABLE_IMPLMAP) | ((guint64)1 << MONO_TABLE_NESTEDCLASS)
4021                 | ((guint64)1 << MONO_TABLE_METHODIMPL) | ((guint64)1 << MONO_TABLE_CUSTOMATTRIBUTE)
4022                 | ((guint64)1 << MONO_TABLE_DECLSECURITY) | ((guint64)1 << MONO_TABLE_GENERICPARAM)
4023                 | ((guint64)1 << MONO_TABLE_INTERFACEIMPL);
4024         
4025         /* Compute table sizes */
4026         /* the MonoImage has already been created in mono_image_basic_init() */
4027         meta = &assembly->image;
4028
4029         /* sizes should be multiple of 4 */
4030         pad_heap (&assembly->blob);
4031         pad_heap (&assembly->guid);
4032         pad_heap (&assembly->sheap);
4033         pad_heap (&assembly->us);
4034
4035         /* Setup the info used by compute_sizes () */
4036         meta->idx_blob_wide = assembly->blob.index >= 65536 ? 1 : 0;
4037         meta->idx_guid_wide = assembly->guid.index >= 65536 ? 1 : 0;
4038         meta->idx_string_wide = assembly->sheap.index >= 65536 ? 1 : 0;
4039
4040         meta_size += assembly->blob.index;
4041         meta_size += assembly->guid.index;
4042         meta_size += assembly->sheap.index;
4043         meta_size += assembly->us.index;
4044
4045         for (i=0; i < MONO_TABLE_NUM; ++i)
4046                 meta->tables [i].rows = assembly->tables [i].rows;
4047         
4048         for (i = 0; i < MONO_TABLE_NUM; i++){
4049                 if (meta->tables [i].rows == 0)
4050                         continue;
4051                 valid_mask |= (guint64)1 << i;
4052                 ntables ++;
4053                 meta->tables [i].row_size = mono_metadata_compute_size (
4054                         meta, i, &meta->tables [i].size_bitfield);
4055                 heapt_size += meta->tables [i].row_size * meta->tables [i].rows;
4056         }
4057         heapt_size += 24; /* #~ header size */
4058         heapt_size += ntables * 4;
4059         /* make multiple of 4 */
4060         heapt_size += 3;
4061         heapt_size &= ~3;
4062         meta_size += heapt_size;
4063         meta->raw_metadata = g_malloc0 (meta_size);
4064         p = (unsigned char*)meta->raw_metadata;
4065         /* the metadata signature */
4066         *p++ = 'B'; *p++ = 'S'; *p++ = 'J'; *p++ = 'B';
4067         /* version numbers and 4 bytes reserved */
4068         int16val = (guint16*)p;
4069         *int16val++ = GUINT16_TO_LE (meta->md_version_major);
4070         *int16val = GUINT16_TO_LE (meta->md_version_minor);
4071         p += 8;
4072         /* version string */
4073         int32val = (guint32*)p;
4074         *int32val = GUINT32_TO_LE ((strlen (meta->version) + 3) & (~3)); /* needs to be multiple of 4 */
4075         p += 4;
4076         memcpy (p, meta->version, strlen (meta->version));
4077         p += GUINT32_FROM_LE (*int32val);
4078         align_pointer (meta->raw_metadata, p);
4079         int16val = (guint16*)p;
4080         *int16val++ = GUINT16_TO_LE (0); /* flags must be 0 */
4081         *int16val = GUINT16_TO_LE (5); /* number of streams */
4082         p += 4;
4083
4084         /*
4085          * write the stream info.
4086          */
4087         table_offset = (p - (unsigned char*)meta->raw_metadata) + 5 * 8 + 40; /* room needed for stream headers */
4088         table_offset += 3; table_offset &= ~3;
4089
4090         assembly->tstream.index = heapt_size;
4091         for (i = 0; i < 5; ++i) {
4092                 int32val = (guint32*)p;
4093                 stream_desc [i].stream->offset = table_offset;
4094                 *int32val++ = GUINT32_TO_LE (table_offset);
4095                 *int32val = GUINT32_TO_LE (stream_desc [i].stream->index);
4096                 table_offset += GUINT32_FROM_LE (*int32val);
4097                 table_offset += 3; table_offset &= ~3;
4098                 p += 8;
4099                 strcpy ((char*)p, stream_desc [i].name);
4100                 p += strlen (stream_desc [i].name) + 1;
4101                 align_pointer (meta->raw_metadata, p);
4102         }
4103         /* 
4104          * now copy the data, the table stream header and contents goes first.
4105          */
4106         g_assert ((p - (unsigned char*)meta->raw_metadata) < assembly->tstream.offset);
4107         p = (guchar*)meta->raw_metadata + assembly->tstream.offset;
4108         int32val = (guint32*)p;
4109         *int32val = GUINT32_TO_LE (0); /* reserved */
4110         p += 4;
4111
4112         *p++ = 2; /* version */
4113         *p++ = 0;
4114
4115         if (meta->idx_string_wide)
4116                 *p |= 0x01;
4117         if (meta->idx_guid_wide)
4118                 *p |= 0x02;
4119         if (meta->idx_blob_wide)
4120                 *p |= 0x04;
4121         ++p;
4122         *p++ = 1; /* reserved */
4123         int64val = (guint64*)p;
4124         *int64val++ = GUINT64_TO_LE (valid_mask);
4125         *int64val++ = GUINT64_TO_LE (valid_mask & sorted_mask); /* bitvector of sorted tables  */
4126         p += 16;
4127         int32val = (guint32*)p;
4128         for (i = 0; i < MONO_TABLE_NUM; i++){
4129                 if (meta->tables [i].rows == 0)
4130                         continue;
4131                 *int32val++ = GUINT32_TO_LE (meta->tables [i].rows);
4132         }
4133         p = (unsigned char*)int32val;
4134
4135         /* sort the tables that still need sorting */
4136         table = &assembly->tables [MONO_TABLE_CONSTANT];
4137         if (table->rows)
4138                 qsort (table->values + MONO_CONSTANT_SIZE, table->rows, sizeof (guint32) * MONO_CONSTANT_SIZE, compare_constants);
4139         table = &assembly->tables [MONO_TABLE_METHODSEMANTICS];
4140         if (table->rows)
4141                 qsort (table->values + MONO_METHOD_SEMA_SIZE, table->rows, sizeof (guint32) * MONO_METHOD_SEMA_SIZE, compare_semantics);
4142         table = &assembly->tables [MONO_TABLE_CUSTOMATTRIBUTE];
4143         if (table->rows)
4144                 qsort (table->values + MONO_CUSTOM_ATTR_SIZE, table->rows, sizeof (guint32) * MONO_CUSTOM_ATTR_SIZE, compare_custom_attrs);
4145         table = &assembly->tables [MONO_TABLE_FIELDMARSHAL];
4146         if (table->rows)
4147                 qsort (table->values + MONO_FIELD_MARSHAL_SIZE, table->rows, sizeof (guint32) * MONO_FIELD_MARSHAL_SIZE, compare_field_marshal);
4148         table = &assembly->tables [MONO_TABLE_NESTEDCLASS];
4149         if (table->rows)
4150                 qsort (table->values + MONO_NESTED_CLASS_SIZE, table->rows, sizeof (guint32) * MONO_NESTED_CLASS_SIZE, compare_nested);
4151         /* Section 21.11 DeclSecurity in Partition II doesn't specify this to be sorted by MS implementation requires it */
4152         table = &assembly->tables [MONO_TABLE_DECLSECURITY];
4153         if (table->rows)
4154                 qsort (table->values + MONO_DECL_SECURITY_SIZE, table->rows, sizeof (guint32) * MONO_DECL_SECURITY_SIZE, compare_declsecurity_attrs);
4155         table = &assembly->tables [MONO_TABLE_INTERFACEIMPL];
4156         if (table->rows)
4157                 qsort (table->values + MONO_INTERFACEIMPL_SIZE, table->rows, sizeof (guint32) * MONO_INTERFACEIMPL_SIZE, compare_interface_impl);
4158
4159         /* compress the tables */
4160         for (i = 0; i < MONO_TABLE_NUM; i++){
4161                 int row, col;
4162                 guint32 *values;
4163                 guint32 bitfield = meta->tables [i].size_bitfield;
4164                 if (!meta->tables [i].rows)
4165                         continue;
4166                 if (assembly->tables [i].columns != mono_metadata_table_count (bitfield))
4167                         g_error ("col count mismatch in %d: %d %d", i, assembly->tables [i].columns, mono_metadata_table_count (bitfield));
4168                 meta->tables [i].base = (char*)p;
4169                 for (row = 1; row <= meta->tables [i].rows; ++row) {
4170                         values = assembly->tables [i].values + row * assembly->tables [i].columns;
4171                         for (col = 0; col < assembly->tables [i].columns; ++col) {
4172                                 switch (mono_metadata_table_size (bitfield, col)) {
4173                                 case 1:
4174                                         *p++ = values [col];
4175                                         break;
4176                                 case 2:
4177                                         *p++ = values [col] & 0xff;
4178                                         *p++ = (values [col] >> 8) & 0xff;
4179                                         break;
4180                                 case 4:
4181                                         *p++ = values [col] & 0xff;
4182                                         *p++ = (values [col] >> 8) & 0xff;
4183                                         *p++ = (values [col] >> 16) & 0xff;
4184                                         *p++ = (values [col] >> 24) & 0xff;
4185                                         break;
4186                                 default:
4187                                         g_assert_not_reached ();
4188                                 }
4189                         }
4190                 }
4191                 g_assert ((p - (const unsigned char*)meta->tables [i].base) == (meta->tables [i].rows * meta->tables [i].row_size));
4192         }
4193         
4194         g_assert (assembly->guid.offset + assembly->guid.index < meta_size);
4195         memcpy (meta->raw_metadata + assembly->sheap.offset, assembly->sheap.data, assembly->sheap.index);
4196         memcpy (meta->raw_metadata + assembly->us.offset, assembly->us.data, assembly->us.index);
4197         memcpy (meta->raw_metadata + assembly->blob.offset, assembly->blob.data, assembly->blob.index);
4198         memcpy (meta->raw_metadata + assembly->guid.offset, assembly->guid.data, assembly->guid.index);
4199
4200         assembly->meta_size = assembly->guid.offset + assembly->guid.index;
4201 }
4202
4203 /*
4204  * Some tables in metadata need to be sorted according to some criteria, but
4205  * when methods and fields are first created with reflection, they may be assigned a token
4206  * that doesn't correspond to the final token they will get assigned after the sorting.
4207  * ILGenerator.cs keeps a fixup table that maps the position of tokens in the IL code stream
4208  * with the reflection objects that represent them. Once all the tables are set up, the 
4209  * reflection objects will contains the correct table index. fixup_method() will fixup the
4210  * tokens for the method with ILGenerator @ilgen.
4211  */
4212 static void
4213 fixup_method (MonoReflectionILGen *ilgen, gpointer value, MonoDynamicImage *assembly)
4214 {
4215         guint32 code_idx = GPOINTER_TO_UINT (value);
4216         MonoReflectionILTokenInfo *iltoken;
4217         MonoReflectionFieldBuilder *field;
4218         MonoReflectionCtorBuilder *ctor;
4219         MonoReflectionMethodBuilder *method;
4220         MonoReflectionTypeBuilder *tb;
4221         MonoReflectionArrayMethod *am;
4222         guint32 i, idx = 0;
4223         unsigned char *target;
4224
4225         for (i = 0; i < ilgen->num_token_fixups; ++i) {
4226                 iltoken = (MonoReflectionILTokenInfo *)mono_array_addr_with_size (ilgen->token_fixups, sizeof (MonoReflectionILTokenInfo), i);
4227                 target = (guchar*)assembly->code.data + code_idx + iltoken->code_pos;
4228                 switch (target [3]) {
4229                 case MONO_TABLE_FIELD:
4230                         if (!strcmp (iltoken->member->vtable->klass->name, "FieldBuilder")) {
4231                                 field = (MonoReflectionFieldBuilder *)iltoken->member;
4232                                 idx = field->table_idx;
4233                         } else if (!strcmp (iltoken->member->vtable->klass->name, "MonoField")) {
4234                                 MonoClassField *f = ((MonoReflectionField*)iltoken->member)->field;
4235                                 idx = GPOINTER_TO_UINT (g_hash_table_lookup (assembly->field_to_table_idx, f));
4236                         } else {
4237                                 g_assert_not_reached ();
4238                         }
4239                         break;
4240                 case MONO_TABLE_METHOD:
4241                         if (!strcmp (iltoken->member->vtable->klass->name, "MethodBuilder")) {
4242                                 method = (MonoReflectionMethodBuilder *)iltoken->member;
4243                                 idx = method->table_idx;
4244                         } else if (!strcmp (iltoken->member->vtable->klass->name, "ConstructorBuilder")) {
4245                                 ctor = (MonoReflectionCtorBuilder *)iltoken->member;
4246                                 idx = ctor->table_idx;
4247                         } else if (!strcmp (iltoken->member->vtable->klass->name, "MonoMethod") || 
4248                                            !strcmp (iltoken->member->vtable->klass->name, "MonoCMethod")) {
4249                                 MonoMethod *m = ((MonoReflectionMethod*)iltoken->member)->method;
4250                                 idx = GPOINTER_TO_UINT (g_hash_table_lookup (assembly->method_to_table_idx, m));
4251                         } else {
4252                                 g_assert_not_reached ();
4253                         }
4254                         break;
4255                 case MONO_TABLE_TYPEDEF:
4256                         if (strcmp (iltoken->member->vtable->klass->name, "TypeBuilder"))
4257                                 g_assert_not_reached ();
4258                         tb = (MonoReflectionTypeBuilder *)iltoken->member;
4259                         idx = tb->table_idx;
4260                         break;
4261                 case MONO_TABLE_MEMBERREF:
4262                         if (!strcmp (iltoken->member->vtable->klass->name, "MonoArrayMethod")) {
4263                                 am = (MonoReflectionArrayMethod*)iltoken->member;
4264                                 idx = am->table_idx;
4265                         } else if (!strcmp (iltoken->member->vtable->klass->name, "MonoMethod") ||
4266                                    !strcmp (iltoken->member->vtable->klass->name, "MonoCMethod") ||
4267                                    !strcmp (iltoken->member->vtable->klass->name, "MonoGenericMethod") ||
4268                                    !strcmp (iltoken->member->vtable->klass->name, "MonoGenericCMethod")) {
4269                                 MonoMethod *m = ((MonoReflectionMethod*)iltoken->member)->method;
4270                                 g_assert (m->klass->generic_class || m->klass->generic_container);
4271                                 continue;
4272                         } else if (!strcmp (iltoken->member->vtable->klass->name, "FieldBuilder")) {
4273                                 continue;
4274                         } else if (!strcmp (iltoken->member->vtable->klass->name, "MonoField")) {
4275                                 MonoClassField *f = ((MonoReflectionField*)iltoken->member)->field;
4276                                 g_assert (is_field_on_inst (f));
4277                                 continue;
4278                         } else if (!strcmp (iltoken->member->vtable->klass->name, "MethodBuilder") ||
4279                                         !strcmp (iltoken->member->vtable->klass->name, "ConstructorBuilder")) {
4280                                 continue;
4281                         } else if (!strcmp (iltoken->member->vtable->klass->name, "FieldOnTypeBuilderInst")) {
4282                                 continue;
4283                         } else if (!strcmp (iltoken->member->vtable->klass->name, "MethodOnTypeBuilderInst")) {
4284                                 continue;
4285                         } else if (!strcmp (iltoken->member->vtable->klass->name, "ConstructorOnTypeBuilderInst")) {
4286                                 continue;
4287                         } else {
4288                                 g_assert_not_reached ();
4289                         }
4290                         break;
4291                 case MONO_TABLE_METHODSPEC:
4292                         if (!strcmp (iltoken->member->vtable->klass->name, "MonoGenericMethod")) {
4293                                 MonoMethod *m = ((MonoReflectionMethod*)iltoken->member)->method;
4294                                 g_assert (mono_method_signature (m)->generic_param_count);
4295                                 continue;
4296                         } else if (!strcmp (iltoken->member->vtable->klass->name, "MethodBuilder")) {
4297                                 continue;
4298                         } else if (!strcmp (iltoken->member->vtable->klass->name, "MethodOnTypeBuilderInst")) {
4299                                 continue;
4300                         } else {
4301                                 g_assert_not_reached ();
4302                         }
4303                         break;
4304                 default:
4305                         g_error ("got unexpected table 0x%02x in fixup", target [3]);
4306                 }
4307                 target [0] = idx & 0xff;
4308                 target [1] = (idx >> 8) & 0xff;
4309                 target [2] = (idx >> 16) & 0xff;
4310         }
4311 }
4312
4313 /*
4314  * fixup_cattrs:
4315  *
4316  *   The CUSTOM_ATTRIBUTE table might contain METHODDEF tokens whose final
4317  * value is not known when the table is emitted.
4318  */
4319 static void
4320 fixup_cattrs (MonoDynamicImage *assembly)
4321 {
4322         MonoDynamicTable *table;
4323         guint32 *values;
4324         guint32 type, i, idx, token;
4325         MonoObject *ctor;
4326
4327         table = &assembly->tables [MONO_TABLE_CUSTOMATTRIBUTE];
4328
4329         for (i = 0; i < table->rows; ++i) {
4330                 values = table->values + ((i + 1) * MONO_CUSTOM_ATTR_SIZE);
4331
4332                 type = values [MONO_CUSTOM_ATTR_TYPE];
4333                 if ((type & MONO_CUSTOM_ATTR_TYPE_MASK) == MONO_CUSTOM_ATTR_TYPE_METHODDEF) {
4334                         idx = type >> MONO_CUSTOM_ATTR_TYPE_BITS;
4335                         token = mono_metadata_make_token (MONO_TABLE_METHOD, idx);
4336                         ctor = mono_g_hash_table_lookup (assembly->remapped_tokens, GUINT_TO_POINTER (token));
4337                         g_assert (ctor);
4338
4339                         if (!strcmp (ctor->vtable->klass->name, "MonoCMethod")) {
4340                                 MonoMethod *m = ((MonoReflectionMethod*)ctor)->method;
4341                                 idx = GPOINTER_TO_UINT (g_hash_table_lookup (assembly->method_to_table_idx, m));
4342                                 values [MONO_CUSTOM_ATTR_TYPE] = (idx << MONO_CUSTOM_ATTR_TYPE_BITS) | MONO_CUSTOM_ATTR_TYPE_METHODDEF;
4343                         } else if (!strcmp (ctor->vtable->klass->name, "ConstructorBuilder")) {
4344                                 MonoMethod *m = ((MonoReflectionCtorBuilder*)ctor)->mhandle;
4345                                 idx = GPOINTER_TO_UINT (g_hash_table_lookup (assembly->method_to_table_idx, m));
4346                                 values [MONO_CUSTOM_ATTR_TYPE] = (idx << MONO_CUSTOM_ATTR_TYPE_BITS) | MONO_CUSTOM_ATTR_TYPE_METHODDEF;
4347                         }
4348                 }
4349         }
4350 }
4351
4352 static void
4353 assembly_add_resource_manifest (MonoReflectionModuleBuilder *mb, MonoDynamicImage *assembly, MonoReflectionResource *rsrc, guint32 implementation)
4354 {
4355         MonoDynamicTable *table;
4356         guint32 *values;
4357
4358         table = &assembly->tables [MONO_TABLE_MANIFESTRESOURCE];
4359         table->rows++;
4360         alloc_table (table, table->rows);
4361         values = table->values + table->next_idx * MONO_MANIFEST_SIZE;
4362         values [MONO_MANIFEST_OFFSET] = rsrc->offset;
4363         values [MONO_MANIFEST_FLAGS] = rsrc->attrs;
4364         values [MONO_MANIFEST_NAME] = string_heap_insert_mstring (&assembly->sheap, rsrc->name);
4365         values [MONO_MANIFEST_IMPLEMENTATION] = implementation;
4366         table->next_idx++;
4367 }
4368
4369 static void
4370 assembly_add_resource (MonoReflectionModuleBuilder *mb, MonoDynamicImage *assembly, MonoReflectionResource *rsrc)
4371 {
4372         MonoDynamicTable *table;
4373         guint32 *values;
4374         char blob_size [6];
4375         guchar hash [20];
4376         char *b = blob_size;
4377         char *name, *sname;
4378         guint32 idx, offset;
4379
4380         if (rsrc->filename) {
4381                 name = mono_string_to_utf8 (rsrc->filename);
4382                 sname = g_path_get_basename (name);
4383         
4384                 table = &assembly->tables [MONO_TABLE_FILE];
4385                 table->rows++;
4386                 alloc_table (table, table->rows);
4387                 values = table->values + table->next_idx * MONO_FILE_SIZE;
4388                 values [MONO_FILE_FLAGS] = FILE_CONTAINS_NO_METADATA;
4389                 values [MONO_FILE_NAME] = string_heap_insert (&assembly->sheap, sname);
4390                 g_free (sname);
4391
4392                 mono_sha1_get_digest_from_file (name, hash);
4393                 mono_metadata_encode_value (20, b, &b);
4394                 values [MONO_FILE_HASH_VALUE] = mono_image_add_stream_data (&assembly->blob, blob_size, b-blob_size);
4395                 mono_image_add_stream_data (&assembly->blob, (char*)hash, 20);
4396                 g_free (name);
4397                 idx = table->next_idx++;
4398                 rsrc->offset = 0;
4399                 idx = MONO_IMPLEMENTATION_FILE | (idx << MONO_IMPLEMENTATION_BITS);
4400         } else {
4401                 char sizebuf [4];
4402                 char *data;
4403                 guint len;
4404                 if (rsrc->data) {
4405                         data = mono_array_addr (rsrc->data, char, 0);
4406                         len = mono_array_length (rsrc->data);
4407                 } else {
4408                         data = NULL;
4409                         len = 0;
4410                 }
4411                 offset = len;
4412                 sizebuf [0] = offset; sizebuf [1] = offset >> 8;
4413                 sizebuf [2] = offset >> 16; sizebuf [3] = offset >> 24;
4414                 rsrc->offset = mono_image_add_stream_data (&assembly->resources, sizebuf, 4);
4415                 mono_image_add_stream_data (&assembly->resources, data, len);
4416
4417                 if (!mb->is_main)
4418                         /* 
4419                          * The entry should be emitted into the MANIFESTRESOURCE table of 
4420                          * the main module, but that needs to reference the FILE table
4421                          * which isn't emitted yet.
4422                          */
4423                         return;
4424                 else
4425                         idx = 0;
4426         }
4427
4428         assembly_add_resource_manifest (mb, assembly, rsrc, idx);
4429 }
4430
4431 static void
4432 set_version_from_string (MonoString *version, guint32 *values)
4433 {
4434         gchar *ver, *p, *str;
4435         guint32 i;
4436         
4437         values [MONO_ASSEMBLY_MAJOR_VERSION] = 0;
4438         values [MONO_ASSEMBLY_MINOR_VERSION] = 0;
4439         values [MONO_ASSEMBLY_REV_NUMBER] = 0;
4440         values [MONO_ASSEMBLY_BUILD_NUMBER] = 0;
4441         if (!version)
4442                 return;
4443         ver = str = mono_string_to_utf8 (version);
4444         for (i = 0; i < 4; ++i) {
4445                 values [MONO_ASSEMBLY_MAJOR_VERSION + i] = strtol (ver, &p, 10);
4446                 switch (*p) {
4447                 case '.':
4448                         p++;
4449                         break;
4450                 case '*':
4451                         /* handle Revision and Build */
4452                         p++;
4453                         break;
4454                 }
4455                 ver = p;
4456         }
4457         g_free (str);
4458 }
4459
4460 static guint32
4461 load_public_key (MonoArray *pkey, MonoDynamicImage *assembly) {
4462         gsize len;
4463         guint32 token = 0;
4464         char blob_size [6];
4465         char *b = blob_size;
4466
4467         if (!pkey)
4468                 return token;
4469
4470         len = mono_array_length (pkey);
4471         mono_metadata_encode_value (len, b, &b);
4472         token = mono_image_add_stream_data (&assembly->blob, blob_size, b - blob_size);
4473         mono_image_add_stream_data (&assembly->blob, mono_array_addr (pkey, char, 0), len);
4474
4475         assembly->public_key = g_malloc (len);
4476         memcpy (assembly->public_key, mono_array_addr (pkey, char, 0), len);
4477         assembly->public_key_len = len;
4478
4479         /* Special case: check for ECMA key (16 bytes) */
4480         if ((len == MONO_ECMA_KEY_LENGTH) && mono_is_ecma_key (mono_array_addr (pkey, char, 0), len)) {
4481                 /* In this case we must reserve 128 bytes (1024 bits) for the signature */
4482                 assembly->strong_name_size = MONO_DEFAULT_PUBLIC_KEY_LENGTH;
4483         } else if (len >= MONO_PUBLIC_KEY_HEADER_LENGTH + MONO_MINIMUM_PUBLIC_KEY_LENGTH) {
4484                 /* minimum key size (in 2.0) is 384 bits */
4485                 assembly->strong_name_size = len - MONO_PUBLIC_KEY_HEADER_LENGTH;
4486         } else {
4487                 /* FIXME - verifier */
4488                 g_warning ("Invalid public key length: %d bits (total: %d)", (int)MONO_PUBLIC_KEY_BIT_SIZE (len), (int)len);
4489                 assembly->strong_name_size = MONO_DEFAULT_PUBLIC_KEY_LENGTH; /* to be safe */
4490         }
4491         assembly->strong_name = g_malloc0 (assembly->strong_name_size);
4492
4493         return token;
4494 }
4495
4496 static void
4497 mono_image_emit_manifest (MonoReflectionModuleBuilder *moduleb)
4498 {
4499         MonoDynamicTable *table;
4500         MonoDynamicImage *assembly;
4501         MonoReflectionAssemblyBuilder *assemblyb;
4502         MonoDomain *domain;
4503         guint32 *values;
4504         int i;
4505         guint32 module_index;
4506
4507         assemblyb = moduleb->assemblyb;
4508         assembly = moduleb->dynamic_image;
4509         domain = mono_object_domain (assemblyb);
4510
4511         /* Emit ASSEMBLY table */
4512         table = &assembly->tables [MONO_TABLE_ASSEMBLY];
4513         alloc_table (table, 1);
4514         values = table->values + MONO_ASSEMBLY_SIZE;
4515         values [MONO_ASSEMBLY_HASH_ALG] = assemblyb->algid? assemblyb->algid: ASSEMBLY_HASH_SHA1;
4516         values [MONO_ASSEMBLY_NAME] = string_heap_insert_mstring (&assembly->sheap, assemblyb->name);
4517         if (assemblyb->culture) {
4518                 values [MONO_ASSEMBLY_CULTURE] = string_heap_insert_mstring (&assembly->sheap, assemblyb->culture);
4519         } else {
4520                 values [MONO_ASSEMBLY_CULTURE] = string_heap_insert (&assembly->sheap, "");
4521         }
4522         values [MONO_ASSEMBLY_PUBLIC_KEY] = load_public_key (assemblyb->public_key, assembly);
4523         values [MONO_ASSEMBLY_FLAGS] = assemblyb->flags;
4524         set_version_from_string (assemblyb->version, values);
4525
4526         /* Emit FILE + EXPORTED_TYPE table */
4527         module_index = 0;
4528         for (i = 0; i < mono_array_length (assemblyb->modules); ++i) {
4529                 int j;
4530                 MonoReflectionModuleBuilder *file_module = 
4531                         mono_array_get (assemblyb->modules, MonoReflectionModuleBuilder*, i);
4532                 if (file_module != moduleb) {
4533                         mono_image_fill_file_table (domain, (MonoReflectionModule*)file_module, assembly);
4534                         module_index ++;
4535                         if (file_module->types) {
4536                                 for (j = 0; j < file_module->num_types; ++j) {
4537                                         MonoReflectionTypeBuilder *tb = mono_array_get (file_module->types, MonoReflectionTypeBuilder*, j);
4538                                         mono_image_fill_export_table (domain, tb, module_index, 0, assembly);
4539                                 }
4540                         }
4541                 }
4542         }
4543         if (assemblyb->loaded_modules) {
4544                 for (i = 0; i < mono_array_length (assemblyb->loaded_modules); ++i) {
4545                         MonoReflectionModule *file_module = 
4546                                 mono_array_get (assemblyb->loaded_modules, MonoReflectionModule*, i);
4547                         mono_image_fill_file_table (domain, file_module, assembly);
4548                         module_index ++;
4549                         mono_image_fill_export_table_from_module (domain, file_module, module_index, assembly);
4550                 }
4551         }
4552         if (assemblyb->type_forwarders)
4553                 mono_image_fill_export_table_from_type_forwarders (assemblyb, assembly);
4554
4555         /* Emit MANIFESTRESOURCE table */
4556         module_index = 0;
4557         for (i = 0; i < mono_array_length (assemblyb->modules); ++i) {
4558                 int j;
4559                 MonoReflectionModuleBuilder *file_module = 
4560                         mono_array_get (assemblyb->modules, MonoReflectionModuleBuilder*, i);
4561                 /* The table for the main module is emitted later */
4562                 if (file_module != moduleb) {
4563                         module_index ++;
4564                         if (file_module->resources) {
4565                                 int len = mono_array_length (file_module->resources);
4566                                 for (j = 0; j < len; ++j) {
4567                                         MonoReflectionResource* res = (MonoReflectionResource*)mono_array_addr (file_module->resources, MonoReflectionResource, j);
4568                                         assembly_add_resource_manifest (file_module, assembly, res, MONO_IMPLEMENTATION_FILE | (module_index << MONO_IMPLEMENTATION_BITS));
4569                                 }
4570                         }
4571                 }
4572         }               
4573 }
4574
4575 #ifndef DISABLE_REFLECTION_EMIT_SAVE
4576
4577 /*
4578  * mono_image_build_metadata() will fill the info in all the needed metadata tables
4579  * for the modulebuilder @moduleb.
4580  * At the end of the process, method and field tokens are fixed up and the 
4581  * on-disk compressed metadata representation is created.
4582  */
4583 void
4584 mono_image_build_metadata (MonoReflectionModuleBuilder *moduleb)
4585 {
4586         MonoDynamicTable *table;
4587         MonoDynamicImage *assembly;
4588         MonoReflectionAssemblyBuilder *assemblyb;
4589         MonoDomain *domain;
4590         MonoPtrArray types;
4591         guint32 *values;
4592         int i, j;
4593
4594         assemblyb = moduleb->assemblyb;
4595         assembly = moduleb->dynamic_image;
4596         domain = mono_object_domain (assemblyb);
4597
4598         if (assembly->text_rva)
4599                 return;
4600
4601         assembly->text_rva = START_TEXT_RVA;
4602
4603         if (moduleb->is_main) {
4604                 mono_image_emit_manifest (moduleb);
4605         }
4606
4607         table = &assembly->tables [MONO_TABLE_TYPEDEF];
4608         table->rows = 1; /* .<Module> */
4609         table->next_idx++;
4610         alloc_table (table, table->rows);
4611         /*
4612          * Set the first entry.
4613          */
4614         values = table->values + table->columns;
4615         values [MONO_TYPEDEF_FLAGS] = 0;
4616         values [MONO_TYPEDEF_NAME] = string_heap_insert (&assembly->sheap, "<Module>") ;
4617         values [MONO_TYPEDEF_NAMESPACE] = string_heap_insert (&assembly->sheap, "") ;
4618         values [MONO_TYPEDEF_EXTENDS] = 0;
4619         values [MONO_TYPEDEF_FIELD_LIST] = 1;
4620         values [MONO_TYPEDEF_METHOD_LIST] = 1;
4621
4622         /* 
4623          * handle global methods 
4624          * FIXME: test what to do when global methods are defined in multiple modules.
4625          */
4626         if (moduleb->global_methods) {
4627                 table = &assembly->tables [MONO_TABLE_METHOD];
4628                 table->rows += mono_array_length (moduleb->global_methods);
4629                 alloc_table (table, table->rows);
4630                 for (i = 0; i < mono_array_length (moduleb->global_methods); ++i)
4631                         mono_image_get_method_info (
4632                                 mono_array_get (moduleb->global_methods, MonoReflectionMethodBuilder*, i), assembly);
4633         }
4634         if (moduleb->global_fields) {
4635                 table = &assembly->tables [MONO_TABLE_FIELD];
4636                 table->rows += mono_array_length (moduleb->global_fields);
4637                 alloc_table (table, table->rows);
4638                 for (i = 0; i < mono_array_length (moduleb->global_fields); ++i)
4639                         mono_image_get_field_info (
4640                                 mono_array_get (moduleb->global_fields, MonoReflectionFieldBuilder*, i), assembly);
4641         }
4642
4643         table = &assembly->tables [MONO_TABLE_MODULE];
4644         alloc_table (table, 1);
4645         mono_image_fill_module_table (domain, moduleb, assembly);
4646
4647         /* Collect all types into a list sorted by their table_idx */
4648         mono_ptr_array_init (types, moduleb->num_types);
4649
4650         if (moduleb->types)
4651                 for (i = 0; i < moduleb->num_types; ++i) {
4652                         MonoReflectionTypeBuilder *type = mono_array_get (moduleb->types, MonoReflectionTypeBuilder*, i);
4653                         collect_types (&types, type);
4654                 }
4655
4656         mono_ptr_array_sort (types, (gpointer)compare_types_by_table_idx);
4657         table = &assembly->tables [MONO_TABLE_TYPEDEF];
4658         table->rows += mono_ptr_array_size (types);
4659         alloc_table (table, table->rows);
4660
4661         /*
4662          * Emit type names + namespaces at one place inside the string heap,
4663          * so load_class_names () needs to touch fewer pages.
4664          */
4665         for (i = 0; i < mono_ptr_array_size (types); ++i) {
4666                 MonoReflectionTypeBuilder *tb = mono_ptr_array_get (types, i);
4667                 string_heap_insert_mstring (&assembly->sheap, tb->nspace);
4668         }
4669         for (i = 0; i < mono_ptr_array_size (types); ++i) {
4670                 MonoReflectionTypeBuilder *tb = mono_ptr_array_get (types, i);
4671                 string_heap_insert_mstring (&assembly->sheap, tb->name);
4672         }
4673
4674         for (i = 0; i < mono_ptr_array_size (types); ++i) {
4675                 MonoReflectionTypeBuilder *type = mono_ptr_array_get (types, i);
4676                 mono_image_get_type_info (domain, type, assembly);
4677         }
4678
4679         /* 
4680          * table->rows is already set above and in mono_image_fill_module_table.
4681          */
4682         /* add all the custom attributes at the end, once all the indexes are stable */
4683         mono_image_add_cattrs (assembly, 1, MONO_CUSTOM_ATTR_ASSEMBLY, assemblyb->cattrs);
4684
4685         /* CAS assembly permissions */
4686         if (assemblyb->permissions_minimum)
4687                 mono_image_add_decl_security (assembly, mono_metadata_make_token (MONO_TABLE_ASSEMBLY, 1), assemblyb->permissions_minimum);
4688         if (assemblyb->permissions_optional)
4689                 mono_image_add_decl_security (assembly, mono_metadata_make_token (MONO_TABLE_ASSEMBLY, 1), assemblyb->permissions_optional);
4690         if (assemblyb->permissions_refused)
4691                 mono_image_add_decl_security (assembly, mono_metadata_make_token (MONO_TABLE_ASSEMBLY, 1), assemblyb->permissions_refused);
4692
4693         module_add_cattrs (assembly, moduleb);
4694
4695         /* fixup tokens */
4696         mono_g_hash_table_foreach (assembly->token_fixups, (GHFunc)fixup_method, assembly);
4697
4698         /* Create the MethodImpl table.  We do this after emitting all methods so we already know
4699          * the final tokens and don't need another fixup pass. */
4700
4701         if (moduleb->global_methods) {
4702                 for (i = 0; i < mono_array_length (moduleb->global_methods); ++i) {
4703                         MonoReflectionMethodBuilder *mb = mono_array_get (
4704                                 moduleb->global_methods, MonoReflectionMethodBuilder*, i);
4705                         mono_image_add_methodimpl (assembly, mb);
4706                 }
4707         }
4708
4709         for (i = 0; i < mono_ptr_array_size (types); ++i) {
4710                 MonoReflectionTypeBuilder *type = mono_ptr_array_get (types, i);
4711                 if (type->methods) {
4712                         for (j = 0; j < type->num_methods; ++j) {
4713                                 MonoReflectionMethodBuilder *mb = mono_array_get (
4714                                         type->methods, MonoReflectionMethodBuilder*, j);
4715
4716                                 mono_image_add_methodimpl (assembly, mb);
4717                         }
4718                 }
4719         }
4720
4721         mono_ptr_array_destroy (types);
4722
4723         fixup_cattrs (assembly);
4724 }
4725
4726 #else /* DISABLE_REFLECTION_EMIT_SAVE */
4727
4728 void
4729 mono_image_build_metadata (MonoReflectionModuleBuilder *moduleb)
4730 {
4731         g_error ("This mono runtime was configured with --enable-minimal=reflection_emit_save, so saving of dynamic assemblies is not supported.");
4732 }
4733
4734 #endif /* DISABLE_REFLECTION_EMIT_SAVE */
4735
4736
4737 typedef struct {
4738         guint32 import_lookup_table;
4739         guint32 timestamp;
4740         guint32 forwarder;
4741         guint32 name_rva;
4742         guint32 import_address_table_rva;
4743 } MonoIDT;
4744
4745 typedef struct {
4746         guint32 name_rva;
4747         guint32 flags;
4748 } MonoILT;
4749
4750 #ifndef DISABLE_REFLECTION_EMIT
4751
4752 /*
4753  * mono_image_insert_string:
4754  * @module: module builder object
4755  * @str: a string
4756  *
4757  * Insert @str into the user string stream of @module.
4758  */
4759 guint32
4760 mono_image_insert_string (MonoReflectionModuleBuilder *module, MonoString *str)
4761 {
4762         MonoDynamicImage *assembly;
4763         guint32 idx;
4764         char buf [16];
4765         char *b = buf;
4766         
4767         MONO_ARCH_SAVE_REGS;
4768
4769         if (!module->dynamic_image)
4770                 mono_image_module_basic_init (module);
4771
4772         assembly = module->dynamic_image;
4773         
4774         if (assembly->save) {
4775                 mono_metadata_encode_value (1 | (str->length * 2), b, &b);
4776                 idx = mono_image_add_stream_data (&assembly->us, buf, b-buf);
4777 #if G_BYTE_ORDER != G_LITTLE_ENDIAN
4778         {
4779                 char *swapped = g_malloc (2 * mono_string_length (str));
4780                 const char *p = (const char*)mono_string_chars (str);
4781
4782                 swap_with_size (swapped, p, 2, mono_string_length (str));
4783                 mono_image_add_stream_data (&assembly->us, swapped, str->length * 2);
4784                 g_free (swapped);
4785         }
4786 #else
4787                 mono_image_add_stream_data (&assembly->us, (const char*)mono_string_chars (str), str->length * 2);
4788 #endif
4789                 mono_image_add_stream_data (&assembly->us, "", 1);
4790         } else {
4791                 idx = assembly->us.index ++;
4792         }
4793
4794         mono_g_hash_table_insert (assembly->tokens, GUINT_TO_POINTER (MONO_TOKEN_STRING | idx), str);
4795
4796         return MONO_TOKEN_STRING | idx;
4797 }
4798
4799 guint32
4800 mono_image_create_method_token (MonoDynamicImage *assembly, MonoObject *obj, MonoArray *opt_param_types)
4801 {
4802         MonoClass *klass;
4803         guint32 token = 0;
4804         MonoMethodSignature *sig;
4805
4806         klass = obj->vtable->klass;
4807         if (strcmp (klass->name, "MonoMethod") == 0 || strcmp (klass->name, "MonoCMethod") == 0) {
4808                 MonoMethod *method = ((MonoReflectionMethod *)obj)->method;
4809                 MonoMethodSignature *old;
4810                 guint32 sig_token, parent;
4811                 int nargs, i;
4812
4813                 g_assert (opt_param_types && (mono_method_signature (method)->sentinelpos >= 0));
4814
4815                 nargs = mono_array_length (opt_param_types);
4816                 old = mono_method_signature (method);
4817                 sig = mono_metadata_signature_alloc ( &assembly->image, old->param_count + nargs);
4818
4819                 sig->hasthis = old->hasthis;
4820                 sig->explicit_this = old->explicit_this;
4821                 sig->call_convention = old->call_convention;
4822                 sig->generic_param_count = old->generic_param_count;
4823                 sig->param_count = old->param_count + nargs;
4824                 sig->sentinelpos = old->param_count;
4825                 sig->ret = old->ret;
4826
4827                 for (i = 0; i < old->param_count; i++)
4828                         sig->params [i] = old->params [i];
4829
4830                 for (i = 0; i < nargs; i++) {
4831                         MonoReflectionType *rt = mono_array_get (opt_param_types, MonoReflectionType *, i);
4832                         sig->params [old->param_count + i] = mono_reflection_type_get_handle (rt);
4833                 }
4834
4835                 parent = mono_image_typedef_or_ref (assembly, &method->klass->byval_arg);
4836                 g_assert ((parent & MONO_TYPEDEFORREF_MASK) == MONO_MEMBERREF_PARENT_TYPEREF);
4837                 parent >>= MONO_TYPEDEFORREF_BITS;
4838
4839                 parent <<= MONO_MEMBERREF_PARENT_BITS;
4840                 parent |= MONO_MEMBERREF_PARENT_TYPEREF;
4841
4842                 sig_token = method_encode_signature (assembly, sig);
4843                 token = mono_image_get_varargs_method_token (assembly, parent, method->name, sig_token);
4844         } else if (strcmp (klass->name, "MethodBuilder") == 0) {
4845                 MonoReflectionMethodBuilder *mb = (MonoReflectionMethodBuilder *)obj;
4846                 ReflectionMethodBuilder rmb;
4847                 guint32 parent, sig_token;
4848                 int nopt_args, nparams, ngparams, i;
4849                 char *name;
4850
4851                 reflection_methodbuilder_from_method_builder (&rmb, mb);
4852                 rmb.opt_types = opt_param_types;
4853                 nopt_args = mono_array_length (opt_param_types);
4854
4855                 nparams = rmb.parameters ? mono_array_length (rmb.parameters): 0;
4856                 ngparams = rmb.generic_params ? mono_array_length (rmb.generic_params): 0;
4857                 sig = mono_metadata_signature_alloc (&assembly->image, nparams + nopt_args);
4858
4859                 sig->hasthis = !(rmb.attrs & METHOD_ATTRIBUTE_STATIC);
4860                 sig->explicit_this = (rmb.call_conv & 0x40) == 0x40;
4861                 sig->call_convention = rmb.call_conv;
4862                 sig->generic_param_count = ngparams;
4863                 sig->param_count = nparams + nopt_args;
4864                 sig->sentinelpos = nparams;
4865                 sig->ret = mono_reflection_type_get_handle (rmb.rtype);
4866
4867                 for (i = 0; i < nparams; i++) {
4868                         MonoReflectionType *rt = mono_array_get (rmb.parameters, MonoReflectionType *, i);
4869                         sig->params [i] = mono_reflection_type_get_handle (rt);
4870                 }
4871
4872                 for (i = 0; i < nopt_args; i++) {
4873                         MonoReflectionType *rt = mono_array_get (opt_param_types, MonoReflectionType *, i);
4874                         sig->params [nparams + i] = mono_reflection_type_get_handle (rt);
4875                 }
4876
4877                 sig_token = method_builder_encode_signature (assembly, &rmb);
4878
4879                 parent = mono_image_create_token (assembly, obj, TRUE, TRUE);
4880                 g_assert (mono_metadata_token_table (parent) == MONO_TABLE_METHOD);
4881
4882                 parent = mono_metadata_token_index (parent) << MONO_MEMBERREF_PARENT_BITS;
4883                 parent |= MONO_MEMBERREF_PARENT_METHODDEF;
4884
4885                 name = mono_string_to_utf8 (rmb.name);
4886                 token = mono_image_get_varargs_method_token (
4887                         assembly, parent, name, sig_token);
4888                 g_free (name);
4889         } else {
4890                 g_error ("requested method token for %s\n", klass->name);
4891         }
4892
4893         g_hash_table_insert (assembly->vararg_aux_hash, GUINT_TO_POINTER (token), sig);
4894         mono_g_hash_table_insert (assembly->tokens, GUINT_TO_POINTER (token), obj);
4895         return token;
4896 }
4897
4898 /*
4899  * mono_image_create_token:
4900  * @assembly: a dynamic assembly
4901  * @obj:
4902  * @register_token: Whenever to register the token in the assembly->tokens hash. 
4903  *
4904  * Get a token to insert in the IL code stream for the given MemberInfo.
4905  * The metadata emission routines need to pass FALSE as REGISTER_TOKEN, since by that time, 
4906  * the table_idx-es were recomputed, so registering the token would overwrite an existing 
4907  * entry.
4908  */
4909 guint32
4910 mono_image_create_token (MonoDynamicImage *assembly, MonoObject *obj, 
4911                                                  gboolean create_open_instance, gboolean register_token)
4912 {
4913         MonoClass *klass;
4914         guint32 token = 0;
4915
4916         klass = obj->vtable->klass;
4917
4918         /* Check for user defined reflection objects */
4919         /* TypeDelegator is the only corlib type which doesn't look like a MonoReflectionType */
4920         if (klass->image != mono_defaults.corlib || (strcmp (klass->name, "TypeDelegator") == 0))
4921                 mono_raise_exception (mono_get_exception_not_supported ("User defined subclasses of System.Type are not yet supported")); \
4922
4923         if (strcmp (klass->name, "MethodBuilder") == 0) {
4924                 MonoReflectionMethodBuilder *mb = (MonoReflectionMethodBuilder *)obj;
4925                 MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder*)mb->type;
4926
4927                 if (tb->module->dynamic_image == assembly && !tb->generic_params && !mb->generic_params)
4928                         token = mb->table_idx | MONO_TOKEN_METHOD_DEF;
4929                 else
4930                         token = mono_image_get_methodbuilder_token (assembly, mb, create_open_instance);
4931                 /*g_print ("got token 0x%08x for %s\n", token, mono_string_to_utf8 (mb->name));*/
4932         } else if (strcmp (klass->name, "ConstructorBuilder") == 0) {
4933                 MonoReflectionCtorBuilder *mb = (MonoReflectionCtorBuilder *)obj;
4934                 MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder*)mb->type;
4935
4936                 if (tb->module->dynamic_image == assembly && !tb->generic_params)
4937                         token = mb->table_idx | MONO_TOKEN_METHOD_DEF;
4938                 else
4939                         token = mono_image_get_ctorbuilder_token (assembly, mb);
4940                 /*g_print ("got token 0x%08x for %s\n", token, mono_string_to_utf8 (mb->name));*/
4941         } else if (strcmp (klass->name, "FieldBuilder") == 0) {
4942                 MonoReflectionFieldBuilder *fb = (MonoReflectionFieldBuilder *)obj;
4943                 MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder *)fb->typeb;
4944                 if (tb->generic_params) {
4945                         token = mono_image_get_generic_field_token (assembly, fb);
4946                 } else {
4947                         if (tb->module->dynamic_image == assembly) {
4948                                 token = fb->table_idx | MONO_TOKEN_FIELD_DEF;
4949                         } else {
4950                                 token = mono_image_get_fieldref_token (assembly, (MonoObject*)fb, fb->handle);
4951                         }
4952                 }
4953         } else if (strcmp (klass->name, "TypeBuilder") == 0) {
4954                 MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder *)obj;
4955                 if (create_open_instance && tb->generic_params) {
4956                         MonoType *type;
4957                         init_type_builder_generics (obj);
4958                         type = mono_reflection_type_get_handle ((MonoReflectionType *)obj);
4959                         token = mono_image_typedef_or_ref_full (assembly, type, TRUE);
4960                         token = mono_metadata_token_from_dor (token);
4961                 } else if (tb->module->dynamic_image == assembly) {
4962                         token = tb->table_idx | MONO_TOKEN_TYPE_DEF;
4963                 } else {
4964                         MonoType *type;
4965                         type = mono_reflection_type_get_handle ((MonoReflectionType *)obj);
4966                         token = mono_metadata_token_from_dor (mono_image_typedef_or_ref (assembly, type));
4967                 }
4968         } else if (strcmp (klass->name, "MonoType") == 0) {
4969                 MonoType *type = mono_reflection_type_get_handle ((MonoReflectionType *)obj);
4970                 MonoClass *mc = mono_class_from_mono_type (type);
4971                 token = mono_metadata_token_from_dor (
4972                         mono_image_typedef_or_ref_full (assembly, type, mc->generic_container == NULL || create_open_instance));
4973         } else if (strcmp (klass->name, "GenericTypeParameterBuilder") == 0) {
4974                 MonoType *type = mono_reflection_type_get_handle ((MonoReflectionType *)obj);
4975                 token = mono_metadata_token_from_dor (
4976                         mono_image_typedef_or_ref (assembly, type));
4977         } else if (strcmp (klass->name, "MonoGenericClass") == 0) {
4978                 MonoType *type = mono_reflection_type_get_handle ((MonoReflectionType *)obj);
4979                 token = mono_metadata_token_from_dor (
4980                         mono_image_typedef_or_ref (assembly, type));
4981         } else if (strcmp (klass->name, "MonoCMethod") == 0 ||
4982                    strcmp (klass->name, "MonoMethod") == 0 ||
4983                    strcmp (klass->name, "MonoGenericMethod") == 0 ||
4984                    strcmp (klass->name, "MonoGenericCMethod") == 0) {
4985                 MonoReflectionMethod *m = (MonoReflectionMethod *)obj;
4986                 if (m->method->is_inflated) {
4987                         if (create_open_instance)
4988                                 token = mono_image_get_methodspec_token (assembly, m->method);
4989                         else
4990                                 token = mono_image_get_inflated_method_token (assembly, m->method);
4991                 } else if ((m->method->klass->image == &assembly->image) &&
4992                          !m->method->klass->generic_class) {
4993                         static guint32 method_table_idx = 0xffffff;
4994                         if (m->method->klass->wastypebuilder) {
4995                                 /* we use the same token as the one that was assigned
4996                                  * to the Methodbuilder.
4997                                  * FIXME: do the equivalent for Fields.
4998                                  */
4999                                 token = m->method->token;
5000                         } else {
5001                                 /*
5002                                  * Each token should have a unique index, but the indexes are
5003                                  * assigned by managed code, so we don't know about them. An
5004                                  * easy solution is to count backwards...
5005                                  */
5006                                 method_table_idx --;
5007                                 token = MONO_TOKEN_METHOD_DEF | method_table_idx;
5008                         }
5009                 } else {
5010                         token = mono_image_get_methodref_token (assembly, m->method, create_open_instance);
5011                 }
5012                 /*g_print ("got token 0x%08x for %s\n", token, m->method->name);*/
5013         } else if (strcmp (klass->name, "MonoField") == 0) {
5014                 MonoReflectionField *f = (MonoReflectionField *)obj;
5015                 if ((f->field->parent->image == &assembly->image) && !is_field_on_inst (f->field)) {
5016                         static guint32 field_table_idx = 0xffffff;
5017                         field_table_idx --;
5018                         token = MONO_TOKEN_FIELD_DEF | field_table_idx;
5019                 } else {
5020                         token = mono_image_get_fieldref_token (assembly, (MonoObject*)f, f->field);
5021                 }
5022                 /*g_print ("got token 0x%08x for %s\n", token, f->field->name);*/
5023         } else if (strcmp (klass->name, "MonoArrayMethod") == 0) {
5024                 MonoReflectionArrayMethod *m = (MonoReflectionArrayMethod *)obj;
5025                 token = mono_image_get_array_token (assembly, m);
5026         } else if (strcmp (klass->name, "SignatureHelper") == 0) {
5027                 MonoReflectionSigHelper *s = (MonoReflectionSigHelper*)obj;
5028                 token = MONO_TOKEN_SIGNATURE | mono_image_get_sighelper_token (assembly, s);
5029         } else if (strcmp (klass->name, "EnumBuilder") == 0) {
5030                 MonoType *type = mono_reflection_type_get_handle ((MonoReflectionType *)obj);
5031                 token = mono_metadata_token_from_dor (
5032                         mono_image_typedef_or_ref (assembly, type));
5033         } else if (strcmp (klass->name, "FieldOnTypeBuilderInst") == 0) {
5034                 MonoReflectionFieldOnTypeBuilderInst *f = (MonoReflectionFieldOnTypeBuilderInst*)obj;
5035                 token = mono_image_get_field_on_inst_token (assembly, f);
5036         } else if (strcmp (klass->name, "ConstructorOnTypeBuilderInst") == 0) {
5037                 MonoReflectionCtorOnTypeBuilderInst *c = (MonoReflectionCtorOnTypeBuilderInst*)obj;
5038                 token = mono_image_get_ctor_on_inst_token (assembly, c, create_open_instance);
5039         } else if (strcmp (klass->name, "MethodOnTypeBuilderInst") == 0) {
5040                 MonoReflectionMethodOnTypeBuilderInst *m = (MonoReflectionMethodOnTypeBuilderInst*)obj;
5041                 token = mono_image_get_method_on_inst_token (assembly, m, create_open_instance);
5042         } else if (is_sre_array (klass) || is_sre_byref (klass) || is_sre_pointer (klass)) {
5043                 MonoReflectionType *type = (MonoReflectionType *)obj;
5044                 token = mono_metadata_token_from_dor (
5045                                 mono_image_typedef_or_ref (assembly, mono_reflection_type_get_handle (type)));
5046         } else {
5047                 g_error ("requested token for %s\n", klass->name);
5048         }
5049
5050         if (register_token)
5051                 mono_image_register_token (assembly, token, obj);
5052
5053         return token;
5054 }
5055
5056 /*
5057  * mono_image_register_token:
5058  *
5059  *   Register the TOKEN->OBJ mapping in the mapping table in ASSEMBLY. This is required for
5060  * the Module.ResolveXXXToken () methods to work.
5061  */
5062 void
5063 mono_image_register_token (MonoDynamicImage *assembly, guint32 token, MonoObject *obj)
5064 {
5065         MonoObject *prev = mono_g_hash_table_lookup (assembly->tokens, GUINT_TO_POINTER (token));
5066         if (prev) {
5067                 /* There could be multiple MethodInfo objects with the same token */
5068                 //g_assert (prev == obj);
5069         } else {
5070                 mono_g_hash_table_insert (assembly->tokens, GUINT_TO_POINTER (token), obj);
5071         }
5072 }
5073
5074 static MonoDynamicImage*
5075 create_dynamic_mono_image (MonoDynamicAssembly *assembly, char *assembly_name, char *module_name)
5076 {
5077         static const guchar entrycode [16] = {0xff, 0x25, 0};
5078         MonoDynamicImage *image;
5079         int i;
5080
5081         const char *version;
5082
5083         if (!strcmp (mono_get_runtime_info ()->framework_version, "2.1"))
5084                 version = "v2.0.50727"; /* HACK: SL 2 enforces the .net 2 metadata version */
5085         else
5086                 version = mono_get_runtime_info ()->runtime_version;
5087
5088 #if HAVE_BOEHM_GC
5089         /* The MonoGHashTable's need GC tracking */
5090         image = GC_MALLOC (sizeof (MonoDynamicImage));
5091 #else
5092         image = g_new0 (MonoDynamicImage, 1);
5093 #endif
5094         
5095         mono_profiler_module_event (&image->image, MONO_PROFILE_START_LOAD);
5096         
5097         /*g_print ("created image %p\n", image);*/
5098         /* keep in sync with image.c */
5099         image->image.name = assembly_name;
5100         image->image.assembly_name = image->image.name; /* they may be different */
5101         image->image.module_name = module_name;
5102         image->image.version = g_strdup (version);
5103         image->image.md_version_major = 1;
5104         image->image.md_version_minor = 1;
5105         image->image.dynamic = TRUE;
5106
5107         image->image.references = g_new0 (MonoAssembly*, 1);
5108         image->image.references [0] = NULL;
5109
5110         mono_image_init (&image->image);
5111
5112         image->token_fixups = mono_g_hash_table_new_type ((GHashFunc)mono_object_hash, NULL, MONO_HASH_KEY_GC);
5113         image->method_to_table_idx = g_hash_table_new (NULL, NULL);
5114         image->field_to_table_idx = g_hash_table_new (NULL, NULL);
5115         image->method_aux_hash = g_hash_table_new (NULL, NULL);
5116         image->vararg_aux_hash = g_hash_table_new (NULL, NULL);
5117         image->handleref = g_hash_table_new (NULL, NULL);
5118         image->handleref_managed = mono_g_hash_table_new_type ((GHashFunc)mono_object_hash, NULL, MONO_HASH_KEY_GC);
5119         image->tokens = mono_g_hash_table_new_type (NULL, NULL, MONO_HASH_VALUE_GC);
5120         image->generic_def_objects = mono_g_hash_table_new_type (NULL, NULL, MONO_HASH_VALUE_GC);
5121         image->methodspec = mono_g_hash_table_new_type ((GHashFunc)mono_object_hash, NULL, MONO_HASH_KEY_GC);
5122         image->typespec = g_hash_table_new ((GHashFunc)mono_metadata_type_hash, (GCompareFunc)mono_metadata_type_equal);
5123         image->typeref = g_hash_table_new ((GHashFunc)mono_metadata_type_hash, (GCompareFunc)mono_metadata_type_equal);
5124         image->blob_cache = g_hash_table_new ((GHashFunc)mono_blob_entry_hash, (GCompareFunc)mono_blob_entry_equal);
5125         image->gen_params = g_ptr_array_new ();
5126         image->remapped_tokens = mono_g_hash_table_new_type (NULL, NULL, MONO_HASH_VALUE_GC);
5127
5128         /*g_print ("string heap create for image %p (%s)\n", image, module_name);*/
5129         string_heap_init (&image->sheap);
5130         mono_image_add_stream_data (&image->us, "", 1);
5131         add_to_blob_cached (image, (char*) "", 1, NULL, 0);
5132         /* import tables... */
5133         mono_image_add_stream_data (&image->code, (char*)entrycode, sizeof (entrycode));
5134         image->iat_offset = mono_image_add_stream_zero (&image->code, 8); /* two IAT entries */
5135         image->idt_offset = mono_image_add_stream_zero (&image->code, 2 * sizeof (MonoIDT)); /* two IDT entries */
5136         image->imp_names_offset = mono_image_add_stream_zero (&image->code, 2); /* flags for name entry */
5137         mono_image_add_stream_data (&image->code, "_CorExeMain", 12);
5138         mono_image_add_stream_data (&image->code, "mscoree.dll", 12);
5139         image->ilt_offset = mono_image_add_stream_zero (&image->code, 8); /* two ILT entries */
5140         stream_data_align (&image->code);
5141
5142         image->cli_header_offset = mono_image_add_stream_zero (&image->code, sizeof (MonoCLIHeader));
5143
5144         for (i=0; i < MONO_TABLE_NUM; ++i) {
5145                 image->tables [i].next_idx = 1;
5146                 image->tables [i].columns = table_sizes [i];
5147         }
5148
5149         image->image.assembly = (MonoAssembly*)assembly;
5150         image->run = assembly->run;
5151         image->save = assembly->save;
5152         image->pe_kind = 0x1; /* ILOnly */
5153         image->machine = 0x14c; /* I386 */
5154         
5155         mono_profiler_module_loaded (&image->image, MONO_PROFILE_OK);
5156
5157         return image;
5158 }
5159 #endif
5160
5161 static void
5162 free_blob_cache_entry (gpointer key, gpointer val, gpointer user_data)
5163 {
5164         g_free (key);
5165 }
5166
5167 static void
5168 release_hashtable (MonoGHashTable **hash)
5169 {
5170         if (*hash) {
5171                 mono_g_hash_table_destroy (*hash);
5172                 *hash = NULL;
5173         }
5174 }
5175
5176 void
5177 mono_dynamic_image_release_gc_roots (MonoDynamicImage *image)
5178 {
5179         release_hashtable (&image->token_fixups);
5180         release_hashtable (&image->handleref_managed);
5181         release_hashtable (&image->tokens);
5182         release_hashtable (&image->remapped_tokens);
5183         release_hashtable (&image->generic_def_objects);
5184         release_hashtable (&image->methodspec);
5185 }
5186
5187 void
5188 mono_dynamic_image_free (MonoDynamicImage *image)
5189 {
5190         MonoDynamicImage *di = image;
5191         GList *list;
5192         int i;
5193
5194         if (di->methodspec)
5195                 mono_g_hash_table_destroy (di->methodspec);
5196         if (di->typespec)
5197                 g_hash_table_destroy (di->typespec);
5198         if (di->typeref)
5199                 g_hash_table_destroy (di->typeref);
5200         if (di->handleref)
5201                 g_hash_table_destroy (di->handleref);
5202         if (di->handleref_managed)
5203                 mono_g_hash_table_destroy (di->handleref_managed);
5204         if (di->tokens)
5205                 mono_g_hash_table_destroy (di->tokens);
5206         if (di->remapped_tokens)
5207                 mono_g_hash_table_destroy (di->remapped_tokens);
5208         if (di->generic_def_objects)
5209                 mono_g_hash_table_destroy (di->generic_def_objects);
5210         if (di->blob_cache) {
5211                 g_hash_table_foreach (di->blob_cache, free_blob_cache_entry, NULL);
5212                 g_hash_table_destroy (di->blob_cache);
5213         }
5214         if (di->standalonesig_cache)
5215                 g_hash_table_destroy (di->standalonesig_cache);
5216         for (list = di->array_methods; list; list = list->next) {
5217                 ArrayMethod *am = (ArrayMethod *)list->data;
5218                 g_free (am->sig);
5219                 g_free (am->name);
5220                 g_free (am);
5221         }
5222         g_list_free (di->array_methods);
5223         if (di->gen_params) {
5224                 for (i = 0; i < di->gen_params->len; i++) {
5225                         GenericParamTableEntry *entry = g_ptr_array_index (di->gen_params, i);
5226                         mono_gc_deregister_root ((char*) &entry->gparam);
5227                         g_free (entry);
5228                 }
5229                 g_ptr_array_free (di->gen_params, TRUE);
5230         }
5231         if (di->token_fixups)
5232                 mono_g_hash_table_destroy (di->token_fixups);
5233         if (di->method_to_table_idx)
5234                 g_hash_table_destroy (di->method_to_table_idx);
5235         if (di->field_to_table_idx)
5236                 g_hash_table_destroy (di->field_to_table_idx);
5237         if (di->method_aux_hash)
5238                 g_hash_table_destroy (di->method_aux_hash);
5239         if (di->vararg_aux_hash)
5240                 g_hash_table_destroy (di->vararg_aux_hash);
5241         g_free (di->strong_name);
5242         g_free (di->win32_res);
5243         if (di->public_key)
5244                 g_free (di->public_key);
5245
5246         /*g_print ("string heap destroy for image %p\n", di);*/
5247         mono_dynamic_stream_reset (&di->sheap);
5248         mono_dynamic_stream_reset (&di->code);
5249         mono_dynamic_stream_reset (&di->resources);
5250         mono_dynamic_stream_reset (&di->us);
5251         mono_dynamic_stream_reset (&di->blob);
5252         mono_dynamic_stream_reset (&di->tstream);
5253         mono_dynamic_stream_reset (&di->guid);
5254         for (i = 0; i < MONO_TABLE_NUM; ++i) {
5255                 g_free (di->tables [i].values);
5256         }
5257 }       
5258
5259 #ifndef DISABLE_REFLECTION_EMIT
5260
5261 /*
5262  * mono_image_basic_init:
5263  * @assembly: an assembly builder object
5264  *
5265  * Create the MonoImage that represents the assembly builder and setup some
5266  * of the helper hash table and the basic metadata streams.
5267  */
5268 void
5269 mono_image_basic_init (MonoReflectionAssemblyBuilder *assemblyb)
5270 {
5271         MonoDynamicAssembly *assembly;
5272         MonoDynamicImage *image;
5273         MonoDomain *domain = mono_object_domain (assemblyb);
5274         
5275         MONO_ARCH_SAVE_REGS;
5276
5277         if (assemblyb->dynamic_assembly)
5278                 return;
5279
5280 #if HAVE_BOEHM_GC
5281         /* assembly->assembly.image might be GC allocated */
5282         assembly = assemblyb->dynamic_assembly = GC_MALLOC (sizeof (MonoDynamicAssembly));
5283 #else
5284         assembly = assemblyb->dynamic_assembly = g_new0 (MonoDynamicAssembly, 1);
5285 #endif
5286
5287         mono_profiler_assembly_event (&assembly->assembly, MONO_PROFILE_START_LOAD);
5288         
5289         assembly->assembly.ref_count = 1;
5290         assembly->assembly.dynamic = TRUE;
5291         assembly->assembly.corlib_internal = assemblyb->corlib_internal;
5292         assemblyb->assembly.assembly = (MonoAssembly*)assembly;
5293         assembly->assembly.basedir = mono_string_to_utf8 (assemblyb->dir);
5294         if (assemblyb->culture)
5295                 assembly->assembly.aname.culture = mono_string_to_utf8 (assemblyb->culture);
5296         else
5297                 assembly->assembly.aname.culture = g_strdup ("");
5298
5299         if (assemblyb->version) {
5300                         char *vstr = mono_string_to_utf8 (assemblyb->version);
5301                         char **version = g_strsplit (vstr, ".", 4);
5302                         char **parts = version;
5303                         assembly->assembly.aname.major = atoi (*parts++);
5304                         assembly->assembly.aname.minor = atoi (*parts++);
5305                         assembly->assembly.aname.build = *parts != NULL ? atoi (*parts++) : 0;
5306                         assembly->assembly.aname.revision = *parts != NULL ? atoi (*parts) : 0;
5307
5308                         g_strfreev (version);
5309                         g_free (vstr);
5310         } else {
5311                         assembly->assembly.aname.major = 0;
5312                         assembly->assembly.aname.minor = 0;
5313                         assembly->assembly.aname.build = 0;
5314                         assembly->assembly.aname.revision = 0;
5315         }
5316
5317         assembly->run = assemblyb->access != 2;
5318         assembly->save = assemblyb->access != 1;
5319         assembly->domain = domain;
5320
5321         image = create_dynamic_mono_image (assembly, mono_string_to_utf8 (assemblyb->name), g_strdup ("RefEmit_YouForgotToDefineAModule"));
5322         image->initial_image = TRUE;
5323         assembly->assembly.aname.name = image->image.name;
5324         assembly->assembly.image = &image->image;
5325         if (assemblyb->pktoken && assemblyb->pktoken->max_length) {
5326                 /* -1 to correct for the trailing NULL byte */
5327                 if (assemblyb->pktoken->max_length != MONO_PUBLIC_KEY_TOKEN_LENGTH - 1) {
5328                         g_error ("Public key token length invalid for assembly %s: %i", assembly->assembly.aname.name, assemblyb->pktoken->max_length);
5329                 }
5330                 memcpy (&assembly->assembly.aname.public_key_token, mono_array_addr (assemblyb->pktoken, guint8, 0), assemblyb->pktoken->max_length);           
5331         }
5332
5333         mono_domain_assemblies_lock (domain);
5334         domain->domain_assemblies = g_slist_append (domain->domain_assemblies, assembly);
5335         mono_domain_assemblies_unlock (domain);
5336
5337         register_assembly (mono_object_domain (assemblyb), &assemblyb->assembly, &assembly->assembly);
5338         
5339         mono_profiler_assembly_loaded (&assembly->assembly, MONO_PROFILE_OK);
5340         
5341         mono_assembly_invoke_load_hook ((MonoAssembly*)assembly);
5342 }
5343
5344 #endif /* !DISABLE_REFLECTION_EMIT */
5345
5346 #ifndef DISABLE_REFLECTION_EMIT_SAVE
5347
5348 static int
5349 calc_section_size (MonoDynamicImage *assembly)
5350 {
5351         int nsections = 0;
5352
5353         /* alignment constraints */
5354         mono_image_add_stream_zero (&assembly->code, 4 - (assembly->code.index % 4));
5355         g_assert ((assembly->code.index % 4) == 0);
5356         assembly->meta_size += 3;
5357         assembly->meta_size &= ~3;
5358         mono_image_add_stream_zero (&assembly->resources, 4 - (assembly->resources.index % 4));
5359         g_assert ((assembly->resources.index % 4) == 0);
5360
5361         assembly->sections [MONO_SECTION_TEXT].size = assembly->meta_size + assembly->code.index + assembly->resources.index + assembly->strong_name_size;
5362         assembly->sections [MONO_SECTION_TEXT].attrs = SECT_FLAGS_HAS_CODE | SECT_FLAGS_MEM_EXECUTE | SECT_FLAGS_MEM_READ;
5363         nsections++;
5364
5365         if (assembly->win32_res) {
5366                 guint32 res_size = (assembly->win32_res_size + 3) & ~3;
5367
5368                 assembly->sections [MONO_SECTION_RSRC].size = res_size;
5369                 assembly->sections [MONO_SECTION_RSRC].attrs = SECT_FLAGS_HAS_INITIALIZED_DATA | SECT_FLAGS_MEM_READ;
5370                 nsections++;
5371         }
5372
5373         assembly->sections [MONO_SECTION_RELOC].size = 12;
5374         assembly->sections [MONO_SECTION_RELOC].attrs = SECT_FLAGS_MEM_READ | SECT_FLAGS_MEM_DISCARDABLE | SECT_FLAGS_HAS_INITIALIZED_DATA;
5375         nsections++;
5376
5377         return nsections;
5378 }
5379
5380 typedef struct {
5381         guint32 id;
5382         guint32 offset;
5383         GSList *children;
5384         MonoReflectionWin32Resource *win32_res; /* Only for leaf nodes */
5385 } ResTreeNode;
5386
5387 static int
5388 resource_tree_compare_by_id (gconstpointer a, gconstpointer b)
5389 {
5390         ResTreeNode *t1 = (ResTreeNode*)a;
5391         ResTreeNode *t2 = (ResTreeNode*)b;
5392
5393         return t1->id - t2->id;
5394 }
5395
5396 /*
5397  * resource_tree_create:
5398  *
5399  *  Organize the resources into a resource tree.
5400  */
5401 static ResTreeNode *
5402 resource_tree_create (MonoArray *win32_resources)
5403 {
5404         ResTreeNode *tree, *res_node, *type_node, *lang_node;
5405         GSList *l;
5406         int i;
5407
5408         tree = g_new0 (ResTreeNode, 1);
5409         
5410         for (i = 0; i < mono_array_length (win32_resources); ++i) {
5411                 MonoReflectionWin32Resource *win32_res =
5412                         (MonoReflectionWin32Resource*)mono_array_addr (win32_resources, MonoReflectionWin32Resource, i);
5413
5414                 /* Create node */
5415
5416                 /* FIXME: BUG: this stores managed references in unmanaged memory */
5417                 lang_node = g_new0 (ResTreeNode, 1);
5418                 lang_node->id = win32_res->lang_id;
5419                 lang_node->win32_res = win32_res;
5420
5421                 /* Create type node if neccesary */
5422                 type_node = NULL;
5423                 for (l = tree->children; l; l = l->next)
5424                         if (((ResTreeNode*)(l->data))->id == win32_res->res_type) {
5425                                 type_node = (ResTreeNode*)l->data;
5426                                 break;
5427                         }
5428
5429                 if (!type_node) {
5430                         type_node = g_new0 (ResTreeNode, 1);
5431                         type_node->id = win32_res->res_type;
5432
5433                         /* 
5434                          * The resource types have to be sorted otherwise
5435                          * Windows Explorer can't display the version information.
5436                          */
5437                         tree->children = g_slist_insert_sorted (tree->children, 
5438                                 type_node, resource_tree_compare_by_id);
5439                 }
5440
5441                 /* Create res node if neccesary */
5442                 res_node = NULL;
5443                 for (l = type_node->children; l; l = l->next)
5444                         if (((ResTreeNode*)(l->data))->id == win32_res->res_id) {
5445                                 res_node = (ResTreeNode*)l->data;
5446                                 break;
5447                         }
5448
5449                 if (!res_node) {
5450                         res_node = g_new0 (ResTreeNode, 1);
5451                         res_node->id = win32_res->res_id;
5452                         type_node->children = g_slist_append (type_node->children, res_node);
5453                 }
5454
5455                 res_node->children = g_slist_append (res_node->children, lang_node);
5456         }
5457
5458         return tree;
5459 }
5460
5461 /*
5462  * resource_tree_encode:
5463  * 
5464  *   Encode the resource tree into the format used in the PE file.
5465  */
5466 static void
5467 resource_tree_encode (ResTreeNode *node, char *begin, char *p, char **endbuf)
5468 {
5469         char *entries;
5470         MonoPEResourceDir dir;
5471         MonoPEResourceDirEntry dir_entry;
5472         MonoPEResourceDataEntry data_entry;
5473         GSList *l;
5474         guint32 res_id_entries;
5475
5476         /*
5477          * For the format of the resource directory, see the article
5478          * "An In-Depth Look into the Win32 Portable Executable File Format" by
5479          * Matt Pietrek
5480          */
5481
5482         memset (&dir, 0, sizeof (dir));
5483         memset (&dir_entry, 0, sizeof (dir_entry));
5484         memset (&data_entry, 0, sizeof (data_entry));
5485
5486         g_assert (sizeof (dir) == 16);
5487         g_assert (sizeof (dir_entry) == 8);
5488         g_assert (sizeof (data_entry) == 16);
5489
5490         node->offset = p - begin;
5491
5492         /* IMAGE_RESOURCE_DIRECTORY */
5493         res_id_entries = g_slist_length (node->children);
5494         dir.res_id_entries = GUINT16_TO_LE (res_id_entries);
5495
5496         memcpy (p, &dir, sizeof (dir));
5497         p += sizeof (dir);
5498
5499         /* Reserve space for entries */
5500         entries = p;
5501         p += sizeof (dir_entry) * res_id_entries;
5502
5503         /* Write children */
5504         for (l = node->children; l; l = l->next) {
5505                 ResTreeNode *child = (ResTreeNode*)l->data;
5506
5507                 if (child->win32_res) {
5508                         guint32 size;
5509
5510                         child->offset = p - begin;
5511
5512                         /* IMAGE_RESOURCE_DATA_ENTRY */
5513                         data_entry.rde_data_offset = GUINT32_TO_LE (p - begin + sizeof (data_entry));
5514                         size = mono_array_length (child->win32_res->res_data);
5515                         data_entry.rde_size = GUINT32_TO_LE (size);
5516
5517                         memcpy (p, &data_entry, sizeof (data_entry));
5518                         p += sizeof (data_entry);
5519
5520                         memcpy (p, mono_array_addr (child->win32_res->res_data, char, 0), size);
5521                         p += size;
5522                 } else {
5523                         resource_tree_encode (child, begin, p, &p);
5524                 }
5525         }
5526
5527         /* IMAGE_RESOURCE_ENTRY */
5528         for (l = node->children; l; l = l->next) {
5529                 ResTreeNode *child = (ResTreeNode*)l->data;
5530
5531                 MONO_PE_RES_DIR_ENTRY_SET_NAME (dir_entry, FALSE, child->id);
5532                 MONO_PE_RES_DIR_ENTRY_SET_DIR (dir_entry, !child->win32_res, child->offset);
5533
5534                 memcpy (entries, &dir_entry, sizeof (dir_entry));
5535                 entries += sizeof (dir_entry);
5536         }
5537
5538         *endbuf = p;
5539 }
5540
5541 static void
5542 resource_tree_free (ResTreeNode * node)
5543 {
5544         GSList * list;
5545         for (list = node->children; list; list = list->next)
5546                 resource_tree_free ((ResTreeNode*)list->data);
5547         g_slist_free(node->children);
5548         g_free (node);
5549 }
5550
5551 static void
5552 assembly_add_win32_resources (MonoDynamicImage *assembly, MonoReflectionAssemblyBuilder *assemblyb)
5553 {
5554         char *buf;
5555         char *p;
5556         guint32 size, i;
5557         MonoReflectionWin32Resource *win32_res;
5558         ResTreeNode *tree;
5559
5560         if (!assemblyb->win32_resources)
5561                 return;
5562
5563         /*
5564          * Resources are stored in a three level tree inside the PE file.
5565          * - level one contains a node for each type of resource
5566          * - level two contains a node for each resource
5567          * - level three contains a node for each instance of a resource for a
5568          *   specific language.
5569          */
5570
5571         tree = resource_tree_create (assemblyb->win32_resources);
5572
5573         /* Estimate the size of the encoded tree */
5574         size = 0;
5575         for (i = 0; i < mono_array_length (assemblyb->win32_resources); ++i) {
5576                 win32_res = (MonoReflectionWin32Resource*)mono_array_addr (assemblyb->win32_resources, MonoReflectionWin32Resource, i);
5577                 size += mono_array_length (win32_res->res_data);
5578         }
5579         /* Directory structure */
5580         size += mono_array_length (assemblyb->win32_resources) * 256;
5581         p = buf = g_malloc (size);
5582
5583         resource_tree_encode (tree, p, p, &p);
5584
5585         g_assert (p - buf <= size);
5586
5587         assembly->win32_res = g_malloc (p - buf);
5588         assembly->win32_res_size = p - buf;
5589         memcpy (assembly->win32_res, buf, p - buf);
5590
5591         g_free (buf);
5592         resource_tree_free (tree);
5593 }
5594
5595 static void
5596 fixup_resource_directory (char *res_section, char *p, guint32 rva)
5597 {
5598         MonoPEResourceDir *dir = (MonoPEResourceDir*)p;
5599         int i;
5600
5601         p += sizeof (MonoPEResourceDir);
5602         for (i = 0; i < GUINT16_FROM_LE (dir->res_named_entries) + GUINT16_FROM_LE (dir->res_id_entries); ++i) {
5603                 MonoPEResourceDirEntry *dir_entry = (MonoPEResourceDirEntry*)p;
5604                 char *child = res_section + MONO_PE_RES_DIR_ENTRY_DIR_OFFSET (*dir_entry);
5605                 if (MONO_PE_RES_DIR_ENTRY_IS_DIR (*dir_entry)) {
5606                         fixup_resource_directory (res_section, child, rva);
5607                 } else {
5608                         MonoPEResourceDataEntry *data_entry = (MonoPEResourceDataEntry*)child;
5609                         data_entry->rde_data_offset = GUINT32_TO_LE (GUINT32_FROM_LE (data_entry->rde_data_offset) + rva);
5610                 }
5611
5612                 p += sizeof (MonoPEResourceDirEntry);
5613         }
5614 }
5615
5616 static void
5617 checked_write_file (HANDLE f, gconstpointer buffer, guint32 numbytes)
5618 {
5619         guint32 dummy;
5620         if (!WriteFile (f, buffer, numbytes, &dummy, NULL))
5621                 g_error ("WriteFile returned %d\n", GetLastError ());
5622 }
5623
5624 /*
5625  * mono_image_create_pefile:
5626  * @mb: a module builder object
5627  * 
5628  * This function creates the PE-COFF header, the image sections, the CLI header  * etc. all the data is written in
5629  * assembly->pefile where it can be easily retrieved later in chunks.
5630  */
5631 void
5632 mono_image_create_pefile (MonoReflectionModuleBuilder *mb, HANDLE file)
5633 {
5634         MonoMSDOSHeader *msdos;
5635         MonoDotNetHeader *header;
5636         MonoSectionTable *section;
5637         MonoCLIHeader *cli_header;
5638         guint32 size, image_size, virtual_base, text_offset;
5639         guint32 header_start, section_start, file_offset, virtual_offset;
5640         MonoDynamicImage *assembly;
5641         MonoReflectionAssemblyBuilder *assemblyb;
5642         MonoDynamicStream pefile_stream = {0};
5643         MonoDynamicStream *pefile = &pefile_stream;
5644         int i, nsections;
5645         guint32 *rva, value;
5646         guchar *p;
5647         static const unsigned char msheader[] = {
5648                 0x4d, 0x5a, 0x90, 0x00, 0x03, 0x00, 0x00, 0x00,  0x04, 0x00, 0x00, 0x00, 0xff, 0xff, 0x00, 0x00,
5649                 0xb8, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,  0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
5650                 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
5651                 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,  0x00, 0x00, 0x00, 0x00, 0x80, 0x00, 0x00, 0x00,
5652                 0x0e, 0x1f, 0xba, 0x0e, 0x00, 0xb4, 0x09, 0xcd,  0x21, 0xb8, 0x01, 0x4c, 0xcd, 0x21, 0x54, 0x68,
5653                 0x69, 0x73, 0x20, 0x70, 0x72, 0x6f, 0x67, 0x72,  0x61, 0x6d, 0x20, 0x63, 0x61, 0x6e, 0x6e, 0x6f,
5654                 0x74, 0x20, 0x62, 0x65, 0x20, 0x72, 0x75, 0x6e,  0x20, 0x69, 0x6e, 0x20, 0x44, 0x4f, 0x53, 0x20,
5655                 0x6d, 0x6f, 0x64, 0x65, 0x2e, 0x0d, 0x0d, 0x0a,  0x24, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
5656         };
5657
5658         assemblyb = mb->assemblyb;
5659
5660         mono_image_basic_init (assemblyb);
5661         assembly = mb->dynamic_image;
5662
5663         assembly->pe_kind = assemblyb->pe_kind;
5664         assembly->machine = assemblyb->machine;
5665         ((MonoDynamicImage*)assemblyb->dynamic_assembly->assembly.image)->pe_kind = assemblyb->pe_kind;
5666         ((MonoDynamicImage*)assemblyb->dynamic_assembly->assembly.image)->machine = assemblyb->machine;
5667         
5668         mono_image_build_metadata (mb);
5669
5670         if (mb->is_main && assemblyb->resources) {
5671                 int len = mono_array_length (assemblyb->resources);
5672                 for (i = 0; i < len; ++i)
5673                         assembly_add_resource (mb, assembly, (MonoReflectionResource*)mono_array_addr (assemblyb->resources, MonoReflectionResource, i));
5674         }
5675
5676         if (mb->resources) {
5677                 int len = mono_array_length (mb->resources);
5678                 for (i = 0; i < len; ++i)
5679                         assembly_add_resource (mb, assembly, (MonoReflectionResource*)mono_array_addr (mb->resources, MonoReflectionResource, i));
5680         }
5681
5682         build_compressed_metadata (assembly);
5683
5684         if (mb->is_main)
5685                 assembly_add_win32_resources (assembly, assemblyb);
5686
5687         nsections = calc_section_size (assembly);
5688         
5689         /* The DOS header and stub */
5690         g_assert (sizeof (MonoMSDOSHeader) == sizeof (msheader));
5691         mono_image_add_stream_data (pefile, (char*)msheader, sizeof (msheader));
5692
5693         /* the dotnet header */
5694         header_start = mono_image_add_stream_zero (pefile, sizeof (MonoDotNetHeader));
5695
5696         /* the section tables */
5697         section_start = mono_image_add_stream_zero (pefile, sizeof (MonoSectionTable) * nsections);
5698
5699         file_offset = section_start + sizeof (MonoSectionTable) * nsections;
5700         virtual_offset = VIRT_ALIGN;
5701         image_size = 0;
5702
5703         for (i = 0; i < MONO_SECTION_MAX; ++i) {
5704                 if (!assembly->sections [i].size)
5705                         continue;
5706                 /* align offsets */
5707                 file_offset += FILE_ALIGN - 1;
5708                 file_offset &= ~(FILE_ALIGN - 1);
5709                 virtual_offset += VIRT_ALIGN - 1;
5710                 virtual_offset &= ~(VIRT_ALIGN - 1);
5711
5712                 assembly->sections [i].offset = file_offset;
5713                 assembly->sections [i].rva = virtual_offset;
5714
5715                 file_offset += assembly->sections [i].size;
5716                 virtual_offset += assembly->sections [i].size;
5717                 image_size += (assembly->sections [i].size + VIRT_ALIGN - 1) & ~(VIRT_ALIGN - 1);
5718         }
5719
5720         file_offset += FILE_ALIGN - 1;
5721         file_offset &= ~(FILE_ALIGN - 1);
5722
5723         image_size += section_start + sizeof (MonoSectionTable) * nsections;
5724
5725         /* back-patch info */
5726         msdos = (MonoMSDOSHeader*)pefile->data;
5727         msdos->pe_offset = GUINT32_FROM_LE (sizeof (MonoMSDOSHeader));
5728
5729         header = (MonoDotNetHeader*)(pefile->data + header_start);
5730         header->pesig [0] = 'P';
5731         header->pesig [1] = 'E';
5732         
5733         header->coff.coff_machine = GUINT16_FROM_LE (assemblyb->machine);
5734         header->coff.coff_sections = GUINT16_FROM_LE (nsections);
5735         header->coff.coff_time = GUINT32_FROM_LE (time (NULL));
5736         header->coff.coff_opt_header_size = GUINT16_FROM_LE (sizeof (MonoDotNetHeader) - sizeof (MonoCOFFHeader) - 4);
5737         if (assemblyb->pekind == 1) {
5738                 /* it's a dll */
5739                 header->coff.coff_attributes = GUINT16_FROM_LE (0x210e);
5740         } else {
5741                 /* it's an exe */
5742                 header->coff.coff_attributes = GUINT16_FROM_LE (0x010e);
5743         }
5744
5745         virtual_base = 0x400000; /* FIXME: 0x10000000 if a DLL */
5746
5747         header->pe.pe_magic = GUINT16_FROM_LE (0x10B);
5748         header->pe.pe_major = 6;
5749         header->pe.pe_minor = 0;
5750         size = assembly->sections [MONO_SECTION_TEXT].size;
5751         size += FILE_ALIGN - 1;
5752         size &= ~(FILE_ALIGN - 1);
5753         header->pe.pe_code_size = GUINT32_FROM_LE(size);
5754         size = assembly->sections [MONO_SECTION_RSRC].size;
5755         size += FILE_ALIGN - 1;
5756         size &= ~(FILE_ALIGN - 1);
5757         header->pe.pe_data_size = GUINT32_FROM_LE(size);
5758         g_assert (START_TEXT_RVA == assembly->sections [MONO_SECTION_TEXT].rva);
5759         header->pe.pe_rva_code_base = GUINT32_FROM_LE (assembly->sections [MONO_SECTION_TEXT].rva);
5760         header->pe.pe_rva_data_base = GUINT32_FROM_LE (assembly->sections [MONO_SECTION_RSRC].rva);
5761         /* pe_rva_entry_point always at the beginning of the text section */
5762         header->pe.pe_rva_entry_point = GUINT32_FROM_LE (assembly->sections [MONO_SECTION_TEXT].rva);
5763
5764         header->nt.pe_image_base = GUINT32_FROM_LE (virtual_base);
5765         header->nt.pe_section_align = GUINT32_FROM_LE (VIRT_ALIGN);
5766         header->nt.pe_file_alignment = GUINT32_FROM_LE (FILE_ALIGN);
5767         header->nt.pe_os_major = GUINT16_FROM_LE (4);
5768         header->nt.pe_os_minor = GUINT16_FROM_LE (0);
5769         header->nt.pe_subsys_major = GUINT16_FROM_LE (4);
5770         size = section_start;
5771         size += FILE_ALIGN - 1;
5772         size &= ~(FILE_ALIGN - 1);
5773         header->nt.pe_header_size = GUINT32_FROM_LE (size);
5774         size = image_size;
5775         size += VIRT_ALIGN - 1;
5776         size &= ~(VIRT_ALIGN - 1);
5777         header->nt.pe_image_size = GUINT32_FROM_LE (size);
5778
5779         /*
5780         // Translate the PEFileKind value to the value expected by the Windows loader
5781         */
5782         {
5783                 short kind;
5784
5785                 /*
5786                 // PEFileKinds.Dll == 1
5787                 // PEFileKinds.ConsoleApplication == 2
5788                 // PEFileKinds.WindowApplication == 3
5789                 //
5790                 // need to get:
5791                 //     IMAGE_SUBSYSTEM_WINDOWS_GUI 2 // Image runs in the Windows GUI subsystem.
5792                 //     IMAGE_SUBSYSTEM_WINDOWS_CUI 3 // Image runs in the Windows character subsystem.
5793                 */
5794                 if (assemblyb->pekind == 3)
5795                         kind = 2;
5796                 else
5797                         kind = 3;
5798                 
5799                 header->nt.pe_subsys_required = GUINT16_FROM_LE (kind);
5800         }    
5801         header->nt.pe_stack_reserve = GUINT32_FROM_LE (0x00100000);
5802         header->nt.pe_stack_commit = GUINT32_FROM_LE (0x00001000);
5803         header->nt.pe_heap_reserve = GUINT32_FROM_LE (0x00100000);
5804         header->nt.pe_heap_commit = GUINT32_FROM_LE (0x00001000);
5805         header->nt.pe_loader_flags = GUINT32_FROM_LE (0);
5806         header->nt.pe_data_dir_count = GUINT32_FROM_LE (16);
5807
5808         /* fill data directory entries */
5809
5810         header->datadir.pe_resource_table.size = GUINT32_FROM_LE (assembly->sections [MONO_SECTION_RSRC].size);
5811         header->datadir.pe_resource_table.rva = GUINT32_FROM_LE (assembly->sections [MONO_SECTION_RSRC].rva);
5812
5813         header->datadir.pe_reloc_table.size = GUINT32_FROM_LE (assembly->sections [MONO_SECTION_RELOC].size);
5814         header->datadir.pe_reloc_table.rva = GUINT32_FROM_LE (assembly->sections [MONO_SECTION_RELOC].rva);
5815
5816         header->datadir.pe_cli_header.size = GUINT32_FROM_LE (72);
5817         header->datadir.pe_cli_header.rva = GUINT32_FROM_LE (assembly->text_rva + assembly->cli_header_offset);
5818         header->datadir.pe_iat.size = GUINT32_FROM_LE (8);
5819         header->datadir.pe_iat.rva = GUINT32_FROM_LE (assembly->text_rva + assembly->iat_offset);
5820         /* patch entrypoint name */
5821         if (assemblyb->pekind == 1)
5822                 memcpy (assembly->code.data + assembly->imp_names_offset + 2, "_CorDllMain", 12);
5823         else
5824                 memcpy (assembly->code.data + assembly->imp_names_offset + 2, "_CorExeMain", 12);
5825         /* patch imported function RVA name */
5826         rva = (guint32*)(assembly->code.data + assembly->iat_offset);
5827         *rva = GUINT32_FROM_LE (assembly->text_rva + assembly->imp_names_offset);
5828
5829         /* the import table */
5830         header->datadir.pe_import_table.size = GUINT32_FROM_LE (79); /* FIXME: magic number? */
5831         header->datadir.pe_import_table.rva = GUINT32_FROM_LE (assembly->text_rva + assembly->idt_offset);
5832         /* patch imported dll RVA name and other entries in the dir */
5833         rva = (guint32*)(assembly->code.data + assembly->idt_offset + G_STRUCT_OFFSET (MonoIDT, name_rva));
5834         *rva = GUINT32_FROM_LE (assembly->text_rva + assembly->imp_names_offset + 14); /* 14 is hint+strlen+1 of func name */
5835         rva = (guint32*)(assembly->code.data + assembly->idt_offset + G_STRUCT_OFFSET (MonoIDT, import_address_table_rva));
5836         *rva = GUINT32_FROM_LE (assembly->text_rva + assembly->iat_offset);
5837         rva = (guint32*)(assembly->code.data + assembly->idt_offset + G_STRUCT_OFFSET (MonoIDT, import_lookup_table));
5838         *rva = GUINT32_FROM_LE (assembly->text_rva + assembly->ilt_offset);
5839
5840         p = (guchar*)(assembly->code.data + assembly->ilt_offset);
5841         value = (assembly->text_rva + assembly->imp_names_offset);
5842         *p++ = (value) & 0xff;
5843         *p++ = (value >> 8) & (0xff);
5844         *p++ = (value >> 16) & (0xff);
5845         *p++ = (value >> 24) & (0xff);
5846
5847         /* the CLI header info */
5848         cli_header = (MonoCLIHeader*)(assembly->code.data + assembly->cli_header_offset);
5849         cli_header->ch_size = GUINT32_FROM_LE (72);
5850         cli_header->ch_runtime_major = GUINT16_FROM_LE (2);
5851         cli_header->ch_runtime_minor = GUINT16_FROM_LE (5);
5852         cli_header->ch_flags = GUINT32_FROM_LE (assemblyb->pe_kind);
5853         if (assemblyb->entry_point) {
5854                 guint32 table_idx = 0;
5855                 if (!strcmp (assemblyb->entry_point->object.vtable->klass->name, "MethodBuilder")) {
5856                         MonoReflectionMethodBuilder *methodb = (MonoReflectionMethodBuilder*)assemblyb->entry_point;
5857                         table_idx = methodb->table_idx;
5858                 } else {
5859                         table_idx = GPOINTER_TO_UINT (g_hash_table_lookup (assembly->method_to_table_idx, assemblyb->entry_point->method));
5860                 }
5861                 cli_header->ch_entry_point = GUINT32_FROM_LE (table_idx | MONO_TOKEN_METHOD_DEF);
5862         } else {
5863                 cli_header->ch_entry_point = GUINT32_FROM_LE (0);
5864         }
5865         /* The embedded managed resources */
5866         text_offset = assembly->text_rva + assembly->code.index;
5867         cli_header->ch_resources.rva = GUINT32_FROM_LE (text_offset);
5868         cli_header->ch_resources.size = GUINT32_FROM_LE (assembly->resources.index);
5869         text_offset += assembly->resources.index;
5870         cli_header->ch_metadata.rva = GUINT32_FROM_LE (text_offset);
5871         cli_header->ch_metadata.size = GUINT32_FROM_LE (assembly->meta_size);
5872         text_offset += assembly->meta_size;
5873         if (assembly->strong_name_size) {
5874                 cli_header->ch_strong_name.rva = GUINT32_FROM_LE (text_offset);
5875                 cli_header->ch_strong_name.size = GUINT32_FROM_LE (assembly->strong_name_size);
5876                 text_offset += assembly->strong_name_size;
5877         }
5878
5879         /* write the section tables and section content */
5880         section = (MonoSectionTable*)(pefile->data + section_start);
5881         for (i = 0; i < MONO_SECTION_MAX; ++i) {
5882                 static const char section_names [][7] = {
5883                         ".text", ".rsrc", ".reloc"
5884                 };
5885                 if (!assembly->sections [i].size)
5886                         continue;
5887                 strcpy (section->st_name, section_names [i]);
5888                 /*g_print ("output section %s (%d), size: %d\n", section->st_name, i, assembly->sections [i].size);*/
5889                 section->st_virtual_address = GUINT32_FROM_LE (assembly->sections [i].rva);
5890                 section->st_virtual_size = GUINT32_FROM_LE (assembly->sections [i].size);
5891                 section->st_raw_data_size = GUINT32_FROM_LE (GUINT32_TO_LE (section->st_virtual_size) + (FILE_ALIGN - 1));
5892                 section->st_raw_data_size &= GUINT32_FROM_LE (~(FILE_ALIGN - 1));
5893                 section->st_raw_data_ptr = GUINT32_FROM_LE (assembly->sections [i].offset);
5894                 section->st_flags = GUINT32_FROM_LE (assembly->sections [i].attrs);
5895                 section ++;
5896         }
5897         
5898         checked_write_file (file, pefile->data, pefile->index);
5899         
5900         mono_dynamic_stream_reset (pefile);
5901         
5902         for (i = 0; i < MONO_SECTION_MAX; ++i) {
5903                 if (!assembly->sections [i].size)
5904                         continue;
5905                 
5906                 if (SetFilePointer (file, assembly->sections [i].offset, NULL, FILE_BEGIN) == INVALID_SET_FILE_POINTER)
5907                         g_error ("SetFilePointer returned %d\n", GetLastError ());
5908                 
5909                 switch (i) {
5910                 case MONO_SECTION_TEXT:
5911                         /* patch entry point */
5912                         p = (guchar*)(assembly->code.data + 2);
5913                         value = (virtual_base + assembly->text_rva + assembly->iat_offset);
5914                         *p++ = (value) & 0xff;
5915                         *p++ = (value >> 8) & 0xff;
5916                         *p++ = (value >> 16) & 0xff;
5917                         *p++ = (value >> 24) & 0xff;
5918                 
5919                         checked_write_file (file, assembly->code.data, assembly->code.index);
5920                         checked_write_file (file, assembly->resources.data, assembly->resources.index);
5921                         checked_write_file (file, assembly->image.raw_metadata, assembly->meta_size);
5922                         checked_write_file (file, assembly->strong_name, assembly->strong_name_size);
5923                                 
5924
5925                         g_free (assembly->image.raw_metadata);
5926                         break;
5927                 case MONO_SECTION_RELOC: {
5928                         struct {
5929                                 guint32 page_rva;
5930                                 guint32 block_size;
5931                                 guint16 type_and_offset;
5932                                 guint16 term;
5933                         } reloc;
5934                         
5935                         g_assert (sizeof (reloc) == 12);
5936                         
5937                         reloc.page_rva = GUINT32_FROM_LE (assembly->text_rva);
5938                         reloc.block_size = GUINT32_FROM_LE (12);
5939                         
5940                         /* 
5941                          * the entrypoint is always at the start of the text section 
5942                          * 3 is IMAGE_REL_BASED_HIGHLOW
5943                          * 2 is patch_size_rva - text_rva
5944                          */
5945                         reloc.type_and_offset = GUINT16_FROM_LE ((3 << 12) + (2));
5946                         reloc.term = 0;
5947                         
5948                         checked_write_file (file, &reloc, sizeof (reloc));
5949                         
5950                         break;
5951                 }
5952                 case MONO_SECTION_RSRC:
5953                         if (assembly->win32_res) {
5954
5955                                 /* Fixup the offsets in the IMAGE_RESOURCE_DATA_ENTRY structures */
5956                                 fixup_resource_directory (assembly->win32_res, assembly->win32_res, assembly->sections [i].rva);
5957                                 checked_write_file (file, assembly->win32_res, assembly->win32_res_size);
5958                         }
5959                         break;
5960                 default:
5961                         g_assert_not_reached ();
5962                 }
5963         }
5964         
5965         /* check that the file is properly padded */
5966         if (SetFilePointer (file, file_offset, NULL, FILE_BEGIN) == INVALID_SET_FILE_POINTER)
5967                 g_error ("SetFilePointer returned %d\n", GetLastError ());
5968         if (! SetEndOfFile (file))
5969                 g_error ("SetEndOfFile returned %d\n", GetLastError ());
5970         
5971         mono_dynamic_stream_reset (&assembly->code);
5972         mono_dynamic_stream_reset (&assembly->us);
5973         mono_dynamic_stream_reset (&assembly->blob);
5974         mono_dynamic_stream_reset (&assembly->guid);
5975         mono_dynamic_stream_reset (&assembly->sheap);
5976
5977         g_hash_table_foreach (assembly->blob_cache, (GHFunc)g_free, NULL);
5978         g_hash_table_destroy (assembly->blob_cache);
5979         assembly->blob_cache = NULL;
5980 }
5981
5982 #else /* DISABLE_REFLECTION_EMIT_SAVE */
5983
5984 void
5985 mono_image_create_pefile (MonoReflectionModuleBuilder *mb, HANDLE file)
5986 {
5987         g_assert_not_reached ();
5988 }
5989
5990 #endif /* DISABLE_REFLECTION_EMIT_SAVE */
5991
5992 #ifndef DISABLE_REFLECTION_EMIT
5993
5994 MonoReflectionModule *
5995 mono_image_load_module_dynamic (MonoReflectionAssemblyBuilder *ab, MonoString *fileName)
5996 {
5997         char *name;
5998         MonoImage *image;
5999         MonoImageOpenStatus status;
6000         MonoDynamicAssembly *assembly;
6001         guint32 module_count;
6002         MonoImage **new_modules;
6003         gboolean *new_modules_loaded;
6004         
6005         name = mono_string_to_utf8 (fileName);
6006
6007         image = mono_image_open (name, &status);
6008         if (!image) {
6009                 MonoException *exc;
6010                 if (status == MONO_IMAGE_ERROR_ERRNO)
6011                         exc = mono_get_exception_file_not_found (fileName);
6012                 else
6013                         exc = mono_get_exception_bad_image_format (name);
6014                 g_free (name);
6015                 mono_raise_exception (exc);
6016         }
6017
6018         g_free (name);
6019
6020         assembly = ab->dynamic_assembly;
6021         image->assembly = (MonoAssembly*)assembly;
6022
6023         module_count = image->assembly->image->module_count;
6024         new_modules = g_new0 (MonoImage *, module_count + 1);
6025         new_modules_loaded = g_new0 (gboolean, module_count + 1);
6026
6027         if (image->assembly->image->modules)
6028                 memcpy (new_modules, image->assembly->image->modules, module_count * sizeof (MonoImage *));
6029         if (image->assembly->image->modules_loaded)
6030                 memcpy (new_modules_loaded, image->assembly->image->modules_loaded, module_count * sizeof (gboolean));
6031         new_modules [module_count] = image;
6032         new_modules_loaded [module_count] = TRUE;
6033         mono_image_addref (image);
6034
6035         g_free (image->assembly->image->modules);
6036         image->assembly->image->modules = new_modules;
6037         image->assembly->image->modules_loaded = new_modules_loaded;
6038         image->assembly->image->module_count ++;
6039
6040         mono_assembly_load_references (image, &status);
6041         if (status) {
6042                 mono_image_close (image);
6043                 mono_raise_exception (mono_get_exception_file_not_found (fileName));
6044         }
6045
6046         return mono_module_get_object (mono_domain_get (), image);
6047 }
6048
6049 #endif /* DISABLE_REFLECTION_EMIT */
6050
6051 /*
6052  * We need to return always the same object for MethodInfo, FieldInfo etc..
6053  * but we need to consider the reflected type.
6054  * type uses a different hash, since it uses custom hash/equal functions.
6055  */
6056
6057 typedef struct {
6058         gpointer item;
6059         MonoClass *refclass;
6060 } ReflectedEntry;
6061
6062 static gboolean
6063 reflected_equal (gconstpointer a, gconstpointer b) {
6064         const ReflectedEntry *ea = a;
6065         const ReflectedEntry *eb = b;
6066
6067         return (ea->item == eb->item) && (ea->refclass == eb->refclass);
6068 }
6069
6070 static guint
6071 reflected_hash (gconstpointer a) {
6072         const ReflectedEntry *ea = a;
6073         return mono_aligned_addr_hash (ea->item);
6074 }
6075
6076 #define CHECK_OBJECT(t,p,k)     \
6077         do {    \
6078                 t _obj; \
6079                 ReflectedEntry e;       \
6080                 e.item = (p);   \
6081                 e.refclass = (k);       \
6082                 mono_domain_lock (domain);      \
6083                 if (!domain->refobject_hash)    \
6084                         domain->refobject_hash = mono_g_hash_table_new_type (reflected_hash, reflected_equal, MONO_HASH_VALUE_GC);      \
6085                 if ((_obj = mono_g_hash_table_lookup (domain->refobject_hash, &e))) {   \
6086                         mono_domain_unlock (domain);    \
6087                         return _obj;    \
6088                 }       \
6089         mono_domain_unlock (domain); \
6090         } while (0)
6091
6092 #ifdef HAVE_BOEHM_GC
6093 /* ReflectedEntry doesn't need to be GC tracked */
6094 #define ALLOC_REFENTRY g_new0 (ReflectedEntry, 1)
6095 #define FREE_REFENTRY(entry) g_free ((entry))
6096 #define REFENTRY_REQUIRES_CLEANUP
6097 #else
6098 #define ALLOC_REFENTRY mono_mempool_alloc (domain->mp, sizeof (ReflectedEntry))
6099 /* FIXME: */
6100 #define FREE_REFENTRY(entry)
6101 #endif
6102
6103 #define CACHE_OBJECT(t,p,o,k)   \
6104         do {    \
6105                 t _obj; \
6106         ReflectedEntry pe; \
6107         pe.item = (p); \
6108         pe.refclass = (k); \
6109         mono_domain_lock (domain); \
6110                 if (!domain->refobject_hash)    \
6111                         domain->refobject_hash = mono_g_hash_table_new_type (reflected_hash, reflected_equal, MONO_HASH_VALUE_GC);      \
6112         _obj = mono_g_hash_table_lookup (domain->refobject_hash, &pe); \
6113         if (!_obj) { \
6114                     ReflectedEntry *e = ALLOC_REFENTRY;         \
6115                     e->item = (p);      \
6116                     e->refclass = (k);  \
6117                     mono_g_hash_table_insert (domain->refobject_hash, e,o);     \
6118             _obj = o; \
6119         } \
6120                 mono_domain_unlock (domain);    \
6121         return _obj; \
6122         } while (0)
6123
6124 static void
6125 clear_cached_object (MonoDomain *domain, gpointer o, MonoClass *klass)
6126 {
6127         mono_domain_lock (domain);
6128         if (domain->refobject_hash) {
6129         ReflectedEntry pe;
6130                 gpointer orig_pe, orig_value;
6131
6132                 pe.item = o;
6133                 pe.refclass = klass;
6134                 if (mono_g_hash_table_lookup_extended (domain->refobject_hash, &pe, &orig_pe, &orig_value)) {
6135                         mono_g_hash_table_remove (domain->refobject_hash, &pe);
6136                         FREE_REFENTRY (orig_pe);
6137                 }
6138         }
6139         mono_domain_unlock (domain);
6140 }
6141
6142 #ifdef REFENTRY_REQUIRES_CLEANUP
6143 static void
6144 cleanup_refobject_hash (gpointer key, gpointer value, gpointer user_data)
6145 {
6146         FREE_REFENTRY (key);
6147 }
6148 #endif
6149
6150 void
6151 mono_reflection_cleanup_domain (MonoDomain *domain)
6152 {
6153         if (domain->refobject_hash) {
6154 /*let's avoid scanning the whole hashtable if not needed*/
6155 #ifdef REFENTRY_REQUIRES_CLEANUP
6156                 mono_g_hash_table_foreach (domain->refobject_hash, cleanup_refobject_hash, NULL);
6157 #endif
6158                 mono_g_hash_table_destroy (domain->refobject_hash);
6159                 domain->refobject_hash = NULL;
6160         }
6161 }
6162
6163 #ifndef DISABLE_REFLECTION_EMIT
6164 static gpointer
6165 register_assembly (MonoDomain *domain, MonoReflectionAssembly *res, MonoAssembly *assembly)
6166 {
6167         CACHE_OBJECT (MonoReflectionAssembly *, assembly, res, NULL);
6168 }
6169
6170 static gpointer
6171 register_module (MonoDomain *domain, MonoReflectionModuleBuilder *res, MonoDynamicImage *module)
6172 {
6173         CACHE_OBJECT (MonoReflectionModuleBuilder *, module, res, NULL);
6174 }
6175
6176 void
6177 mono_image_module_basic_init (MonoReflectionModuleBuilder *moduleb)
6178 {
6179         MonoDynamicImage *image = moduleb->dynamic_image;
6180         MonoReflectionAssemblyBuilder *ab = moduleb->assemblyb;
6181         if (!image) {
6182                 MonoError error;
6183                 int module_count;
6184                 MonoImage **new_modules;
6185                 MonoImage *ass;
6186                 char *name, *fqname;
6187                 /*
6188                  * FIXME: we already created an image in mono_image_basic_init (), but
6189                  * we don't know which module it belongs to, since that is only 
6190                  * determined at assembly save time.
6191                  */
6192                 /*image = (MonoDynamicImage*)ab->dynamic_assembly->assembly.image; */
6193                 name = mono_string_to_utf8 (ab->name);
6194                 fqname = mono_string_to_utf8_checked (moduleb->module.fqname, &error);
6195                 if (!mono_error_ok (&error)) {
6196                         g_free (name);
6197                         mono_error_raise_exception (&error);
6198                 }
6199                 image = create_dynamic_mono_image (ab->dynamic_assembly, name, fqname);
6200
6201                 moduleb->module.image = &image->image;
6202                 moduleb->dynamic_image = image;
6203                 register_module (mono_object_domain (moduleb), moduleb, image);
6204
6205                 /* register the module with the assembly */
6206                 ass = ab->dynamic_assembly->assembly.image;
6207                 module_count = ass->module_count;
6208                 new_modules = g_new0 (MonoImage *, module_count + 1);
6209
6210                 if (ass->modules)
6211                         memcpy (new_modules, ass->modules, module_count * sizeof (MonoImage *));
6212                 new_modules [module_count] = &image->image;
6213                 mono_image_addref (&image->image);
6214
6215                 g_free (ass->modules);
6216                 ass->modules = new_modules;
6217                 ass->module_count ++;
6218         }
6219 }
6220
6221 void
6222 mono_image_set_wrappers_type (MonoReflectionModuleBuilder *moduleb, MonoReflectionType *type)
6223 {
6224         MonoDynamicImage *image = moduleb->dynamic_image;
6225
6226         g_assert (type->type);
6227         image->wrappers_type = mono_class_from_mono_type (type->type);
6228 }
6229
6230 #endif
6231
6232 /*
6233  * mono_assembly_get_object:
6234  * @domain: an app domain
6235  * @assembly: an assembly
6236  *
6237  * Return an System.Reflection.Assembly object representing the MonoAssembly @assembly.
6238  */
6239 MonoReflectionAssembly*
6240 mono_assembly_get_object (MonoDomain *domain, MonoAssembly *assembly)
6241 {
6242         static MonoClass *assembly_type;
6243         MonoReflectionAssembly *res;
6244         
6245         CHECK_OBJECT (MonoReflectionAssembly *, assembly, NULL);
6246         if (!assembly_type) {
6247                 MonoClass *class = mono_class_from_name (mono_defaults.corlib, "System.Reflection", "MonoAssembly");
6248                 if (class == NULL)
6249                         class = mono_class_from_name (mono_defaults.corlib, "System.Reflection", "Assembly");
6250                 g_assert (class);
6251                 assembly_type = class;
6252         }
6253         res = (MonoReflectionAssembly *)mono_object_new (domain, assembly_type);
6254         res->assembly = assembly;
6255
6256         CACHE_OBJECT (MonoReflectionAssembly *, assembly, res, NULL);
6257 }
6258
6259
6260
6261 MonoReflectionModule*   
6262 mono_module_get_object   (MonoDomain *domain, MonoImage *image)
6263 {
6264         static MonoClass *module_type;
6265         MonoReflectionModule *res;
6266         char* basename;
6267         
6268         CHECK_OBJECT (MonoReflectionModule *, image, NULL);
6269         if (!module_type) {
6270                 MonoClass *class = mono_class_from_name (mono_defaults.corlib, "System.Reflection", "MonoModule");
6271                 if (class == NULL)
6272                         class = mono_class_from_name (mono_defaults.corlib, "System.Reflection", "Module");
6273                 g_assert (class);
6274                 module_type = class;
6275         }
6276         res = (MonoReflectionModule *)mono_object_new (domain, module_type);
6277
6278         res->image = image;
6279         MONO_OBJECT_SETREF (res, assembly, (MonoReflectionAssembly *) mono_assembly_get_object(domain, image->assembly));
6280
6281         MONO_OBJECT_SETREF (res, fqname, mono_string_new (domain, image->name));
6282         basename = g_path_get_basename (image->name);
6283         MONO_OBJECT_SETREF (res, name, mono_string_new (domain, basename));
6284         MONO_OBJECT_SETREF (res, scopename, mono_string_new (domain, image->module_name));
6285         
6286         g_free (basename);
6287
6288         if (image->assembly->image == image) {
6289                 res->token = mono_metadata_make_token (MONO_TABLE_MODULE, 1);
6290         } else {
6291                 int i;
6292                 res->token = 0;
6293                 if (image->assembly->image->modules) {
6294                         for (i = 0; i < image->assembly->image->module_count; i++) {
6295                                 if (image->assembly->image->modules [i] == image)
6296                                         res->token = mono_metadata_make_token (MONO_TABLE_MODULEREF, i + 1);
6297                         }
6298                         g_assert (res->token);
6299                 }
6300         }
6301
6302         CACHE_OBJECT (MonoReflectionModule *, image, res, NULL);
6303 }
6304
6305 MonoReflectionModule*   
6306 mono_module_file_get_object (MonoDomain *domain, MonoImage *image, int table_index)
6307 {
6308         static MonoClass *module_type;
6309         MonoReflectionModule *res;
6310         MonoTableInfo *table;
6311         guint32 cols [MONO_FILE_SIZE];
6312         const char *name;
6313         guint32 i, name_idx;
6314         const char *val;
6315         
6316         if (!module_type) {
6317                 MonoClass *class = mono_class_from_name (mono_defaults.corlib, "System.Reflection", "MonoModule");
6318                 if (class == NULL)
6319                         class = mono_class_from_name (mono_defaults.corlib, "System.Reflection", "Module");
6320                 g_assert (class);
6321                 module_type = class;
6322         }
6323         res = (MonoReflectionModule *)mono_object_new (domain, module_type);
6324
6325         table = &image->tables [MONO_TABLE_FILE];
6326         g_assert (table_index < table->rows);
6327         mono_metadata_decode_row (table, table_index, cols, MONO_FILE_SIZE);
6328
6329         res->image = NULL;
6330         MONO_OBJECT_SETREF (res, assembly, (MonoReflectionAssembly *) mono_assembly_get_object(domain, image->assembly));
6331         name = mono_metadata_string_heap (image, cols [MONO_FILE_NAME]);
6332
6333         /* Check whenever the row has a corresponding row in the moduleref table */
6334         table = &image->tables [MONO_TABLE_MODULEREF];
6335         for (i = 0; i < table->rows; ++i) {
6336                 name_idx = mono_metadata_decode_row_col (table, i, MONO_MODULEREF_NAME);
6337                 val = mono_metadata_string_heap (image, name_idx);
6338                 if (strcmp (val, name) == 0)
6339                         res->image = image->modules [i];
6340         }
6341
6342         MONO_OBJECT_SETREF (res, fqname, mono_string_new (domain, name));
6343         MONO_OBJECT_SETREF (res, name, mono_string_new (domain, name));
6344         MONO_OBJECT_SETREF (res, scopename, mono_string_new (domain, name));
6345         res->is_resource = cols [MONO_FILE_FLAGS] && FILE_CONTAINS_NO_METADATA;
6346         res->token = mono_metadata_make_token (MONO_TABLE_FILE, table_index + 1);
6347
6348         return res;
6349 }
6350
6351 static gboolean
6352 verify_safe_for_managed_space (MonoType *type)
6353 {
6354         switch (type->type) {
6355 #ifdef DEBUG_HARDER
6356         case MONO_TYPE_ARRAY:
6357                 return verify_safe_for_managed_space (&type->data.array->eklass->byval_arg);
6358         case MONO_TYPE_PTR:
6359                 return verify_safe_for_managed_space (type->data.type);
6360         case MONO_TYPE_SZARRAY:
6361                 return verify_safe_for_managed_space (&type->data.klass->byval_arg);
6362         case MONO_TYPE_GENERICINST: {
6363                 MonoGenericInst *inst = type->data.generic_class->inst;
6364                 int i;
6365                 if (!inst->is_open)
6366                         break;
6367                 for (i = 0; i < inst->type_argc; ++i)
6368                         if (!verify_safe_for_managed_space (inst->type_argv [i]))
6369                                 return FALSE;
6370                 break;
6371         }
6372 #endif
6373         case MONO_TYPE_VAR:
6374         case MONO_TYPE_MVAR:
6375                 return TRUE;
6376         }
6377         return TRUE;
6378 }
6379
6380 static MonoType*
6381 mono_type_normalize (MonoType *type)
6382 {
6383         int i;
6384         MonoGenericClass *gclass;
6385         MonoGenericInst *ginst;
6386         MonoClass *gtd;
6387         MonoGenericContainer *gcontainer;
6388         MonoType **argv = NULL;
6389         gboolean is_denorm_gtd = TRUE, requires_rebind = FALSE;
6390
6391         if (type->type != MONO_TYPE_GENERICINST)
6392                 return type;
6393
6394         gclass = type->data.generic_class;
6395         ginst = gclass->context.class_inst;
6396         if (!ginst->is_open)
6397                 return type;
6398
6399         gtd = gclass->container_class;
6400         gcontainer = gtd->generic_container;
6401         argv = g_newa (MonoType*, ginst->type_argc);
6402
6403         for (i = 0; i < ginst->type_argc; ++i) {
6404                 MonoType *t = ginst->type_argv [i], *norm;
6405                 if (t->type != MONO_TYPE_VAR || t->data.generic_param->num != i || t->data.generic_param->owner != gcontainer)
6406                         is_denorm_gtd = FALSE;
6407                 norm = mono_type_normalize (t);
6408                 argv [i] = norm;
6409                 if (norm != t)
6410                         requires_rebind = TRUE;
6411         }
6412
6413         if (is_denorm_gtd)
6414                 return type->byref == gtd->byval_arg.byref ? &gtd->byval_arg : &gtd->this_arg;
6415
6416         if (requires_rebind) {
6417                 MonoClass *klass = mono_class_bind_generic_parameters (gtd, ginst->type_argc, argv, gclass->is_dynamic);
6418                 return type->byref == klass->byval_arg.byref ? &klass->byval_arg : &klass->this_arg;
6419         }
6420
6421         return type;
6422 }
6423 /*
6424  * mono_type_get_object:
6425  * @domain: an app domain
6426  * @type: a type
6427  *
6428  * Return an System.MonoType object representing the type @type.
6429  */
6430 MonoReflectionType*
6431 mono_type_get_object (MonoDomain *domain, MonoType *type)
6432 {
6433         MonoType *norm_type;
6434         MonoReflectionType *res;
6435         MonoClass *klass = mono_class_from_mono_type (type);
6436
6437         /*we must avoid using @type as it might have come
6438          * from a mono_metadata_type_dup and the caller
6439          * expects that is can be freed.
6440          * Using the right type from 
6441          */
6442         type = klass->byval_arg.byref == type->byref ? &klass->byval_arg : &klass->this_arg;
6443
6444         /* void is very common */
6445         if (type->type == MONO_TYPE_VOID && domain->typeof_void)
6446                 return (MonoReflectionType*)domain->typeof_void;
6447
6448         /*
6449          * If the vtable of the given class was already created, we can use
6450          * the MonoType from there and avoid all locking and hash table lookups.
6451          * 
6452          * We cannot do this for TypeBuilders as mono_reflection_create_runtime_class expects
6453          * that the resulting object is different.   
6454          */
6455         if (type == &klass->byval_arg && !klass->image->dynamic) {
6456                 MonoVTable *vtable = mono_class_try_get_vtable (domain, klass);
6457                 if (vtable && vtable->type)
6458                         return vtable->type;
6459         }
6460
6461         mono_loader_lock (); /*FIXME mono_class_init and mono_class_vtable acquire it*/
6462         mono_domain_lock (domain);
6463         if (!domain->type_hash)
6464                 domain->type_hash = mono_g_hash_table_new_type ((GHashFunc)mono_metadata_type_hash, 
6465                                 (GCompareFunc)mono_metadata_type_equal, MONO_HASH_VALUE_GC);
6466         if ((res = mono_g_hash_table_lookup (domain->type_hash, type))) {
6467                 mono_domain_unlock (domain);
6468                 mono_loader_unlock ();
6469                 return res;
6470         }
6471
6472         /*Types must be normalized so a generic instance of the GTD get's the same inner type.
6473          * For example in: Foo<A,B>; Bar<A> : Foo<A, Bar<A>>
6474          * The second Bar will be encoded a generic instance of Bar with <A> as parameter.
6475          * On all other places, Bar<A> will be encoded as the GTD itself. This is an implementation
6476          * artifact of how generics are encoded and should be transparent to managed code so we
6477          * need to weed out this diference when retrieving managed System.Type objects.
6478          */
6479         norm_type = mono_type_normalize (type);
6480         if (norm_type != type) {
6481                 res = mono_type_get_object (domain, norm_type);
6482                 mono_g_hash_table_insert (domain->type_hash, type, res);
6483                 mono_domain_unlock (domain);
6484                 mono_loader_unlock ();
6485                 return res;
6486         }
6487
6488         /* This MonoGenericClass hack is no longer necessary. Let's leave it here until we finish with the 2-stage type-builder setup.*/
6489         if ((type->type == MONO_TYPE_GENERICINST) && type->data.generic_class->is_dynamic && !type->data.generic_class->container_class->wastypebuilder)
6490                 g_assert (0);
6491
6492         if (!verify_safe_for_managed_space (type)) {
6493                 mono_domain_unlock (domain);
6494                 mono_loader_unlock ();
6495                 mono_raise_exception (mono_get_exception_invalid_operation ("This type cannot be propagated to managed space"));
6496         }
6497
6498         if (mono_class_get_ref_info (klass) && !klass->wastypebuilder) {
6499                 gboolean is_type_done = TRUE;
6500                 /* Generic parameters have reflection_info set but they are not finished together with their enclosing type.
6501                  * We must ensure that once a type is finished we don't return a GenericTypeParameterBuilder.
6502                  * We can't simply close the types as this will interfere with other parts of the generics machinery.
6503                 */
6504                 if (klass->byval_arg.type == MONO_TYPE_MVAR || klass->byval_arg.type == MONO_TYPE_VAR) {
6505                         MonoGenericParam *gparam = klass->byval_arg.data.generic_param;
6506
6507                         if (gparam->owner && gparam->owner->is_method) {
6508                                 MonoMethod *method = gparam->owner->owner.method;
6509                                 if (method && mono_class_get_generic_type_definition (method->klass)->wastypebuilder)
6510                                         is_type_done = FALSE;
6511                         } else if (gparam->owner && !gparam->owner->is_method) {
6512                                 MonoClass *klass = gparam->owner->owner.klass;
6513                                 if (klass && mono_class_get_generic_type_definition (klass)->wastypebuilder)
6514                                         is_type_done = FALSE;
6515                         }
6516                 } 
6517
6518                 /* g_assert_not_reached (); */
6519                 /* should this be considered an error condition? */
6520                 if (is_type_done && !type->byref) {
6521                         mono_domain_unlock (domain);
6522                         mono_loader_unlock ();
6523                         return mono_class_get_ref_info (klass);
6524                 }
6525         }
6526         /* This is stored in vtables/JITted code so it has to be pinned */
6527         res = (MonoReflectionType *)mono_object_new_pinned (domain, mono_defaults.monotype_class);
6528         res->type = type;
6529         mono_g_hash_table_insert (domain->type_hash, type, res);
6530
6531         if (type->type == MONO_TYPE_VOID)
6532                 domain->typeof_void = (MonoObject*)res;
6533
6534         mono_domain_unlock (domain);
6535         mono_loader_unlock ();
6536         return res;
6537 }
6538
6539 /*
6540  * mono_method_get_object:
6541  * @domain: an app domain
6542  * @method: a method
6543  * @refclass: the reflected type (can be NULL)
6544  *
6545  * Return an System.Reflection.MonoMethod object representing the method @method.
6546  */
6547 MonoReflectionMethod*
6548 mono_method_get_object (MonoDomain *domain, MonoMethod *method, MonoClass *refclass)
6549 {
6550         /*
6551          * We use the same C representation for methods and constructors, but the type 
6552          * name in C# is different.
6553          */
6554         static MonoClass *System_Reflection_MonoMethod = NULL;
6555         static MonoClass *System_Reflection_MonoCMethod = NULL;
6556         static MonoClass *System_Reflection_MonoGenericMethod = NULL;
6557         static MonoClass *System_Reflection_MonoGenericCMethod = NULL;
6558         MonoClass *klass;
6559         MonoReflectionMethod *ret;
6560
6561         if (method->is_inflated) {
6562                 MonoReflectionGenericMethod *gret;
6563
6564                 refclass = method->klass;
6565                 CHECK_OBJECT (MonoReflectionMethod *, method, refclass);
6566                 if ((*method->name == '.') && (!strcmp (method->name, ".ctor") || !strcmp (method->name, ".cctor"))) {
6567                         if (!System_Reflection_MonoGenericCMethod)
6568                                 System_Reflection_MonoGenericCMethod = mono_class_from_name (mono_defaults.corlib, "System.Reflection", "MonoGenericCMethod");
6569                         klass = System_Reflection_MonoGenericCMethod;
6570                 } else {
6571                         if (!System_Reflection_MonoGenericMethod)
6572                                 System_Reflection_MonoGenericMethod = mono_class_from_name (mono_defaults.corlib, "System.Reflection", "MonoGenericMethod");
6573                         klass = System_Reflection_MonoGenericMethod;
6574                 }
6575                 gret = (MonoReflectionGenericMethod*)mono_object_new (domain, klass);
6576                 gret->method.method = method;
6577                 MONO_OBJECT_SETREF (gret, method.name, mono_string_new (domain, method->name));
6578                 MONO_OBJECT_SETREF (gret, method.reftype, mono_type_get_object (domain, &refclass->byval_arg));
6579                 CACHE_OBJECT (MonoReflectionMethod *, method, (MonoReflectionMethod*)gret, refclass);
6580         }
6581
6582         if (!refclass)
6583                 refclass = method->klass;
6584
6585         CHECK_OBJECT (MonoReflectionMethod *, method, refclass);
6586         if (*method->name == '.' && (strcmp (method->name, ".ctor") == 0 || strcmp (method->name, ".cctor") == 0)) {
6587                 if (!System_Reflection_MonoCMethod)
6588                         System_Reflection_MonoCMethod = mono_class_from_name (mono_defaults.corlib, "System.Reflection", "MonoCMethod");
6589                 klass = System_Reflection_MonoCMethod;
6590         }
6591         else {
6592                 if (!System_Reflection_MonoMethod)
6593                         System_Reflection_MonoMethod = mono_class_from_name (mono_defaults.corlib, "System.Reflection", "MonoMethod");
6594                 klass = System_Reflection_MonoMethod;
6595         }
6596         ret = (MonoReflectionMethod*)mono_object_new (domain, klass);
6597         ret->method = method;
6598         MONO_OBJECT_SETREF (ret, reftype, mono_type_get_object (domain, &refclass->byval_arg));
6599         CACHE_OBJECT (MonoReflectionMethod *, method, ret, refclass);
6600 }
6601
6602 /*
6603  * mono_method_clear_object:
6604  *
6605  *   Clear the cached reflection objects for the dynamic method METHOD.
6606  */
6607 void
6608 mono_method_clear_object (MonoDomain *domain, MonoMethod *method)
6609 {
6610         MonoClass *klass;
6611         g_assert (method->dynamic);
6612
6613         klass = method->klass;
6614         while (klass) {
6615                 clear_cached_object (domain, method, klass);
6616                 klass = klass->parent;
6617         }
6618         /* Added by mono_param_get_objects () */
6619         clear_cached_object (domain, &(method->signature), NULL);
6620         klass = method->klass;
6621         while (klass) {
6622                 clear_cached_object (domain, &(method->signature), klass);
6623                 klass = klass->parent;
6624         }
6625 }
6626
6627 /*
6628  * mono_field_get_object:
6629  * @domain: an app domain
6630  * @klass: a type
6631  * @field: a field
6632  *
6633  * Return an System.Reflection.MonoField object representing the field @field
6634  * in class @klass.
6635  */
6636 MonoReflectionField*
6637 mono_field_get_object (MonoDomain *domain, MonoClass *klass, MonoClassField *field)
6638 {
6639         MonoReflectionField *res;
6640         static MonoClass *monofield_klass;
6641
6642         CHECK_OBJECT (MonoReflectionField *, field, klass);
6643         if (!monofield_klass)
6644                 monofield_klass = mono_class_from_name (mono_defaults.corlib, "System.Reflection", "MonoField");
6645         res = (MonoReflectionField *)mono_object_new (domain, monofield_klass);
6646         res->klass = klass;
6647         res->field = field;
6648         MONO_OBJECT_SETREF (res, name, mono_string_new (domain, mono_field_get_name (field)));
6649
6650         if (is_field_on_inst (field)) {
6651                 res->attrs = get_field_on_inst_generic_type (field)->attrs;
6652                 MONO_OBJECT_SETREF (res, type, mono_type_get_object (domain, field->type));
6653         } else {
6654                 if (field->type)
6655                         MONO_OBJECT_SETREF (res, type, mono_type_get_object (domain, field->type));
6656                 res->attrs = mono_field_get_flags (field);
6657         }
6658         CACHE_OBJECT (MonoReflectionField *, field, res, klass);
6659 }
6660
6661 /*
6662  * mono_property_get_object:
6663  * @domain: an app domain
6664  * @klass: a type
6665  * @property: a property
6666  *
6667  * Return an System.Reflection.MonoProperty object representing the property @property
6668  * in class @klass.
6669  */
6670 MonoReflectionProperty*
6671 mono_property_get_object (MonoDomain *domain, MonoClass *klass, MonoProperty *property)
6672 {
6673         MonoReflectionProperty *res;
6674         static MonoClass *monoproperty_klass;
6675
6676         CHECK_OBJECT (MonoReflectionProperty *, property, klass);
6677         if (!monoproperty_klass)
6678                 monoproperty_klass = mono_class_from_name (mono_defaults.corlib, "System.Reflection", "MonoProperty");
6679         res = (MonoReflectionProperty *)mono_object_new (domain, monoproperty_klass);
6680         res->klass = klass;
6681         res->property = property;
6682         CACHE_OBJECT (MonoReflectionProperty *, property, res, klass);
6683 }
6684
6685 /*
6686  * mono_event_get_object:
6687  * @domain: an app domain
6688  * @klass: a type
6689  * @event: a event
6690  *
6691  * Return an System.Reflection.MonoEvent object representing the event @event
6692  * in class @klass.
6693  */
6694 MonoReflectionEvent*
6695 mono_event_get_object (MonoDomain *domain, MonoClass *klass, MonoEvent *event)
6696 {
6697         MonoReflectionEvent *res;
6698         MonoReflectionMonoEvent *mono_event;
6699         static MonoClass *monoevent_klass;
6700
6701         CHECK_OBJECT (MonoReflectionEvent *, event, klass);
6702         if (!monoevent_klass)
6703                 monoevent_klass = mono_class_from_name (mono_defaults.corlib, "System.Reflection", "MonoEvent");
6704         mono_event = (MonoReflectionMonoEvent *)mono_object_new (domain, monoevent_klass);
6705         mono_event->klass = klass;
6706         mono_event->event = event;
6707         res = (MonoReflectionEvent*)mono_event;
6708         CACHE_OBJECT (MonoReflectionEvent *, event, res, klass);
6709 }
6710
6711 /**
6712  * mono_get_reflection_missing_object:
6713  * @domain: Domain where the object lives
6714  *
6715  * Returns the System.Reflection.Missing.Value singleton object
6716  * (of type System.Reflection.Missing).
6717  *
6718  * Used as the value for ParameterInfo.DefaultValue when Optional
6719  * is present
6720  */
6721 static MonoObject *
6722 mono_get_reflection_missing_object (MonoDomain *domain)
6723 {
6724         MonoObject *obj;
6725         static MonoClassField *missing_value_field = NULL;
6726         
6727         if (!missing_value_field) {
6728                 MonoClass *missing_klass;
6729                 missing_klass = mono_class_from_name (mono_defaults.corlib, "System.Reflection", "Missing");
6730                 mono_class_init (missing_klass);
6731                 missing_value_field = mono_class_get_field_from_name (missing_klass, "Value");
6732                 g_assert (missing_value_field);
6733         }
6734         obj = mono_field_get_value_object (domain, missing_value_field, NULL); 
6735         g_assert (obj);
6736         return obj;
6737 }
6738
6739 static MonoObject*
6740 get_dbnull (MonoDomain *domain, MonoObject **dbnull)
6741 {
6742         if (!*dbnull)
6743                 *dbnull = mono_get_dbnull_object (domain);
6744         return *dbnull;
6745 }
6746
6747 static MonoObject*
6748 get_reflection_missing (MonoDomain *domain, MonoObject **reflection_missing)
6749 {
6750         if (!*reflection_missing)
6751                 *reflection_missing = mono_get_reflection_missing_object (domain);
6752         return *reflection_missing;
6753 }
6754
6755 /*
6756  * mono_param_get_objects:
6757  * @domain: an app domain
6758  * @method: a method
6759  *
6760  * Return an System.Reflection.ParameterInfo array object representing the parameters
6761  * in the method @method.
6762  */
6763 MonoArray*
6764 mono_param_get_objects_internal (MonoDomain *domain, MonoMethod *method, MonoClass *refclass)
6765 {
6766         static MonoClass *System_Reflection_ParameterInfo;
6767         static MonoClass *System_Reflection_ParameterInfo_array;
6768         MonoError error;
6769         MonoArray *res = NULL;
6770         MonoReflectionMethod *member = NULL;
6771         MonoReflectionParameter *param = NULL;
6772         char **names, **blobs = NULL;
6773         guint32 *types = NULL;
6774         MonoType *type = NULL;
6775         MonoObject *dbnull = NULL;
6776         MonoObject *missing = NULL;
6777         MonoMarshalSpec **mspecs;
6778         MonoMethodSignature *sig;
6779         MonoVTable *pinfo_vtable;
6780         int i;
6781
6782         if (!System_Reflection_ParameterInfo_array) {
6783                 MonoClass *klass;
6784
6785                 klass = mono_class_from_name (mono_defaults.corlib, "System.Reflection", "MonoParameterInfo");
6786                 if (!klass)
6787                         klass = mono_class_from_name (mono_defaults.corlib, "System.Reflection", "ParameterInfo");
6788
6789                 mono_memory_barrier ();
6790                 System_Reflection_ParameterInfo = klass; 
6791
6792         
6793                 klass = mono_array_class_get (klass, 1);
6794                 mono_memory_barrier ();
6795                 System_Reflection_ParameterInfo_array = klass;
6796         }
6797
6798         sig = mono_method_signature_checked (method, &error);
6799         if (!mono_error_ok (&error))
6800                 mono_error_raise_exception (&error);
6801
6802         if (!sig->param_count)
6803                 return mono_array_new_specific (mono_class_vtable (domain, System_Reflection_ParameterInfo_array), 0);
6804
6805         /* Note: the cache is based on the address of the signature into the method
6806          * since we already cache MethodInfos with the method as keys.
6807          */
6808         CHECK_OBJECT (MonoArray*, &(method->signature), refclass);
6809
6810         member = mono_method_get_object (domain, method, refclass);
6811         names = g_new (char *, sig->param_count);
6812         mono_method_get_param_names (method, (const char **) names);
6813
6814         mspecs = g_new (MonoMarshalSpec*, sig->param_count + 1);
6815         mono_method_get_marshal_info (method, mspecs);
6816
6817         res = mono_array_new_specific (mono_class_vtable (domain, System_Reflection_ParameterInfo_array), sig->param_count);
6818         pinfo_vtable = mono_class_vtable (domain, System_Reflection_ParameterInfo);
6819         for (i = 0; i < sig->param_count; ++i) {
6820                 param = (MonoReflectionParameter *)mono_object_new_specific (pinfo_vtable);
6821                 MONO_OBJECT_SETREF (param, ClassImpl, mono_type_get_object (domain, sig->params [i]));
6822                 MONO_OBJECT_SETREF (param, MemberImpl, (MonoObject*)member);
6823                 MONO_OBJECT_SETREF (param, NameImpl, mono_string_new (domain, names [i]));
6824                 param->PositionImpl = i;
6825                 param->AttrsImpl = sig->params [i]->attrs;
6826
6827                 if (!(param->AttrsImpl & PARAM_ATTRIBUTE_HAS_DEFAULT)) {
6828                         if (param->AttrsImpl & PARAM_ATTRIBUTE_OPTIONAL)
6829                                 MONO_OBJECT_SETREF (param, DefaultValueImpl, get_reflection_missing (domain, &missing));
6830                         else
6831                                 MONO_OBJECT_SETREF (param, DefaultValueImpl, get_dbnull (domain, &dbnull));
6832                 } else {
6833
6834                         if (!blobs) {
6835                                 blobs = g_new0 (char *, sig->param_count);
6836                                 types = g_new0 (guint32, sig->param_count);
6837                                 get_default_param_value_blobs (method, blobs, types); 
6838                         }
6839
6840                         /* Build MonoType for the type from the Constant Table */
6841                         if (!type)
6842                                 type = g_new0 (MonoType, 1);
6843                         type->type = types [i];
6844                         type->data.klass = NULL;
6845                         if (types [i] == MONO_TYPE_CLASS)
6846                                 type->data.klass = mono_defaults.object_class;
6847                         else if ((sig->params [i]->type == MONO_TYPE_VALUETYPE) && sig->params [i]->data.klass->enumtype) {
6848                                 /* For enums, types [i] contains the base type */
6849
6850                                         type->type = MONO_TYPE_VALUETYPE;
6851                                         type->data.klass = mono_class_from_mono_type (sig->params [i]);
6852                         } else
6853                                 type->data.klass = mono_class_from_mono_type (type);
6854
6855                         MONO_OBJECT_SETREF (param, DefaultValueImpl, mono_get_object_from_blob (domain, type, blobs [i]));
6856
6857                         /* Type in the Constant table is MONO_TYPE_CLASS for nulls */
6858                         if (types [i] != MONO_TYPE_CLASS && !param->DefaultValueImpl) {
6859                                 if (param->AttrsImpl & PARAM_ATTRIBUTE_OPTIONAL)
6860                                         MONO_OBJECT_SETREF (param, DefaultValueImpl, get_reflection_missing (domain, &missing));
6861                                 else
6862                                         MONO_OBJECT_SETREF (param, DefaultValueImpl, get_dbnull (domain, &dbnull));
6863                         }
6864                         
6865                 }
6866
6867                 if (mspecs [i + 1])
6868                         MONO_OBJECT_SETREF (param, MarshalAsImpl, (MonoObject*)mono_reflection_marshal_as_attribute_from_marshal_spec (domain, method->klass, mspecs [i + 1]));
6869                 
6870                 mono_array_setref (res, i, param);
6871         }
6872         g_free (names);
6873         g_free (blobs);
6874         g_free (types);
6875         g_free (type);
6876
6877         for (i = mono_method_signature (method)->param_count; i >= 0; i--)
6878                 if (mspecs [i])
6879                         mono_metadata_free_marshal_spec (mspecs [i]);
6880         g_free (mspecs);
6881         
6882         CACHE_OBJECT (MonoArray *, &(method->signature), res, refclass);
6883 }
6884
6885 MonoArray*
6886 mono_param_get_objects (MonoDomain *domain, MonoMethod *method)
6887 {
6888         return mono_param_get_objects_internal (domain, method, NULL);
6889 }
6890
6891 /*
6892  * mono_method_body_get_object:
6893  * @domain: an app domain
6894  * @method: a method
6895  *
6896  * Return an System.Reflection.MethodBody object representing the method @method.
6897  */
6898 MonoReflectionMethodBody*
6899 mono_method_body_get_object (MonoDomain *domain, MonoMethod *method)
6900 {
6901         static MonoClass *System_Reflection_MethodBody = NULL;
6902         static MonoClass *System_Reflection_LocalVariableInfo = NULL;
6903         static MonoClass *System_Reflection_ExceptionHandlingClause = NULL;
6904         MonoReflectionMethodBody *ret;
6905         MonoMethodHeader *header;
6906         MonoImage *image;
6907         guint32 method_rva, local_var_sig_token;
6908     char *ptr;
6909         unsigned char format, flags;
6910         int i;
6911
6912         /* for compatibility with .net */
6913     if (method->dynamic)
6914         mono_raise_exception (mono_get_exception_invalid_operation (NULL));
6915
6916         if (!System_Reflection_MethodBody)
6917                 System_Reflection_MethodBody = mono_class_from_name (mono_defaults.corlib, "System.Reflection", "MethodBody");
6918         if (!System_Reflection_LocalVariableInfo)
6919                 System_Reflection_LocalVariableInfo = mono_class_from_name (mono_defaults.corlib, "System.Reflection", "LocalVariableInfo");
6920         if (!System_Reflection_ExceptionHandlingClause)
6921                 System_Reflection_ExceptionHandlingClause = mono_class_from_name (mono_defaults.corlib, "System.Reflection", "ExceptionHandlingClause");
6922
6923         CHECK_OBJECT (MonoReflectionMethodBody *, method, NULL);
6924
6925         if ((method->flags & METHOD_ATTRIBUTE_PINVOKE_IMPL) ||
6926                 (method->flags & METHOD_ATTRIBUTE_ABSTRACT) ||
6927             (method->iflags & METHOD_IMPL_ATTRIBUTE_INTERNAL_CALL) ||
6928             (method->iflags & METHOD_IMPL_ATTRIBUTE_RUNTIME))
6929                 return NULL;
6930
6931         image = method->klass->image;
6932         header = mono_method_get_header (method);
6933
6934         if (!image->dynamic) {
6935                 /* Obtain local vars signature token */
6936                 method_rva = mono_metadata_decode_row_col (&image->tables [MONO_TABLE_METHOD], mono_metadata_token_index (method->token) - 1, MONO_METHOD_RVA);
6937                 ptr = mono_image_rva_map (image, method_rva);
6938                 flags = *(const unsigned char *) ptr;
6939                 format = flags & METHOD_HEADER_FORMAT_MASK;
6940                 switch (format){
6941                 case METHOD_HEADER_TINY_FORMAT:
6942                         local_var_sig_token = 0;
6943                         break;
6944                 case METHOD_HEADER_FAT_FORMAT:
6945                         ptr += 2;
6946                         ptr += 2;
6947                         ptr += 4;
6948                         local_var_sig_token = read32 (ptr);
6949                         break;
6950                 default:
6951                         g_assert_not_reached ();
6952                 }
6953         } else
6954                 local_var_sig_token = 0; //FIXME
6955
6956         ret = (MonoReflectionMethodBody*)mono_object_new (domain, System_Reflection_MethodBody);
6957
6958         ret->init_locals = header->init_locals;
6959         ret->max_stack = header->max_stack;
6960         ret->local_var_sig_token = local_var_sig_token;
6961         MONO_OBJECT_SETREF (ret, il, mono_array_new_cached (domain, mono_defaults.byte_class, header->code_size));
6962         memcpy (mono_array_addr (ret->il, guint8, 0), header->code, header->code_size);
6963
6964         /* Locals */
6965         MONO_OBJECT_SETREF (ret, locals, mono_array_new_cached (domain, System_Reflection_LocalVariableInfo, header->num_locals));
6966         for (i = 0; i < header->num_locals; ++i) {
6967                 MonoReflectionLocalVariableInfo *info = (MonoReflectionLocalVariableInfo*)mono_object_new (domain, System_Reflection_LocalVariableInfo);
6968                 MONO_OBJECT_SETREF (info, local_type, mono_type_get_object (domain, header->locals [i]));
6969                 info->is_pinned = header->locals [i]->pinned;
6970                 info->local_index = i;
6971                 mono_array_setref (ret->locals, i, info);
6972         }
6973
6974         /* Exceptions */
6975         MONO_OBJECT_SETREF (ret, clauses, mono_array_new_cached (domain, System_Reflection_ExceptionHandlingClause, header->num_clauses));
6976         for (i = 0; i < header->num_clauses; ++i) {
6977                 MonoReflectionExceptionHandlingClause *info = (MonoReflectionExceptionHandlingClause*)mono_object_new (domain, System_Reflection_ExceptionHandlingClause);
6978                 MonoExceptionClause *clause = &header->clauses [i];
6979
6980                 info->flags = clause->flags;
6981                 info->try_offset = clause->try_offset;
6982                 info->try_length = clause->try_len;
6983                 info->handler_offset = clause->handler_offset;
6984                 info->handler_length = clause->handler_len;
6985                 if (clause->flags == MONO_EXCEPTION_CLAUSE_FILTER)
6986                         info->filter_offset = clause->data.filter_offset;
6987                 else if (clause->data.catch_class)
6988                         MONO_OBJECT_SETREF (info, catch_type, mono_type_get_object (mono_domain_get (), &clause->data.catch_class->byval_arg));
6989
6990                 mono_array_setref (ret->clauses, i, info);
6991         }
6992
6993         mono_metadata_free_mh (header);
6994         CACHE_OBJECT (MonoReflectionMethodBody *, method, ret, NULL);
6995         return ret;
6996 }
6997
6998 /**
6999  * mono_get_dbnull_object:
7000  * @domain: Domain where the object lives
7001  *
7002  * Returns the System.DBNull.Value singleton object
7003  *
7004  * Used as the value for ParameterInfo.DefaultValue 
7005  */
7006 MonoObject *
7007 mono_get_dbnull_object (MonoDomain *domain)
7008 {
7009         MonoObject *obj;
7010         static MonoClassField *dbnull_value_field = NULL;
7011         
7012         if (!dbnull_value_field) {
7013                 MonoClass *dbnull_klass;
7014                 dbnull_klass = mono_class_from_name (mono_defaults.corlib, "System", "DBNull");
7015                 mono_class_init (dbnull_klass);
7016                 dbnull_value_field = mono_class_get_field_from_name (dbnull_klass, "Value");
7017                 g_assert (dbnull_value_field);
7018         }
7019         obj = mono_field_get_value_object (domain, dbnull_value_field, NULL); 
7020         g_assert (obj);
7021         return obj;
7022 }
7023
7024 static void
7025 get_default_param_value_blobs (MonoMethod *method, char **blobs, guint32 *types)
7026 {
7027         guint32 param_index, i, lastp, crow = 0;
7028         guint32 param_cols [MONO_PARAM_SIZE], const_cols [MONO_CONSTANT_SIZE];
7029         gint32 idx;
7030
7031         MonoClass *klass = method->klass;
7032         MonoImage *image = klass->image;
7033         MonoMethodSignature *methodsig = mono_method_signature (method);
7034
7035         MonoTableInfo *constt;
7036         MonoTableInfo *methodt;
7037         MonoTableInfo *paramt;
7038
7039         if (!methodsig->param_count)
7040                 return;
7041
7042         mono_class_init (klass);
7043
7044         if (klass->image->dynamic) {
7045                 MonoReflectionMethodAux *aux;
7046                 if (method->is_inflated)
7047                         method = ((MonoMethodInflated*)method)->declaring;
7048                 aux = g_hash_table_lookup (((MonoDynamicImage*)method->klass->image)->method_aux_hash, method);
7049                 if (aux && aux->param_defaults) {
7050                         memcpy (blobs, &(aux->param_defaults [1]), methodsig->param_count * sizeof (char*));
7051                         memcpy (types, &(aux->param_default_types [1]), methodsig->param_count * sizeof (guint32));
7052                 }
7053                 return;
7054         }
7055
7056         methodt = &klass->image->tables [MONO_TABLE_METHOD];
7057         paramt = &klass->image->tables [MONO_TABLE_PARAM];
7058         constt = &image->tables [MONO_TABLE_CONSTANT];
7059
7060         idx = mono_method_get_index (method) - 1;
7061         g_assert (idx != -1);
7062
7063         param_index = mono_metadata_decode_row_col (methodt, idx, MONO_METHOD_PARAMLIST);
7064         if (idx + 1 < methodt->rows)
7065                 lastp = mono_metadata_decode_row_col (methodt, idx + 1, MONO_METHOD_PARAMLIST);
7066         else
7067                 lastp = paramt->rows + 1;
7068
7069         for (i = param_index; i < lastp; ++i) {
7070                 guint32 paramseq;
7071
7072                 mono_metadata_decode_row (paramt, i - 1, param_cols, MONO_PARAM_SIZE);
7073                 paramseq = param_cols [MONO_PARAM_SEQUENCE];
7074
7075                 if (!(param_cols [MONO_PARAM_FLAGS] & PARAM_ATTRIBUTE_HAS_DEFAULT))
7076                         continue;
7077
7078                 crow = mono_metadata_get_constant_index (image, MONO_TOKEN_PARAM_DEF | i, crow + 1);
7079                 if (!crow) {
7080                         continue;
7081                 }
7082         
7083                 mono_metadata_decode_row (constt, crow - 1, const_cols, MONO_CONSTANT_SIZE);
7084                 blobs [paramseq - 1] = (gpointer) mono_metadata_blob_heap (image, const_cols [MONO_CONSTANT_VALUE]);
7085                 types [paramseq - 1] = const_cols [MONO_CONSTANT_TYPE];
7086         }
7087
7088         return;
7089 }
7090
7091 MonoObject *
7092 mono_get_object_from_blob (MonoDomain *domain, MonoType *type, const char *blob)
7093 {
7094         void *retval;
7095         MonoClass *klass;
7096         MonoObject *object;
7097         MonoType *basetype = type;
7098
7099         if (!blob)
7100                 return NULL;
7101         
7102         klass = mono_class_from_mono_type (type);
7103         if (klass->valuetype) {
7104                 object = mono_object_new (domain, klass);
7105                 retval = ((gchar *) object + sizeof (MonoObject));
7106                 if (klass->enumtype)
7107                         basetype = mono_class_enum_basetype (klass);
7108         } else {
7109                 retval = &object;
7110         }
7111                         
7112         if (!mono_get_constant_value_from_blob (domain, basetype->type,  blob, retval))
7113                 return object;
7114         else
7115                 return NULL;
7116 }
7117
7118 static int
7119 assembly_name_to_aname (MonoAssemblyName *assembly, char *p) {
7120         int found_sep;
7121         char *s;
7122         gboolean quoted = FALSE;
7123
7124         memset (assembly, 0, sizeof (MonoAssemblyName));
7125         assembly->culture = "";
7126         memset (assembly->public_key_token, 0, MONO_PUBLIC_KEY_TOKEN_LENGTH);
7127
7128         if (*p == '"') {
7129                 quoted = TRUE;
7130                 p++;
7131         }
7132         assembly->name = p;
7133         while (*p && (isalnum (*p) || *p == '.' || *p == '-' || *p == '_' || *p == '$' || *p == '@' || g_ascii_isspace (*p)))
7134                 p++;
7135         if (quoted) {
7136                 if (*p != '"')
7137                         return 1;
7138                 *p = 0;
7139                 p++;
7140         }
7141         if (*p != ',')
7142                 return 1;
7143         *p = 0;
7144         /* Remove trailing whitespace */
7145         s = p - 1;
7146         while (*s && g_ascii_isspace (*s))
7147                 *s-- = 0;
7148         p ++;
7149         while (g_ascii_isspace (*p))
7150                 p++;
7151         while (*p) {
7152                 if (*p == 'V' && g_ascii_strncasecmp (p, "Version=", 8) == 0) {
7153                         p += 8;
7154                         assembly->major = strtoul (p, &s, 10);
7155                         if (s == p || *s != '.')
7156                                 return 1;
7157                         p = ++s;
7158                         assembly->minor = strtoul (p, &s, 10);
7159                         if (s == p || *s != '.')
7160                                 return 1;
7161                         p = ++s;
7162                         assembly->build = strtoul (p, &s, 10);
7163                         if (s == p || *s != '.')
7164                                 return 1;
7165                         p = ++s;
7166                         assembly->revision = strtoul (p, &s, 10);
7167                         if (s == p)
7168                                 return 1;
7169                         p = s;
7170                 } else if (*p == 'C' && g_ascii_strncasecmp (p, "Culture=", 8) == 0) {
7171                         p += 8;
7172                         if (g_ascii_strncasecmp (p, "neutral", 7) == 0) {
7173                                 assembly->culture = "";
7174                                 p += 7;
7175                         } else {
7176                                 assembly->culture = p;
7177                                 while (*p && *p != ',') {
7178                                         p++;
7179                                 }
7180                         }
7181                 } else if (*p == 'P' && g_ascii_strncasecmp (p, "PublicKeyToken=", 15) == 0) {
7182                         p += 15;
7183                         if (strncmp (p, "null", 4) == 0) {
7184                                 p += 4;
7185                         } else {
7186                                 int len;
7187                                 gchar *start = p;
7188                                 while (*p && *p != ',') {
7189                                         p++;
7190                                 }
7191                                 len = (p - start + 1);
7192                                 if (len > MONO_PUBLIC_KEY_TOKEN_LENGTH)
7193                                         len = MONO_PUBLIC_KEY_TOKEN_LENGTH;
7194                                 g_strlcpy ((char*)assembly->public_key_token, start, len);
7195                         }
7196                 } else {
7197                         while (*p && *p != ',')
7198                                 p++;
7199                 }
7200                 found_sep = 0;
7201                 while (g_ascii_isspace (*p) || *p == ',') {
7202                         *p++ = 0;
7203                         found_sep = 1;
7204                         continue;
7205                 }
7206                 /* failed */
7207                 if (!found_sep)
7208                         return 1;
7209         }
7210
7211         return 0;
7212 }
7213
7214 /*
7215  * mono_reflection_parse_type:
7216  * @name: type name
7217  *
7218  * Parse a type name as accepted by the GetType () method and output the info
7219  * extracted in the info structure.
7220  * the name param will be mangled, so, make a copy before passing it to this function.
7221  * The fields in info will be valid until the memory pointed to by name is valid.
7222  *
7223  * See also mono_type_get_name () below.
7224  *
7225  * Returns: 0 on parse error.
7226  */
7227 static int
7228 _mono_reflection_parse_type (char *name, char **endptr, gboolean is_recursed,
7229                              MonoTypeNameParse *info)
7230 {
7231         char *start, *p, *w, *last_point, *startn;
7232         int in_modifiers = 0;
7233         int isbyref = 0, rank = 0;
7234
7235         start = p = w = name;
7236
7237         //FIXME could we just zero the whole struct? memset (&info, 0, sizeof (MonoTypeNameParse))
7238         memset (&info->assembly, 0, sizeof (MonoAssemblyName));
7239         info->name = info->name_space = NULL;
7240         info->nested = NULL;
7241         info->modifiers = NULL;
7242         info->type_arguments = NULL;
7243
7244         /* last_point separates the namespace from the name */
7245         last_point = NULL;
7246         /* Skips spaces */
7247         while (*p == ' ') p++, start++, w++, name++;
7248
7249         while (*p) {
7250                 switch (*p) {
7251                 case '+':
7252                         *p = 0; /* NULL terminate the name */
7253                         startn = p + 1;
7254                         info->nested = g_list_append (info->nested, startn);
7255                         /* we have parsed the nesting namespace + name */
7256                         if (info->name)
7257                                 break;
7258                         if (last_point) {
7259                                 info->name_space = start;
7260                                 *last_point = 0;
7261                                 info->name = last_point + 1;
7262                         } else {
7263                                 info->name_space = (char *)"";
7264                                 info->name = start;
7265                         }
7266                         break;
7267                 case '.':
7268                         last_point = p;
7269                         break;
7270                 case '\\':
7271                         ++p;
7272                         break;
7273                 case '&':
7274                 case '*':
7275                 case '[':
7276                 case ',':
7277                 case ']':
7278                         in_modifiers = 1;
7279                         break;
7280                 default:
7281                         break;
7282                 }
7283                 if (in_modifiers)
7284                         break;
7285                 // *w++ = *p++;
7286                 p++;
7287         }
7288         
7289         if (!info->name) {
7290                 if (last_point) {
7291                         info->name_space = start;
7292                         *last_point = 0;
7293                         info->name = last_point + 1;
7294                 } else {
7295                         info->name_space = (char *)"";
7296                         info->name = start;
7297                 }
7298         }
7299         while (*p) {
7300                 switch (*p) {
7301                 case '&':
7302                         if (isbyref) /* only one level allowed by the spec */
7303                                 return 0;
7304                         isbyref = 1;
7305                         info->modifiers = g_list_append (info->modifiers, GUINT_TO_POINTER (0));
7306                         *p++ = 0;
7307                         break;
7308                 case '*':
7309                         info->modifiers = g_list_append (info->modifiers, GUINT_TO_POINTER (-1));
7310                         *p++ = 0;
7311                         break;
7312                 case '[':
7313                         //Decide if it's an array of a generic argument list
7314                         *p++ = 0;
7315
7316                         if (!*p) //XXX test
7317                                 return 0;
7318                         if (*p  == ',' || *p == '*' || *p == ']') { //array
7319                                 rank = 1;
7320                                 while (*p) {
7321                                         if (*p == ']')
7322                                                 break;
7323                                         if (*p == ',')
7324                                                 rank++;
7325                                         else if (*p == '*') /* '*' means unknown lower bound */
7326                                                 info->modifiers = g_list_append (info->modifiers, GUINT_TO_POINTER (-2));
7327                                         else
7328                                                 return 0;
7329                                         ++p;
7330                                 }
7331                                 if (*p++ != ']')
7332                                         return 0;
7333                                 info->modifiers = g_list_append (info->modifiers, GUINT_TO_POINTER (rank));
7334                         } else {
7335                                 if (rank) /* generic args after array spec*/ //XXX test
7336                                         return 0;
7337                                 info->type_arguments = g_ptr_array_new ();
7338                                 while (*p) {
7339                                         MonoTypeNameParse *subinfo = g_new0 (MonoTypeNameParse, 1);
7340                                         gboolean fqname = FALSE;
7341
7342                                         g_ptr_array_add (info->type_arguments, subinfo);
7343
7344                                         if (*p == '[') {
7345                                                 p++;
7346                                                 fqname = TRUE;
7347                                         }
7348
7349                                         if (!_mono_reflection_parse_type (p, &p, TRUE, subinfo))
7350                                                 return 0;
7351
7352                                         /*MS is lenient on [] delimited parameters that aren't fqn - and F# uses them.*/
7353                                         if (fqname && (*p != ']')) {
7354                                                 char *aname;
7355
7356                                                 if (*p != ',')
7357                                                         return 0;
7358                                                 *p++ = 0;
7359
7360                                                 aname = p;
7361                                                 while (*p && (*p != ']'))
7362                                                         p++;
7363
7364                                                 if (*p != ']')
7365                                                         return 0;
7366
7367                                                 *p++ = 0;
7368                                                 while (*aname) {
7369                                                         if (g_ascii_isspace (*aname)) {
7370                                                                 ++aname;
7371                                                                 continue;
7372                                                         }
7373                                                         break;
7374                                                 }
7375                                                 if (!*aname ||
7376                                                     !assembly_name_to_aname (&subinfo->assembly, aname))
7377                                                         return 0;
7378                                         } else if (fqname && (*p == ']')) {
7379                                                 *p++ = 0;
7380                                         }
7381                                         if (*p == ']') {
7382                                                 *p++ = 0;
7383                                                 break;
7384                                         } else if (!*p) {
7385                                                 return 0;
7386                                         }
7387                                         *p++ = 0;
7388                                 }
7389                         }
7390                         break;
7391                 case ']':
7392                         if (is_recursed)
7393                                 goto end;
7394                         return 0;
7395                 case ',':
7396                         if (is_recursed)
7397                                 goto end;
7398                         *p++ = 0;
7399                         while (*p) {
7400                                 if (g_ascii_isspace (*p)) {
7401                                         ++p;
7402                                         continue;
7403                                 }
7404                                 break;
7405                         }
7406                         if (!*p)
7407                                 return 0; /* missing assembly name */
7408                         if (!assembly_name_to_aname (&info->assembly, p))
7409                                 return 0;
7410                         break;
7411                 default:
7412                         return 0;
7413                 }
7414                 if (info->assembly.name)
7415                         break;
7416         }
7417         // *w = 0; /* terminate class name */
7418  end:
7419         if (!info->name || !*info->name)
7420                 return 0;
7421         if (endptr)
7422                 *endptr = p;
7423         /* add other consistency checks */
7424         return 1;
7425 }
7426
7427 int
7428 mono_reflection_parse_type (char *name, MonoTypeNameParse *info)
7429 {
7430         return _mono_reflection_parse_type (name, NULL, FALSE, info);
7431 }
7432
7433 static MonoType*
7434 _mono_reflection_get_type_from_info (MonoTypeNameParse *info, MonoImage *image, gboolean ignorecase)
7435 {
7436         gboolean type_resolve = FALSE;
7437         MonoType *type;
7438         MonoImage *rootimage = image;
7439
7440         if (info->assembly.name) {
7441                 MonoAssembly *assembly = mono_assembly_loaded (&info->assembly);
7442                 if (!assembly && image && image->assembly && mono_assembly_names_equal (&info->assembly, &image->assembly->aname))
7443                         /* 
7444                          * This could happen in the AOT compiler case when the search hook is not
7445                          * installed.
7446                          */
7447                         assembly = image->assembly;
7448                 if (!assembly) {
7449                         /* then we must load the assembly ourselve - see #60439 */
7450                         assembly = mono_assembly_load (&info->assembly, NULL, NULL);
7451                         if (!assembly)
7452                                 return NULL;
7453                 }
7454                 image = assembly->image;
7455         } else if (!image) {
7456                 image = mono_defaults.corlib;
7457         }
7458
7459         type = mono_reflection_get_type_with_rootimage (rootimage, image, info, ignorecase, &type_resolve);
7460         if (type == NULL && !info->assembly.name && image != mono_defaults.corlib) {
7461                 image = mono_defaults.corlib;
7462                 type = mono_reflection_get_type_with_rootimage (rootimage, image, info, ignorecase, &type_resolve);
7463         }
7464
7465         return type;
7466 }
7467
7468 static MonoType*
7469 mono_reflection_get_type_internal (MonoImage *rootimage, MonoImage* image, MonoTypeNameParse *info, gboolean ignorecase)
7470 {
7471         MonoClass *klass;
7472         GList *mod;
7473         int modval;
7474         gboolean bounded = FALSE;
7475         
7476         if (!image)
7477                 image = mono_defaults.corlib;
7478
7479         if (ignorecase)
7480                 klass = mono_class_from_name_case (image, info->name_space, info->name);
7481         else
7482                 klass = mono_class_from_name (image, info->name_space, info->name);
7483         if (!klass)
7484                 return NULL;
7485         for (mod = info->nested; mod; mod = mod->next) {
7486                 gpointer iter = NULL;
7487                 MonoClass *parent;
7488
7489                 parent = klass;
7490                 mono_class_init (parent);
7491
7492                 while ((klass = mono_class_get_nested_types (parent, &iter))) {
7493                         if (ignorecase) {
7494                                 if (mono_utf8_strcasecmp (klass->name, mod->data) == 0)
7495                                         break;
7496                         } else {
7497                                 if (strcmp (klass->name, mod->data) == 0)
7498                                         break;
7499                         }
7500                 }
7501                 if (!klass)
7502                         break;
7503         }
7504         if (!klass)
7505                 return NULL;
7506
7507         if (info->type_arguments) {
7508                 MonoType **type_args = g_new0 (MonoType *, info->type_arguments->len);
7509                 MonoReflectionType *the_type;
7510                 MonoType *instance;
7511                 int i;
7512
7513                 for (i = 0; i < info->type_arguments->len; i++) {
7514                         MonoTypeNameParse *subinfo = g_ptr_array_index (info->type_arguments, i);
7515
7516                         type_args [i] = _mono_reflection_get_type_from_info (subinfo, rootimage, ignorecase);
7517                         if (!type_args [i]) {
7518                                 g_free (type_args);
7519                                 return NULL;
7520                         }
7521                 }
7522
7523                 the_type = mono_type_get_object (mono_domain_get (), &klass->byval_arg);
7524
7525                 instance = mono_reflection_bind_generic_parameters (
7526                         the_type, info->type_arguments->len, type_args);
7527
7528                 g_free (type_args);
7529                 if (!instance)
7530                         return NULL;
7531
7532                 klass = mono_class_from_mono_type (instance);
7533         }
7534
7535         for (mod = info->modifiers; mod; mod = mod->next) {
7536                 modval = GPOINTER_TO_UINT (mod->data);
7537                 if (!modval) { /* byref: must be last modifier */
7538                         return &klass->this_arg;
7539                 } else if (modval == -1) {
7540                         klass = mono_ptr_class_get (&klass->byval_arg);
7541                 } else if (modval == -2) {
7542                         bounded = TRUE;
7543                 } else { /* array rank */
7544                         klass = mono_bounded_array_class_get (klass, modval, bounded);
7545                 }
7546         }
7547
7548         return &klass->byval_arg;
7549 }
7550
7551 /*
7552  * mono_reflection_get_type:
7553  * @image: a metadata context
7554  * @info: type description structure
7555  * @ignorecase: flag for case-insensitive string compares
7556  * @type_resolve: whenever type resolve was already tried
7557  *
7558  * Build a MonoType from the type description in @info.
7559  * 
7560  */
7561
7562 MonoType*
7563 mono_reflection_get_type (MonoImage* image, MonoTypeNameParse *info, gboolean ignorecase, gboolean *type_resolve) {
7564         return mono_reflection_get_type_with_rootimage(image, image, info, ignorecase, type_resolve);
7565 }
7566
7567 static MonoType*
7568 mono_reflection_get_type_internal_dynamic (MonoImage *rootimage, MonoAssembly *assembly, MonoTypeNameParse *info, gboolean ignorecase)
7569 {
7570         MonoReflectionAssemblyBuilder *abuilder;
7571         MonoType *type;
7572         int i;
7573
7574         g_assert (assembly->dynamic);
7575         abuilder = (MonoReflectionAssemblyBuilder*)mono_assembly_get_object (((MonoDynamicAssembly*)assembly)->domain, assembly);
7576
7577         /* Enumerate all modules */
7578
7579         type = NULL;
7580         if (abuilder->modules) {
7581                 for (i = 0; i < mono_array_length (abuilder->modules); ++i) {
7582                         MonoReflectionModuleBuilder *mb = mono_array_get (abuilder->modules, MonoReflectionModuleBuilder*, i);
7583                         type = mono_reflection_get_type_internal (rootimage, &mb->dynamic_image->image, info, ignorecase);
7584                         if (type)
7585                                 break;
7586                 }
7587         }
7588
7589         if (!type && abuilder->loaded_modules) {
7590                 for (i = 0; i < mono_array_length (abuilder->loaded_modules); ++i) {
7591                         MonoReflectionModule *mod = mono_array_get (abuilder->loaded_modules, MonoReflectionModule*, i);
7592                         type = mono_reflection_get_type_internal (rootimage, mod->image, info, ignorecase);
7593                         if (type)
7594                                 break;
7595                 }
7596         }
7597
7598         return type;
7599 }
7600         
7601 MonoType*
7602 mono_reflection_get_type_with_rootimage (MonoImage *rootimage, MonoImage* image, MonoTypeNameParse *info, gboolean ignorecase, gboolean *type_resolve)
7603 {
7604         MonoType *type;
7605         MonoReflectionAssembly *assembly;
7606         GString *fullName;
7607         GList *mod;
7608
7609         if (image && image->dynamic)
7610                 type = mono_reflection_get_type_internal_dynamic (rootimage, image->assembly, info, ignorecase);
7611         else
7612                 type = mono_reflection_get_type_internal (rootimage, image, info, ignorecase);
7613         if (type)
7614                 return type;
7615         if (!mono_domain_has_type_resolve (mono_domain_get ()))
7616                 return NULL;
7617
7618         if (type_resolve) {
7619                 if (*type_resolve) 
7620                         return NULL;
7621                 else
7622                         *type_resolve = TRUE;
7623         }
7624         
7625         /* Reconstruct the type name */
7626         fullName = g_string_new ("");
7627         if (info->name_space && (info->name_space [0] != '\0'))
7628                 g_string_printf (fullName, "%s.%s", info->name_space, info->name);
7629         else
7630                 g_string_printf (fullName, "%s", info->name);
7631         for (mod = info->nested; mod; mod = mod->next)
7632                 g_string_append_printf (fullName, "+%s", (char*)mod->data);
7633
7634         assembly = mono_domain_try_type_resolve ( mono_domain_get (), fullName->str, NULL);
7635         if (assembly) {
7636                 if (assembly->assembly->dynamic)
7637                         type = mono_reflection_get_type_internal_dynamic (rootimage, assembly->assembly, info, ignorecase);
7638                 else
7639                         type = mono_reflection_get_type_internal (rootimage, assembly->assembly->image, 
7640                                                                                                           info, ignorecase);
7641         }
7642         g_string_free (fullName, TRUE);
7643         return type;
7644 }
7645
7646 void
7647 mono_reflection_free_type_info (MonoTypeNameParse *info)
7648 {
7649         g_list_free (info->modifiers);
7650         g_list_free (info->nested);
7651
7652         if (info->type_arguments) {
7653                 int i;
7654
7655                 for (i = 0; i < info->type_arguments->len; i++) {
7656                         MonoTypeNameParse *subinfo = g_ptr_array_index (info->type_arguments, i);
7657
7658                         mono_reflection_free_type_info (subinfo);
7659                         /*We free the subinfo since it is allocated by _mono_reflection_parse_type*/
7660                         g_free (subinfo);
7661                 }
7662
7663                 g_ptr_array_free (info->type_arguments, TRUE);
7664         }
7665 }
7666
7667 /*
7668  * mono_reflection_type_from_name:
7669  * @name: type name.
7670  * @image: a metadata context (can be NULL).
7671  *
7672  * Retrieves a MonoType from its @name. If the name is not fully qualified,
7673  * it defaults to get the type from @image or, if @image is NULL or loading
7674  * from it fails, uses corlib.
7675  * 
7676  */
7677 MonoType*
7678 mono_reflection_type_from_name (char *name, MonoImage *image)
7679 {
7680         MonoType *type = NULL;
7681         MonoTypeNameParse info;
7682         char *tmp;
7683
7684         /* Make a copy since parse_type modifies its argument */
7685         tmp = g_strdup (name);
7686         
7687         /*g_print ("requested type %s\n", str);*/
7688         if (mono_reflection_parse_type (tmp, &info)) {
7689                 type = _mono_reflection_get_type_from_info (&info, image, FALSE);
7690         }
7691
7692         g_free (tmp);
7693         mono_reflection_free_type_info (&info);
7694         return type;
7695 }
7696
7697 /*
7698  * mono_reflection_get_token:
7699  *
7700  *   Return the metadata token of OBJ which should be an object
7701  * representing a metadata element.
7702  */
7703 guint32
7704 mono_reflection_get_token (MonoObject *obj)
7705 {
7706         MonoClass *klass;
7707         guint32 token = 0;
7708
7709         klass = obj->vtable->klass;
7710
7711         if (strcmp (klass->name, "MethodBuilder") == 0) {
7712                 MonoReflectionMethodBuilder *mb = (MonoReflectionMethodBuilder *)obj;
7713
7714                 token = mb->table_idx | MONO_TOKEN_METHOD_DEF;
7715         } else if (strcmp (klass->name, "ConstructorBuilder") == 0) {
7716                 MonoReflectionCtorBuilder *mb = (MonoReflectionCtorBuilder *)obj;
7717
7718                 token = mb->table_idx | MONO_TOKEN_METHOD_DEF;
7719         } else if (strcmp (klass->name, "FieldBuilder") == 0) {
7720                 MonoReflectionFieldBuilder *fb = (MonoReflectionFieldBuilder *)obj;
7721
7722                 token = fb->table_idx | MONO_TOKEN_FIELD_DEF;
7723         } else if (strcmp (klass->name, "TypeBuilder") == 0) {
7724                 MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder *)obj;
7725                 token = tb->table_idx | MONO_TOKEN_TYPE_DEF;
7726         } else if (strcmp (klass->name, "MonoType") == 0) {
7727                 MonoType *type = mono_reflection_type_get_handle ((MonoReflectionType*)obj);
7728                 MonoClass *mc = mono_class_from_mono_type (type);
7729                 if (!mono_class_init (mc))
7730                         mono_raise_exception (mono_class_get_exception_for_failure (mc));
7731
7732                 token = mc->type_token;
7733         } else if (strcmp (klass->name, "MonoCMethod") == 0 ||
7734                    strcmp (klass->name, "MonoMethod") == 0 ||
7735                    strcmp (klass->name, "MonoGenericMethod") == 0 ||
7736                    strcmp (klass->name, "MonoGenericCMethod") == 0) {
7737                 MonoReflectionMethod *m = (MonoReflectionMethod *)obj;
7738                 if (m->method->is_inflated) {
7739                         MonoMethodInflated *inflated = (MonoMethodInflated *) m->method;
7740                         return inflated->declaring->token;
7741                 } else {
7742                         token = m->method->token;
7743                 }
7744         } else if (strcmp (klass->name, "MonoField") == 0) {
7745                 MonoReflectionField *f = (MonoReflectionField*)obj;
7746
7747                 if (is_field_on_inst (f->field)) {
7748                         MonoDynamicGenericClass *dgclass = (MonoDynamicGenericClass*)f->field->parent->generic_class;
7749                         int field_index = f->field - dgclass->fields;
7750                         MonoObject *obj;
7751
7752                         g_assert (field_index >= 0 && field_index < dgclass->count_fields);
7753                         obj = dgclass->field_objects [field_index];
7754                         return mono_reflection_get_token (obj);
7755                 }
7756                 token = mono_class_get_field_token (f->field);
7757         } else if (strcmp (klass->name, "MonoProperty") == 0) {
7758                 MonoReflectionProperty *p = (MonoReflectionProperty*)obj;
7759
7760                 token = mono_class_get_property_token (p->property);
7761         } else if (strcmp (klass->name, "MonoEvent") == 0) {
7762                 MonoReflectionMonoEvent *p = (MonoReflectionMonoEvent*)obj;
7763
7764                 token = mono_class_get_event_token (p->event);
7765         } else if (strcmp (klass->name, "ParameterInfo") == 0 || strcmp (klass->name, "MonoParameterInfo") == 0) {
7766                 MonoReflectionParameter *p = (MonoReflectionParameter*)obj;
7767                 MonoClass *member_class = mono_object_class (p->MemberImpl);
7768                 g_assert (mono_class_is_reflection_method_or_constructor (member_class));
7769
7770                 token = mono_method_get_param_token (((MonoReflectionMethod*)p->MemberImpl)->method, p->PositionImpl);
7771         } else if (strcmp (klass->name, "Module") == 0 || strcmp (klass->name, "MonoModule") == 0) {
7772                 MonoReflectionModule *m = (MonoReflectionModule*)obj;
7773
7774                 token = m->token;
7775         } else if (strcmp (klass->name, "Assembly") == 0 || strcmp (klass->name, "MonoAssembly") == 0) {
7776                 token = mono_metadata_make_token (MONO_TABLE_ASSEMBLY, 1);
7777         } else {
7778                 gchar *msg = g_strdup_printf ("MetadataToken is not supported for type '%s.%s'", klass->name_space, klass->name);
7779                 MonoException *ex = mono_get_exception_not_implemented (msg);
7780                 g_free (msg);
7781                 mono_raise_exception (ex);
7782         }
7783
7784         return token;
7785 }
7786
7787 static MonoClass*
7788 load_cattr_enum_type (MonoImage *image, const char *p, const char **end)
7789 {
7790         char *n;
7791         MonoType *t;
7792         int slen = mono_metadata_decode_value (p, &p);
7793         n = g_memdup (p, slen + 1);
7794         n [slen] = 0;
7795         t = mono_reflection_type_from_name (n, image);
7796         if (!t)
7797                 g_error ("Cannot load type '%s'", n);
7798         g_free (n);
7799         p += slen;
7800         *end = p;
7801         return mono_class_from_mono_type (t);
7802 }
7803
7804 static void*
7805 load_cattr_value (MonoImage *image, MonoType *t, const char *p, const char **end)
7806 {
7807         int slen, type = t->type;
7808         MonoClass *tklass = t->data.klass;
7809
7810 handle_enum:
7811         switch (type) {
7812         case MONO_TYPE_U1:
7813         case MONO_TYPE_I1:
7814         case MONO_TYPE_BOOLEAN: {
7815                 MonoBoolean *bval = g_malloc (sizeof (MonoBoolean));
7816                 *bval = *p;
7817                 *end = p + 1;
7818                 return bval;
7819         }
7820         case MONO_TYPE_CHAR:
7821         case MONO_TYPE_U2:
7822         case MONO_TYPE_I2: {
7823                 guint16 *val = g_malloc (sizeof (guint16));
7824                 *val = read16 (p);
7825                 *end = p + 2;
7826                 return val;
7827         }
7828 #if SIZEOF_VOID_P == 4
7829         case MONO_TYPE_U:
7830         case MONO_TYPE_I:
7831 #endif
7832         case MONO_TYPE_R4:
7833         case MONO_TYPE_U4:
7834         case MONO_TYPE_I4: {
7835                 guint32 *val = g_malloc (sizeof (guint32));
7836                 *val = read32 (p);
7837                 *end = p + 4;
7838                 return val;
7839         }
7840 #if SIZEOF_VOID_P == 8
7841         case MONO_TYPE_U: /* error out instead? this should probably not happen */
7842         case MONO_TYPE_I:
7843 #endif
7844         case MONO_TYPE_U8:
7845         case MONO_TYPE_I8: {
7846                 guint64 *val = g_malloc (sizeof (guint64));
7847                 *val = read64 (p);
7848                 *end = p + 8;
7849                 return val;
7850         }
7851         case MONO_TYPE_R8: {
7852                 double *val = g_malloc (sizeof (double));
7853                 readr8 (p, val);
7854                 *end = p + 8;
7855                 return val;
7856         }
7857         case MONO_TYPE_VALUETYPE:
7858                 if (t->data.klass->enumtype) {
7859                         type = mono_class_enum_basetype (t->data.klass)->type;
7860                         goto handle_enum;
7861                 } else {
7862                         MonoClass *k =  t->data.klass;
7863                         
7864                         if (mono_is_corlib_image (k->image) && strcmp (k->name_space, "System") == 0 && strcmp (k->name, "DateTime") == 0){
7865                                 guint64 *val = g_malloc (sizeof (guint64));
7866                                 *val = read64 (p);
7867                                 *end = p + 8;
7868                                 return val;
7869                         }
7870                 }
7871                 g_error ("generic valutype %s not handled in custom attr value decoding", t->data.klass->name);
7872                 break;
7873                 
7874         case MONO_TYPE_STRING:
7875                 if (*p == (char)0xFF) {
7876                         *end = p + 1;
7877                         return NULL;
7878                 }
7879                 slen = mono_metadata_decode_value (p, &p);
7880                 *end = p + slen;
7881                 return mono_string_new_len (mono_domain_get (), p, slen);
7882         case MONO_TYPE_CLASS: {
7883                 char *n;
7884                 MonoType *t;
7885                 if (*p == (char)0xFF) {
7886                         *end = p + 1;
7887                         return NULL;
7888                 }
7889 handle_type:
7890                 slen = mono_metadata_decode_value (p, &p);
7891                 n = g_memdup (p, slen + 1);
7892                 n [slen] = 0;
7893                 t = mono_reflection_type_from_name (n, image);
7894                 if (!t)
7895                         g_warning ("Cannot load type '%s'", n);
7896                 g_free (n);
7897                 *end = p + slen;
7898                 if (t)
7899                         return mono_type_get_object (mono_domain_get (), t);
7900                 else
7901                         return NULL;
7902         }
7903         case MONO_TYPE_OBJECT: {
7904                 char subt = *p++;
7905                 MonoObject *obj;
7906                 MonoClass *subc = NULL;
7907                 void *val;
7908
7909                 if (subt == 0x50) {
7910                         goto handle_type;
7911                 } else if (subt == 0x0E) {
7912                         type = MONO_TYPE_STRING;
7913                         goto handle_enum;
7914                 } else if (subt == 0x1D) {
7915                         MonoType simple_type = {{0}};
7916                         int etype = *p;
7917                         p ++;
7918
7919                         type = MONO_TYPE_SZARRAY;
7920                         if (etype == 0x50) {
7921                                 tklass = mono_defaults.systemtype_class;
7922                         } else if (etype == 0x55) {
7923                                 tklass = load_cattr_enum_type (image, p, &p);
7924                         } else {
7925                                 if (etype == 0x51)
7926                                         /* See Partition II, Appendix B3 */
7927                                         etype = MONO_TYPE_OBJECT;
7928                                 simple_type.type = etype;
7929                                 tklass = mono_class_from_mono_type (&simple_type);
7930                         }
7931                         goto handle_enum;
7932                 } else if (subt == 0x55) {
7933                         char *n;
7934                         MonoType *t;
7935                         slen = mono_metadata_decode_value (p, &p);
7936                         n = g_memdup (p, slen + 1);
7937                         n [slen] = 0;
7938                         t = mono_reflection_type_from_name (n, image);
7939                         if (!t)
7940                                 g_error ("Cannot load type '%s'", n);
7941                         g_free (n);
7942                         p += slen;
7943                         subc = mono_class_from_mono_type (t);
7944                 } else if (subt >= MONO_TYPE_BOOLEAN && subt <= MONO_TYPE_R8) {
7945                         MonoType simple_type = {{0}};
7946                         simple_type.type = subt;
7947                         subc = mono_class_from_mono_type (&simple_type);
7948                 } else {
7949                         g_error ("Unknown type 0x%02x for object type encoding in custom attr", subt);
7950                 }
7951                 val = load_cattr_value (image, &subc->byval_arg, p, end);
7952                 obj = mono_object_new (mono_domain_get (), subc);
7953                 g_assert (!subc->has_references);
7954                 mono_gc_memmove ((char*)obj + sizeof (MonoObject), val, mono_class_value_size (subc, NULL));
7955                 g_free (val);
7956                 return obj;
7957         }
7958         case MONO_TYPE_SZARRAY: {
7959                 MonoArray *arr;
7960                 guint32 i, alen, basetype;
7961                 alen = read32 (p);
7962                 p += 4;
7963                 if (alen == 0xffffffff) {
7964                         *end = p;
7965                         return NULL;
7966                 }
7967                 arr = mono_array_new (mono_domain_get(), tklass, alen);
7968                 basetype = tklass->byval_arg.type;
7969                 if (basetype == MONO_TYPE_VALUETYPE && tklass->enumtype)
7970                         basetype = mono_class_enum_basetype (tklass)->type;
7971                 switch (basetype)
7972                 {
7973                         case MONO_TYPE_U1:
7974                         case MONO_TYPE_I1:
7975                         case MONO_TYPE_BOOLEAN:
7976                                 for (i = 0; i < alen; i++) {
7977                                         MonoBoolean val = *p++;
7978                                         mono_array_set (arr, MonoBoolean, i, val);
7979                                 }
7980                                 break;
7981                         case MONO_TYPE_CHAR:
7982                         case MONO_TYPE_U2:
7983                         case MONO_TYPE_I2:
7984                                 for (i = 0; i < alen; i++) {
7985                                         guint16 val = read16 (p);
7986                                         mono_array_set (arr, guint16, i, val);
7987                                         p += 2;
7988                                 }
7989                                 break;
7990                         case MONO_TYPE_R4:
7991                         case MONO_TYPE_U4:
7992                         case MONO_TYPE_I4:
7993                                 for (i = 0; i < alen; i++) {
7994                                         guint32 val = read32 (p);
7995                                         mono_array_set (arr, guint32, i, val);
7996                                         p += 4;
7997                                 }
7998                                 break;
7999                         case MONO_TYPE_R8:
8000                                 for (i = 0; i < alen; i++) {
8001                                         double val;
8002                                         readr8 (p, &val);
8003                                         mono_array_set (arr, double, i, val);
8004                                         p += 8;
8005                                 }
8006                                 break;
8007                         case MONO_TYPE_U8:
8008                         case MONO_TYPE_I8:
8009                                 for (i = 0; i < alen; i++) {
8010                                         guint64 val = read64 (p);
8011                                         mono_array_set (arr, guint64, i, val);
8012                                         p += 8;
8013                                 }
8014                                 break;
8015                         case MONO_TYPE_CLASS:
8016                         case MONO_TYPE_OBJECT:
8017                         case MONO_TYPE_STRING:
8018                                 for (i = 0; i < alen; i++) {
8019                                         MonoObject *item = load_cattr_value (image, &tklass->byval_arg, p, &p);
8020                                         mono_array_setref (arr, i, item);
8021                                 }
8022                                 break;
8023                         default:
8024                                 g_error ("Type 0x%02x not handled in custom attr array decoding", basetype);
8025                 }
8026                 *end=p;
8027                 return arr;
8028         }
8029         default:
8030                 g_error ("Type 0x%02x not handled in custom attr value decoding", type);
8031         }
8032         return NULL;
8033 }
8034
8035 static MonoObject*
8036 create_cattr_typed_arg (MonoType *t, MonoObject *val)
8037 {
8038         static MonoClass *klass;
8039         static MonoMethod *ctor;
8040         MonoObject *retval;
8041         void *params [2], *unboxed;
8042
8043         if (!klass)
8044                 klass = mono_class_from_name (mono_defaults.corlib, "System.Reflection", "CustomAttributeTypedArgument");
8045         if (!ctor)
8046                 ctor = mono_class_get_method_from_name (klass, ".ctor", 2);
8047         
8048         params [0] = mono_type_get_object (mono_domain_get (), t);
8049         params [1] = val;
8050         retval = mono_object_new (mono_domain_get (), klass);
8051         unboxed = mono_object_unbox (retval);
8052         mono_runtime_invoke (ctor, unboxed, params, NULL);
8053
8054         return retval;
8055 }
8056
8057 static MonoObject*
8058 create_cattr_named_arg (void *minfo, MonoObject *typedarg)
8059 {
8060         static MonoClass *klass;
8061         static MonoMethod *ctor;
8062         MonoObject *retval;
8063         void *unboxed, *params [2];
8064
8065         if (!klass)
8066                 klass = mono_class_from_name (mono_defaults.corlib, "System.Reflection", "CustomAttributeNamedArgument");
8067         if (!ctor)
8068                 ctor = mono_class_get_method_from_name (klass, ".ctor", 2);
8069
8070         params [0] = minfo;
8071         params [1] = typedarg;
8072         retval = mono_object_new (mono_domain_get (), klass);
8073         unboxed = mono_object_unbox (retval);
8074         mono_runtime_invoke (ctor, unboxed, params, NULL);
8075
8076         return retval;
8077 }
8078
8079 static gboolean
8080 type_is_reference (MonoType *type)
8081 {
8082         switch (type->type) {
8083         case MONO_TYPE_BOOLEAN:
8084         case MONO_TYPE_CHAR:
8085         case MONO_TYPE_U:
8086         case MONO_TYPE_I:
8087         case MONO_TYPE_U1:
8088         case MONO_TYPE_I1:
8089         case MONO_TYPE_U2:
8090         case MONO_TYPE_I2:
8091         case MONO_TYPE_U4:
8092         case MONO_TYPE_I4:
8093         case MONO_TYPE_U8:
8094         case MONO_TYPE_I8:
8095         case MONO_TYPE_R8:
8096         case MONO_TYPE_R4:
8097         case MONO_TYPE_VALUETYPE:
8098                 return FALSE;
8099         default:
8100                 return TRUE;
8101         }
8102 }
8103
8104 static void
8105 free_param_data (MonoMethodSignature *sig, void **params) {
8106         int i;
8107         for (i = 0; i < sig->param_count; ++i) {
8108                 if (!type_is_reference (sig->params [i]))
8109                         g_free (params [i]);
8110         }
8111 }
8112
8113 /*
8114  * Find the field index in the metadata FieldDef table.
8115  */
8116 static guint32
8117 find_field_index (MonoClass *klass, MonoClassField *field) {
8118         int i;
8119
8120         for (i = 0; i < klass->field.count; ++i) {
8121                 if (field == &klass->fields [i])
8122                         return klass->field.first + 1 + i;
8123         }
8124         return 0;
8125 }
8126
8127 /*
8128  * Find the property index in the metadata Property table.
8129  */
8130 static guint32
8131 find_property_index (MonoClass *klass, MonoProperty *property) {
8132         int i;
8133
8134         for (i = 0; i < klass->ext->property.count; ++i) {
8135                 if (property == &klass->ext->properties [i])
8136                         return klass->ext->property.first + 1 + i;
8137         }
8138         return 0;
8139 }
8140
8141 /*
8142  * Find the event index in the metadata Event table.
8143  */
8144 static guint32
8145 find_event_index (MonoClass *klass, MonoEvent *event) {
8146         int i;
8147
8148         for (i = 0; i < klass->ext->event.count; ++i) {
8149                 if (event == &klass->ext->events [i])
8150                         return klass->ext->event.first + 1 + i;
8151         }
8152         return 0;
8153 }
8154
8155 static MonoObject*
8156 create_custom_attr (MonoImage *image, MonoMethod *method, const guchar *data, guint32 len, MonoError *error)
8157 {
8158         const char *p = (const char*)data;
8159         const char *named;
8160         guint32 i, j, num_named;
8161         MonoObject *attr;
8162         void *params_buf [32];
8163         void **params;
8164         MonoMethodSignature *sig;
8165
8166         mono_error_init (error);
8167
8168         mono_class_init (method->klass);
8169
8170         if (!mono_verifier_verify_cattr_content (image, method, data, len, NULL)) {
8171                 mono_error_set_generic_error (error, "System.Reflection", "CustomAttributeFormatException", "Binary format of the specified custom attribute was invalid.");
8172                 return NULL;
8173         }
8174
8175         if (len == 0) {
8176                 attr = mono_object_new (mono_domain_get (), method->klass);
8177                 mono_runtime_invoke (method, attr, NULL, NULL);
8178                 return attr;
8179         }
8180
8181         if (len < 2 || read16 (p) != 0x0001) /* Prolog */
8182                 return NULL;
8183
8184         /*g_print ("got attr %s\n", method->klass->name);*/
8185
8186         sig = mono_method_signature (method);
8187         if (sig->param_count < 32)
8188                 params = params_buf;
8189         else
8190                 /* Allocate using GC so it gets GC tracking */
8191                 params = mono_gc_alloc_fixed (sig->param_count * sizeof (void*), NULL);
8192
8193         /* skip prolog */
8194         p += 2;
8195         for (i = 0; i < mono_method_signature (method)->param_count; ++i) {
8196                 params [i] = load_cattr_value (image, mono_method_signature (method)->params [i], p, &p);
8197         }
8198
8199         named = p;
8200         attr = mono_object_new (mono_domain_get (), method->klass);
8201         mono_runtime_invoke (method, attr, params, NULL);
8202         free_param_data (method->signature, params);
8203         num_named = read16 (named);
8204         named += 2;
8205         for (j = 0; j < num_named; j++) {
8206                 gint name_len;
8207                 char *name, named_type, data_type;
8208                 named_type = *named++;
8209                 data_type = *named++; /* type of data */
8210                 if (data_type == MONO_TYPE_SZARRAY)
8211                         data_type = *named++;
8212                 if (data_type == MONO_TYPE_ENUM) {
8213                         gint type_len;
8214                         char *type_name;
8215                         type_len = mono_metadata_decode_blob_size (named, &named);
8216                         type_name = g_malloc (type_len + 1);
8217                         memcpy (type_name, named, type_len);
8218                         type_name [type_len] = 0;
8219                         named += type_len;
8220                         /* FIXME: lookup the type and check type consistency */
8221                         g_free (type_name);
8222                 }
8223                 name_len = mono_metadata_decode_blob_size (named, &named);
8224                 name = g_malloc (name_len + 1);
8225                 memcpy (name, named, name_len);
8226                 name [name_len] = 0;
8227                 named += name_len;
8228                 if (named_type == 0x53) {
8229                         MonoClassField *field = mono_class_get_field_from_name (mono_object_class (attr), name);
8230                         void *val = load_cattr_value (image, field->type, named, &named);
8231                         mono_field_set_value (attr, field, val);
8232                         if (!type_is_reference (field->type))
8233                                 g_free (val);
8234                 } else if (named_type == 0x54) {
8235                         MonoProperty *prop;
8236                         void *pparams [1];
8237                         MonoType *prop_type;
8238
8239                         prop = mono_class_get_property_from_name (mono_object_class (attr), name);
8240                         /* can we have more that 1 arg in a custom attr named property? */
8241                         prop_type = prop->get? mono_method_signature (prop->get)->ret :
8242                              mono_method_signature (prop->set)->params [mono_method_signature (prop->set)->param_count - 1];
8243                         pparams [0] = load_cattr_value (image, prop_type, named, &named);
8244                         mono_property_set_value (prop, attr, pparams, NULL);
8245                         if (!type_is_reference (prop_type))
8246                                 g_free (pparams [0]);
8247                 }
8248                 g_free (name);
8249         }
8250
8251         if (params != params_buf)
8252                 mono_gc_free_fixed (params);
8253
8254         return attr;
8255 }
8256         
8257 /*
8258  * mono_reflection_create_custom_attr_data_args:
8259  *
8260  *   Create an array of typed and named arguments from the cattr blob given by DATA.
8261  * TYPED_ARGS and NAMED_ARGS will contain the objects representing the arguments,
8262  * NAMED_ARG_INFO will contain information about the named arguments.
8263  */
8264 void
8265 mono_reflection_create_custom_attr_data_args (MonoImage *image, MonoMethod *method, const guchar *data, guint32 len, MonoArray **typed_args, MonoArray **named_args, CattrNamedArg **named_arg_info, MonoError *error)
8266 {
8267         MonoArray *typedargs, *namedargs;
8268         MonoClass *attrklass;
8269         MonoDomain *domain;
8270         const char *p = (const char*)data;
8271         const char *named;
8272         guint32 i, j, num_named;
8273         CattrNamedArg *arginfo = NULL;
8274
8275         *typed_args = NULL;
8276         *named_args = NULL;
8277         *named_arg_info = NULL;
8278
8279         mono_error_init (error);
8280
8281         if (!mono_verifier_verify_cattr_content (image, method, data, len, NULL)) {
8282                 mono_error_set_generic_error (error, "System.Reflection", "CustomAttributeFormatException", "Binary format of the specified custom attribute was invalid.");
8283                 return;
8284         }
8285
8286         mono_class_init (method->klass);
8287         
8288         domain = mono_domain_get ();
8289
8290         if (len < 2 || read16 (p) != 0x0001) /* Prolog */
8291                 return;
8292
8293         typedargs = mono_array_new (domain, mono_get_object_class (), mono_method_signature (method)->param_count);
8294         
8295         /* skip prolog */
8296         p += 2;
8297         for (i = 0; i < mono_method_signature (method)->param_count; ++i) {
8298                 MonoObject *obj;
8299                 void *val;
8300
8301                 val = load_cattr_value (image, mono_method_signature (method)->params [i], p, &p);
8302                 obj = type_is_reference (mono_method_signature (method)->params [i]) ? 
8303                         val : mono_value_box (domain, mono_class_from_mono_type (mono_method_signature (method)->params [i]), val);
8304                 mono_array_setref (typedargs, i, obj);
8305
8306                 if (!type_is_reference (mono_method_signature (method)->params [i]))
8307                         g_free (val);
8308         }
8309
8310         named = p;
8311         num_named = read16 (named);
8312         namedargs = mono_array_new (domain, mono_get_object_class (), num_named);
8313         named += 2;
8314         attrklass = method->klass;
8315
8316         arginfo = g_new0 (CattrNamedArg, num_named);
8317         *named_arg_info = arginfo;
8318
8319         for (j = 0; j < num_named; j++) {
8320                 gint name_len;
8321                 char *name, named_type, data_type;
8322                 named_type = *named++;
8323                 data_type = *named++; /* type of data */
8324                 if (data_type == MONO_TYPE_SZARRAY)
8325                         data_type = *named++;
8326                 if (data_type == MONO_TYPE_ENUM) {
8327                         gint type_len;
8328                         char *type_name;
8329                         type_len = mono_metadata_decode_blob_size (named, &named);
8330                         if (ADDP_IS_GREATER_OR_OVF ((const guchar*)named, type_len, data + len))
8331                                 goto fail;
8332
8333                         type_name = g_malloc (type_len + 1);
8334                         memcpy (type_name, named, type_len);
8335                         type_name [type_len] = 0;
8336                         named += type_len;
8337                         /* FIXME: lookup the type and check type consistency */
8338                         g_free (type_name);
8339                 }
8340                 name_len = mono_metadata_decode_blob_size (named, &named);
8341                 if (ADDP_IS_GREATER_OR_OVF ((const guchar*)named, name_len, data + len))
8342                         goto fail;
8343                 name = g_malloc (name_len + 1);
8344                 memcpy (name, named, name_len);
8345                 name [name_len] = 0;
8346                 named += name_len;
8347                 if (named_type == 0x53) {
8348                         MonoObject *obj;
8349                         MonoClassField *field = mono_class_get_field_from_name (attrklass, name);
8350                         void *val;
8351
8352                         arginfo [j].type = field->type;
8353                         arginfo [j].field = field;
8354
8355                         val = load_cattr_value (image, field->type, named, &named);
8356                         obj = type_is_reference (field->type) ? val : mono_value_box (domain, mono_class_from_mono_type (field->type), val);
8357                         mono_array_setref (namedargs, j, obj);
8358                         if (!type_is_reference (field->type))
8359                                 g_free (val);
8360                 } else if (named_type == 0x54) {
8361                         MonoObject *obj;
8362                         MonoType *prop_type;
8363                         MonoProperty *prop = mono_class_get_property_from_name (attrklass, name);
8364                         void *val;
8365
8366                         prop_type = prop->get? mono_method_signature (prop->get)->ret :
8367                              mono_method_signature (prop->set)->params [mono_method_signature (prop->set)->param_count - 1];
8368
8369                         arginfo [j].type = prop_type;
8370                         arginfo [j].prop = prop;
8371
8372                         val = load_cattr_value (image, prop_type, named, &named);
8373                         obj = type_is_reference (prop_type) ? val : mono_value_box (domain, mono_class_from_mono_type (prop_type), val);
8374                         mono_array_setref (namedargs, j, obj);
8375                         if (!type_is_reference (prop_type))
8376                                 g_free (val);
8377                 }
8378                 g_free (name);
8379         }
8380
8381         *typed_args = typedargs;
8382         *named_args = namedargs;
8383         return;
8384 fail:
8385         mono_error_set_generic_error (error, "System.Reflection", "CustomAttributeFormatException", "Binary format of the specified custom attribute was invalid.");
8386         g_free (arginfo);
8387         *named_arg_info = NULL;
8388 }
8389
8390 void
8391 mono_reflection_resolve_custom_attribute_data (MonoReflectionMethod *ref_method, MonoReflectionAssembly *assembly, gpointer data, guint32 len, MonoArray **ctor_args, MonoArray **named_args)
8392 {
8393         MonoDomain *domain;
8394         MonoArray *typedargs, *namedargs;
8395         MonoImage *image;
8396         MonoMethod *method;
8397         CattrNamedArg *arginfo = NULL;
8398         MonoError error;
8399         int i;
8400
8401         *ctor_args = NULL;
8402         *named_args = NULL;
8403
8404         if (len == 0)
8405                 return;
8406
8407         image = assembly->assembly->image;
8408         method = ref_method->method;
8409         domain = mono_object_domain (ref_method);
8410
8411         if (!mono_class_init (method->klass))
8412                 mono_raise_exception (mono_class_get_exception_for_failure (method->klass));
8413
8414         mono_reflection_create_custom_attr_data_args (image, method, data, len, &typedargs, &namedargs, &arginfo, &error);
8415         if (!mono_error_ok (&error))
8416                 mono_error_raise_exception (&error);
8417         if (mono_loader_get_last_error ())
8418                 mono_raise_exception (mono_loader_error_prepare_exception (mono_loader_get_last_error ()));
8419
8420         if (!typedargs || !namedargs) {
8421                 g_free (arginfo);
8422                 return;
8423         }
8424
8425         for (i = 0; i < mono_method_signature (method)->param_count; ++i) {
8426                 MonoObject *obj = mono_array_get (typedargs, MonoObject*, i);
8427                 MonoObject *typedarg;
8428
8429                 typedarg = create_cattr_typed_arg (mono_method_signature (method)->params [i], obj);
8430                 mono_array_setref (typedargs, i, typedarg);
8431         }
8432
8433         for (i = 0; i < mono_array_length (namedargs); ++i) {
8434                 MonoObject *obj = mono_array_get (namedargs, MonoObject*, i);
8435                 MonoObject *typedarg, *namedarg, *minfo;
8436
8437                 if (arginfo [i].prop)
8438                         minfo = (MonoObject*)mono_property_get_object (domain, NULL, arginfo [i].prop);
8439                 else
8440                         minfo = (MonoObject*)mono_field_get_object (domain, NULL, arginfo [i].field);
8441
8442                 typedarg = create_cattr_typed_arg (arginfo [i].type, obj);
8443                 namedarg = create_cattr_named_arg (minfo, typedarg);
8444
8445                 mono_array_setref (namedargs, i, namedarg);
8446         }
8447
8448         *ctor_args = typedargs;
8449         *named_args = namedargs;
8450         g_free (arginfo);
8451 }
8452
8453 static MonoObject*
8454 create_custom_attr_data (MonoImage *image, MonoCustomAttrEntry *cattr)
8455 {
8456         static MonoMethod *ctor;
8457         MonoDomain *domain;
8458         MonoObject *attr;
8459         void *params [4];
8460
8461         g_assert (image->assembly);
8462
8463         if (!ctor)
8464                 ctor = mono_class_get_method_from_name (mono_defaults.customattribute_data_class, ".ctor", 4);
8465
8466         domain = mono_domain_get ();
8467         attr = mono_object_new (domain, mono_defaults.customattribute_data_class);
8468         params [0] = mono_method_get_object (domain, cattr->ctor, NULL);
8469         params [1] = mono_assembly_get_object (domain, image->assembly);
8470         params [2] = (gpointer)&cattr->data;
8471         params [3] = &cattr->data_size;
8472         mono_runtime_invoke (ctor, attr, params, NULL);
8473         return attr;
8474 }
8475
8476 static MonoArray*
8477 mono_custom_attrs_construct_by_type (MonoCustomAttrInfo *cinfo, MonoClass *attr_klass, MonoError *error)
8478 {
8479         MonoArray *result;
8480         MonoObject *attr;
8481         int i, n;
8482
8483         mono_error_init (error);
8484
8485         n = 0;
8486         for (i = 0; i < cinfo->num_attrs; ++i) {
8487                 if (!attr_klass || mono_class_is_assignable_from (attr_klass, cinfo->attrs [i].ctor->klass))
8488                         n ++;
8489         }
8490
8491         result = mono_array_new_cached (mono_domain_get (), mono_defaults.attribute_class, n);
8492         n = 0;
8493         for (i = 0; i < cinfo->num_attrs; ++i) {
8494                 if (!cinfo->attrs [i].ctor)
8495                         /* The cattr type is not finished yet */
8496                         /* We should include the type name but cinfo doesn't contain it */
8497                         mono_raise_exception (mono_get_exception_type_load (NULL, NULL));
8498                 if (!attr_klass || mono_class_is_assignable_from (attr_klass, cinfo->attrs [i].ctor->klass)) {
8499                         attr = create_custom_attr (cinfo->image, cinfo->attrs [i].ctor, cinfo->attrs [i].data, cinfo->attrs [i].data_size, error);
8500                         if (!mono_error_ok (error))
8501                                 return result;
8502                         mono_array_setref (result, n, attr);
8503                         n ++;
8504                 }
8505         }
8506         return result;
8507 }
8508
8509 MonoArray*
8510 mono_custom_attrs_construct (MonoCustomAttrInfo *cinfo)
8511 {
8512         MonoError error;
8513
8514         return mono_custom_attrs_construct_by_type (cinfo, NULL, &error);
8515 }
8516
8517 static MonoArray*
8518 mono_custom_attrs_data_construct (MonoCustomAttrInfo *cinfo)
8519 {
8520         MonoArray *result;
8521         MonoObject *attr;
8522         int i;
8523         
8524         result = mono_array_new (mono_domain_get (), mono_defaults.customattribute_data_class, cinfo->num_attrs);
8525         for (i = 0; i < cinfo->num_attrs; ++i) {
8526                 attr = create_custom_attr_data (cinfo->image, &cinfo->attrs [i]);
8527                 mono_array_setref (result, i, attr);
8528         }
8529         return result;
8530 }
8531
8532 /**
8533  * mono_custom_attrs_from_index:
8534  *
8535  * Returns: NULL if no attributes are found or if a loading error occurs.
8536  */
8537 MonoCustomAttrInfo*
8538 mono_custom_attrs_from_index (MonoImage *image, guint32 idx)
8539 {
8540         guint32 mtoken, i, len;
8541         guint32 cols [MONO_CUSTOM_ATTR_SIZE];
8542         MonoTableInfo *ca;
8543         MonoCustomAttrInfo *ainfo;
8544         GList *tmp, *list = NULL;
8545         const char *data;
8546
8547         ca = &image->tables [MONO_TABLE_CUSTOMATTRIBUTE];
8548
8549         i = mono_metadata_custom_attrs_from_index (image, idx);
8550         if (!i)
8551                 return NULL;
8552         i --;
8553         while (i < ca->rows) {
8554                 if (mono_metadata_decode_row_col (ca, i, MONO_CUSTOM_ATTR_PARENT) != idx)
8555                         break;
8556                 list = g_list_prepend (list, GUINT_TO_POINTER (i));
8557                 ++i;
8558         }
8559         len = g_list_length (list);
8560         if (!len)
8561                 return NULL;
8562         ainfo = g_malloc0 (MONO_SIZEOF_CUSTOM_ATTR_INFO + sizeof (MonoCustomAttrEntry) * len);
8563         ainfo->num_attrs = len;
8564         ainfo->image = image;
8565         for (i = 0, tmp = list; i < len; ++i, tmp = tmp->next) {
8566                 mono_metadata_decode_row (ca, GPOINTER_TO_UINT (tmp->data), cols, MONO_CUSTOM_ATTR_SIZE);
8567                 mtoken = cols [MONO_CUSTOM_ATTR_TYPE] >> MONO_CUSTOM_ATTR_TYPE_BITS;
8568                 switch (cols [MONO_CUSTOM_ATTR_TYPE] & MONO_CUSTOM_ATTR_TYPE_MASK) {
8569                 case MONO_CUSTOM_ATTR_TYPE_METHODDEF:
8570                         mtoken |= MONO_TOKEN_METHOD_DEF;
8571                         break;
8572                 case MONO_CUSTOM_ATTR_TYPE_MEMBERREF:
8573                         mtoken |= MONO_TOKEN_MEMBER_REF;
8574                         break;
8575                 default:
8576                         g_error ("Unknown table for custom attr type %08x", cols [MONO_CUSTOM_ATTR_TYPE]);
8577                         break;
8578                 }
8579                 ainfo->attrs [i].ctor = mono_get_method (image, mtoken, NULL);
8580                 if (!ainfo->attrs [i].ctor) {
8581                         g_warning ("Can't find custom attr constructor image: %s mtoken: 0x%08x", image->name, mtoken);
8582                         g_list_free (list);
8583                         g_free (ainfo);
8584                         return NULL;
8585                 }
8586
8587                 if (!mono_verifier_verify_cattr_blob (image, cols [MONO_CUSTOM_ATTR_VALUE], NULL)) {
8588                         /*FIXME raising an exception here doesn't make any sense*/
8589                         g_warning ("Invalid custom attribute blob on image %s for index %x", image->name, idx);
8590                         g_list_free (list);
8591                         g_free (ainfo);
8592                         return NULL;
8593                 }
8594                 data = mono_metadata_blob_heap (image, cols [MONO_CUSTOM_ATTR_VALUE]);
8595                 ainfo->attrs [i].data_size = mono_metadata_decode_value (data, &data);
8596                 ainfo->attrs [i].data = (guchar*)data;
8597         }
8598         g_list_free (list);
8599
8600         return ainfo;
8601 }
8602
8603 MonoCustomAttrInfo*
8604 mono_custom_attrs_from_method (MonoMethod *method)
8605 {
8606         guint32 idx;
8607
8608         /*
8609          * An instantiated method has the same cattrs as the generic method definition.
8610          *
8611          * LAMESPEC: The .NET SRE throws an exception for instantiations of generic method builders
8612          *           Note that this stanza is not necessary for non-SRE types, but it's a micro-optimization
8613          */
8614         if (method->is_inflated)
8615                 method = ((MonoMethodInflated *) method)->declaring;
8616         
8617         if (method->dynamic || method->klass->image->dynamic)
8618                 return lookup_custom_attr (method->klass->image, method);
8619
8620         if (!method->token)
8621                 /* Synthetic methods */
8622                 return NULL;
8623
8624         idx = mono_method_get_index (method);
8625         idx <<= MONO_CUSTOM_ATTR_BITS;
8626         idx |= MONO_CUSTOM_ATTR_METHODDEF;
8627         return mono_custom_attrs_from_index (method->klass->image, idx);
8628 }
8629
8630 MonoCustomAttrInfo*
8631 mono_custom_attrs_from_class (MonoClass *klass)
8632 {
8633         guint32 idx;
8634
8635         if (klass->generic_class)
8636                 klass = klass->generic_class->container_class;
8637
8638         if (klass->image->dynamic)
8639                 return lookup_custom_attr (klass->image, klass);
8640
8641         if (klass->byval_arg.type == MONO_TYPE_VAR || klass->byval_arg.type == MONO_TYPE_MVAR) {
8642                 idx = mono_metadata_token_index (klass->sizes.generic_param_token);
8643                 idx <<= MONO_CUSTOM_ATTR_BITS;
8644                 idx |= MONO_CUSTOM_ATTR_GENERICPAR;
8645         } else {
8646                 idx = mono_metadata_token_index (klass->type_token);
8647                 idx <<= MONO_CUSTOM_ATTR_BITS;
8648                 idx |= MONO_CUSTOM_ATTR_TYPEDEF;
8649         }
8650         return mono_custom_attrs_from_index (klass->image, idx);
8651 }
8652
8653 MonoCustomAttrInfo*
8654 mono_custom_attrs_from_assembly (MonoAssembly *assembly)
8655 {
8656         guint32 idx;
8657         
8658         if (assembly->image->dynamic)
8659                 return lookup_custom_attr (assembly->image, assembly);
8660         idx = 1; /* there is only one assembly */
8661         idx <<= MONO_CUSTOM_ATTR_BITS;
8662         idx |= MONO_CUSTOM_ATTR_ASSEMBLY;
8663         return mono_custom_attrs_from_index (assembly->image, idx);
8664 }
8665
8666 static MonoCustomAttrInfo*
8667 mono_custom_attrs_from_module (MonoImage *image)
8668 {
8669         guint32 idx;
8670         
8671         if (image->dynamic)
8672                 return lookup_custom_attr (image, image);
8673         idx = 1; /* there is only one module */
8674         idx <<= MONO_CUSTOM_ATTR_BITS;
8675         idx |= MONO_CUSTOM_ATTR_MODULE;
8676         return mono_custom_attrs_from_index (image, idx);
8677 }
8678
8679 MonoCustomAttrInfo*
8680 mono_custom_attrs_from_property (MonoClass *klass, MonoProperty *property)
8681 {
8682         guint32 idx;
8683         
8684         if (klass->image->dynamic) {
8685                 property = mono_metadata_get_corresponding_property_from_generic_type_definition (property);
8686                 return lookup_custom_attr (klass->image, property);
8687         }
8688         idx = find_property_index (klass, property);
8689         idx <<= MONO_CUSTOM_ATTR_BITS;
8690         idx |= MONO_CUSTOM_ATTR_PROPERTY;
8691         return mono_custom_attrs_from_index (klass->image, idx);
8692 }
8693
8694 MonoCustomAttrInfo*
8695 mono_custom_attrs_from_event (MonoClass *klass, MonoEvent *event)
8696 {
8697         guint32 idx;
8698         
8699         if (klass->image->dynamic) {
8700                 event = mono_metadata_get_corresponding_event_from_generic_type_definition (event);
8701                 return lookup_custom_attr (klass->image, event);
8702         }
8703         idx = find_event_index (klass, event);
8704         idx <<= MONO_CUSTOM_ATTR_BITS;
8705         idx |= MONO_CUSTOM_ATTR_EVENT;
8706         return mono_custom_attrs_from_index (klass->image, idx);
8707 }
8708
8709 MonoCustomAttrInfo*
8710 mono_custom_attrs_from_field (MonoClass *klass, MonoClassField *field)
8711 {
8712         guint32 idx;
8713         if (klass->image->dynamic) {
8714                 field = mono_metadata_get_corresponding_field_from_generic_type_definition (field);
8715                 return lookup_custom_attr (klass->image, field);
8716         }
8717         idx = find_field_index (klass, field);
8718         idx <<= MONO_CUSTOM_ATTR_BITS;
8719         idx |= MONO_CUSTOM_ATTR_FIELDDEF;
8720         return mono_custom_attrs_from_index (klass->image, idx);
8721 }
8722
8723 /**
8724  * mono_custom_attrs_from_param:
8725  * @method: handle to the method that we want to retrieve custom parameter information from
8726  * @param: parameter number, where zero represent the return value, and one is the first parameter in the method
8727  *
8728  * The result must be released with mono_custom_attrs_free().
8729  *
8730  * Returns: the custom attribute object for the specified parameter, or NULL if there are none.
8731  */
8732 MonoCustomAttrInfo*
8733 mono_custom_attrs_from_param (MonoMethod *method, guint32 param)
8734 {
8735         MonoTableInfo *ca;
8736         guint32 i, idx, method_index;
8737         guint32 param_list, param_last, param_pos, found;
8738         MonoImage *image;
8739         MonoReflectionMethodAux *aux;
8740
8741         /*
8742          * An instantiated method has the same cattrs as the generic method definition.
8743          *
8744          * LAMESPEC: The .NET SRE throws an exception for instantiations of generic method builders
8745          *           Note that this stanza is not necessary for non-SRE types, but it's a micro-optimization
8746          */
8747         if (method->is_inflated)
8748                 method = ((MonoMethodInflated *) method)->declaring;
8749
8750         if (method->klass->image->dynamic) {
8751                 MonoCustomAttrInfo *res, *ainfo;
8752                 int size;
8753
8754                 aux = g_hash_table_lookup (((MonoDynamicImage*)method->klass->image)->method_aux_hash, method);
8755                 if (!aux || !aux->param_cattr)
8756                         return NULL;
8757
8758                 /* Need to copy since it will be freed later */
8759                 ainfo = aux->param_cattr [param];
8760                 if (!ainfo)
8761                         return NULL;
8762                 size = MONO_SIZEOF_CUSTOM_ATTR_INFO + sizeof (MonoCustomAttrEntry) * ainfo->num_attrs;
8763                 res = g_malloc0 (size);
8764                 memcpy (res, ainfo, size);
8765                 return res;
8766         }
8767
8768         image = method->klass->image;
8769         method_index = mono_method_get_index (method);
8770         if (!method_index)
8771                 return NULL;
8772         ca = &image->tables [MONO_TABLE_METHOD];
8773
8774         param_list = mono_metadata_decode_row_col (ca, method_index - 1, MONO_METHOD_PARAMLIST);
8775         if (method_index == ca->rows) {
8776                 ca = &image->tables [MONO_TABLE_PARAM];
8777                 param_last = ca->rows + 1;
8778         } else {
8779                 param_last = mono_metadata_decode_row_col (ca, method_index, MONO_METHOD_PARAMLIST);
8780                 ca = &image->tables [MONO_TABLE_PARAM];
8781         }
8782         found = FALSE;
8783         for (i = param_list; i < param_last; ++i) {
8784                 param_pos = mono_metadata_decode_row_col (ca, i - 1, MONO_PARAM_SEQUENCE);
8785                 if (param_pos == param) {
8786                         found = TRUE;
8787                         break;
8788                 }
8789         }
8790         if (!found)
8791                 return NULL;
8792         idx = i;
8793         idx <<= MONO_CUSTOM_ATTR_BITS;
8794         idx |= MONO_CUSTOM_ATTR_PARAMDEF;
8795         return mono_custom_attrs_from_index (image, idx);
8796 }
8797
8798 gboolean
8799 mono_custom_attrs_has_attr (MonoCustomAttrInfo *ainfo, MonoClass *attr_klass)
8800 {
8801         int i;
8802         MonoClass *klass;
8803         for (i = 0; i < ainfo->num_attrs; ++i) {
8804                 klass = ainfo->attrs [i].ctor->klass;
8805                 if (mono_class_has_parent (klass, attr_klass) || (MONO_CLASS_IS_INTERFACE (attr_klass) && mono_class_is_assignable_from (attr_klass, klass)))
8806                         return TRUE;
8807         }
8808         return FALSE;
8809 }
8810
8811 MonoObject*
8812 mono_custom_attrs_get_attr (MonoCustomAttrInfo *ainfo, MonoClass *attr_klass)
8813 {
8814         int i, attr_index;
8815         MonoClass *klass;
8816         MonoArray *attrs;
8817
8818         attr_index = -1;
8819         for (i = 0; i < ainfo->num_attrs; ++i) {
8820                 klass = ainfo->attrs [i].ctor->klass;
8821                 if (mono_class_has_parent (klass, attr_klass)) {
8822                         attr_index = i;
8823                         break;
8824                 }
8825         }
8826         if (attr_index == -1)
8827                 return NULL;
8828
8829         attrs = mono_custom_attrs_construct (ainfo);
8830         if (attrs)
8831                 return mono_array_get (attrs, MonoObject*, attr_index);
8832         else
8833                 return NULL;
8834 }
8835
8836 /*
8837  * mono_reflection_get_custom_attrs_info:
8838  * @obj: a reflection object handle
8839  *
8840  * Return the custom attribute info for attributes defined for the
8841  * reflection handle @obj. The objects.
8842  *
8843  * FIXME this function leaks like a sieve for SRE objects.
8844  */
8845 MonoCustomAttrInfo*
8846 mono_reflection_get_custom_attrs_info (MonoObject *obj)
8847 {
8848         MonoClass *klass;
8849         MonoCustomAttrInfo *cinfo = NULL;
8850         
8851         klass = obj->vtable->klass;
8852         if (klass == mono_defaults.monotype_class) {
8853                 MonoType *type = mono_reflection_type_get_handle ((MonoReflectionType *)obj);
8854                 klass = mono_class_from_mono_type (type);
8855                 /*We cannot mono_class_init the class from which we'll load the custom attributes since this must work with broken types.*/
8856                 cinfo = mono_custom_attrs_from_class (klass);
8857         } else if (strcmp ("Assembly", klass->name) == 0 || strcmp ("MonoAssembly", klass->name) == 0) {
8858                 MonoReflectionAssembly *rassembly = (MonoReflectionAssembly*)obj;
8859                 cinfo = mono_custom_attrs_from_assembly (rassembly->assembly);
8860         } else if (strcmp ("Module", klass->name) == 0 || strcmp ("MonoModule", klass->name) == 0) {
8861                 MonoReflectionModule *module = (MonoReflectionModule*)obj;
8862                 cinfo = mono_custom_attrs_from_module (module->image);
8863         } else if (strcmp ("MonoProperty", klass->name) == 0) {
8864                 MonoReflectionProperty *rprop = (MonoReflectionProperty*)obj;
8865                 cinfo = mono_custom_attrs_from_property (rprop->property->parent, rprop->property);
8866         } else if (strcmp ("MonoEvent", klass->name) == 0) {
8867                 MonoReflectionMonoEvent *revent = (MonoReflectionMonoEvent*)obj;
8868                 cinfo = mono_custom_attrs_from_event (revent->event->parent, revent->event);
8869         } else if (strcmp ("MonoField", klass->name) == 0) {
8870                 MonoReflectionField *rfield = (MonoReflectionField*)obj;
8871                 cinfo = mono_custom_attrs_from_field (rfield->field->parent, rfield->field);
8872         } else if ((strcmp ("MonoMethod", klass->name) == 0) || (strcmp ("MonoCMethod", klass->name) == 0)) {
8873                 MonoReflectionMethod *rmethod = (MonoReflectionMethod*)obj;
8874                 cinfo = mono_custom_attrs_from_method (rmethod->method);
8875         } else if ((strcmp ("MonoGenericMethod", klass->name) == 0) || (strcmp ("MonoGenericCMethod", klass->name) == 0)) {
8876                 MonoReflectionMethod *rmethod = (MonoReflectionMethod*)obj;
8877                 cinfo = mono_custom_attrs_from_method (rmethod->method);
8878         } else if (strcmp ("ParameterInfo", klass->name) == 0 || strcmp ("MonoParameterInfo", klass->name) == 0) {
8879                 MonoReflectionParameter *param = (MonoReflectionParameter*)obj;
8880                 MonoClass *member_class = mono_object_class (param->MemberImpl);
8881                 if (mono_class_is_reflection_method_or_constructor (member_class)) {
8882                         MonoReflectionMethod *rmethod = (MonoReflectionMethod*)param->MemberImpl;
8883                         cinfo = mono_custom_attrs_from_param (rmethod->method, param->PositionImpl + 1);
8884                 } else if (is_sr_mono_property (member_class)) {
8885                         MonoReflectionProperty *prop = (MonoReflectionProperty *)param->MemberImpl;
8886                         MonoMethod *method;
8887                         if (!(method = prop->property->get))
8888                                 method = prop->property->set;
8889                         g_assert (method);
8890
8891                         cinfo = mono_custom_attrs_from_param (method, param->PositionImpl + 1);
8892                 } 
8893 #ifndef DISABLE_REFLECTION_EMIT
8894                 else if (is_sre_method_on_tb_inst (member_class)) {/*XXX This is a workaround for Compiler Context*/
8895                         MonoMethod *method = mono_reflection_method_on_tb_inst_get_handle ((MonoReflectionMethodOnTypeBuilderInst*)param->MemberImpl);
8896                         cinfo = mono_custom_attrs_from_param (method, param->PositionImpl + 1);
8897                 } else if (is_sre_ctor_on_tb_inst (member_class)) { /*XX This is a workaround for Compiler Context*/
8898                         MonoReflectionCtorOnTypeBuilderInst *c = (MonoReflectionCtorOnTypeBuilderInst*)param->MemberImpl;
8899                         MonoMethod *method = NULL;
8900                         if (is_sre_ctor_builder (mono_object_class (c->cb)))
8901                                 method = ((MonoReflectionCtorBuilder *)c->cb)->mhandle;
8902                         else if (is_sr_mono_cmethod (mono_object_class (c->cb)))
8903                                 method = ((MonoReflectionMethod *)c->cb)->method;
8904                         else
8905                                 g_error ("mono_reflection_get_custom_attrs_info:: can't handle a CTBI with base_method of type %s", mono_type_get_full_name (member_class));
8906
8907                         cinfo = mono_custom_attrs_from_param (method, param->PositionImpl + 1);
8908                 } 
8909 #endif
8910                 else {
8911                         char *type_name = mono_type_get_full_name (member_class);
8912                         char *msg = g_strdup_printf ("Custom attributes on a ParamInfo with member %s are not supported", type_name);
8913                         MonoException *ex = mono_get_exception_not_supported  (msg);
8914                         g_free (type_name);
8915                         g_free (msg);
8916                         mono_raise_exception (ex);
8917                 }
8918         } else if (strcmp ("AssemblyBuilder", klass->name) == 0) {
8919                 MonoReflectionAssemblyBuilder *assemblyb = (MonoReflectionAssemblyBuilder*)obj;
8920                 cinfo = mono_custom_attrs_from_builders (NULL, assemblyb->assembly.assembly->image, assemblyb->cattrs);
8921         } else if (strcmp ("TypeBuilder", klass->name) == 0) {
8922                 MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder*)obj;
8923                 cinfo = mono_custom_attrs_from_builders (NULL, &tb->module->dynamic_image->image, tb->cattrs);
8924         } else if (strcmp ("ModuleBuilder", klass->name) == 0) {
8925                 MonoReflectionModuleBuilder *mb = (MonoReflectionModuleBuilder*)obj;
8926                 cinfo = mono_custom_attrs_from_builders (NULL, &mb->dynamic_image->image, mb->cattrs);
8927         } else if (strcmp ("ConstructorBuilder", klass->name) == 0) {
8928                 MonoReflectionCtorBuilder *cb = (MonoReflectionCtorBuilder*)obj;
8929                 cinfo = mono_custom_attrs_from_builders (NULL, cb->mhandle->klass->image, cb->cattrs);
8930         } else if (strcmp ("MethodBuilder", klass->name) == 0) {
8931                 MonoReflectionMethodBuilder *mb = (MonoReflectionMethodBuilder*)obj;
8932                 cinfo = mono_custom_attrs_from_builders (NULL, mb->mhandle->klass->image, mb->cattrs);
8933         } else if (strcmp ("FieldBuilder", klass->name) == 0) {
8934                 MonoReflectionFieldBuilder *fb = (MonoReflectionFieldBuilder*)obj;
8935                 cinfo = mono_custom_attrs_from_builders (NULL, &((MonoReflectionTypeBuilder*)fb->typeb)->module->dynamic_image->image, fb->cattrs);
8936         } else if (strcmp ("MonoGenericClass", klass->name) == 0) {
8937                 MonoReflectionGenericClass *gclass = (MonoReflectionGenericClass*)obj;
8938                 cinfo = mono_reflection_get_custom_attrs_info ((MonoObject*)gclass->generic_type);
8939         } else { /* handle other types here... */
8940                 g_error ("get custom attrs not yet supported for %s", klass->name);
8941         }
8942
8943         return cinfo;
8944 }
8945
8946 /*
8947  * mono_reflection_get_custom_attrs_by_type:
8948  * @obj: a reflection object handle
8949  *
8950  * Return an array with all the custom attributes defined of the
8951  * reflection handle @obj. If @attr_klass is non-NULL, only custom attributes 
8952  * of that type are returned. The objects are fully build. Return NULL if a loading error
8953  * occurs.
8954  */
8955 MonoArray*
8956 mono_reflection_get_custom_attrs_by_type (MonoObject *obj, MonoClass *attr_klass, MonoError *error)
8957 {
8958         MonoArray *result;
8959         MonoCustomAttrInfo *cinfo;
8960
8961         mono_error_init (error);
8962
8963         cinfo = mono_reflection_get_custom_attrs_info (obj);
8964         if (cinfo) {
8965                 result = mono_custom_attrs_construct_by_type (cinfo, attr_klass, error);
8966                 if (!cinfo->cached)
8967                         mono_custom_attrs_free (cinfo);
8968         } else {
8969                 if (mono_loader_get_last_error ())
8970                         return NULL;
8971                 result = mono_array_new_cached (mono_domain_get (), mono_defaults.attribute_class, 0);
8972         }
8973
8974         return result;
8975 }
8976
8977 /*
8978  * mono_reflection_get_custom_attrs:
8979  * @obj: a reflection object handle
8980  *
8981  * Return an array with all the custom attributes defined of the
8982  * reflection handle @obj. The objects are fully build. Return NULL if a loading error
8983  * occurs.
8984  */
8985 MonoArray*
8986 mono_reflection_get_custom_attrs (MonoObject *obj)
8987 {
8988         MonoError error;
8989
8990         return mono_reflection_get_custom_attrs_by_type (obj, NULL, &error);
8991 }
8992
8993 /*
8994  * mono_reflection_get_custom_attrs_data:
8995  * @obj: a reflection obj handle
8996  *
8997  * Returns an array of System.Reflection.CustomAttributeData,
8998  * which include information about attributes reflected on
8999  * types loaded using the Reflection Only methods
9000  */
9001 MonoArray*
9002 mono_reflection_get_custom_attrs_data (MonoObject *obj)
9003 {
9004         MonoArray *result;
9005         MonoCustomAttrInfo *cinfo;
9006
9007         cinfo = mono_reflection_get_custom_attrs_info (obj);
9008         if (cinfo) {
9009                 result = mono_custom_attrs_data_construct (cinfo);
9010                 if (!cinfo->cached)
9011                         mono_custom_attrs_free (cinfo);
9012         } else
9013                 result = mono_array_new (mono_domain_get (), mono_defaults.customattribute_data_class, 0);
9014
9015         return result;
9016 }
9017
9018 static MonoReflectionType*
9019 mono_reflection_type_get_underlying_system_type (MonoReflectionType* t)
9020 {
9021         static MonoMethod *method_get_underlying_system_type = NULL;
9022         MonoMethod *usertype_method;
9023
9024         if (!method_get_underlying_system_type)
9025                 method_get_underlying_system_type = mono_class_get_method_from_name (mono_defaults.systemtype_class, "get_UnderlyingSystemType", 0);
9026         usertype_method = mono_object_get_virtual_method ((MonoObject *) t, method_get_underlying_system_type);
9027         return (MonoReflectionType *) mono_runtime_invoke (usertype_method, t, NULL, NULL);
9028 }
9029
9030
9031 static gboolean
9032 is_corlib_type (MonoClass *class)
9033 {
9034         return class->image == mono_defaults.corlib;
9035 }
9036
9037 #define check_corlib_type_cached(_class, _namespace, _name) do { \
9038         static MonoClass *cached_class; \
9039         if (cached_class) \
9040                 return cached_class == _class; \
9041         if (is_corlib_type (_class) && !strcmp (_name, _class->name) && !strcmp (_namespace, _class->name_space)) { \
9042                 cached_class = _class; \
9043                 return TRUE; \
9044         } \
9045         return FALSE; \
9046 } while (0) \
9047
9048
9049 #ifndef DISABLE_REFLECTION_EMIT
9050 static gboolean
9051 is_sre_array (MonoClass *class)
9052 {
9053         check_corlib_type_cached (class, "System.Reflection.Emit", "ArrayType");
9054 }
9055
9056 static gboolean
9057 is_sre_byref (MonoClass *class)
9058 {
9059         check_corlib_type_cached (class, "System.Reflection.Emit", "ByRefType");
9060 }
9061
9062 static gboolean
9063 is_sre_pointer (MonoClass *class)
9064 {
9065         check_corlib_type_cached (class, "System.Reflection.Emit", "PointerType");
9066 }
9067
9068 static gboolean
9069 is_sre_generic_instance (MonoClass *class)
9070 {
9071         check_corlib_type_cached (class, "System.Reflection", "MonoGenericClass");
9072 }
9073
9074 static gboolean
9075 is_sre_type_builder (MonoClass *class)
9076 {
9077         check_corlib_type_cached (class, "System.Reflection.Emit", "TypeBuilder");
9078 }
9079
9080 static gboolean
9081 is_sre_method_builder (MonoClass *class)
9082 {
9083         check_corlib_type_cached (class, "System.Reflection.Emit", "MethodBuilder");
9084 }
9085
9086 static gboolean
9087 is_sre_ctor_builder (MonoClass *class)
9088 {
9089         check_corlib_type_cached (class, "System.Reflection.Emit", "ConstructorBuilder");
9090 }
9091
9092 static gboolean
9093 is_sre_field_builder (MonoClass *class)
9094 {
9095         check_corlib_type_cached (class, "System.Reflection.Emit", "FieldBuilder");
9096 }
9097
9098 static gboolean
9099 is_sre_method_on_tb_inst (MonoClass *class)
9100 {
9101         check_corlib_type_cached (class, "System.Reflection.Emit", "MethodOnTypeBuilderInst");
9102 }
9103
9104 static gboolean
9105 is_sre_ctor_on_tb_inst (MonoClass *class)
9106 {
9107         check_corlib_type_cached (class, "System.Reflection.Emit", "ConstructorOnTypeBuilderInst");
9108 }
9109
9110 MonoType*
9111 mono_reflection_type_get_handle (MonoReflectionType* ref)
9112 {
9113         MonoClass *class;
9114         if (!ref)
9115                 return NULL;
9116         if (ref->type)
9117                 return ref->type;
9118
9119         if (is_usertype (ref)) {
9120                 ref = mono_reflection_type_get_underlying_system_type (ref);
9121                 if (ref == NULL || is_usertype (ref))
9122                         return NULL;
9123                 if (ref->type)
9124                         return ref->type;
9125         }
9126
9127         class = mono_object_class (ref);
9128
9129         if (is_sre_array (class)) {
9130                 MonoType *res;
9131                 MonoReflectionArrayType *sre_array = (MonoReflectionArrayType*)ref;
9132                 MonoType *base = mono_reflection_type_get_handle (sre_array->element_type);
9133                 g_assert (base);
9134                 if (sre_array->rank == 0) //single dimentional array
9135                         res = &mono_array_class_get (mono_class_from_mono_type (base), 1)->byval_arg;
9136                 else
9137                         res = &mono_bounded_array_class_get (mono_class_from_mono_type (base), sre_array->rank, TRUE)->byval_arg;
9138                 sre_array->type.type = res;
9139                 return res;
9140         } else if (is_sre_byref (class)) {
9141                 MonoType *res;
9142                 MonoReflectionDerivedType *sre_byref = (MonoReflectionDerivedType*)ref;
9143                 MonoType *base = mono_reflection_type_get_handle (sre_byref->element_type);
9144                 g_assert (base);
9145                 res = &mono_class_from_mono_type (base)->this_arg;
9146                 sre_byref->type.type = res;
9147                 return res;
9148         } else if (is_sre_pointer (class)) {
9149                 MonoType *res;
9150                 MonoReflectionDerivedType *sre_pointer = (MonoReflectionDerivedType*)ref;
9151                 MonoType *base = mono_reflection_type_get_handle (sre_pointer->element_type);
9152                 g_assert (base);
9153                 res = &mono_ptr_class_get (base)->byval_arg;
9154                 sre_pointer->type.type = res;
9155                 return res;
9156         } else if (is_sre_generic_instance (class)) {
9157                 MonoType *res, **types;
9158                 MonoReflectionGenericClass *gclass = (MonoReflectionGenericClass*)ref;
9159                 int i, count;
9160
9161                 count = mono_array_length (gclass->type_arguments);
9162                 types = g_new0 (MonoType*, count);
9163                 for (i = 0; i < count; ++i) {
9164                         MonoReflectionType *t = mono_array_get (gclass->type_arguments, gpointer, i);
9165                         types [i] = mono_reflection_type_get_handle (t);
9166                         if (!types[i]) {
9167                                 g_free (types);
9168                                 return NULL;
9169                         }
9170                 }
9171
9172                 res = mono_reflection_bind_generic_parameters (gclass->generic_type, count, types);
9173                 g_free (types);
9174                 g_assert (res);
9175                 gclass->type.type = res;
9176                 return res;
9177         }
9178
9179         g_error ("Cannot handle corlib user type %s", mono_type_full_name (&mono_object_class(ref)->byval_arg));
9180         return NULL;
9181 }
9182
9183
9184
9185 void
9186 mono_reflection_create_unmanaged_type (MonoReflectionType *type)
9187 {
9188         mono_reflection_type_get_handle (type);
9189 }
9190
9191 void
9192 mono_reflection_register_with_runtime (MonoReflectionType *type)
9193 {
9194         MonoType *res = mono_reflection_type_get_handle (type);
9195         MonoDomain *domain = mono_object_domain ((MonoObject*)type);
9196         MonoClass *class;
9197
9198         if (!res)
9199                 mono_raise_exception (mono_get_exception_argument (NULL, "Invalid generic instantiation, one or more arguments are not proper user types"));
9200
9201         class = mono_class_from_mono_type (res);
9202
9203         mono_loader_lock (); /*same locking as mono_type_get_object*/
9204         mono_domain_lock (domain);
9205
9206         if (!class->image->dynamic) {
9207                 mono_class_setup_supertypes (class);
9208         } else {
9209                 if (!domain->type_hash)
9210                         domain->type_hash = mono_g_hash_table_new_type ((GHashFunc)mono_metadata_type_hash, 
9211                                         (GCompareFunc)mono_metadata_type_equal, MONO_HASH_VALUE_GC);
9212                 mono_g_hash_table_insert (domain->type_hash, res, type);
9213         }
9214         mono_domain_unlock (domain);
9215         mono_loader_unlock ();
9216 }
9217
9218 /**
9219  * LOCKING: Assumes the loader lock is held.
9220  */
9221 static MonoMethodSignature*
9222 parameters_to_signature (MonoImage *image, MonoArray *parameters) {
9223         MonoMethodSignature *sig;
9224         int count, i;
9225
9226         count = parameters? mono_array_length (parameters): 0;
9227
9228         sig = image_g_malloc0 (image, MONO_SIZEOF_METHOD_SIGNATURE + sizeof (MonoType*) * count);
9229         sig->param_count = count;
9230         sig->sentinelpos = -1; /* FIXME */
9231         for (i = 0; i < count; ++i)
9232                 sig->params [i] = mono_type_array_get_and_resolve (parameters, i);
9233         return sig;
9234 }
9235
9236 /**
9237  * LOCKING: Assumes the loader lock is held.
9238  */
9239 static MonoMethodSignature*
9240 ctor_builder_to_signature (MonoImage *image, MonoReflectionCtorBuilder *ctor) {
9241         MonoMethodSignature *sig;
9242
9243         sig = parameters_to_signature (image, ctor->parameters);
9244         sig->hasthis = ctor->attrs & METHOD_ATTRIBUTE_STATIC? 0: 1;
9245         sig->ret = &mono_defaults.void_class->byval_arg;
9246         return sig;
9247 }
9248
9249 /**
9250  * LOCKING: Assumes the loader lock is held.
9251  */
9252 static MonoMethodSignature*
9253 method_builder_to_signature (MonoImage *image, MonoReflectionMethodBuilder *method) {
9254         MonoMethodSignature *sig;
9255
9256         sig = parameters_to_signature (image, method->parameters);
9257         sig->hasthis = method->attrs & METHOD_ATTRIBUTE_STATIC? 0: 1;
9258         sig->ret = method->rtype? mono_reflection_type_get_handle ((MonoReflectionType*)method->rtype): &mono_defaults.void_class->byval_arg;
9259         sig->generic_param_count = method->generic_params ? mono_array_length (method->generic_params) : 0;
9260         return sig;
9261 }
9262
9263 static MonoMethodSignature*
9264 dynamic_method_to_signature (MonoReflectionDynamicMethod *method) {
9265         MonoMethodSignature *sig;
9266
9267         sig = parameters_to_signature (NULL, method->parameters);
9268         sig->hasthis = method->attrs & METHOD_ATTRIBUTE_STATIC? 0: 1;
9269         sig->ret = method->rtype? mono_reflection_type_get_handle (method->rtype): &mono_defaults.void_class->byval_arg;
9270         sig->generic_param_count = 0;
9271         return sig;
9272 }
9273
9274 static void
9275 get_prop_name_and_type (MonoObject *prop, char **name, MonoType **type)
9276 {
9277         MonoClass *klass = mono_object_class (prop);
9278         if (strcmp (klass->name, "PropertyBuilder") == 0) {
9279                 MonoReflectionPropertyBuilder *pb = (MonoReflectionPropertyBuilder *)prop;
9280                 *name = mono_string_to_utf8 (pb->name);
9281                 *type = mono_reflection_type_get_handle ((MonoReflectionType*)pb->type);
9282         } else {
9283                 MonoReflectionProperty *p = (MonoReflectionProperty *)prop;
9284                 *name = g_strdup (p->property->name);
9285                 if (p->property->get)
9286                         *type = mono_method_signature (p->property->get)->ret;
9287                 else
9288                         *type = mono_method_signature (p->property->set)->params [mono_method_signature (p->property->set)->param_count - 1];
9289         }
9290 }
9291
9292 static void
9293 get_field_name_and_type (MonoObject *field, char **name, MonoType **type)
9294 {
9295         MonoClass *klass = mono_object_class (field);
9296         if (strcmp (klass->name, "FieldBuilder") == 0) {
9297                 MonoReflectionFieldBuilder *fb = (MonoReflectionFieldBuilder *)field;
9298                 *name = mono_string_to_utf8 (fb->name);
9299                 *type = mono_reflection_type_get_handle ((MonoReflectionType*)fb->type);
9300         } else {
9301                 MonoReflectionField *f = (MonoReflectionField *)field;
9302                 *name = g_strdup (mono_field_get_name (f->field));
9303                 *type = f->field->type;
9304         }
9305 }
9306
9307 #else /* DISABLE_REFLECTION_EMIT */
9308
9309 void
9310 mono_reflection_register_with_runtime (MonoReflectionType *type)
9311 {
9312         /* This is empty */
9313 }
9314
9315 static gboolean
9316 is_sre_type_builder (MonoClass *class)
9317 {
9318         return FALSE;
9319 }
9320
9321 static gboolean
9322 is_sre_generic_instance (MonoClass *class)
9323 {
9324         return FALSE;
9325 }
9326
9327 static void
9328 init_type_builder_generics (MonoObject *type)
9329 {
9330 }
9331
9332 #endif /* !DISABLE_REFLECTION_EMIT */
9333
9334
9335 static gboolean
9336 is_sr_mono_field (MonoClass *class)
9337 {
9338         check_corlib_type_cached (class, "System.Reflection", "MonoField");
9339 }
9340
9341 static gboolean
9342 is_sr_mono_property (MonoClass *class)
9343 {
9344         check_corlib_type_cached (class, "System.Reflection", "MonoProperty");
9345 }
9346
9347 static gboolean
9348 is_sr_mono_method (MonoClass *class)
9349 {
9350         check_corlib_type_cached (class, "System.Reflection", "MonoMethod");
9351 }
9352
9353 static gboolean
9354 is_sr_mono_cmethod (MonoClass *class)
9355 {
9356         check_corlib_type_cached (class, "System.Reflection", "MonoCMethod");
9357 }
9358
9359 static gboolean
9360 is_sr_mono_generic_method (MonoClass *class)
9361 {
9362         check_corlib_type_cached (class, "System.Reflection", "MonoGenericMethod");
9363 }
9364
9365 static gboolean
9366 is_sr_mono_generic_cmethod (MonoClass *class)
9367 {
9368         check_corlib_type_cached (class, "System.Reflection", "MonoGenericCMethod");
9369 }
9370
9371 gboolean
9372 mono_class_is_reflection_method_or_constructor (MonoClass *class)
9373 {
9374         return is_sr_mono_method (class) || is_sr_mono_cmethod (class) || is_sr_mono_generic_method (class) || is_sr_mono_generic_cmethod (class);
9375 }
9376
9377 static gboolean
9378 is_usertype (MonoReflectionType *ref)
9379 {
9380         MonoClass *class = mono_object_class (ref);
9381         return class->image != mono_defaults.corlib || strcmp ("TypeDelegator", class->name) == 0;
9382 }
9383
9384 static MonoReflectionType*
9385 mono_reflection_type_resolve_user_types (MonoReflectionType *type)
9386 {
9387         if (!type || type->type)
9388                 return type;
9389
9390         if (is_usertype (type)) {
9391                 type = mono_reflection_type_get_underlying_system_type (type);
9392                 if (is_usertype (type))
9393                         mono_raise_exception (mono_get_exception_not_supported ("User defined subclasses of System.Type are not yet supported22"));
9394         }
9395
9396         return type;
9397 }
9398 /*
9399  * Encode a value in a custom attribute stream of bytes.
9400  * The value to encode is either supplied as an object in argument val
9401  * (valuetypes are boxed), or as a pointer to the data in the
9402  * argument argval.
9403  * @type represents the type of the value
9404  * @buffer is the start of the buffer
9405  * @p the current position in the buffer
9406  * @buflen contains the size of the buffer and is used to return the new buffer size
9407  * if this needs to be realloced.
9408  * @retbuffer and @retp return the start and the position of the buffer
9409  */
9410 static void
9411 encode_cattr_value (MonoAssembly *assembly, char *buffer, char *p, char **retbuffer, char **retp, guint32 *buflen, MonoType *type, MonoObject *arg, char *argval)
9412 {
9413         MonoTypeEnum simple_type;
9414         
9415         if ((p-buffer) + 10 >= *buflen) {
9416                 char *newbuf;
9417                 *buflen *= 2;
9418                 newbuf = g_realloc (buffer, *buflen);
9419                 p = newbuf + (p-buffer);
9420                 buffer = newbuf;
9421         }
9422         if (!argval)
9423                 argval = ((char*)arg + sizeof (MonoObject));
9424         simple_type = type->type;
9425 handle_enum:
9426         switch (simple_type) {
9427         case MONO_TYPE_BOOLEAN:
9428         case MONO_TYPE_U1:
9429         case MONO_TYPE_I1:
9430                 *p++ = *argval;
9431                 break;
9432         case MONO_TYPE_CHAR:
9433         case MONO_TYPE_U2:
9434         case MONO_TYPE_I2:
9435                 swap_with_size (p, argval, 2, 1);
9436                 p += 2;
9437                 break;
9438         case MONO_TYPE_U4:
9439         case MONO_TYPE_I4:
9440         case MONO_TYPE_R4:
9441                 swap_with_size (p, argval, 4, 1);
9442                 p += 4;
9443                 break;
9444         case MONO_TYPE_R8:
9445                 swap_with_size (p, argval, 8, 1);
9446                 p += 8;
9447                 break;
9448         case MONO_TYPE_U8:
9449         case MONO_TYPE_I8:
9450                 swap_with_size (p, argval, 8, 1);
9451                 p += 8;
9452                 break;
9453         case MONO_TYPE_VALUETYPE:
9454                 if (type->data.klass->enumtype) {
9455                         simple_type = mono_class_enum_basetype (type->data.klass)->type;
9456                         goto handle_enum;
9457                 } else {
9458                         g_warning ("generic valutype %s not handled in custom attr value decoding", type->data.klass->name);
9459                 }
9460                 break;
9461         case MONO_TYPE_STRING: {
9462                 char *str;
9463                 guint32 slen;
9464                 if (!arg) {
9465                         *p++ = 0xFF;
9466                         break;
9467                 }
9468                 str = mono_string_to_utf8 ((MonoString*)arg);
9469                 slen = strlen (str);
9470                 if ((p-buffer) + 10 + slen >= *buflen) {
9471                         char *newbuf;
9472                         *buflen *= 2;
9473                         *buflen += slen;
9474                         newbuf = g_realloc (buffer, *buflen);
9475                         p = newbuf + (p-buffer);
9476                         buffer = newbuf;
9477                 }
9478                 mono_metadata_encode_value (slen, p, &p);
9479                 memcpy (p, str, slen);
9480                 p += slen;
9481                 g_free (str);
9482                 break;
9483         }
9484         case MONO_TYPE_CLASS: {
9485                 char *str;
9486                 guint32 slen;
9487                 if (!arg) {
9488                         *p++ = 0xFF;
9489                         break;
9490                 }
9491 handle_type:
9492                 str = type_get_qualified_name (mono_reflection_type_get_handle ((MonoReflectionType*)arg), NULL);
9493                 slen = strlen (str);
9494                 if ((p-buffer) + 10 + slen >= *buflen) {
9495                         char *newbuf;
9496                         *buflen *= 2;
9497                         *buflen += slen;
9498                         newbuf = g_realloc (buffer, *buflen);
9499                         p = newbuf + (p-buffer);
9500                         buffer = newbuf;
9501                 }
9502                 mono_metadata_encode_value (slen, p, &p);
9503                 memcpy (p, str, slen);
9504                 p += slen;
9505                 g_free (str);
9506                 break;
9507         }
9508         case MONO_TYPE_SZARRAY: {
9509                 int len, i;
9510                 MonoClass *eclass, *arg_eclass;
9511
9512                 if (!arg) {
9513                         *p++ = 0xff; *p++ = 0xff; *p++ = 0xff; *p++ = 0xff;
9514                         break;
9515                 }
9516                 len = mono_array_length ((MonoArray*)arg);
9517                 *p++ = len & 0xff;
9518                 *p++ = (len >> 8) & 0xff;
9519                 *p++ = (len >> 16) & 0xff;
9520                 *p++ = (len >> 24) & 0xff;
9521                 *retp = p;
9522                 *retbuffer = buffer;
9523                 eclass = type->data.klass;
9524                 arg_eclass = mono_object_class (arg)->element_class;
9525
9526                 if (!eclass) {
9527                         /* Happens when we are called from the MONO_TYPE_OBJECT case below */
9528                         eclass = mono_defaults.object_class;
9529                 }
9530                 if (eclass == mono_defaults.object_class && arg_eclass->valuetype) {
9531                         char *elptr = mono_array_addr ((MonoArray*)arg, char, 0);
9532                         int elsize = mono_class_array_element_size (arg_eclass);
9533                         for (i = 0; i < len; ++i) {
9534                                 encode_cattr_value (assembly, buffer, p, &buffer, &p, buflen, &arg_eclass->byval_arg, NULL, elptr);
9535                                 elptr += elsize;
9536                         }
9537                 } else if (eclass->valuetype && arg_eclass->valuetype) {
9538                         char *elptr = mono_array_addr ((MonoArray*)arg, char, 0);
9539                         int elsize = mono_class_array_element_size (eclass);
9540                         for (i = 0; i < len; ++i) {
9541                                 encode_cattr_value (assembly, buffer, p, &buffer, &p, buflen, &eclass->byval_arg, NULL, elptr);
9542                                 elptr += elsize;
9543                         }
9544                 } else {
9545                         for (i = 0; i < len; ++i) {
9546                                 encode_cattr_value (assembly, buffer, p, &buffer, &p, buflen, &eclass->byval_arg, mono_array_get ((MonoArray*)arg, MonoObject*, i), NULL);
9547                         }
9548                 }
9549                 break;
9550         }
9551         case MONO_TYPE_OBJECT: {
9552                 MonoClass *klass;
9553                 char *str;
9554                 guint32 slen;
9555
9556                 /*
9557                  * The parameter type is 'object' but the type of the actual
9558                  * argument is not. So we have to add type information to the blob
9559                  * too. This is completely undocumented in the spec.
9560                  */
9561
9562                 if (arg == NULL) {
9563                         *p++ = MONO_TYPE_STRING;        // It's same hack as MS uses
9564                         *p++ = 0xFF;
9565                         break;
9566                 }
9567                 
9568                 klass = mono_object_class (arg);
9569
9570                 if (mono_object_isinst (arg, mono_defaults.systemtype_class)) {
9571                         *p++ = 0x50;
9572                         goto handle_type;
9573                 } else if (klass->enumtype) {
9574                         *p++ = 0x55;
9575                 } else if (klass == mono_defaults.string_class) {
9576                         simple_type = MONO_TYPE_STRING;
9577                         *p++ = 0x0E;
9578                         goto handle_enum;
9579                 } else if (klass->rank == 1) {
9580                         *p++ = 0x1D;
9581                         if (klass->element_class->byval_arg.type == MONO_TYPE_OBJECT)
9582                                 /* See Partition II, Appendix B3 */
9583                                 *p++ = 0x51;
9584                         else
9585                                 *p++ = klass->element_class->byval_arg.type;
9586                         encode_cattr_value (assembly, buffer, p, &buffer, &p, buflen, &klass->byval_arg, arg, NULL);
9587                         break;
9588                 } else if (klass->byval_arg.type >= MONO_TYPE_BOOLEAN && klass->byval_arg.type <= MONO_TYPE_R8) {
9589                         *p++ = simple_type = klass->byval_arg.type;
9590                         goto handle_enum;
9591                 } else {
9592                         g_error ("unhandled type in custom attr");
9593                 }
9594                 str = type_get_qualified_name (mono_class_get_type(klass), NULL);
9595                 slen = strlen (str);
9596                 if ((p-buffer) + 10 + slen >= *buflen) {
9597                         char *newbuf;
9598                         *buflen *= 2;
9599                         *buflen += slen;
9600                         newbuf = g_realloc (buffer, *buflen);
9601                         p = newbuf + (p-buffer);
9602                         buffer = newbuf;
9603                 }
9604                 mono_metadata_encode_value (slen, p, &p);
9605                 memcpy (p, str, slen);
9606                 p += slen;
9607                 g_free (str);
9608                 simple_type = mono_class_enum_basetype (klass)->type;
9609                 goto handle_enum;
9610         }
9611         default:
9612                 g_error ("type 0x%02x not yet supported in custom attr encoder", simple_type);
9613         }
9614         *retp = p;
9615         *retbuffer = buffer;
9616 }
9617
9618 static void
9619 encode_field_or_prop_type (MonoType *type, char *p, char **retp)
9620 {
9621         if (type->type == MONO_TYPE_VALUETYPE && type->data.klass->enumtype) {
9622                 char *str = type_get_qualified_name (type, NULL);
9623                 int slen = strlen (str);
9624
9625                 *p++ = 0x55;
9626                 /*
9627                  * This seems to be optional...
9628                  * *p++ = 0x80;
9629                  */
9630                 mono_metadata_encode_value (slen, p, &p);
9631                 memcpy (p, str, slen);
9632                 p += slen;
9633                 g_free (str);
9634         } else if (type->type == MONO_TYPE_OBJECT) {
9635                 *p++ = 0x51;
9636         } else if (type->type == MONO_TYPE_CLASS) {
9637                 /* it should be a type: encode_cattr_value () has the check */
9638                 *p++ = 0x50;
9639         } else {
9640                 mono_metadata_encode_value (type->type, p, &p);
9641                 if (type->type == MONO_TYPE_SZARRAY)
9642                         /* See the examples in Partition VI, Annex B */
9643                         encode_field_or_prop_type (&type->data.klass->byval_arg, p, &p);
9644         }
9645
9646         *retp = p;
9647 }
9648
9649 #ifndef DISABLE_REFLECTION_EMIT
9650 static void
9651 encode_named_val (MonoReflectionAssembly *assembly, char *buffer, char *p, char **retbuffer, char **retp, guint32 *buflen, MonoType *type, char *name, MonoObject *value)
9652 {
9653         int len;
9654         /* Preallocate a large enough buffer */
9655         if (type->type == MONO_TYPE_VALUETYPE && type->data.klass->enumtype) {
9656                 char *str = type_get_qualified_name (type, NULL);
9657                 len = strlen (str);
9658                 g_free (str);
9659         } else if (type->type == MONO_TYPE_SZARRAY && type->data.klass->enumtype) {
9660                 char *str = type_get_qualified_name (&type->data.klass->byval_arg, NULL);
9661                 len = strlen (str);
9662                 g_free (str);
9663         } else {
9664                 len = 0;
9665         }
9666         len += strlen (name);
9667
9668         if ((p-buffer) + 20 + len >= *buflen) {
9669                 char *newbuf;
9670                 *buflen *= 2;
9671                 *buflen += len;
9672                 newbuf = g_realloc (buffer, *buflen);
9673                 p = newbuf + (p-buffer);
9674                 buffer = newbuf;
9675         }
9676
9677         encode_field_or_prop_type (type, p, &p);
9678
9679         len = strlen (name);
9680         mono_metadata_encode_value (len, p, &p);
9681         memcpy (p, name, len);
9682         p += len;
9683         encode_cattr_value (assembly->assembly, buffer, p, &buffer, &p, buflen, type, value, NULL);
9684         *retp = p;
9685         *retbuffer = buffer;
9686 }
9687
9688 /*
9689  * mono_reflection_get_custom_attrs_blob:
9690  * @ctor: custom attribute constructor
9691  * @ctorArgs: arguments o the constructor
9692  * @properties:
9693  * @propValues:
9694  * @fields:
9695  * @fieldValues:
9696  * 
9697  * Creates the blob of data that needs to be saved in the metadata and that represents
9698  * the custom attributed described by @ctor, @ctorArgs etc.
9699  * Returns: a Byte array representing the blob of data.
9700  */
9701 MonoArray*
9702 mono_reflection_get_custom_attrs_blob (MonoReflectionAssembly *assembly, MonoObject *ctor, MonoArray *ctorArgs, MonoArray *properties, MonoArray *propValues, MonoArray *fields, MonoArray* fieldValues) 
9703 {
9704         MonoArray *result;
9705         MonoMethodSignature *sig;
9706         MonoObject *arg;
9707         char *buffer, *p;
9708         guint32 buflen, i;
9709
9710         MONO_ARCH_SAVE_REGS;
9711
9712         if (strcmp (ctor->vtable->klass->name, "MonoCMethod")) {
9713                 /* sig is freed later so allocate it in the heap */
9714                 sig = ctor_builder_to_signature (NULL, (MonoReflectionCtorBuilder*)ctor);
9715         } else {
9716                 sig = mono_method_signature (((MonoReflectionMethod*)ctor)->method);
9717         }
9718
9719         g_assert (mono_array_length (ctorArgs) == sig->param_count);
9720         buflen = 256;
9721         p = buffer = g_malloc (buflen);
9722         /* write the prolog */
9723         *p++ = 1;
9724         *p++ = 0;
9725         for (i = 0; i < sig->param_count; ++i) {
9726                 arg = mono_array_get (ctorArgs, MonoObject*, i);
9727                 encode_cattr_value (assembly->assembly, buffer, p, &buffer, &p, &buflen, sig->params [i], arg, NULL);
9728         }
9729         i = 0;
9730         if (properties)
9731                 i += mono_array_length (properties);
9732         if (fields)
9733                 i += mono_array_length (fields);
9734         *p++ = i & 0xff;
9735         *p++ = (i >> 8) & 0xff;
9736         if (properties) {
9737                 MonoObject *prop;
9738                 for (i = 0; i < mono_array_length (properties); ++i) {
9739                         MonoType *ptype;
9740                         char *pname;
9741
9742                         prop = mono_array_get (properties, gpointer, i);
9743                         get_prop_name_and_type (prop, &pname, &ptype);
9744                         *p++ = 0x54; /* PROPERTY signature */
9745                         encode_named_val (assembly, buffer, p, &buffer, &p, &buflen, ptype, pname, (MonoObject*)mono_array_get (propValues, gpointer, i));
9746                         g_free (pname);
9747                 }
9748         }
9749
9750         if (fields) {
9751                 MonoObject *field;
9752                 for (i = 0; i < mono_array_length (fields); ++i) {
9753                         MonoType *ftype;
9754                         char *fname;
9755
9756                         field = mono_array_get (fields, gpointer, i);
9757                         get_field_name_and_type (field, &fname, &ftype);
9758                         *p++ = 0x53; /* FIELD signature */
9759                         encode_named_val (assembly, buffer, p, &buffer, &p, &buflen, ftype, fname, (MonoObject*)mono_array_get (fieldValues, gpointer, i));
9760                         g_free (fname);
9761                 }
9762         }
9763
9764         g_assert (p - buffer <= buflen);
9765         buflen = p - buffer;
9766         result = mono_array_new (mono_domain_get (), mono_defaults.byte_class, buflen);
9767         p = mono_array_addr (result, char, 0);
9768         memcpy (p, buffer, buflen);
9769         g_free (buffer);
9770         if (strcmp (ctor->vtable->klass->name, "MonoCMethod"))
9771                 g_free (sig);
9772         return result;
9773 }
9774
9775 /*
9776  * mono_reflection_setup_internal_class:
9777  * @tb: a TypeBuilder object
9778  *
9779  * Creates a MonoClass that represents the TypeBuilder.
9780  * This is a trick that lets us simplify a lot of reflection code
9781  * (and will allow us to support Build and Run assemblies easier).
9782  */
9783 void
9784 mono_reflection_setup_internal_class (MonoReflectionTypeBuilder *tb)
9785 {
9786         MonoError error;
9787         MonoClass *klass, *parent;
9788
9789         MONO_ARCH_SAVE_REGS;
9790
9791         RESOLVE_TYPE (tb->parent);
9792
9793         mono_loader_lock ();
9794
9795         if (tb->parent) {
9796                 /* check so we can compile corlib correctly */
9797                 if (strcmp (mono_object_class (tb->parent)->name, "TypeBuilder") == 0) {
9798                         /* mono_class_setup_mono_type () guaranteess type->data.klass is valid */
9799                         parent = mono_reflection_type_get_handle ((MonoReflectionType*)tb->parent)->data.klass;
9800                 } else {
9801                         parent = mono_class_from_mono_type (mono_reflection_type_get_handle ((MonoReflectionType*)tb->parent));
9802                 }
9803         } else {
9804                 parent = NULL;
9805         }
9806         
9807         /* the type has already being created: it means we just have to change the parent */
9808         if (tb->type.type) {
9809                 klass = mono_class_from_mono_type (tb->type.type);
9810                 klass->parent = NULL;
9811                 /* fool mono_class_setup_parent */
9812                 klass->supertypes = NULL;
9813                 mono_class_setup_parent (klass, parent);
9814                 mono_class_setup_mono_type (klass);
9815                 mono_loader_unlock ();
9816                 return;
9817         }
9818
9819         klass = mono_image_alloc0 (&tb->module->dynamic_image->image, sizeof (MonoClass));
9820
9821         klass->image = &tb->module->dynamic_image->image;
9822
9823         klass->inited = 1; /* we lie to the runtime */
9824         klass->name = mono_string_to_utf8_image (klass->image, tb->name, &error);
9825         if (!mono_error_ok (&error))
9826                 goto failure;
9827         klass->name_space = mono_string_to_utf8_image (klass->image, tb->nspace, &error);
9828         if (!mono_error_ok (&error))
9829                 goto failure;
9830         klass->type_token = MONO_TOKEN_TYPE_DEF | tb->table_idx;
9831         klass->flags = tb->attrs;
9832         
9833         mono_profiler_class_event (klass, MONO_PROFILE_START_LOAD);
9834
9835         klass->element_class = klass;
9836
9837         if (mono_class_get_ref_info (klass) == NULL) {
9838
9839                 mono_class_set_ref_info (klass, tb);
9840
9841                 /* Put into cache so mono_class_get () will find it.
9842                 Skip nested types as those should not be available on the global scope. */
9843                 if (!tb->nesting_type)
9844                         mono_image_add_to_name_cache (klass->image, klass->name_space, klass->name, tb->table_idx);
9845
9846                 /*
9847                 We must register all types as we cannot rely on the name_cache hashtable since we find the class
9848                 by performing a mono_class_get which does the full resolution.
9849
9850                 Working around this semantics would require us to write a lot of code for no clear advantage.
9851                 */
9852                 mono_image_append_class_to_reflection_info_set (klass);
9853         } else {
9854                 g_assert (mono_class_get_ref_info (klass) == tb);
9855         }
9856
9857         mono_g_hash_table_insert (tb->module->dynamic_image->tokens,
9858                 GUINT_TO_POINTER (MONO_TOKEN_TYPE_DEF | tb->table_idx), tb);
9859
9860         if (parent != NULL) {
9861                 mono_class_setup_parent (klass, parent);
9862         } else if (strcmp (klass->name, "Object") == 0 && strcmp (klass->name_space, "System") == 0) {
9863                 const char *old_n = klass->name;
9864                 /* trick to get relative numbering right when compiling corlib */
9865                 klass->name = "BuildingObject";
9866                 mono_class_setup_parent (klass, mono_defaults.object_class);
9867                 klass->name = old_n;
9868         }
9869
9870         if ((!strcmp (klass->name, "ValueType") && !strcmp (klass->name_space, "System")) ||
9871                         (!strcmp (klass->name, "Object") && !strcmp (klass->name_space, "System")) ||
9872                         (!strcmp (klass->name, "Enum") && !strcmp (klass->name_space, "System"))) {
9873                 klass->instance_size = sizeof (MonoObject);
9874                 klass->size_inited = 1;
9875                 mono_class_setup_vtable_general (klass, NULL, 0, NULL);
9876         }
9877
9878         mono_class_setup_mono_type (klass);
9879
9880         mono_class_setup_supertypes (klass);
9881
9882         /*
9883          * FIXME: handle interfaces.
9884          */
9885
9886         tb->type.type = &klass->byval_arg;
9887
9888         if (tb->nesting_type) {
9889                 g_assert (tb->nesting_type->type);
9890                 klass->nested_in = mono_class_from_mono_type (mono_reflection_type_get_handle (tb->nesting_type));
9891         }
9892
9893         /*g_print ("setup %s as %s (%p)\n", klass->name, ((MonoObject*)tb)->vtable->klass->name, tb);*/
9894
9895         mono_profiler_class_loaded (klass, MONO_PROFILE_OK);
9896         
9897         mono_loader_unlock ();
9898         return;
9899
9900 failure:
9901         mono_loader_unlock ();
9902         mono_error_raise_exception (&error);
9903 }
9904
9905 /*
9906  * mono_reflection_setup_generic_class:
9907  * @tb: a TypeBuilder object
9908  *
9909  * Setup the generic class before adding the first generic parameter.
9910  */
9911 void
9912 mono_reflection_setup_generic_class (MonoReflectionTypeBuilder *tb)
9913 {
9914 }
9915
9916 /*
9917  * mono_reflection_create_generic_class:
9918  * @tb: a TypeBuilder object
9919  *
9920  * Creates the generic class after all generic parameters have been added.
9921  */
9922 void
9923 mono_reflection_create_generic_class (MonoReflectionTypeBuilder *tb)
9924 {
9925         MonoClass *klass;
9926         int count, i;
9927
9928         MONO_ARCH_SAVE_REGS;
9929
9930         klass = mono_class_from_mono_type (tb->type.type);
9931
9932         count = tb->generic_params ? mono_array_length (tb->generic_params) : 0;
9933
9934         if (klass->generic_container || (count == 0))
9935                 return;
9936
9937         g_assert (tb->generic_container && (tb->generic_container->owner.klass == klass));
9938
9939         klass->generic_container = mono_image_alloc0 (klass->image, sizeof (MonoGenericContainer));
9940
9941         klass->generic_container->owner.klass = klass;
9942         klass->generic_container->type_argc = count;
9943         klass->generic_container->type_params = mono_image_alloc0 (klass->image, sizeof (MonoGenericParamFull) * count);
9944
9945         klass->is_generic = 1;
9946
9947         for (i = 0; i < count; i++) {
9948                 MonoReflectionGenericParam *gparam = mono_array_get (tb->generic_params, gpointer, i);
9949                 MonoGenericParamFull *param = (MonoGenericParamFull *) mono_reflection_type_get_handle ((MonoReflectionType*)gparam)->data.generic_param;
9950                 klass->generic_container->type_params [i] = *param;
9951                 /*Make sure we are a diferent type instance */
9952                 klass->generic_container->type_params [i].param.owner = klass->generic_container;
9953                 klass->generic_container->type_params [i].info.pklass = NULL;
9954                 klass->generic_container->type_params [i].info.flags = gparam->attrs;
9955
9956                 g_assert (klass->generic_container->type_params [i].param.owner);
9957         }
9958
9959         klass->generic_container->context.class_inst = mono_get_shared_generic_inst (klass->generic_container);
9960 }
9961
9962 /*
9963  * mono_reflection_create_internal_class:
9964  * @tb: a TypeBuilder object
9965  *
9966  * Actually create the MonoClass that is associated with the TypeBuilder.
9967  */
9968 void
9969 mono_reflection_create_internal_class (MonoReflectionTypeBuilder *tb)
9970 {
9971         MonoClass *klass;
9972
9973         MONO_ARCH_SAVE_REGS;
9974
9975         klass = mono_class_from_mono_type (tb->type.type);
9976
9977         mono_loader_lock ();
9978         if (klass->enumtype && mono_class_enum_basetype (klass) == NULL) {
9979                 MonoReflectionFieldBuilder *fb;
9980                 MonoClass *ec;
9981                 MonoType *enum_basetype;
9982
9983                 g_assert (tb->fields != NULL);
9984                 g_assert (mono_array_length (tb->fields) >= 1);
9985
9986                 fb = mono_array_get (tb->fields, MonoReflectionFieldBuilder*, 0);
9987
9988                 if (!mono_type_is_valid_enum_basetype (mono_reflection_type_get_handle ((MonoReflectionType*)fb->type))) {
9989                         mono_loader_unlock ();
9990                         return;
9991                 }
9992
9993                 enum_basetype = mono_reflection_type_get_handle ((MonoReflectionType*)fb->type);
9994                 klass->element_class = mono_class_from_mono_type (enum_basetype);
9995                 if (!klass->element_class)
9996                         klass->element_class = mono_class_from_mono_type (enum_basetype);
9997
9998                 /*
9999                  * get the element_class from the current corlib.
10000                  */
10001                 ec = default_class_from_mono_type (enum_basetype);
10002                 klass->instance_size = ec->instance_size;
10003                 klass->size_inited = 1;
10004                 /* 
10005                  * this is almost safe to do with enums and it's needed to be able
10006                  * to create objects of the enum type (for use in SetConstant).
10007                  */
10008                 /* FIXME: Does this mean enums can't have method overrides ? */
10009                 mono_class_setup_vtable_general (klass, NULL, 0, NULL);
10010         }
10011         mono_loader_unlock ();
10012 }
10013
10014 static MonoMarshalSpec*
10015 mono_marshal_spec_from_builder (MonoImage *image, MonoAssembly *assembly,
10016                                                                 MonoReflectionMarshal *minfo)
10017 {
10018         MonoMarshalSpec *res;
10019
10020         res = image_g_new0 (image, MonoMarshalSpec, 1);
10021         res->native = minfo->type;
10022
10023         switch (minfo->type) {
10024         case MONO_NATIVE_LPARRAY:
10025                 res->data.array_data.elem_type = minfo->eltype;
10026                 if (minfo->has_size) {
10027                         res->data.array_data.param_num = minfo->param_num;
10028                         res->data.array_data.num_elem = minfo->count;
10029                         res->data.array_data.elem_mult = minfo->param_num == -1 ? 0 : 1;
10030                 }
10031                 else {
10032                         res->data.array_data.param_num = -1;
10033                         res->data.array_data.num_elem = -1;
10034                         res->data.array_data.elem_mult = -1;
10035                 }
10036                 break;
10037
10038         case MONO_NATIVE_BYVALTSTR:
10039         case MONO_NATIVE_BYVALARRAY:
10040                 res->data.array_data.num_elem = minfo->count;
10041                 break;
10042
10043         case MONO_NATIVE_CUSTOM:
10044                 if (minfo->marshaltyperef)
10045                         res->data.custom_data.custom_name =
10046                                 type_get_fully_qualified_name (mono_reflection_type_get_handle ((MonoReflectionType*)minfo->marshaltyperef));
10047                 if (minfo->mcookie)
10048                         res->data.custom_data.cookie = mono_string_to_utf8 (minfo->mcookie);
10049                 break;
10050
10051         default:
10052                 break;
10053         }
10054
10055         return res;
10056 }
10057 #endif /* !DISABLE_REFLECTION_EMIT */
10058
10059 MonoReflectionMarshalAsAttribute*
10060 mono_reflection_marshal_as_attribute_from_marshal_spec (MonoDomain *domain, MonoClass *klass,
10061                                                                                    MonoMarshalSpec *spec)
10062 {
10063         static MonoClass *System_Reflection_Emit_MarshalAsAttribute;
10064         MonoReflectionMarshalAsAttribute *minfo;
10065         MonoType *mtype;
10066
10067         if (!System_Reflection_Emit_MarshalAsAttribute) {
10068                 System_Reflection_Emit_MarshalAsAttribute = mono_class_from_name (
10069                    mono_defaults.corlib, "System.Runtime.InteropServices", "MarshalAsAttribute");
10070                 g_assert (System_Reflection_Emit_MarshalAsAttribute);
10071         }
10072
10073         minfo = (MonoReflectionMarshalAsAttribute*)mono_object_new (domain, System_Reflection_Emit_MarshalAsAttribute);
10074         minfo->utype = spec->native;
10075
10076         switch (minfo->utype) {
10077         case MONO_NATIVE_LPARRAY:
10078                 minfo->array_subtype = spec->data.array_data.elem_type;
10079                 minfo->size_const = spec->data.array_data.num_elem;
10080                 if (spec->data.array_data.param_num != -1)
10081                         minfo->size_param_index = spec->data.array_data.param_num;
10082                 break;
10083
10084         case MONO_NATIVE_BYVALTSTR:
10085         case MONO_NATIVE_BYVALARRAY:
10086                 minfo->size_const = spec->data.array_data.num_elem;
10087                 break;
10088
10089         case MONO_NATIVE_CUSTOM:
10090                 if (spec->data.custom_data.custom_name) {
10091                         mtype = mono_reflection_type_from_name (spec->data.custom_data.custom_name, klass->image);
10092                         if (mtype)
10093                                 MONO_OBJECT_SETREF (minfo, marshal_type_ref, mono_type_get_object (domain, mtype));
10094
10095                         MONO_OBJECT_SETREF (minfo, marshal_type, mono_string_new (domain, spec->data.custom_data.custom_name));
10096                 }
10097                 if (spec->data.custom_data.cookie)
10098                         MONO_OBJECT_SETREF (minfo, marshal_cookie, mono_string_new (domain, spec->data.custom_data.cookie));
10099                 break;
10100
10101         default:
10102                 break;
10103         }
10104
10105         return minfo;
10106 }
10107
10108 #ifndef DISABLE_REFLECTION_EMIT
10109 static MonoMethod*
10110 reflection_methodbuilder_to_mono_method (MonoClass *klass,
10111                                          ReflectionMethodBuilder *rmb,
10112                                          MonoMethodSignature *sig)
10113 {
10114         MonoError error;
10115         MonoMethod *m;
10116         MonoMethodWrapper *wrapperm;
10117         MonoMarshalSpec **specs;
10118         MonoReflectionMethodAux *method_aux;
10119         MonoImage *image;
10120         gboolean dynamic;
10121         int i;
10122
10123         mono_error_init (&error);
10124         /*
10125          * Methods created using a MethodBuilder should have their memory allocated
10126          * inside the image mempool, while dynamic methods should have their memory
10127          * malloc'd.
10128          */
10129         dynamic = rmb->refs != NULL;
10130         image = dynamic ? NULL : klass->image;
10131
10132         if (!dynamic)
10133                 g_assert (!klass->generic_class);
10134
10135         mono_loader_lock ();
10136
10137         if ((rmb->attrs & METHOD_ATTRIBUTE_PINVOKE_IMPL) ||
10138                         (rmb->iattrs & METHOD_IMPL_ATTRIBUTE_INTERNAL_CALL))
10139                 m = (MonoMethod *)image_g_new0 (image, MonoMethodPInvoke, 1);
10140         else
10141                 m = (MonoMethod *)image_g_new0 (image, MonoMethodWrapper, 1);
10142
10143         wrapperm = (MonoMethodWrapper*)m;
10144
10145         m->dynamic = dynamic;
10146         m->slot = -1;
10147         m->flags = rmb->attrs;
10148         m->iflags = rmb->iattrs;
10149         m->name = mono_string_to_utf8_image_ignore (image, rmb->name);
10150         m->klass = klass;
10151         m->signature = sig;
10152         m->sre_method = TRUE;
10153         m->skip_visibility = rmb->skip_visibility;
10154         if (rmb->table_idx)
10155                 m->token = MONO_TOKEN_METHOD_DEF | (*rmb->table_idx);
10156
10157         if (m->iflags & METHOD_IMPL_ATTRIBUTE_INTERNAL_CALL) {
10158                 if (klass == mono_defaults.string_class && !strcmp (m->name, ".ctor"))
10159                         m->string_ctor = 1;
10160
10161                 m->signature->pinvoke = 1;
10162         } else if (m->flags & METHOD_ATTRIBUTE_PINVOKE_IMPL) {
10163                 m->signature->pinvoke = 1;
10164
10165                 method_aux = image_g_new0 (image, MonoReflectionMethodAux, 1);
10166
10167                 method_aux->dllentry = rmb->dllentry ? mono_string_to_utf8_image (image, rmb->dllentry, &error) : image_strdup (image, m->name);
10168                 g_assert (mono_error_ok (&error));
10169                 method_aux->dll = mono_string_to_utf8_image (image, rmb->dll, &error);
10170                 g_assert (mono_error_ok (&error));
10171                 
10172                 ((MonoMethodPInvoke*)m)->piflags = (rmb->native_cc << 8) | (rmb->charset ? (rmb->charset - 1) * 2 : 0) | rmb->extra_flags;
10173
10174                 if (klass->image->dynamic)
10175                         g_hash_table_insert (((MonoDynamicImage*)klass->image)->method_aux_hash, m, method_aux);
10176
10177                 mono_loader_unlock ();
10178
10179                 return m;
10180         } else if (!(m->flags & METHOD_ATTRIBUTE_ABSTRACT) &&
10181                            !(m->iflags & METHOD_IMPL_ATTRIBUTE_RUNTIME)) {
10182                 MonoMethodHeader *header;
10183                 guint32 code_size;
10184                 gint32 max_stack, i;
10185                 gint32 num_locals = 0;
10186                 gint32 num_clauses = 0;
10187                 guint8 *code;
10188
10189                 if (rmb->ilgen) {
10190                         code = mono_array_addr (rmb->ilgen->code, guint8, 0);
10191                         code_size = rmb->ilgen->code_len;
10192                         max_stack = rmb->ilgen->max_stack;
10193                         num_locals = rmb->ilgen->locals ? mono_array_length (rmb->ilgen->locals) : 0;
10194                         if (rmb->ilgen->ex_handlers)
10195                                 num_clauses = method_count_clauses (rmb->ilgen);
10196                 } else {
10197                         if (rmb->code) {
10198                                 code = mono_array_addr (rmb->code, guint8, 0);
10199                                 code_size = mono_array_length (rmb->code);
10200                                 /* we probably need to run a verifier on the code... */
10201                                 max_stack = 8; 
10202                         }
10203                         else {
10204                                 code = NULL;
10205                                 code_size = 0;
10206                                 max_stack = 8;
10207                         }
10208                 }
10209
10210                 header = image_g_malloc0 (image, MONO_SIZEOF_METHOD_HEADER + num_locals * sizeof (MonoType*));
10211                 header->code_size = code_size;
10212                 header->code = image_g_malloc (image, code_size);
10213                 memcpy ((char*)header->code, code, code_size);
10214                 header->max_stack = max_stack;
10215                 header->init_locals = rmb->init_locals;
10216                 header->num_locals = num_locals;
10217
10218                 for (i = 0; i < num_locals; ++i) {
10219                         MonoReflectionLocalBuilder *lb = 
10220                                 mono_array_get (rmb->ilgen->locals, MonoReflectionLocalBuilder*, i);
10221
10222                         header->locals [i] = image_g_new0 (image, MonoType, 1);
10223                         memcpy (header->locals [i], mono_reflection_type_get_handle ((MonoReflectionType*)lb->type), MONO_SIZEOF_TYPE);
10224                 }
10225
10226                 header->num_clauses = num_clauses;
10227                 if (num_clauses) {
10228                         header->clauses = method_encode_clauses (image, (MonoDynamicImage*)klass->image,
10229                                  rmb->ilgen, num_clauses);
10230                 }
10231
10232                 wrapperm->header = header;
10233         }
10234
10235         if (rmb->generic_params) {
10236                 int count = mono_array_length (rmb->generic_params);
10237                 MonoGenericContainer *container = rmb->generic_container;
10238
10239                 g_assert (container);
10240
10241                 container->type_argc = count;
10242                 container->type_params = image_g_new0 (image, MonoGenericParamFull, count);
10243                 container->owner.method = m;
10244
10245                 m->is_generic = TRUE;
10246                 mono_method_set_generic_container (m, container);
10247
10248                 for (i = 0; i < count; i++) {
10249                         MonoReflectionGenericParam *gp =
10250                                 mono_array_get (rmb->generic_params, MonoReflectionGenericParam*, i);
10251                         MonoGenericParamFull *param = (MonoGenericParamFull *) mono_reflection_type_get_handle ((MonoReflectionType*)gp)->data.generic_param;
10252                         container->type_params [i] = *param;
10253                 }
10254
10255                 /*
10256                  * The method signature might have pointers to generic parameters that belong to other methods.
10257                  * This is a valid SRE case, but the resulting method signature must be encoded using the proper
10258                  * generic parameters.
10259                  */
10260                 for (i = 0; i < m->signature->param_count; ++i) {
10261                         MonoType *t = m->signature->params [i];
10262                         if (t->type == MONO_TYPE_MVAR) {
10263                                 MonoGenericParam *gparam =  t->data.generic_param;
10264                                 if (gparam->num < count) {
10265                                         m->signature->params [i] = mono_metadata_type_dup (image, m->signature->params [i]);
10266                                         m->signature->params [i]->data.generic_param = mono_generic_container_get_param (container, gparam->num);
10267                                 }
10268
10269                         }
10270                 }
10271
10272                 if (klass->generic_container) {
10273                         container->parent = klass->generic_container;
10274                         container->context.class_inst = klass->generic_container->context.class_inst;
10275                 }
10276                 container->context.method_inst = mono_get_shared_generic_inst (container);
10277         }
10278
10279         if (rmb->refs) {
10280                 MonoMethodWrapper *mw = (MonoMethodWrapper*)m;
10281                 int i;
10282                 void **data;
10283
10284                 m->wrapper_type = MONO_WRAPPER_DYNAMIC_METHOD;
10285
10286                 mw->method_data = data = image_g_new (image, gpointer, rmb->nrefs + 1);
10287                 data [0] = GUINT_TO_POINTER (rmb->nrefs);
10288                 for (i = 0; i < rmb->nrefs; ++i)
10289                         data [i + 1] = rmb->refs [i];
10290         }
10291
10292         method_aux = NULL;
10293
10294         /* Parameter info */
10295         if (rmb->pinfo) {
10296                 if (!method_aux)
10297                         method_aux = image_g_new0 (image, MonoReflectionMethodAux, 1);
10298                 method_aux->param_names = image_g_new0 (image, char *, mono_method_signature (m)->param_count + 1);
10299                 for (i = 0; i <= m->signature->param_count; ++i) {
10300                         MonoReflectionParamBuilder *pb;
10301                         if ((pb = mono_array_get (rmb->pinfo, MonoReflectionParamBuilder*, i))) {
10302                                 if ((i > 0) && (pb->attrs)) {
10303                                         /* Make a copy since it might point to a shared type structure */
10304                                         m->signature->params [i - 1] = mono_metadata_type_dup (klass->image, m->signature->params [i - 1]);
10305                                         m->signature->params [i - 1]->attrs = pb->attrs;
10306                                 }
10307
10308                                 if (pb->attrs & PARAM_ATTRIBUTE_HAS_DEFAULT) {
10309                                         MonoDynamicImage *assembly;
10310                                         guint32 idx, def_type, len;
10311                                         char *p;
10312                                         const char *p2;
10313
10314                                         if (!method_aux->param_defaults) {
10315                                                 method_aux->param_defaults = image_g_new0 (image, guint8*, m->signature->param_count + 1);
10316                                                 method_aux->param_default_types = image_g_new0 (image, guint32, m->signature->param_count + 1);
10317                                         }
10318                                         assembly = (MonoDynamicImage*)klass->image;
10319                                         idx = encode_constant (assembly, pb->def_value, &def_type);
10320                                         /* Copy the data from the blob since it might get realloc-ed */
10321                                         p = assembly->blob.data + idx;
10322                                         len = mono_metadata_decode_blob_size (p, &p2);
10323                                         len += p2 - p;
10324                                         method_aux->param_defaults [i] = image_g_malloc (image, len);
10325                                         method_aux->param_default_types [i] = def_type;
10326                                         memcpy ((gpointer)method_aux->param_defaults [i], p, len);
10327                                 }
10328
10329                                 if (pb->name) {
10330                                         method_aux->param_names [i] = mono_string_to_utf8_image (image, pb->name, &error);
10331                                         g_assert (mono_error_ok (&error));
10332                                 }
10333                                 if (pb->cattrs) {
10334                                         if (!method_aux->param_cattr)
10335                                                 method_aux->param_cattr = image_g_new0 (image, MonoCustomAttrInfo*, m->signature->param_count + 1);
10336                                         method_aux->param_cattr [i] = mono_custom_attrs_from_builders (image, klass->image, pb->cattrs);
10337                                 }
10338                         }
10339                 }
10340         }
10341
10342         /* Parameter marshalling */
10343         specs = NULL;
10344         if (rmb->pinfo)         
10345                 for (i = 0; i < mono_array_length (rmb->pinfo); ++i) {
10346                         MonoReflectionParamBuilder *pb;
10347                         if ((pb = mono_array_get (rmb->pinfo, MonoReflectionParamBuilder*, i))) {
10348                                 if (pb->marshal_info) {
10349                                         if (specs == NULL)
10350                                                 specs = image_g_new0 (image, MonoMarshalSpec*, sig->param_count + 1);
10351                                         specs [pb->position] = 
10352                                                 mono_marshal_spec_from_builder (image, klass->image->assembly, pb->marshal_info);
10353                                 }
10354                         }
10355                 }
10356         if (specs != NULL) {
10357                 if (!method_aux)
10358                         method_aux = image_g_new0 (image, MonoReflectionMethodAux, 1);
10359                 method_aux->param_marshall = specs;
10360         }
10361
10362         if (klass->image->dynamic && method_aux)
10363                 g_hash_table_insert (((MonoDynamicImage*)klass->image)->method_aux_hash, m, method_aux);
10364
10365         mono_loader_unlock ();
10366
10367         return m;
10368 }       
10369
10370 static MonoMethod*
10371 ctorbuilder_to_mono_method (MonoClass *klass, MonoReflectionCtorBuilder* mb)
10372 {
10373         ReflectionMethodBuilder rmb;
10374         MonoMethodSignature *sig;
10375
10376         mono_loader_lock ();
10377         sig = ctor_builder_to_signature (klass->image, mb);
10378         mono_loader_unlock ();
10379
10380         reflection_methodbuilder_from_ctor_builder (&rmb, mb);
10381
10382         mb->mhandle = reflection_methodbuilder_to_mono_method (klass, &rmb, sig);
10383         mono_save_custom_attrs (klass->image, mb->mhandle, mb->cattrs);
10384
10385         /* If we are in a generic class, we might be called multiple times from inflate_method */
10386         if (!((MonoDynamicImage*)(MonoDynamicImage*)klass->image)->save && !klass->generic_container) {
10387                 /* ilgen is no longer needed */
10388                 mb->ilgen = NULL;
10389         }
10390
10391         return mb->mhandle;
10392 }
10393
10394 static MonoMethod*
10395 methodbuilder_to_mono_method (MonoClass *klass, MonoReflectionMethodBuilder* mb)
10396 {
10397         ReflectionMethodBuilder rmb;
10398         MonoMethodSignature *sig;
10399
10400         mono_loader_lock ();
10401         sig = method_builder_to_signature (klass->image, mb);
10402         mono_loader_unlock ();
10403
10404         reflection_methodbuilder_from_method_builder (&rmb, mb);
10405
10406         mb->mhandle = reflection_methodbuilder_to_mono_method (klass, &rmb, sig);
10407         mono_save_custom_attrs (klass->image, mb->mhandle, mb->cattrs);
10408
10409         /* If we are in a generic class, we might be called multiple times from inflate_method */
10410         if (!((MonoDynamicImage*)(MonoDynamicImage*)klass->image)->save && !klass->generic_container) {
10411                 /* ilgen is no longer needed */
10412                 mb->ilgen = NULL;
10413         }
10414         return mb->mhandle;
10415 }
10416
10417 static MonoClassField*
10418 fieldbuilder_to_mono_class_field (MonoClass *klass, MonoReflectionFieldBuilder* fb)
10419 {
10420         MonoClassField *field;
10421         MonoType *custom;
10422         MonoError error;
10423
10424         field = g_new0 (MonoClassField, 1);
10425
10426         field->name = mono_string_to_utf8_image (klass->image, fb->name, &error);
10427         g_assert (mono_error_ok (&error));
10428         if (fb->attrs || fb->modreq || fb->modopt) {
10429                 field->type = mono_metadata_type_dup (NULL, mono_reflection_type_get_handle ((MonoReflectionType*)fb->type));
10430                 field->type->attrs = fb->attrs;
10431
10432                 g_assert (klass->image->dynamic);
10433                 custom = add_custom_modifiers ((MonoDynamicImage*)klass->image, field->type, fb->modreq, fb->modopt);
10434                 g_free (field->type);
10435                 field->type = mono_metadata_type_dup (klass->image, custom);
10436                 g_free (custom);
10437         } else {
10438                 field->type = mono_reflection_type_get_handle ((MonoReflectionType*)fb->type);
10439         }
10440         if (fb->offset != -1)
10441                 field->offset = fb->offset;
10442         field->parent = klass;
10443         mono_save_custom_attrs (klass->image, field, fb->cattrs);
10444
10445         // FIXME: Can't store fb->def_value/RVA, is it needed for field_on_insts ?
10446
10447         return field;
10448 }
10449 #endif
10450
10451 MonoType*
10452 mono_reflection_bind_generic_parameters (MonoReflectionType *type, int type_argc, MonoType **types)
10453 {
10454         MonoClass *klass;
10455         MonoReflectionTypeBuilder *tb = NULL;
10456         gboolean is_dynamic = FALSE;
10457         MonoDomain *domain;
10458         MonoClass *geninst;
10459
10460         mono_loader_lock ();
10461
10462         domain = mono_object_domain (type);
10463
10464         if (is_sre_type_builder (mono_object_class (type))) {
10465                 tb = (MonoReflectionTypeBuilder *) type;
10466
10467                 is_dynamic = TRUE;
10468         } else if (is_sre_generic_instance (mono_object_class (type))) {
10469                 MonoReflectionGenericClass *rgi = (MonoReflectionGenericClass *) type;
10470                 MonoReflectionType *gtd = rgi->generic_type;
10471
10472                 if (is_sre_type_builder (mono_object_class (gtd))) {
10473                         tb = (MonoReflectionTypeBuilder *)gtd;
10474                         is_dynamic = TRUE;
10475                 }
10476         }
10477
10478         /* FIXME: fix the CreateGenericParameters protocol to avoid the two stage setup of TypeBuilders */
10479         if (tb && tb->generic_container)
10480                 mono_reflection_create_generic_class (tb);
10481
10482         klass = mono_class_from_mono_type (mono_reflection_type_get_handle (type));
10483         if (!klass->generic_container) {
10484                 mono_loader_unlock ();
10485                 return NULL;
10486         }
10487
10488         if (klass->wastypebuilder) {
10489                 tb = (MonoReflectionTypeBuilder *) mono_class_get_ref_info (klass);
10490
10491                 is_dynamic = TRUE;
10492         }
10493
10494         mono_loader_unlock ();
10495
10496         geninst = mono_class_bind_generic_parameters (klass, type_argc, types, is_dynamic);
10497
10498         return &geninst->byval_arg;
10499 }
10500
10501 MonoClass*
10502 mono_class_bind_generic_parameters (MonoClass *klass, int type_argc, MonoType **types, gboolean is_dynamic)
10503 {
10504         MonoGenericClass *gclass;
10505         MonoGenericInst *inst;
10506
10507         g_assert (klass->generic_container);
10508
10509         inst = mono_metadata_get_generic_inst (type_argc, types);
10510         gclass = mono_metadata_lookup_generic_class (klass, inst, is_dynamic);
10511
10512         return mono_generic_class_get_class (gclass);
10513 }
10514
10515 MonoReflectionMethod*
10516 mono_reflection_bind_generic_method_parameters (MonoReflectionMethod *rmethod, MonoArray *types)
10517 {
10518         MonoClass *klass;
10519         MonoMethod *method, *inflated;
10520         MonoMethodInflated *imethod;
10521         MonoGenericContext tmp_context;
10522         MonoGenericInst *ginst;
10523         MonoType **type_argv;
10524         int count, i;
10525
10526         MONO_ARCH_SAVE_REGS;
10527
10528         /*FIXME but this no longer should happen*/
10529         if (!strcmp (rmethod->object.vtable->klass->name, "MethodBuilder")) {
10530 #ifndef DISABLE_REFLECTION_EMIT
10531                 MonoReflectionMethodBuilder *mb = NULL;
10532                 MonoReflectionTypeBuilder *tb;
10533                 MonoClass *klass;
10534
10535                 mb = (MonoReflectionMethodBuilder *) rmethod;
10536                 tb = (MonoReflectionTypeBuilder *) mb->type;
10537                 klass = mono_class_from_mono_type (mono_reflection_type_get_handle ((MonoReflectionType*)tb));
10538
10539                 method = methodbuilder_to_mono_method (klass, mb);
10540 #else
10541                 g_assert_not_reached ();
10542                 method = NULL;
10543 #endif
10544         } else {
10545                 method = rmethod->method;
10546         }
10547
10548         klass = method->klass;
10549
10550         if (method->is_inflated)
10551                 method = ((MonoMethodInflated *) method)->declaring;
10552
10553         count = mono_method_signature (method)->generic_param_count;
10554         if (count != mono_array_length (types))
10555                 return NULL;
10556
10557         type_argv = g_new0 (MonoType *, count);
10558         for (i = 0; i < count; i++) {
10559                 MonoReflectionType *garg = mono_array_get (types, gpointer, i);
10560                 type_argv [i] = mono_reflection_type_get_handle (garg);
10561         }
10562         ginst = mono_metadata_get_generic_inst (count, type_argv);
10563         g_free (type_argv);
10564
10565         tmp_context.class_inst = klass->generic_class ? klass->generic_class->context.class_inst : NULL;
10566         tmp_context.method_inst = ginst;
10567
10568         inflated = mono_class_inflate_generic_method (method, &tmp_context);
10569         imethod = (MonoMethodInflated *) inflated;
10570
10571         /*FIXME but I think this is no longer necessary*/
10572         if (method->klass->image->dynamic) {
10573                 MonoDynamicImage *image = (MonoDynamicImage*)method->klass->image;
10574                 /*
10575                  * This table maps metadata structures representing inflated methods/fields
10576                  * to the reflection objects representing their generic definitions.
10577                  */
10578                 mono_image_lock ((MonoImage*)image);
10579                 mono_g_hash_table_insert (image->generic_def_objects, imethod, rmethod);
10580                 mono_image_unlock ((MonoImage*)image);
10581         }
10582
10583         if (!mono_verifier_is_method_valid_generic_instantiation (inflated))
10584                 mono_raise_exception (mono_get_exception_argument ("typeArguments", "Invalid generic arguments"));
10585         
10586         return mono_method_get_object (mono_object_domain (rmethod), inflated, NULL);
10587 }
10588
10589 #ifndef DISABLE_REFLECTION_EMIT
10590
10591 static MonoMethod *
10592 inflate_mono_method (MonoClass *klass, MonoMethod *method, MonoObject *obj)
10593 {
10594         MonoMethodInflated *imethod;
10595         MonoGenericContext *context;
10596         int i;
10597
10598         /*
10599          * With generic code sharing the klass might not be inflated.
10600          * This can happen because classes inflated with their own
10601          * type arguments are "normalized" to the uninflated class.
10602          */
10603         if (!klass->generic_class)
10604                 return method;
10605
10606         context = mono_class_get_context (klass);
10607
10608         if (klass->method.count && klass->methods) {
10609                 /* Find the already created inflated method */
10610                 for (i = 0; i < klass->method.count; ++i) {
10611                         g_assert (klass->methods [i]->is_inflated);
10612                         if (((MonoMethodInflated*)klass->methods [i])->declaring == method)
10613                                 break;
10614                 }
10615                 g_assert (i < klass->method.count);
10616                 imethod = (MonoMethodInflated*)klass->methods [i];
10617         } else {
10618                 imethod = (MonoMethodInflated *) mono_class_inflate_generic_method_full (method, klass, context);
10619         }
10620
10621         if (method->is_generic && method->klass->image->dynamic) {
10622                 MonoDynamicImage *image = (MonoDynamicImage*)method->klass->image;
10623
10624                 mono_image_lock ((MonoImage*)image);
10625                 mono_g_hash_table_insert (image->generic_def_objects, imethod, obj);
10626                 mono_image_unlock ((MonoImage*)image);
10627         }
10628         return (MonoMethod *) imethod;
10629 }
10630
10631 static MonoMethod *
10632 inflate_method (MonoReflectionType *type, MonoObject *obj)
10633 {
10634         MonoMethod *method;
10635         MonoClass *gklass;
10636
10637         MonoClass *type_class = mono_object_class (type);
10638
10639         if (is_sre_generic_instance (type_class)) {
10640                 MonoReflectionGenericClass *mgc = (MonoReflectionGenericClass*)type;
10641                 gklass = mono_class_from_mono_type (mono_reflection_type_get_handle ((MonoReflectionType*)mgc->generic_type));
10642         } else if (is_sre_type_builder (type_class)) {
10643                 gklass = mono_class_from_mono_type (mono_reflection_type_get_handle (type));
10644         } else if (type->type) {
10645                 gklass = mono_class_from_mono_type (type->type);
10646                 gklass = mono_class_get_generic_type_definition (gklass);
10647         } else {
10648                 g_error ("Can't handle type %s", mono_type_get_full_name (mono_object_class (type)));
10649         }
10650
10651         if (!strcmp (obj->vtable->klass->name, "MethodBuilder"))
10652                 if (((MonoReflectionMethodBuilder*)obj)->mhandle)
10653                         method = ((MonoReflectionMethodBuilder*)obj)->mhandle;
10654                 else
10655                         method = methodbuilder_to_mono_method (gklass, (MonoReflectionMethodBuilder *) obj);
10656         else if (!strcmp (obj->vtable->klass->name, "ConstructorBuilder"))
10657                 method = ctorbuilder_to_mono_method (gklass, (MonoReflectionCtorBuilder *) obj);
10658         else if (!strcmp (obj->vtable->klass->name, "MonoMethod") || !strcmp (obj->vtable->klass->name, "MonoCMethod"))
10659                 method = ((MonoReflectionMethod *) obj)->method;
10660         else {
10661                 method = NULL; /* prevent compiler warning */
10662                 g_error ("can't handle type %s", obj->vtable->klass->name);
10663         }
10664
10665         return inflate_mono_method (mono_class_from_mono_type (mono_reflection_type_get_handle ((MonoReflectionType*)type)), method, obj);
10666 }
10667
10668 /*TODO avoid saving custom attrs for generic classes as it's enough to have them on the generic type definition.*/
10669 void
10670 mono_reflection_generic_class_initialize (MonoReflectionGenericClass *type, MonoArray *fields)
10671 {
10672         MonoGenericClass *gclass;
10673         MonoDynamicGenericClass *dgclass;
10674         MonoClass *klass, *gklass;
10675         MonoType *gtype;
10676         int i;
10677
10678         MONO_ARCH_SAVE_REGS;
10679
10680         gtype = mono_reflection_type_get_handle ((MonoReflectionType*)type);
10681         klass = mono_class_from_mono_type (gtype);
10682         g_assert (gtype->type == MONO_TYPE_GENERICINST);
10683         gclass = gtype->data.generic_class;
10684
10685         if (!gclass->is_dynamic)
10686                 return;
10687
10688         dgclass = (MonoDynamicGenericClass *) gclass;
10689
10690         if (dgclass->initialized)
10691                 return;
10692
10693         gklass = gclass->container_class;
10694         mono_class_init (gklass);
10695
10696         dgclass->count_fields = fields ? mono_array_length (fields) : 0;
10697
10698         dgclass->fields = mono_image_set_new0 (gclass->owner, MonoClassField, dgclass->count_fields);
10699         dgclass->field_objects = mono_image_set_new0 (gclass->owner, MonoObject*, dgclass->count_fields);
10700         dgclass->field_generic_types = mono_image_set_new0 (gclass->owner, MonoType*, dgclass->count_fields);
10701
10702         for (i = 0; i < dgclass->count_fields; i++) {
10703                 MonoObject *obj = mono_array_get (fields, gpointer, i);
10704                 MonoClassField *field, *inflated_field = NULL;
10705
10706                 if (!strcmp (obj->vtable->klass->name, "FieldBuilder"))
10707                         inflated_field = field = fieldbuilder_to_mono_class_field (klass, (MonoReflectionFieldBuilder *) obj);
10708                 else if (!strcmp (obj->vtable->klass->name, "MonoField"))
10709                         field = ((MonoReflectionField *) obj)->field;
10710                 else {
10711                         field = NULL; /* prevent compiler warning */
10712                         g_assert_not_reached ();
10713                 }
10714
10715                 dgclass->fields [i] = *field;
10716                 dgclass->fields [i].parent = klass;
10717                 dgclass->fields [i].type = mono_class_inflate_generic_type (
10718                         field->type, mono_generic_class_get_context ((MonoGenericClass *) dgclass));
10719                 dgclass->field_generic_types [i] = field->type;
10720                 MONO_GC_REGISTER_ROOT_IF_MOVING (dgclass->field_objects [i]);
10721                 dgclass->field_objects [i] = obj;
10722
10723                 if (inflated_field) {
10724                         g_free (inflated_field);
10725                 } else {
10726                         dgclass->fields [i].name = mono_image_set_strdup (gclass->owner, dgclass->fields [i].name);
10727                 }
10728         }
10729
10730         dgclass->initialized = TRUE;
10731 }
10732
10733 void
10734 mono_reflection_free_dynamic_generic_class (MonoGenericClass *gclass)
10735 {
10736         MonoDynamicGenericClass *dgclass;
10737         int i;
10738
10739         g_assert (gclass->is_dynamic);
10740
10741         dgclass = (MonoDynamicGenericClass *)gclass;
10742
10743         for (i = 0; i < dgclass->count_fields; ++i) {
10744                 MonoClassField *field = dgclass->fields + i;
10745                 mono_metadata_free_type (field->type);
10746                 MONO_GC_UNREGISTER_ROOT_IF_MOVING (dgclass->field_objects [i]);
10747         }
10748 }
10749
10750 static void
10751 fix_partial_generic_class (MonoClass *klass)
10752 {
10753         MonoClass *gklass = klass->generic_class->container_class;
10754         MonoDynamicGenericClass *dgclass;
10755         int i;
10756
10757         if (klass->wastypebuilder)
10758                 return;
10759
10760         dgclass = (MonoDynamicGenericClass *)  klass->generic_class;
10761         if (klass->parent != gklass->parent) {
10762                 MonoError error;
10763                 MonoType *parent_type = mono_class_inflate_generic_type_checked (&gklass->parent->byval_arg, &klass->generic_class->context, &error);
10764                 if (mono_error_ok (&error)) {
10765                         MonoClass *parent = mono_class_from_mono_type (parent_type);
10766                         mono_metadata_free_type (parent_type);
10767                         if (parent != klass->parent) {
10768                                 /*fool mono_class_setup_parent*/
10769                                 klass->supertypes = NULL;
10770                                 mono_class_setup_parent (klass, parent);
10771                         }
10772                 } else {
10773                         mono_class_set_failure (klass, MONO_EXCEPTION_TYPE_LOAD, NULL);
10774                         mono_error_cleanup (&error);
10775                         if (gklass->wastypebuilder)
10776                                 klass->wastypebuilder = TRUE;
10777                         return;
10778                 }
10779         }
10780
10781         if (!dgclass->initialized)
10782                 return;
10783
10784         if (klass->method.count != gklass->method.count) {
10785                 klass->method.count = gklass->method.count;
10786                 klass->methods = mono_image_alloc (klass->image, sizeof (MonoMethod*) * (klass->method.count + 1));
10787
10788                 for (i = 0; i < klass->method.count; i++) {
10789                         klass->methods [i] = mono_class_inflate_generic_method_full (
10790                                 gklass->methods [i], klass, mono_class_get_context (klass));
10791                 }
10792         }
10793
10794         if (klass->interface_count && klass->interface_count != gklass->interface_count) {
10795                 klass->interface_count = gklass->interface_count;
10796                 klass->interfaces = mono_image_alloc (klass->image, sizeof (MonoClass*) * gklass->interface_count);
10797                 klass->interfaces_packed = NULL; /*make setup_interface_offsets happy*/
10798
10799                 for (i = 0; i < gklass->interface_count; ++i) {
10800                         MonoType *iface_type = mono_class_inflate_generic_type (&gklass->interfaces [i]->byval_arg, mono_class_get_context (klass));
10801                         klass->interfaces [i] = mono_class_from_mono_type (iface_type);
10802                         mono_metadata_free_type (iface_type);
10803
10804                         ensure_runtime_vtable (klass->interfaces [i]);
10805                 }
10806                 klass->interfaces_inited = 1;
10807         }
10808
10809         if (klass->field.count != gklass->field.count) {
10810                 klass->field.count = gklass->field.count;
10811                 klass->fields = image_g_new0 (klass->image, MonoClassField, klass->field.count);
10812
10813                 for (i = 0; i < klass->field.count; i++) {
10814                         klass->fields [i] = gklass->fields [i];
10815                         klass->fields [i].parent = klass;
10816                         klass->fields [i].type = mono_class_inflate_generic_type (gklass->fields [i].type, mono_class_get_context (klass));
10817                 }
10818         }
10819
10820         /*We can only finish with this klass once it's parent has as well*/
10821         if (gklass->wastypebuilder)
10822                 klass->wastypebuilder = TRUE;
10823         return;
10824 }
10825
10826 static void
10827 ensure_generic_class_runtime_vtable (MonoClass *klass)
10828 {
10829         MonoClass *gklass = klass->generic_class->container_class;
10830
10831         ensure_runtime_vtable (gklass); 
10832
10833         fix_partial_generic_class (klass);
10834 }
10835
10836 static void
10837 ensure_runtime_vtable (MonoClass *klass)
10838 {
10839         MonoReflectionTypeBuilder *tb = mono_class_get_ref_info (klass);
10840         int i, num, j;
10841
10842         if (!klass->image->dynamic || (!tb && !klass->generic_class) || klass->wastypebuilder)
10843                 return;
10844         if (klass->parent)
10845                 ensure_runtime_vtable (klass->parent);
10846
10847         if (tb) {
10848                 num = tb->ctors? mono_array_length (tb->ctors): 0;
10849                 num += tb->num_methods;
10850                 klass->method.count = num;
10851                 klass->methods = mono_image_alloc (klass->image, sizeof (MonoMethod*) * num);
10852                 num = tb->ctors? mono_array_length (tb->ctors): 0;
10853                 for (i = 0; i < num; ++i)
10854                         klass->methods [i] = ctorbuilder_to_mono_method (klass, mono_array_get (tb->ctors, MonoReflectionCtorBuilder*, i));
10855                 num = tb->num_methods;
10856                 j = i;
10857                 for (i = 0; i < num; ++i)
10858                         klass->methods [j++] = methodbuilder_to_mono_method (klass, mono_array_get (tb->methods, MonoReflectionMethodBuilder*, i));
10859         
10860                 if (tb->interfaces) {
10861                         klass->interface_count = mono_array_length (tb->interfaces);
10862                         klass->interfaces = mono_image_alloc (klass->image, sizeof (MonoClass*) * klass->interface_count);
10863                         for (i = 0; i < klass->interface_count; ++i) {
10864                                 MonoType *iface = mono_type_array_get_and_resolve (tb->interfaces, i);
10865                                 klass->interfaces [i] = mono_class_from_mono_type (iface);
10866                                 ensure_runtime_vtable (klass->interfaces [i]);
10867                         }
10868                         klass->interfaces_inited = 1;
10869                 }
10870         } else if (klass->generic_class){
10871                 ensure_generic_class_runtime_vtable (klass);
10872         }
10873
10874         if (klass->flags & TYPE_ATTRIBUTE_INTERFACE) {
10875                 int slot_num = 0;
10876                 for (i = 0; i < klass->method.count; ++i) {
10877                         MonoMethod *im = klass->methods [i];
10878                         if (!(im->flags & METHOD_ATTRIBUTE_STATIC))
10879                                 im->slot = slot_num++;
10880                 }
10881                 
10882                 klass->interfaces_packed = NULL; /*make setup_interface_offsets happy*/
10883                 mono_class_setup_interface_offsets (klass);
10884                 mono_class_setup_interface_id (klass);
10885         }
10886
10887         /*
10888          * The generic vtable is needed even if image->run is not set since some
10889          * runtime code like ves_icall_Type_GetMethodsByName depends on 
10890          * method->slot being defined.
10891          */
10892
10893         /* 
10894          * tb->methods could not be freed since it is used for determining 
10895          * overrides during dynamic vtable construction.
10896          */
10897 }
10898
10899 static MonoMethod*
10900 mono_reflection_method_get_handle (MonoObject *method)
10901 {
10902         MonoClass *class = mono_object_class (method);
10903         if (is_sr_mono_method (class) || is_sr_mono_generic_method (class)) {
10904                 MonoReflectionMethod *sr_method = (MonoReflectionMethod*)method;
10905                 return sr_method->method;
10906         }
10907         if (is_sre_method_builder (class)) {
10908                 MonoReflectionMethodBuilder *mb = (MonoReflectionMethodBuilder*)method;
10909                 return mb->mhandle;
10910         }
10911         if (is_sre_method_on_tb_inst (class)) {
10912                 MonoReflectionMethodOnTypeBuilderInst *m = (MonoReflectionMethodOnTypeBuilderInst*)method;
10913                 MonoMethod *result;
10914                 /*FIXME move this to a proper method and unify with resolve_object*/
10915                 if (m->method_args) {
10916                         result = mono_reflection_method_on_tb_inst_get_handle (m);
10917                 } else {
10918                         MonoType *type = mono_reflection_type_get_handle ((MonoReflectionType*)m->inst);
10919                         MonoClass *inflated_klass = mono_class_from_mono_type (type);
10920                         MonoMethod *mono_method;
10921
10922                         if (is_sre_method_builder (mono_object_class (m->mb)))
10923                                 mono_method = ((MonoReflectionMethodBuilder *)m->mb)->mhandle;
10924                         else if (is_sr_mono_method (mono_object_class (m->mb)))
10925                                 mono_method = ((MonoReflectionMethod *)m->mb)->method;
10926                         else
10927                                 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)));
10928
10929                         result = inflate_mono_method (inflated_klass, mono_method, (MonoObject*)m->mb);
10930                 }
10931                 return result;
10932         }
10933
10934         g_error ("Can't handle methods of type %s:%s", class->name_space, class->name);
10935         return NULL;
10936 }
10937
10938 void
10939 mono_reflection_get_dynamic_overrides (MonoClass *klass, MonoMethod ***overrides, int *num_overrides)
10940 {
10941         MonoReflectionTypeBuilder *tb;
10942         int i, j, onum;
10943         MonoReflectionMethod *m;
10944
10945         *overrides = NULL;
10946         *num_overrides = 0;
10947
10948         g_assert (klass->image->dynamic);
10949
10950         if (!mono_class_get_ref_info (klass))
10951                 return;
10952
10953         g_assert (strcmp (((MonoObject*)mono_class_get_ref_info (klass))->vtable->klass->name, "TypeBuilder") == 0);
10954
10955         tb = (MonoReflectionTypeBuilder*)mono_class_get_ref_info (klass);
10956
10957         onum = 0;
10958         if (tb->methods) {
10959                 for (i = 0; i < tb->num_methods; ++i) {
10960                         MonoReflectionMethodBuilder *mb = 
10961                                 mono_array_get (tb->methods, MonoReflectionMethodBuilder*, i);
10962                         if (mb->override_methods)
10963                                 onum += mono_array_length (mb->override_methods);
10964                 }
10965         }
10966
10967         if (onum) {
10968                 *overrides = g_new0 (MonoMethod*, onum * 2);
10969
10970                 onum = 0;
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                                 for (j = 0; j < mono_array_length (mb->override_methods); ++j) {
10976                                         m = mono_array_get (mb->override_methods, MonoReflectionMethod*, j);
10977
10978                                         (*overrides) [onum * 2] = mono_reflection_method_get_handle ((MonoObject*)m);
10979                                         (*overrides) [onum * 2 + 1] = mb->mhandle;
10980
10981                                         g_assert (mb->mhandle);
10982
10983                                         onum ++;
10984                                 }
10985                         }
10986                 }
10987         }
10988
10989         *num_overrides = onum;
10990 }
10991
10992 static void
10993 typebuilder_setup_fields (MonoClass *klass, MonoError *error)
10994 {
10995         MonoReflectionTypeBuilder *tb = mono_class_get_ref_info (klass);
10996         MonoReflectionFieldBuilder *fb;
10997         MonoClassField *field;
10998         MonoImage *image = klass->image;
10999         const char *p, *p2;
11000         int i;
11001         guint32 len, idx, real_size = 0;
11002
11003         klass->field.count = tb->num_fields;
11004         klass->field.first = 0;
11005
11006         mono_error_init (error);
11007
11008         if (tb->class_size) {
11009                 if ((tb->packing_size & 0xfffffff0) != 0) {
11010                         char *err_msg = g_strdup_printf ("Could not load struct '%s' with packing size %d >= 16", klass->name, tb->packing_size);
11011                         mono_class_set_failure (klass, MONO_EXCEPTION_TYPE_LOAD, err_msg);
11012                         return;
11013                 }
11014                 klass->packing_size = tb->packing_size;
11015                 real_size = klass->instance_size + tb->class_size;
11016         }
11017
11018         if (!klass->field.count) {
11019                 klass->instance_size = MAX (klass->instance_size, real_size);
11020                 return;
11021         }
11022         
11023         klass->fields = image_g_new0 (image, MonoClassField, klass->field.count);
11024         mono_class_alloc_ext (klass);
11025         klass->ext->field_def_values = image_g_new0 (image, MonoFieldDefaultValue, klass->field.count);
11026         /*
11027         This is, guess what, a hack.
11028         The issue is that the runtime doesn't know how to setup the fields of a typebuider and crash.
11029         On the static path no field class is resolved, only types are built. This is the right thing to do
11030         but we suck.
11031         Setting size_inited is harmless because we're doing the same job as mono_class_setup_fields anyway.
11032         */
11033         klass->size_inited = 1;
11034
11035         for (i = 0; i < klass->field.count; ++i) {
11036                 MonoArray *rva_data;
11037                 fb = mono_array_get (tb->fields, gpointer, i);
11038                 field = &klass->fields [i];
11039                 field->name = mono_string_to_utf8_image (image, fb->name, error);
11040                 if (!mono_error_ok (error))
11041                         return;
11042                 if (fb->attrs) {
11043                         field->type = mono_metadata_type_dup (klass->image, mono_reflection_type_get_handle ((MonoReflectionType*)fb->type));
11044                         field->type->attrs = fb->attrs;
11045                 } else {
11046                         field->type = mono_reflection_type_get_handle ((MonoReflectionType*)fb->type);
11047                 }
11048
11049                 if ((fb->attrs & FIELD_ATTRIBUTE_HAS_FIELD_RVA) && (rva_data = fb->rva_data)) {
11050                         char *base = mono_array_addr (rva_data, char, 0);
11051                         size_t size = mono_array_length (rva_data);
11052                         char *data = mono_image_alloc (klass->image, size);
11053                         memcpy (data, base, size);
11054                         klass->ext->field_def_values [i].data = data;
11055                 }
11056                 if (fb->offset != -1)
11057                         field->offset = fb->offset;
11058                 field->parent = klass;
11059                 fb->handle = field;
11060                 mono_save_custom_attrs (klass->image, field, fb->cattrs);
11061
11062                 if (klass->enumtype && !(field->type->attrs & FIELD_ATTRIBUTE_STATIC)) {
11063                         klass->cast_class = klass->element_class = mono_class_from_mono_type (field->type);
11064                 }
11065                 if (fb->def_value) {
11066                         MonoDynamicImage *assembly = (MonoDynamicImage*)klass->image;
11067                         field->type->attrs |= FIELD_ATTRIBUTE_HAS_DEFAULT;
11068                         idx = encode_constant (assembly, fb->def_value, &klass->ext->field_def_values [i].def_type);
11069                         /* Copy the data from the blob since it might get realloc-ed */
11070                         p = assembly->blob.data + idx;
11071                         len = mono_metadata_decode_blob_size (p, &p2);
11072                         len += p2 - p;
11073                         klass->ext->field_def_values [i].data = mono_image_alloc (image, len);
11074                         memcpy ((gpointer)klass->ext->field_def_values [i].data, p, len);
11075                 }
11076         }
11077
11078         klass->instance_size = MAX (klass->instance_size, real_size);
11079         mono_class_layout_fields (klass);
11080 }
11081
11082 static void
11083 typebuilder_setup_properties (MonoClass *klass, MonoError *error)
11084 {
11085         MonoReflectionTypeBuilder *tb = mono_class_get_ref_info (klass);
11086         MonoReflectionPropertyBuilder *pb;
11087         MonoImage *image = klass->image;
11088         MonoProperty *properties;
11089         int i;
11090
11091         mono_error_init (error);
11092
11093         if (!klass->ext)
11094                 klass->ext = image_g_new0 (image, MonoClassExt, 1);
11095
11096         klass->ext->property.count = tb->properties ? mono_array_length (tb->properties) : 0;
11097         klass->ext->property.first = 0;
11098
11099         properties = image_g_new0 (image, MonoProperty, klass->ext->property.count);
11100         klass->ext->properties = properties;
11101         for (i = 0; i < klass->ext->property.count; ++i) {
11102                 pb = mono_array_get (tb->properties, MonoReflectionPropertyBuilder*, i);
11103                 properties [i].parent = klass;
11104                 properties [i].attrs = pb->attrs;
11105                 properties [i].name = mono_string_to_utf8_image (image, pb->name, error);
11106                 if (!mono_error_ok (error))
11107                         return;
11108                 if (pb->get_method)
11109                         properties [i].get = pb->get_method->mhandle;
11110                 if (pb->set_method)
11111                         properties [i].set = pb->set_method->mhandle;
11112
11113                 mono_save_custom_attrs (klass->image, &properties [i], pb->cattrs);
11114                 if (pb->def_value) {
11115                         guint32 len, idx;
11116                         const char *p, *p2;
11117                         MonoDynamicImage *assembly = (MonoDynamicImage*)klass->image;
11118                         if (!klass->ext->prop_def_values)
11119                                 klass->ext->prop_def_values = image_g_new0 (image, MonoFieldDefaultValue, klass->ext->property.count);
11120                         properties [i].attrs |= PROPERTY_ATTRIBUTE_HAS_DEFAULT;
11121                         idx = encode_constant (assembly, pb->def_value, &klass->ext->prop_def_values [i].def_type);
11122                         /* Copy the data from the blob since it might get realloc-ed */
11123                         p = assembly->blob.data + idx;
11124                         len = mono_metadata_decode_blob_size (p, &p2);
11125                         len += p2 - p;
11126                         klass->ext->prop_def_values [i].data = mono_image_alloc (image, len);
11127                         memcpy ((gpointer)klass->ext->prop_def_values [i].data, p, len);
11128                 }
11129         }
11130 }
11131
11132 MonoReflectionEvent *
11133 mono_reflection_event_builder_get_event_info (MonoReflectionTypeBuilder *tb, MonoReflectionEventBuilder *eb)
11134 {
11135         MonoEvent *event = g_new0 (MonoEvent, 1);
11136         MonoClass *klass;
11137
11138         klass = mono_class_from_mono_type (mono_reflection_type_get_handle ((MonoReflectionType*)tb));
11139
11140         event->parent = klass;
11141         event->attrs = eb->attrs;
11142         event->name = mono_string_to_utf8 (eb->name);
11143         if (eb->add_method)
11144                 event->add = eb->add_method->mhandle;
11145         if (eb->remove_method)
11146                 event->remove = eb->remove_method->mhandle;
11147         if (eb->raise_method)
11148                 event->raise = eb->raise_method->mhandle;
11149
11150 #ifndef MONO_SMALL_CONFIG
11151         if (eb->other_methods) {
11152                 int j;
11153                 event->other = g_new0 (MonoMethod*, mono_array_length (eb->other_methods) + 1);
11154                 for (j = 0; j < mono_array_length (eb->other_methods); ++j) {
11155                         MonoReflectionMethodBuilder *mb = 
11156                                 mono_array_get (eb->other_methods,
11157                                                 MonoReflectionMethodBuilder*, j);
11158                         event->other [j] = mb->mhandle;
11159                 }
11160         }
11161 #endif
11162
11163         return mono_event_get_object (mono_object_domain (tb), klass, event);
11164 }
11165
11166 static void
11167 typebuilder_setup_events (MonoClass *klass, MonoError *error)
11168 {
11169         MonoReflectionTypeBuilder *tb = mono_class_get_ref_info (klass);
11170         MonoReflectionEventBuilder *eb;
11171         MonoImage *image = klass->image;
11172         MonoEvent *events;
11173         int i;
11174
11175         mono_error_init (error);
11176
11177         if (!klass->ext)
11178                 klass->ext = image_g_new0 (image, MonoClassExt, 1);
11179
11180         klass->ext->event.count = tb->events ? mono_array_length (tb->events) : 0;
11181         klass->ext->event.first = 0;
11182
11183         events = image_g_new0 (image, MonoEvent, klass->ext->event.count);
11184         klass->ext->events = events;
11185         for (i = 0; i < klass->ext->event.count; ++i) {
11186                 eb = mono_array_get (tb->events, MonoReflectionEventBuilder*, i);
11187                 events [i].parent = klass;
11188                 events [i].attrs = eb->attrs;
11189                 events [i].name = mono_string_to_utf8_image (image, eb->name, error);
11190                 if (!mono_error_ok (error))
11191                         return;
11192                 if (eb->add_method)
11193                         events [i].add = eb->add_method->mhandle;
11194                 if (eb->remove_method)
11195                         events [i].remove = eb->remove_method->mhandle;
11196                 if (eb->raise_method)
11197                         events [i].raise = eb->raise_method->mhandle;
11198
11199 #ifndef MONO_SMALL_CONFIG
11200                 if (eb->other_methods) {
11201                         int j;
11202                         events [i].other = image_g_new0 (image, MonoMethod*, mono_array_length (eb->other_methods) + 1);
11203                         for (j = 0; j < mono_array_length (eb->other_methods); ++j) {
11204                                 MonoReflectionMethodBuilder *mb = 
11205                                         mono_array_get (eb->other_methods,
11206                                                                         MonoReflectionMethodBuilder*, j);
11207                                 events [i].other [j] = mb->mhandle;
11208                         }
11209                 }
11210 #endif
11211                 mono_save_custom_attrs (klass->image, &events [i], eb->cattrs);
11212         }
11213 }
11214
11215 static gboolean
11216 remove_instantiations_of_and_ensure_contents (gpointer key,
11217                                                   gpointer value,
11218                                                   gpointer user_data)
11219 {
11220         MonoType *type = (MonoType*)key;
11221         MonoClass *klass = (MonoClass*)user_data;
11222
11223         if ((type->type == MONO_TYPE_GENERICINST) && (type->data.generic_class->container_class == klass)) {
11224                 fix_partial_generic_class (mono_class_from_mono_type (type)); //Ensure it's safe to use it.
11225                 return TRUE;
11226         } else
11227                 return FALSE;
11228 }
11229
11230 static void
11231 check_array_for_usertypes (MonoArray *arr)
11232 {
11233         int i;
11234
11235         if (!arr)
11236                 return;
11237
11238         for (i = 0; i < mono_array_length (arr); ++i)
11239                 RESOLVE_ARRAY_TYPE_ELEMENT (arr, i);
11240 }
11241
11242 MonoReflectionType*
11243 mono_reflection_create_runtime_class (MonoReflectionTypeBuilder *tb)
11244 {
11245         MonoError error;
11246         MonoClass *klass;
11247         MonoDomain* domain;
11248         MonoReflectionType* res;
11249         int i, j;
11250
11251         MONO_ARCH_SAVE_REGS;
11252
11253         domain = mono_object_domain (tb);
11254         klass = mono_class_from_mono_type (tb->type.type);
11255
11256         /*
11257          * Check for user defined Type subclasses.
11258          */
11259         RESOLVE_TYPE (tb->parent);
11260         check_array_for_usertypes (tb->interfaces);
11261         if (tb->fields) {
11262                 for (i = 0; i < mono_array_length (tb->fields); ++i) {
11263                         MonoReflectionFieldBuilder *fb = mono_array_get (tb->fields, gpointer, i);
11264                         if (fb) {
11265                                 RESOLVE_TYPE (fb->type);
11266                                 check_array_for_usertypes (fb->modreq);
11267                                 check_array_for_usertypes (fb->modopt);
11268                                 if (fb->marshal_info && fb->marshal_info->marshaltyperef)
11269                                         RESOLVE_TYPE (fb->marshal_info->marshaltyperef);
11270                         }
11271                 }
11272         }
11273         if (tb->methods) {
11274                 for (i = 0; i < mono_array_length (tb->methods); ++i) {
11275                         MonoReflectionMethodBuilder *mb = mono_array_get (tb->methods, gpointer, i);
11276                         if (mb) {
11277                                 RESOLVE_TYPE (mb->rtype);
11278                                 check_array_for_usertypes (mb->return_modreq);
11279                                 check_array_for_usertypes (mb->return_modopt);
11280                                 check_array_for_usertypes (mb->parameters);
11281                                 if (mb->param_modreq)
11282                                         for (j = 0; j < mono_array_length (mb->param_modreq); ++j)
11283                                                 check_array_for_usertypes (mono_array_get (mb->param_modreq, MonoArray*, j));
11284                                 if (mb->param_modopt)
11285                                         for (j = 0; j < mono_array_length (mb->param_modopt); ++j)
11286                                                 check_array_for_usertypes (mono_array_get (mb->param_modopt, MonoArray*, j));
11287                         }
11288                 }
11289         }
11290         if (tb->ctors) {
11291                 for (i = 0; i < mono_array_length (tb->ctors); ++i) {
11292                         MonoReflectionCtorBuilder *mb = mono_array_get (tb->ctors, gpointer, i);
11293                         if (mb) {
11294                                 check_array_for_usertypes (mb->parameters);
11295                                 if (mb->param_modreq)
11296                                         for (j = 0; j < mono_array_length (mb->param_modreq); ++j)
11297                                                 check_array_for_usertypes (mono_array_get (mb->param_modreq, MonoArray*, j));
11298                                 if (mb->param_modopt)
11299                                         for (j = 0; j < mono_array_length (mb->param_modopt); ++j)
11300                                                 check_array_for_usertypes (mono_array_get (mb->param_modopt, MonoArray*, j));
11301                         }
11302                 }
11303         }
11304
11305         mono_save_custom_attrs (klass->image, klass, tb->cattrs);
11306
11307         /* 
11308          * we need to lock the domain because the lock will be taken inside
11309          * So, we need to keep the locking order correct.
11310          */
11311         mono_loader_lock ();
11312         mono_domain_lock (domain);
11313         if (klass->wastypebuilder) {
11314                 mono_domain_unlock (domain);
11315                 mono_loader_unlock ();
11316                 return mono_type_get_object (mono_object_domain (tb), &klass->byval_arg);
11317         }
11318         /*
11319          * Fields to set in klass:
11320          * the various flags: delegate/unicode/contextbound etc.
11321          */
11322         klass->flags = tb->attrs;
11323         klass->has_cctor = 1;
11324         klass->has_finalize = 1;
11325         klass->has_finalize_inited = 1;
11326
11327         /* fool mono_class_setup_parent */
11328         klass->supertypes = NULL;
11329         mono_class_setup_parent (klass, klass->parent);
11330         mono_class_setup_mono_type (klass);
11331
11332 #if 0
11333         if (!((MonoDynamicImage*)klass->image)->run) {
11334                 if (klass->generic_container) {
11335                         /* FIXME: The code below can't handle generic classes */
11336                         klass->wastypebuilder = TRUE;
11337                         mono_loader_unlock ();
11338                         mono_domain_unlock (domain);
11339                         return mono_type_get_object (mono_object_domain (tb), &klass->byval_arg);
11340                 }
11341         }
11342 #endif
11343
11344         /* enums are done right away */
11345         if (!klass->enumtype)
11346                 ensure_runtime_vtable (klass);
11347
11348         if (tb->subtypes) {
11349                 for (i = 0; i < mono_array_length (tb->subtypes); ++i) {
11350                         MonoReflectionTypeBuilder *subtb = mono_array_get (tb->subtypes, MonoReflectionTypeBuilder*, i);
11351                         mono_class_alloc_ext (klass);
11352                         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)));
11353                 }
11354         }
11355
11356         klass->nested_classes_inited = TRUE;
11357
11358         /* fields and object layout */
11359         if (klass->parent) {
11360                 if (!klass->parent->size_inited)
11361                         mono_class_init (klass->parent);
11362                 klass->instance_size = klass->parent->instance_size;
11363                 klass->sizes.class_size = 0;
11364                 klass->min_align = klass->parent->min_align;
11365                 /* if the type has no fields we won't call the field_setup
11366                  * routine which sets up klass->has_references.
11367                  */
11368                 klass->has_references |= klass->parent->has_references;
11369         } else {
11370                 klass->instance_size = sizeof (MonoObject);
11371                 klass->min_align = 1;
11372         }
11373
11374         /* FIXME: handle packing_size and instance_size */
11375         typebuilder_setup_fields (klass, &error);
11376         if (!mono_error_ok (&error))
11377                 goto failure;
11378         typebuilder_setup_properties (klass, &error);
11379         if (!mono_error_ok (&error))
11380                 goto failure;
11381
11382         typebuilder_setup_events (klass, &error);
11383         if (!mono_error_ok (&error))
11384                 goto failure;
11385
11386         klass->wastypebuilder = TRUE;
11387
11388         /* 
11389          * If we are a generic TypeBuilder, there might be instantiations in the type cache
11390          * which have type System.Reflection.MonoGenericClass, but after the type is created, 
11391          * we want to return normal System.MonoType objects, so clear these out from the cache.
11392          *
11393          * Together with this we must ensure the contents of all instances to match the created type.
11394          */
11395         if (domain->type_hash && klass->generic_container)
11396                 mono_g_hash_table_foreach_remove (domain->type_hash, remove_instantiations_of_and_ensure_contents, klass);
11397
11398         mono_domain_unlock (domain);
11399         mono_loader_unlock ();
11400
11401         if (klass->enumtype && !mono_class_is_valid_enum (klass)) {
11402                 mono_class_set_failure (klass, MONO_EXCEPTION_TYPE_LOAD, NULL);
11403                 mono_raise_exception (mono_get_exception_type_load (tb->name, NULL));
11404         }
11405
11406         res = mono_type_get_object (mono_object_domain (tb), &klass->byval_arg);
11407         g_assert (res != (MonoReflectionType*)tb);
11408
11409         return res;
11410
11411 failure:
11412         mono_class_set_failure (klass, MONO_EXCEPTION_TYPE_LOAD, NULL);
11413         klass->wastypebuilder = TRUE;
11414         mono_domain_unlock (domain);
11415         mono_loader_unlock ();
11416         mono_error_raise_exception (&error);
11417         return NULL;
11418 }
11419
11420 void
11421 mono_reflection_initialize_generic_parameter (MonoReflectionGenericParam *gparam)
11422 {
11423         MonoGenericParamFull *param;
11424         MonoImage *image;
11425         MonoClass *pklass;
11426         MonoError error;
11427
11428         MONO_ARCH_SAVE_REGS;
11429
11430         image = &gparam->tbuilder->module->dynamic_image->image;
11431
11432         param = mono_image_new0 (image, MonoGenericParamFull, 1);
11433
11434         param->info.name = mono_string_to_utf8_image (image, gparam->name, &error);
11435         g_assert (mono_error_ok (&error));
11436         param->param.num = gparam->index;
11437
11438         if (gparam->mbuilder) {
11439                 if (!gparam->mbuilder->generic_container) {
11440                         MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder *)gparam->mbuilder->type;
11441                         MonoClass *klass = mono_class_from_mono_type (mono_reflection_type_get_handle ((MonoReflectionType*)tb));
11442                         gparam->mbuilder->generic_container = mono_image_alloc0 (klass->image, sizeof (MonoGenericContainer));
11443                         gparam->mbuilder->generic_container->is_method = TRUE;
11444                         /* 
11445                          * Cannot set owner.method, since the MonoMethod is not created yet.
11446                          * Set the image field instead, so type_in_image () works.
11447                          */
11448                         gparam->mbuilder->generic_container->image = klass->image;
11449                 }
11450                 param->param.owner = gparam->mbuilder->generic_container;
11451         } else if (gparam->tbuilder) {
11452                 if (!gparam->tbuilder->generic_container) {
11453                         MonoClass *klass = mono_class_from_mono_type (mono_reflection_type_get_handle ((MonoReflectionType*)gparam->tbuilder));
11454                         gparam->tbuilder->generic_container = mono_image_alloc0 (klass->image, sizeof (MonoGenericContainer));
11455                         gparam->tbuilder->generic_container->owner.klass = klass;
11456                 }
11457                 param->param.owner = gparam->tbuilder->generic_container;
11458         }
11459
11460         pklass = mono_class_from_generic_parameter ((MonoGenericParam *) param, image, gparam->mbuilder != NULL);
11461
11462         gparam->type.type = &pklass->byval_arg;
11463
11464         mono_class_set_ref_info (pklass, gparam);
11465         mono_image_append_class_to_reflection_info_set (pklass);
11466 }
11467
11468 MonoArray *
11469 mono_reflection_sighelper_get_signature_local (MonoReflectionSigHelper *sig)
11470 {
11471         MonoReflectionModuleBuilder *module = sig->module;
11472         MonoDynamicImage *assembly = module != NULL ? module->dynamic_image : NULL;
11473         guint32 na = sig->arguments ? mono_array_length (sig->arguments) : 0;
11474         guint32 buflen, i;
11475         MonoArray *result;
11476         SigBuffer buf;
11477
11478         check_array_for_usertypes (sig->arguments);
11479
11480         sigbuffer_init (&buf, 32);
11481
11482         sigbuffer_add_value (&buf, 0x07);
11483         sigbuffer_add_value (&buf, na);
11484         if (assembly != NULL){
11485                 for (i = 0; i < na; ++i) {
11486                         MonoReflectionType *type = mono_array_get (sig->arguments, MonoReflectionType*, i);
11487                         encode_reflection_type (assembly, type, &buf);
11488                 }
11489         }
11490
11491         buflen = buf.p - buf.buf;
11492         result = mono_array_new (mono_domain_get (), mono_defaults.byte_class, buflen);
11493         memcpy (mono_array_addr (result, char, 0), buf.buf, buflen);
11494         sigbuffer_free (&buf);
11495
11496         return result;
11497 }
11498
11499 MonoArray *
11500 mono_reflection_sighelper_get_signature_field (MonoReflectionSigHelper *sig)
11501 {
11502         MonoDynamicImage *assembly = sig->module->dynamic_image;
11503         guint32 na = sig->arguments ? mono_array_length (sig->arguments) : 0;
11504         guint32 buflen, i;
11505         MonoArray *result;
11506         SigBuffer buf;
11507
11508         check_array_for_usertypes (sig->arguments);
11509
11510         sigbuffer_init (&buf, 32);
11511
11512         sigbuffer_add_value (&buf, 0x06);
11513         for (i = 0; i < na; ++i) {
11514                 MonoReflectionType *type = mono_array_get (sig->arguments, MonoReflectionType*, i);
11515                 encode_reflection_type (assembly, type, &buf);
11516         }
11517
11518         buflen = buf.p - buf.buf;
11519         result = mono_array_new (mono_domain_get (), mono_defaults.byte_class, buflen);
11520         memcpy (mono_array_addr (result, char, 0), buf.buf, buflen);
11521         sigbuffer_free (&buf);
11522
11523         return result;
11524 }
11525
11526 typedef struct {
11527         MonoMethod *handle;
11528         MonoDomain *domain;
11529 } DynamicMethodReleaseData;
11530
11531 /*
11532  * The runtime automatically clean up those after finalization.
11533 */      
11534 static MonoReferenceQueue *dynamic_method_queue;
11535
11536 static void
11537 free_dynamic_method (void *dynamic_method)
11538 {
11539         DynamicMethodReleaseData *data = dynamic_method;
11540
11541         mono_runtime_free_method (data->domain, data->handle);
11542         g_free (data);
11543 }
11544
11545 void 
11546 mono_reflection_create_dynamic_method (MonoReflectionDynamicMethod *mb)
11547 {
11548         MonoReferenceQueue *queue;
11549         MonoMethod *handle;
11550         DynamicMethodReleaseData *release_data;
11551         ReflectionMethodBuilder rmb;
11552         MonoMethodSignature *sig;
11553         MonoClass *klass;
11554         GSList *l;
11555         int i;
11556
11557         if (mono_runtime_is_shutting_down ())
11558                 mono_raise_exception (mono_get_exception_invalid_operation (""));
11559
11560         if (!(queue = dynamic_method_queue)) {
11561                 mono_loader_lock ();
11562                 if (!(queue = dynamic_method_queue))
11563                         queue = dynamic_method_queue = mono_gc_reference_queue_new (free_dynamic_method);
11564                 mono_loader_unlock ();
11565         }
11566
11567         sig = dynamic_method_to_signature (mb);
11568
11569         reflection_methodbuilder_from_dynamic_method (&rmb, mb);
11570
11571         /*
11572          * Resolve references.
11573          */
11574         /* 
11575          * Every second entry in the refs array is reserved for storing handle_class,
11576          * which is needed by the ldtoken implementation in the JIT.
11577          */
11578         rmb.nrefs = mb->nrefs;
11579         rmb.refs = g_new0 (gpointer, mb->nrefs + 1);
11580         for (i = 0; i < mb->nrefs; i += 2) {
11581                 MonoClass *handle_class;
11582                 gpointer ref;
11583                 MonoObject *obj = mono_array_get (mb->refs, MonoObject*, i);
11584
11585                 if (strcmp (obj->vtable->klass->name, "DynamicMethod") == 0) {
11586                         MonoReflectionDynamicMethod *method = (MonoReflectionDynamicMethod*)obj;
11587                         /*
11588                          * The referenced DynamicMethod should already be created by the managed
11589                          * code, except in the case of circular references. In that case, we store
11590                          * method in the refs array, and fix it up later when the referenced 
11591                          * DynamicMethod is created.
11592                          */
11593                         if (method->mhandle) {
11594                                 ref = method->mhandle;
11595                         } else {
11596                                 /* FIXME: GC object stored in unmanaged memory */
11597                                 ref = method;
11598
11599                                 /* FIXME: GC object stored in unmanaged memory */
11600                                 method->referenced_by = g_slist_append (method->referenced_by, mb);
11601                         }
11602                         handle_class = mono_defaults.methodhandle_class;
11603                 } else {
11604                         MonoException *ex = NULL;
11605                         ref = resolve_object (mb->module->image, obj, &handle_class, NULL);
11606                         if (!ref)
11607                                 ex = mono_get_exception_type_load (NULL, NULL);
11608                         else if (mono_security_core_clr_enabled ())
11609                                 ex = mono_security_core_clr_ensure_dynamic_method_resolved_object (ref, handle_class);
11610
11611                         if (ex) {
11612                                 g_free (rmb.refs);
11613                                 mono_raise_exception (ex);
11614                                 return;
11615                         }
11616                 }
11617
11618                 rmb.refs [i] = ref; /* FIXME: GC object stored in unmanaged memory (change also resolve_object() signature) */
11619                 rmb.refs [i + 1] = handle_class;
11620         }               
11621
11622         klass = mb->owner ? mono_class_from_mono_type (mono_reflection_type_get_handle ((MonoReflectionType*)mb->owner)) : mono_defaults.object_class;
11623
11624         mb->mhandle = handle = reflection_methodbuilder_to_mono_method (klass, &rmb, sig);
11625         release_data = g_new (DynamicMethodReleaseData, 1);
11626         release_data->handle = handle;
11627         release_data->domain = mono_object_get_domain ((MonoObject*)mb);
11628         if (!mono_gc_reference_queue_add (queue, (MonoObject*)mb, release_data))
11629                 g_free (release_data);
11630
11631         /* Fix up refs entries pointing at us */
11632         for (l = mb->referenced_by; l; l = l->next) {
11633                 MonoReflectionDynamicMethod *method = (MonoReflectionDynamicMethod*)l->data;
11634                 MonoMethodWrapper *wrapper = (MonoMethodWrapper*)method->mhandle;
11635                 gpointer *data;
11636                 
11637                 g_assert (method->mhandle);
11638
11639                 data = (gpointer*)wrapper->method_data;
11640                 for (i = 0; i < GPOINTER_TO_UINT (data [0]); i += 2) {
11641                         if ((data [i + 1] == mb) && (data [i + 1 + 1] == mono_defaults.methodhandle_class))
11642                                 data [i + 1] = mb->mhandle;
11643                 }
11644         }
11645         g_slist_free (mb->referenced_by);
11646
11647         g_free (rmb.refs);
11648
11649         /* ilgen is no longer needed */
11650         mb->ilgen = NULL;
11651 }
11652
11653 #endif /* DISABLE_REFLECTION_EMIT */
11654
11655 /**
11656  * 
11657  * mono_reflection_is_valid_dynamic_token:
11658  * 
11659  * Returns TRUE if token is valid.
11660  * 
11661  */
11662 gboolean
11663 mono_reflection_is_valid_dynamic_token (MonoDynamicImage *image, guint32 token)
11664 {
11665         return mono_g_hash_table_lookup (image->tokens, GUINT_TO_POINTER (token)) != NULL;
11666 }
11667
11668 MonoMethodSignature *
11669 mono_reflection_lookup_signature (MonoImage *image, MonoMethod *method, guint32 token)
11670 {
11671         MonoMethodSignature *sig;
11672         g_assert (image->dynamic);
11673
11674         sig = g_hash_table_lookup (((MonoDynamicImage*)image)->vararg_aux_hash, GUINT_TO_POINTER (token));
11675         if (sig)
11676                 return sig;
11677
11678         return mono_method_signature (method);
11679 }
11680
11681 #ifndef DISABLE_REFLECTION_EMIT
11682
11683 /**
11684  * mono_reflection_lookup_dynamic_token:
11685  *
11686  * Finish the Builder object pointed to by TOKEN and return the corresponding
11687  * runtime structure. If HANDLE_CLASS is not NULL, it is set to the class required by 
11688  * mono_ldtoken. If valid_token is TRUE, assert if it is not found in the token->object
11689  * mapping table.
11690  *
11691  * LOCKING: Take the loader lock
11692  */
11693 gpointer
11694 mono_reflection_lookup_dynamic_token (MonoImage *image, guint32 token, gboolean valid_token, MonoClass **handle_class, MonoGenericContext *context)
11695 {
11696         MonoDynamicImage *assembly = (MonoDynamicImage*)image;
11697         MonoObject *obj;
11698         MonoClass *klass;
11699
11700         mono_loader_lock ();
11701         obj = mono_g_hash_table_lookup (assembly->tokens, GUINT_TO_POINTER (token));
11702         mono_loader_unlock ();
11703         if (!obj) {
11704                 if (valid_token)
11705                         g_error ("Could not find required dynamic token 0x%08x", token);
11706                 else
11707                         return NULL;
11708         }
11709
11710         if (!handle_class)
11711                 handle_class = &klass;
11712         return resolve_object (image, obj, handle_class, context);
11713 }
11714
11715 /*
11716  * ensure_complete_type:
11717  *
11718  *   Ensure that KLASS is completed if it is a dynamic type, or references
11719  * dynamic types.
11720  */
11721 static void
11722 ensure_complete_type (MonoClass *klass)
11723 {
11724         if (klass->image->dynamic && !klass->wastypebuilder && mono_class_get_ref_info (klass)) {
11725                 MonoReflectionTypeBuilder *tb = mono_class_get_ref_info (klass);
11726
11727                 mono_domain_try_type_resolve (mono_domain_get (), NULL, (MonoObject*)tb);
11728
11729                 // Asserting here could break a lot of code
11730                 //g_assert (klass->wastypebuilder);
11731         }
11732
11733         if (klass->generic_class) {
11734                 MonoGenericInst *inst = klass->generic_class->context.class_inst;
11735                 int i;
11736
11737                 for (i = 0; i < inst->type_argc; ++i) {
11738                         ensure_complete_type (mono_class_from_mono_type (inst->type_argv [i]));
11739                 }
11740         }
11741 }
11742
11743 static gpointer
11744 resolve_object (MonoImage *image, MonoObject *obj, MonoClass **handle_class, MonoGenericContext *context)
11745 {
11746         gpointer result = NULL;
11747
11748         if (strcmp (obj->vtable->klass->name, "String") == 0) {
11749                 result = mono_string_intern ((MonoString*)obj);
11750                 *handle_class = mono_defaults.string_class;
11751                 g_assert (result);
11752         } else if (strcmp (obj->vtable->klass->name, "MonoType") == 0) {
11753                 MonoType *type = mono_reflection_type_get_handle ((MonoReflectionType*)obj);
11754                 MonoClass *mc = mono_class_from_mono_type (type);
11755                 if (!mono_class_init (mc))
11756                         mono_raise_exception (mono_class_get_exception_for_failure (mc));
11757
11758                 if (context) {
11759                         MonoType *inflated = mono_class_inflate_generic_type (type, context);
11760                         result = mono_class_from_mono_type (inflated);
11761                         mono_metadata_free_type (inflated);
11762                 } else {
11763                         result = mono_class_from_mono_type (type);
11764                 }
11765                 *handle_class = mono_defaults.typehandle_class;
11766                 g_assert (result);
11767         } else if (strcmp (obj->vtable->klass->name, "MonoMethod") == 0 ||
11768                    strcmp (obj->vtable->klass->name, "MonoCMethod") == 0 ||
11769                    strcmp (obj->vtable->klass->name, "MonoGenericCMethod") == 0 ||
11770                    strcmp (obj->vtable->klass->name, "MonoGenericMethod") == 0) {
11771                 result = ((MonoReflectionMethod*)obj)->method;
11772                 if (context)
11773                         result = mono_class_inflate_generic_method (result, context);
11774                 *handle_class = mono_defaults.methodhandle_class;
11775                 g_assert (result);
11776         } else if (strcmp (obj->vtable->klass->name, "MethodBuilder") == 0) {
11777                 MonoReflectionMethodBuilder *mb = (MonoReflectionMethodBuilder*)obj;
11778                 result = mb->mhandle;
11779                 if (!result) {
11780                         /* Type is not yet created */
11781                         MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder*)mb->type;
11782
11783                         mono_domain_try_type_resolve (mono_domain_get (), NULL, (MonoObject*)tb);
11784
11785                         /*
11786                          * Hopefully this has been filled in by calling CreateType() on the
11787                          * TypeBuilder.
11788                          */
11789                         /*
11790                          * TODO: This won't work if the application finishes another 
11791                          * TypeBuilder instance instead of this one.
11792                          */
11793                         result = mb->mhandle;
11794                 }
11795                 if (context)
11796                         result = mono_class_inflate_generic_method (result, context);
11797                 *handle_class = mono_defaults.methodhandle_class;
11798         } else if (strcmp (obj->vtable->klass->name, "ConstructorBuilder") == 0) {
11799                 MonoReflectionCtorBuilder *cb = (MonoReflectionCtorBuilder*)obj;
11800
11801                 result = cb->mhandle;
11802                 if (!result) {
11803                         MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder*)cb->type;
11804
11805                         mono_domain_try_type_resolve (mono_domain_get (), NULL, (MonoObject*)tb);
11806                         result = cb->mhandle;
11807                 }
11808                 if (context)
11809                         result = mono_class_inflate_generic_method (result, context);
11810                 *handle_class = mono_defaults.methodhandle_class;
11811         } else if (strcmp (obj->vtable->klass->name, "MonoField") == 0) {
11812                 MonoClassField *field = ((MonoReflectionField*)obj)->field;
11813
11814                 ensure_complete_type (field->parent);
11815                 if (context) {
11816                         MonoType *inflated = mono_class_inflate_generic_type (&field->parent->byval_arg, context);
11817                         MonoClass *class = mono_class_from_mono_type (inflated);
11818                         MonoClassField *inflated_field;
11819                         gpointer iter = NULL;
11820                         mono_metadata_free_type (inflated);
11821                         while ((inflated_field = mono_class_get_fields (class, &iter))) {
11822                                 if (!strcmp (field->name, inflated_field->name))
11823                                         break;
11824                         }
11825                         g_assert (inflated_field && !strcmp (field->name, inflated_field->name));
11826                         result = inflated_field;
11827                 } else {
11828                         result = field;
11829                 }
11830                 *handle_class = mono_defaults.fieldhandle_class;
11831                 g_assert (result);
11832         } else if (strcmp (obj->vtable->klass->name, "FieldBuilder") == 0) {
11833                 MonoReflectionFieldBuilder *fb = (MonoReflectionFieldBuilder*)obj;
11834                 result = fb->handle;
11835
11836                 if (!result) {
11837                         MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder*)fb->typeb;
11838
11839                         mono_domain_try_type_resolve (mono_domain_get (), NULL, (MonoObject*)tb);
11840                         result = fb->handle;
11841                 }
11842
11843                 if (fb->handle && fb->handle->parent->generic_container) {
11844                         MonoClass *klass = fb->handle->parent;
11845                         MonoType *type = mono_class_inflate_generic_type (&klass->byval_arg, context);
11846                         MonoClass *inflated = mono_class_from_mono_type (type);
11847
11848                         result = mono_class_get_field_from_name (inflated, mono_field_get_name (fb->handle));
11849                         g_assert (result);
11850                         mono_metadata_free_type (type);
11851                 }
11852                 *handle_class = mono_defaults.fieldhandle_class;
11853         } else if (strcmp (obj->vtable->klass->name, "TypeBuilder") == 0) {
11854                 MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder*)obj;
11855                 MonoType *type = mono_reflection_type_get_handle ((MonoReflectionType*)tb); 
11856                 MonoClass *klass;
11857
11858                 klass = type->data.klass;
11859                 if (klass->wastypebuilder) {
11860                         /* Already created */
11861                         result = klass;
11862                 }
11863                 else {
11864                         mono_domain_try_type_resolve (mono_domain_get (), NULL, (MonoObject*)tb);
11865                         result = type->data.klass;
11866                         g_assert (result);
11867                 }
11868                 *handle_class = mono_defaults.typehandle_class;
11869         } else if (strcmp (obj->vtable->klass->name, "SignatureHelper") == 0) {
11870                 MonoReflectionSigHelper *helper = (MonoReflectionSigHelper*)obj;
11871                 MonoMethodSignature *sig;
11872                 int nargs, i;
11873
11874                 if (helper->arguments)
11875                         nargs = mono_array_length (helper->arguments);
11876                 else
11877                         nargs = 0;
11878
11879                 sig = mono_metadata_signature_alloc (image, nargs);
11880                 sig->explicit_this = helper->call_conv & 64 ? 1 : 0;
11881                 sig->hasthis = helper->call_conv & 32 ? 1 : 0;
11882
11883                 if (helper->unmanaged_call_conv) { /* unmanaged */
11884                         sig->call_convention = helper->unmanaged_call_conv - 1;
11885                         sig->pinvoke = TRUE;
11886                 } else if (helper->call_conv & 0x02) {
11887                         sig->call_convention = MONO_CALL_VARARG;
11888                 } else {
11889                         sig->call_convention = MONO_CALL_DEFAULT;
11890                 }
11891
11892                 sig->param_count = nargs;
11893                 /* TODO: Copy type ? */
11894                 sig->ret = helper->return_type->type;
11895                 for (i = 0; i < nargs; ++i)
11896                         sig->params [i] = mono_type_array_get_and_resolve (helper->arguments, i);
11897
11898                 result = sig;
11899                 *handle_class = NULL;
11900         } else if (strcmp (obj->vtable->klass->name, "DynamicMethod") == 0) {
11901                 MonoReflectionDynamicMethod *method = (MonoReflectionDynamicMethod*)obj;
11902                 /* Already created by the managed code */
11903                 g_assert (method->mhandle);
11904                 result = method->mhandle;
11905                 *handle_class = mono_defaults.methodhandle_class;
11906         } else if (strcmp (obj->vtable->klass->name, "GenericTypeParameterBuilder") == 0) {
11907                 MonoType *type = mono_reflection_type_get_handle ((MonoReflectionType*)obj);
11908                 type = mono_class_inflate_generic_type (type, context);
11909                 result = mono_class_from_mono_type (type);
11910                 *handle_class = mono_defaults.typehandle_class;
11911                 g_assert (result);
11912                 mono_metadata_free_type (type);
11913         } else if (strcmp (obj->vtable->klass->name, "MonoGenericClass") == 0) {
11914                 MonoType *type = mono_reflection_type_get_handle ((MonoReflectionType*)obj);
11915                 type = mono_class_inflate_generic_type (type, context);
11916                 result = mono_class_from_mono_type (type);
11917                 *handle_class = mono_defaults.typehandle_class;
11918                 g_assert (result);
11919                 mono_metadata_free_type (type);
11920         } else if (strcmp (obj->vtable->klass->name, "FieldOnTypeBuilderInst") == 0) {
11921                 MonoReflectionFieldOnTypeBuilderInst *f = (MonoReflectionFieldOnTypeBuilderInst*)obj;
11922                 MonoClass *inflated;
11923                 MonoType *type;
11924                 MonoClassField *field;
11925
11926                 if (is_sre_field_builder (mono_object_class (f->fb)))
11927                         field = ((MonoReflectionFieldBuilder*)f->fb)->handle;
11928                 else if (is_sr_mono_field (mono_object_class (f->fb)))
11929                         field = ((MonoReflectionField*)f->fb)->field;
11930                 else
11931                         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)));
11932
11933                 type = mono_class_inflate_generic_type (mono_reflection_type_get_handle ((MonoReflectionType*)f->inst), context);
11934                 inflated = mono_class_from_mono_type (type);
11935
11936                 result = field = mono_class_get_field_from_name (inflated, mono_field_get_name (field));
11937                 ensure_complete_type (field->parent);
11938                 g_assert (result);
11939                 mono_metadata_free_type (type);
11940                 *handle_class = mono_defaults.fieldhandle_class;
11941         } else if (strcmp (obj->vtable->klass->name, "ConstructorOnTypeBuilderInst") == 0) {
11942                 MonoReflectionCtorOnTypeBuilderInst *c = (MonoReflectionCtorOnTypeBuilderInst*)obj;
11943                 MonoType *type = mono_class_inflate_generic_type (mono_reflection_type_get_handle ((MonoReflectionType*)c->inst), context);
11944                 MonoClass *inflated_klass = mono_class_from_mono_type (type);
11945                 MonoMethod *method;
11946
11947                 if (is_sre_ctor_builder (mono_object_class (c->cb)))
11948                         method = ((MonoReflectionCtorBuilder *)c->cb)->mhandle;
11949                 else if (is_sr_mono_cmethod (mono_object_class (c->cb)))
11950                         method = ((MonoReflectionMethod *)c->cb)->method;
11951                 else
11952                         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)));
11953
11954                 result = inflate_mono_method (inflated_klass, method, (MonoObject*)c->cb);
11955                 *handle_class = mono_defaults.methodhandle_class;
11956                 mono_metadata_free_type (type);
11957         } else if (strcmp (obj->vtable->klass->name, "MethodOnTypeBuilderInst") == 0) {
11958                 MonoReflectionMethodOnTypeBuilderInst *m = (MonoReflectionMethodOnTypeBuilderInst*)obj;
11959                 if (m->method_args) {
11960                         result = mono_reflection_method_on_tb_inst_get_handle (m);
11961                         if (context)
11962                                 result = mono_class_inflate_generic_method (result, context);
11963                 } else {
11964                         MonoType *type = mono_class_inflate_generic_type (mono_reflection_type_get_handle ((MonoReflectionType*)m->inst), context);
11965                         MonoClass *inflated_klass = mono_class_from_mono_type (type);
11966                         MonoMethod *method;
11967
11968                         if (is_sre_method_builder (mono_object_class (m->mb)))
11969                                 method = ((MonoReflectionMethodBuilder *)m->mb)->mhandle;
11970                         else if (is_sr_mono_method (mono_object_class (m->mb)))
11971                                 method = ((MonoReflectionMethod *)m->mb)->method;
11972                         else
11973                                 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)));
11974
11975                         result = inflate_mono_method (inflated_klass, method, (MonoObject*)m->mb);
11976                         mono_metadata_free_type (type);
11977                 }
11978                 *handle_class = mono_defaults.methodhandle_class;
11979         } else if (strcmp (obj->vtable->klass->name, "MonoArrayMethod") == 0) {
11980                 MonoReflectionArrayMethod *m = (MonoReflectionArrayMethod*)obj;
11981                 MonoType *mtype;
11982                 MonoClass *klass;
11983                 MonoMethod *method;
11984                 gpointer iter;
11985                 char *name;
11986
11987                 mtype = mono_reflection_type_get_handle (m->parent);
11988                 klass = mono_class_from_mono_type (mtype);
11989
11990                 /* Find the method */
11991
11992                 name = mono_string_to_utf8 (m->name);
11993                 iter = NULL;
11994                 while ((method = mono_class_get_methods (klass, &iter))) {
11995                         if (!strcmp (method->name, name))
11996                                 break;
11997                 }
11998                 g_free (name);
11999
12000                 // FIXME:
12001                 g_assert (method);
12002                 // FIXME: Check parameters/return value etc. match
12003
12004                 result = method;
12005                 *handle_class = mono_defaults.methodhandle_class;
12006         } else if (is_sre_array (mono_object_get_class(obj)) ||
12007                                 is_sre_byref (mono_object_get_class(obj)) ||
12008                                 is_sre_pointer (mono_object_get_class(obj))) {
12009                 MonoReflectionType *ref_type = (MonoReflectionType *)obj;
12010                 MonoType *type = mono_reflection_type_get_handle (ref_type);
12011
12012                 if (context) {
12013                         MonoType *inflated = mono_class_inflate_generic_type (type, context);
12014                         result = mono_class_from_mono_type (inflated);
12015                         mono_metadata_free_type (inflated);
12016                 } else {
12017                         result = mono_class_from_mono_type (type);
12018                 }
12019                 *handle_class = mono_defaults.typehandle_class;
12020         } else {
12021                 g_print ("%s\n", obj->vtable->klass->name);
12022                 g_assert_not_reached ();
12023         }
12024         return result;
12025 }
12026
12027 #else /* DISABLE_REFLECTION_EMIT */
12028
12029 MonoArray*
12030 mono_reflection_get_custom_attrs_blob (MonoReflectionAssembly *assembly, MonoObject *ctor, MonoArray *ctorArgs, MonoArray *properties, MonoArray *propValues, MonoArray *fields, MonoArray* fieldValues) 
12031 {
12032         g_assert_not_reached ();
12033         return NULL;
12034 }
12035
12036 void
12037 mono_reflection_setup_internal_class (MonoReflectionTypeBuilder *tb)
12038 {
12039         g_assert_not_reached ();
12040 }
12041
12042 void
12043 mono_reflection_setup_generic_class (MonoReflectionTypeBuilder *tb)
12044 {
12045         g_assert_not_reached ();
12046 }
12047
12048 void
12049 mono_reflection_create_generic_class (MonoReflectionTypeBuilder *tb)
12050 {
12051         g_assert_not_reached ();
12052 }
12053
12054 void
12055 mono_reflection_create_internal_class (MonoReflectionTypeBuilder *tb)
12056 {
12057         g_assert_not_reached ();
12058 }
12059
12060 void
12061 mono_image_basic_init (MonoReflectionAssemblyBuilder *assemblyb)
12062 {
12063         g_error ("This mono runtime was configured with --enable-minimal=reflection_emit, so System.Reflection.Emit is not supported.");
12064 }
12065
12066 void
12067 mono_image_module_basic_init (MonoReflectionModuleBuilder *moduleb)
12068 {
12069         g_assert_not_reached ();
12070 }
12071
12072 void
12073 mono_image_set_wrappers_type (MonoReflectionModuleBuilder *moduleb, MonoReflectionType *type)
12074 {
12075         g_assert_not_reached ();
12076 }
12077
12078 MonoReflectionModule *
12079 mono_image_load_module_dynamic (MonoReflectionAssemblyBuilder *ab, MonoString *fileName)
12080 {
12081         g_assert_not_reached ();
12082         return NULL;
12083 }
12084
12085 guint32
12086 mono_image_insert_string (MonoReflectionModuleBuilder *module, MonoString *str)
12087 {
12088         g_assert_not_reached ();
12089         return 0;
12090 }
12091
12092 guint32
12093 mono_image_create_method_token (MonoDynamicImage *assembly, MonoObject *obj, MonoArray *opt_param_types)
12094 {
12095         g_assert_not_reached ();
12096         return 0;
12097 }
12098
12099 guint32
12100 mono_image_create_token (MonoDynamicImage *assembly, MonoObject *obj, 
12101                                                  gboolean create_open_instance, gboolean register_token)
12102 {
12103         g_assert_not_reached ();
12104         return 0;
12105 }
12106
12107 void
12108 mono_image_register_token (MonoDynamicImage *assembly, guint32 token, MonoObject *obj)
12109 {
12110 }
12111
12112 void
12113 mono_reflection_generic_class_initialize (MonoReflectionGenericClass *type, MonoArray *fields)
12114 {
12115         g_assert_not_reached ();
12116 }
12117
12118 void
12119 mono_reflection_get_dynamic_overrides (MonoClass *klass, MonoMethod ***overrides, int *num_overrides)
12120 {
12121         *overrides = NULL;
12122         *num_overrides = 0;
12123 }
12124
12125 MonoReflectionEvent *
12126 mono_reflection_event_builder_get_event_info (MonoReflectionTypeBuilder *tb, MonoReflectionEventBuilder *eb)
12127 {
12128         g_assert_not_reached ();
12129         return NULL;
12130 }
12131
12132 MonoReflectionType*
12133 mono_reflection_create_runtime_class (MonoReflectionTypeBuilder *tb)
12134 {
12135         g_assert_not_reached ();
12136         return NULL;
12137 }
12138
12139 void
12140 mono_reflection_initialize_generic_parameter (MonoReflectionGenericParam *gparam)
12141 {
12142         g_assert_not_reached ();
12143 }
12144
12145 MonoArray *
12146 mono_reflection_sighelper_get_signature_local (MonoReflectionSigHelper *sig)
12147 {
12148         g_assert_not_reached ();
12149         return NULL;
12150 }
12151
12152 MonoArray *
12153 mono_reflection_sighelper_get_signature_field (MonoReflectionSigHelper *sig)
12154 {
12155         g_assert_not_reached ();
12156         return NULL;
12157 }
12158
12159 void 
12160 mono_reflection_create_dynamic_method (MonoReflectionDynamicMethod *mb)
12161 {
12162 }
12163
12164 gpointer
12165 mono_reflection_lookup_dynamic_token (MonoImage *image, guint32 token, gboolean valid_token, MonoClass **handle_class, MonoGenericContext *context)
12166 {
12167         return NULL;
12168 }
12169
12170 MonoType*
12171 mono_reflection_type_get_handle (MonoReflectionType* ref)
12172 {
12173         if (!ref)
12174                 return NULL;
12175         return ref->type;
12176 }
12177
12178 void
12179 mono_reflection_free_dynamic_generic_class (MonoGenericClass *gclass)
12180 {
12181         g_assert_not_reached ();
12182 }
12183
12184 #endif /* DISABLE_REFLECTION_EMIT */
12185
12186 /* SECURITY_ACTION_* are defined in mono/metadata/tabledefs.h */
12187 const static guint32 declsec_flags_map[] = {
12188         0x00000000,                                     /* empty */
12189         MONO_DECLSEC_FLAG_REQUEST,                      /* SECURITY_ACTION_REQUEST                      (x01) */
12190         MONO_DECLSEC_FLAG_DEMAND,                       /* SECURITY_ACTION_DEMAND                       (x02) */
12191         MONO_DECLSEC_FLAG_ASSERT,                       /* SECURITY_ACTION_ASSERT                       (x03) */
12192         MONO_DECLSEC_FLAG_DENY,                         /* SECURITY_ACTION_DENY                         (x04) */
12193         MONO_DECLSEC_FLAG_PERMITONLY,                   /* SECURITY_ACTION_PERMITONLY                   (x05) */
12194         MONO_DECLSEC_FLAG_LINKDEMAND,                   /* SECURITY_ACTION_LINKDEMAND                   (x06) */
12195         MONO_DECLSEC_FLAG_INHERITANCEDEMAND,            /* SECURITY_ACTION_INHERITANCEDEMAND            (x07) */
12196         MONO_DECLSEC_FLAG_REQUEST_MINIMUM,              /* SECURITY_ACTION_REQUEST_MINIMUM              (x08) */
12197         MONO_DECLSEC_FLAG_REQUEST_OPTIONAL,             /* SECURITY_ACTION_REQUEST_OPTIONAL             (x09) */
12198         MONO_DECLSEC_FLAG_REQUEST_REFUSE,               /* SECURITY_ACTION_REQUEST_REFUSE               (x0A) */
12199         MONO_DECLSEC_FLAG_PREJIT_GRANT,                 /* SECURITY_ACTION_PREJIT_GRANT                 (x0B) */
12200         MONO_DECLSEC_FLAG_PREJIT_DENY,                  /* SECURITY_ACTION_PREJIT_DENY                  (x0C) */
12201         MONO_DECLSEC_FLAG_NONCAS_DEMAND,                /* SECURITY_ACTION_NONCAS_DEMAND                (x0D) */
12202         MONO_DECLSEC_FLAG_NONCAS_LINKDEMAND,            /* SECURITY_ACTION_NONCAS_LINKDEMAND            (x0E) */
12203         MONO_DECLSEC_FLAG_NONCAS_INHERITANCEDEMAND,     /* SECURITY_ACTION_NONCAS_INHERITANCEDEMAND     (x0F) */
12204         MONO_DECLSEC_FLAG_LINKDEMAND_CHOICE,            /* SECURITY_ACTION_LINKDEMAND_CHOICE            (x10) */
12205         MONO_DECLSEC_FLAG_INHERITANCEDEMAND_CHOICE,     /* SECURITY_ACTION_INHERITANCEDEMAND_CHOICE     (x11) */
12206         MONO_DECLSEC_FLAG_DEMAND_CHOICE,                /* SECURITY_ACTION_DEMAND_CHOICE                (x12) */
12207 };
12208
12209 /*
12210  * Returns flags that includes all available security action associated to the handle.
12211  * @token: metadata token (either for a class or a method)
12212  * @image: image where resides the metadata.
12213  */
12214 static guint32
12215 mono_declsec_get_flags (MonoImage *image, guint32 token)
12216 {
12217         int index = mono_metadata_declsec_from_index (image, token);
12218         MonoTableInfo *t = &image->tables [MONO_TABLE_DECLSECURITY];
12219         guint32 result = 0;
12220         guint32 action;
12221         int i;
12222
12223         /* HasSecurity can be present for other, not specially encoded, attributes,
12224            e.g. SuppressUnmanagedCodeSecurityAttribute */
12225         if (index < 0)
12226                 return 0;
12227
12228         for (i = index; i < t->rows; i++) {
12229                 guint32 cols [MONO_DECL_SECURITY_SIZE];
12230
12231                 mono_metadata_decode_row (t, i, cols, MONO_DECL_SECURITY_SIZE);
12232                 if (cols [MONO_DECL_SECURITY_PARENT] != token)
12233                         break;
12234
12235                 action = cols [MONO_DECL_SECURITY_ACTION];
12236                 if ((action >= MONO_DECLSEC_ACTION_MIN) && (action <= MONO_DECLSEC_ACTION_MAX)) {
12237                         result |= declsec_flags_map [action];
12238                 } else {
12239                         g_assert_not_reached ();
12240                 }
12241         }
12242         return result;
12243 }
12244
12245 /*
12246  * Get the security actions (in the form of flags) associated with the specified method.
12247  *
12248  * @method: The method for which we want the declarative security flags.
12249  * Return the declarative security flags for the method (only).
12250  *
12251  * Note: To keep MonoMethod size down we do not cache the declarative security flags
12252  *       (except for the stack modifiers which are kept in the MonoJitInfo structure)
12253  */
12254 guint32
12255 mono_declsec_flags_from_method (MonoMethod *method)
12256 {
12257         if (method->flags & METHOD_ATTRIBUTE_HAS_SECURITY) {
12258                 /* FIXME: No cache (for the moment) */
12259                 guint32 idx = mono_method_get_index (method);
12260                 idx <<= MONO_HAS_DECL_SECURITY_BITS;
12261                 idx |= MONO_HAS_DECL_SECURITY_METHODDEF;
12262                 return mono_declsec_get_flags (method->klass->image, idx);
12263         }
12264         return 0;
12265 }
12266
12267 /*
12268  * Get the security actions (in the form of flags) associated with the specified class.
12269  *
12270  * @klass: The class for which we want the declarative security flags.
12271  * Return the declarative security flags for the class.
12272  *
12273  * Note: We cache the flags inside the MonoClass structure as this will get 
12274  *       called very often (at least for each method).
12275  */
12276 guint32
12277 mono_declsec_flags_from_class (MonoClass *klass)
12278 {
12279         if (klass->flags & TYPE_ATTRIBUTE_HAS_SECURITY) {
12280                 if (!klass->ext || !klass->ext->declsec_flags) {
12281                         guint32 idx;
12282
12283                         idx = mono_metadata_token_index (klass->type_token);
12284                         idx <<= MONO_HAS_DECL_SECURITY_BITS;
12285                         idx |= MONO_HAS_DECL_SECURITY_TYPEDEF;
12286                         mono_loader_lock ();
12287                         mono_class_alloc_ext (klass);
12288                         mono_loader_unlock ();
12289                         /* we cache the flags on classes */
12290                         klass->ext->declsec_flags = mono_declsec_get_flags (klass->image, idx);
12291                 }
12292                 return klass->ext->declsec_flags;
12293         }
12294         return 0;
12295 }
12296
12297 /*
12298  * Get the security actions (in the form of flags) associated with the specified assembly.
12299  *
12300  * @assembly: The assembly for which we want the declarative security flags.
12301  * Return the declarative security flags for the assembly.
12302  */
12303 guint32
12304 mono_declsec_flags_from_assembly (MonoAssembly *assembly)
12305 {
12306         guint32 idx = 1; /* there is only one assembly */
12307         idx <<= MONO_HAS_DECL_SECURITY_BITS;
12308         idx |= MONO_HAS_DECL_SECURITY_ASSEMBLY;
12309         return mono_declsec_get_flags (assembly->image, idx);
12310 }
12311
12312
12313 /*
12314  * Fill actions for the specific index (which may either be an encoded class token or
12315  * an encoded method token) from the metadata image.
12316  * Returns TRUE if some actions requiring code generation are present, FALSE otherwise.
12317  */
12318 static MonoBoolean
12319 fill_actions_from_index (MonoImage *image, guint32 token, MonoDeclSecurityActions* actions,
12320         guint32 id_std, guint32 id_noncas, guint32 id_choice)
12321 {
12322         MonoBoolean result = FALSE;
12323         MonoTableInfo *t;
12324         guint32 cols [MONO_DECL_SECURITY_SIZE];
12325         int index = mono_metadata_declsec_from_index (image, token);
12326         int i;
12327
12328         t  = &image->tables [MONO_TABLE_DECLSECURITY];
12329         for (i = index; i < t->rows; i++) {
12330                 mono_metadata_decode_row (t, i, cols, MONO_DECL_SECURITY_SIZE);
12331
12332                 if (cols [MONO_DECL_SECURITY_PARENT] != token)
12333                         return result;
12334
12335                 /* if present only replace (class) permissions with method permissions */
12336                 /* if empty accept either class or method permissions */
12337                 if (cols [MONO_DECL_SECURITY_ACTION] == id_std) {
12338                         if (!actions->demand.blob) {
12339                                 const char *blob = mono_metadata_blob_heap (image, cols [MONO_DECL_SECURITY_PERMISSIONSET]);
12340                                 actions->demand.index = cols [MONO_DECL_SECURITY_PERMISSIONSET];
12341                                 actions->demand.blob = (char*) (blob + 2);
12342                                 actions->demand.size = mono_metadata_decode_blob_size (blob, &blob);
12343                                 result = TRUE;
12344                         }
12345                 } else if (cols [MONO_DECL_SECURITY_ACTION] == id_noncas) {
12346                         if (!actions->noncasdemand.blob) {
12347                                 const char *blob = mono_metadata_blob_heap (image, cols [MONO_DECL_SECURITY_PERMISSIONSET]);
12348                                 actions->noncasdemand.index = cols [MONO_DECL_SECURITY_PERMISSIONSET];
12349                                 actions->noncasdemand.blob = (char*) (blob + 2);
12350                                 actions->noncasdemand.size = mono_metadata_decode_blob_size (blob, &blob);
12351                                 result = TRUE;
12352                         }
12353                 } else if (cols [MONO_DECL_SECURITY_ACTION] == id_choice) {
12354                         if (!actions->demandchoice.blob) {
12355                                 const char *blob = mono_metadata_blob_heap (image, cols [MONO_DECL_SECURITY_PERMISSIONSET]);
12356                                 actions->demandchoice.index = cols [MONO_DECL_SECURITY_PERMISSIONSET];
12357                                 actions->demandchoice.blob = (char*) (blob + 2);
12358                                 actions->demandchoice.size = mono_metadata_decode_blob_size (blob, &blob);
12359                                 result = TRUE;
12360                         }
12361                 }
12362         }
12363
12364         return result;
12365 }
12366
12367 static MonoBoolean
12368 mono_declsec_get_class_demands_params (MonoClass *klass, MonoDeclSecurityActions* demands, 
12369         guint32 id_std, guint32 id_noncas, guint32 id_choice)
12370 {
12371         guint32 idx = mono_metadata_token_index (klass->type_token);
12372         idx <<= MONO_HAS_DECL_SECURITY_BITS;
12373         idx |= MONO_HAS_DECL_SECURITY_TYPEDEF;
12374         return fill_actions_from_index (klass->image, idx, demands, id_std, id_noncas, id_choice);
12375 }
12376
12377 static MonoBoolean
12378 mono_declsec_get_method_demands_params (MonoMethod *method, MonoDeclSecurityActions* demands, 
12379         guint32 id_std, guint32 id_noncas, guint32 id_choice)
12380 {
12381         guint32 idx = mono_method_get_index (method);
12382         idx <<= MONO_HAS_DECL_SECURITY_BITS;
12383         idx |= MONO_HAS_DECL_SECURITY_METHODDEF;
12384         return fill_actions_from_index (method->klass->image, idx, demands, id_std, id_noncas, id_choice);
12385 }
12386
12387 /*
12388  * Collect all actions (that requires to generate code in mini) assigned for
12389  * the specified method.
12390  * Note: Don't use the content of actions if the function return FALSE.
12391  */
12392 MonoBoolean
12393 mono_declsec_get_demands (MonoMethod *method, MonoDeclSecurityActions* demands)
12394 {
12395         guint32 mask = MONO_DECLSEC_FLAG_DEMAND | MONO_DECLSEC_FLAG_NONCAS_DEMAND | 
12396                 MONO_DECLSEC_FLAG_DEMAND_CHOICE;
12397         MonoBoolean result = FALSE;
12398         guint32 flags;
12399
12400         /* quick exit if no declarative security is present in the metadata */
12401         if (!method->klass->image->tables [MONO_TABLE_DECLSECURITY].rows)
12402                 return FALSE;
12403
12404         /* we want the original as the wrapper is "free" of the security informations */
12405         if (method->wrapper_type == MONO_WRAPPER_MANAGED_TO_NATIVE || method->wrapper_type == MONO_WRAPPER_MANAGED_TO_MANAGED) {
12406                 method = mono_marshal_method_from_wrapper (method);
12407                 if (!method)
12408                         return FALSE;
12409         }
12410
12411         /* First we look for method-level attributes */
12412         if (method->flags & METHOD_ATTRIBUTE_HAS_SECURITY) {
12413                 mono_class_init (method->klass);
12414                 memset (demands, 0, sizeof (MonoDeclSecurityActions));
12415
12416                 result = mono_declsec_get_method_demands_params (method, demands, 
12417                         SECURITY_ACTION_DEMAND, SECURITY_ACTION_NONCASDEMAND, SECURITY_ACTION_DEMANDCHOICE);
12418         }
12419
12420         /* Here we use (or create) the class declarative cache to look for demands */
12421         flags = mono_declsec_flags_from_class (method->klass);
12422         if (flags & mask) {
12423                 if (!result) {
12424                         mono_class_init (method->klass);
12425                         memset (demands, 0, sizeof (MonoDeclSecurityActions));
12426                 }
12427                 result |= mono_declsec_get_class_demands_params (method->klass, demands, 
12428                         SECURITY_ACTION_DEMAND, SECURITY_ACTION_NONCASDEMAND, SECURITY_ACTION_DEMANDCHOICE);
12429         }
12430
12431         /* The boolean return value is used as a shortcut in case nothing needs to
12432            be generated (e.g. LinkDemand[Choice] and InheritanceDemand[Choice]) */
12433         return result;
12434 }
12435
12436
12437 /*
12438  * Collect all Link actions: LinkDemand, NonCasLinkDemand and LinkDemandChoice (2.0).
12439  *
12440  * Note: Don't use the content of actions if the function return FALSE.
12441  */
12442 MonoBoolean
12443 mono_declsec_get_linkdemands (MonoMethod *method, MonoDeclSecurityActions* klass, MonoDeclSecurityActions *cmethod)
12444 {
12445         MonoBoolean result = FALSE;
12446         guint32 flags;
12447
12448         /* quick exit if no declarative security is present in the metadata */
12449         if (!method->klass->image->tables [MONO_TABLE_DECLSECURITY].rows)
12450                 return FALSE;
12451
12452         /* we want the original as the wrapper is "free" of the security informations */
12453         if (method->wrapper_type == MONO_WRAPPER_MANAGED_TO_NATIVE || method->wrapper_type == MONO_WRAPPER_MANAGED_TO_MANAGED) {
12454                 method = mono_marshal_method_from_wrapper (method);
12455                 if (!method)
12456                         return FALSE;
12457         }
12458
12459         /* results are independant - zeroize both */
12460         memset (cmethod, 0, sizeof (MonoDeclSecurityActions));
12461         memset (klass, 0, sizeof (MonoDeclSecurityActions));
12462
12463         /* First we look for method-level attributes */
12464         if (method->flags & METHOD_ATTRIBUTE_HAS_SECURITY) {
12465                 mono_class_init (method->klass);
12466
12467                 result = mono_declsec_get_method_demands_params (method, cmethod, 
12468                         SECURITY_ACTION_LINKDEMAND, SECURITY_ACTION_NONCASLINKDEMAND, SECURITY_ACTION_LINKDEMANDCHOICE);
12469         }
12470
12471         /* Here we use (or create) the class declarative cache to look for demands */
12472         flags = mono_declsec_flags_from_class (method->klass);
12473         if (flags & (MONO_DECLSEC_FLAG_LINKDEMAND | MONO_DECLSEC_FLAG_NONCAS_LINKDEMAND | MONO_DECLSEC_FLAG_LINKDEMAND_CHOICE)) {
12474                 mono_class_init (method->klass);
12475
12476                 result |= mono_declsec_get_class_demands_params (method->klass, klass, 
12477                         SECURITY_ACTION_LINKDEMAND, SECURITY_ACTION_NONCASLINKDEMAND, SECURITY_ACTION_LINKDEMANDCHOICE);
12478         }
12479
12480         return result;
12481 }
12482
12483 /*
12484  * Collect all Inherit actions: InheritanceDemand, NonCasInheritanceDemand and InheritanceDemandChoice (2.0).
12485  *
12486  * @klass       The inherited class - this is the class that provides the security check (attributes)
12487  * @demans      
12488  * return TRUE if inheritance demands (any kind) are present, FALSE otherwise.
12489  * 
12490  * Note: Don't use the content of actions if the function return FALSE.
12491  */
12492 MonoBoolean
12493 mono_declsec_get_inheritdemands_class (MonoClass *klass, MonoDeclSecurityActions* demands)
12494 {
12495         MonoBoolean result = FALSE;
12496         guint32 flags;
12497
12498         /* quick exit if no declarative security is present in the metadata */
12499         if (!klass->image->tables [MONO_TABLE_DECLSECURITY].rows)
12500                 return FALSE;
12501
12502         /* Here we use (or create) the class declarative cache to look for demands */
12503         flags = mono_declsec_flags_from_class (klass);
12504         if (flags & (MONO_DECLSEC_FLAG_INHERITANCEDEMAND | MONO_DECLSEC_FLAG_NONCAS_INHERITANCEDEMAND | MONO_DECLSEC_FLAG_INHERITANCEDEMAND_CHOICE)) {
12505                 mono_class_init (klass);
12506                 memset (demands, 0, sizeof (MonoDeclSecurityActions));
12507
12508                 result |= mono_declsec_get_class_demands_params (klass, demands, 
12509                         SECURITY_ACTION_INHERITDEMAND, SECURITY_ACTION_NONCASINHERITANCE, SECURITY_ACTION_INHERITDEMANDCHOICE);
12510         }
12511
12512         return result;
12513 }
12514
12515 /*
12516  * Collect all Inherit actions: InheritanceDemand, NonCasInheritanceDemand and InheritanceDemandChoice (2.0).
12517  *
12518  * Note: Don't use the content of actions if the function return FALSE.
12519  */
12520 MonoBoolean
12521 mono_declsec_get_inheritdemands_method (MonoMethod *method, MonoDeclSecurityActions* demands)
12522 {
12523         /* quick exit if no declarative security is present in the metadata */
12524         if (!method->klass->image->tables [MONO_TABLE_DECLSECURITY].rows)
12525                 return FALSE;
12526
12527         /* we want the original as the wrapper is "free" of the security informations */
12528         if (method->wrapper_type == MONO_WRAPPER_MANAGED_TO_NATIVE || method->wrapper_type == MONO_WRAPPER_MANAGED_TO_MANAGED) {
12529                 method = mono_marshal_method_from_wrapper (method);
12530                 if (!method)
12531                         return FALSE;
12532         }
12533
12534         if (method->flags & METHOD_ATTRIBUTE_HAS_SECURITY) {
12535                 mono_class_init (method->klass);
12536                 memset (demands, 0, sizeof (MonoDeclSecurityActions));
12537
12538                 return mono_declsec_get_method_demands_params (method, demands, 
12539                         SECURITY_ACTION_INHERITDEMAND, SECURITY_ACTION_NONCASINHERITANCE, SECURITY_ACTION_INHERITDEMANDCHOICE);
12540         }
12541         return FALSE;
12542 }
12543
12544
12545 static MonoBoolean
12546 get_declsec_action (MonoImage *image, guint32 token, guint32 action, MonoDeclSecurityEntry *entry)
12547 {
12548         guint32 cols [MONO_DECL_SECURITY_SIZE];
12549         MonoTableInfo *t;
12550         int i;
12551
12552         int index = mono_metadata_declsec_from_index (image, token);
12553         if (index == -1)
12554                 return FALSE;
12555
12556         t =  &image->tables [MONO_TABLE_DECLSECURITY];
12557         for (i = index; i < t->rows; i++) {
12558                 mono_metadata_decode_row (t, i, cols, MONO_DECL_SECURITY_SIZE);
12559
12560                 /* shortcut - index are ordered */
12561                 if (token != cols [MONO_DECL_SECURITY_PARENT])
12562                         return FALSE;
12563
12564                 if (cols [MONO_DECL_SECURITY_ACTION] == action) {
12565                         const char *metadata = mono_metadata_blob_heap (image, cols [MONO_DECL_SECURITY_PERMISSIONSET]);
12566                         entry->blob = (char*) (metadata + 2);
12567                         entry->size = mono_metadata_decode_blob_size (metadata, &metadata);
12568                         return TRUE;
12569                 }
12570         }
12571
12572         return FALSE;
12573 }
12574
12575 MonoBoolean
12576 mono_declsec_get_method_action (MonoMethod *method, guint32 action, MonoDeclSecurityEntry *entry)
12577 {
12578         if (method->flags & METHOD_ATTRIBUTE_HAS_SECURITY) {
12579                 guint32 idx = mono_method_get_index (method);
12580                 idx <<= MONO_HAS_DECL_SECURITY_BITS;
12581                 idx |= MONO_HAS_DECL_SECURITY_METHODDEF;
12582                 return get_declsec_action (method->klass->image, idx, action, entry);
12583         }
12584         return FALSE;
12585 }
12586
12587 MonoBoolean
12588 mono_declsec_get_class_action (MonoClass *klass, guint32 action, MonoDeclSecurityEntry *entry)
12589 {
12590         /* use cache */
12591         guint32 flags = mono_declsec_flags_from_class (klass);
12592         if (declsec_flags_map [action] & flags) {
12593                 guint32 idx = mono_metadata_token_index (klass->type_token);
12594                 idx <<= MONO_HAS_DECL_SECURITY_BITS;
12595                 idx |= MONO_HAS_DECL_SECURITY_TYPEDEF;
12596                 return get_declsec_action (klass->image, idx, action, entry);
12597         }
12598         return FALSE;
12599 }
12600
12601 MonoBoolean
12602 mono_declsec_get_assembly_action (MonoAssembly *assembly, guint32 action, MonoDeclSecurityEntry *entry)
12603 {
12604         guint32 idx = 1; /* there is only one assembly */
12605         idx <<= MONO_HAS_DECL_SECURITY_BITS;
12606         idx |= MONO_HAS_DECL_SECURITY_ASSEMBLY;
12607
12608         return get_declsec_action (assembly->image, idx, action, entry);
12609 }
12610
12611 gboolean
12612 mono_reflection_call_is_assignable_to (MonoClass *klass, MonoClass *oklass)
12613 {
12614         MonoObject *res, *exc;
12615         void *params [1];
12616         static MonoClass *System_Reflection_Emit_TypeBuilder = NULL;
12617         static MonoMethod *method = NULL;
12618
12619         if (!System_Reflection_Emit_TypeBuilder) {
12620                 System_Reflection_Emit_TypeBuilder = mono_class_from_name (mono_defaults.corlib, "System.Reflection.Emit", "TypeBuilder");
12621                 g_assert (System_Reflection_Emit_TypeBuilder);
12622         }
12623         if (method == NULL) {
12624                 method = mono_class_get_method_from_name (System_Reflection_Emit_TypeBuilder, "IsAssignableTo", 1);
12625                 g_assert (method);
12626         }
12627
12628         /* 
12629          * The result of mono_type_get_object () might be a System.MonoType but we
12630          * need a TypeBuilder so use mono_class_get_ref_info (klass).
12631          */
12632         g_assert (mono_class_get_ref_info (klass));
12633         g_assert (!strcmp (((MonoObject*)(mono_class_get_ref_info (klass)))->vtable->klass->name, "TypeBuilder"));
12634
12635         params [0] = mono_type_get_object (mono_domain_get (), &oklass->byval_arg);
12636
12637         res = mono_runtime_invoke (method, (MonoObject*)(mono_class_get_ref_info (klass)), params, &exc);
12638         if (exc)
12639                 return FALSE;
12640         else
12641                 return *(MonoBoolean*)mono_object_unbox (res);
12642 }
12643
12644 /**
12645  * mono_reflection_type_get_type:
12646  * @reftype: the System.Type object
12647  *
12648  * Returns the MonoType* associated with the C# System.Type object @reftype.
12649  */
12650 MonoType*
12651 mono_reflection_type_get_type (MonoReflectionType *reftype)
12652 {
12653         g_assert (reftype);
12654
12655         return mono_reflection_type_get_handle (reftype);
12656 }
12657