Changed TryPeek to handle race condition with Dequeue.
[mono.git] / mono / metadata / reflection.c
1 /*
2  * reflection.c: Routines for creating an image at runtime.
3  * 
4  * Author:
5  *   Paolo Molaro (lupus@ximian.com)
6  *
7  * Copyright 2001-2003 Ximian, Inc (http://www.ximian.com)
8  * Copyright 2004-2009 Novell, Inc (http://www.novell.com)
9  * Copyright 2011 Rodrigo Kumpera
10  *
11  */
12 #include <config.h>
13 #include "mono/utils/mono-digest.h"
14 #include "mono/utils/mono-membar.h"
15 #include "mono/metadata/reflection-internals.h"
16 #include "mono/metadata/tabledefs.h"
17 #include "mono/metadata/metadata-internals.h"
18 #include <mono/metadata/profiler-private.h>
19 #include "mono/metadata/class-internals.h"
20 #include "mono/metadata/gc-internal.h"
21 #include "mono/metadata/tokentype.h"
22 #include "mono/metadata/domain-internals.h"
23 #include "mono/metadata/opcodes.h"
24 #include "mono/metadata/assembly.h"
25 #include "mono/metadata/object-internals.h"
26 #include <mono/metadata/exception.h>
27 #include <mono/metadata/marshal.h>
28 #include <mono/metadata/security-manager.h>
29 #include <stdio.h>
30 #include <glib.h>
31 #include <errno.h>
32 #include <time.h>
33 #include <string.h>
34 #include <ctype.h>
35 #include "image.h"
36 #include "cil-coff.h"
37 #include "mono-endian.h"
38 #include <mono/metadata/gc-internal.h>
39 #include <mono/metadata/mempool-internals.h>
40 #include <mono/metadata/security-core-clr.h>
41 #include <mono/metadata/debug-helpers.h>
42 #include <mono/metadata/verify-internals.h>
43 #include <mono/metadata/mono-ptr-array.h>
44 #include <mono/utils/mono-string.h>
45 #include <mono/utils/mono-error-internals.h>
46
47 static gboolean is_usertype (MonoReflectionType *ref);
48 static MonoReflectionType *mono_reflection_type_resolve_user_types (MonoReflectionType *type);
49
50 typedef struct {
51         char *p;
52         char *buf;
53         char *end;
54 } SigBuffer;
55
56 #define TEXT_OFFSET 512
57 #define CLI_H_SIZE 136
58 #define FILE_ALIGN 512
59 #define VIRT_ALIGN 8192
60 #define START_TEXT_RVA  0x00002000
61
62 typedef struct {
63         MonoReflectionILGen *ilgen;
64         MonoReflectionType *rtype;
65         MonoArray *parameters;
66         MonoArray *generic_params;
67         MonoGenericContainer *generic_container;
68         MonoArray *pinfo;
69         MonoArray *opt_types;
70         guint32 attrs;
71         guint32 iattrs;
72         guint32 call_conv;
73         guint32 *table_idx; /* note: it's a pointer */
74         MonoArray *code;
75         MonoObject *type;
76         MonoString *name;
77         MonoBoolean init_locals;
78         MonoBoolean skip_visibility;
79         MonoArray *return_modreq;
80         MonoArray *return_modopt;
81         MonoArray *param_modreq;
82         MonoArray *param_modopt;
83         MonoArray *permissions;
84         MonoMethod *mhandle;
85         guint32 nrefs;
86         gpointer *refs;
87         /* for PInvoke */
88         int charset, extra_flags, native_cc;
89         MonoString *dll, *dllentry;
90 } ReflectionMethodBuilder;
91
92 typedef struct {
93         guint32 owner;
94         MonoReflectionGenericParam *gparam;
95 } GenericParamTableEntry;
96
97 const unsigned char table_sizes [MONO_TABLE_NUM] = {
98         MONO_MODULE_SIZE,
99         MONO_TYPEREF_SIZE,
100         MONO_TYPEDEF_SIZE,
101         0,
102         MONO_FIELD_SIZE,
103         0,
104         MONO_METHOD_SIZE,
105         0,
106         MONO_PARAM_SIZE,
107         MONO_INTERFACEIMPL_SIZE,
108         MONO_MEMBERREF_SIZE,    /* 0x0A */
109         MONO_CONSTANT_SIZE,
110         MONO_CUSTOM_ATTR_SIZE,
111         MONO_FIELD_MARSHAL_SIZE,
112         MONO_DECL_SECURITY_SIZE,
113         MONO_CLASS_LAYOUT_SIZE,
114         MONO_FIELD_LAYOUT_SIZE, /* 0x10 */
115         MONO_STAND_ALONE_SIGNATURE_SIZE,
116         MONO_EVENT_MAP_SIZE,
117         0,
118         MONO_EVENT_SIZE,
119         MONO_PROPERTY_MAP_SIZE,
120         0,
121         MONO_PROPERTY_SIZE,
122         MONO_METHOD_SEMA_SIZE,
123         MONO_METHODIMPL_SIZE,
124         MONO_MODULEREF_SIZE,    /* 0x1A */
125         MONO_TYPESPEC_SIZE,
126         MONO_IMPLMAP_SIZE,      
127         MONO_FIELD_RVA_SIZE,
128         0,
129         0,
130         MONO_ASSEMBLY_SIZE,     /* 0x20 */
131         MONO_ASSEMBLY_PROCESSOR_SIZE,
132         MONO_ASSEMBLYOS_SIZE,
133         MONO_ASSEMBLYREF_SIZE,
134         MONO_ASSEMBLYREFPROC_SIZE,
135         MONO_ASSEMBLYREFOS_SIZE,
136         MONO_FILE_SIZE,
137         MONO_EXP_TYPE_SIZE,
138         MONO_MANIFEST_SIZE,
139         MONO_NESTED_CLASS_SIZE,
140
141         MONO_GENERICPARAM_SIZE, /* 0x2A */
142         MONO_METHODSPEC_SIZE,
143         MONO_GENPARCONSTRAINT_SIZE
144
145 };
146
147 #ifndef DISABLE_REFLECTION_EMIT
148 static guint32 mono_image_get_methodref_token (MonoDynamicImage *assembly, MonoMethod *method, gboolean create_typespec);
149 static guint32 mono_image_get_methodbuilder_token (MonoDynamicImage *assembly, MonoReflectionMethodBuilder *mb, gboolean create_open_instance);
150 static guint32 mono_image_get_ctorbuilder_token (MonoDynamicImage *assembly, MonoReflectionCtorBuilder *cb);
151 static guint32 mono_image_get_sighelper_token (MonoDynamicImage *assembly, MonoReflectionSigHelper *helper);
152 static void    ensure_runtime_vtable (MonoClass *klass);
153 static gpointer resolve_object (MonoImage *image, MonoObject *obj, MonoClass **handle_class, MonoGenericContext *context);
154 static guint32 mono_image_get_methodref_token_for_methodbuilder (MonoDynamicImage *assembly, MonoReflectionMethodBuilder *method);
155 static guint32 encode_generic_method_sig (MonoDynamicImage *assembly, MonoGenericContext *context);
156 static gpointer register_assembly (MonoDomain *domain, MonoReflectionAssembly *res, MonoAssembly *assembly);
157 static void reflection_methodbuilder_from_method_builder (ReflectionMethodBuilder *rmb, MonoReflectionMethodBuilder *mb);
158 static void reflection_methodbuilder_from_ctor_builder (ReflectionMethodBuilder *rmb, MonoReflectionCtorBuilder *mb);
159 static guint32 create_generic_typespec (MonoDynamicImage *assembly, MonoReflectionTypeBuilder *tb);
160 #endif
161
162 static guint32 mono_image_typedef_or_ref (MonoDynamicImage *assembly, MonoType *type);
163 static guint32 mono_image_typedef_or_ref_full (MonoDynamicImage *assembly, MonoType *type, gboolean try_typespec);
164 static void    mono_image_get_generic_param_info (MonoReflectionGenericParam *gparam, guint32 owner, MonoDynamicImage *assembly);
165 static guint32 encode_marshal_blob (MonoDynamicImage *assembly, MonoReflectionMarshal *minfo);
166 static guint32 encode_constant (MonoDynamicImage *assembly, MonoObject *val, guint32 *ret_type);
167 static char*   type_get_qualified_name (MonoType *type, MonoAssembly *ass);
168 static void    encode_type (MonoDynamicImage *assembly, MonoType *type, SigBuffer *buf);
169 static void get_default_param_value_blobs (MonoMethod *method, char **blobs, guint32 *types);
170 static MonoReflectionType *mono_reflection_type_get_underlying_system_type (MonoReflectionType* t);
171 static MonoType* mono_reflection_get_type_with_rootimage (MonoImage *rootimage, MonoImage* image, MonoTypeNameParse *info, gboolean ignorecase, gboolean *type_resolve);
172 static MonoReflectionType* mono_reflection_type_resolve_user_types (MonoReflectionType *type);
173 static gboolean is_sre_array (MonoClass *class);
174 static gboolean is_sre_byref (MonoClass *class);
175 static gboolean is_sre_pointer (MonoClass *class);
176 static gboolean is_sre_type_builder (MonoClass *class);
177 static gboolean is_sre_method_builder (MonoClass *class);
178 static gboolean is_sre_ctor_builder (MonoClass *class);
179 static gboolean is_sre_field_builder (MonoClass *class);
180 static gboolean is_sr_mono_method (MonoClass *class);
181 static gboolean is_sr_mono_cmethod (MonoClass *class);
182 static gboolean is_sr_mono_generic_method (MonoClass *class);
183 static gboolean is_sr_mono_generic_cmethod (MonoClass *class);
184 static gboolean is_sr_mono_field (MonoClass *class);
185 static gboolean is_sr_mono_property (MonoClass *class);
186 static gboolean is_sre_method_on_tb_inst (MonoClass *class);
187 static gboolean is_sre_ctor_on_tb_inst (MonoClass *class);
188
189 static guint32 mono_image_get_methodspec_token (MonoDynamicImage *assembly, MonoMethod *method);
190 static guint32 mono_image_get_inflated_method_token (MonoDynamicImage *assembly, MonoMethod *m);
191 static MonoMethod * inflate_method (MonoReflectionType *type, MonoObject *obj);
192
193 static guint32 create_typespec (MonoDynamicImage *assembly, MonoType *type);
194 static void init_type_builder_generics (MonoObject *type);
195
196 #define RESOLVE_TYPE(type) do { type = (void*)mono_reflection_type_resolve_user_types ((MonoReflectionType*)type); } while (0)
197 #define RESOLVE_ARRAY_TYPE_ELEMENT(array, index) do {   \
198         MonoReflectionType *__type = mono_array_get (array, MonoReflectionType*, index);        \
199         __type = mono_reflection_type_resolve_user_types (__type);      \
200         mono_array_set (arr, MonoReflectionType*, index, __type);       \
201 } while (0)
202
203 #define mono_type_array_get_and_resolve(array, index) mono_reflection_type_get_handle ((MonoReflectionType*)mono_array_get (array, gpointer, index))
204
205 #define CHECK_ADD4_OVERFLOW_UN(a, b) ((guint32)(0xFFFFFFFFU) - (guint32)(b) < (guint32)(a))
206 #define CHECK_ADD8_OVERFLOW_UN(a, b) ((guint64)(0xFFFFFFFFFFFFFFFFUL) - (guint64)(b) < (guint64)(a))
207
208 #if SIZEOF_VOID_P == 4
209 #define CHECK_ADDP_OVERFLOW_UN(a,b) CHECK_ADD4_OVERFLOW_UN(a, b)
210 #else
211 #define CHECK_ADDP_OVERFLOW_UN(a,b) CHECK_ADD8_OVERFLOW_UN(a, b)
212 #endif
213
214 #define ADDP_IS_GREATER_OR_OVF(a, b, c) (((a) + (b) > (c)) || CHECK_ADDP_OVERFLOW_UN (a, b))
215 #define ADD_IS_GREATER_OR_OVF(a, b, c) (((a) + (b) > (c)) || CHECK_ADD4_OVERFLOW_UN (a, b))
216
217
218 void
219 mono_reflection_init (void)
220 {
221 }
222
223 static void
224 sigbuffer_init (SigBuffer *buf, int size)
225 {
226         buf->buf = g_malloc (size);
227         buf->p = buf->buf;
228         buf->end = buf->buf + size;
229 }
230
231 static void
232 sigbuffer_make_room (SigBuffer *buf, int size)
233 {
234         if (buf->end - buf->p < size) {
235                 int new_size = buf->end - buf->buf + size + 32;
236                 char *p = g_realloc (buf->buf, new_size);
237                 size = buf->p - buf->buf;
238                 buf->buf = p;
239                 buf->p = p + size;
240                 buf->end = buf->buf + new_size;
241         }
242 }
243
244 static void
245 sigbuffer_add_value (SigBuffer *buf, guint32 val)
246 {
247         sigbuffer_make_room (buf, 6);
248         mono_metadata_encode_value (val, buf->p, &buf->p);
249 }
250
251 static void
252 sigbuffer_add_byte (SigBuffer *buf, guint8 val)
253 {
254         sigbuffer_make_room (buf, 1);
255         buf->p [0] = val;
256         buf->p++;
257 }
258
259 static void
260 sigbuffer_add_mem (SigBuffer *buf, char *p, guint32 size)
261 {
262         sigbuffer_make_room (buf, size);
263         memcpy (buf->p, p, size);
264         buf->p += size;
265 }
266
267 static void
268 sigbuffer_free (SigBuffer *buf)
269 {
270         g_free (buf->buf);
271 }
272
273 #ifndef DISABLE_REFLECTION_EMIT
274 /**
275  * mp_g_alloc:
276  *
277  * Allocate memory from the @image mempool if it is non-NULL. Otherwise, allocate memory
278  * from the C heap.
279  */
280 static gpointer
281 image_g_malloc (MonoImage *image, guint size)
282 {
283         if (image)
284                 return mono_image_alloc (image, size);
285         else
286                 return g_malloc (size);
287 }
288 #endif /* !DISABLE_REFLECTION_EMIT */
289
290 /**
291  * image_g_alloc0:
292  *
293  * Allocate memory from the @image mempool if it is non-NULL. Otherwise, allocate memory
294  * from the C heap.
295  */
296 static gpointer
297 image_g_malloc0 (MonoImage *image, guint size)
298 {
299         if (image)
300                 return mono_image_alloc0 (image, size);
301         else
302                 return g_malloc0 (size);
303 }
304
305 #ifndef DISABLE_REFLECTION_EMIT
306 static char*
307 image_strdup (MonoImage *image, const char *s)
308 {
309         if (image)
310                 return mono_image_strdup (image, s);
311         else
312                 return g_strdup (s);
313 }
314 #endif
315
316 #define image_g_new(image,struct_type, n_structs)               \
317     ((struct_type *) image_g_malloc (image, ((gsize) sizeof (struct_type)) * ((gsize) (n_structs))))
318
319 #define image_g_new0(image,struct_type, n_structs)              \
320     ((struct_type *) image_g_malloc0 (image, ((gsize) sizeof (struct_type)) * ((gsize) (n_structs))))
321
322
323 static void
324 alloc_table (MonoDynamicTable *table, guint nrows)
325 {
326         table->rows = nrows;
327         g_assert (table->columns);
328         if (nrows + 1 >= table->alloc_rows) {
329                 while (nrows + 1 >= table->alloc_rows) {
330                         if (table->alloc_rows == 0)
331                                 table->alloc_rows = 16;
332                         else
333                                 table->alloc_rows *= 2;
334                 }
335
336                 table->values = g_renew (guint32, table->values, (table->alloc_rows) * table->columns);
337         }
338 }
339
340 static void
341 make_room_in_stream (MonoDynamicStream *stream, int size)
342 {
343         if (size <= stream->alloc_size)
344                 return;
345         
346         while (stream->alloc_size <= size) {
347                 if (stream->alloc_size < 4096)
348                         stream->alloc_size = 4096;
349                 else
350                         stream->alloc_size *= 2;
351         }
352         
353         stream->data = g_realloc (stream->data, stream->alloc_size);
354 }
355
356 static guint32
357 string_heap_insert (MonoDynamicStream *sh, const char *str)
358 {
359         guint32 idx;
360         guint32 len;
361         gpointer oldkey, oldval;
362
363         if (g_hash_table_lookup_extended (sh->hash, str, &oldkey, &oldval))
364                 return GPOINTER_TO_UINT (oldval);
365
366         len = strlen (str) + 1;
367         idx = sh->index;
368         
369         make_room_in_stream (sh, idx + len);
370
371         /*
372          * We strdup the string even if we already copy them in sh->data
373          * so that the string pointers in the hash remain valid even if
374          * we need to realloc sh->data. We may want to avoid that later.
375          */
376         g_hash_table_insert (sh->hash, g_strdup (str), GUINT_TO_POINTER (idx));
377         memcpy (sh->data + idx, str, len);
378         sh->index += len;
379         return idx;
380 }
381
382 static guint32
383 string_heap_insert_mstring (MonoDynamicStream *sh, MonoString *str)
384 {
385         char *name = mono_string_to_utf8 (str);
386         guint32 idx;
387         idx = string_heap_insert (sh, name);
388         g_free (name);
389         return idx;
390 }
391
392 #ifndef DISABLE_REFLECTION_EMIT
393 static void
394 string_heap_init (MonoDynamicStream *sh)
395 {
396         sh->index = 0;
397         sh->alloc_size = 4096;
398         sh->data = g_malloc (4096);
399         sh->hash = g_hash_table_new_full (g_str_hash, g_str_equal, g_free, NULL);
400         string_heap_insert (sh, "");
401 }
402 #endif
403
404 static guint32
405 mono_image_add_stream_data (MonoDynamicStream *stream, const char *data, guint32 len)
406 {
407         guint32 idx;
408         
409         make_room_in_stream (stream, stream->index + len);
410         memcpy (stream->data + stream->index, data, len);
411         idx = stream->index;
412         stream->index += len;
413         /* 
414          * align index? Not without adding an additional param that controls it since
415          * we may store a blob value in pieces.
416          */
417         return idx;
418 }
419
420 static guint32
421 mono_image_add_stream_zero (MonoDynamicStream *stream, guint32 len)
422 {
423         guint32 idx;
424         
425         make_room_in_stream (stream, stream->index + len);
426         memset (stream->data + stream->index, 0, len);
427         idx = stream->index;
428         stream->index += len;
429         return idx;
430 }
431
432 static void
433 stream_data_align (MonoDynamicStream *stream)
434 {
435         char buf [4] = {0};
436         guint32 count = stream->index % 4;
437
438         /* we assume the stream data will be aligned */
439         if (count)
440                 mono_image_add_stream_data (stream, buf, 4 - count);
441 }
442
443 #ifndef DISABLE_REFLECTION_EMIT
444 static int
445 mono_blob_entry_hash (const char* str)
446 {
447         guint len, h;
448         const char *end;
449         len = mono_metadata_decode_blob_size (str, &str);
450         if (len > 0) {
451                 end = str + len;
452                 h = *str;
453                 for (str += 1; str < end; str++)
454                         h = (h << 5) - h + *str;
455                 return h;
456         } else {
457                 return 0;
458         }
459 }
460
461 static gboolean
462 mono_blob_entry_equal (const char *str1, const char *str2) {
463         int len, len2;
464         const char *end1;
465         const char *end2;
466         len = mono_metadata_decode_blob_size (str1, &end1);
467         len2 = mono_metadata_decode_blob_size (str2, &end2);
468         if (len != len2)
469                 return 0;
470         return memcmp (end1, end2, len) == 0;
471 }
472 #endif
473 static guint32
474 add_to_blob_cached (MonoDynamicImage *assembly, char *b1, int s1, char *b2, int s2)
475 {
476         guint32 idx;
477         char *copy;
478         gpointer oldkey, oldval;
479
480         copy = g_malloc (s1+s2);
481         memcpy (copy, b1, s1);
482         memcpy (copy + s1, b2, s2);
483         if (g_hash_table_lookup_extended (assembly->blob_cache, copy, &oldkey, &oldval)) {
484                 g_free (copy);
485                 idx = GPOINTER_TO_UINT (oldval);
486         } else {
487                 idx = mono_image_add_stream_data (&assembly->blob, b1, s1);
488                 mono_image_add_stream_data (&assembly->blob, b2, s2);
489                 g_hash_table_insert (assembly->blob_cache, copy, GUINT_TO_POINTER (idx));
490         }
491         return idx;
492 }
493
494 static guint32
495 sigbuffer_add_to_blob_cached (MonoDynamicImage *assembly, SigBuffer *buf)
496 {
497         char blob_size [8];
498         char *b = blob_size;
499         guint32 size = buf->p - buf->buf;
500         /* store length */
501         g_assert (size <= (buf->end - buf->buf));
502         mono_metadata_encode_value (size, b, &b);
503         return add_to_blob_cached (assembly, blob_size, b-blob_size, buf->buf, size);
504 }
505
506 /*
507  * Copy len * nelem bytes from val to dest, swapping bytes to LE if necessary.
508  * dest may be misaligned.
509  */
510 static void
511 swap_with_size (char *dest, const char* val, int len, int nelem) {
512 #if G_BYTE_ORDER != G_LITTLE_ENDIAN
513         int elem;
514
515         for (elem = 0; elem < nelem; ++elem) {
516                 switch (len) {
517                 case 1:
518                         *dest = *val;
519                         break;
520                 case 2:
521                         dest [0] = val [1];
522                         dest [1] = val [0];
523                         break;
524                 case 4:
525                         dest [0] = val [3];
526                         dest [1] = val [2];
527                         dest [2] = val [1];
528                         dest [3] = val [0];
529                         break;
530                 case 8:
531                         dest [0] = val [7];
532                         dest [1] = val [6];
533                         dest [2] = val [5];
534                         dest [3] = val [4];
535                         dest [4] = val [3];
536                         dest [5] = val [2];
537                         dest [6] = val [1];
538                         dest [7] = val [0];
539                         break;
540                 default:
541                         g_assert_not_reached ();
542                 }
543                 dest += len;
544                 val += len;
545         }
546 #else
547         memcpy (dest, val, len * nelem);
548 #endif
549 }
550
551 static guint32
552 add_mono_string_to_blob_cached (MonoDynamicImage *assembly, MonoString *str)
553 {
554         char blob_size [64];
555         char *b = blob_size;
556         guint32 idx = 0, len;
557
558         len = str->length * 2;
559         mono_metadata_encode_value (len, b, &b);
560 #if G_BYTE_ORDER != G_LITTLE_ENDIAN
561         {
562                 char *swapped = g_malloc (2 * mono_string_length (str));
563                 const char *p = (const char*)mono_string_chars (str);
564
565                 swap_with_size (swapped, p, 2, mono_string_length (str));
566                 idx = add_to_blob_cached (assembly, blob_size, b-blob_size, swapped, len);
567                 g_free (swapped);
568         }
569 #else
570         idx = add_to_blob_cached (assembly, blob_size, b-blob_size, (char*)mono_string_chars (str), len);
571 #endif
572         return idx;
573 }
574
575 #ifndef DISABLE_REFLECTION_EMIT
576 static MonoClass *
577 default_class_from_mono_type (MonoType *type)
578 {
579         switch (type->type) {
580         case MONO_TYPE_OBJECT:
581                 return mono_defaults.object_class;
582         case MONO_TYPE_VOID:
583                 return mono_defaults.void_class;
584         case MONO_TYPE_BOOLEAN:
585                 return mono_defaults.boolean_class;
586         case MONO_TYPE_CHAR:
587                 return mono_defaults.char_class;
588         case MONO_TYPE_I1:
589                 return mono_defaults.sbyte_class;
590         case MONO_TYPE_U1:
591                 return mono_defaults.byte_class;
592         case MONO_TYPE_I2:
593                 return mono_defaults.int16_class;
594         case MONO_TYPE_U2:
595                 return mono_defaults.uint16_class;
596         case MONO_TYPE_I4:
597                 return mono_defaults.int32_class;
598         case MONO_TYPE_U4:
599                 return mono_defaults.uint32_class;
600         case MONO_TYPE_I:
601                 return mono_defaults.int_class;
602         case MONO_TYPE_U:
603                 return mono_defaults.uint_class;
604         case MONO_TYPE_I8:
605                 return mono_defaults.int64_class;
606         case MONO_TYPE_U8:
607                 return mono_defaults.uint64_class;
608         case MONO_TYPE_R4:
609                 return mono_defaults.single_class;
610         case MONO_TYPE_R8:
611                 return mono_defaults.double_class;
612         case MONO_TYPE_STRING:
613                 return mono_defaults.string_class;
614         default:
615                 g_warning ("default_class_from_mono_type: implement me 0x%02x\n", type->type);
616                 g_assert_not_reached ();
617         }
618         
619         return NULL;
620 }
621 #endif
622
623 /*
624  * mono_class_get_ref_info:
625  *
626  *   Return the type builder/generic param builder corresponding to KLASS, if it exists.
627  */
628 gpointer
629 mono_class_get_ref_info (MonoClass *klass)
630 {
631         if (klass->ref_info_handle == 0)
632                 return NULL;
633         else
634                 return mono_gchandle_get_target (klass->ref_info_handle);
635 }
636
637 void
638 mono_class_set_ref_info (MonoClass *klass, gpointer obj)
639 {
640         klass->ref_info_handle = mono_gchandle_new ((MonoObject*)obj, FALSE);
641         g_assert (klass->ref_info_handle != 0);
642 }
643
644 void
645 mono_class_free_ref_info (MonoClass *klass)
646 {
647         if (klass->ref_info_handle) {
648                 mono_gchandle_free (klass->ref_info_handle);
649                 klass->ref_info_handle = 0;
650         }
651 }
652
653 static void
654 encode_generic_class (MonoDynamicImage *assembly, MonoGenericClass *gclass, SigBuffer *buf)
655 {
656         int i;
657         MonoGenericInst *class_inst;
658         MonoClass *klass;
659
660         g_assert (gclass);
661
662         class_inst = gclass->context.class_inst;
663
664         sigbuffer_add_value (buf, MONO_TYPE_GENERICINST);
665         klass = gclass->container_class;
666         sigbuffer_add_value (buf, klass->byval_arg.type);
667         sigbuffer_add_value (buf, mono_image_typedef_or_ref_full (assembly, &klass->byval_arg, FALSE));
668
669         sigbuffer_add_value (buf, class_inst->type_argc);
670         for (i = 0; i < class_inst->type_argc; ++i)
671                 encode_type (assembly, class_inst->type_argv [i], buf);
672
673 }
674
675 static void
676 encode_type (MonoDynamicImage *assembly, MonoType *type, SigBuffer *buf)
677 {
678         if (!type) {
679                 g_assert_not_reached ();
680                 return;
681         }
682                 
683         if (type->byref)
684                 sigbuffer_add_value (buf, MONO_TYPE_BYREF);
685
686         switch (type->type){
687         case MONO_TYPE_VOID:
688         case MONO_TYPE_BOOLEAN:
689         case MONO_TYPE_CHAR:
690         case MONO_TYPE_I1:
691         case MONO_TYPE_U1:
692         case MONO_TYPE_I2:
693         case MONO_TYPE_U2:
694         case MONO_TYPE_I4:
695         case MONO_TYPE_U4:
696         case MONO_TYPE_I8:
697         case MONO_TYPE_U8:
698         case MONO_TYPE_R4:
699         case MONO_TYPE_R8:
700         case MONO_TYPE_I:
701         case MONO_TYPE_U:
702         case MONO_TYPE_STRING:
703         case MONO_TYPE_OBJECT:
704         case MONO_TYPE_TYPEDBYREF:
705                 sigbuffer_add_value (buf, type->type);
706                 break;
707         case MONO_TYPE_PTR:
708                 sigbuffer_add_value (buf, type->type);
709                 encode_type (assembly, type->data.type, buf);
710                 break;
711         case MONO_TYPE_SZARRAY:
712                 sigbuffer_add_value (buf, type->type);
713                 encode_type (assembly, &type->data.klass->byval_arg, buf);
714                 break;
715         case MONO_TYPE_VALUETYPE:
716         case MONO_TYPE_CLASS: {
717                 MonoClass *k = mono_class_from_mono_type (type);
718
719                 if (k->generic_container) {
720                         MonoGenericClass *gclass = mono_metadata_lookup_generic_class (k, k->generic_container->context.class_inst, TRUE);
721                         encode_generic_class (assembly, gclass, buf);
722                 } else {
723                         /*
724                          * Make sure we use the correct type.
725                          */
726                         sigbuffer_add_value (buf, k->byval_arg.type);
727                         /*
728                          * ensure only non-byref gets passed to mono_image_typedef_or_ref(),
729                          * otherwise two typerefs could point to the same type, leading to
730                          * verification errors.
731                          */
732                         sigbuffer_add_value (buf, mono_image_typedef_or_ref (assembly, &k->byval_arg));
733                 }
734                 break;
735         }
736         case MONO_TYPE_ARRAY:
737                 sigbuffer_add_value (buf, type->type);
738                 encode_type (assembly, &type->data.array->eklass->byval_arg, buf);
739                 sigbuffer_add_value (buf, type->data.array->rank);
740                 sigbuffer_add_value (buf, 0); /* FIXME: set to 0 for now */
741                 sigbuffer_add_value (buf, 0);
742                 break;
743         case MONO_TYPE_GENERICINST:
744                 encode_generic_class (assembly, type->data.generic_class, buf);
745                 break;
746         case MONO_TYPE_VAR:
747         case MONO_TYPE_MVAR:
748                 sigbuffer_add_value (buf, type->type);
749                 sigbuffer_add_value (buf, mono_type_get_generic_param_num (type));
750                 break;
751         default:
752                 g_error ("need to encode type %x", type->type);
753         }
754 }
755
756 static void
757 encode_reflection_type (MonoDynamicImage *assembly, MonoReflectionType *type, SigBuffer *buf)
758 {
759         if (!type) {
760                 sigbuffer_add_value (buf, MONO_TYPE_VOID);
761                 return;
762         }
763
764         encode_type (assembly, mono_reflection_type_get_handle (type), buf);
765 }
766
767 static void
768 encode_custom_modifiers (MonoDynamicImage *assembly, MonoArray *modreq, MonoArray *modopt, SigBuffer *buf)
769 {
770         int i;
771
772         if (modreq) {
773                 for (i = 0; i < mono_array_length (modreq); ++i) {
774                         MonoType *mod = mono_type_array_get_and_resolve (modreq, i);
775                         sigbuffer_add_byte (buf, MONO_TYPE_CMOD_REQD);
776                         sigbuffer_add_value (buf, mono_image_typedef_or_ref (assembly, mod));
777                 }
778         }
779         if (modopt) {
780                 for (i = 0; i < mono_array_length (modopt); ++i) {
781                         MonoType *mod = mono_type_array_get_and_resolve (modopt, i);
782                         sigbuffer_add_byte (buf, MONO_TYPE_CMOD_OPT);
783                         sigbuffer_add_value (buf, mono_image_typedef_or_ref (assembly, mod));
784                 }
785         }
786 }
787
788 #ifndef DISABLE_REFLECTION_EMIT
789 static guint32
790 method_encode_signature (MonoDynamicImage *assembly, MonoMethodSignature *sig)
791 {
792         SigBuffer buf;
793         int i;
794         guint32 nparams =  sig->param_count;
795         guint32 idx;
796
797         if (!assembly->save)
798                 return 0;
799
800         sigbuffer_init (&buf, 32);
801         /*
802          * FIXME: vararg, explicit_this, differenc call_conv values...
803          */
804         idx = sig->call_convention;
805         if (sig->hasthis)
806                 idx |= 0x20; /* hasthis */
807         if (sig->generic_param_count)
808                 idx |= 0x10; /* generic */
809         sigbuffer_add_byte (&buf, idx);
810         if (sig->generic_param_count)
811                 sigbuffer_add_value (&buf, sig->generic_param_count);
812         sigbuffer_add_value (&buf, nparams);
813         encode_type (assembly, sig->ret, &buf);
814         for (i = 0; i < nparams; ++i) {
815                 if (i == sig->sentinelpos)
816                         sigbuffer_add_byte (&buf, MONO_TYPE_SENTINEL);
817                 encode_type (assembly, sig->params [i], &buf);
818         }
819         idx = sigbuffer_add_to_blob_cached (assembly, &buf);
820         sigbuffer_free (&buf);
821         return idx;
822 }
823 #endif
824
825 static guint32
826 method_builder_encode_signature (MonoDynamicImage *assembly, ReflectionMethodBuilder *mb)
827 {
828         /*
829          * FIXME: reuse code from method_encode_signature().
830          */
831         SigBuffer buf;
832         int i;
833         guint32 nparams =  mb->parameters ? mono_array_length (mb->parameters): 0;
834         guint32 ngparams = mb->generic_params ? mono_array_length (mb->generic_params): 0;
835         guint32 notypes = mb->opt_types ? mono_array_length (mb->opt_types): 0;
836         guint32 idx;
837
838         sigbuffer_init (&buf, 32);
839         /* LAMESPEC: all the call conv spec is foobared */
840         idx = mb->call_conv & 0x60; /* has-this, explicit-this */
841         if (mb->call_conv & 2)
842                 idx |= 0x5; /* vararg */
843         if (!(mb->attrs & METHOD_ATTRIBUTE_STATIC))
844                 idx |= 0x20; /* hasthis */
845         if (ngparams)
846                 idx |= 0x10; /* generic */
847         sigbuffer_add_byte (&buf, idx);
848         if (ngparams)
849                 sigbuffer_add_value (&buf, ngparams);
850         sigbuffer_add_value (&buf, nparams + notypes);
851         encode_custom_modifiers (assembly, mb->return_modreq, mb->return_modopt, &buf);
852         encode_reflection_type (assembly, mb->rtype, &buf);
853         for (i = 0; i < nparams; ++i) {
854                 MonoArray *modreq = NULL;
855                 MonoArray *modopt = NULL;
856                 MonoReflectionType *pt;
857
858                 if (mb->param_modreq && (i < mono_array_length (mb->param_modreq)))
859                         modreq = mono_array_get (mb->param_modreq, MonoArray*, i);
860                 if (mb->param_modopt && (i < mono_array_length (mb->param_modopt)))
861                         modopt = mono_array_get (mb->param_modopt, MonoArray*, i);
862                 encode_custom_modifiers (assembly, modreq, modopt, &buf);
863                 pt = mono_array_get (mb->parameters, MonoReflectionType*, i);
864                 encode_reflection_type (assembly, pt, &buf);
865         }
866         if (notypes)
867                 sigbuffer_add_byte (&buf, MONO_TYPE_SENTINEL);
868         for (i = 0; i < notypes; ++i) {
869                 MonoReflectionType *pt;
870
871                 pt = mono_array_get (mb->opt_types, MonoReflectionType*, i);
872                 encode_reflection_type (assembly, pt, &buf);
873         }
874
875         idx = sigbuffer_add_to_blob_cached (assembly, &buf);
876         sigbuffer_free (&buf);
877         return idx;
878 }
879
880 static guint32
881 encode_locals (MonoDynamicImage *assembly, MonoReflectionILGen *ilgen)
882 {
883         MonoDynamicTable *table;
884         guint32 *values;
885         guint32 idx, sig_idx;
886         guint nl = mono_array_length (ilgen->locals);
887         SigBuffer buf;
888         int i;
889
890         sigbuffer_init (&buf, 32);
891         sigbuffer_add_value (&buf, 0x07);
892         sigbuffer_add_value (&buf, nl);
893         for (i = 0; i < nl; ++i) {
894                 MonoReflectionLocalBuilder *lb = mono_array_get (ilgen->locals, MonoReflectionLocalBuilder*, i);
895                 
896                 if (lb->is_pinned)
897                         sigbuffer_add_value (&buf, MONO_TYPE_PINNED);
898                 
899                 encode_reflection_type (assembly, (MonoReflectionType*)lb->type, &buf);
900         }
901         sig_idx = sigbuffer_add_to_blob_cached (assembly, &buf);
902         sigbuffer_free (&buf);
903
904         if (assembly->standalonesig_cache == NULL)
905                 assembly->standalonesig_cache = g_hash_table_new (NULL, NULL);
906         idx = GPOINTER_TO_UINT (g_hash_table_lookup (assembly->standalonesig_cache, GUINT_TO_POINTER (sig_idx)));
907         if (idx)
908                 return idx;
909
910         table = &assembly->tables [MONO_TABLE_STANDALONESIG];
911         idx = table->next_idx ++;
912         table->rows ++;
913         alloc_table (table, table->rows);
914         values = table->values + idx * MONO_STAND_ALONE_SIGNATURE_SIZE;
915
916         values [MONO_STAND_ALONE_SIGNATURE] = sig_idx;
917
918         g_hash_table_insert (assembly->standalonesig_cache, GUINT_TO_POINTER (sig_idx), GUINT_TO_POINTER (idx));
919
920         return idx;
921 }
922
923 static guint32
924 method_count_clauses (MonoReflectionILGen *ilgen)
925 {
926         guint32 num_clauses = 0;
927         int i;
928
929         MonoILExceptionInfo *ex_info;
930         for (i = 0; i < mono_array_length (ilgen->ex_handlers); ++i) {
931                 ex_info = (MonoILExceptionInfo*)mono_array_addr (ilgen->ex_handlers, MonoILExceptionInfo, i);
932                 if (ex_info->handlers)
933                         num_clauses += mono_array_length (ex_info->handlers);
934                 else
935                         num_clauses++;
936         }
937
938         return num_clauses;
939 }
940
941 #ifndef DISABLE_REFLECTION_EMIT
942 static MonoExceptionClause*
943 method_encode_clauses (MonoImage *image, MonoDynamicImage *assembly, MonoReflectionILGen *ilgen, guint32 num_clauses)
944 {
945         MonoExceptionClause *clauses;
946         MonoExceptionClause *clause;
947         MonoILExceptionInfo *ex_info;
948         MonoILExceptionBlock *ex_block;
949         guint32 finally_start;
950         int i, j, clause_index;;
951
952         clauses = image_g_new0 (image, MonoExceptionClause, num_clauses);
953
954         clause_index = 0;
955         for (i = mono_array_length (ilgen->ex_handlers) - 1; i >= 0; --i) {
956                 ex_info = (MonoILExceptionInfo*)mono_array_addr (ilgen->ex_handlers, MonoILExceptionInfo, i);
957                 finally_start = ex_info->start + ex_info->len;
958                 if (!ex_info->handlers)
959                         continue;
960                 for (j = 0; j < mono_array_length (ex_info->handlers); ++j) {
961                         ex_block = (MonoILExceptionBlock*)mono_array_addr (ex_info->handlers, MonoILExceptionBlock, j);
962                         clause = &(clauses [clause_index]);
963
964                         clause->flags = ex_block->type;
965                         clause->try_offset = ex_info->start;
966
967                         if (ex_block->type == MONO_EXCEPTION_CLAUSE_FINALLY)
968                                 clause->try_len = finally_start - ex_info->start;
969                         else
970                                 clause->try_len = ex_info->len;
971                         clause->handler_offset = ex_block->start;
972                         clause->handler_len = ex_block->len;
973                         if (ex_block->extype) {
974                                 clause->data.catch_class = mono_class_from_mono_type (mono_reflection_type_get_handle ((MonoReflectionType*)ex_block->extype));
975                         } else {
976                                 if (ex_block->type == MONO_EXCEPTION_CLAUSE_FILTER)
977                                         clause->data.filter_offset = ex_block->filter_offset;
978                                 else
979                                         clause->data.filter_offset = 0;
980                         }
981                         finally_start = ex_block->start + ex_block->len;
982
983                         clause_index ++;
984                 }
985         }
986
987         return clauses;
988 }
989 #endif /* !DISABLE_REFLECTION_EMIT */
990
991 static guint32
992 method_encode_code (MonoDynamicImage *assembly, ReflectionMethodBuilder *mb)
993 {
994         char flags = 0;
995         guint32 idx;
996         guint32 code_size;
997         gint32 max_stack, i;
998         gint32 num_locals = 0;
999         gint32 num_exception = 0;
1000         gint maybe_small;
1001         guint32 fat_flags;
1002         char fat_header [12];
1003         guint32 int_value;
1004         guint16 short_value;
1005         guint32 local_sig = 0;
1006         guint32 header_size = 12;
1007         MonoArray *code;
1008
1009         if ((mb->attrs & (METHOD_ATTRIBUTE_PINVOKE_IMPL | METHOD_ATTRIBUTE_ABSTRACT)) ||
1010                         (mb->iattrs & (METHOD_IMPL_ATTRIBUTE_INTERNAL_CALL | METHOD_IMPL_ATTRIBUTE_RUNTIME)))
1011                 return 0;
1012
1013         /*if (mb->name)
1014                 g_print ("Encode method %s\n", mono_string_to_utf8 (mb->name));*/
1015         if (mb->ilgen) {
1016                 code = mb->ilgen->code;
1017                 code_size = mb->ilgen->code_len;
1018                 max_stack = mb->ilgen->max_stack;
1019                 num_locals = mb->ilgen->locals ? mono_array_length (mb->ilgen->locals) : 0;
1020                 if (mb->ilgen->ex_handlers)
1021                         num_exception = method_count_clauses (mb->ilgen);
1022         } else {
1023                 code = mb->code;
1024                 if (code == NULL){
1025                         char *name = mono_string_to_utf8 (mb->name);
1026                         char *str = g_strdup_printf ("Method %s does not have any IL associated", name);
1027                         MonoException *exception = mono_get_exception_argument (NULL, "a method does not have any IL associated");
1028                         g_free (str);
1029                         g_free (name);
1030                         mono_raise_exception (exception);
1031                 }
1032
1033                 code_size = mono_array_length (code);
1034                 max_stack = 8; /* we probably need to run a verifier on the code... */
1035         }
1036
1037         stream_data_align (&assembly->code);
1038
1039         /* check for exceptions, maxstack, locals */
1040         maybe_small = (max_stack <= 8) && (!num_locals) && (!num_exception);
1041         if (maybe_small) {
1042                 if (code_size < 64 && !(code_size & 1)) {
1043                         flags = (code_size << 2) | 0x2;
1044                 } else if (code_size < 32 && (code_size & 1)) {
1045                         flags = (code_size << 2) | 0x6; /* LAMESPEC: see metadata.c */
1046                 } else {
1047                         goto fat_header;
1048                 }
1049                 idx = mono_image_add_stream_data (&assembly->code, &flags, 1);
1050                 /* add to the fixup todo list */
1051                 if (mb->ilgen && mb->ilgen->num_token_fixups)
1052                         mono_g_hash_table_insert (assembly->token_fixups, mb->ilgen, GUINT_TO_POINTER (idx + 1));
1053                 mono_image_add_stream_data (&assembly->code, mono_array_addr (code, char, 0), code_size);
1054                 return assembly->text_rva + idx;
1055         } 
1056 fat_header:
1057         if (num_locals)
1058                 local_sig = MONO_TOKEN_SIGNATURE | encode_locals (assembly, mb->ilgen);
1059         /* 
1060          * FIXME: need to set also the header size in fat_flags.
1061          * (and more sects and init locals flags)
1062          */
1063         fat_flags =  0x03;
1064         if (num_exception)
1065                 fat_flags |= METHOD_HEADER_MORE_SECTS;
1066         if (mb->init_locals)
1067                 fat_flags |= METHOD_HEADER_INIT_LOCALS;
1068         fat_header [0] = fat_flags;
1069         fat_header [1] = (header_size / 4 ) << 4;
1070         short_value = GUINT16_TO_LE (max_stack);
1071         memcpy (fat_header + 2, &short_value, 2);
1072         int_value = GUINT32_TO_LE (code_size);
1073         memcpy (fat_header + 4, &int_value, 4);
1074         int_value = GUINT32_TO_LE (local_sig);
1075         memcpy (fat_header + 8, &int_value, 4);
1076         idx = mono_image_add_stream_data (&assembly->code, fat_header, 12);
1077         /* add to the fixup todo list */
1078         if (mb->ilgen && mb->ilgen->num_token_fixups)
1079                 mono_g_hash_table_insert (assembly->token_fixups, mb->ilgen, GUINT_TO_POINTER (idx + 12));
1080         
1081         mono_image_add_stream_data (&assembly->code, mono_array_addr (code, char, 0), code_size);
1082         if (num_exception) {
1083                 unsigned char sheader [4];
1084                 MonoILExceptionInfo * ex_info;
1085                 MonoILExceptionBlock * ex_block;
1086                 int j;
1087
1088                 stream_data_align (&assembly->code);
1089                 /* always use fat format for now */
1090                 sheader [0] = METHOD_HEADER_SECTION_FAT_FORMAT | METHOD_HEADER_SECTION_EHTABLE;
1091                 num_exception *= 6 * sizeof (guint32);
1092                 num_exception += 4; /* include the size of the header */
1093                 sheader [1] = num_exception & 0xff;
1094                 sheader [2] = (num_exception >> 8) & 0xff;
1095                 sheader [3] = (num_exception >> 16) & 0xff;
1096                 mono_image_add_stream_data (&assembly->code, (char*)sheader, 4);
1097                 /* fat header, so we are already aligned */
1098                 /* reverse order */
1099                 for (i = mono_array_length (mb->ilgen->ex_handlers) - 1; i >= 0; --i) {
1100                         ex_info = (MonoILExceptionInfo *)mono_array_addr (mb->ilgen->ex_handlers, MonoILExceptionInfo, i);
1101                         if (ex_info->handlers) {
1102                                 int finally_start = ex_info->start + ex_info->len;
1103                                 for (j = 0; j < mono_array_length (ex_info->handlers); ++j) {
1104                                         guint32 val;
1105                                         ex_block = (MonoILExceptionBlock*)mono_array_addr (ex_info->handlers, MonoILExceptionBlock, j);
1106                                         /* the flags */
1107                                         val = GUINT32_TO_LE (ex_block->type);
1108                                         mono_image_add_stream_data (&assembly->code, (char*)&val, sizeof (guint32));
1109                                         /* try offset */
1110                                         val = GUINT32_TO_LE (ex_info->start);
1111                                         mono_image_add_stream_data (&assembly->code, (char*)&val, sizeof (guint32));
1112                                         /* need fault, too, probably */
1113                                         if (ex_block->type == MONO_EXCEPTION_CLAUSE_FINALLY)
1114                                                 val = GUINT32_TO_LE (finally_start - ex_info->start);
1115                                         else
1116                                                 val = GUINT32_TO_LE (ex_info->len);
1117                                         mono_image_add_stream_data (&assembly->code, (char*)&val, sizeof (guint32));
1118                                         /* handler offset */
1119                                         val = GUINT32_TO_LE (ex_block->start);
1120                                         mono_image_add_stream_data (&assembly->code, (char*)&val, sizeof (guint32));
1121                                         /* handler len */
1122                                         val = GUINT32_TO_LE (ex_block->len);
1123                                         mono_image_add_stream_data (&assembly->code, (char*)&val, sizeof (guint32));
1124                                         finally_start = ex_block->start + ex_block->len;
1125                                         if (ex_block->extype) {
1126                                                 val = mono_metadata_token_from_dor (mono_image_typedef_or_ref (assembly, mono_reflection_type_get_handle ((MonoReflectionType*)ex_block->extype)));
1127                                         } else {
1128                                                 if (ex_block->type == MONO_EXCEPTION_CLAUSE_FILTER)
1129                                                         val = ex_block->filter_offset;
1130                                                 else
1131                                                         val = 0;
1132                                         }
1133                                         val = GUINT32_TO_LE (val);
1134                                         mono_image_add_stream_data (&assembly->code, (char*)&val, sizeof (guint32));
1135                                         /*g_print ("out clause %d: from %d len=%d, handler at %d, %d, finally_start=%d, ex_info->start=%d, ex_info->len=%d, ex_block->type=%d, j=%d, i=%d\n", 
1136                                                         clause.flags, clause.try_offset, clause.try_len, clause.handler_offset, clause.handler_len, finally_start, ex_info->start, ex_info->len, ex_block->type, j, i);*/
1137                                 }
1138                         } else {
1139                                 g_error ("No clauses for ex info block %d", i);
1140                         }
1141                 }
1142         }
1143         return assembly->text_rva + idx;
1144 }
1145
1146 static guint32
1147 find_index_in_table (MonoDynamicImage *assembly, int table_idx, int col, guint32 token)
1148 {
1149         int i;
1150         MonoDynamicTable *table;
1151         guint32 *values;
1152         
1153         table = &assembly->tables [table_idx];
1154
1155         g_assert (col < table->columns);
1156
1157         values = table->values + table->columns;
1158         for (i = 1; i <= table->rows; ++i) {
1159                 if (values [col] == token)
1160                         return i;
1161                 values += table->columns;
1162         }
1163         return 0;
1164 }
1165
1166 /*
1167  * LOCKING: Acquires the loader lock. 
1168  */
1169 static MonoCustomAttrInfo*
1170 lookup_custom_attr (MonoImage *image, gpointer member)
1171 {
1172         MonoCustomAttrInfo* res;
1173
1174         res = mono_image_property_lookup (image, member, MONO_PROP_DYNAMIC_CATTR);
1175
1176         if (!res)
1177                 return NULL;
1178
1179         res = g_memdup (res, MONO_SIZEOF_CUSTOM_ATTR_INFO + sizeof (MonoCustomAttrEntry) * res->num_attrs);
1180         res->cached = 0;
1181         return res;
1182 }
1183
1184 static gboolean
1185 custom_attr_visible (MonoImage *image, MonoReflectionCustomAttr *cattr)
1186 {
1187         /* FIXME: Need to do more checks */
1188         if (cattr->ctor->method && (cattr->ctor->method->klass->image != image)) {
1189                 int visibility = cattr->ctor->method->klass->flags & TYPE_ATTRIBUTE_VISIBILITY_MASK;
1190
1191                 if ((visibility != TYPE_ATTRIBUTE_PUBLIC) && (visibility != TYPE_ATTRIBUTE_NESTED_PUBLIC))
1192                         return FALSE;
1193         }
1194
1195         return TRUE;
1196 }
1197
1198 static MonoCustomAttrInfo*
1199 mono_custom_attrs_from_builders (MonoImage *alloc_img, MonoImage *image, MonoArray *cattrs)
1200 {
1201         int i, index, count, not_visible;
1202         MonoCustomAttrInfo *ainfo;
1203         MonoReflectionCustomAttr *cattr;
1204
1205         if (!cattrs)
1206                 return NULL;
1207         /* FIXME: check in assembly the Run flag is set */
1208
1209         count = mono_array_length (cattrs);
1210
1211         /* Skip nonpublic attributes since MS.NET seems to do the same */
1212         /* FIXME: This needs to be done more globally */
1213         not_visible = 0;
1214         for (i = 0; i < count; ++i) {
1215                 cattr = (MonoReflectionCustomAttr*)mono_array_get (cattrs, gpointer, i);
1216                 if (!custom_attr_visible (image, cattr))
1217                         not_visible ++;
1218         }
1219         count -= not_visible;
1220
1221         ainfo = image_g_malloc0 (alloc_img, MONO_SIZEOF_CUSTOM_ATTR_INFO + sizeof (MonoCustomAttrEntry) * count);
1222
1223         ainfo->image = image;
1224         ainfo->num_attrs = count;
1225         ainfo->cached = alloc_img != NULL;
1226         index = 0;
1227         for (i = 0; i < count; ++i) {
1228                 cattr = (MonoReflectionCustomAttr*)mono_array_get (cattrs, gpointer, i);
1229                 if (custom_attr_visible (image, cattr)) {
1230                         unsigned char *saved = mono_image_alloc (image, mono_array_length (cattr->data));
1231                         memcpy (saved, mono_array_addr (cattr->data, char, 0), mono_array_length (cattr->data));
1232                         ainfo->attrs [index].ctor = cattr->ctor->method;
1233                         ainfo->attrs [index].data = saved;
1234                         ainfo->attrs [index].data_size = mono_array_length (cattr->data);
1235                         index ++;
1236                 }
1237         }
1238
1239         return ainfo;
1240 }
1241
1242 #ifndef DISABLE_REFLECTION_EMIT
1243 /*
1244  * LOCKING: Acquires the loader lock. 
1245  */
1246 static void
1247 mono_save_custom_attrs (MonoImage *image, void *obj, MonoArray *cattrs)
1248 {
1249         MonoCustomAttrInfo *ainfo, *tmp;
1250
1251         if (!cattrs || !mono_array_length (cattrs))
1252                 return;
1253
1254         ainfo = mono_custom_attrs_from_builders (image, image, cattrs);
1255
1256         mono_loader_lock ();
1257         tmp = mono_image_property_lookup (image, obj, MONO_PROP_DYNAMIC_CATTR);
1258         if (tmp)
1259                 mono_custom_attrs_free (tmp);
1260         mono_image_property_insert (image, obj, MONO_PROP_DYNAMIC_CATTR, ainfo);
1261         mono_loader_unlock ();
1262
1263 }
1264 #endif
1265
1266 void
1267 mono_custom_attrs_free (MonoCustomAttrInfo *ainfo)
1268 {
1269         if (!ainfo->cached)
1270                 g_free (ainfo);
1271 }
1272
1273 /*
1274  * idx is the table index of the object
1275  * type is one of MONO_CUSTOM_ATTR_*
1276  */
1277 static void
1278 mono_image_add_cattrs (MonoDynamicImage *assembly, guint32 idx, guint32 type, MonoArray *cattrs)
1279 {
1280         MonoDynamicTable *table;
1281         MonoReflectionCustomAttr *cattr;
1282         guint32 *values;
1283         guint32 count, i, token;
1284         char blob_size [6];
1285         char *p = blob_size;
1286         
1287         /* it is legal to pass a NULL cattrs: we avoid to use the if in a lot of places */
1288         if (!cattrs)
1289                 return;
1290         count = mono_array_length (cattrs);
1291         table = &assembly->tables [MONO_TABLE_CUSTOMATTRIBUTE];
1292         table->rows += count;
1293         alloc_table (table, table->rows);
1294         values = table->values + table->next_idx * MONO_CUSTOM_ATTR_SIZE;
1295         idx <<= MONO_CUSTOM_ATTR_BITS;
1296         idx |= type;
1297         for (i = 0; i < count; ++i) {
1298                 cattr = (MonoReflectionCustomAttr*)mono_array_get (cattrs, gpointer, i);
1299                 values [MONO_CUSTOM_ATTR_PARENT] = idx;
1300                 token = mono_image_create_token (assembly, (MonoObject*)cattr->ctor, FALSE, FALSE);
1301                 type = mono_metadata_token_index (token);
1302                 type <<= MONO_CUSTOM_ATTR_TYPE_BITS;
1303                 switch (mono_metadata_token_table (token)) {
1304                 case MONO_TABLE_METHOD:
1305                         type |= MONO_CUSTOM_ATTR_TYPE_METHODDEF;
1306                         /*
1307                          * fixup_cattrs () needs to fix this up. We can't use image->tokens, since it contains the old token for the
1308                          * method, not the one returned by mono_image_create_token ().
1309                          */
1310                         mono_g_hash_table_insert (assembly->remapped_tokens, GUINT_TO_POINTER (token), cattr->ctor);
1311                         break;
1312                 case MONO_TABLE_MEMBERREF:
1313                         type |= MONO_CUSTOM_ATTR_TYPE_MEMBERREF;
1314                         break;
1315                 default:
1316                         g_warning ("got wrong token in custom attr");
1317                         continue;
1318                 }
1319                 values [MONO_CUSTOM_ATTR_TYPE] = type;
1320                 p = blob_size;
1321                 mono_metadata_encode_value (mono_array_length (cattr->data), p, &p);
1322                 values [MONO_CUSTOM_ATTR_VALUE] = add_to_blob_cached (assembly, blob_size, p - blob_size,
1323                         mono_array_addr (cattr->data, char, 0), mono_array_length (cattr->data));
1324                 values += MONO_CUSTOM_ATTR_SIZE;
1325                 ++table->next_idx;
1326         }
1327 }
1328
1329 static void
1330 mono_image_add_decl_security (MonoDynamicImage *assembly, guint32 parent_token, MonoArray *permissions)
1331 {
1332         MonoDynamicTable *table;
1333         guint32 *values;
1334         guint32 count, i, idx;
1335         MonoReflectionPermissionSet *perm;
1336
1337         if (!permissions)
1338                 return;
1339
1340         count = mono_array_length (permissions);
1341         table = &assembly->tables [MONO_TABLE_DECLSECURITY];
1342         table->rows += count;
1343         alloc_table (table, table->rows);
1344
1345         for (i = 0; i < mono_array_length (permissions); ++i) {
1346                 perm = (MonoReflectionPermissionSet*)mono_array_addr (permissions, MonoReflectionPermissionSet, i);
1347
1348                 values = table->values + table->next_idx * MONO_DECL_SECURITY_SIZE;
1349
1350                 idx = mono_metadata_token_index (parent_token);
1351                 idx <<= MONO_HAS_DECL_SECURITY_BITS;
1352                 switch (mono_metadata_token_table (parent_token)) {
1353                 case MONO_TABLE_TYPEDEF:
1354                         idx |= MONO_HAS_DECL_SECURITY_TYPEDEF;
1355                         break;
1356                 case MONO_TABLE_METHOD:
1357                         idx |= MONO_HAS_DECL_SECURITY_METHODDEF;
1358                         break;
1359                 case MONO_TABLE_ASSEMBLY:
1360                         idx |= MONO_HAS_DECL_SECURITY_ASSEMBLY;
1361                         break;
1362                 default:
1363                         g_assert_not_reached ();
1364                 }
1365
1366                 values [MONO_DECL_SECURITY_ACTION] = perm->action;
1367                 values [MONO_DECL_SECURITY_PARENT] = idx;
1368                 values [MONO_DECL_SECURITY_PERMISSIONSET] = add_mono_string_to_blob_cached (assembly, perm->pset);
1369
1370                 ++table->next_idx;
1371         }
1372 }
1373
1374 /*
1375  * Fill in the MethodDef and ParamDef tables for a method.
1376  * This is used for both normal methods and constructors.
1377  */
1378 static void
1379 mono_image_basic_method (ReflectionMethodBuilder *mb, MonoDynamicImage *assembly)
1380 {
1381         MonoDynamicTable *table;
1382         guint32 *values;
1383         guint i, count;
1384
1385         /* room in this table is already allocated */
1386         table = &assembly->tables [MONO_TABLE_METHOD];
1387         *mb->table_idx = table->next_idx ++;
1388         g_hash_table_insert (assembly->method_to_table_idx, mb->mhandle, GUINT_TO_POINTER ((*mb->table_idx)));
1389         values = table->values + *mb->table_idx * MONO_METHOD_SIZE;
1390         values [MONO_METHOD_NAME] = string_heap_insert_mstring (&assembly->sheap, mb->name);
1391         values [MONO_METHOD_FLAGS] = mb->attrs;
1392         values [MONO_METHOD_IMPLFLAGS] = mb->iattrs;
1393         values [MONO_METHOD_SIGNATURE] = method_builder_encode_signature (assembly, mb);
1394         values [MONO_METHOD_RVA] = method_encode_code (assembly, mb);
1395         
1396         table = &assembly->tables [MONO_TABLE_PARAM];
1397         values [MONO_METHOD_PARAMLIST] = table->next_idx;
1398
1399         mono_image_add_decl_security (assembly, 
1400                 mono_metadata_make_token (MONO_TABLE_METHOD, *mb->table_idx), mb->permissions);
1401
1402         if (mb->pinfo) {
1403                 MonoDynamicTable *mtable;
1404                 guint32 *mvalues;
1405                 
1406                 mtable = &assembly->tables [MONO_TABLE_FIELDMARSHAL];
1407                 mvalues = mtable->values + mtable->next_idx * MONO_FIELD_MARSHAL_SIZE;
1408                 
1409                 count = 0;
1410                 for (i = 0; i < mono_array_length (mb->pinfo); ++i) {
1411                         if (mono_array_get (mb->pinfo, gpointer, i))
1412                                 count++;
1413                 }
1414                 table->rows += count;
1415                 alloc_table (table, table->rows);
1416                 values = table->values + table->next_idx * MONO_PARAM_SIZE;
1417                 for (i = 0; i < mono_array_length (mb->pinfo); ++i) {
1418                         MonoReflectionParamBuilder *pb;
1419                         if ((pb = mono_array_get (mb->pinfo, MonoReflectionParamBuilder*, i))) {
1420                                 values [MONO_PARAM_FLAGS] = pb->attrs;
1421                                 values [MONO_PARAM_SEQUENCE] = i;
1422                                 if (pb->name != NULL) {
1423                                         values [MONO_PARAM_NAME] = string_heap_insert_mstring (&assembly->sheap, pb->name);
1424                                 } else {
1425                                         values [MONO_PARAM_NAME] = 0;
1426                                 }
1427                                 values += MONO_PARAM_SIZE;
1428                                 if (pb->marshal_info) {
1429                                         mtable->rows++;
1430                                         alloc_table (mtable, mtable->rows);
1431                                         mvalues = mtable->values + mtable->rows * MONO_FIELD_MARSHAL_SIZE;
1432                                         mvalues [MONO_FIELD_MARSHAL_PARENT] = (table->next_idx << MONO_HAS_FIELD_MARSHAL_BITS) | MONO_HAS_FIELD_MARSHAL_PARAMDEF;
1433                                         mvalues [MONO_FIELD_MARSHAL_NATIVE_TYPE] = encode_marshal_blob (assembly, pb->marshal_info);
1434                                 }
1435                                 pb->table_idx = table->next_idx++;
1436                                 if (pb->attrs & PARAM_ATTRIBUTE_HAS_DEFAULT) {
1437                                         guint32 field_type = 0;
1438                                         mtable = &assembly->tables [MONO_TABLE_CONSTANT];
1439                                         mtable->rows ++;
1440                                         alloc_table (mtable, mtable->rows);
1441                                         mvalues = mtable->values + mtable->rows * MONO_CONSTANT_SIZE;
1442                                         mvalues [MONO_CONSTANT_PARENT] = MONO_HASCONSTANT_PARAM | (pb->table_idx << MONO_HASCONSTANT_BITS);
1443                                         mvalues [MONO_CONSTANT_VALUE] = encode_constant (assembly, pb->def_value, &field_type);
1444                                         mvalues [MONO_CONSTANT_TYPE] = field_type;
1445                                         mvalues [MONO_CONSTANT_PADDING] = 0;
1446                                 }
1447                         }
1448                 }
1449         }
1450 }
1451
1452 #ifndef DISABLE_REFLECTION_EMIT
1453 static void
1454 reflection_methodbuilder_from_method_builder (ReflectionMethodBuilder *rmb, MonoReflectionMethodBuilder *mb)
1455 {
1456         memset (rmb, 0, sizeof (ReflectionMethodBuilder));
1457
1458         rmb->ilgen = mb->ilgen;
1459         rmb->rtype = mono_reflection_type_resolve_user_types ((MonoReflectionType*)mb->rtype);
1460         rmb->parameters = mb->parameters;
1461         rmb->generic_params = mb->generic_params;
1462         rmb->generic_container = mb->generic_container;
1463         rmb->opt_types = NULL;
1464         rmb->pinfo = mb->pinfo;
1465         rmb->attrs = mb->attrs;
1466         rmb->iattrs = mb->iattrs;
1467         rmb->call_conv = mb->call_conv;
1468         rmb->code = mb->code;
1469         rmb->type = mb->type;
1470         rmb->name = mb->name;
1471         rmb->table_idx = &mb->table_idx;
1472         rmb->init_locals = mb->init_locals;
1473         rmb->skip_visibility = FALSE;
1474         rmb->return_modreq = mb->return_modreq;
1475         rmb->return_modopt = mb->return_modopt;
1476         rmb->param_modreq = mb->param_modreq;
1477         rmb->param_modopt = mb->param_modopt;
1478         rmb->permissions = mb->permissions;
1479         rmb->mhandle = mb->mhandle;
1480         rmb->nrefs = 0;
1481         rmb->refs = NULL;
1482
1483         if (mb->dll) {
1484                 rmb->charset = mb->charset;
1485                 rmb->extra_flags = mb->extra_flags;
1486                 rmb->native_cc = mb->native_cc;
1487                 rmb->dllentry = mb->dllentry;
1488                 rmb->dll = mb->dll;
1489         }
1490 }
1491
1492 static void
1493 reflection_methodbuilder_from_ctor_builder (ReflectionMethodBuilder *rmb, MonoReflectionCtorBuilder *mb)
1494 {
1495         const char *name = mb->attrs & METHOD_ATTRIBUTE_STATIC ? ".cctor": ".ctor";
1496
1497         memset (rmb, 0, sizeof (ReflectionMethodBuilder));
1498
1499         rmb->ilgen = mb->ilgen;
1500         rmb->rtype = mono_type_get_object (mono_domain_get (), &mono_defaults.void_class->byval_arg);
1501         rmb->parameters = mb->parameters;
1502         rmb->generic_params = NULL;
1503         rmb->generic_container = NULL;
1504         rmb->opt_types = NULL;
1505         rmb->pinfo = mb->pinfo;
1506         rmb->attrs = mb->attrs;
1507         rmb->iattrs = mb->iattrs;
1508         rmb->call_conv = mb->call_conv;
1509         rmb->code = NULL;
1510         rmb->type = mb->type;
1511         rmb->name = mono_string_new (mono_domain_get (), name);
1512         rmb->table_idx = &mb->table_idx;
1513         rmb->init_locals = mb->init_locals;
1514         rmb->skip_visibility = FALSE;
1515         rmb->return_modreq = NULL;
1516         rmb->return_modopt = NULL;
1517         rmb->param_modreq = mb->param_modreq;
1518         rmb->param_modopt = mb->param_modopt;
1519         rmb->permissions = mb->permissions;
1520         rmb->mhandle = mb->mhandle;
1521         rmb->nrefs = 0;
1522         rmb->refs = NULL;
1523 }
1524
1525 static void
1526 reflection_methodbuilder_from_dynamic_method (ReflectionMethodBuilder *rmb, MonoReflectionDynamicMethod *mb)
1527 {
1528         memset (rmb, 0, sizeof (ReflectionMethodBuilder));
1529
1530         rmb->ilgen = mb->ilgen;
1531         rmb->rtype = mb->rtype;
1532         rmb->parameters = mb->parameters;
1533         rmb->generic_params = NULL;
1534         rmb->generic_container = NULL;
1535         rmb->opt_types = NULL;
1536         rmb->pinfo = NULL;
1537         rmb->attrs = mb->attrs;
1538         rmb->iattrs = 0;
1539         rmb->call_conv = mb->call_conv;
1540         rmb->code = NULL;
1541         rmb->type = (MonoObject *) mb->owner;
1542         rmb->name = mb->name;
1543         rmb->table_idx = NULL;
1544         rmb->init_locals = mb->init_locals;
1545         rmb->skip_visibility = mb->skip_visibility;
1546         rmb->return_modreq = NULL;
1547         rmb->return_modopt = NULL;
1548         rmb->param_modreq = NULL;
1549         rmb->param_modopt = NULL;
1550         rmb->permissions = NULL;
1551         rmb->mhandle = mb->mhandle;
1552         rmb->nrefs = 0;
1553         rmb->refs = NULL;
1554 }       
1555 #endif
1556
1557 static void
1558 mono_image_add_methodimpl (MonoDynamicImage *assembly, MonoReflectionMethodBuilder *mb)
1559 {
1560         MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder *)mb->type;
1561         MonoDynamicTable *table;
1562         guint32 *values;
1563         guint32 tok;
1564         MonoReflectionMethod *m;
1565         int i;
1566
1567         if (!mb->override_methods)
1568                 return;
1569
1570         for (i = 0; i < mono_array_length (mb->override_methods); ++i) {
1571                 m = mono_array_get (mb->override_methods, MonoReflectionMethod*, i);
1572
1573                 table = &assembly->tables [MONO_TABLE_METHODIMPL];
1574                 table->rows ++;
1575                 alloc_table (table, table->rows);
1576                 values = table->values + table->rows * MONO_METHODIMPL_SIZE;
1577                 values [MONO_METHODIMPL_CLASS] = tb->table_idx;
1578                 values [MONO_METHODIMPL_BODY] = MONO_METHODDEFORREF_METHODDEF | (mb->table_idx << MONO_METHODDEFORREF_BITS);
1579
1580                 tok = mono_image_create_token (assembly, (MonoObject*)m, FALSE, FALSE);
1581                 switch (mono_metadata_token_table (tok)) {
1582                 case MONO_TABLE_MEMBERREF:
1583                         tok = (mono_metadata_token_index (tok) << MONO_METHODDEFORREF_BITS ) | MONO_METHODDEFORREF_METHODREF;
1584                         break;
1585                 case MONO_TABLE_METHOD:
1586                         tok = (mono_metadata_token_index (tok) << MONO_METHODDEFORREF_BITS ) | MONO_METHODDEFORREF_METHODDEF;
1587                         break;
1588                 default:
1589                         g_assert_not_reached ();
1590                 }
1591                 values [MONO_METHODIMPL_DECLARATION] = tok;
1592         }
1593 }
1594
1595 #ifndef DISABLE_REFLECTION_EMIT
1596 static void
1597 mono_image_get_method_info (MonoReflectionMethodBuilder *mb, MonoDynamicImage *assembly)
1598 {
1599         MonoDynamicTable *table;
1600         guint32 *values;
1601         ReflectionMethodBuilder rmb;
1602         int i;
1603
1604         reflection_methodbuilder_from_method_builder (&rmb, mb);
1605
1606         mono_image_basic_method (&rmb, assembly);
1607         mb->table_idx = *rmb.table_idx;
1608
1609         if (mb->dll) { /* It's a P/Invoke method */
1610                 guint32 moduleref;
1611                 /* map CharSet values to on-disk values */
1612                 int ncharset = (mb->charset ? (mb->charset - 1) * 2 : 0);
1613                 int extra_flags = mb->extra_flags;
1614                 table = &assembly->tables [MONO_TABLE_IMPLMAP];
1615                 table->rows ++;
1616                 alloc_table (table, table->rows);
1617                 values = table->values + table->rows * MONO_IMPLMAP_SIZE;
1618                 
1619                 values [MONO_IMPLMAP_FLAGS] = (mb->native_cc << 8) | ncharset | extra_flags;
1620                 values [MONO_IMPLMAP_MEMBER] = (mb->table_idx << 1) | 1; /* memberforwarded: method */
1621                 if (mb->dllentry)
1622                         values [MONO_IMPLMAP_NAME] = string_heap_insert_mstring (&assembly->sheap, mb->dllentry);
1623                 else
1624                         values [MONO_IMPLMAP_NAME] = string_heap_insert_mstring (&assembly->sheap, mb->name);
1625                 moduleref = string_heap_insert_mstring (&assembly->sheap, mb->dll);
1626                 if (!(values [MONO_IMPLMAP_SCOPE] = find_index_in_table (assembly, MONO_TABLE_MODULEREF, MONO_MODULEREF_NAME, moduleref))) {
1627                         table = &assembly->tables [MONO_TABLE_MODULEREF];
1628                         table->rows ++;
1629                         alloc_table (table, table->rows);
1630                         table->values [table->rows * MONO_MODULEREF_SIZE + MONO_MODULEREF_NAME] = moduleref;
1631                         values [MONO_IMPLMAP_SCOPE] = table->rows;
1632                 }
1633         }
1634
1635         if (mb->generic_params) {
1636                 table = &assembly->tables [MONO_TABLE_GENERICPARAM];
1637                 table->rows += mono_array_length (mb->generic_params);
1638                 alloc_table (table, table->rows);
1639                 for (i = 0; i < mono_array_length (mb->generic_params); ++i) {
1640                         guint32 owner = MONO_TYPEORMETHOD_METHOD | (mb->table_idx << MONO_TYPEORMETHOD_BITS);
1641
1642                         mono_image_get_generic_param_info (
1643                                 mono_array_get (mb->generic_params, gpointer, i), owner, assembly);
1644                 }
1645         }
1646
1647 }
1648
1649 static void
1650 mono_image_get_ctor_info (MonoDomain *domain, MonoReflectionCtorBuilder *mb, MonoDynamicImage *assembly)
1651 {
1652         ReflectionMethodBuilder rmb;
1653
1654         reflection_methodbuilder_from_ctor_builder (&rmb, mb);
1655
1656         mono_image_basic_method (&rmb, assembly);
1657         mb->table_idx = *rmb.table_idx;
1658 }
1659 #endif
1660
1661 static char*
1662 type_get_fully_qualified_name (MonoType *type)
1663 {
1664         return mono_type_get_name_full (type, MONO_TYPE_NAME_FORMAT_ASSEMBLY_QUALIFIED);
1665 }
1666
1667 static char*
1668 type_get_qualified_name (MonoType *type, MonoAssembly *ass) {
1669         MonoClass *klass;
1670         MonoAssembly *ta;
1671
1672         klass = mono_class_from_mono_type (type);
1673         if (!klass) 
1674                 return mono_type_get_name_full (type, MONO_TYPE_NAME_FORMAT_REFLECTION);
1675         ta = klass->image->assembly;
1676         if (ta->dynamic || (ta == ass)) {
1677                 if (klass->generic_class || klass->generic_container)
1678                         /* For generic type definitions, we want T, while REFLECTION returns T<K> */
1679                         return mono_type_get_name_full (type, MONO_TYPE_NAME_FORMAT_FULL_NAME);
1680                 else
1681                         return mono_type_get_name_full (type, MONO_TYPE_NAME_FORMAT_REFLECTION);
1682         }
1683
1684         return mono_type_get_name_full (type, MONO_TYPE_NAME_FORMAT_ASSEMBLY_QUALIFIED);
1685 }
1686
1687 #ifndef DISABLE_REFLECTION_EMIT
1688 /*field_image is the image to which the eventual custom mods have been encoded against*/
1689 static guint32
1690 fieldref_encode_signature (MonoDynamicImage *assembly, MonoImage *field_image, MonoType *type)
1691 {
1692         SigBuffer buf;
1693         guint32 idx, i, token;
1694
1695         if (!assembly->save)
1696                 return 0;
1697
1698         sigbuffer_init (&buf, 32);
1699         
1700         sigbuffer_add_value (&buf, 0x06);
1701         /* encode custom attributes before the type */
1702         if (type->num_mods) {
1703                 for (i = 0; i < type->num_mods; ++i) {
1704                         if (field_image) {
1705                                 MonoClass *class = mono_class_get (field_image, type->modifiers [i].token);
1706                                 g_assert (class);
1707                                 token = mono_image_typedef_or_ref (assembly, &class->byval_arg);
1708                         } else {
1709                                 token = type->modifiers [i].token;
1710                         }
1711
1712                         if (type->modifiers [i].required)
1713                                 sigbuffer_add_byte (&buf, MONO_TYPE_CMOD_REQD);
1714                         else
1715                                 sigbuffer_add_byte (&buf, MONO_TYPE_CMOD_OPT);
1716
1717                         sigbuffer_add_value (&buf, token);
1718                 }
1719         }
1720         encode_type (assembly, type, &buf);
1721         idx = sigbuffer_add_to_blob_cached (assembly, &buf);
1722         sigbuffer_free (&buf);
1723         return idx;
1724 }
1725 #endif
1726
1727 static guint32
1728 field_encode_signature (MonoDynamicImage *assembly, MonoReflectionFieldBuilder *fb)
1729 {
1730         SigBuffer buf;
1731         guint32 idx;
1732         guint32 typespec = 0;
1733         MonoType *type;
1734         MonoClass *class;
1735
1736         init_type_builder_generics (fb->type);
1737
1738         type = mono_reflection_type_get_handle ((MonoReflectionType*)fb->type);
1739         class = mono_class_from_mono_type (type);
1740
1741         sigbuffer_init (&buf, 32);
1742         
1743         sigbuffer_add_value (&buf, 0x06);
1744         encode_custom_modifiers (assembly, fb->modreq, fb->modopt, &buf);
1745         /* encode custom attributes before the type */
1746
1747         if (class->generic_container)
1748                 typespec = create_typespec (assembly, type);
1749
1750         if (typespec) {
1751                 MonoGenericClass *gclass;
1752                 gclass = mono_metadata_lookup_generic_class (class, class->generic_container->context.class_inst, TRUE);
1753                 encode_generic_class (assembly, gclass, &buf);
1754         } else {
1755                 encode_type (assembly, type, &buf);
1756         }
1757         idx = sigbuffer_add_to_blob_cached (assembly, &buf);
1758         sigbuffer_free (&buf);
1759         return idx;
1760 }
1761
1762 static guint32
1763 encode_constant (MonoDynamicImage *assembly, MonoObject *val, guint32 *ret_type) {
1764         char blob_size [64];
1765         char *b = blob_size;
1766         char *p, *box_val;
1767         char* buf;
1768         guint32 idx = 0, len = 0, dummy = 0;
1769
1770         p = buf = g_malloc (64);
1771         if (!val) {
1772                 *ret_type = MONO_TYPE_CLASS;
1773                 len = 4;
1774                 box_val = (char*)&dummy;
1775         } else {
1776                 box_val = ((char*)val) + sizeof (MonoObject);
1777                 *ret_type = val->vtable->klass->byval_arg.type;
1778         }
1779 handle_enum:
1780         switch (*ret_type) {
1781         case MONO_TYPE_BOOLEAN:
1782         case MONO_TYPE_U1:
1783         case MONO_TYPE_I1:
1784                 len = 1;
1785                 break;
1786         case MONO_TYPE_CHAR:
1787         case MONO_TYPE_U2:
1788         case MONO_TYPE_I2:
1789                 len = 2;
1790                 break;
1791         case MONO_TYPE_U4:
1792         case MONO_TYPE_I4:
1793         case MONO_TYPE_R4:
1794                 len = 4;
1795                 break;
1796         case MONO_TYPE_U8:
1797         case MONO_TYPE_I8:
1798                 len = 8;
1799                 break;
1800         case MONO_TYPE_R8:
1801                 len = 8;
1802                 break;
1803         case MONO_TYPE_VALUETYPE: {
1804                 MonoClass *klass = val->vtable->klass;
1805                 
1806                 if (klass->enumtype) {
1807                         *ret_type = mono_class_enum_basetype (klass)->type;
1808                         goto handle_enum;
1809                 } else if (mono_is_corlib_image (klass->image) && strcmp (klass->name_space, "System") == 0 && strcmp (klass->name, "DateTime") == 0) {
1810                         len = 8;
1811                 } else 
1812                         g_error ("we can't encode valuetypes, we should have never reached this line");
1813                 break;
1814         }
1815         case MONO_TYPE_CLASS:
1816                 break;
1817         case MONO_TYPE_STRING: {
1818                 MonoString *str = (MonoString*)val;
1819                 /* there is no signature */
1820                 len = str->length * 2;
1821                 mono_metadata_encode_value (len, b, &b);
1822 #if G_BYTE_ORDER != G_LITTLE_ENDIAN
1823                 {
1824                         char *swapped = g_malloc (2 * mono_string_length (str));
1825                         const char *p = (const char*)mono_string_chars (str);
1826
1827                         swap_with_size (swapped, p, 2, mono_string_length (str));
1828                         idx = add_to_blob_cached (assembly, blob_size, b-blob_size, swapped, len);
1829                         g_free (swapped);
1830                 }
1831 #else
1832                 idx = add_to_blob_cached (assembly, blob_size, b-blob_size, (char*)mono_string_chars (str), len);
1833 #endif
1834
1835                 g_free (buf);
1836                 return idx;
1837         }
1838         case MONO_TYPE_GENERICINST:
1839                 *ret_type = val->vtable->klass->generic_class->container_class->byval_arg.type;
1840                 goto handle_enum;
1841         default:
1842                 g_error ("we don't encode constant type 0x%02x yet", *ret_type);
1843         }
1844
1845         /* there is no signature */
1846         mono_metadata_encode_value (len, b, &b);
1847 #if G_BYTE_ORDER != G_LITTLE_ENDIAN
1848         idx = mono_image_add_stream_data (&assembly->blob, blob_size, b-blob_size);
1849         swap_with_size (blob_size, box_val, len, 1);
1850         mono_image_add_stream_data (&assembly->blob, blob_size, len);
1851 #else
1852         idx = add_to_blob_cached (assembly, blob_size, b-blob_size, box_val, len);
1853 #endif
1854
1855         g_free (buf);
1856         return idx;
1857 }
1858
1859 static guint32
1860 encode_marshal_blob (MonoDynamicImage *assembly, MonoReflectionMarshal *minfo) {
1861         char *str;
1862         SigBuffer buf;
1863         guint32 idx, len;
1864
1865         sigbuffer_init (&buf, 32);
1866
1867         sigbuffer_add_value (&buf, minfo->type);
1868
1869         switch (minfo->type) {
1870         case MONO_NATIVE_BYVALTSTR:
1871         case MONO_NATIVE_BYVALARRAY:
1872                 sigbuffer_add_value (&buf, minfo->count);
1873                 break;
1874         case MONO_NATIVE_LPARRAY:
1875                 if (minfo->eltype || minfo->has_size) {
1876                         sigbuffer_add_value (&buf, minfo->eltype);
1877                         if (minfo->has_size) {
1878                                 sigbuffer_add_value (&buf, minfo->param_num != -1? minfo->param_num: 0);
1879                                 sigbuffer_add_value (&buf, minfo->count != -1? minfo->count: 0);
1880
1881                                 /* LAMESPEC: ElemMult is undocumented */
1882                                 sigbuffer_add_value (&buf, minfo->param_num != -1? 1: 0);
1883                         }
1884                 }
1885                 break;
1886         case MONO_NATIVE_SAFEARRAY:
1887                 if (minfo->eltype)
1888                         sigbuffer_add_value (&buf, minfo->eltype);
1889                 break;
1890         case MONO_NATIVE_CUSTOM:
1891                 if (minfo->guid) {
1892                         str = mono_string_to_utf8 (minfo->guid);
1893                         len = strlen (str);
1894                         sigbuffer_add_value (&buf, len);
1895                         sigbuffer_add_mem (&buf, str, len);
1896                         g_free (str);
1897                 } else {
1898                         sigbuffer_add_value (&buf, 0);
1899                 }
1900                 /* native type name */
1901                 sigbuffer_add_value (&buf, 0);
1902                 /* custom marshaler type name */
1903                 if (minfo->marshaltype || minfo->marshaltyperef) {
1904                         if (minfo->marshaltyperef)
1905                                 str = type_get_fully_qualified_name (mono_reflection_type_get_handle ((MonoReflectionType*)minfo->marshaltyperef));
1906                         else
1907                                 str = mono_string_to_utf8 (minfo->marshaltype);
1908                         len = strlen (str);
1909                         sigbuffer_add_value (&buf, len);
1910                         sigbuffer_add_mem (&buf, str, len);
1911                         g_free (str);
1912                 } else {
1913                         /* FIXME: Actually a bug, since this field is required.  Punting for now ... */
1914                         sigbuffer_add_value (&buf, 0);
1915                 }
1916                 if (minfo->mcookie) {
1917                         str = mono_string_to_utf8 (minfo->mcookie);
1918                         len = strlen (str);
1919                         sigbuffer_add_value (&buf, len);
1920                         sigbuffer_add_mem (&buf, str, len);
1921                         g_free (str);
1922                 } else {
1923                         sigbuffer_add_value (&buf, 0);
1924                 }
1925                 break;
1926         default:
1927                 break;
1928         }
1929         idx = sigbuffer_add_to_blob_cached (assembly, &buf);
1930         sigbuffer_free (&buf);
1931         return idx;
1932 }
1933
1934 static void
1935 mono_image_get_field_info (MonoReflectionFieldBuilder *fb, MonoDynamicImage *assembly)
1936 {
1937         MonoDynamicTable *table;
1938         guint32 *values;
1939
1940         /* maybe this fixup should be done in the C# code */
1941         if (fb->attrs & FIELD_ATTRIBUTE_LITERAL)
1942                 fb->attrs |= FIELD_ATTRIBUTE_HAS_DEFAULT;
1943         table = &assembly->tables [MONO_TABLE_FIELD];
1944         fb->table_idx = table->next_idx ++;
1945         g_hash_table_insert (assembly->field_to_table_idx, fb->handle, GUINT_TO_POINTER (fb->table_idx));
1946         values = table->values + fb->table_idx * MONO_FIELD_SIZE;
1947         values [MONO_FIELD_NAME] = string_heap_insert_mstring (&assembly->sheap, fb->name);
1948         values [MONO_FIELD_FLAGS] = fb->attrs;
1949         values [MONO_FIELD_SIGNATURE] = field_encode_signature (assembly, fb);
1950
1951         if (fb->offset != -1) {
1952                 table = &assembly->tables [MONO_TABLE_FIELDLAYOUT];
1953                 table->rows ++;
1954                 alloc_table (table, table->rows);
1955                 values = table->values + table->rows * MONO_FIELD_LAYOUT_SIZE;
1956                 values [MONO_FIELD_LAYOUT_FIELD] = fb->table_idx;
1957                 values [MONO_FIELD_LAYOUT_OFFSET] = fb->offset;
1958         }
1959         if (fb->attrs & FIELD_ATTRIBUTE_LITERAL) {
1960                 guint32 field_type = 0;
1961                 table = &assembly->tables [MONO_TABLE_CONSTANT];
1962                 table->rows ++;
1963                 alloc_table (table, table->rows);
1964                 values = table->values + table->rows * MONO_CONSTANT_SIZE;
1965                 values [MONO_CONSTANT_PARENT] = MONO_HASCONSTANT_FIEDDEF | (fb->table_idx << MONO_HASCONSTANT_BITS);
1966                 values [MONO_CONSTANT_VALUE] = encode_constant (assembly, fb->def_value, &field_type);
1967                 values [MONO_CONSTANT_TYPE] = field_type;
1968                 values [MONO_CONSTANT_PADDING] = 0;
1969         }
1970         if (fb->attrs & FIELD_ATTRIBUTE_HAS_FIELD_RVA) {
1971                 guint32 rva_idx;
1972                 table = &assembly->tables [MONO_TABLE_FIELDRVA];
1973                 table->rows ++;
1974                 alloc_table (table, table->rows);
1975                 values = table->values + table->rows * MONO_FIELD_RVA_SIZE;
1976                 values [MONO_FIELD_RVA_FIELD] = fb->table_idx;
1977                 /*
1978                  * We store it in the code section because it's simpler for now.
1979                  */
1980                 if (fb->rva_data) {
1981                         if (mono_array_length (fb->rva_data) >= 10)
1982                                 stream_data_align (&assembly->code);
1983                         rva_idx = mono_image_add_stream_data (&assembly->code, mono_array_addr (fb->rva_data, char, 0), mono_array_length (fb->rva_data));
1984                 } else
1985                         rva_idx = mono_image_add_stream_zero (&assembly->code, mono_class_value_size (fb->handle->parent, NULL));
1986                 values [MONO_FIELD_RVA_RVA] = rva_idx + assembly->text_rva;
1987         }
1988         if (fb->marshal_info) {
1989                 table = &assembly->tables [MONO_TABLE_FIELDMARSHAL];
1990                 table->rows ++;
1991                 alloc_table (table, table->rows);
1992                 values = table->values + table->rows * MONO_FIELD_MARSHAL_SIZE;
1993                 values [MONO_FIELD_MARSHAL_PARENT] = (fb->table_idx << MONO_HAS_FIELD_MARSHAL_BITS) | MONO_HAS_FIELD_MARSHAL_FIELDSREF;
1994                 values [MONO_FIELD_MARSHAL_NATIVE_TYPE] = encode_marshal_blob (assembly, fb->marshal_info);
1995         }
1996 }
1997
1998 static guint32
1999 property_encode_signature (MonoDynamicImage *assembly, MonoReflectionPropertyBuilder *fb)
2000 {
2001         SigBuffer buf;
2002         guint32 nparams = 0;
2003         MonoReflectionMethodBuilder *mb = fb->get_method;
2004         MonoReflectionMethodBuilder *smb = fb->set_method;
2005         guint32 idx, i;
2006
2007         if (mb && mb->parameters)
2008                 nparams = mono_array_length (mb->parameters);
2009         if (!mb && smb && smb->parameters)
2010                 nparams = mono_array_length (smb->parameters) - 1;
2011         sigbuffer_init (&buf, 32);
2012         if (fb->call_conv & 0x20)
2013                 sigbuffer_add_byte (&buf, 0x28);
2014         else
2015                 sigbuffer_add_byte (&buf, 0x08);
2016         sigbuffer_add_value (&buf, nparams);
2017         if (mb) {
2018                 encode_reflection_type (assembly, (MonoReflectionType*)mb->rtype, &buf);
2019                 for (i = 0; i < nparams; ++i) {
2020                         MonoReflectionType *pt = mono_array_get (mb->parameters, MonoReflectionType*, i);
2021                         encode_reflection_type (assembly, pt, &buf);
2022                 }
2023         } else if (smb && smb->parameters) {
2024                 /* the property type is the last param */
2025                 encode_reflection_type (assembly, mono_array_get (smb->parameters, MonoReflectionType*, nparams), &buf);
2026                 for (i = 0; i < nparams; ++i) {
2027                         MonoReflectionType *pt = mono_array_get (smb->parameters, MonoReflectionType*, i);
2028                         encode_reflection_type (assembly, pt, &buf);
2029                 }
2030         } else {
2031                 encode_reflection_type (assembly, (MonoReflectionType*)fb->type, &buf);
2032         }
2033
2034         idx = sigbuffer_add_to_blob_cached (assembly, &buf);
2035         sigbuffer_free (&buf);
2036         return idx;
2037 }
2038
2039 static void
2040 mono_image_get_property_info (MonoReflectionPropertyBuilder *pb, MonoDynamicImage *assembly)
2041 {
2042         MonoDynamicTable *table;
2043         guint32 *values;
2044         guint num_methods = 0;
2045         guint32 semaidx;
2046
2047         /* 
2048          * we need to set things in the following tables:
2049          * PROPERTYMAP (info already filled in _get_type_info ())
2050          * PROPERTY    (rows already preallocated in _get_type_info ())
2051          * METHOD      (method info already done with the generic method code)
2052          * METHODSEMANTICS
2053          * CONSTANT
2054          */
2055         table = &assembly->tables [MONO_TABLE_PROPERTY];
2056         pb->table_idx = table->next_idx ++;
2057         values = table->values + pb->table_idx * MONO_PROPERTY_SIZE;
2058         values [MONO_PROPERTY_NAME] = string_heap_insert_mstring (&assembly->sheap, pb->name);
2059         values [MONO_PROPERTY_FLAGS] = pb->attrs;
2060         values [MONO_PROPERTY_TYPE] = property_encode_signature (assembly, pb);
2061
2062         /* FIXME: we still don't handle 'other' methods */
2063         if (pb->get_method) num_methods ++;
2064         if (pb->set_method) num_methods ++;
2065
2066         table = &assembly->tables [MONO_TABLE_METHODSEMANTICS];
2067         table->rows += num_methods;
2068         alloc_table (table, table->rows);
2069
2070         if (pb->get_method) {
2071                 semaidx = table->next_idx ++;
2072                 values = table->values + semaidx * MONO_METHOD_SEMA_SIZE;
2073                 values [MONO_METHOD_SEMA_SEMANTICS] = METHOD_SEMANTIC_GETTER;
2074                 values [MONO_METHOD_SEMA_METHOD] = pb->get_method->table_idx;
2075                 values [MONO_METHOD_SEMA_ASSOCIATION] = (pb->table_idx << MONO_HAS_SEMANTICS_BITS) | MONO_HAS_SEMANTICS_PROPERTY;
2076         }
2077         if (pb->set_method) {
2078                 semaidx = table->next_idx ++;
2079                 values = table->values + semaidx * MONO_METHOD_SEMA_SIZE;
2080                 values [MONO_METHOD_SEMA_SEMANTICS] = METHOD_SEMANTIC_SETTER;
2081                 values [MONO_METHOD_SEMA_METHOD] = pb->set_method->table_idx;
2082                 values [MONO_METHOD_SEMA_ASSOCIATION] = (pb->table_idx << MONO_HAS_SEMANTICS_BITS) | MONO_HAS_SEMANTICS_PROPERTY;
2083         }
2084         if (pb->attrs & PROPERTY_ATTRIBUTE_HAS_DEFAULT) {
2085                 guint32 field_type = 0;
2086                 table = &assembly->tables [MONO_TABLE_CONSTANT];
2087                 table->rows ++;
2088                 alloc_table (table, table->rows);
2089                 values = table->values + table->rows * MONO_CONSTANT_SIZE;
2090                 values [MONO_CONSTANT_PARENT] = MONO_HASCONSTANT_PROPERTY | (pb->table_idx << MONO_HASCONSTANT_BITS);
2091                 values [MONO_CONSTANT_VALUE] = encode_constant (assembly, pb->def_value, &field_type);
2092                 values [MONO_CONSTANT_TYPE] = field_type;
2093                 values [MONO_CONSTANT_PADDING] = 0;
2094         }
2095 }
2096
2097 static void
2098 mono_image_get_event_info (MonoReflectionEventBuilder *eb, MonoDynamicImage *assembly)
2099 {
2100         MonoDynamicTable *table;
2101         guint32 *values;
2102         guint num_methods = 0;
2103         guint32 semaidx;
2104
2105         /* 
2106          * we need to set things in the following tables:
2107          * EVENTMAP (info already filled in _get_type_info ())
2108          * EVENT    (rows already preallocated in _get_type_info ())
2109          * METHOD      (method info already done with the generic method code)
2110          * METHODSEMANTICS
2111          */
2112         table = &assembly->tables [MONO_TABLE_EVENT];
2113         eb->table_idx = table->next_idx ++;
2114         values = table->values + eb->table_idx * MONO_EVENT_SIZE;
2115         values [MONO_EVENT_NAME] = string_heap_insert_mstring (&assembly->sheap, eb->name);
2116         values [MONO_EVENT_FLAGS] = eb->attrs;
2117         values [MONO_EVENT_TYPE] = mono_image_typedef_or_ref (assembly, mono_reflection_type_get_handle (eb->type));
2118
2119         /*
2120          * FIXME: we still don't handle 'other' methods 
2121          */
2122         if (eb->add_method) num_methods ++;
2123         if (eb->remove_method) num_methods ++;
2124         if (eb->raise_method) num_methods ++;
2125
2126         table = &assembly->tables [MONO_TABLE_METHODSEMANTICS];
2127         table->rows += num_methods;
2128         alloc_table (table, table->rows);
2129
2130         if (eb->add_method) {
2131                 semaidx = table->next_idx ++;
2132                 values = table->values + semaidx * MONO_METHOD_SEMA_SIZE;
2133                 values [MONO_METHOD_SEMA_SEMANTICS] = METHOD_SEMANTIC_ADD_ON;
2134                 values [MONO_METHOD_SEMA_METHOD] = eb->add_method->table_idx;
2135                 values [MONO_METHOD_SEMA_ASSOCIATION] = (eb->table_idx << MONO_HAS_SEMANTICS_BITS) | MONO_HAS_SEMANTICS_EVENT;
2136         }
2137         if (eb->remove_method) {
2138                 semaidx = table->next_idx ++;
2139                 values = table->values + semaidx * MONO_METHOD_SEMA_SIZE;
2140                 values [MONO_METHOD_SEMA_SEMANTICS] = METHOD_SEMANTIC_REMOVE_ON;
2141                 values [MONO_METHOD_SEMA_METHOD] = eb->remove_method->table_idx;
2142                 values [MONO_METHOD_SEMA_ASSOCIATION] = (eb->table_idx << MONO_HAS_SEMANTICS_BITS) | MONO_HAS_SEMANTICS_EVENT;
2143         }
2144         if (eb->raise_method) {
2145                 semaidx = table->next_idx ++;
2146                 values = table->values + semaidx * MONO_METHOD_SEMA_SIZE;
2147                 values [MONO_METHOD_SEMA_SEMANTICS] = METHOD_SEMANTIC_FIRE;
2148                 values [MONO_METHOD_SEMA_METHOD] = eb->raise_method->table_idx;
2149                 values [MONO_METHOD_SEMA_ASSOCIATION] = (eb->table_idx << MONO_HAS_SEMANTICS_BITS) | MONO_HAS_SEMANTICS_EVENT;
2150         }
2151 }
2152
2153 static void
2154 encode_constraints (MonoReflectionGenericParam *gparam, guint32 owner, MonoDynamicImage *assembly)
2155 {
2156         MonoDynamicTable *table;
2157         guint32 num_constraints, i;
2158         guint32 *values;
2159         guint32 table_idx;
2160
2161         table = &assembly->tables [MONO_TABLE_GENERICPARAMCONSTRAINT];
2162         num_constraints = gparam->iface_constraints ?
2163                 mono_array_length (gparam->iface_constraints) : 0;
2164         table->rows += num_constraints;
2165         if (gparam->base_type)
2166                 table->rows++;
2167         alloc_table (table, table->rows);
2168
2169         if (gparam->base_type) {
2170                 table_idx = table->next_idx ++;
2171                 values = table->values + table_idx * MONO_GENPARCONSTRAINT_SIZE;
2172
2173                 values [MONO_GENPARCONSTRAINT_GENERICPAR] = owner;
2174                 values [MONO_GENPARCONSTRAINT_CONSTRAINT] = mono_image_typedef_or_ref (
2175                         assembly, mono_reflection_type_get_handle (gparam->base_type));
2176         }
2177
2178         for (i = 0; i < num_constraints; i++) {
2179                 MonoReflectionType *constraint = mono_array_get (
2180                         gparam->iface_constraints, gpointer, i);
2181
2182                 table_idx = table->next_idx ++;
2183                 values = table->values + table_idx * MONO_GENPARCONSTRAINT_SIZE;
2184
2185                 values [MONO_GENPARCONSTRAINT_GENERICPAR] = owner;
2186                 values [MONO_GENPARCONSTRAINT_CONSTRAINT] = mono_image_typedef_or_ref (
2187                         assembly, mono_reflection_type_get_handle (constraint));
2188         }
2189 }
2190
2191 static void
2192 mono_image_get_generic_param_info (MonoReflectionGenericParam *gparam, guint32 owner, MonoDynamicImage *assembly)
2193 {
2194         GenericParamTableEntry *entry;
2195
2196         /*
2197          * The GenericParam table must be sorted according to the `owner' field.
2198          * We need to do this sorting prior to writing the GenericParamConstraint
2199          * table, since we have to use the final GenericParam table indices there
2200          * and they must also be sorted.
2201          */
2202
2203         entry = g_new0 (GenericParamTableEntry, 1);
2204         entry->owner = owner;
2205         /* FIXME: track where gen_params should be freed and remove the GC root as well */
2206         MONO_GC_REGISTER_ROOT_IF_MOVING (entry->gparam);
2207         entry->gparam = gparam;
2208         
2209         g_ptr_array_add (assembly->gen_params, entry);
2210 }
2211
2212 static void
2213 write_generic_param_entry (MonoDynamicImage *assembly, GenericParamTableEntry *entry)
2214 {
2215         MonoDynamicTable *table;
2216         MonoGenericParam *param;
2217         guint32 *values;
2218         guint32 table_idx;
2219
2220         table = &assembly->tables [MONO_TABLE_GENERICPARAM];
2221         table_idx = table->next_idx ++;
2222         values = table->values + table_idx * MONO_GENERICPARAM_SIZE;
2223
2224         param = mono_reflection_type_get_handle ((MonoReflectionType*)entry->gparam)->data.generic_param;
2225
2226         values [MONO_GENERICPARAM_OWNER] = entry->owner;
2227         values [MONO_GENERICPARAM_FLAGS] = entry->gparam->attrs;
2228         values [MONO_GENERICPARAM_NUMBER] = mono_generic_param_num (param);
2229         values [MONO_GENERICPARAM_NAME] = string_heap_insert (&assembly->sheap, mono_generic_param_info (param)->name);
2230
2231         mono_image_add_cattrs (assembly, table_idx, MONO_CUSTOM_ATTR_GENERICPAR, entry->gparam->cattrs);
2232
2233         encode_constraints (entry->gparam, table_idx, assembly);
2234 }
2235
2236 static guint32
2237 resolution_scope_from_image (MonoDynamicImage *assembly, MonoImage *image)
2238 {
2239         MonoDynamicTable *table;
2240         guint32 token;
2241         guint32 *values;
2242         guint32 cols [MONO_ASSEMBLY_SIZE];
2243         const char *pubkey;
2244         guint32 publen;
2245
2246         if ((token = GPOINTER_TO_UINT (g_hash_table_lookup (assembly->handleref, image))))
2247                 return token;
2248
2249         if (image->assembly->dynamic && (image->assembly == assembly->image.assembly)) {
2250                 table = &assembly->tables [MONO_TABLE_MODULEREF];
2251                 token = table->next_idx ++;
2252                 table->rows ++;
2253                 alloc_table (table, table->rows);
2254                 values = table->values + token * MONO_MODULEREF_SIZE;
2255                 values [MONO_MODULEREF_NAME] = string_heap_insert (&assembly->sheap, image->module_name);
2256
2257                 token <<= MONO_RESOLTION_SCOPE_BITS;
2258                 token |= MONO_RESOLTION_SCOPE_MODULEREF;
2259                 g_hash_table_insert (assembly->handleref, image, GUINT_TO_POINTER (token));
2260
2261                 return token;
2262         }
2263         
2264         if (image->assembly->dynamic)
2265                 /* FIXME: */
2266                 memset (cols, 0, sizeof (cols));
2267         else {
2268                 /* image->assembly->image is the manifest module */
2269                 image = image->assembly->image;
2270                 mono_metadata_decode_row (&image->tables [MONO_TABLE_ASSEMBLY], 0, cols, MONO_ASSEMBLY_SIZE);
2271         }
2272
2273         table = &assembly->tables [MONO_TABLE_ASSEMBLYREF];
2274         token = table->next_idx ++;
2275         table->rows ++;
2276         alloc_table (table, table->rows);
2277         values = table->values + token * MONO_ASSEMBLYREF_SIZE;
2278         values [MONO_ASSEMBLYREF_NAME] = string_heap_insert (&assembly->sheap, image->assembly_name);
2279         values [MONO_ASSEMBLYREF_MAJOR_VERSION] = cols [MONO_ASSEMBLY_MAJOR_VERSION];
2280         values [MONO_ASSEMBLYREF_MINOR_VERSION] = cols [MONO_ASSEMBLY_MINOR_VERSION];
2281         values [MONO_ASSEMBLYREF_BUILD_NUMBER] = cols [MONO_ASSEMBLY_BUILD_NUMBER];
2282         values [MONO_ASSEMBLYREF_REV_NUMBER] = cols [MONO_ASSEMBLY_REV_NUMBER];
2283         values [MONO_ASSEMBLYREF_FLAGS] = 0;
2284         values [MONO_ASSEMBLYREF_CULTURE] = 0;
2285         values [MONO_ASSEMBLYREF_HASH_VALUE] = 0;
2286
2287         if (strcmp ("", image->assembly->aname.culture)) {
2288                 values [MONO_ASSEMBLYREF_CULTURE] = string_heap_insert (&assembly->sheap,
2289                                 image->assembly->aname.culture);
2290         }
2291
2292         if ((pubkey = mono_image_get_public_key (image, &publen))) {
2293                 guchar pubtoken [9];
2294                 pubtoken [0] = 8;
2295                 mono_digest_get_public_token (pubtoken + 1, (guchar*)pubkey, publen);
2296                 values [MONO_ASSEMBLYREF_PUBLIC_KEY] = mono_image_add_stream_data (&assembly->blob, (char*)pubtoken, 9);
2297         } else {
2298                 values [MONO_ASSEMBLYREF_PUBLIC_KEY] = 0;
2299         }
2300         token <<= MONO_RESOLTION_SCOPE_BITS;
2301         token |= MONO_RESOLTION_SCOPE_ASSEMBLYREF;
2302         g_hash_table_insert (assembly->handleref, image, GUINT_TO_POINTER (token));
2303         return token;
2304 }
2305
2306 static guint32
2307 create_typespec (MonoDynamicImage *assembly, MonoType *type)
2308 {
2309         MonoDynamicTable *table;
2310         guint32 *values;
2311         guint32 token;
2312         SigBuffer buf;
2313
2314         if ((token = GPOINTER_TO_UINT (g_hash_table_lookup (assembly->typespec, type))))
2315                 return token;
2316
2317         sigbuffer_init (&buf, 32);
2318         switch (type->type) {
2319         case MONO_TYPE_FNPTR:
2320         case MONO_TYPE_PTR:
2321         case MONO_TYPE_SZARRAY:
2322         case MONO_TYPE_ARRAY:
2323         case MONO_TYPE_VAR:
2324         case MONO_TYPE_MVAR:
2325         case MONO_TYPE_GENERICINST:
2326                 encode_type (assembly, type, &buf);
2327                 break;
2328         case MONO_TYPE_CLASS:
2329         case MONO_TYPE_VALUETYPE: {
2330                 MonoClass *k = mono_class_from_mono_type (type);
2331                 if (!k || !k->generic_container) {
2332                         sigbuffer_free (&buf);
2333                         return 0;
2334                 }
2335                 encode_type (assembly, type, &buf);
2336                 break;
2337         }
2338         default:
2339                 sigbuffer_free (&buf);
2340                 return 0;
2341         }
2342
2343         table = &assembly->tables [MONO_TABLE_TYPESPEC];
2344         if (assembly->save) {
2345                 token = sigbuffer_add_to_blob_cached (assembly, &buf);
2346                 alloc_table (table, table->rows + 1);
2347                 values = table->values + table->next_idx * MONO_TYPESPEC_SIZE;
2348                 values [MONO_TYPESPEC_SIGNATURE] = token;
2349         }
2350         sigbuffer_free (&buf);
2351
2352         token = MONO_TYPEDEFORREF_TYPESPEC | (table->next_idx << MONO_TYPEDEFORREF_BITS);
2353         g_hash_table_insert (assembly->typespec, type, GUINT_TO_POINTER(token));
2354         table->next_idx ++;
2355         return token;
2356 }
2357
2358 static guint32
2359 mono_image_typedef_or_ref_full (MonoDynamicImage *assembly, MonoType *type, gboolean try_typespec)
2360 {
2361         MonoDynamicTable *table;
2362         guint32 *values;
2363         guint32 token, scope, enclosing;
2364         MonoClass *klass;
2365
2366         /* if the type requires a typespec, we must try that first*/
2367         if (try_typespec && (token = create_typespec (assembly, type)))
2368                 return token;
2369         token = GPOINTER_TO_UINT (g_hash_table_lookup (assembly->typeref, type));
2370         if (token)
2371                 return token;
2372         klass = mono_class_from_mono_type (type);
2373         if (!klass)
2374                 klass = mono_class_from_mono_type (type);
2375
2376         /*
2377          * If it's in the same module and not a generic type parameter:
2378          */
2379         if ((klass->image == &assembly->image) && (type->type != MONO_TYPE_VAR) && 
2380                         (type->type != MONO_TYPE_MVAR)) {
2381                 MonoReflectionTypeBuilder *tb = mono_class_get_ref_info (klass);
2382                 token = MONO_TYPEDEFORREF_TYPEDEF | (tb->table_idx << MONO_TYPEDEFORREF_BITS);
2383                 mono_g_hash_table_insert (assembly->tokens, GUINT_TO_POINTER (token), mono_class_get_ref_info (klass));
2384                 return token;
2385         }
2386
2387         if (klass->nested_in) {
2388                 enclosing = mono_image_typedef_or_ref_full (assembly, &klass->nested_in->byval_arg, FALSE);
2389                 /* get the typeref idx of the enclosing type */
2390                 enclosing >>= MONO_TYPEDEFORREF_BITS;
2391                 scope = (enclosing << MONO_RESOLTION_SCOPE_BITS) | MONO_RESOLTION_SCOPE_TYPEREF;
2392         } else {
2393                 scope = resolution_scope_from_image (assembly, klass->image);
2394         }
2395         table = &assembly->tables [MONO_TABLE_TYPEREF];
2396         if (assembly->save) {
2397                 alloc_table (table, table->rows + 1);
2398                 values = table->values + table->next_idx * MONO_TYPEREF_SIZE;
2399                 values [MONO_TYPEREF_SCOPE] = scope;
2400                 values [MONO_TYPEREF_NAME] = string_heap_insert (&assembly->sheap, klass->name);
2401                 values [MONO_TYPEREF_NAMESPACE] = string_heap_insert (&assembly->sheap, klass->name_space);
2402         }
2403         token = MONO_TYPEDEFORREF_TYPEREF | (table->next_idx << MONO_TYPEDEFORREF_BITS); /* typeref */
2404         g_hash_table_insert (assembly->typeref, type, GUINT_TO_POINTER(token));
2405         table->next_idx ++;
2406         mono_g_hash_table_insert (assembly->tokens, GUINT_TO_POINTER (token), mono_class_get_ref_info (klass));
2407         return token;
2408 }
2409
2410 /*
2411  * Despite the name, we handle also TypeSpec (with the above helper).
2412  */
2413 static guint32
2414 mono_image_typedef_or_ref (MonoDynamicImage *assembly, MonoType *type)
2415 {
2416         return mono_image_typedef_or_ref_full (assembly, type, TRUE);
2417 }
2418
2419 #ifndef DISABLE_REFLECTION_EMIT
2420 static guint32
2421 mono_image_add_memberef_row (MonoDynamicImage *assembly, guint32 parent, const char *name, guint32 sig)
2422 {
2423         MonoDynamicTable *table;
2424         guint32 *values;
2425         guint32 token, pclass;
2426
2427         switch (parent & MONO_TYPEDEFORREF_MASK) {
2428         case MONO_TYPEDEFORREF_TYPEREF:
2429                 pclass = MONO_MEMBERREF_PARENT_TYPEREF;
2430                 break;
2431         case MONO_TYPEDEFORREF_TYPESPEC:
2432                 pclass = MONO_MEMBERREF_PARENT_TYPESPEC;
2433                 break;
2434         case MONO_TYPEDEFORREF_TYPEDEF:
2435                 pclass = MONO_MEMBERREF_PARENT_TYPEDEF;
2436                 break;
2437         default:
2438                 g_warning ("unknown typeref or def token 0x%08x for %s", parent, name);
2439                 return 0;
2440         }
2441         /* extract the index */
2442         parent >>= MONO_TYPEDEFORREF_BITS;
2443
2444         table = &assembly->tables [MONO_TABLE_MEMBERREF];
2445
2446         if (assembly->save) {
2447                 alloc_table (table, table->rows + 1);
2448                 values = table->values + table->next_idx * MONO_MEMBERREF_SIZE;
2449                 values [MONO_MEMBERREF_CLASS] = pclass | (parent << MONO_MEMBERREF_PARENT_BITS);
2450                 values [MONO_MEMBERREF_NAME] = string_heap_insert (&assembly->sheap, name);
2451                 values [MONO_MEMBERREF_SIGNATURE] = sig;
2452         }
2453
2454         token = MONO_TOKEN_MEMBER_REF | table->next_idx;
2455         table->next_idx ++;
2456
2457         return token;
2458 }
2459
2460 /*
2461  * Insert a memberef row into the metadata: the token that point to the memberref
2462  * is returned. Caching is done in the caller (mono_image_get_methodref_token() or
2463  * mono_image_get_fieldref_token()).
2464  * The sig param is an index to an already built signature.
2465  */
2466 static guint32
2467 mono_image_get_memberref_token (MonoDynamicImage *assembly, MonoType *type, const char *name, guint32 sig)
2468 {
2469         guint32 parent = mono_image_typedef_or_ref (assembly, type);
2470         return mono_image_add_memberef_row (assembly, parent, name, sig);
2471 }
2472
2473
2474 static guint32
2475 mono_image_get_methodref_token (MonoDynamicImage *assembly, MonoMethod *method, gboolean create_typespec)
2476 {
2477         guint32 token;
2478         MonoMethodSignature *sig;
2479         
2480         create_typespec = create_typespec && method->is_generic && method->klass->image != &assembly->image;
2481
2482         if (create_typespec) {
2483                 token = GPOINTER_TO_UINT (g_hash_table_lookup (assembly->handleref, GUINT_TO_POINTER (GPOINTER_TO_UINT (method) + 1)));
2484                 if (token)
2485                         return token;
2486         } 
2487
2488         token = GPOINTER_TO_UINT (g_hash_table_lookup (assembly->handleref, method));
2489         if (token && !create_typespec)
2490                 return token;
2491
2492         g_assert (!method->is_inflated);
2493         if (!token) {
2494                 /*
2495                  * A methodref signature can't contain an unmanaged calling convention.
2496                  */
2497                 sig = mono_metadata_signature_dup (mono_method_signature (method));
2498                 if ((sig->call_convention != MONO_CALL_DEFAULT) && (sig->call_convention != MONO_CALL_VARARG))
2499                         sig->call_convention = MONO_CALL_DEFAULT;
2500                 token = mono_image_get_memberref_token (assembly, &method->klass->byval_arg,
2501                         method->name,  method_encode_signature (assembly, sig));
2502                 g_free (sig);
2503                 g_hash_table_insert (assembly->handleref, method, GUINT_TO_POINTER(token));
2504         }
2505
2506         if (create_typespec) {
2507                 MonoDynamicTable *table = &assembly->tables [MONO_TABLE_METHODSPEC];
2508                 g_assert (mono_metadata_token_table (token) == MONO_TABLE_MEMBERREF);
2509                 token = (mono_metadata_token_index (token) << MONO_METHODDEFORREF_BITS) | MONO_METHODDEFORREF_METHODREF;
2510
2511                 if (assembly->save) {
2512                         guint32 *values;
2513
2514                         alloc_table (table, table->rows + 1);
2515                         values = table->values + table->next_idx * MONO_METHODSPEC_SIZE;
2516                         values [MONO_METHODSPEC_METHOD] = token;
2517                         values [MONO_METHODSPEC_SIGNATURE] = encode_generic_method_sig (assembly, &mono_method_get_generic_container (method)->context);
2518                 }
2519
2520                 token = MONO_TOKEN_METHOD_SPEC | table->next_idx;
2521                 table->next_idx ++;
2522                 /*methodspec and memberef tokens are diferent, */
2523                 g_hash_table_insert (assembly->handleref, GUINT_TO_POINTER (GPOINTER_TO_UINT (method) + 1), GUINT_TO_POINTER (token));
2524                 return token;
2525         }
2526         return token;
2527 }
2528
2529 static guint32
2530 mono_image_get_methodref_token_for_methodbuilder (MonoDynamicImage *assembly, MonoReflectionMethodBuilder *method)
2531 {
2532         guint32 token, parent, sig;
2533         ReflectionMethodBuilder rmb;
2534         char *name;
2535         MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder *)method->type;
2536         
2537         token = GPOINTER_TO_UINT (g_hash_table_lookup (assembly->handleref, method));
2538         if (token)
2539                 return token;
2540
2541         name = mono_string_to_utf8 (method->name);
2542         reflection_methodbuilder_from_method_builder (&rmb, method);
2543
2544         /*
2545          * A methodref signature can't contain an unmanaged calling convention.
2546          * Since some flags are encoded as part of call_conv, we need to check against it.
2547         */
2548         if ((rmb.call_conv & ~0x60) != MONO_CALL_DEFAULT && (rmb.call_conv & ~0x60) != MONO_CALL_VARARG)
2549                 rmb.call_conv = (rmb.call_conv & 0x60) | MONO_CALL_DEFAULT;
2550
2551         sig = method_builder_encode_signature (assembly, &rmb);
2552
2553         if (tb->generic_params)
2554                 parent = create_generic_typespec (assembly, tb);
2555         else
2556                 parent = mono_image_typedef_or_ref (assembly, mono_reflection_type_get_handle ((MonoReflectionType*)rmb.type));
2557
2558         token = mono_image_add_memberef_row (assembly, parent, name, sig);
2559
2560         g_free (name);
2561         g_hash_table_insert (assembly->handleref, method, GUINT_TO_POINTER(token));
2562         return token;
2563 }
2564
2565 static guint32
2566 mono_image_get_varargs_method_token (MonoDynamicImage *assembly, guint32 original,
2567                                      const gchar *name, guint32 sig)
2568 {
2569         MonoDynamicTable *table;
2570         guint32 token;
2571         guint32 *values;
2572         
2573         table = &assembly->tables [MONO_TABLE_MEMBERREF];
2574
2575         if (assembly->save) {
2576                 alloc_table (table, table->rows + 1);
2577                 values = table->values + table->next_idx * MONO_MEMBERREF_SIZE;
2578                 values [MONO_MEMBERREF_CLASS] = original;
2579                 values [MONO_MEMBERREF_NAME] = string_heap_insert (&assembly->sheap, name);
2580                 values [MONO_MEMBERREF_SIGNATURE] = sig;
2581         }
2582
2583         token = MONO_TOKEN_MEMBER_REF | table->next_idx;
2584         table->next_idx ++;
2585
2586         return token;
2587 }
2588
2589 static guint32
2590 encode_generic_method_definition_sig (MonoDynamicImage *assembly, MonoReflectionMethodBuilder *mb)
2591 {
2592         SigBuffer buf;
2593         int i;
2594         guint32 nparams = mono_array_length (mb->generic_params);
2595         guint32 idx;
2596
2597         if (!assembly->save)
2598                 return 0;
2599
2600         sigbuffer_init (&buf, 32);
2601
2602         sigbuffer_add_value (&buf, 0xa);
2603         sigbuffer_add_value (&buf, nparams);
2604
2605         for (i = 0; i < nparams; i++) {
2606                 sigbuffer_add_value (&buf, MONO_TYPE_MVAR);
2607                 sigbuffer_add_value (&buf, i);
2608         }
2609
2610         idx = sigbuffer_add_to_blob_cached (assembly, &buf);
2611         sigbuffer_free (&buf);
2612         return idx;
2613 }
2614
2615 static guint32
2616 mono_image_get_methodspec_token_for_generic_method_definition (MonoDynamicImage *assembly, MonoReflectionMethodBuilder *mb)
2617 {
2618         MonoDynamicTable *table;
2619         guint32 *values;
2620         guint32 token, mtoken = 0;
2621
2622         token = GPOINTER_TO_UINT (mono_g_hash_table_lookup (assembly->methodspec, mb));
2623         if (token)
2624                 return token;
2625
2626         table = &assembly->tables [MONO_TABLE_METHODSPEC];
2627
2628         mtoken = mono_image_get_methodref_token_for_methodbuilder (assembly, mb);
2629         switch (mono_metadata_token_table (mtoken)) {
2630         case MONO_TABLE_MEMBERREF:
2631                 mtoken = (mono_metadata_token_index (mtoken) << MONO_METHODDEFORREF_BITS) | MONO_METHODDEFORREF_METHODREF;
2632                 break;
2633         case MONO_TABLE_METHOD:
2634                 mtoken = (mono_metadata_token_index (mtoken) << MONO_METHODDEFORREF_BITS) | MONO_METHODDEFORREF_METHODDEF;
2635                 break;
2636         default:
2637                 g_assert_not_reached ();
2638         }
2639
2640         if (assembly->save) {
2641                 alloc_table (table, table->rows + 1);
2642                 values = table->values + table->next_idx * MONO_METHODSPEC_SIZE;
2643                 values [MONO_METHODSPEC_METHOD] = mtoken;
2644                 values [MONO_METHODSPEC_SIGNATURE] = encode_generic_method_definition_sig (assembly, mb);
2645         }
2646
2647         token = MONO_TOKEN_METHOD_SPEC | table->next_idx;
2648         table->next_idx ++;
2649
2650         mono_g_hash_table_insert (assembly->methodspec, mb, GUINT_TO_POINTER(token));
2651         return token;
2652 }
2653
2654 static guint32
2655 mono_image_get_methodbuilder_token (MonoDynamicImage *assembly, MonoReflectionMethodBuilder *mb, gboolean create_methodspec)
2656 {
2657         guint32 token;
2658
2659         if (mb->generic_params && create_methodspec) 
2660                 return mono_image_get_methodspec_token_for_generic_method_definition (assembly, mb);
2661
2662         token = GPOINTER_TO_UINT (mono_g_hash_table_lookup (assembly->handleref_managed, mb));
2663         if (token)
2664                 return token;
2665
2666         token = mono_image_get_methodref_token_for_methodbuilder (assembly, mb);
2667         mono_g_hash_table_insert (assembly->handleref_managed, mb, GUINT_TO_POINTER(token));
2668         return token;
2669 }
2670
2671 static guint32
2672 mono_image_get_ctorbuilder_token (MonoDynamicImage *assembly, MonoReflectionCtorBuilder *mb)
2673 {
2674         guint32 token, parent, sig;
2675         ReflectionMethodBuilder rmb;
2676         char *name;
2677         MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder *)mb->type;
2678         
2679         token = GPOINTER_TO_UINT (mono_g_hash_table_lookup (assembly->handleref_managed, mb));
2680         if (token)
2681                 return token;
2682
2683         reflection_methodbuilder_from_ctor_builder (&rmb, mb);
2684
2685         if (tb->generic_params)
2686                 parent = create_generic_typespec (assembly, tb);
2687         else
2688                 parent = mono_image_typedef_or_ref (assembly, mono_reflection_type_get_handle ((MonoReflectionType*)tb));
2689         
2690         name = mono_string_to_utf8 (rmb.name);
2691         sig = method_builder_encode_signature (assembly, &rmb);
2692
2693         token = mono_image_add_memberef_row (assembly, parent, name, sig);
2694
2695         g_free (name);
2696         mono_g_hash_table_insert (assembly->handleref_managed, mb, GUINT_TO_POINTER(token));
2697         return token;
2698 }
2699 #endif
2700
2701 static gboolean
2702 is_field_on_inst (MonoClassField *field)
2703 {
2704         return (field->parent->generic_class && field->parent->generic_class->is_dynamic && ((MonoDynamicGenericClass*)field->parent->generic_class)->fields);
2705 }
2706
2707 /*
2708  * If FIELD is a field of a MonoDynamicGenericClass, return its non-inflated type.
2709  */
2710 static MonoType*
2711 get_field_on_inst_generic_type (MonoClassField *field)
2712 {
2713         MonoClass *class, *gtd;
2714         MonoDynamicGenericClass *dgclass;
2715         int field_index;
2716
2717         g_assert (is_field_on_inst (field));
2718
2719         dgclass = (MonoDynamicGenericClass*)field->parent->generic_class;
2720
2721         if (field >= dgclass->fields && field - dgclass->fields < dgclass->count_fields) {
2722                 field_index = field - dgclass->fields;
2723                 return dgclass->field_generic_types [field_index];              
2724         }
2725
2726         class = field->parent;
2727         gtd = class->generic_class->container_class;
2728
2729         if (field >= class->fields && field - class->fields < class->field.count) {
2730                 field_index = field - class->fields;
2731                 return gtd->fields [field_index].type;
2732         }
2733
2734         g_assert_not_reached ();
2735         return 0;
2736 }
2737
2738 #ifndef DISABLE_REFLECTION_EMIT
2739 static guint32
2740 mono_image_get_fieldref_token (MonoDynamicImage *assembly, MonoObject *f, MonoClassField *field)
2741 {
2742         MonoType *type;
2743         guint32 token;
2744
2745         g_assert (field);
2746         g_assert (field->parent);
2747
2748         token = GPOINTER_TO_UINT (mono_g_hash_table_lookup (assembly->handleref_managed, f));
2749         if (token)
2750                 return token;
2751
2752         if (field->parent->generic_class && field->parent->generic_class->container_class && field->parent->generic_class->container_class->fields) {
2753                 int index = field - field->parent->fields;
2754                 type = mono_field_get_type (&field->parent->generic_class->container_class->fields [index]);
2755         } else {
2756                 if (is_field_on_inst (field))
2757                         type = get_field_on_inst_generic_type (field);
2758                 else
2759                         type = mono_field_get_type (field);
2760         }
2761         token = mono_image_get_memberref_token (assembly, &field->parent->byval_arg,
2762                                                                                         mono_field_get_name (field),
2763                                                                                         fieldref_encode_signature (assembly, field->parent->image, type));
2764         mono_g_hash_table_insert (assembly->handleref_managed, f, GUINT_TO_POINTER(token));
2765         return token;
2766 }
2767
2768 static guint32
2769 mono_image_get_field_on_inst_token (MonoDynamicImage *assembly, MonoReflectionFieldOnTypeBuilderInst *f)
2770 {
2771         guint32 token;
2772         MonoClass *klass;
2773         MonoGenericClass *gclass;
2774         MonoDynamicGenericClass *dgclass;
2775         MonoType *type;
2776         char *name;
2777
2778         token = GPOINTER_TO_UINT (mono_g_hash_table_lookup (assembly->handleref_managed, f));
2779         if (token)
2780                 return token;
2781         if (is_sre_field_builder (mono_object_class (f->fb))) {
2782                 MonoReflectionFieldBuilder *fb = (MonoReflectionFieldBuilder *)f->fb;
2783                 type = mono_reflection_type_get_handle ((MonoReflectionType*)f->inst);
2784                 klass = mono_class_from_mono_type (type);
2785                 gclass = type->data.generic_class;
2786                 g_assert (gclass->is_dynamic);
2787                 dgclass = (MonoDynamicGenericClass *) gclass;
2788
2789                 name = mono_string_to_utf8 (fb->name);
2790                 token = mono_image_get_memberref_token (assembly, &klass->byval_arg, name, 
2791                                                                                                 field_encode_signature (assembly, fb));
2792                 g_free (name);          
2793         } else if (is_sr_mono_field (mono_object_class (f->fb))) {
2794                 guint32 sig;
2795                 MonoClassField *field = ((MonoReflectionField *)f->fb)->field;
2796
2797                 type = mono_reflection_type_get_handle ((MonoReflectionType*)f->inst);
2798                 klass = mono_class_from_mono_type (type);
2799
2800                 sig = fieldref_encode_signature (assembly, field->parent->image, field->type);
2801                 token = mono_image_get_memberref_token (assembly, &klass->byval_arg, field->name, sig);
2802         } else {
2803                 char *name = mono_type_get_full_name (mono_object_class (f->fb));
2804                 g_error ("mono_image_get_field_on_inst_token: don't know how to handle %s", name);
2805         }
2806
2807         mono_g_hash_table_insert (assembly->handleref_managed, f, GUINT_TO_POINTER (token));
2808         return token;
2809 }
2810
2811 static guint32
2812 mono_image_get_ctor_on_inst_token (MonoDynamicImage *assembly, MonoReflectionCtorOnTypeBuilderInst *c, gboolean create_methodspec)
2813 {
2814         guint32 sig, token;
2815         MonoClass *klass;
2816         MonoGenericClass *gclass;
2817         MonoType *type;
2818
2819         /* A ctor cannot be a generic method, so we can ignore create_methodspec */
2820
2821         token = GPOINTER_TO_UINT (mono_g_hash_table_lookup (assembly->handleref_managed, c));
2822         if (token)
2823                 return token;
2824
2825         if (is_sre_ctor_builder (mono_object_class (c->cb))) {
2826                 MonoReflectionCtorBuilder *cb = (MonoReflectionCtorBuilder *)c->cb;
2827                 MonoDynamicGenericClass *dgclass;
2828                 ReflectionMethodBuilder rmb;
2829                 char *name;
2830
2831                 type = mono_reflection_type_get_handle ((MonoReflectionType*)c->inst);
2832                 klass = mono_class_from_mono_type (type);
2833
2834                 gclass = type->data.generic_class;
2835                 g_assert (gclass->is_dynamic);
2836                 dgclass = (MonoDynamicGenericClass *) gclass;
2837
2838                 reflection_methodbuilder_from_ctor_builder (&rmb, cb);
2839
2840                 name = mono_string_to_utf8 (rmb.name);
2841
2842                 sig = method_builder_encode_signature (assembly, &rmb);
2843
2844                 token = mono_image_get_memberref_token (assembly, &klass->byval_arg, name, sig);
2845                 g_free (name);
2846         } else if (is_sr_mono_cmethod (mono_object_class (c->cb))) {
2847                 MonoMethod *mm = ((MonoReflectionMethod *)c->cb)->method;
2848
2849                 type = mono_reflection_type_get_handle ((MonoReflectionType*)c->inst);
2850                 klass = mono_class_from_mono_type (type);
2851
2852                 sig = method_encode_signature (assembly, mono_method_signature (mm));
2853                 token = mono_image_get_memberref_token (assembly, &klass->byval_arg, mm->name, sig);
2854         } else {
2855                 char *name = mono_type_get_full_name (mono_object_class (c->cb));
2856                 g_error ("mono_image_get_method_on_inst_token: don't know how to handle %s", name);
2857         }
2858
2859
2860         mono_g_hash_table_insert (assembly->handleref_managed, c, GUINT_TO_POINTER (token));
2861         return token;
2862 }
2863
2864 static MonoMethod*
2865 mono_reflection_method_on_tb_inst_get_handle (MonoReflectionMethodOnTypeBuilderInst *m)
2866 {
2867         MonoClass *klass;
2868         MonoGenericContext tmp_context;
2869         MonoType **type_argv;
2870         MonoGenericInst *ginst;
2871         MonoMethod *method, *inflated;
2872         int count, i;
2873
2874         init_type_builder_generics ((MonoObject*)m->inst);
2875
2876         method = inflate_method (m->inst, (MonoObject*)m->mb);
2877
2878         klass = method->klass;
2879
2880         if (m->method_args == NULL)
2881                 return method;
2882
2883         if (method->is_inflated)
2884                 method = ((MonoMethodInflated *) method)->declaring;
2885
2886         count = mono_array_length (m->method_args);
2887
2888         type_argv = g_new0 (MonoType *, count);
2889         for (i = 0; i < count; i++) {
2890                 MonoReflectionType *garg = mono_array_get (m->method_args, gpointer, i);
2891                 type_argv [i] = mono_reflection_type_get_handle (garg);
2892         }
2893         ginst = mono_metadata_get_generic_inst (count, type_argv);
2894         g_free (type_argv);
2895
2896         tmp_context.class_inst = klass->generic_class ? klass->generic_class->context.class_inst : NULL;
2897         tmp_context.method_inst = ginst;
2898
2899         inflated = mono_class_inflate_generic_method (method, &tmp_context);
2900         return inflated;
2901 }
2902
2903 static guint32
2904 mono_image_get_method_on_inst_token (MonoDynamicImage *assembly, MonoReflectionMethodOnTypeBuilderInst *m, gboolean create_methodspec)
2905 {
2906         guint32 sig, token = 0;
2907         MonoType *type;
2908         MonoClass *klass;
2909
2910         if (m->method_args) {
2911                 MonoMethod *inflated;
2912
2913                 inflated = mono_reflection_method_on_tb_inst_get_handle (m);
2914                 if (create_methodspec)
2915                         token = mono_image_get_methodspec_token (assembly, inflated);
2916                 else
2917                         token = mono_image_get_inflated_method_token (assembly, inflated);
2918                 return token;
2919         }
2920
2921         token = GPOINTER_TO_UINT (mono_g_hash_table_lookup (assembly->handleref_managed, m));
2922         if (token)
2923                 return token;
2924
2925         if (is_sre_method_builder (mono_object_class (m->mb))) {
2926                 MonoReflectionMethodBuilder *mb = (MonoReflectionMethodBuilder *)m->mb;
2927                 MonoGenericClass *gclass;
2928                 ReflectionMethodBuilder rmb;
2929                 char *name;
2930
2931                 type = mono_reflection_type_get_handle ((MonoReflectionType*)m->inst);
2932                 klass = mono_class_from_mono_type (type);
2933                 gclass = type->data.generic_class;
2934                 g_assert (gclass->is_dynamic);
2935
2936                 reflection_methodbuilder_from_method_builder (&rmb, mb);
2937
2938                 name = mono_string_to_utf8 (rmb.name);
2939
2940                 sig = method_builder_encode_signature (assembly, &rmb);
2941
2942                 token = mono_image_get_memberref_token (assembly, &klass->byval_arg, name, sig);
2943                 g_free (name);          
2944         } else if (is_sr_mono_method (mono_object_class (m->mb))) {
2945                 MonoMethod *mm = ((MonoReflectionMethod *)m->mb)->method;
2946
2947                 type = mono_reflection_type_get_handle ((MonoReflectionType*)m->inst);
2948                 klass = mono_class_from_mono_type (type);
2949
2950                 sig = method_encode_signature (assembly, mono_method_signature (mm));
2951                 token = mono_image_get_memberref_token (assembly, &klass->byval_arg, mm->name, sig);
2952         } else {
2953                 char *name = mono_type_get_full_name (mono_object_class (m->mb));
2954                 g_error ("mono_image_get_method_on_inst_token: don't know how to handle %s", name);
2955         }
2956
2957         mono_g_hash_table_insert (assembly->handleref_managed, m, GUINT_TO_POINTER (token));
2958         return token;
2959 }
2960
2961 static guint32
2962 encode_generic_method_sig (MonoDynamicImage *assembly, MonoGenericContext *context)
2963 {
2964         SigBuffer buf;
2965         int i;
2966         guint32 nparams = context->method_inst->type_argc;
2967         guint32 idx;
2968
2969         if (!assembly->save)
2970                 return 0;
2971
2972         sigbuffer_init (&buf, 32);
2973         /*
2974          * FIXME: vararg, explicit_this, differenc call_conv values...
2975          */
2976         sigbuffer_add_value (&buf, 0xa); /* FIXME FIXME FIXME */
2977         sigbuffer_add_value (&buf, nparams);
2978
2979         for (i = 0; i < nparams; i++)
2980                 encode_type (assembly, context->method_inst->type_argv [i], &buf);
2981
2982         idx = sigbuffer_add_to_blob_cached (assembly, &buf);
2983         sigbuffer_free (&buf);
2984         return idx;
2985 }
2986
2987 static guint32
2988 method_encode_methodspec (MonoDynamicImage *assembly, MonoMethod *method)
2989 {
2990         MonoDynamicTable *table;
2991         guint32 *values;
2992         guint32 token, mtoken = 0, sig;
2993         MonoMethodInflated *imethod;
2994         MonoMethod *declaring;
2995
2996         table = &assembly->tables [MONO_TABLE_METHODSPEC];
2997
2998         g_assert (method->is_inflated);
2999         imethod = (MonoMethodInflated *) method;
3000         declaring = imethod->declaring;
3001
3002         sig = method_encode_signature (assembly, mono_method_signature (declaring));
3003         mtoken = mono_image_get_memberref_token (assembly, &method->klass->byval_arg, declaring->name, sig);
3004
3005         if (!mono_method_signature (declaring)->generic_param_count)
3006                 return mtoken;
3007
3008         switch (mono_metadata_token_table (mtoken)) {
3009         case MONO_TABLE_MEMBERREF:
3010                 mtoken = (mono_metadata_token_index (mtoken) << MONO_METHODDEFORREF_BITS) | MONO_METHODDEFORREF_METHODREF;
3011                 break;
3012         case MONO_TABLE_METHOD:
3013                 mtoken = (mono_metadata_token_index (mtoken) << MONO_METHODDEFORREF_BITS) | MONO_METHODDEFORREF_METHODDEF;
3014                 break;
3015         default:
3016                 g_assert_not_reached ();
3017         }
3018
3019         sig = encode_generic_method_sig (assembly, mono_method_get_context (method));
3020
3021         if (assembly->save) {
3022                 alloc_table (table, table->rows + 1);
3023                 values = table->values + table->next_idx * MONO_METHODSPEC_SIZE;
3024                 values [MONO_METHODSPEC_METHOD] = mtoken;
3025                 values [MONO_METHODSPEC_SIGNATURE] = sig;
3026         }
3027
3028         token = MONO_TOKEN_METHOD_SPEC | table->next_idx;
3029         table->next_idx ++;
3030
3031         return token;
3032 }
3033
3034 static guint32
3035 mono_image_get_methodspec_token (MonoDynamicImage *assembly, MonoMethod *method)
3036 {
3037         MonoMethodInflated *imethod;
3038         guint32 token;
3039         
3040         token = GPOINTER_TO_UINT (g_hash_table_lookup (assembly->handleref, method));
3041         if (token)
3042                 return token;
3043
3044         g_assert (method->is_inflated);
3045         imethod = (MonoMethodInflated *) method;
3046
3047         if (mono_method_signature (imethod->declaring)->generic_param_count) {
3048                 token = method_encode_methodspec (assembly, method);
3049         } else {
3050                 guint32 sig = method_encode_signature (
3051                         assembly, mono_method_signature (imethod->declaring));
3052                 token = mono_image_get_memberref_token (
3053                         assembly, &method->klass->byval_arg, method->name, sig);
3054         }
3055
3056         g_hash_table_insert (assembly->handleref, method, GUINT_TO_POINTER(token));
3057         return token;
3058 }
3059
3060 static guint32
3061 mono_image_get_inflated_method_token (MonoDynamicImage *assembly, MonoMethod *m)
3062 {
3063         MonoMethodInflated *imethod = (MonoMethodInflated *) m;
3064         guint32 sig, token;
3065
3066         sig = method_encode_signature (assembly, mono_method_signature (imethod->declaring));
3067         token = mono_image_get_memberref_token (
3068                 assembly, &m->klass->byval_arg, m->name, sig);
3069
3070         return token;
3071 }
3072
3073 static guint32
3074 create_generic_typespec (MonoDynamicImage *assembly, MonoReflectionTypeBuilder *tb)
3075 {
3076         MonoDynamicTable *table;
3077         MonoClass *klass;
3078         MonoType *type;
3079         guint32 *values;
3080         guint32 token;
3081         SigBuffer buf;
3082         int count, i;
3083
3084         /*
3085          * We're creating a TypeSpec for the TypeBuilder of a generic type declaration,
3086          * ie. what we'd normally use as the generic type in a TypeSpec signature.
3087          * Because of this, we must not insert it into the `typeref' hash table.
3088          */
3089         type = mono_reflection_type_get_handle ((MonoReflectionType*)tb);
3090         token = GPOINTER_TO_UINT (g_hash_table_lookup (assembly->typespec, type));
3091         if (token)
3092                 return token;
3093
3094         sigbuffer_init (&buf, 32);
3095
3096         g_assert (tb->generic_params);
3097         klass = mono_class_from_mono_type (type);
3098
3099         if (tb->generic_container)
3100                 mono_reflection_create_generic_class (tb);
3101
3102         sigbuffer_add_value (&buf, MONO_TYPE_GENERICINST);
3103         g_assert (klass->generic_container);
3104         sigbuffer_add_value (&buf, klass->byval_arg.type);
3105         sigbuffer_add_value (&buf, mono_image_typedef_or_ref_full (assembly, &klass->byval_arg, FALSE));
3106
3107         count = mono_array_length (tb->generic_params);
3108         sigbuffer_add_value (&buf, count);
3109         for (i = 0; i < count; i++) {
3110                 MonoReflectionGenericParam *gparam;
3111
3112                 gparam = mono_array_get (tb->generic_params, MonoReflectionGenericParam *, i);
3113
3114                 encode_type (assembly, mono_reflection_type_get_handle ((MonoReflectionType*)gparam), &buf);
3115         }
3116
3117         table = &assembly->tables [MONO_TABLE_TYPESPEC];
3118
3119         if (assembly->save) {
3120                 token = sigbuffer_add_to_blob_cached (assembly, &buf);
3121                 alloc_table (table, table->rows + 1);
3122                 values = table->values + table->next_idx * MONO_TYPESPEC_SIZE;
3123                 values [MONO_TYPESPEC_SIGNATURE] = token;
3124         }
3125         sigbuffer_free (&buf);
3126
3127         token = MONO_TYPEDEFORREF_TYPESPEC | (table->next_idx << MONO_TYPEDEFORREF_BITS);
3128         g_hash_table_insert (assembly->typespec, type, GUINT_TO_POINTER(token));
3129         table->next_idx ++;
3130         return token;
3131 }
3132
3133 /*
3134  * Return a copy of TYPE, adding the custom modifiers in MODREQ and MODOPT.
3135  */
3136 static MonoType*
3137 add_custom_modifiers (MonoDynamicImage *assembly, MonoType *type, MonoArray *modreq, MonoArray *modopt)
3138 {
3139         int i, count, len, pos;
3140         MonoType *t;
3141
3142         count = 0;
3143         if (modreq)
3144                 count += mono_array_length (modreq);
3145         if (modopt)
3146                 count += mono_array_length (modopt);
3147
3148         if (count == 0)
3149                 return mono_metadata_type_dup (NULL, type);
3150
3151         len = MONO_SIZEOF_TYPE + ((gint32)count) * sizeof (MonoCustomMod);
3152         t = g_malloc (len);
3153         memcpy (t, type, MONO_SIZEOF_TYPE);
3154
3155         t->num_mods = count;
3156         pos = 0;
3157         if (modreq) {
3158                 for (i = 0; i < mono_array_length (modreq); ++i) {
3159                         MonoType *mod = mono_type_array_get_and_resolve (modreq, i);
3160                         t->modifiers [pos].required = 1;
3161                         t->modifiers [pos].token = mono_image_typedef_or_ref (assembly, mod);
3162                         pos ++;
3163                 }
3164         }
3165         if (modopt) {
3166                 for (i = 0; i < mono_array_length (modopt); ++i) {
3167                         MonoType *mod = mono_type_array_get_and_resolve (modopt, i);
3168                         t->modifiers [pos].required = 0;
3169                         t->modifiers [pos].token = mono_image_typedef_or_ref (assembly, mod);
3170                         pos ++;
3171                 }
3172         }
3173
3174         return t;
3175 }
3176
3177 static void
3178 init_type_builder_generics (MonoObject *type)
3179 {
3180         MonoReflectionTypeBuilder *tb;
3181
3182         if (!is_sre_type_builder(mono_object_class (type)))
3183                 return;
3184         tb = (MonoReflectionTypeBuilder *)type;
3185
3186         if (tb && tb->generic_container)
3187                 mono_reflection_create_generic_class (tb);
3188 }
3189
3190 static guint32
3191 mono_image_get_generic_field_token (MonoDynamicImage *assembly, MonoReflectionFieldBuilder *fb)
3192 {
3193         MonoDynamicTable *table;
3194         MonoClass *klass;
3195         MonoType *custom = NULL, *type;
3196         guint32 *values;
3197         guint32 token, pclass, parent, sig;
3198         gchar *name;
3199
3200         token = GPOINTER_TO_UINT (mono_g_hash_table_lookup (assembly->handleref_managed, fb));
3201         if (token)
3202                 return token;
3203
3204         klass = mono_class_from_mono_type (mono_reflection_type_get_handle (fb->typeb));
3205         name = mono_string_to_utf8 (fb->name);
3206
3207         /*FIXME this is one more layer of ugliness due how types are created.*/
3208         init_type_builder_generics (fb->type);
3209
3210         /* fb->type does not include the custom modifiers */
3211         /* FIXME: We should do this in one place when a fieldbuilder is created */
3212         type = mono_reflection_type_get_handle ((MonoReflectionType*)fb->type);
3213         if (fb->modreq || fb->modopt)
3214                 type = custom = add_custom_modifiers (assembly, type, fb->modreq, fb->modopt);
3215
3216         sig = fieldref_encode_signature (assembly, NULL, type);
3217         g_free (custom);
3218
3219         parent = create_generic_typespec (assembly, (MonoReflectionTypeBuilder *) fb->typeb);
3220         g_assert ((parent & MONO_TYPEDEFORREF_MASK) == MONO_TYPEDEFORREF_TYPESPEC);
3221         
3222         pclass = MONO_MEMBERREF_PARENT_TYPESPEC;
3223         parent >>= MONO_TYPEDEFORREF_BITS;
3224
3225         table = &assembly->tables [MONO_TABLE_MEMBERREF];
3226
3227         if (assembly->save) {
3228                 alloc_table (table, table->rows + 1);
3229                 values = table->values + table->next_idx * MONO_MEMBERREF_SIZE;
3230                 values [MONO_MEMBERREF_CLASS] = pclass | (parent << MONO_MEMBERREF_PARENT_BITS);
3231                 values [MONO_MEMBERREF_NAME] = string_heap_insert (&assembly->sheap, name);
3232                 values [MONO_MEMBERREF_SIGNATURE] = sig;
3233         }
3234
3235         token = MONO_TOKEN_MEMBER_REF | table->next_idx;
3236         table->next_idx ++;
3237         mono_g_hash_table_insert (assembly->handleref_managed, fb, GUINT_TO_POINTER(token));
3238         g_free (name);
3239         return token;
3240 }
3241
3242 static guint32
3243 mono_reflection_encode_sighelper (MonoDynamicImage *assembly, MonoReflectionSigHelper *helper)
3244 {
3245         SigBuffer buf;
3246         guint32 nargs;
3247         guint32 size;
3248         guint32 i, idx;
3249
3250         if (!assembly->save)
3251                 return 0;
3252
3253         /* FIXME: this means SignatureHelper.SignatureHelpType.HELPER_METHOD */
3254         g_assert (helper->type == 2);
3255
3256         if (helper->arguments)
3257                 nargs = mono_array_length (helper->arguments);
3258         else
3259                 nargs = 0;
3260
3261         size = 10 + (nargs * 10);
3262         
3263         sigbuffer_init (&buf, 32);
3264
3265         /* Encode calling convention */
3266         /* Change Any to Standard */
3267         if ((helper->call_conv & 0x03) == 0x03)
3268                 helper->call_conv = 0x01;
3269         /* explicit_this implies has_this */
3270         if (helper->call_conv & 0x40)
3271                 helper->call_conv &= 0x20;
3272
3273         if (helper->call_conv == 0) { /* Unmanaged */
3274                 idx = helper->unmanaged_call_conv - 1;
3275         } else {
3276                 /* Managed */
3277                 idx = helper->call_conv & 0x60; /* has_this + explicit_this */
3278                 if (helper->call_conv & 0x02) /* varargs */
3279                         idx += 0x05;
3280         }
3281
3282         sigbuffer_add_byte (&buf, idx);
3283         sigbuffer_add_value (&buf, nargs);
3284         encode_reflection_type (assembly, helper->return_type, &buf);
3285         for (i = 0; i < nargs; ++i) {
3286                 MonoArray *modreqs = NULL;
3287                 MonoArray *modopts = NULL;
3288                 MonoReflectionType *pt;
3289
3290                 if (helper->modreqs && (i < mono_array_length (helper->modreqs)))
3291                         modreqs = mono_array_get (helper->modreqs, MonoArray*, i);
3292                 if (helper->modopts && (i < mono_array_length (helper->modopts)))
3293                         modopts = mono_array_get (helper->modopts, MonoArray*, i);
3294
3295                 encode_custom_modifiers (assembly, modreqs, modopts, &buf);
3296                 pt = mono_array_get (helper->arguments, MonoReflectionType*, i);
3297                 encode_reflection_type (assembly, pt, &buf);
3298         }
3299         idx = sigbuffer_add_to_blob_cached (assembly, &buf);
3300         sigbuffer_free (&buf);
3301
3302         return idx;
3303 }
3304
3305 static guint32 
3306 mono_image_get_sighelper_token (MonoDynamicImage *assembly, MonoReflectionSigHelper *helper)
3307 {
3308         guint32 idx;
3309         MonoDynamicTable *table;
3310         guint32 *values;
3311
3312         table = &assembly->tables [MONO_TABLE_STANDALONESIG];
3313         idx = table->next_idx ++;
3314         table->rows ++;
3315         alloc_table (table, table->rows);
3316         values = table->values + idx * MONO_STAND_ALONE_SIGNATURE_SIZE;
3317
3318         values [MONO_STAND_ALONE_SIGNATURE] =
3319                 mono_reflection_encode_sighelper (assembly, helper);
3320
3321         return idx;
3322 }
3323
3324 static int
3325 reflection_cc_to_file (int call_conv) {
3326         switch (call_conv & 0x3) {
3327         case 0:
3328         case 1: return MONO_CALL_DEFAULT;
3329         case 2: return MONO_CALL_VARARG;
3330         default:
3331                 g_assert_not_reached ();
3332         }
3333         return 0;
3334 }
3335 #endif /* !DISABLE_REFLECTION_EMIT */
3336
3337 typedef struct {
3338         MonoType *parent;
3339         MonoMethodSignature *sig;
3340         char *name;
3341         guint32 token;
3342 } ArrayMethod;
3343
3344 #ifndef DISABLE_REFLECTION_EMIT
3345 static guint32
3346 mono_image_get_array_token (MonoDynamicImage *assembly, MonoReflectionArrayMethod *m)
3347 {
3348         guint32 nparams, i;
3349         GList *tmp;
3350         char *name;
3351         MonoMethodSignature *sig;
3352         ArrayMethod *am;
3353         MonoType *mtype;
3354
3355         name = mono_string_to_utf8 (m->name);
3356         nparams = mono_array_length (m->parameters);
3357         sig = g_malloc0 (MONO_SIZEOF_METHOD_SIGNATURE + sizeof (MonoType*) * nparams);
3358         sig->hasthis = 1;
3359         sig->sentinelpos = -1;
3360         sig->call_convention = reflection_cc_to_file (m->call_conv);
3361         sig->param_count = nparams;
3362         sig->ret = m->ret ? mono_reflection_type_get_handle (m->ret): &mono_defaults.void_class->byval_arg;
3363         mtype = mono_reflection_type_get_handle (m->parent);
3364         for (i = 0; i < nparams; ++i)
3365                 sig->params [i] = mono_type_array_get_and_resolve (m->parameters, i);
3366
3367         for (tmp = assembly->array_methods; tmp; tmp = tmp->next) {
3368                 am = tmp->data;
3369                 if (strcmp (name, am->name) == 0 && 
3370                                 mono_metadata_type_equal (am->parent, mtype) &&
3371                                 mono_metadata_signature_equal (am->sig, sig)) {
3372                         g_free (name);
3373                         g_free (sig);
3374                         m->table_idx = am->token & 0xffffff;
3375                         return am->token;
3376                 }
3377         }
3378         am = g_new0 (ArrayMethod, 1);
3379         am->name = name;
3380         am->sig = sig;
3381         am->parent = mtype;
3382         am->token = mono_image_get_memberref_token (assembly, am->parent, name,
3383                 method_encode_signature (assembly, sig));
3384         assembly->array_methods = g_list_prepend (assembly->array_methods, am);
3385         m->table_idx = am->token & 0xffffff;
3386         return am->token;
3387 }
3388
3389 /*
3390  * Insert into the metadata tables all the info about the TypeBuilder tb.
3391  * Data in the tables is inserted in a predefined order, since some tables need to be sorted.
3392  */
3393 static void
3394 mono_image_get_type_info (MonoDomain *domain, MonoReflectionTypeBuilder *tb, MonoDynamicImage *assembly)
3395 {
3396         MonoDynamicTable *table;
3397         guint *values;
3398         int i, is_object = 0, is_system = 0;
3399         char *n;
3400
3401         table = &assembly->tables [MONO_TABLE_TYPEDEF];
3402         values = table->values + tb->table_idx * MONO_TYPEDEF_SIZE;
3403         values [MONO_TYPEDEF_FLAGS] = tb->attrs;
3404         n = mono_string_to_utf8 (tb->name);
3405         if (strcmp (n, "Object") == 0)
3406                 is_object++;
3407         values [MONO_TYPEDEF_NAME] = string_heap_insert (&assembly->sheap, n);
3408         g_free (n);
3409         n = mono_string_to_utf8 (tb->nspace);
3410         if (strcmp (n, "System") == 0)
3411                 is_system++;
3412         values [MONO_TYPEDEF_NAMESPACE] = string_heap_insert (&assembly->sheap, n);
3413         g_free (n);
3414         if (tb->parent && !(is_system && is_object) && 
3415                         !(tb->attrs & TYPE_ATTRIBUTE_INTERFACE)) { /* interfaces don't have a parent */
3416                 values [MONO_TYPEDEF_EXTENDS] = mono_image_typedef_or_ref (assembly, mono_reflection_type_get_handle ((MonoReflectionType*)tb->parent));
3417         } else {
3418                 values [MONO_TYPEDEF_EXTENDS] = 0;
3419         }
3420         values [MONO_TYPEDEF_FIELD_LIST] = assembly->tables [MONO_TABLE_FIELD].next_idx;
3421         values [MONO_TYPEDEF_METHOD_LIST] = assembly->tables [MONO_TABLE_METHOD].next_idx;
3422
3423         /*
3424          * if we have explicitlayout or sequentiallayouts, output data in the
3425          * ClassLayout table.
3426          */
3427         if (((tb->attrs & TYPE_ATTRIBUTE_LAYOUT_MASK) != TYPE_ATTRIBUTE_AUTO_LAYOUT) &&
3428                         ((tb->class_size > 0) || (tb->packing_size > 0))) {
3429                 table = &assembly->tables [MONO_TABLE_CLASSLAYOUT];
3430                 table->rows++;
3431                 alloc_table (table, table->rows);
3432                 values = table->values + table->rows * MONO_CLASS_LAYOUT_SIZE;
3433                 values [MONO_CLASS_LAYOUT_PARENT] = tb->table_idx;
3434                 values [MONO_CLASS_LAYOUT_CLASS_SIZE] = tb->class_size;
3435                 values [MONO_CLASS_LAYOUT_PACKING_SIZE] = tb->packing_size;
3436         }
3437
3438         /* handle interfaces */
3439         if (tb->interfaces) {
3440                 table = &assembly->tables [MONO_TABLE_INTERFACEIMPL];
3441                 i = table->rows;
3442                 table->rows += mono_array_length (tb->interfaces);
3443                 alloc_table (table, table->rows);
3444                 values = table->values + (i + 1) * MONO_INTERFACEIMPL_SIZE;
3445                 for (i = 0; i < mono_array_length (tb->interfaces); ++i) {
3446                         MonoReflectionType* iface = (MonoReflectionType*) mono_array_get (tb->interfaces, gpointer, i);
3447                         values [MONO_INTERFACEIMPL_CLASS] = tb->table_idx;
3448                         values [MONO_INTERFACEIMPL_INTERFACE] = mono_image_typedef_or_ref (assembly, mono_reflection_type_get_handle (iface));
3449                         values += MONO_INTERFACEIMPL_SIZE;
3450                 }
3451         }
3452
3453         /* handle fields */
3454         if (tb->fields) {
3455                 table = &assembly->tables [MONO_TABLE_FIELD];
3456                 table->rows += tb->num_fields;
3457                 alloc_table (table, table->rows);
3458                 for (i = 0; i < tb->num_fields; ++i)
3459                         mono_image_get_field_info (
3460                                 mono_array_get (tb->fields, MonoReflectionFieldBuilder*, i), assembly);
3461         }
3462
3463         /* handle constructors */
3464         if (tb->ctors) {
3465                 table = &assembly->tables [MONO_TABLE_METHOD];
3466                 table->rows += mono_array_length (tb->ctors);
3467                 alloc_table (table, table->rows);
3468                 for (i = 0; i < mono_array_length (tb->ctors); ++i)
3469                         mono_image_get_ctor_info (domain,
3470                                 mono_array_get (tb->ctors, MonoReflectionCtorBuilder*, i), assembly);
3471         }
3472
3473         /* handle methods */
3474         if (tb->methods) {
3475                 table = &assembly->tables [MONO_TABLE_METHOD];
3476                 table->rows += tb->num_methods;
3477                 alloc_table (table, table->rows);
3478                 for (i = 0; i < tb->num_methods; ++i)
3479                         mono_image_get_method_info (
3480                                 mono_array_get (tb->methods, MonoReflectionMethodBuilder*, i), assembly);
3481         }
3482
3483         /* Do the same with properties etc.. */
3484         if (tb->events && mono_array_length (tb->events)) {
3485                 table = &assembly->tables [MONO_TABLE_EVENT];
3486                 table->rows += mono_array_length (tb->events);
3487                 alloc_table (table, table->rows);
3488                 table = &assembly->tables [MONO_TABLE_EVENTMAP];
3489                 table->rows ++;
3490                 alloc_table (table, table->rows);
3491                 values = table->values + table->rows * MONO_EVENT_MAP_SIZE;
3492                 values [MONO_EVENT_MAP_PARENT] = tb->table_idx;
3493                 values [MONO_EVENT_MAP_EVENTLIST] = assembly->tables [MONO_TABLE_EVENT].next_idx;
3494                 for (i = 0; i < mono_array_length (tb->events); ++i)
3495                         mono_image_get_event_info (
3496                                 mono_array_get (tb->events, MonoReflectionEventBuilder*, i), assembly);
3497         }
3498         if (tb->properties && mono_array_length (tb->properties)) {
3499                 table = &assembly->tables [MONO_TABLE_PROPERTY];
3500                 table->rows += mono_array_length (tb->properties);
3501                 alloc_table (table, table->rows);
3502                 table = &assembly->tables [MONO_TABLE_PROPERTYMAP];
3503                 table->rows ++;
3504                 alloc_table (table, table->rows);
3505                 values = table->values + table->rows * MONO_PROPERTY_MAP_SIZE;
3506                 values [MONO_PROPERTY_MAP_PARENT] = tb->table_idx;
3507                 values [MONO_PROPERTY_MAP_PROPERTY_LIST] = assembly->tables [MONO_TABLE_PROPERTY].next_idx;
3508                 for (i = 0; i < mono_array_length (tb->properties); ++i)
3509                         mono_image_get_property_info (
3510                                 mono_array_get (tb->properties, MonoReflectionPropertyBuilder*, i), assembly);
3511         }
3512
3513         /* handle generic parameters */
3514         if (tb->generic_params) {
3515                 table = &assembly->tables [MONO_TABLE_GENERICPARAM];
3516                 table->rows += mono_array_length (tb->generic_params);
3517                 alloc_table (table, table->rows);
3518                 for (i = 0; i < mono_array_length (tb->generic_params); ++i) {
3519                         guint32 owner = MONO_TYPEORMETHOD_TYPE | (tb->table_idx << MONO_TYPEORMETHOD_BITS);
3520
3521                         mono_image_get_generic_param_info (
3522                                 mono_array_get (tb->generic_params, MonoReflectionGenericParam*, i), owner, assembly);
3523                 }
3524         }
3525
3526         mono_image_add_decl_security (assembly, 
3527                 mono_metadata_make_token (MONO_TABLE_TYPEDEF, tb->table_idx), tb->permissions);
3528
3529         if (tb->subtypes) {
3530                 MonoDynamicTable *ntable;
3531                 
3532                 ntable = &assembly->tables [MONO_TABLE_NESTEDCLASS];
3533                 ntable->rows += mono_array_length (tb->subtypes);
3534                 alloc_table (ntable, ntable->rows);
3535                 values = ntable->values + ntable->next_idx * MONO_NESTED_CLASS_SIZE;
3536
3537                 for (i = 0; i < mono_array_length (tb->subtypes); ++i) {
3538                         MonoReflectionTypeBuilder *subtype = mono_array_get (tb->subtypes, MonoReflectionTypeBuilder*, i);
3539
3540                         values [MONO_NESTED_CLASS_NESTED] = subtype->table_idx;
3541                         values [MONO_NESTED_CLASS_ENCLOSING] = tb->table_idx;
3542                         /*g_print ("nesting %s (%d) in %s (%d) (rows %d/%d)\n",
3543                                 mono_string_to_utf8 (subtype->name), subtype->table_idx,
3544                                 mono_string_to_utf8 (tb->name), tb->table_idx,
3545                                 ntable->next_idx, ntable->rows);*/
3546                         values += MONO_NESTED_CLASS_SIZE;
3547                         ntable->next_idx++;
3548                 }
3549         }
3550 }
3551 #endif
3552
3553 static void
3554 collect_types (MonoPtrArray *types, MonoReflectionTypeBuilder *type)
3555 {
3556         int i;
3557
3558         mono_ptr_array_append (*types, type);
3559
3560         if (!type->subtypes)
3561                 return;
3562
3563         for (i = 0; i < mono_array_length (type->subtypes); ++i) {
3564                 MonoReflectionTypeBuilder *subtype = mono_array_get (type->subtypes, MonoReflectionTypeBuilder*, i);
3565                 collect_types (types, subtype);
3566         }
3567 }
3568
3569 static gint
3570 compare_types_by_table_idx (MonoReflectionTypeBuilder **type1, MonoReflectionTypeBuilder **type2)
3571 {
3572         if ((*type1)->table_idx < (*type2)->table_idx)
3573                 return -1;
3574         else
3575                 if ((*type1)->table_idx > (*type2)->table_idx)
3576                         return 1;
3577         else
3578                 return 0;
3579 }
3580
3581 static void
3582 params_add_cattrs (MonoDynamicImage *assembly, MonoArray *pinfo) {
3583         int i;
3584
3585         if (!pinfo)
3586                 return;
3587         for (i = 0; i < mono_array_length (pinfo); ++i) {
3588                 MonoReflectionParamBuilder *pb;
3589                 pb = mono_array_get (pinfo, MonoReflectionParamBuilder *, i);
3590                 if (!pb)
3591                         continue;
3592                 mono_image_add_cattrs (assembly, pb->table_idx, MONO_CUSTOM_ATTR_PARAMDEF, pb->cattrs);
3593         }
3594 }
3595
3596 static void
3597 type_add_cattrs (MonoDynamicImage *assembly, MonoReflectionTypeBuilder *tb) {
3598         int i;
3599         
3600         mono_image_add_cattrs (assembly, tb->table_idx, MONO_CUSTOM_ATTR_TYPEDEF, tb->cattrs);
3601         if (tb->fields) {
3602                 for (i = 0; i < tb->num_fields; ++i) {
3603                         MonoReflectionFieldBuilder* fb;
3604                         fb = mono_array_get (tb->fields, MonoReflectionFieldBuilder*, i);
3605                         mono_image_add_cattrs (assembly, fb->table_idx, MONO_CUSTOM_ATTR_FIELDDEF, fb->cattrs);
3606                 }
3607         }
3608         if (tb->events) {
3609                 for (i = 0; i < mono_array_length (tb->events); ++i) {
3610                         MonoReflectionEventBuilder* eb;
3611                         eb = mono_array_get (tb->events, MonoReflectionEventBuilder*, i);
3612                         mono_image_add_cattrs (assembly, eb->table_idx, MONO_CUSTOM_ATTR_EVENT, eb->cattrs);
3613                 }
3614         }
3615         if (tb->properties) {
3616                 for (i = 0; i < mono_array_length (tb->properties); ++i) {
3617                         MonoReflectionPropertyBuilder* pb;
3618                         pb = mono_array_get (tb->properties, MonoReflectionPropertyBuilder*, i);
3619                         mono_image_add_cattrs (assembly, pb->table_idx, MONO_CUSTOM_ATTR_PROPERTY, pb->cattrs);
3620                 }
3621         }
3622         if (tb->ctors) {
3623                 for (i = 0; i < mono_array_length (tb->ctors); ++i) {
3624                         MonoReflectionCtorBuilder* cb;
3625                         cb = mono_array_get (tb->ctors, MonoReflectionCtorBuilder*, i);
3626                         mono_image_add_cattrs (assembly, cb->table_idx, MONO_CUSTOM_ATTR_METHODDEF, cb->cattrs);
3627                         params_add_cattrs (assembly, cb->pinfo);
3628                 }
3629         }
3630
3631         if (tb->methods) {
3632                 for (i = 0; i < tb->num_methods; ++i) {
3633                         MonoReflectionMethodBuilder* mb;
3634                         mb = mono_array_get (tb->methods, MonoReflectionMethodBuilder*, i);
3635                         mono_image_add_cattrs (assembly, mb->table_idx, MONO_CUSTOM_ATTR_METHODDEF, mb->cattrs);
3636                         params_add_cattrs (assembly, mb->pinfo);
3637                 }
3638         }
3639
3640         if (tb->subtypes) {
3641                 for (i = 0; i < mono_array_length (tb->subtypes); ++i)
3642                         type_add_cattrs (assembly, mono_array_get (tb->subtypes, MonoReflectionTypeBuilder*, i));
3643         }
3644 }
3645
3646 static void
3647 module_add_cattrs (MonoDynamicImage *assembly, MonoReflectionModuleBuilder *moduleb)
3648 {
3649         int i;
3650         
3651         mono_image_add_cattrs (assembly, moduleb->table_idx, MONO_CUSTOM_ATTR_MODULE, moduleb->cattrs);
3652
3653         if (moduleb->global_methods) {
3654                 for (i = 0; i < mono_array_length (moduleb->global_methods); ++i) {
3655                         MonoReflectionMethodBuilder* mb = mono_array_get (moduleb->global_methods, MonoReflectionMethodBuilder*, i);
3656                         mono_image_add_cattrs (assembly, mb->table_idx, MONO_CUSTOM_ATTR_METHODDEF, mb->cattrs);
3657                         params_add_cattrs (assembly, mb->pinfo);
3658                 }
3659         }
3660
3661         if (moduleb->global_fields) {
3662                 for (i = 0; i < mono_array_length (moduleb->global_fields); ++i) {
3663                         MonoReflectionFieldBuilder *fb = mono_array_get (moduleb->global_fields, MonoReflectionFieldBuilder*, i);
3664                         mono_image_add_cattrs (assembly, fb->table_idx, MONO_CUSTOM_ATTR_FIELDDEF, fb->cattrs);
3665                 }
3666         }
3667         
3668         if (moduleb->types) {
3669                 for (i = 0; i < moduleb->num_types; ++i)
3670                         type_add_cattrs (assembly, mono_array_get (moduleb->types, MonoReflectionTypeBuilder*, i));
3671         }
3672 }
3673
3674 static void
3675 mono_image_fill_file_table (MonoDomain *domain, MonoReflectionModule *module, MonoDynamicImage *assembly)
3676 {
3677         MonoDynamicTable *table;
3678         guint32 *values;
3679         char blob_size [6];
3680         guchar hash [20];
3681         char *b = blob_size;
3682         char *dir, *path;
3683
3684         table = &assembly->tables [MONO_TABLE_FILE];
3685         table->rows++;
3686         alloc_table (table, table->rows);
3687         values = table->values + table->next_idx * MONO_FILE_SIZE;
3688         values [MONO_FILE_FLAGS] = FILE_CONTAINS_METADATA;
3689         values [MONO_FILE_NAME] = string_heap_insert (&assembly->sheap, module->image->module_name);
3690         if (module->image->dynamic) {
3691                 /* This depends on the fact that the main module is emitted last */
3692                 dir = mono_string_to_utf8 (((MonoReflectionModuleBuilder*)module)->assemblyb->dir);
3693                 path = g_strdup_printf ("%s%c%s", dir, G_DIR_SEPARATOR, module->image->module_name);
3694         } else {
3695                 dir = NULL;
3696                 path = g_strdup (module->image->name);
3697         }
3698         mono_sha1_get_digest_from_file (path, hash);
3699         g_free (dir);
3700         g_free (path);
3701         mono_metadata_encode_value (20, b, &b);
3702         values [MONO_FILE_HASH_VALUE] = mono_image_add_stream_data (&assembly->blob, blob_size, b-blob_size);
3703         mono_image_add_stream_data (&assembly->blob, (char*)hash, 20);
3704         table->next_idx ++;
3705 }
3706
3707 static void
3708 mono_image_fill_module_table (MonoDomain *domain, MonoReflectionModuleBuilder *mb, MonoDynamicImage *assembly)
3709 {
3710         MonoDynamicTable *table;
3711         int i;
3712
3713         table = &assembly->tables [MONO_TABLE_MODULE];
3714         mb->table_idx = table->next_idx ++;
3715         table->values [mb->table_idx * MONO_MODULE_SIZE + MONO_MODULE_NAME] = string_heap_insert_mstring (&assembly->sheap, mb->module.name);
3716         i = mono_image_add_stream_data (&assembly->guid, mono_array_addr (mb->guid, char, 0), 16);
3717         i /= 16;
3718         ++i;
3719         table->values [mb->table_idx * MONO_MODULE_SIZE + MONO_MODULE_GENERATION] = 0;
3720         table->values [mb->table_idx * MONO_MODULE_SIZE + MONO_MODULE_MVID] = i;
3721         table->values [mb->table_idx * MONO_MODULE_SIZE + MONO_MODULE_ENC] = 0;
3722         table->values [mb->table_idx * MONO_MODULE_SIZE + MONO_MODULE_ENCBASE] = 0;
3723 }
3724
3725 static guint32
3726 mono_image_fill_export_table_from_class (MonoDomain *domain, MonoClass *klass,
3727         guint32 module_index, guint32 parent_index, MonoDynamicImage *assembly)
3728 {
3729         MonoDynamicTable *table;
3730         guint32 *values;
3731         guint32 visib, res;
3732
3733         visib = klass->flags & TYPE_ATTRIBUTE_VISIBILITY_MASK;
3734         if (! ((visib & TYPE_ATTRIBUTE_PUBLIC) || (visib & TYPE_ATTRIBUTE_NESTED_PUBLIC)))
3735                 return 0;
3736
3737         table = &assembly->tables [MONO_TABLE_EXPORTEDTYPE];
3738         table->rows++;
3739         alloc_table (table, table->rows);
3740         values = table->values + table->next_idx * MONO_EXP_TYPE_SIZE;
3741
3742         values [MONO_EXP_TYPE_FLAGS] = klass->flags;
3743         values [MONO_EXP_TYPE_TYPEDEF] = klass->type_token;
3744         if (klass->nested_in)
3745                 values [MONO_EXP_TYPE_IMPLEMENTATION] = (parent_index << MONO_IMPLEMENTATION_BITS) + MONO_IMPLEMENTATION_EXP_TYPE;
3746         else
3747                 values [MONO_EXP_TYPE_IMPLEMENTATION] = (module_index << MONO_IMPLEMENTATION_BITS) + MONO_IMPLEMENTATION_FILE;
3748         values [MONO_EXP_TYPE_NAME] = string_heap_insert (&assembly->sheap, klass->name);
3749         values [MONO_EXP_TYPE_NAMESPACE] = string_heap_insert (&assembly->sheap, klass->name_space);
3750
3751         res = table->next_idx;
3752
3753         table->next_idx ++;
3754
3755         /* Emit nested types */
3756         if (klass->ext && klass->ext->nested_classes) {
3757                 GList *tmp;
3758
3759                 for (tmp = klass->ext->nested_classes; tmp; tmp = tmp->next)
3760                         mono_image_fill_export_table_from_class (domain, tmp->data, module_index, table->next_idx - 1, assembly);
3761         }
3762
3763         return res;
3764 }
3765
3766 static void
3767 mono_image_fill_export_table (MonoDomain *domain, MonoReflectionTypeBuilder *tb,
3768         guint32 module_index, guint32 parent_index, MonoDynamicImage *assembly)
3769 {
3770         MonoClass *klass;
3771         guint32 idx, i;
3772
3773         klass = mono_class_from_mono_type (mono_reflection_type_get_handle ((MonoReflectionType*)tb));
3774
3775         klass->type_token = mono_metadata_make_token (MONO_TABLE_TYPEDEF, tb->table_idx);
3776
3777         idx = mono_image_fill_export_table_from_class (domain, klass, module_index, 
3778                                                                                                    parent_index, assembly);
3779
3780         /* 
3781          * Emit nested types
3782          * We need to do this ourselves since klass->nested_classes is not set up.
3783          */
3784         if (tb->subtypes) {
3785                 for (i = 0; i < mono_array_length (tb->subtypes); ++i)
3786                         mono_image_fill_export_table (domain, mono_array_get (tb->subtypes, MonoReflectionTypeBuilder*, i), module_index, idx, assembly);
3787         }
3788 }
3789
3790 static void
3791 mono_image_fill_export_table_from_module (MonoDomain *domain, MonoReflectionModule *module,
3792         guint32 module_index, MonoDynamicImage *assembly)
3793 {
3794         MonoImage *image = module->image;
3795         MonoTableInfo  *t;
3796         guint32 i;
3797
3798         t = &image->tables [MONO_TABLE_TYPEDEF];
3799
3800         for (i = 0; i < t->rows; ++i) {
3801                 MonoClass *klass = mono_class_get (image, mono_metadata_make_token (MONO_TABLE_TYPEDEF, i + 1));
3802
3803                 if (klass->flags & TYPE_ATTRIBUTE_PUBLIC)
3804                         mono_image_fill_export_table_from_class (domain, klass, module_index, 0, assembly);
3805         }
3806 }
3807
3808 static void
3809 add_exported_type (MonoReflectionAssemblyBuilder *assemblyb, MonoDynamicImage *assembly, MonoClass *klass, guint32 parent_index)
3810 {
3811         MonoDynamicTable *table;
3812         guint32 *values;
3813         guint32 scope, scope_idx, impl, current_idx;
3814         gboolean forwarder = TRUE;
3815         gpointer iter = NULL;
3816         MonoClass *nested;
3817
3818         if (klass->nested_in) {
3819                 impl = (parent_index << MONO_IMPLEMENTATION_BITS) + MONO_IMPLEMENTATION_EXP_TYPE;
3820                 forwarder = FALSE;
3821         } else {
3822                 scope = resolution_scope_from_image (assembly, klass->image);
3823                 g_assert ((scope & MONO_RESOLTION_SCOPE_MASK) == MONO_RESOLTION_SCOPE_ASSEMBLYREF);
3824                 scope_idx = scope >> MONO_RESOLTION_SCOPE_BITS;
3825                 impl = (scope_idx << MONO_IMPLEMENTATION_BITS) + MONO_IMPLEMENTATION_ASSEMBLYREF;
3826         }
3827
3828         table = &assembly->tables [MONO_TABLE_EXPORTEDTYPE];
3829
3830         table->rows++;
3831         alloc_table (table, table->rows);
3832         current_idx = table->next_idx;
3833         values = table->values + current_idx * MONO_EXP_TYPE_SIZE;
3834
3835         values [MONO_EXP_TYPE_FLAGS] = forwarder ? TYPE_ATTRIBUTE_FORWARDER : 0;
3836         values [MONO_EXP_TYPE_TYPEDEF] = 0;
3837         values [MONO_EXP_TYPE_IMPLEMENTATION] = impl;
3838         values [MONO_EXP_TYPE_NAME] = string_heap_insert (&assembly->sheap, klass->name);
3839         values [MONO_EXP_TYPE_NAMESPACE] = string_heap_insert (&assembly->sheap, klass->name_space);
3840
3841         table->next_idx++;
3842
3843         while ((nested = mono_class_get_nested_types (klass, &iter)))
3844                 add_exported_type (assemblyb, assembly, nested, current_idx);
3845 }
3846
3847 static void
3848 mono_image_fill_export_table_from_type_forwarders (MonoReflectionAssemblyBuilder *assemblyb, MonoDynamicImage *assembly)
3849 {
3850         MonoClass *klass;
3851         int i;
3852
3853         if (!assemblyb->type_forwarders)
3854                 return;
3855
3856         for (i = 0; i < mono_array_length (assemblyb->type_forwarders); ++i) {
3857                 MonoReflectionType *t = mono_array_get (assemblyb->type_forwarders, MonoReflectionType *, i);
3858                 MonoType *type;
3859                 if (!t)
3860                         continue;
3861
3862                 type = mono_reflection_type_get_handle (t);
3863                 g_assert (type);
3864
3865                 klass = mono_class_from_mono_type (type);
3866
3867                 add_exported_type (assemblyb, assembly, klass, 0);
3868         }
3869 }
3870
3871 #define align_pointer(base,p)\
3872         do {\
3873                 guint32 __diff = (unsigned char*)(p)-(unsigned char*)(base);\
3874                 if (__diff & 3)\
3875                         (p) += 4 - (__diff & 3);\
3876         } while (0)
3877
3878 static int
3879 compare_constants (const void *a, const void *b)
3880 {
3881         const guint32 *a_values = a;
3882         const guint32 *b_values = b;
3883         return a_values [MONO_CONSTANT_PARENT] - b_values [MONO_CONSTANT_PARENT];
3884 }
3885
3886 static int
3887 compare_semantics (const void *a, const void *b)
3888 {
3889         const guint32 *a_values = a;
3890         const guint32 *b_values = b;
3891         int assoc = a_values [MONO_METHOD_SEMA_ASSOCIATION] - b_values [MONO_METHOD_SEMA_ASSOCIATION];
3892         if (assoc)
3893                 return assoc;
3894         return a_values [MONO_METHOD_SEMA_SEMANTICS] - b_values [MONO_METHOD_SEMA_SEMANTICS];
3895 }
3896
3897 static int
3898 compare_custom_attrs (const void *a, const void *b)
3899 {
3900         const guint32 *a_values = a;
3901         const guint32 *b_values = b;
3902
3903         return a_values [MONO_CUSTOM_ATTR_PARENT] - b_values [MONO_CUSTOM_ATTR_PARENT];
3904 }
3905
3906 static int
3907 compare_field_marshal (const void *a, const void *b)
3908 {
3909         const guint32 *a_values = a;
3910         const guint32 *b_values = b;
3911
3912         return a_values [MONO_FIELD_MARSHAL_PARENT] - b_values [MONO_FIELD_MARSHAL_PARENT];
3913 }
3914
3915 static int
3916 compare_nested (const void *a, const void *b)
3917 {
3918         const guint32 *a_values = a;
3919         const guint32 *b_values = b;
3920
3921         return a_values [MONO_NESTED_CLASS_NESTED] - b_values [MONO_NESTED_CLASS_NESTED];
3922 }
3923
3924 static int
3925 compare_genericparam (const void *a, const void *b)
3926 {
3927         const GenericParamTableEntry **a_entry = (const GenericParamTableEntry **) a;
3928         const GenericParamTableEntry **b_entry = (const GenericParamTableEntry **) b;
3929
3930         if ((*b_entry)->owner == (*a_entry)->owner)
3931                 return 
3932                         mono_type_get_generic_param_num (mono_reflection_type_get_handle ((MonoReflectionType*)(*a_entry)->gparam)) -
3933                         mono_type_get_generic_param_num (mono_reflection_type_get_handle ((MonoReflectionType*)(*b_entry)->gparam));
3934         else
3935                 return (*a_entry)->owner - (*b_entry)->owner;
3936 }
3937
3938 static int
3939 compare_declsecurity_attrs (const void *a, const void *b)
3940 {
3941         const guint32 *a_values = a;
3942         const guint32 *b_values = b;
3943
3944         return a_values [MONO_DECL_SECURITY_PARENT] - b_values [MONO_DECL_SECURITY_PARENT];
3945 }
3946
3947 static int
3948 compare_interface_impl (const void *a, const void *b)
3949 {
3950         const guint32 *a_values = a;
3951         const guint32 *b_values = b;
3952
3953         int klass = a_values [MONO_INTERFACEIMPL_CLASS] - b_values [MONO_INTERFACEIMPL_CLASS];
3954         if (klass)
3955                 return klass;
3956
3957         return a_values [MONO_INTERFACEIMPL_INTERFACE] - b_values [MONO_INTERFACEIMPL_INTERFACE];
3958 }
3959
3960 static void
3961 pad_heap (MonoDynamicStream *sh)
3962 {
3963         if (sh->index & 3) {
3964                 int sz = 4 - (sh->index & 3);
3965                 memset (sh->data + sh->index, 0, sz);
3966                 sh->index += sz;
3967         }
3968 }
3969
3970 struct StreamDesc {
3971         const char *name;
3972         MonoDynamicStream *stream;
3973 };
3974
3975 /*
3976  * build_compressed_metadata() fills in the blob of data that represents the 
3977  * raw metadata as it will be saved in the PE file. The five streams are output 
3978  * and the metadata tables are comnpressed from the guint32 array representation, 
3979  * to the compressed on-disk format.
3980  */
3981 static void
3982 build_compressed_metadata (MonoDynamicImage *assembly)
3983 {
3984         MonoDynamicTable *table;
3985         int i;
3986         guint64 valid_mask = 0;
3987         guint64 sorted_mask;
3988         guint32 heapt_size = 0;
3989         guint32 meta_size = 256; /* allow for header and other stuff */
3990         guint32 table_offset;
3991         guint32 ntables = 0;
3992         guint64 *int64val;
3993         guint32 *int32val;
3994         guint16 *int16val;
3995         MonoImage *meta;
3996         unsigned char *p;
3997         struct StreamDesc stream_desc [5];
3998
3999         qsort (assembly->gen_params->pdata, assembly->gen_params->len, sizeof (gpointer), compare_genericparam);
4000         for (i = 0; i < assembly->gen_params->len; i++){
4001                 GenericParamTableEntry *entry = g_ptr_array_index (assembly->gen_params, i);
4002                 write_generic_param_entry (assembly, entry);
4003         }
4004
4005         stream_desc [0].name  = "#~";
4006         stream_desc [0].stream = &assembly->tstream;
4007         stream_desc [1].name  = "#Strings";
4008         stream_desc [1].stream = &assembly->sheap;
4009         stream_desc [2].name  = "#US";
4010         stream_desc [2].stream = &assembly->us;
4011         stream_desc [3].name  = "#Blob";
4012         stream_desc [3].stream = &assembly->blob;
4013         stream_desc [4].name  = "#GUID";
4014         stream_desc [4].stream = &assembly->guid;
4015         
4016         /* tables that are sorted */
4017         sorted_mask = ((guint64)1 << MONO_TABLE_CONSTANT) | ((guint64)1 << MONO_TABLE_FIELDMARSHAL)
4018                 | ((guint64)1 << MONO_TABLE_METHODSEMANTICS) | ((guint64)1 << MONO_TABLE_CLASSLAYOUT)
4019                 | ((guint64)1 << MONO_TABLE_FIELDLAYOUT) | ((guint64)1 << MONO_TABLE_FIELDRVA)
4020                 | ((guint64)1 << MONO_TABLE_IMPLMAP) | ((guint64)1 << MONO_TABLE_NESTEDCLASS)
4021                 | ((guint64)1 << MONO_TABLE_METHODIMPL) | ((guint64)1 << MONO_TABLE_CUSTOMATTRIBUTE)
4022                 | ((guint64)1 << MONO_TABLE_DECLSECURITY) | ((guint64)1 << MONO_TABLE_GENERICPARAM)
4023                 | ((guint64)1 << MONO_TABLE_INTERFACEIMPL);
4024         
4025         /* Compute table sizes */
4026         /* the MonoImage has already been created in mono_image_basic_init() */
4027         meta = &assembly->image;
4028
4029         /* sizes should be multiple of 4 */
4030         pad_heap (&assembly->blob);
4031         pad_heap (&assembly->guid);
4032         pad_heap (&assembly->sheap);
4033         pad_heap (&assembly->us);
4034
4035         /* Setup the info used by compute_sizes () */
4036         meta->idx_blob_wide = assembly->blob.index >= 65536 ? 1 : 0;
4037         meta->idx_guid_wide = assembly->guid.index >= 65536 ? 1 : 0;
4038         meta->idx_string_wide = assembly->sheap.index >= 65536 ? 1 : 0;
4039
4040         meta_size += assembly->blob.index;
4041         meta_size += assembly->guid.index;
4042         meta_size += assembly->sheap.index;
4043         meta_size += assembly->us.index;
4044
4045         for (i=0; i < MONO_TABLE_NUM; ++i)
4046                 meta->tables [i].rows = assembly->tables [i].rows;
4047         
4048         for (i = 0; i < MONO_TABLE_NUM; i++){
4049                 if (meta->tables [i].rows == 0)
4050                         continue;
4051                 valid_mask |= (guint64)1 << i;
4052                 ntables ++;
4053                 meta->tables [i].row_size = mono_metadata_compute_size (
4054                         meta, i, &meta->tables [i].size_bitfield);
4055                 heapt_size += meta->tables [i].row_size * meta->tables [i].rows;
4056         }
4057         heapt_size += 24; /* #~ header size */
4058         heapt_size += ntables * 4;
4059         /* make multiple of 4 */
4060         heapt_size += 3;
4061         heapt_size &= ~3;
4062         meta_size += heapt_size;
4063         meta->raw_metadata = g_malloc0 (meta_size);
4064         p = (unsigned char*)meta->raw_metadata;
4065         /* the metadata signature */
4066         *p++ = 'B'; *p++ = 'S'; *p++ = 'J'; *p++ = 'B';
4067         /* version numbers and 4 bytes reserved */
4068         int16val = (guint16*)p;
4069         *int16val++ = GUINT16_TO_LE (meta->md_version_major);
4070         *int16val = GUINT16_TO_LE (meta->md_version_minor);
4071         p += 8;
4072         /* version string */
4073         int32val = (guint32*)p;
4074         *int32val = GUINT32_TO_LE ((strlen (meta->version) + 3) & (~3)); /* needs to be multiple of 4 */
4075         p += 4;
4076         memcpy (p, meta->version, strlen (meta->version));
4077         p += GUINT32_FROM_LE (*int32val);
4078         align_pointer (meta->raw_metadata, p);
4079         int16val = (guint16*)p;
4080         *int16val++ = GUINT16_TO_LE (0); /* flags must be 0 */
4081         *int16val = GUINT16_TO_LE (5); /* number of streams */
4082         p += 4;
4083
4084         /*
4085          * write the stream info.
4086          */
4087         table_offset = (p - (unsigned char*)meta->raw_metadata) + 5 * 8 + 40; /* room needed for stream headers */
4088         table_offset += 3; table_offset &= ~3;
4089
4090         assembly->tstream.index = heapt_size;
4091         for (i = 0; i < 5; ++i) {
4092                 int32val = (guint32*)p;
4093                 stream_desc [i].stream->offset = table_offset;
4094                 *int32val++ = GUINT32_TO_LE (table_offset);
4095                 *int32val = GUINT32_TO_LE (stream_desc [i].stream->index);
4096                 table_offset += GUINT32_FROM_LE (*int32val);
4097                 table_offset += 3; table_offset &= ~3;
4098                 p += 8;
4099                 strcpy ((char*)p, stream_desc [i].name);
4100                 p += strlen (stream_desc [i].name) + 1;
4101                 align_pointer (meta->raw_metadata, p);
4102         }
4103         /* 
4104          * now copy the data, the table stream header and contents goes first.
4105          */
4106         g_assert ((p - (unsigned char*)meta->raw_metadata) < assembly->tstream.offset);
4107         p = (guchar*)meta->raw_metadata + assembly->tstream.offset;
4108         int32val = (guint32*)p;
4109         *int32val = GUINT32_TO_LE (0); /* reserved */
4110         p += 4;
4111
4112         *p++ = 2; /* version */
4113         *p++ = 0;
4114
4115         if (meta->idx_string_wide)
4116                 *p |= 0x01;
4117         if (meta->idx_guid_wide)
4118                 *p |= 0x02;
4119         if (meta->idx_blob_wide)
4120                 *p |= 0x04;
4121         ++p;
4122         *p++ = 1; /* reserved */
4123         int64val = (guint64*)p;
4124         *int64val++ = GUINT64_TO_LE (valid_mask);
4125         *int64val++ = GUINT64_TO_LE (valid_mask & sorted_mask); /* bitvector of sorted tables  */
4126         p += 16;
4127         int32val = (guint32*)p;
4128         for (i = 0; i < MONO_TABLE_NUM; i++){
4129                 if (meta->tables [i].rows == 0)
4130                         continue;
4131                 *int32val++ = GUINT32_TO_LE (meta->tables [i].rows);
4132         }
4133         p = (unsigned char*)int32val;
4134
4135         /* sort the tables that still need sorting */
4136         table = &assembly->tables [MONO_TABLE_CONSTANT];
4137         if (table->rows)
4138                 qsort (table->values + MONO_CONSTANT_SIZE, table->rows, sizeof (guint32) * MONO_CONSTANT_SIZE, compare_constants);
4139         table = &assembly->tables [MONO_TABLE_METHODSEMANTICS];
4140         if (table->rows)
4141                 qsort (table->values + MONO_METHOD_SEMA_SIZE, table->rows, sizeof (guint32) * MONO_METHOD_SEMA_SIZE, compare_semantics);
4142         table = &assembly->tables [MONO_TABLE_CUSTOMATTRIBUTE];
4143         if (table->rows)
4144                 qsort (table->values + MONO_CUSTOM_ATTR_SIZE, table->rows, sizeof (guint32) * MONO_CUSTOM_ATTR_SIZE, compare_custom_attrs);
4145         table = &assembly->tables [MONO_TABLE_FIELDMARSHAL];
4146         if (table->rows)
4147                 qsort (table->values + MONO_FIELD_MARSHAL_SIZE, table->rows, sizeof (guint32) * MONO_FIELD_MARSHAL_SIZE, compare_field_marshal);
4148         table = &assembly->tables [MONO_TABLE_NESTEDCLASS];
4149         if (table->rows)
4150                 qsort (table->values + MONO_NESTED_CLASS_SIZE, table->rows, sizeof (guint32) * MONO_NESTED_CLASS_SIZE, compare_nested);
4151         /* Section 21.11 DeclSecurity in Partition II doesn't specify this to be sorted by MS implementation requires it */
4152         table = &assembly->tables [MONO_TABLE_DECLSECURITY];
4153         if (table->rows)
4154                 qsort (table->values + MONO_DECL_SECURITY_SIZE, table->rows, sizeof (guint32) * MONO_DECL_SECURITY_SIZE, compare_declsecurity_attrs);
4155         table = &assembly->tables [MONO_TABLE_INTERFACEIMPL];
4156         if (table->rows)
4157                 qsort (table->values + MONO_INTERFACEIMPL_SIZE, table->rows, sizeof (guint32) * MONO_INTERFACEIMPL_SIZE, compare_interface_impl);
4158
4159         /* compress the tables */
4160         for (i = 0; i < MONO_TABLE_NUM; i++){
4161                 int row, col;
4162                 guint32 *values;
4163                 guint32 bitfield = meta->tables [i].size_bitfield;
4164                 if (!meta->tables [i].rows)
4165                         continue;
4166                 if (assembly->tables [i].columns != mono_metadata_table_count (bitfield))
4167                         g_error ("col count mismatch in %d: %d %d", i, assembly->tables [i].columns, mono_metadata_table_count (bitfield));
4168                 meta->tables [i].base = (char*)p;
4169                 for (row = 1; row <= meta->tables [i].rows; ++row) {
4170                         values = assembly->tables [i].values + row * assembly->tables [i].columns;
4171                         for (col = 0; col < assembly->tables [i].columns; ++col) {
4172                                 switch (mono_metadata_table_size (bitfield, col)) {
4173                                 case 1:
4174                                         *p++ = values [col];
4175                                         break;
4176                                 case 2:
4177                                         *p++ = values [col] & 0xff;
4178                                         *p++ = (values [col] >> 8) & 0xff;
4179                                         break;
4180                                 case 4:
4181                                         *p++ = values [col] & 0xff;
4182                                         *p++ = (values [col] >> 8) & 0xff;
4183                                         *p++ = (values [col] >> 16) & 0xff;
4184                                         *p++ = (values [col] >> 24) & 0xff;
4185                                         break;
4186                                 default:
4187                                         g_assert_not_reached ();
4188                                 }
4189                         }
4190                 }
4191                 g_assert ((p - (const unsigned char*)meta->tables [i].base) == (meta->tables [i].rows * meta->tables [i].row_size));
4192         }
4193         
4194         g_assert (assembly->guid.offset + assembly->guid.index < meta_size);
4195         memcpy (meta->raw_metadata + assembly->sheap.offset, assembly->sheap.data, assembly->sheap.index);
4196         memcpy (meta->raw_metadata + assembly->us.offset, assembly->us.data, assembly->us.index);
4197         memcpy (meta->raw_metadata + assembly->blob.offset, assembly->blob.data, assembly->blob.index);
4198         memcpy (meta->raw_metadata + assembly->guid.offset, assembly->guid.data, assembly->guid.index);
4199
4200         assembly->meta_size = assembly->guid.offset + assembly->guid.index;
4201 }
4202
4203 /*
4204  * Some tables in metadata need to be sorted according to some criteria, but
4205  * when methods and fields are first created with reflection, they may be assigned a token
4206  * that doesn't correspond to the final token they will get assigned after the sorting.
4207  * ILGenerator.cs keeps a fixup table that maps the position of tokens in the IL code stream
4208  * with the reflection objects that represent them. Once all the tables are set up, the 
4209  * reflection objects will contains the correct table index. fixup_method() will fixup the
4210  * tokens for the method with ILGenerator @ilgen.
4211  */
4212 static void
4213 fixup_method (MonoReflectionILGen *ilgen, gpointer value, MonoDynamicImage *assembly)
4214 {
4215         guint32 code_idx = GPOINTER_TO_UINT (value);
4216         MonoReflectionILTokenInfo *iltoken;
4217         MonoReflectionFieldBuilder *field;
4218         MonoReflectionCtorBuilder *ctor;
4219         MonoReflectionMethodBuilder *method;
4220         MonoReflectionTypeBuilder *tb;
4221         MonoReflectionArrayMethod *am;
4222         guint32 i, idx = 0;
4223         unsigned char *target;
4224
4225         for (i = 0; i < ilgen->num_token_fixups; ++i) {
4226                 iltoken = (MonoReflectionILTokenInfo *)mono_array_addr_with_size (ilgen->token_fixups, sizeof (MonoReflectionILTokenInfo), i);
4227                 target = (guchar*)assembly->code.data + code_idx + iltoken->code_pos;
4228                 switch (target [3]) {
4229                 case MONO_TABLE_FIELD:
4230                         if (!strcmp (iltoken->member->vtable->klass->name, "FieldBuilder")) {
4231                                 field = (MonoReflectionFieldBuilder *)iltoken->member;
4232                                 idx = field->table_idx;
4233                         } else if (!strcmp (iltoken->member->vtable->klass->name, "MonoField")) {
4234                                 MonoClassField *f = ((MonoReflectionField*)iltoken->member)->field;
4235                                 idx = GPOINTER_TO_UINT (g_hash_table_lookup (assembly->field_to_table_idx, f));
4236                         } else {
4237                                 g_assert_not_reached ();
4238                         }
4239                         break;
4240                 case MONO_TABLE_METHOD:
4241                         if (!strcmp (iltoken->member->vtable->klass->name, "MethodBuilder")) {
4242                                 method = (MonoReflectionMethodBuilder *)iltoken->member;
4243                                 idx = method->table_idx;
4244                         } else if (!strcmp (iltoken->member->vtable->klass->name, "ConstructorBuilder")) {
4245                                 ctor = (MonoReflectionCtorBuilder *)iltoken->member;
4246                                 idx = ctor->table_idx;
4247                         } else if (!strcmp (iltoken->member->vtable->klass->name, "MonoMethod") || 
4248                                            !strcmp (iltoken->member->vtable->klass->name, "MonoCMethod")) {
4249                                 MonoMethod *m = ((MonoReflectionMethod*)iltoken->member)->method;
4250                                 idx = GPOINTER_TO_UINT (g_hash_table_lookup (assembly->method_to_table_idx, m));
4251                         } else {
4252                                 g_assert_not_reached ();
4253                         }
4254                         break;
4255                 case MONO_TABLE_TYPEDEF:
4256                         if (strcmp (iltoken->member->vtable->klass->name, "TypeBuilder"))
4257                                 g_assert_not_reached ();
4258                         tb = (MonoReflectionTypeBuilder *)iltoken->member;
4259                         idx = tb->table_idx;
4260                         break;
4261                 case MONO_TABLE_MEMBERREF:
4262                         if (!strcmp (iltoken->member->vtable->klass->name, "MonoArrayMethod")) {
4263                                 am = (MonoReflectionArrayMethod*)iltoken->member;
4264                                 idx = am->table_idx;
4265                         } else if (!strcmp (iltoken->member->vtable->klass->name, "MonoMethod") ||
4266                                    !strcmp (iltoken->member->vtable->klass->name, "MonoCMethod") ||
4267                                    !strcmp (iltoken->member->vtable->klass->name, "MonoGenericMethod") ||
4268                                    !strcmp (iltoken->member->vtable->klass->name, "MonoGenericCMethod")) {
4269                                 MonoMethod *m = ((MonoReflectionMethod*)iltoken->member)->method;
4270                                 g_assert (m->klass->generic_class || m->klass->generic_container);
4271                                 continue;
4272                         } else if (!strcmp (iltoken->member->vtable->klass->name, "FieldBuilder")) {
4273                                 continue;
4274                         } else if (!strcmp (iltoken->member->vtable->klass->name, "MonoField")) {
4275                                 MonoClassField *f = ((MonoReflectionField*)iltoken->member)->field;
4276                                 g_assert (is_field_on_inst (f));
4277                                 continue;
4278                         } else if (!strcmp (iltoken->member->vtable->klass->name, "MethodBuilder") ||
4279                                         !strcmp (iltoken->member->vtable->klass->name, "ConstructorBuilder")) {
4280                                 continue;
4281                         } else if (!strcmp (iltoken->member->vtable->klass->name, "FieldOnTypeBuilderInst")) {
4282                                 continue;
4283                         } else if (!strcmp (iltoken->member->vtable->klass->name, "MethodOnTypeBuilderInst")) {
4284                                 continue;
4285                         } else if (!strcmp (iltoken->member->vtable->klass->name, "ConstructorOnTypeBuilderInst")) {
4286                                 continue;
4287                         } else {
4288                                 g_assert_not_reached ();
4289                         }
4290                         break;
4291                 case MONO_TABLE_METHODSPEC:
4292                         if (!strcmp (iltoken->member->vtable->klass->name, "MonoGenericMethod")) {
4293                                 MonoMethod *m = ((MonoReflectionMethod*)iltoken->member)->method;
4294                                 g_assert (mono_method_signature (m)->generic_param_count);
4295                                 continue;
4296                         } else if (!strcmp (iltoken->member->vtable->klass->name, "MethodBuilder")) {
4297                                 continue;
4298                         } else if (!strcmp (iltoken->member->vtable->klass->name, "MethodOnTypeBuilderInst")) {
4299                                 continue;
4300                         } else {
4301                                 g_assert_not_reached ();
4302                         }
4303                         break;
4304                 default:
4305                         g_error ("got unexpected table 0x%02x in fixup", target [3]);
4306                 }
4307                 target [0] = idx & 0xff;
4308                 target [1] = (idx >> 8) & 0xff;
4309                 target [2] = (idx >> 16) & 0xff;
4310         }
4311 }
4312
4313 /*
4314  * fixup_cattrs:
4315  *
4316  *   The CUSTOM_ATTRIBUTE table might contain METHODDEF tokens whose final
4317  * value is not known when the table is emitted.
4318  */
4319 static void
4320 fixup_cattrs (MonoDynamicImage *assembly)
4321 {
4322         MonoDynamicTable *table;
4323         guint32 *values;
4324         guint32 type, i, idx, token;
4325         MonoObject *ctor;
4326
4327         table = &assembly->tables [MONO_TABLE_CUSTOMATTRIBUTE];
4328
4329         for (i = 0; i < table->rows; ++i) {
4330                 values = table->values + ((i + 1) * MONO_CUSTOM_ATTR_SIZE);
4331
4332                 type = values [MONO_CUSTOM_ATTR_TYPE];
4333                 if ((type & MONO_CUSTOM_ATTR_TYPE_MASK) == MONO_CUSTOM_ATTR_TYPE_METHODDEF) {
4334                         idx = type >> MONO_CUSTOM_ATTR_TYPE_BITS;
4335                         token = mono_metadata_make_token (MONO_TABLE_METHOD, idx);
4336                         ctor = mono_g_hash_table_lookup (assembly->remapped_tokens, GUINT_TO_POINTER (token));
4337                         g_assert (ctor);
4338
4339                         if (!strcmp (ctor->vtable->klass->name, "MonoCMethod")) {
4340                                 MonoMethod *m = ((MonoReflectionMethod*)ctor)->method;
4341                                 idx = GPOINTER_TO_UINT (g_hash_table_lookup (assembly->method_to_table_idx, m));
4342                                 values [MONO_CUSTOM_ATTR_TYPE] = (idx << MONO_CUSTOM_ATTR_TYPE_BITS) | MONO_CUSTOM_ATTR_TYPE_METHODDEF;
4343                         } else if (!strcmp (ctor->vtable->klass->name, "ConstructorBuilder")) {
4344                                 MonoMethod *m = ((MonoReflectionCtorBuilder*)ctor)->mhandle;
4345                                 idx = GPOINTER_TO_UINT (g_hash_table_lookup (assembly->method_to_table_idx, m));
4346                                 values [MONO_CUSTOM_ATTR_TYPE] = (idx << MONO_CUSTOM_ATTR_TYPE_BITS) | MONO_CUSTOM_ATTR_TYPE_METHODDEF;
4347                         }
4348                 }
4349         }
4350 }
4351
4352 static void
4353 assembly_add_resource_manifest (MonoReflectionModuleBuilder *mb, MonoDynamicImage *assembly, MonoReflectionResource *rsrc, guint32 implementation)
4354 {
4355         MonoDynamicTable *table;
4356         guint32 *values;
4357
4358         table = &assembly->tables [MONO_TABLE_MANIFESTRESOURCE];
4359         table->rows++;
4360         alloc_table (table, table->rows);
4361         values = table->values + table->next_idx * MONO_MANIFEST_SIZE;
4362         values [MONO_MANIFEST_OFFSET] = rsrc->offset;
4363         values [MONO_MANIFEST_FLAGS] = rsrc->attrs;
4364         values [MONO_MANIFEST_NAME] = string_heap_insert_mstring (&assembly->sheap, rsrc->name);
4365         values [MONO_MANIFEST_IMPLEMENTATION] = implementation;
4366         table->next_idx++;
4367 }
4368
4369 static void
4370 assembly_add_resource (MonoReflectionModuleBuilder *mb, MonoDynamicImage *assembly, MonoReflectionResource *rsrc)
4371 {
4372         MonoDynamicTable *table;
4373         guint32 *values;
4374         char blob_size [6];
4375         guchar hash [20];
4376         char *b = blob_size;
4377         char *name, *sname;
4378         guint32 idx, offset;
4379
4380         if (rsrc->filename) {
4381                 name = mono_string_to_utf8 (rsrc->filename);
4382                 sname = g_path_get_basename (name);
4383         
4384                 table = &assembly->tables [MONO_TABLE_FILE];
4385                 table->rows++;
4386                 alloc_table (table, table->rows);
4387                 values = table->values + table->next_idx * MONO_FILE_SIZE;
4388                 values [MONO_FILE_FLAGS] = FILE_CONTAINS_NO_METADATA;
4389                 values [MONO_FILE_NAME] = string_heap_insert (&assembly->sheap, sname);
4390                 g_free (sname);
4391
4392                 mono_sha1_get_digest_from_file (name, hash);
4393                 mono_metadata_encode_value (20, b, &b);
4394                 values [MONO_FILE_HASH_VALUE] = mono_image_add_stream_data (&assembly->blob, blob_size, b-blob_size);
4395                 mono_image_add_stream_data (&assembly->blob, (char*)hash, 20);
4396                 g_free (name);
4397                 idx = table->next_idx++;
4398                 rsrc->offset = 0;
4399                 idx = MONO_IMPLEMENTATION_FILE | (idx << MONO_IMPLEMENTATION_BITS);
4400         } else {
4401                 char sizebuf [4];
4402                 char *data;
4403                 guint len;
4404                 if (rsrc->data) {
4405                         data = mono_array_addr (rsrc->data, char, 0);
4406                         len = mono_array_length (rsrc->data);
4407                 } else {
4408                         data = NULL;
4409                         len = 0;
4410                 }
4411                 offset = len;
4412                 sizebuf [0] = offset; sizebuf [1] = offset >> 8;
4413                 sizebuf [2] = offset >> 16; sizebuf [3] = offset >> 24;
4414                 rsrc->offset = mono_image_add_stream_data (&assembly->resources, sizebuf, 4);
4415                 mono_image_add_stream_data (&assembly->resources, data, len);
4416
4417                 if (!mb->is_main)
4418                         /* 
4419                          * The entry should be emitted into the MANIFESTRESOURCE table of 
4420                          * the main module, but that needs to reference the FILE table
4421                          * which isn't emitted yet.
4422                          */
4423                         return;
4424                 else
4425                         idx = 0;
4426         }
4427
4428         assembly_add_resource_manifest (mb, assembly, rsrc, idx);
4429 }
4430
4431 static void
4432 set_version_from_string (MonoString *version, guint32 *values)
4433 {
4434         gchar *ver, *p, *str;
4435         guint32 i;
4436         
4437         values [MONO_ASSEMBLY_MAJOR_VERSION] = 0;
4438         values [MONO_ASSEMBLY_MINOR_VERSION] = 0;
4439         values [MONO_ASSEMBLY_REV_NUMBER] = 0;
4440         values [MONO_ASSEMBLY_BUILD_NUMBER] = 0;
4441         if (!version)
4442                 return;
4443         ver = str = mono_string_to_utf8 (version);
4444         for (i = 0; i < 4; ++i) {
4445                 values [MONO_ASSEMBLY_MAJOR_VERSION + i] = strtol (ver, &p, 10);
4446                 switch (*p) {
4447                 case '.':
4448                         p++;
4449                         break;
4450                 case '*':
4451                         /* handle Revision and Build */
4452                         p++;
4453                         break;
4454                 }
4455                 ver = p;
4456         }
4457         g_free (str);
4458 }
4459
4460 static guint32
4461 load_public_key (MonoArray *pkey, MonoDynamicImage *assembly) {
4462         gsize len;
4463         guint32 token = 0;
4464         char blob_size [6];
4465         char *b = blob_size;
4466
4467         if (!pkey)
4468                 return token;
4469
4470         len = mono_array_length (pkey);
4471         mono_metadata_encode_value (len, b, &b);
4472         token = mono_image_add_stream_data (&assembly->blob, blob_size, b - blob_size);
4473         mono_image_add_stream_data (&assembly->blob, mono_array_addr (pkey, char, 0), len);
4474
4475         assembly->public_key = g_malloc (len);
4476         memcpy (assembly->public_key, mono_array_addr (pkey, char, 0), len);
4477         assembly->public_key_len = len;
4478
4479         /* Special case: check for ECMA key (16 bytes) */
4480         if ((len == MONO_ECMA_KEY_LENGTH) && mono_is_ecma_key (mono_array_addr (pkey, char, 0), len)) {
4481                 /* In this case we must reserve 128 bytes (1024 bits) for the signature */
4482                 assembly->strong_name_size = MONO_DEFAULT_PUBLIC_KEY_LENGTH;
4483         } else if (len >= MONO_PUBLIC_KEY_HEADER_LENGTH + MONO_MINIMUM_PUBLIC_KEY_LENGTH) {
4484                 /* minimum key size (in 2.0) is 384 bits */
4485                 assembly->strong_name_size = len - MONO_PUBLIC_KEY_HEADER_LENGTH;
4486         } else {
4487                 /* FIXME - verifier */
4488                 g_warning ("Invalid public key length: %d bits (total: %d)", (int)MONO_PUBLIC_KEY_BIT_SIZE (len), (int)len);
4489                 assembly->strong_name_size = MONO_DEFAULT_PUBLIC_KEY_LENGTH; /* to be safe */
4490         }
4491         assembly->strong_name = g_malloc0 (assembly->strong_name_size);
4492
4493         return token;
4494 }
4495
4496 static void
4497 mono_image_emit_manifest (MonoReflectionModuleBuilder *moduleb)
4498 {
4499         MonoDynamicTable *table;
4500         MonoDynamicImage *assembly;
4501         MonoReflectionAssemblyBuilder *assemblyb;
4502         MonoDomain *domain;
4503         guint32 *values;
4504         int i;
4505         guint32 module_index;
4506
4507         assemblyb = moduleb->assemblyb;
4508         assembly = moduleb->dynamic_image;
4509         domain = mono_object_domain (assemblyb);
4510
4511         /* Emit ASSEMBLY table */
4512         table = &assembly->tables [MONO_TABLE_ASSEMBLY];
4513         alloc_table (table, 1);
4514         values = table->values + MONO_ASSEMBLY_SIZE;
4515         values [MONO_ASSEMBLY_HASH_ALG] = assemblyb->algid? assemblyb->algid: ASSEMBLY_HASH_SHA1;
4516         values [MONO_ASSEMBLY_NAME] = string_heap_insert_mstring (&assembly->sheap, assemblyb->name);
4517         if (assemblyb->culture) {
4518                 values [MONO_ASSEMBLY_CULTURE] = string_heap_insert_mstring (&assembly->sheap, assemblyb->culture);
4519         } else {
4520                 values [MONO_ASSEMBLY_CULTURE] = string_heap_insert (&assembly->sheap, "");
4521         }
4522         values [MONO_ASSEMBLY_PUBLIC_KEY] = load_public_key (assemblyb->public_key, assembly);
4523         values [MONO_ASSEMBLY_FLAGS] = assemblyb->flags;
4524         set_version_from_string (assemblyb->version, values);
4525
4526         /* Emit FILE + EXPORTED_TYPE table */
4527         module_index = 0;
4528         for (i = 0; i < mono_array_length (assemblyb->modules); ++i) {
4529                 int j;
4530                 MonoReflectionModuleBuilder *file_module = 
4531                         mono_array_get (assemblyb->modules, MonoReflectionModuleBuilder*, i);
4532                 if (file_module != moduleb) {
4533                         mono_image_fill_file_table (domain, (MonoReflectionModule*)file_module, assembly);
4534                         module_index ++;
4535                         if (file_module->types) {
4536                                 for (j = 0; j < file_module->num_types; ++j) {
4537                                         MonoReflectionTypeBuilder *tb = mono_array_get (file_module->types, MonoReflectionTypeBuilder*, j);
4538                                         mono_image_fill_export_table (domain, tb, module_index, 0, assembly);
4539                                 }
4540                         }
4541                 }
4542         }
4543         if (assemblyb->loaded_modules) {
4544                 for (i = 0; i < mono_array_length (assemblyb->loaded_modules); ++i) {
4545                         MonoReflectionModule *file_module = 
4546                                 mono_array_get (assemblyb->loaded_modules, MonoReflectionModule*, i);
4547                         mono_image_fill_file_table (domain, file_module, assembly);
4548                         module_index ++;
4549                         mono_image_fill_export_table_from_module (domain, file_module, module_index, assembly);
4550                 }
4551         }
4552         if (assemblyb->type_forwarders)
4553                 mono_image_fill_export_table_from_type_forwarders (assemblyb, assembly);
4554
4555         /* Emit MANIFESTRESOURCE table */
4556         module_index = 0;
4557         for (i = 0; i < mono_array_length (assemblyb->modules); ++i) {
4558                 int j;
4559                 MonoReflectionModuleBuilder *file_module = 
4560                         mono_array_get (assemblyb->modules, MonoReflectionModuleBuilder*, i);
4561                 /* The table for the main module is emitted later */
4562                 if (file_module != moduleb) {
4563                         module_index ++;
4564                         if (file_module->resources) {
4565                                 int len = mono_array_length (file_module->resources);
4566                                 for (j = 0; j < len; ++j) {
4567                                         MonoReflectionResource* res = (MonoReflectionResource*)mono_array_addr (file_module->resources, MonoReflectionResource, j);
4568                                         assembly_add_resource_manifest (file_module, assembly, res, MONO_IMPLEMENTATION_FILE | (module_index << MONO_IMPLEMENTATION_BITS));
4569                                 }
4570                         }
4571                 }
4572         }               
4573 }
4574
4575 #ifndef DISABLE_REFLECTION_EMIT_SAVE
4576
4577 /*
4578  * mono_image_build_metadata() will fill the info in all the needed metadata tables
4579  * for the modulebuilder @moduleb.
4580  * At the end of the process, method and field tokens are fixed up and the 
4581  * on-disk compressed metadata representation is created.
4582  */
4583 void
4584 mono_image_build_metadata (MonoReflectionModuleBuilder *moduleb)
4585 {
4586         MonoDynamicTable *table;
4587         MonoDynamicImage *assembly;
4588         MonoReflectionAssemblyBuilder *assemblyb;
4589         MonoDomain *domain;
4590         MonoPtrArray types;
4591         guint32 *values;
4592         int i, j;
4593
4594         assemblyb = moduleb->assemblyb;
4595         assembly = moduleb->dynamic_image;
4596         domain = mono_object_domain (assemblyb);
4597
4598         if (assembly->text_rva)
4599                 return;
4600
4601         assembly->text_rva = START_TEXT_RVA;
4602
4603         if (moduleb->is_main) {
4604                 mono_image_emit_manifest (moduleb);
4605         }
4606
4607         table = &assembly->tables [MONO_TABLE_TYPEDEF];
4608         table->rows = 1; /* .<Module> */
4609         table->next_idx++;
4610         alloc_table (table, table->rows);
4611         /*
4612          * Set the first entry.
4613          */
4614         values = table->values + table->columns;
4615         values [MONO_TYPEDEF_FLAGS] = 0;
4616         values [MONO_TYPEDEF_NAME] = string_heap_insert (&assembly->sheap, "<Module>") ;
4617         values [MONO_TYPEDEF_NAMESPACE] = string_heap_insert (&assembly->sheap, "") ;
4618         values [MONO_TYPEDEF_EXTENDS] = 0;
4619         values [MONO_TYPEDEF_FIELD_LIST] = 1;
4620         values [MONO_TYPEDEF_METHOD_LIST] = 1;
4621
4622         /* 
4623          * handle global methods 
4624          * FIXME: test what to do when global methods are defined in multiple modules.
4625          */
4626         if (moduleb->global_methods) {
4627                 table = &assembly->tables [MONO_TABLE_METHOD];
4628                 table->rows += mono_array_length (moduleb->global_methods);
4629                 alloc_table (table, table->rows);
4630                 for (i = 0; i < mono_array_length (moduleb->global_methods); ++i)
4631                         mono_image_get_method_info (
4632                                 mono_array_get (moduleb->global_methods, MonoReflectionMethodBuilder*, i), assembly);
4633         }
4634         if (moduleb->global_fields) {
4635                 table = &assembly->tables [MONO_TABLE_FIELD];
4636                 table->rows += mono_array_length (moduleb->global_fields);
4637                 alloc_table (table, table->rows);
4638                 for (i = 0; i < mono_array_length (moduleb->global_fields); ++i)
4639                         mono_image_get_field_info (
4640                                 mono_array_get (moduleb->global_fields, MonoReflectionFieldBuilder*, i), assembly);
4641         }
4642
4643         table = &assembly->tables [MONO_TABLE_MODULE];
4644         alloc_table (table, 1);
4645         mono_image_fill_module_table (domain, moduleb, assembly);
4646
4647         /* Collect all types into a list sorted by their table_idx */
4648         mono_ptr_array_init (types, moduleb->num_types);
4649
4650         if (moduleb->types)
4651                 for (i = 0; i < moduleb->num_types; ++i) {
4652                         MonoReflectionTypeBuilder *type = mono_array_get (moduleb->types, MonoReflectionTypeBuilder*, i);
4653                         collect_types (&types, type);
4654                 }
4655
4656         mono_ptr_array_sort (types, (gpointer)compare_types_by_table_idx);
4657         table = &assembly->tables [MONO_TABLE_TYPEDEF];
4658         table->rows += mono_ptr_array_size (types);
4659         alloc_table (table, table->rows);
4660
4661         /*
4662          * Emit type names + namespaces at one place inside the string heap,
4663          * so load_class_names () needs to touch fewer pages.
4664          */
4665         for (i = 0; i < mono_ptr_array_size (types); ++i) {
4666                 MonoReflectionTypeBuilder *tb = mono_ptr_array_get (types, i);
4667                 string_heap_insert_mstring (&assembly->sheap, tb->nspace);
4668         }
4669         for (i = 0; i < mono_ptr_array_size (types); ++i) {
4670                 MonoReflectionTypeBuilder *tb = mono_ptr_array_get (types, i);
4671                 string_heap_insert_mstring (&assembly->sheap, tb->name);
4672         }
4673
4674         for (i = 0; i < mono_ptr_array_size (types); ++i) {
4675                 MonoReflectionTypeBuilder *type = mono_ptr_array_get (types, i);
4676                 mono_image_get_type_info (domain, type, assembly);
4677         }
4678
4679         /* 
4680          * table->rows is already set above and in mono_image_fill_module_table.
4681          */
4682         /* add all the custom attributes at the end, once all the indexes are stable */
4683         mono_image_add_cattrs (assembly, 1, MONO_CUSTOM_ATTR_ASSEMBLY, assemblyb->cattrs);
4684
4685         /* CAS assembly permissions */
4686         if (assemblyb->permissions_minimum)
4687                 mono_image_add_decl_security (assembly, mono_metadata_make_token (MONO_TABLE_ASSEMBLY, 1), assemblyb->permissions_minimum);
4688         if (assemblyb->permissions_optional)
4689                 mono_image_add_decl_security (assembly, mono_metadata_make_token (MONO_TABLE_ASSEMBLY, 1), assemblyb->permissions_optional);
4690         if (assemblyb->permissions_refused)
4691                 mono_image_add_decl_security (assembly, mono_metadata_make_token (MONO_TABLE_ASSEMBLY, 1), assemblyb->permissions_refused);
4692
4693         module_add_cattrs (assembly, moduleb);
4694
4695         /* fixup tokens */
4696         mono_g_hash_table_foreach (assembly->token_fixups, (GHFunc)fixup_method, assembly);
4697
4698         /* Create the MethodImpl table.  We do this after emitting all methods so we already know
4699          * the final tokens and don't need another fixup pass. */
4700
4701         if (moduleb->global_methods) {
4702                 for (i = 0; i < mono_array_length (moduleb->global_methods); ++i) {
4703                         MonoReflectionMethodBuilder *mb = mono_array_get (
4704                                 moduleb->global_methods, MonoReflectionMethodBuilder*, i);
4705                         mono_image_add_methodimpl (assembly, mb);
4706                 }
4707         }
4708
4709         for (i = 0; i < mono_ptr_array_size (types); ++i) {
4710                 MonoReflectionTypeBuilder *type = mono_ptr_array_get (types, i);
4711                 if (type->methods) {
4712                         for (j = 0; j < type->num_methods; ++j) {
4713                                 MonoReflectionMethodBuilder *mb = mono_array_get (
4714                                         type->methods, MonoReflectionMethodBuilder*, j);
4715
4716                                 mono_image_add_methodimpl (assembly, mb);
4717                         }
4718                 }
4719         }
4720
4721         mono_ptr_array_destroy (types);
4722
4723         fixup_cattrs (assembly);
4724 }
4725
4726 #else /* DISABLE_REFLECTION_EMIT_SAVE */
4727
4728 void
4729 mono_image_build_metadata (MonoReflectionModuleBuilder *moduleb)
4730 {
4731         g_error ("This mono runtime was configured with --enable-minimal=reflection_emit_save, so saving of dynamic assemblies is not supported.");
4732 }
4733
4734 #endif /* DISABLE_REFLECTION_EMIT_SAVE */
4735
4736
4737 typedef struct {
4738         guint32 import_lookup_table;
4739         guint32 timestamp;
4740         guint32 forwarder;
4741         guint32 name_rva;
4742         guint32 import_address_table_rva;
4743 } MonoIDT;
4744
4745 typedef struct {
4746         guint32 name_rva;
4747         guint32 flags;
4748 } MonoILT;
4749
4750 #ifndef DISABLE_REFLECTION_EMIT
4751
4752 /*
4753  * mono_image_insert_string:
4754  * @module: module builder object
4755  * @str: a string
4756  *
4757  * Insert @str into the user string stream of @module.
4758  */
4759 guint32
4760 mono_image_insert_string (MonoReflectionModuleBuilder *module, MonoString *str)
4761 {
4762         MonoDynamicImage *assembly;
4763         guint32 idx;
4764         char buf [16];
4765         char *b = buf;
4766         
4767         MONO_ARCH_SAVE_REGS;
4768
4769         if (!module->dynamic_image)
4770                 mono_image_module_basic_init (module);
4771
4772         assembly = module->dynamic_image;
4773         
4774         if (assembly->save) {
4775                 mono_metadata_encode_value (1 | (str->length * 2), b, &b);
4776                 idx = mono_image_add_stream_data (&assembly->us, buf, b-buf);
4777 #if G_BYTE_ORDER != G_LITTLE_ENDIAN
4778         {
4779                 char *swapped = g_malloc (2 * mono_string_length (str));
4780                 const char *p = (const char*)mono_string_chars (str);
4781
4782                 swap_with_size (swapped, p, 2, mono_string_length (str));
4783                 mono_image_add_stream_data (&assembly->us, swapped, str->length * 2);
4784                 g_free (swapped);
4785         }
4786 #else
4787                 mono_image_add_stream_data (&assembly->us, (const char*)mono_string_chars (str), str->length * 2);
4788 #endif
4789                 mono_image_add_stream_data (&assembly->us, "", 1);
4790         } else {
4791                 idx = assembly->us.index ++;
4792         }
4793
4794         mono_g_hash_table_insert (assembly->tokens, GUINT_TO_POINTER (MONO_TOKEN_STRING | idx), str);
4795
4796         return MONO_TOKEN_STRING | idx;
4797 }
4798
4799 guint32
4800 mono_image_create_method_token (MonoDynamicImage *assembly, MonoObject *obj, MonoArray *opt_param_types)
4801 {
4802         MonoClass *klass;
4803         guint32 token = 0;
4804         MonoMethodSignature *sig;
4805
4806         klass = obj->vtable->klass;
4807         if (strcmp (klass->name, "MonoMethod") == 0 || strcmp (klass->name, "MonoCMethod") == 0) {
4808                 MonoMethod *method = ((MonoReflectionMethod *)obj)->method;
4809                 MonoMethodSignature *old;
4810                 guint32 sig_token, parent;
4811                 int nargs, i;
4812
4813                 g_assert (opt_param_types && (mono_method_signature (method)->sentinelpos >= 0));
4814
4815                 nargs = mono_array_length (opt_param_types);
4816                 old = mono_method_signature (method);
4817                 sig = mono_metadata_signature_alloc ( &assembly->image, old->param_count + nargs);
4818
4819                 sig->hasthis = old->hasthis;
4820                 sig->explicit_this = old->explicit_this;
4821                 sig->call_convention = old->call_convention;
4822                 sig->generic_param_count = old->generic_param_count;
4823                 sig->param_count = old->param_count + nargs;
4824                 sig->sentinelpos = old->param_count;
4825                 sig->ret = old->ret;
4826
4827                 for (i = 0; i < old->param_count; i++)
4828                         sig->params [i] = old->params [i];
4829
4830                 for (i = 0; i < nargs; i++) {
4831                         MonoReflectionType *rt = mono_array_get (opt_param_types, MonoReflectionType *, i);
4832                         sig->params [old->param_count + i] = mono_reflection_type_get_handle (rt);
4833                 }
4834
4835                 parent = mono_image_typedef_or_ref (assembly, &method->klass->byval_arg);
4836                 g_assert ((parent & MONO_TYPEDEFORREF_MASK) == MONO_MEMBERREF_PARENT_TYPEREF);
4837                 parent >>= MONO_TYPEDEFORREF_BITS;
4838
4839                 parent <<= MONO_MEMBERREF_PARENT_BITS;
4840                 parent |= MONO_MEMBERREF_PARENT_TYPEREF;
4841
4842                 sig_token = method_encode_signature (assembly, sig);
4843                 token = mono_image_get_varargs_method_token (assembly, parent, method->name, sig_token);
4844         } else if (strcmp (klass->name, "MethodBuilder") == 0) {
4845                 MonoReflectionMethodBuilder *mb = (MonoReflectionMethodBuilder *)obj;
4846                 ReflectionMethodBuilder rmb;
4847                 guint32 parent, sig_token;
4848                 int nopt_args, nparams, ngparams, i;
4849                 char *name;
4850
4851                 reflection_methodbuilder_from_method_builder (&rmb, mb);
4852                 rmb.opt_types = opt_param_types;
4853                 nopt_args = mono_array_length (opt_param_types);
4854
4855                 nparams = rmb.parameters ? mono_array_length (rmb.parameters): 0;
4856                 ngparams = rmb.generic_params ? mono_array_length (rmb.generic_params): 0;
4857                 sig = mono_metadata_signature_alloc (&assembly->image, nparams + nopt_args);
4858
4859                 sig->hasthis = !(rmb.attrs & METHOD_ATTRIBUTE_STATIC);
4860                 sig->explicit_this = (rmb.call_conv & 0x40) == 0x40;
4861                 sig->call_convention = rmb.call_conv;
4862                 sig->generic_param_count = ngparams;
4863                 sig->param_count = nparams + nopt_args;
4864                 sig->sentinelpos = nparams;
4865                 sig->ret = mono_reflection_type_get_handle (rmb.rtype);
4866
4867                 for (i = 0; i < nparams; i++) {
4868                         MonoReflectionType *rt = mono_array_get (rmb.parameters, MonoReflectionType *, i);
4869                         sig->params [i] = mono_reflection_type_get_handle (rt);
4870                 }
4871
4872                 for (i = 0; i < nopt_args; i++) {
4873                         MonoReflectionType *rt = mono_array_get (opt_param_types, MonoReflectionType *, i);
4874                         sig->params [nparams + i] = mono_reflection_type_get_handle (rt);
4875                 }
4876
4877                 sig_token = method_builder_encode_signature (assembly, &rmb);
4878
4879                 parent = mono_image_create_token (assembly, obj, TRUE, TRUE);
4880                 g_assert (mono_metadata_token_table (parent) == MONO_TABLE_METHOD);
4881
4882                 parent = mono_metadata_token_index (parent) << MONO_MEMBERREF_PARENT_BITS;
4883                 parent |= MONO_MEMBERREF_PARENT_METHODDEF;
4884
4885                 name = mono_string_to_utf8 (rmb.name);
4886                 token = mono_image_get_varargs_method_token (
4887                         assembly, parent, name, sig_token);
4888                 g_free (name);
4889         } else {
4890                 g_error ("requested method token for %s\n", klass->name);
4891         }
4892
4893         g_hash_table_insert (assembly->vararg_aux_hash, GUINT_TO_POINTER (token), sig);
4894         mono_g_hash_table_insert (assembly->tokens, GUINT_TO_POINTER (token), obj);
4895         return token;
4896 }
4897
4898 /*
4899  * mono_image_create_token:
4900  * @assembly: a dynamic assembly
4901  * @obj:
4902  * @register_token: Whenever to register the token in the assembly->tokens hash. 
4903  *
4904  * Get a token to insert in the IL code stream for the given MemberInfo.
4905  * The metadata emission routines need to pass FALSE as REGISTER_TOKEN, since by that time, 
4906  * the table_idx-es were recomputed, so registering the token would overwrite an existing 
4907  * entry.
4908  */
4909 guint32
4910 mono_image_create_token (MonoDynamicImage *assembly, MonoObject *obj, 
4911                                                  gboolean create_open_instance, gboolean register_token)
4912 {
4913         MonoClass *klass;
4914         guint32 token = 0;
4915
4916         klass = obj->vtable->klass;
4917
4918         /* Check for user defined reflection objects */
4919         /* TypeDelegator is the only corlib type which doesn't look like a MonoReflectionType */
4920         if (klass->image != mono_defaults.corlib || (strcmp (klass->name, "TypeDelegator") == 0))
4921                 mono_raise_exception (mono_get_exception_not_supported ("User defined subclasses of System.Type are not yet supported")); \
4922
4923         if (strcmp (klass->name, "MethodBuilder") == 0) {
4924                 MonoReflectionMethodBuilder *mb = (MonoReflectionMethodBuilder *)obj;
4925                 MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder*)mb->type;
4926
4927                 if (tb->module->dynamic_image == assembly && !tb->generic_params && !mb->generic_params)
4928                         token = mb->table_idx | MONO_TOKEN_METHOD_DEF;
4929                 else
4930                         token = mono_image_get_methodbuilder_token (assembly, mb, create_open_instance);
4931                 /*g_print ("got token 0x%08x for %s\n", token, mono_string_to_utf8 (mb->name));*/
4932         } else if (strcmp (klass->name, "ConstructorBuilder") == 0) {
4933                 MonoReflectionCtorBuilder *mb = (MonoReflectionCtorBuilder *)obj;
4934                 MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder*)mb->type;
4935
4936                 if (tb->module->dynamic_image == assembly && !tb->generic_params)
4937                         token = mb->table_idx | MONO_TOKEN_METHOD_DEF;
4938                 else
4939                         token = mono_image_get_ctorbuilder_token (assembly, mb);
4940                 /*g_print ("got token 0x%08x for %s\n", token, mono_string_to_utf8 (mb->name));*/
4941         } else if (strcmp (klass->name, "FieldBuilder") == 0) {
4942                 MonoReflectionFieldBuilder *fb = (MonoReflectionFieldBuilder *)obj;
4943                 MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder *)fb->typeb;
4944                 if (tb->generic_params) {
4945                         token = mono_image_get_generic_field_token (assembly, fb);
4946                 } else {
4947                         if (tb->module->dynamic_image == assembly) {
4948                                 token = fb->table_idx | MONO_TOKEN_FIELD_DEF;
4949                         } else {
4950                                 token = mono_image_get_fieldref_token (assembly, (MonoObject*)fb, fb->handle);
4951                         }
4952                 }
4953         } else if (strcmp (klass->name, "TypeBuilder") == 0) {
4954                 MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder *)obj;
4955                 if (create_open_instance && tb->generic_params) {
4956                         MonoType *type;
4957                         init_type_builder_generics (obj);
4958                         type = mono_reflection_type_get_handle ((MonoReflectionType *)obj);
4959                         token = mono_image_typedef_or_ref_full (assembly, type, TRUE);
4960                         token = mono_metadata_token_from_dor (token);
4961                 } else if (tb->module->dynamic_image == assembly) {
4962                         token = tb->table_idx | MONO_TOKEN_TYPE_DEF;
4963                 } else {
4964                         MonoType *type;
4965                         type = mono_reflection_type_get_handle ((MonoReflectionType *)obj);
4966                         token = mono_metadata_token_from_dor (mono_image_typedef_or_ref (assembly, type));
4967                 }
4968         } else if (strcmp (klass->name, "MonoType") == 0) {
4969                 MonoType *type = mono_reflection_type_get_handle ((MonoReflectionType *)obj);
4970                 MonoClass *mc = mono_class_from_mono_type (type);
4971                 token = mono_metadata_token_from_dor (
4972                         mono_image_typedef_or_ref_full (assembly, type, mc->generic_container == NULL || create_open_instance));
4973         } else if (strcmp (klass->name, "GenericTypeParameterBuilder") == 0) {
4974                 MonoType *type = mono_reflection_type_get_handle ((MonoReflectionType *)obj);
4975                 token = mono_metadata_token_from_dor (
4976                         mono_image_typedef_or_ref (assembly, type));
4977         } else if (strcmp (klass->name, "MonoGenericClass") == 0) {
4978                 MonoType *type = mono_reflection_type_get_handle ((MonoReflectionType *)obj);
4979                 token = mono_metadata_token_from_dor (
4980                         mono_image_typedef_or_ref (assembly, type));
4981         } else if (strcmp (klass->name, "MonoCMethod") == 0 ||
4982                    strcmp (klass->name, "MonoMethod") == 0 ||
4983                    strcmp (klass->name, "MonoGenericMethod") == 0 ||
4984                    strcmp (klass->name, "MonoGenericCMethod") == 0) {
4985                 MonoReflectionMethod *m = (MonoReflectionMethod *)obj;
4986                 if (m->method->is_inflated) {
4987                         if (create_open_instance)
4988                                 token = mono_image_get_methodspec_token (assembly, m->method);
4989                         else
4990                                 token = mono_image_get_inflated_method_token (assembly, m->method);
4991                 } else if ((m->method->klass->image == &assembly->image) &&
4992                          !m->method->klass->generic_class) {
4993                         static guint32 method_table_idx = 0xffffff;
4994                         if (m->method->klass->wastypebuilder) {
4995                                 /* we use the same token as the one that was assigned
4996                                  * to the Methodbuilder.
4997                                  * FIXME: do the equivalent for Fields.
4998                                  */
4999                                 token = m->method->token;
5000                         } else {
5001                                 /*
5002                                  * Each token should have a unique index, but the indexes are
5003                                  * assigned by managed code, so we don't know about them. An
5004                                  * easy solution is to count backwards...
5005                                  */
5006                                 method_table_idx --;
5007                                 token = MONO_TOKEN_METHOD_DEF | method_table_idx;
5008                         }
5009                 } else {
5010                         token = mono_image_get_methodref_token (assembly, m->method, create_open_instance);
5011                 }
5012                 /*g_print ("got token 0x%08x for %s\n", token, m->method->name);*/
5013         } else if (strcmp (klass->name, "MonoField") == 0) {
5014                 MonoReflectionField *f = (MonoReflectionField *)obj;
5015                 if ((f->field->parent->image == &assembly->image) && !is_field_on_inst (f->field)) {
5016                         static guint32 field_table_idx = 0xffffff;
5017                         field_table_idx --;
5018                         token = MONO_TOKEN_FIELD_DEF | field_table_idx;
5019                 } else {
5020                         token = mono_image_get_fieldref_token (assembly, (MonoObject*)f, f->field);
5021                 }
5022                 /*g_print ("got token 0x%08x for %s\n", token, f->field->name);*/
5023         } else if (strcmp (klass->name, "MonoArrayMethod") == 0) {
5024                 MonoReflectionArrayMethod *m = (MonoReflectionArrayMethod *)obj;
5025                 token = mono_image_get_array_token (assembly, m);
5026         } else if (strcmp (klass->name, "SignatureHelper") == 0) {
5027                 MonoReflectionSigHelper *s = (MonoReflectionSigHelper*)obj;
5028                 token = MONO_TOKEN_SIGNATURE | mono_image_get_sighelper_token (assembly, s);
5029         } else if (strcmp (klass->name, "EnumBuilder") == 0) {
5030                 MonoType *type = mono_reflection_type_get_handle ((MonoReflectionType *)obj);
5031                 token = mono_metadata_token_from_dor (
5032                         mono_image_typedef_or_ref (assembly, type));
5033         } else if (strcmp (klass->name, "FieldOnTypeBuilderInst") == 0) {
5034                 MonoReflectionFieldOnTypeBuilderInst *f = (MonoReflectionFieldOnTypeBuilderInst*)obj;
5035                 token = mono_image_get_field_on_inst_token (assembly, f);
5036         } else if (strcmp (klass->name, "ConstructorOnTypeBuilderInst") == 0) {
5037                 MonoReflectionCtorOnTypeBuilderInst *c = (MonoReflectionCtorOnTypeBuilderInst*)obj;
5038                 token = mono_image_get_ctor_on_inst_token (assembly, c, create_open_instance);
5039         } else if (strcmp (klass->name, "MethodOnTypeBuilderInst") == 0) {
5040                 MonoReflectionMethodOnTypeBuilderInst *m = (MonoReflectionMethodOnTypeBuilderInst*)obj;
5041                 token = mono_image_get_method_on_inst_token (assembly, m, create_open_instance);
5042         } else if (is_sre_array (klass) || is_sre_byref (klass) || is_sre_pointer (klass)) {
5043                 MonoReflectionType *type = (MonoReflectionType *)obj;
5044                 token = mono_metadata_token_from_dor (
5045                                 mono_image_typedef_or_ref (assembly, mono_reflection_type_get_handle (type)));
5046         } else {
5047                 g_error ("requested token for %s\n", klass->name);
5048         }
5049
5050         if (register_token)
5051                 mono_image_register_token (assembly, token, obj);
5052
5053         return token;
5054 }
5055
5056 /*
5057  * mono_image_register_token:
5058  *
5059  *   Register the TOKEN->OBJ mapping in the mapping table in ASSEMBLY. This is required for
5060  * the Module.ResolveXXXToken () methods to work.
5061  */
5062 void
5063 mono_image_register_token (MonoDynamicImage *assembly, guint32 token, MonoObject *obj)
5064 {
5065         MonoObject *prev = mono_g_hash_table_lookup (assembly->tokens, GUINT_TO_POINTER (token));
5066         if (prev) {
5067                 /* There could be multiple MethodInfo objects with the same token */
5068                 //g_assert (prev == obj);
5069         } else {
5070                 mono_g_hash_table_insert (assembly->tokens, GUINT_TO_POINTER (token), obj);
5071         }
5072 }
5073
5074 static MonoDynamicImage*
5075 create_dynamic_mono_image (MonoDynamicAssembly *assembly, char *assembly_name, char *module_name)
5076 {
5077         static const guchar entrycode [16] = {0xff, 0x25, 0};
5078         MonoDynamicImage *image;
5079         int i;
5080
5081         const char *version;
5082
5083         if (!strcmp (mono_get_runtime_info ()->framework_version, "2.1"))
5084                 version = "v2.0.50727"; /* HACK: SL 2 enforces the .net 2 metadata version */
5085         else
5086                 version = mono_get_runtime_info ()->runtime_version;
5087
5088 #if HAVE_BOEHM_GC
5089         /* The MonoGHashTable's need GC tracking */
5090         image = GC_MALLOC (sizeof (MonoDynamicImage));
5091 #else
5092         image = g_new0 (MonoDynamicImage, 1);
5093 #endif
5094
5095         mono_profiler_module_event (&image->image, MONO_PROFILE_START_LOAD);
5096         
5097         /*g_print ("created image %p\n", image);*/
5098         /* keep in sync with image.c */
5099         image->image.name = assembly_name;
5100         image->image.assembly_name = image->image.name; /* they may be different */
5101         image->image.module_name = module_name;
5102         image->image.version = g_strdup (version);
5103         image->image.md_version_major = 1;
5104         image->image.md_version_minor = 1;
5105         image->image.dynamic = TRUE;
5106
5107         image->image.references = g_new0 (MonoAssembly*, 1);
5108         image->image.references [0] = NULL;
5109
5110         mono_image_init (&image->image);
5111
5112         image->token_fixups = mono_g_hash_table_new_type ((GHashFunc)mono_object_hash, NULL, MONO_HASH_KEY_GC);
5113         image->method_to_table_idx = g_hash_table_new (NULL, NULL);
5114         image->field_to_table_idx = g_hash_table_new (NULL, NULL);
5115         image->method_aux_hash = g_hash_table_new (NULL, NULL);
5116         image->vararg_aux_hash = g_hash_table_new (NULL, NULL);
5117         image->handleref = g_hash_table_new (NULL, NULL);
5118         image->handleref_managed = mono_g_hash_table_new_type ((GHashFunc)mono_object_hash, NULL, MONO_HASH_KEY_GC);
5119         image->tokens = mono_g_hash_table_new_type (NULL, NULL, MONO_HASH_VALUE_GC);
5120         image->generic_def_objects = mono_g_hash_table_new_type (NULL, NULL, MONO_HASH_VALUE_GC);
5121         image->methodspec = mono_g_hash_table_new_type ((GHashFunc)mono_object_hash, NULL, MONO_HASH_KEY_GC);
5122         image->typespec = g_hash_table_new ((GHashFunc)mono_metadata_type_hash, (GCompareFunc)mono_metadata_type_equal);
5123         image->typeref = g_hash_table_new ((GHashFunc)mono_metadata_type_hash, (GCompareFunc)mono_metadata_type_equal);
5124         image->blob_cache = g_hash_table_new ((GHashFunc)mono_blob_entry_hash, (GCompareFunc)mono_blob_entry_equal);
5125         image->gen_params = g_ptr_array_new ();
5126         image->remapped_tokens = mono_g_hash_table_new_type (NULL, NULL, MONO_HASH_VALUE_GC);
5127
5128         /*g_print ("string heap create for image %p (%s)\n", image, module_name);*/
5129         string_heap_init (&image->sheap);
5130         mono_image_add_stream_data (&image->us, "", 1);
5131         add_to_blob_cached (image, (char*) "", 1, NULL, 0);
5132         /* import tables... */
5133         mono_image_add_stream_data (&image->code, (char*)entrycode, sizeof (entrycode));
5134         image->iat_offset = mono_image_add_stream_zero (&image->code, 8); /* two IAT entries */
5135         image->idt_offset = mono_image_add_stream_zero (&image->code, 2 * sizeof (MonoIDT)); /* two IDT entries */
5136         image->imp_names_offset = mono_image_add_stream_zero (&image->code, 2); /* flags for name entry */
5137         mono_image_add_stream_data (&image->code, "_CorExeMain", 12);
5138         mono_image_add_stream_data (&image->code, "mscoree.dll", 12);
5139         image->ilt_offset = mono_image_add_stream_zero (&image->code, 8); /* two ILT entries */
5140         stream_data_align (&image->code);
5141
5142         image->cli_header_offset = mono_image_add_stream_zero (&image->code, sizeof (MonoCLIHeader));
5143
5144         for (i=0; i < MONO_TABLE_NUM; ++i) {
5145                 image->tables [i].next_idx = 1;
5146                 image->tables [i].columns = table_sizes [i];
5147         }
5148
5149         image->image.assembly = (MonoAssembly*)assembly;
5150         image->run = assembly->run;
5151         image->save = assembly->save;
5152         image->pe_kind = 0x1; /* ILOnly */
5153         image->machine = 0x14c; /* I386 */
5154         
5155         mono_profiler_module_loaded (&image->image, MONO_PROFILE_OK);
5156
5157         return image;
5158 }
5159 #endif
5160
5161 static void
5162 free_blob_cache_entry (gpointer key, gpointer val, gpointer user_data)
5163 {
5164         g_free (key);
5165 }
5166
5167 static void
5168 release_hashtable (MonoGHashTable **hash)
5169 {
5170         if (*hash) {
5171                 mono_g_hash_table_destroy (*hash);
5172                 *hash = NULL;
5173         }
5174 }
5175
5176 void
5177 mono_dynamic_image_release_gc_roots (MonoDynamicImage *image)
5178 {
5179         release_hashtable (&image->token_fixups);
5180         release_hashtable (&image->handleref_managed);
5181         release_hashtable (&image->tokens);
5182         release_hashtable (&image->remapped_tokens);
5183         release_hashtable (&image->generic_def_objects);
5184         release_hashtable (&image->methodspec);
5185 }
5186
5187 void
5188 mono_dynamic_image_free (MonoDynamicImage *image)
5189 {
5190         MonoDynamicImage *di = image;
5191         GList *list;
5192         int i;
5193
5194         if (di->methodspec)
5195                 mono_g_hash_table_destroy (di->methodspec);
5196         if (di->typespec)
5197                 g_hash_table_destroy (di->typespec);
5198         if (di->typeref)
5199                 g_hash_table_destroy (di->typeref);
5200         if (di->handleref)
5201                 g_hash_table_destroy (di->handleref);
5202         if (di->handleref_managed)
5203                 mono_g_hash_table_destroy (di->handleref_managed);
5204         if (di->tokens)
5205                 mono_g_hash_table_destroy (di->tokens);
5206         if (di->remapped_tokens)
5207                 mono_g_hash_table_destroy (di->remapped_tokens);
5208         if (di->generic_def_objects)
5209                 mono_g_hash_table_destroy (di->generic_def_objects);
5210         if (di->blob_cache) {
5211                 g_hash_table_foreach (di->blob_cache, free_blob_cache_entry, NULL);
5212                 g_hash_table_destroy (di->blob_cache);
5213         }
5214         if (di->standalonesig_cache)
5215                 g_hash_table_destroy (di->standalonesig_cache);
5216         for (list = di->array_methods; list; list = list->next) {
5217                 ArrayMethod *am = (ArrayMethod *)list->data;
5218                 g_free (am->sig);
5219                 g_free (am->name);
5220                 g_free (am);
5221         }
5222         g_list_free (di->array_methods);
5223         if (di->gen_params) {
5224                 for (i = 0; i < di->gen_params->len; i++) {
5225                         GenericParamTableEntry *entry = g_ptr_array_index (di->gen_params, i);
5226                         mono_gc_deregister_root ((char*) &entry->gparam);
5227                         g_free (entry);
5228                 }
5229                 g_ptr_array_free (di->gen_params, TRUE);
5230         }
5231         if (di->token_fixups)
5232                 mono_g_hash_table_destroy (di->token_fixups);
5233         if (di->method_to_table_idx)
5234                 g_hash_table_destroy (di->method_to_table_idx);
5235         if (di->field_to_table_idx)
5236                 g_hash_table_destroy (di->field_to_table_idx);
5237         if (di->method_aux_hash)
5238                 g_hash_table_destroy (di->method_aux_hash);
5239         if (di->vararg_aux_hash)
5240                 g_hash_table_destroy (di->vararg_aux_hash);
5241         g_free (di->strong_name);
5242         g_free (di->win32_res);
5243         if (di->public_key)
5244                 g_free (di->public_key);
5245
5246         /*g_print ("string heap destroy for image %p\n", di);*/
5247         mono_dynamic_stream_reset (&di->sheap);
5248         mono_dynamic_stream_reset (&di->code);
5249         mono_dynamic_stream_reset (&di->resources);
5250         mono_dynamic_stream_reset (&di->us);
5251         mono_dynamic_stream_reset (&di->blob);
5252         mono_dynamic_stream_reset (&di->tstream);
5253         mono_dynamic_stream_reset (&di->guid);
5254         for (i = 0; i < MONO_TABLE_NUM; ++i) {
5255                 g_free (di->tables [i].values);
5256         }
5257 }       
5258
5259 void
5260 mono_dynamic_image_free_image (MonoDynamicImage *image)
5261 {
5262         /* See create_dynamic_mono_image () */
5263 #if HAVE_BOEHM_GC
5264         /* Allocated using GC_MALLOC */
5265 #else
5266         g_free (image);
5267 #endif
5268 }
5269
5270 #ifndef DISABLE_REFLECTION_EMIT
5271
5272 /*
5273  * mono_image_basic_init:
5274  * @assembly: an assembly builder object
5275  *
5276  * Create the MonoImage that represents the assembly builder and setup some
5277  * of the helper hash table and the basic metadata streams.
5278  */
5279 void
5280 mono_image_basic_init (MonoReflectionAssemblyBuilder *assemblyb)
5281 {
5282         MonoDynamicAssembly *assembly;
5283         MonoDynamicImage *image;
5284         MonoDomain *domain = mono_object_domain (assemblyb);
5285         
5286         MONO_ARCH_SAVE_REGS;
5287
5288         if (assemblyb->dynamic_assembly)
5289                 return;
5290
5291 #if HAVE_BOEHM_GC
5292         /* assembly->assembly.image might be GC allocated */
5293         assembly = assemblyb->dynamic_assembly = GC_MALLOC (sizeof (MonoDynamicAssembly));
5294 #else
5295         assembly = assemblyb->dynamic_assembly = g_new0 (MonoDynamicAssembly, 1);
5296 #endif
5297
5298         mono_profiler_assembly_event (&assembly->assembly, MONO_PROFILE_START_LOAD);
5299         
5300         assembly->assembly.ref_count = 1;
5301         assembly->assembly.dynamic = TRUE;
5302         assembly->assembly.corlib_internal = assemblyb->corlib_internal;
5303         assemblyb->assembly.assembly = (MonoAssembly*)assembly;
5304         assembly->assembly.basedir = mono_string_to_utf8 (assemblyb->dir);
5305         if (assemblyb->culture)
5306                 assembly->assembly.aname.culture = mono_string_to_utf8 (assemblyb->culture);
5307         else
5308                 assembly->assembly.aname.culture = g_strdup ("");
5309
5310         if (assemblyb->version) {
5311                         char *vstr = mono_string_to_utf8 (assemblyb->version);
5312                         char **version = g_strsplit (vstr, ".", 4);
5313                         char **parts = version;
5314                         assembly->assembly.aname.major = atoi (*parts++);
5315                         assembly->assembly.aname.minor = atoi (*parts++);
5316                         assembly->assembly.aname.build = *parts != NULL ? atoi (*parts++) : 0;
5317                         assembly->assembly.aname.revision = *parts != NULL ? atoi (*parts) : 0;
5318
5319                         g_strfreev (version);
5320                         g_free (vstr);
5321         } else {
5322                         assembly->assembly.aname.major = 0;
5323                         assembly->assembly.aname.minor = 0;
5324                         assembly->assembly.aname.build = 0;
5325                         assembly->assembly.aname.revision = 0;
5326         }
5327
5328         assembly->run = assemblyb->access != 2;
5329         assembly->save = assemblyb->access != 1;
5330         assembly->domain = domain;
5331
5332         image = create_dynamic_mono_image (assembly, mono_string_to_utf8 (assemblyb->name), g_strdup ("RefEmit_YouForgotToDefineAModule"));
5333         image->initial_image = TRUE;
5334         assembly->assembly.aname.name = image->image.name;
5335         assembly->assembly.image = &image->image;
5336         if (assemblyb->pktoken && assemblyb->pktoken->max_length) {
5337                 /* -1 to correct for the trailing NULL byte */
5338                 if (assemblyb->pktoken->max_length != MONO_PUBLIC_KEY_TOKEN_LENGTH - 1) {
5339                         g_error ("Public key token length invalid for assembly %s: %i", assembly->assembly.aname.name, assemblyb->pktoken->max_length);
5340                 }
5341                 memcpy (&assembly->assembly.aname.public_key_token, mono_array_addr (assemblyb->pktoken, guint8, 0), assemblyb->pktoken->max_length);           
5342         }
5343
5344         mono_domain_assemblies_lock (domain);
5345         domain->domain_assemblies = g_slist_append (domain->domain_assemblies, assembly);
5346         mono_domain_assemblies_unlock (domain);
5347
5348         register_assembly (mono_object_domain (assemblyb), &assemblyb->assembly, &assembly->assembly);
5349         
5350         mono_profiler_assembly_loaded (&assembly->assembly, MONO_PROFILE_OK);
5351         
5352         mono_assembly_invoke_load_hook ((MonoAssembly*)assembly);
5353 }
5354
5355 #endif /* !DISABLE_REFLECTION_EMIT */
5356
5357 #ifndef DISABLE_REFLECTION_EMIT_SAVE
5358
5359 static int
5360 calc_section_size (MonoDynamicImage *assembly)
5361 {
5362         int nsections = 0;
5363
5364         /* alignment constraints */
5365         mono_image_add_stream_zero (&assembly->code, 4 - (assembly->code.index % 4));
5366         g_assert ((assembly->code.index % 4) == 0);
5367         assembly->meta_size += 3;
5368         assembly->meta_size &= ~3;
5369         mono_image_add_stream_zero (&assembly->resources, 4 - (assembly->resources.index % 4));
5370         g_assert ((assembly->resources.index % 4) == 0);
5371
5372         assembly->sections [MONO_SECTION_TEXT].size = assembly->meta_size + assembly->code.index + assembly->resources.index + assembly->strong_name_size;
5373         assembly->sections [MONO_SECTION_TEXT].attrs = SECT_FLAGS_HAS_CODE | SECT_FLAGS_MEM_EXECUTE | SECT_FLAGS_MEM_READ;
5374         nsections++;
5375
5376         if (assembly->win32_res) {
5377                 guint32 res_size = (assembly->win32_res_size + 3) & ~3;
5378
5379                 assembly->sections [MONO_SECTION_RSRC].size = res_size;
5380                 assembly->sections [MONO_SECTION_RSRC].attrs = SECT_FLAGS_HAS_INITIALIZED_DATA | SECT_FLAGS_MEM_READ;
5381                 nsections++;
5382         }
5383
5384         assembly->sections [MONO_SECTION_RELOC].size = 12;
5385         assembly->sections [MONO_SECTION_RELOC].attrs = SECT_FLAGS_MEM_READ | SECT_FLAGS_MEM_DISCARDABLE | SECT_FLAGS_HAS_INITIALIZED_DATA;
5386         nsections++;
5387
5388         return nsections;
5389 }
5390
5391 typedef struct {
5392         guint32 id;
5393         guint32 offset;
5394         GSList *children;
5395         MonoReflectionWin32Resource *win32_res; /* Only for leaf nodes */
5396 } ResTreeNode;
5397
5398 static int
5399 resource_tree_compare_by_id (gconstpointer a, gconstpointer b)
5400 {
5401         ResTreeNode *t1 = (ResTreeNode*)a;
5402         ResTreeNode *t2 = (ResTreeNode*)b;
5403
5404         return t1->id - t2->id;
5405 }
5406
5407 /*
5408  * resource_tree_create:
5409  *
5410  *  Organize the resources into a resource tree.
5411  */
5412 static ResTreeNode *
5413 resource_tree_create (MonoArray *win32_resources)
5414 {
5415         ResTreeNode *tree, *res_node, *type_node, *lang_node;
5416         GSList *l;
5417         int i;
5418
5419         tree = g_new0 (ResTreeNode, 1);
5420         
5421         for (i = 0; i < mono_array_length (win32_resources); ++i) {
5422                 MonoReflectionWin32Resource *win32_res =
5423                         (MonoReflectionWin32Resource*)mono_array_addr (win32_resources, MonoReflectionWin32Resource, i);
5424
5425                 /* Create node */
5426
5427                 /* FIXME: BUG: this stores managed references in unmanaged memory */
5428                 lang_node = g_new0 (ResTreeNode, 1);
5429                 lang_node->id = win32_res->lang_id;
5430                 lang_node->win32_res = win32_res;
5431
5432                 /* Create type node if neccesary */
5433                 type_node = NULL;
5434                 for (l = tree->children; l; l = l->next)
5435                         if (((ResTreeNode*)(l->data))->id == win32_res->res_type) {
5436                                 type_node = (ResTreeNode*)l->data;
5437                                 break;
5438                         }
5439
5440                 if (!type_node) {
5441                         type_node = g_new0 (ResTreeNode, 1);
5442                         type_node->id = win32_res->res_type;
5443
5444                         /* 
5445                          * The resource types have to be sorted otherwise
5446                          * Windows Explorer can't display the version information.
5447                          */
5448                         tree->children = g_slist_insert_sorted (tree->children, 
5449                                 type_node, resource_tree_compare_by_id);
5450                 }
5451
5452                 /* Create res node if neccesary */
5453                 res_node = NULL;
5454                 for (l = type_node->children; l; l = l->next)
5455                         if (((ResTreeNode*)(l->data))->id == win32_res->res_id) {
5456                                 res_node = (ResTreeNode*)l->data;
5457                                 break;
5458                         }
5459
5460                 if (!res_node) {
5461                         res_node = g_new0 (ResTreeNode, 1);
5462                         res_node->id = win32_res->res_id;
5463                         type_node->children = g_slist_append (type_node->children, res_node);
5464                 }
5465
5466                 res_node->children = g_slist_append (res_node->children, lang_node);
5467         }
5468
5469         return tree;
5470 }
5471
5472 /*
5473  * resource_tree_encode:
5474  * 
5475  *   Encode the resource tree into the format used in the PE file.
5476  */
5477 static void
5478 resource_tree_encode (ResTreeNode *node, char *begin, char *p, char **endbuf)
5479 {
5480         char *entries;
5481         MonoPEResourceDir dir;
5482         MonoPEResourceDirEntry dir_entry;
5483         MonoPEResourceDataEntry data_entry;
5484         GSList *l;
5485         guint32 res_id_entries;
5486
5487         /*
5488          * For the format of the resource directory, see the article
5489          * "An In-Depth Look into the Win32 Portable Executable File Format" by
5490          * Matt Pietrek
5491          */
5492
5493         memset (&dir, 0, sizeof (dir));
5494         memset (&dir_entry, 0, sizeof (dir_entry));
5495         memset (&data_entry, 0, sizeof (data_entry));
5496
5497         g_assert (sizeof (dir) == 16);
5498         g_assert (sizeof (dir_entry) == 8);
5499         g_assert (sizeof (data_entry) == 16);
5500
5501         node->offset = p - begin;
5502
5503         /* IMAGE_RESOURCE_DIRECTORY */
5504         res_id_entries = g_slist_length (node->children);
5505         dir.res_id_entries = GUINT16_TO_LE (res_id_entries);
5506
5507         memcpy (p, &dir, sizeof (dir));
5508         p += sizeof (dir);
5509
5510         /* Reserve space for entries */
5511         entries = p;
5512         p += sizeof (dir_entry) * res_id_entries;
5513
5514         /* Write children */
5515         for (l = node->children; l; l = l->next) {
5516                 ResTreeNode *child = (ResTreeNode*)l->data;
5517
5518                 if (child->win32_res) {
5519                         guint32 size;
5520
5521                         child->offset = p - begin;
5522
5523                         /* IMAGE_RESOURCE_DATA_ENTRY */
5524                         data_entry.rde_data_offset = GUINT32_TO_LE (p - begin + sizeof (data_entry));
5525                         size = mono_array_length (child->win32_res->res_data);
5526                         data_entry.rde_size = GUINT32_TO_LE (size);
5527
5528                         memcpy (p, &data_entry, sizeof (data_entry));
5529                         p += sizeof (data_entry);
5530
5531                         memcpy (p, mono_array_addr (child->win32_res->res_data, char, 0), size);
5532                         p += size;
5533                 } else {
5534                         resource_tree_encode (child, begin, p, &p);
5535                 }
5536         }
5537
5538         /* IMAGE_RESOURCE_ENTRY */
5539         for (l = node->children; l; l = l->next) {
5540                 ResTreeNode *child = (ResTreeNode*)l->data;
5541
5542                 MONO_PE_RES_DIR_ENTRY_SET_NAME (dir_entry, FALSE, child->id);
5543                 MONO_PE_RES_DIR_ENTRY_SET_DIR (dir_entry, !child->win32_res, child->offset);
5544
5545                 memcpy (entries, &dir_entry, sizeof (dir_entry));
5546                 entries += sizeof (dir_entry);
5547         }
5548
5549         *endbuf = p;
5550 }
5551
5552 static void
5553 resource_tree_free (ResTreeNode * node)
5554 {
5555         GSList * list;
5556         for (list = node->children; list; list = list->next)
5557                 resource_tree_free ((ResTreeNode*)list->data);
5558         g_slist_free(node->children);
5559         g_free (node);
5560 }
5561
5562 static void
5563 assembly_add_win32_resources (MonoDynamicImage *assembly, MonoReflectionAssemblyBuilder *assemblyb)
5564 {
5565         char *buf;
5566         char *p;
5567         guint32 size, i;
5568         MonoReflectionWin32Resource *win32_res;
5569         ResTreeNode *tree;
5570
5571         if (!assemblyb->win32_resources)
5572                 return;
5573
5574         /*
5575          * Resources are stored in a three level tree inside the PE file.
5576          * - level one contains a node for each type of resource
5577          * - level two contains a node for each resource
5578          * - level three contains a node for each instance of a resource for a
5579          *   specific language.
5580          */
5581
5582         tree = resource_tree_create (assemblyb->win32_resources);
5583
5584         /* Estimate the size of the encoded tree */
5585         size = 0;
5586         for (i = 0; i < mono_array_length (assemblyb->win32_resources); ++i) {
5587                 win32_res = (MonoReflectionWin32Resource*)mono_array_addr (assemblyb->win32_resources, MonoReflectionWin32Resource, i);
5588                 size += mono_array_length (win32_res->res_data);
5589         }
5590         /* Directory structure */
5591         size += mono_array_length (assemblyb->win32_resources) * 256;
5592         p = buf = g_malloc (size);
5593
5594         resource_tree_encode (tree, p, p, &p);
5595
5596         g_assert (p - buf <= size);
5597
5598         assembly->win32_res = g_malloc (p - buf);
5599         assembly->win32_res_size = p - buf;
5600         memcpy (assembly->win32_res, buf, p - buf);
5601
5602         g_free (buf);
5603         resource_tree_free (tree);
5604 }
5605
5606 static void
5607 fixup_resource_directory (char *res_section, char *p, guint32 rva)
5608 {
5609         MonoPEResourceDir *dir = (MonoPEResourceDir*)p;
5610         int i;
5611
5612         p += sizeof (MonoPEResourceDir);
5613         for (i = 0; i < GUINT16_FROM_LE (dir->res_named_entries) + GUINT16_FROM_LE (dir->res_id_entries); ++i) {
5614                 MonoPEResourceDirEntry *dir_entry = (MonoPEResourceDirEntry*)p;
5615                 char *child = res_section + MONO_PE_RES_DIR_ENTRY_DIR_OFFSET (*dir_entry);
5616                 if (MONO_PE_RES_DIR_ENTRY_IS_DIR (*dir_entry)) {
5617                         fixup_resource_directory (res_section, child, rva);
5618                 } else {
5619                         MonoPEResourceDataEntry *data_entry = (MonoPEResourceDataEntry*)child;
5620                         data_entry->rde_data_offset = GUINT32_TO_LE (GUINT32_FROM_LE (data_entry->rde_data_offset) + rva);
5621                 }
5622
5623                 p += sizeof (MonoPEResourceDirEntry);
5624         }
5625 }
5626
5627 static void
5628 checked_write_file (HANDLE f, gconstpointer buffer, guint32 numbytes)
5629 {
5630         guint32 dummy;
5631         if (!WriteFile (f, buffer, numbytes, &dummy, NULL))
5632                 g_error ("WriteFile returned %d\n", GetLastError ());
5633 }
5634
5635 /*
5636  * mono_image_create_pefile:
5637  * @mb: a module builder object
5638  * 
5639  * This function creates the PE-COFF header, the image sections, the CLI header  * etc. all the data is written in
5640  * assembly->pefile where it can be easily retrieved later in chunks.
5641  */
5642 void
5643 mono_image_create_pefile (MonoReflectionModuleBuilder *mb, HANDLE file)
5644 {
5645         MonoMSDOSHeader *msdos;
5646         MonoDotNetHeader *header;
5647         MonoSectionTable *section;
5648         MonoCLIHeader *cli_header;
5649         guint32 size, image_size, virtual_base, text_offset;
5650         guint32 header_start, section_start, file_offset, virtual_offset;
5651         MonoDynamicImage *assembly;
5652         MonoReflectionAssemblyBuilder *assemblyb;
5653         MonoDynamicStream pefile_stream = {0};
5654         MonoDynamicStream *pefile = &pefile_stream;
5655         int i, nsections;
5656         guint32 *rva, value;
5657         guchar *p;
5658         static const unsigned char msheader[] = {
5659                 0x4d, 0x5a, 0x90, 0x00, 0x03, 0x00, 0x00, 0x00,  0x04, 0x00, 0x00, 0x00, 0xff, 0xff, 0x00, 0x00,
5660                 0xb8, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,  0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
5661                 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
5662                 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,  0x00, 0x00, 0x00, 0x00, 0x80, 0x00, 0x00, 0x00,
5663                 0x0e, 0x1f, 0xba, 0x0e, 0x00, 0xb4, 0x09, 0xcd,  0x21, 0xb8, 0x01, 0x4c, 0xcd, 0x21, 0x54, 0x68,
5664                 0x69, 0x73, 0x20, 0x70, 0x72, 0x6f, 0x67, 0x72,  0x61, 0x6d, 0x20, 0x63, 0x61, 0x6e, 0x6e, 0x6f,
5665                 0x74, 0x20, 0x62, 0x65, 0x20, 0x72, 0x75, 0x6e,  0x20, 0x69, 0x6e, 0x20, 0x44, 0x4f, 0x53, 0x20,
5666                 0x6d, 0x6f, 0x64, 0x65, 0x2e, 0x0d, 0x0d, 0x0a,  0x24, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
5667         };
5668
5669         assemblyb = mb->assemblyb;
5670
5671         mono_image_basic_init (assemblyb);
5672         assembly = mb->dynamic_image;
5673
5674         assembly->pe_kind = assemblyb->pe_kind;
5675         assembly->machine = assemblyb->machine;
5676         ((MonoDynamicImage*)assemblyb->dynamic_assembly->assembly.image)->pe_kind = assemblyb->pe_kind;
5677         ((MonoDynamicImage*)assemblyb->dynamic_assembly->assembly.image)->machine = assemblyb->machine;
5678         
5679         mono_image_build_metadata (mb);
5680
5681         if (mb->is_main && assemblyb->resources) {
5682                 int len = mono_array_length (assemblyb->resources);
5683                 for (i = 0; i < len; ++i)
5684                         assembly_add_resource (mb, assembly, (MonoReflectionResource*)mono_array_addr (assemblyb->resources, MonoReflectionResource, i));
5685         }
5686
5687         if (mb->resources) {
5688                 int len = mono_array_length (mb->resources);
5689                 for (i = 0; i < len; ++i)
5690                         assembly_add_resource (mb, assembly, (MonoReflectionResource*)mono_array_addr (mb->resources, MonoReflectionResource, i));
5691         }
5692
5693         build_compressed_metadata (assembly);
5694
5695         if (mb->is_main)
5696                 assembly_add_win32_resources (assembly, assemblyb);
5697
5698         nsections = calc_section_size (assembly);
5699         
5700         /* The DOS header and stub */
5701         g_assert (sizeof (MonoMSDOSHeader) == sizeof (msheader));
5702         mono_image_add_stream_data (pefile, (char*)msheader, sizeof (msheader));
5703
5704         /* the dotnet header */
5705         header_start = mono_image_add_stream_zero (pefile, sizeof (MonoDotNetHeader));
5706
5707         /* the section tables */
5708         section_start = mono_image_add_stream_zero (pefile, sizeof (MonoSectionTable) * nsections);
5709
5710         file_offset = section_start + sizeof (MonoSectionTable) * nsections;
5711         virtual_offset = VIRT_ALIGN;
5712         image_size = 0;
5713
5714         for (i = 0; i < MONO_SECTION_MAX; ++i) {
5715                 if (!assembly->sections [i].size)
5716                         continue;
5717                 /* align offsets */
5718                 file_offset += FILE_ALIGN - 1;
5719                 file_offset &= ~(FILE_ALIGN - 1);
5720                 virtual_offset += VIRT_ALIGN - 1;
5721                 virtual_offset &= ~(VIRT_ALIGN - 1);
5722
5723                 assembly->sections [i].offset = file_offset;
5724                 assembly->sections [i].rva = virtual_offset;
5725
5726                 file_offset += assembly->sections [i].size;
5727                 virtual_offset += assembly->sections [i].size;
5728                 image_size += (assembly->sections [i].size + VIRT_ALIGN - 1) & ~(VIRT_ALIGN - 1);
5729         }
5730
5731         file_offset += FILE_ALIGN - 1;
5732         file_offset &= ~(FILE_ALIGN - 1);
5733
5734         image_size += section_start + sizeof (MonoSectionTable) * nsections;
5735
5736         /* back-patch info */
5737         msdos = (MonoMSDOSHeader*)pefile->data;
5738         msdos->pe_offset = GUINT32_FROM_LE (sizeof (MonoMSDOSHeader));
5739
5740         header = (MonoDotNetHeader*)(pefile->data + header_start);
5741         header->pesig [0] = 'P';
5742         header->pesig [1] = 'E';
5743         
5744         header->coff.coff_machine = GUINT16_FROM_LE (assemblyb->machine);
5745         header->coff.coff_sections = GUINT16_FROM_LE (nsections);
5746         header->coff.coff_time = GUINT32_FROM_LE (time (NULL));
5747         header->coff.coff_opt_header_size = GUINT16_FROM_LE (sizeof (MonoDotNetHeader) - sizeof (MonoCOFFHeader) - 4);
5748         if (assemblyb->pekind == 1) {
5749                 /* it's a dll */
5750                 header->coff.coff_attributes = GUINT16_FROM_LE (0x210e);
5751         } else {
5752                 /* it's an exe */
5753                 header->coff.coff_attributes = GUINT16_FROM_LE (0x010e);
5754         }
5755
5756         virtual_base = 0x400000; /* FIXME: 0x10000000 if a DLL */
5757
5758         header->pe.pe_magic = GUINT16_FROM_LE (0x10B);
5759         header->pe.pe_major = 6;
5760         header->pe.pe_minor = 0;
5761         size = assembly->sections [MONO_SECTION_TEXT].size;
5762         size += FILE_ALIGN - 1;
5763         size &= ~(FILE_ALIGN - 1);
5764         header->pe.pe_code_size = GUINT32_FROM_LE(size);
5765         size = assembly->sections [MONO_SECTION_RSRC].size;
5766         size += FILE_ALIGN - 1;
5767         size &= ~(FILE_ALIGN - 1);
5768         header->pe.pe_data_size = GUINT32_FROM_LE(size);
5769         g_assert (START_TEXT_RVA == assembly->sections [MONO_SECTION_TEXT].rva);
5770         header->pe.pe_rva_code_base = GUINT32_FROM_LE (assembly->sections [MONO_SECTION_TEXT].rva);
5771         header->pe.pe_rva_data_base = GUINT32_FROM_LE (assembly->sections [MONO_SECTION_RSRC].rva);
5772         /* pe_rva_entry_point always at the beginning of the text section */
5773         header->pe.pe_rva_entry_point = GUINT32_FROM_LE (assembly->sections [MONO_SECTION_TEXT].rva);
5774
5775         header->nt.pe_image_base = GUINT32_FROM_LE (virtual_base);
5776         header->nt.pe_section_align = GUINT32_FROM_LE (VIRT_ALIGN);
5777         header->nt.pe_file_alignment = GUINT32_FROM_LE (FILE_ALIGN);
5778         header->nt.pe_os_major = GUINT16_FROM_LE (4);
5779         header->nt.pe_os_minor = GUINT16_FROM_LE (0);
5780         header->nt.pe_subsys_major = GUINT16_FROM_LE (4);
5781         size = section_start;
5782         size += FILE_ALIGN - 1;
5783         size &= ~(FILE_ALIGN - 1);
5784         header->nt.pe_header_size = GUINT32_FROM_LE (size);
5785         size = image_size;
5786         size += VIRT_ALIGN - 1;
5787         size &= ~(VIRT_ALIGN - 1);
5788         header->nt.pe_image_size = GUINT32_FROM_LE (size);
5789
5790         /*
5791         // Translate the PEFileKind value to the value expected by the Windows loader
5792         */
5793         {
5794                 short kind;
5795
5796                 /*
5797                 // PEFileKinds.Dll == 1
5798                 // PEFileKinds.ConsoleApplication == 2
5799                 // PEFileKinds.WindowApplication == 3
5800                 //
5801                 // need to get:
5802                 //     IMAGE_SUBSYSTEM_WINDOWS_GUI 2 // Image runs in the Windows GUI subsystem.
5803                 //     IMAGE_SUBSYSTEM_WINDOWS_CUI 3 // Image runs in the Windows character subsystem.
5804                 */
5805                 if (assemblyb->pekind == 3)
5806                         kind = 2;
5807                 else
5808                         kind = 3;
5809                 
5810                 header->nt.pe_subsys_required = GUINT16_FROM_LE (kind);
5811         }    
5812         header->nt.pe_stack_reserve = GUINT32_FROM_LE (0x00100000);
5813         header->nt.pe_stack_commit = GUINT32_FROM_LE (0x00001000);
5814         header->nt.pe_heap_reserve = GUINT32_FROM_LE (0x00100000);
5815         header->nt.pe_heap_commit = GUINT32_FROM_LE (0x00001000);
5816         header->nt.pe_loader_flags = GUINT32_FROM_LE (0);
5817         header->nt.pe_data_dir_count = GUINT32_FROM_LE (16);
5818
5819         /* fill data directory entries */
5820
5821         header->datadir.pe_resource_table.size = GUINT32_FROM_LE (assembly->sections [MONO_SECTION_RSRC].size);
5822         header->datadir.pe_resource_table.rva = GUINT32_FROM_LE (assembly->sections [MONO_SECTION_RSRC].rva);
5823
5824         header->datadir.pe_reloc_table.size = GUINT32_FROM_LE (assembly->sections [MONO_SECTION_RELOC].size);
5825         header->datadir.pe_reloc_table.rva = GUINT32_FROM_LE (assembly->sections [MONO_SECTION_RELOC].rva);
5826
5827         header->datadir.pe_cli_header.size = GUINT32_FROM_LE (72);
5828         header->datadir.pe_cli_header.rva = GUINT32_FROM_LE (assembly->text_rva + assembly->cli_header_offset);
5829         header->datadir.pe_iat.size = GUINT32_FROM_LE (8);
5830         header->datadir.pe_iat.rva = GUINT32_FROM_LE (assembly->text_rva + assembly->iat_offset);
5831         /* patch entrypoint name */
5832         if (assemblyb->pekind == 1)
5833                 memcpy (assembly->code.data + assembly->imp_names_offset + 2, "_CorDllMain", 12);
5834         else
5835                 memcpy (assembly->code.data + assembly->imp_names_offset + 2, "_CorExeMain", 12);
5836         /* patch imported function RVA name */
5837         rva = (guint32*)(assembly->code.data + assembly->iat_offset);
5838         *rva = GUINT32_FROM_LE (assembly->text_rva + assembly->imp_names_offset);
5839
5840         /* the import table */
5841         header->datadir.pe_import_table.size = GUINT32_FROM_LE (79); /* FIXME: magic number? */
5842         header->datadir.pe_import_table.rva = GUINT32_FROM_LE (assembly->text_rva + assembly->idt_offset);
5843         /* patch imported dll RVA name and other entries in the dir */
5844         rva = (guint32*)(assembly->code.data + assembly->idt_offset + G_STRUCT_OFFSET (MonoIDT, name_rva));
5845         *rva = GUINT32_FROM_LE (assembly->text_rva + assembly->imp_names_offset + 14); /* 14 is hint+strlen+1 of func name */
5846         rva = (guint32*)(assembly->code.data + assembly->idt_offset + G_STRUCT_OFFSET (MonoIDT, import_address_table_rva));
5847         *rva = GUINT32_FROM_LE (assembly->text_rva + assembly->iat_offset);
5848         rva = (guint32*)(assembly->code.data + assembly->idt_offset + G_STRUCT_OFFSET (MonoIDT, import_lookup_table));
5849         *rva = GUINT32_FROM_LE (assembly->text_rva + assembly->ilt_offset);
5850
5851         p = (guchar*)(assembly->code.data + assembly->ilt_offset);
5852         value = (assembly->text_rva + assembly->imp_names_offset);
5853         *p++ = (value) & 0xff;
5854         *p++ = (value >> 8) & (0xff);
5855         *p++ = (value >> 16) & (0xff);
5856         *p++ = (value >> 24) & (0xff);
5857
5858         /* the CLI header info */
5859         cli_header = (MonoCLIHeader*)(assembly->code.data + assembly->cli_header_offset);
5860         cli_header->ch_size = GUINT32_FROM_LE (72);
5861         cli_header->ch_runtime_major = GUINT16_FROM_LE (2);
5862         cli_header->ch_runtime_minor = GUINT16_FROM_LE (5);
5863         cli_header->ch_flags = GUINT32_FROM_LE (assemblyb->pe_kind);
5864         if (assemblyb->entry_point) {
5865                 guint32 table_idx = 0;
5866                 if (!strcmp (assemblyb->entry_point->object.vtable->klass->name, "MethodBuilder")) {
5867                         MonoReflectionMethodBuilder *methodb = (MonoReflectionMethodBuilder*)assemblyb->entry_point;
5868                         table_idx = methodb->table_idx;
5869                 } else {
5870                         table_idx = GPOINTER_TO_UINT (g_hash_table_lookup (assembly->method_to_table_idx, assemblyb->entry_point->method));
5871                 }
5872                 cli_header->ch_entry_point = GUINT32_FROM_LE (table_idx | MONO_TOKEN_METHOD_DEF);
5873         } else {
5874                 cli_header->ch_entry_point = GUINT32_FROM_LE (0);
5875         }
5876         /* The embedded managed resources */
5877         text_offset = assembly->text_rva + assembly->code.index;
5878         cli_header->ch_resources.rva = GUINT32_FROM_LE (text_offset);
5879         cli_header->ch_resources.size = GUINT32_FROM_LE (assembly->resources.index);
5880         text_offset += assembly->resources.index;
5881         cli_header->ch_metadata.rva = GUINT32_FROM_LE (text_offset);
5882         cli_header->ch_metadata.size = GUINT32_FROM_LE (assembly->meta_size);
5883         text_offset += assembly->meta_size;
5884         if (assembly->strong_name_size) {
5885                 cli_header->ch_strong_name.rva = GUINT32_FROM_LE (text_offset);
5886                 cli_header->ch_strong_name.size = GUINT32_FROM_LE (assembly->strong_name_size);
5887                 text_offset += assembly->strong_name_size;
5888         }
5889
5890         /* write the section tables and section content */
5891         section = (MonoSectionTable*)(pefile->data + section_start);
5892         for (i = 0; i < MONO_SECTION_MAX; ++i) {
5893                 static const char section_names [][7] = {
5894                         ".text", ".rsrc", ".reloc"
5895                 };
5896                 if (!assembly->sections [i].size)
5897                         continue;
5898                 strcpy (section->st_name, section_names [i]);
5899                 /*g_print ("output section %s (%d), size: %d\n", section->st_name, i, assembly->sections [i].size);*/
5900                 section->st_virtual_address = GUINT32_FROM_LE (assembly->sections [i].rva);
5901                 section->st_virtual_size = GUINT32_FROM_LE (assembly->sections [i].size);
5902                 section->st_raw_data_size = GUINT32_FROM_LE (GUINT32_TO_LE (section->st_virtual_size) + (FILE_ALIGN - 1));
5903                 section->st_raw_data_size &= GUINT32_FROM_LE (~(FILE_ALIGN - 1));
5904                 section->st_raw_data_ptr = GUINT32_FROM_LE (assembly->sections [i].offset);
5905                 section->st_flags = GUINT32_FROM_LE (assembly->sections [i].attrs);
5906                 section ++;
5907         }
5908         
5909         checked_write_file (file, pefile->data, pefile->index);
5910         
5911         mono_dynamic_stream_reset (pefile);
5912         
5913         for (i = 0; i < MONO_SECTION_MAX; ++i) {
5914                 if (!assembly->sections [i].size)
5915                         continue;
5916                 
5917                 if (SetFilePointer (file, assembly->sections [i].offset, NULL, FILE_BEGIN) == INVALID_SET_FILE_POINTER)
5918                         g_error ("SetFilePointer returned %d\n", GetLastError ());
5919                 
5920                 switch (i) {
5921                 case MONO_SECTION_TEXT:
5922                         /* patch entry point */
5923                         p = (guchar*)(assembly->code.data + 2);
5924                         value = (virtual_base + assembly->text_rva + assembly->iat_offset);
5925                         *p++ = (value) & 0xff;
5926                         *p++ = (value >> 8) & 0xff;
5927                         *p++ = (value >> 16) & 0xff;
5928                         *p++ = (value >> 24) & 0xff;
5929                 
5930                         checked_write_file (file, assembly->code.data, assembly->code.index);
5931                         checked_write_file (file, assembly->resources.data, assembly->resources.index);
5932                         checked_write_file (file, assembly->image.raw_metadata, assembly->meta_size);
5933                         checked_write_file (file, assembly->strong_name, assembly->strong_name_size);
5934                                 
5935
5936                         g_free (assembly->image.raw_metadata);
5937                         break;
5938                 case MONO_SECTION_RELOC: {
5939                         struct {
5940                                 guint32 page_rva;
5941                                 guint32 block_size;
5942                                 guint16 type_and_offset;
5943                                 guint16 term;
5944                         } reloc;
5945                         
5946                         g_assert (sizeof (reloc) == 12);
5947                         
5948                         reloc.page_rva = GUINT32_FROM_LE (assembly->text_rva);
5949                         reloc.block_size = GUINT32_FROM_LE (12);
5950                         
5951                         /* 
5952                          * the entrypoint is always at the start of the text section 
5953                          * 3 is IMAGE_REL_BASED_HIGHLOW
5954                          * 2 is patch_size_rva - text_rva
5955                          */
5956                         reloc.type_and_offset = GUINT16_FROM_LE ((3 << 12) + (2));
5957                         reloc.term = 0;
5958                         
5959                         checked_write_file (file, &reloc, sizeof (reloc));
5960                         
5961                         break;
5962                 }
5963                 case MONO_SECTION_RSRC:
5964                         if (assembly->win32_res) {
5965
5966                                 /* Fixup the offsets in the IMAGE_RESOURCE_DATA_ENTRY structures */
5967                                 fixup_resource_directory (assembly->win32_res, assembly->win32_res, assembly->sections [i].rva);
5968                                 checked_write_file (file, assembly->win32_res, assembly->win32_res_size);
5969                         }
5970                         break;
5971                 default:
5972                         g_assert_not_reached ();
5973                 }
5974         }
5975         
5976         /* check that the file is properly padded */
5977         if (SetFilePointer (file, file_offset, NULL, FILE_BEGIN) == INVALID_SET_FILE_POINTER)
5978                 g_error ("SetFilePointer returned %d\n", GetLastError ());
5979         if (! SetEndOfFile (file))
5980                 g_error ("SetEndOfFile returned %d\n", GetLastError ());
5981         
5982         mono_dynamic_stream_reset (&assembly->code);
5983         mono_dynamic_stream_reset (&assembly->us);
5984         mono_dynamic_stream_reset (&assembly->blob);
5985         mono_dynamic_stream_reset (&assembly->guid);
5986         mono_dynamic_stream_reset (&assembly->sheap);
5987
5988         g_hash_table_foreach (assembly->blob_cache, (GHFunc)g_free, NULL);
5989         g_hash_table_destroy (assembly->blob_cache);
5990         assembly->blob_cache = NULL;
5991 }
5992
5993 #else /* DISABLE_REFLECTION_EMIT_SAVE */
5994
5995 void
5996 mono_image_create_pefile (MonoReflectionModuleBuilder *mb, HANDLE file)
5997 {
5998         g_assert_not_reached ();
5999 }
6000
6001 #endif /* DISABLE_REFLECTION_EMIT_SAVE */
6002
6003 #ifndef DISABLE_REFLECTION_EMIT
6004
6005 MonoReflectionModule *
6006 mono_image_load_module_dynamic (MonoReflectionAssemblyBuilder *ab, MonoString *fileName)
6007 {
6008         char *name;
6009         MonoImage *image;
6010         MonoImageOpenStatus status;
6011         MonoDynamicAssembly *assembly;
6012         guint32 module_count;
6013         MonoImage **new_modules;
6014         gboolean *new_modules_loaded;
6015         
6016         name = mono_string_to_utf8 (fileName);
6017
6018         image = mono_image_open (name, &status);
6019         if (!image) {
6020                 MonoException *exc;
6021                 if (status == MONO_IMAGE_ERROR_ERRNO)
6022                         exc = mono_get_exception_file_not_found (fileName);
6023                 else
6024                         exc = mono_get_exception_bad_image_format (name);
6025                 g_free (name);
6026                 mono_raise_exception (exc);
6027         }
6028
6029         g_free (name);
6030
6031         assembly = ab->dynamic_assembly;
6032         image->assembly = (MonoAssembly*)assembly;
6033
6034         module_count = image->assembly->image->module_count;
6035         new_modules = g_new0 (MonoImage *, module_count + 1);
6036         new_modules_loaded = g_new0 (gboolean, module_count + 1);
6037
6038         if (image->assembly->image->modules)
6039                 memcpy (new_modules, image->assembly->image->modules, module_count * sizeof (MonoImage *));
6040         if (image->assembly->image->modules_loaded)
6041                 memcpy (new_modules_loaded, image->assembly->image->modules_loaded, module_count * sizeof (gboolean));
6042         new_modules [module_count] = image;
6043         new_modules_loaded [module_count] = TRUE;
6044         mono_image_addref (image);
6045
6046         g_free (image->assembly->image->modules);
6047         image->assembly->image->modules = new_modules;
6048         image->assembly->image->modules_loaded = new_modules_loaded;
6049         image->assembly->image->module_count ++;
6050
6051         mono_assembly_load_references (image, &status);
6052         if (status) {
6053                 mono_image_close (image);
6054                 mono_raise_exception (mono_get_exception_file_not_found (fileName));
6055         }
6056
6057         return mono_module_get_object (mono_domain_get (), image);
6058 }
6059
6060 #endif /* DISABLE_REFLECTION_EMIT */
6061
6062 /*
6063  * We need to return always the same object for MethodInfo, FieldInfo etc..
6064  * but we need to consider the reflected type.
6065  * type uses a different hash, since it uses custom hash/equal functions.
6066  */
6067
6068 typedef struct {
6069         gpointer item;
6070         MonoClass *refclass;
6071 } ReflectedEntry;
6072
6073 static gboolean
6074 reflected_equal (gconstpointer a, gconstpointer b) {
6075         const ReflectedEntry *ea = a;
6076         const ReflectedEntry *eb = b;
6077
6078         return (ea->item == eb->item) && (ea->refclass == eb->refclass);
6079 }
6080
6081 static guint
6082 reflected_hash (gconstpointer a) {
6083         const ReflectedEntry *ea = a;
6084         return mono_aligned_addr_hash (ea->item);
6085 }
6086
6087 #define CHECK_OBJECT(t,p,k)     \
6088         do {    \
6089                 t _obj; \
6090                 ReflectedEntry e;       \
6091                 e.item = (p);   \
6092                 e.refclass = (k);       \
6093                 mono_domain_lock (domain);      \
6094                 if (!domain->refobject_hash)    \
6095                         domain->refobject_hash = mono_g_hash_table_new_type (reflected_hash, reflected_equal, MONO_HASH_VALUE_GC);      \
6096                 if ((_obj = mono_g_hash_table_lookup (domain->refobject_hash, &e))) {   \
6097                         mono_domain_unlock (domain);    \
6098                         return _obj;    \
6099                 }       \
6100         mono_domain_unlock (domain); \
6101         } while (0)
6102
6103 #ifdef HAVE_BOEHM_GC
6104 /* ReflectedEntry doesn't need to be GC tracked */
6105 #define ALLOC_REFENTRY g_new0 (ReflectedEntry, 1)
6106 #define FREE_REFENTRY(entry) g_free ((entry))
6107 #define REFENTRY_REQUIRES_CLEANUP
6108 #else
6109 #define ALLOC_REFENTRY mono_mempool_alloc (domain->mp, sizeof (ReflectedEntry))
6110 /* FIXME: */
6111 #define FREE_REFENTRY(entry)
6112 #endif
6113
6114 #define CACHE_OBJECT(t,p,o,k)   \
6115         do {    \
6116                 t _obj; \
6117         ReflectedEntry pe; \
6118         pe.item = (p); \
6119         pe.refclass = (k); \
6120         mono_domain_lock (domain); \
6121                 if (!domain->refobject_hash)    \
6122                         domain->refobject_hash = mono_g_hash_table_new_type (reflected_hash, reflected_equal, MONO_HASH_VALUE_GC);      \
6123         _obj = mono_g_hash_table_lookup (domain->refobject_hash, &pe); \
6124         if (!_obj) { \
6125                     ReflectedEntry *e = ALLOC_REFENTRY;         \
6126                     e->item = (p);      \
6127                     e->refclass = (k);  \
6128                     mono_g_hash_table_insert (domain->refobject_hash, e,o);     \
6129             _obj = o; \
6130         } \
6131                 mono_domain_unlock (domain);    \
6132         return _obj; \
6133         } while (0)
6134
6135 static void
6136 clear_cached_object (MonoDomain *domain, gpointer o, MonoClass *klass)
6137 {
6138         mono_domain_lock (domain);
6139         if (domain->refobject_hash) {
6140         ReflectedEntry pe;
6141                 gpointer orig_pe, orig_value;
6142
6143                 pe.item = o;
6144                 pe.refclass = klass;
6145                 if (mono_g_hash_table_lookup_extended (domain->refobject_hash, &pe, &orig_pe, &orig_value)) {
6146                         mono_g_hash_table_remove (domain->refobject_hash, &pe);
6147                         FREE_REFENTRY (orig_pe);
6148                 }
6149         }
6150         mono_domain_unlock (domain);
6151 }
6152
6153 #ifdef REFENTRY_REQUIRES_CLEANUP
6154 static void
6155 cleanup_refobject_hash (gpointer key, gpointer value, gpointer user_data)
6156 {
6157         FREE_REFENTRY (key);
6158 }
6159 #endif
6160
6161 void
6162 mono_reflection_cleanup_domain (MonoDomain *domain)
6163 {
6164         if (domain->refobject_hash) {
6165 /*let's avoid scanning the whole hashtable if not needed*/
6166 #ifdef REFENTRY_REQUIRES_CLEANUP
6167                 mono_g_hash_table_foreach (domain->refobject_hash, cleanup_refobject_hash, NULL);
6168 #endif
6169                 mono_g_hash_table_destroy (domain->refobject_hash);
6170                 domain->refobject_hash = NULL;
6171         }
6172 }
6173
6174 #ifndef DISABLE_REFLECTION_EMIT
6175 static gpointer
6176 register_assembly (MonoDomain *domain, MonoReflectionAssembly *res, MonoAssembly *assembly)
6177 {
6178         CACHE_OBJECT (MonoReflectionAssembly *, assembly, res, NULL);
6179 }
6180
6181 static gpointer
6182 register_module (MonoDomain *domain, MonoReflectionModuleBuilder *res, MonoDynamicImage *module)
6183 {
6184         CACHE_OBJECT (MonoReflectionModuleBuilder *, module, res, NULL);
6185 }
6186
6187 void
6188 mono_image_module_basic_init (MonoReflectionModuleBuilder *moduleb)
6189 {
6190         MonoDynamicImage *image = moduleb->dynamic_image;
6191         MonoReflectionAssemblyBuilder *ab = moduleb->assemblyb;
6192         if (!image) {
6193                 MonoError error;
6194                 int module_count;
6195                 MonoImage **new_modules;
6196                 MonoImage *ass;
6197                 char *name, *fqname;
6198                 /*
6199                  * FIXME: we already created an image in mono_image_basic_init (), but
6200                  * we don't know which module it belongs to, since that is only 
6201                  * determined at assembly save time.
6202                  */
6203                 /*image = (MonoDynamicImage*)ab->dynamic_assembly->assembly.image; */
6204                 name = mono_string_to_utf8 (ab->name);
6205                 fqname = mono_string_to_utf8_checked (moduleb->module.fqname, &error);
6206                 if (!mono_error_ok (&error)) {
6207                         g_free (name);
6208                         mono_error_raise_exception (&error);
6209                 }
6210                 image = create_dynamic_mono_image (ab->dynamic_assembly, name, fqname);
6211
6212                 moduleb->module.image = &image->image;
6213                 moduleb->dynamic_image = image;
6214                 register_module (mono_object_domain (moduleb), moduleb, image);
6215
6216                 /* register the module with the assembly */
6217                 ass = ab->dynamic_assembly->assembly.image;
6218                 module_count = ass->module_count;
6219                 new_modules = g_new0 (MonoImage *, module_count + 1);
6220
6221                 if (ass->modules)
6222                         memcpy (new_modules, ass->modules, module_count * sizeof (MonoImage *));
6223                 new_modules [module_count] = &image->image;
6224                 mono_image_addref (&image->image);
6225
6226                 g_free (ass->modules);
6227                 ass->modules = new_modules;
6228                 ass->module_count ++;
6229         }
6230 }
6231
6232 void
6233 mono_image_set_wrappers_type (MonoReflectionModuleBuilder *moduleb, MonoReflectionType *type)
6234 {
6235         MonoDynamicImage *image = moduleb->dynamic_image;
6236
6237         g_assert (type->type);
6238         image->wrappers_type = mono_class_from_mono_type (type->type);
6239 }
6240
6241 #endif
6242
6243 /*
6244  * mono_assembly_get_object:
6245  * @domain: an app domain
6246  * @assembly: an assembly
6247  *
6248  * Return an System.Reflection.Assembly object representing the MonoAssembly @assembly.
6249  */
6250 MonoReflectionAssembly*
6251 mono_assembly_get_object (MonoDomain *domain, MonoAssembly *assembly)
6252 {
6253         static MonoClass *assembly_type;
6254         MonoReflectionAssembly *res;
6255         
6256         CHECK_OBJECT (MonoReflectionAssembly *, assembly, NULL);
6257         if (!assembly_type) {
6258                 MonoClass *class = mono_class_from_name (mono_defaults.corlib, "System.Reflection", "MonoAssembly");
6259                 if (class == NULL)
6260                         class = mono_class_from_name (mono_defaults.corlib, "System.Reflection", "Assembly");
6261                 g_assert (class);
6262                 assembly_type = class;
6263         }
6264         res = (MonoReflectionAssembly *)mono_object_new (domain, assembly_type);
6265         res->assembly = assembly;
6266
6267         CACHE_OBJECT (MonoReflectionAssembly *, assembly, res, NULL);
6268 }
6269
6270
6271
6272 MonoReflectionModule*   
6273 mono_module_get_object   (MonoDomain *domain, MonoImage *image)
6274 {
6275         static MonoClass *module_type;
6276         MonoReflectionModule *res;
6277         char* basename;
6278         
6279         CHECK_OBJECT (MonoReflectionModule *, image, NULL);
6280         if (!module_type) {
6281                 MonoClass *class = mono_class_from_name (mono_defaults.corlib, "System.Reflection", "MonoModule");
6282                 if (class == NULL)
6283                         class = mono_class_from_name (mono_defaults.corlib, "System.Reflection", "Module");
6284                 g_assert (class);
6285                 module_type = class;
6286         }
6287         res = (MonoReflectionModule *)mono_object_new (domain, module_type);
6288
6289         res->image = image;
6290         MONO_OBJECT_SETREF (res, assembly, (MonoReflectionAssembly *) mono_assembly_get_object(domain, image->assembly));
6291
6292         MONO_OBJECT_SETREF (res, fqname, mono_string_new (domain, image->name));
6293         basename = g_path_get_basename (image->name);
6294         MONO_OBJECT_SETREF (res, name, mono_string_new (domain, basename));
6295         MONO_OBJECT_SETREF (res, scopename, mono_string_new (domain, image->module_name));
6296         
6297         g_free (basename);
6298
6299         if (image->assembly->image == image) {
6300                 res->token = mono_metadata_make_token (MONO_TABLE_MODULE, 1);
6301         } else {
6302                 int i;
6303                 res->token = 0;
6304                 if (image->assembly->image->modules) {
6305                         for (i = 0; i < image->assembly->image->module_count; i++) {
6306                                 if (image->assembly->image->modules [i] == image)
6307                                         res->token = mono_metadata_make_token (MONO_TABLE_MODULEREF, i + 1);
6308                         }
6309                         g_assert (res->token);
6310                 }
6311         }
6312
6313         CACHE_OBJECT (MonoReflectionModule *, image, res, NULL);
6314 }
6315
6316 MonoReflectionModule*   
6317 mono_module_file_get_object (MonoDomain *domain, MonoImage *image, int table_index)
6318 {
6319         static MonoClass *module_type;
6320         MonoReflectionModule *res;
6321         MonoTableInfo *table;
6322         guint32 cols [MONO_FILE_SIZE];
6323         const char *name;
6324         guint32 i, name_idx;
6325         const char *val;
6326         
6327         if (!module_type) {
6328                 MonoClass *class = mono_class_from_name (mono_defaults.corlib, "System.Reflection", "MonoModule");
6329                 if (class == NULL)
6330                         class = mono_class_from_name (mono_defaults.corlib, "System.Reflection", "Module");
6331                 g_assert (class);
6332                 module_type = class;
6333         }
6334         res = (MonoReflectionModule *)mono_object_new (domain, module_type);
6335
6336         table = &image->tables [MONO_TABLE_FILE];
6337         g_assert (table_index < table->rows);
6338         mono_metadata_decode_row (table, table_index, cols, MONO_FILE_SIZE);
6339
6340         res->image = NULL;
6341         MONO_OBJECT_SETREF (res, assembly, (MonoReflectionAssembly *) mono_assembly_get_object(domain, image->assembly));
6342         name = mono_metadata_string_heap (image, cols [MONO_FILE_NAME]);
6343
6344         /* Check whenever the row has a corresponding row in the moduleref table */
6345         table = &image->tables [MONO_TABLE_MODULEREF];
6346         for (i = 0; i < table->rows; ++i) {
6347                 name_idx = mono_metadata_decode_row_col (table, i, MONO_MODULEREF_NAME);
6348                 val = mono_metadata_string_heap (image, name_idx);
6349                 if (strcmp (val, name) == 0)
6350                         res->image = image->modules [i];
6351         }
6352
6353         MONO_OBJECT_SETREF (res, fqname, mono_string_new (domain, name));
6354         MONO_OBJECT_SETREF (res, name, mono_string_new (domain, name));
6355         MONO_OBJECT_SETREF (res, scopename, mono_string_new (domain, name));
6356         res->is_resource = cols [MONO_FILE_FLAGS] && FILE_CONTAINS_NO_METADATA;
6357         res->token = mono_metadata_make_token (MONO_TABLE_FILE, table_index + 1);
6358
6359         return res;
6360 }
6361
6362 static gboolean
6363 verify_safe_for_managed_space (MonoType *type)
6364 {
6365         switch (type->type) {
6366 #ifdef DEBUG_HARDER
6367         case MONO_TYPE_ARRAY:
6368                 return verify_safe_for_managed_space (&type->data.array->eklass->byval_arg);
6369         case MONO_TYPE_PTR:
6370                 return verify_safe_for_managed_space (type->data.type);
6371         case MONO_TYPE_SZARRAY:
6372                 return verify_safe_for_managed_space (&type->data.klass->byval_arg);
6373         case MONO_TYPE_GENERICINST: {
6374                 MonoGenericInst *inst = type->data.generic_class->inst;
6375                 int i;
6376                 if (!inst->is_open)
6377                         break;
6378                 for (i = 0; i < inst->type_argc; ++i)
6379                         if (!verify_safe_for_managed_space (inst->type_argv [i]))
6380                                 return FALSE;
6381                 break;
6382         }
6383 #endif
6384         case MONO_TYPE_VAR:
6385         case MONO_TYPE_MVAR:
6386                 return TRUE;
6387         }
6388         return TRUE;
6389 }
6390
6391 static MonoType*
6392 mono_type_normalize (MonoType *type)
6393 {
6394         int i;
6395         MonoGenericClass *gclass;
6396         MonoGenericInst *ginst;
6397         MonoClass *gtd;
6398         MonoGenericContainer *gcontainer;
6399         MonoType **argv = NULL;
6400         gboolean is_denorm_gtd = TRUE, requires_rebind = FALSE;
6401
6402         if (type->type != MONO_TYPE_GENERICINST)
6403                 return type;
6404
6405         gclass = type->data.generic_class;
6406         ginst = gclass->context.class_inst;
6407         if (!ginst->is_open)
6408                 return type;
6409
6410         gtd = gclass->container_class;
6411         gcontainer = gtd->generic_container;
6412         argv = g_newa (MonoType*, ginst->type_argc);
6413
6414         for (i = 0; i < ginst->type_argc; ++i) {
6415                 MonoType *t = ginst->type_argv [i], *norm;
6416                 if (t->type != MONO_TYPE_VAR || t->data.generic_param->num != i || t->data.generic_param->owner != gcontainer)
6417                         is_denorm_gtd = FALSE;
6418                 norm = mono_type_normalize (t);
6419                 argv [i] = norm;
6420                 if (norm != t)
6421                         requires_rebind = TRUE;
6422         }
6423
6424         if (is_denorm_gtd)
6425                 return type->byref == gtd->byval_arg.byref ? &gtd->byval_arg : &gtd->this_arg;
6426
6427         if (requires_rebind) {
6428                 MonoClass *klass = mono_class_bind_generic_parameters (gtd, ginst->type_argc, argv, gclass->is_dynamic);
6429                 return type->byref == klass->byval_arg.byref ? &klass->byval_arg : &klass->this_arg;
6430         }
6431
6432         return type;
6433 }
6434 /*
6435  * mono_type_get_object:
6436  * @domain: an app domain
6437  * @type: a type
6438  *
6439  * Return an System.MonoType object representing the type @type.
6440  */
6441 MonoReflectionType*
6442 mono_type_get_object (MonoDomain *domain, MonoType *type)
6443 {
6444         MonoType *norm_type;
6445         MonoReflectionType *res;
6446         MonoClass *klass = mono_class_from_mono_type (type);
6447
6448         /*we must avoid using @type as it might have come
6449          * from a mono_metadata_type_dup and the caller
6450          * expects that is can be freed.
6451          * Using the right type from 
6452          */
6453         type = klass->byval_arg.byref == type->byref ? &klass->byval_arg : &klass->this_arg;
6454
6455         /* void is very common */
6456         if (type->type == MONO_TYPE_VOID && domain->typeof_void)
6457                 return (MonoReflectionType*)domain->typeof_void;
6458
6459         /*
6460          * If the vtable of the given class was already created, we can use
6461          * the MonoType from there and avoid all locking and hash table lookups.
6462          * 
6463          * We cannot do this for TypeBuilders as mono_reflection_create_runtime_class expects
6464          * that the resulting object is different.   
6465          */
6466         if (type == &klass->byval_arg && !klass->image->dynamic) {
6467                 MonoVTable *vtable = mono_class_try_get_vtable (domain, klass);
6468                 if (vtable && vtable->type)
6469                         return vtable->type;
6470         }
6471
6472         mono_loader_lock (); /*FIXME mono_class_init and mono_class_vtable acquire it*/
6473         mono_domain_lock (domain);
6474         if (!domain->type_hash)
6475                 domain->type_hash = mono_g_hash_table_new_type ((GHashFunc)mono_metadata_type_hash, 
6476                                 (GCompareFunc)mono_metadata_type_equal, MONO_HASH_VALUE_GC);
6477         if ((res = mono_g_hash_table_lookup (domain->type_hash, type))) {
6478                 mono_domain_unlock (domain);
6479                 mono_loader_unlock ();
6480                 return res;
6481         }
6482
6483         /*Types must be normalized so a generic instance of the GTD get's the same inner type.
6484          * For example in: Foo<A,B>; Bar<A> : Foo<A, Bar<A>>
6485          * The second Bar will be encoded a generic instance of Bar with <A> as parameter.
6486          * On all other places, Bar<A> will be encoded as the GTD itself. This is an implementation
6487          * artifact of how generics are encoded and should be transparent to managed code so we
6488          * need to weed out this diference when retrieving managed System.Type objects.
6489          */
6490         norm_type = mono_type_normalize (type);
6491         if (norm_type != type) {
6492                 res = mono_type_get_object (domain, norm_type);
6493                 mono_g_hash_table_insert (domain->type_hash, type, res);
6494                 mono_domain_unlock (domain);
6495                 mono_loader_unlock ();
6496                 return res;
6497         }
6498
6499         /* This MonoGenericClass hack is no longer necessary. Let's leave it here until we finish with the 2-stage type-builder setup.*/
6500         if ((type->type == MONO_TYPE_GENERICINST) && type->data.generic_class->is_dynamic && !type->data.generic_class->container_class->wastypebuilder)
6501                 g_assert (0);
6502
6503         if (!verify_safe_for_managed_space (type)) {
6504                 mono_domain_unlock (domain);
6505                 mono_loader_unlock ();
6506                 mono_raise_exception (mono_get_exception_invalid_operation ("This type cannot be propagated to managed space"));
6507         }
6508
6509         if (mono_class_get_ref_info (klass) && !klass->wastypebuilder) {
6510                 gboolean is_type_done = TRUE;
6511                 /* Generic parameters have reflection_info set but they are not finished together with their enclosing type.
6512                  * We must ensure that once a type is finished we don't return a GenericTypeParameterBuilder.
6513                  * We can't simply close the types as this will interfere with other parts of the generics machinery.
6514                 */
6515                 if (klass->byval_arg.type == MONO_TYPE_MVAR || klass->byval_arg.type == MONO_TYPE_VAR) {
6516                         MonoGenericParam *gparam = klass->byval_arg.data.generic_param;
6517
6518                         if (gparam->owner && gparam->owner->is_method) {
6519                                 MonoMethod *method = gparam->owner->owner.method;
6520                                 if (method && mono_class_get_generic_type_definition (method->klass)->wastypebuilder)
6521                                         is_type_done = FALSE;
6522                         } else if (gparam->owner && !gparam->owner->is_method) {
6523                                 MonoClass *klass = gparam->owner->owner.klass;
6524                                 if (klass && mono_class_get_generic_type_definition (klass)->wastypebuilder)
6525                                         is_type_done = FALSE;
6526                         }
6527                 } 
6528
6529                 /* g_assert_not_reached (); */
6530                 /* should this be considered an error condition? */
6531                 if (is_type_done && !type->byref) {
6532                         mono_domain_unlock (domain);
6533                         mono_loader_unlock ();
6534                         return mono_class_get_ref_info (klass);
6535                 }
6536         }
6537         /* This is stored in vtables/JITted code so it has to be pinned */
6538         res = (MonoReflectionType *)mono_object_new_pinned (domain, mono_defaults.monotype_class);
6539         res->type = type;
6540         mono_g_hash_table_insert (domain->type_hash, type, res);
6541
6542         if (type->type == MONO_TYPE_VOID)
6543                 domain->typeof_void = (MonoObject*)res;
6544
6545         mono_domain_unlock (domain);
6546         mono_loader_unlock ();
6547         return res;
6548 }
6549
6550 /*
6551  * mono_method_get_object:
6552  * @domain: an app domain
6553  * @method: a method
6554  * @refclass: the reflected type (can be NULL)
6555  *
6556  * Return an System.Reflection.MonoMethod object representing the method @method.
6557  */
6558 MonoReflectionMethod*
6559 mono_method_get_object (MonoDomain *domain, MonoMethod *method, MonoClass *refclass)
6560 {
6561         /*
6562          * We use the same C representation for methods and constructors, but the type 
6563          * name in C# is different.
6564          */
6565         static MonoClass *System_Reflection_MonoMethod = NULL;
6566         static MonoClass *System_Reflection_MonoCMethod = NULL;
6567         static MonoClass *System_Reflection_MonoGenericMethod = NULL;
6568         static MonoClass *System_Reflection_MonoGenericCMethod = NULL;
6569         MonoClass *klass;
6570         MonoReflectionMethod *ret;
6571
6572         if (method->is_inflated) {
6573                 MonoReflectionGenericMethod *gret;
6574
6575                 refclass = method->klass;
6576                 CHECK_OBJECT (MonoReflectionMethod *, method, refclass);
6577                 if ((*method->name == '.') && (!strcmp (method->name, ".ctor") || !strcmp (method->name, ".cctor"))) {
6578                         if (!System_Reflection_MonoGenericCMethod)
6579                                 System_Reflection_MonoGenericCMethod = mono_class_from_name (mono_defaults.corlib, "System.Reflection", "MonoGenericCMethod");
6580                         klass = System_Reflection_MonoGenericCMethod;
6581                 } else {
6582                         if (!System_Reflection_MonoGenericMethod)
6583                                 System_Reflection_MonoGenericMethod = mono_class_from_name (mono_defaults.corlib, "System.Reflection", "MonoGenericMethod");
6584                         klass = System_Reflection_MonoGenericMethod;
6585                 }
6586                 gret = (MonoReflectionGenericMethod*)mono_object_new (domain, klass);
6587                 gret->method.method = method;
6588                 MONO_OBJECT_SETREF (gret, method.name, mono_string_new (domain, method->name));
6589                 MONO_OBJECT_SETREF (gret, method.reftype, mono_type_get_object (domain, &refclass->byval_arg));
6590                 CACHE_OBJECT (MonoReflectionMethod *, method, (MonoReflectionMethod*)gret, refclass);
6591         }
6592
6593         if (!refclass)
6594                 refclass = method->klass;
6595
6596         CHECK_OBJECT (MonoReflectionMethod *, method, refclass);
6597         if (*method->name == '.' && (strcmp (method->name, ".ctor") == 0 || strcmp (method->name, ".cctor") == 0)) {
6598                 if (!System_Reflection_MonoCMethod)
6599                         System_Reflection_MonoCMethod = mono_class_from_name (mono_defaults.corlib, "System.Reflection", "MonoCMethod");
6600                 klass = System_Reflection_MonoCMethod;
6601         }
6602         else {
6603                 if (!System_Reflection_MonoMethod)
6604                         System_Reflection_MonoMethod = mono_class_from_name (mono_defaults.corlib, "System.Reflection", "MonoMethod");
6605                 klass = System_Reflection_MonoMethod;
6606         }
6607         ret = (MonoReflectionMethod*)mono_object_new (domain, klass);
6608         ret->method = method;
6609         MONO_OBJECT_SETREF (ret, reftype, mono_type_get_object (domain, &refclass->byval_arg));
6610         CACHE_OBJECT (MonoReflectionMethod *, method, ret, refclass);
6611 }
6612
6613 /*
6614  * mono_method_clear_object:
6615  *
6616  *   Clear the cached reflection objects for the dynamic method METHOD.
6617  */
6618 void
6619 mono_method_clear_object (MonoDomain *domain, MonoMethod *method)
6620 {
6621         MonoClass *klass;
6622         g_assert (method->dynamic);
6623
6624         klass = method->klass;
6625         while (klass) {
6626                 clear_cached_object (domain, method, klass);
6627                 klass = klass->parent;
6628         }
6629         /* Added by mono_param_get_objects () */
6630         clear_cached_object (domain, &(method->signature), NULL);
6631         klass = method->klass;
6632         while (klass) {
6633                 clear_cached_object (domain, &(method->signature), klass);
6634                 klass = klass->parent;
6635         }
6636 }
6637
6638 /*
6639  * mono_field_get_object:
6640  * @domain: an app domain
6641  * @klass: a type
6642  * @field: a field
6643  *
6644  * Return an System.Reflection.MonoField object representing the field @field
6645  * in class @klass.
6646  */
6647 MonoReflectionField*
6648 mono_field_get_object (MonoDomain *domain, MonoClass *klass, MonoClassField *field)
6649 {
6650         MonoReflectionField *res;
6651         static MonoClass *monofield_klass;
6652
6653         CHECK_OBJECT (MonoReflectionField *, field, klass);
6654         if (!monofield_klass)
6655                 monofield_klass = mono_class_from_name (mono_defaults.corlib, "System.Reflection", "MonoField");
6656         res = (MonoReflectionField *)mono_object_new (domain, monofield_klass);
6657         res->klass = klass;
6658         res->field = field;
6659         MONO_OBJECT_SETREF (res, name, mono_string_new (domain, mono_field_get_name (field)));
6660
6661         if (is_field_on_inst (field)) {
6662                 res->attrs = get_field_on_inst_generic_type (field)->attrs;
6663                 MONO_OBJECT_SETREF (res, type, mono_type_get_object (domain, field->type));
6664         } else {
6665                 if (field->type)
6666                         MONO_OBJECT_SETREF (res, type, mono_type_get_object (domain, field->type));
6667                 res->attrs = mono_field_get_flags (field);
6668         }
6669         CACHE_OBJECT (MonoReflectionField *, field, res, klass);
6670 }
6671
6672 /*
6673  * mono_property_get_object:
6674  * @domain: an app domain
6675  * @klass: a type
6676  * @property: a property
6677  *
6678  * Return an System.Reflection.MonoProperty object representing the property @property
6679  * in class @klass.
6680  */
6681 MonoReflectionProperty*
6682 mono_property_get_object (MonoDomain *domain, MonoClass *klass, MonoProperty *property)
6683 {
6684         MonoReflectionProperty *res;
6685         static MonoClass *monoproperty_klass;
6686
6687         CHECK_OBJECT (MonoReflectionProperty *, property, klass);
6688         if (!monoproperty_klass)
6689                 monoproperty_klass = mono_class_from_name (mono_defaults.corlib, "System.Reflection", "MonoProperty");
6690         res = (MonoReflectionProperty *)mono_object_new (domain, monoproperty_klass);
6691         res->klass = klass;
6692         res->property = property;
6693         CACHE_OBJECT (MonoReflectionProperty *, property, res, klass);
6694 }
6695
6696 /*
6697  * mono_event_get_object:
6698  * @domain: an app domain
6699  * @klass: a type
6700  * @event: a event
6701  *
6702  * Return an System.Reflection.MonoEvent object representing the event @event
6703  * in class @klass.
6704  */
6705 MonoReflectionEvent*
6706 mono_event_get_object (MonoDomain *domain, MonoClass *klass, MonoEvent *event)
6707 {
6708         MonoReflectionEvent *res;
6709         MonoReflectionMonoEvent *mono_event;
6710         static MonoClass *monoevent_klass;
6711
6712         CHECK_OBJECT (MonoReflectionEvent *, event, klass);
6713         if (!monoevent_klass)
6714                 monoevent_klass = mono_class_from_name (mono_defaults.corlib, "System.Reflection", "MonoEvent");
6715         mono_event = (MonoReflectionMonoEvent *)mono_object_new (domain, monoevent_klass);
6716         mono_event->klass = klass;
6717         mono_event->event = event;
6718         res = (MonoReflectionEvent*)mono_event;
6719         CACHE_OBJECT (MonoReflectionEvent *, event, res, klass);
6720 }
6721
6722 /**
6723  * mono_get_reflection_missing_object:
6724  * @domain: Domain where the object lives
6725  *
6726  * Returns the System.Reflection.Missing.Value singleton object
6727  * (of type System.Reflection.Missing).
6728  *
6729  * Used as the value for ParameterInfo.DefaultValue when Optional
6730  * is present
6731  */
6732 static MonoObject *
6733 mono_get_reflection_missing_object (MonoDomain *domain)
6734 {
6735         MonoObject *obj;
6736         static MonoClassField *missing_value_field = NULL;
6737         
6738         if (!missing_value_field) {
6739                 MonoClass *missing_klass;
6740                 missing_klass = mono_class_from_name (mono_defaults.corlib, "System.Reflection", "Missing");
6741                 mono_class_init (missing_klass);
6742                 missing_value_field = mono_class_get_field_from_name (missing_klass, "Value");
6743                 g_assert (missing_value_field);
6744         }
6745         obj = mono_field_get_value_object (domain, missing_value_field, NULL); 
6746         g_assert (obj);
6747         return obj;
6748 }
6749
6750 static MonoObject*
6751 get_dbnull (MonoDomain *domain, MonoObject **dbnull)
6752 {
6753         if (!*dbnull)
6754                 *dbnull = mono_get_dbnull_object (domain);
6755         return *dbnull;
6756 }
6757
6758 static MonoObject*
6759 get_reflection_missing (MonoDomain *domain, MonoObject **reflection_missing)
6760 {
6761         if (!*reflection_missing)
6762                 *reflection_missing = mono_get_reflection_missing_object (domain);
6763         return *reflection_missing;
6764 }
6765
6766 /*
6767  * mono_param_get_objects:
6768  * @domain: an app domain
6769  * @method: a method
6770  *
6771  * Return an System.Reflection.ParameterInfo array object representing the parameters
6772  * in the method @method.
6773  */
6774 MonoArray*
6775 mono_param_get_objects_internal (MonoDomain *domain, MonoMethod *method, MonoClass *refclass)
6776 {
6777         static MonoClass *System_Reflection_ParameterInfo;
6778         static MonoClass *System_Reflection_ParameterInfo_array;
6779         MonoError error;
6780         MonoArray *res = NULL;
6781         MonoReflectionMethod *member = NULL;
6782         MonoReflectionParameter *param = NULL;
6783         char **names, **blobs = NULL;
6784         guint32 *types = NULL;
6785         MonoType *type = NULL;
6786         MonoObject *dbnull = NULL;
6787         MonoObject *missing = NULL;
6788         MonoMarshalSpec **mspecs;
6789         MonoMethodSignature *sig;
6790         MonoVTable *pinfo_vtable;
6791         int i;
6792
6793         if (!System_Reflection_ParameterInfo_array) {
6794                 MonoClass *klass;
6795
6796                 klass = mono_class_from_name (mono_defaults.corlib, "System.Reflection", "MonoParameterInfo");
6797                 if (!klass)
6798                         klass = mono_class_from_name (mono_defaults.corlib, "System.Reflection", "ParameterInfo");
6799
6800                 mono_memory_barrier ();
6801                 System_Reflection_ParameterInfo = klass; 
6802
6803         
6804                 klass = mono_array_class_get (klass, 1);
6805                 mono_memory_barrier ();
6806                 System_Reflection_ParameterInfo_array = klass;
6807         }
6808
6809         sig = mono_method_signature_checked (method, &error);
6810         if (!mono_error_ok (&error))
6811                 mono_error_raise_exception (&error);
6812
6813         if (!sig->param_count)
6814                 return mono_array_new_specific (mono_class_vtable (domain, System_Reflection_ParameterInfo_array), 0);
6815
6816         /* Note: the cache is based on the address of the signature into the method
6817          * since we already cache MethodInfos with the method as keys.
6818          */
6819         CHECK_OBJECT (MonoArray*, &(method->signature), refclass);
6820
6821         member = mono_method_get_object (domain, method, refclass);
6822         names = g_new (char *, sig->param_count);
6823         mono_method_get_param_names (method, (const char **) names);
6824
6825         mspecs = g_new (MonoMarshalSpec*, sig->param_count + 1);
6826         mono_method_get_marshal_info (method, mspecs);
6827
6828         res = mono_array_new_specific (mono_class_vtable (domain, System_Reflection_ParameterInfo_array), sig->param_count);
6829         pinfo_vtable = mono_class_vtable (domain, System_Reflection_ParameterInfo);
6830         for (i = 0; i < sig->param_count; ++i) {
6831                 param = (MonoReflectionParameter *)mono_object_new_specific (pinfo_vtable);
6832                 MONO_OBJECT_SETREF (param, ClassImpl, mono_type_get_object (domain, sig->params [i]));
6833                 MONO_OBJECT_SETREF (param, MemberImpl, (MonoObject*)member);
6834                 MONO_OBJECT_SETREF (param, NameImpl, mono_string_new (domain, names [i]));
6835                 param->PositionImpl = i;
6836                 param->AttrsImpl = sig->params [i]->attrs;
6837
6838                 if (!(param->AttrsImpl & PARAM_ATTRIBUTE_HAS_DEFAULT)) {
6839                         if (param->AttrsImpl & PARAM_ATTRIBUTE_OPTIONAL)
6840                                 MONO_OBJECT_SETREF (param, DefaultValueImpl, get_reflection_missing (domain, &missing));
6841                         else
6842                                 MONO_OBJECT_SETREF (param, DefaultValueImpl, get_dbnull (domain, &dbnull));
6843                 } else {
6844
6845                         if (!blobs) {
6846                                 blobs = g_new0 (char *, sig->param_count);
6847                                 types = g_new0 (guint32, sig->param_count);
6848                                 get_default_param_value_blobs (method, blobs, types); 
6849                         }
6850
6851                         /* Build MonoType for the type from the Constant Table */
6852                         if (!type)
6853                                 type = g_new0 (MonoType, 1);
6854                         type->type = types [i];
6855                         type->data.klass = NULL;
6856                         if (types [i] == MONO_TYPE_CLASS)
6857                                 type->data.klass = mono_defaults.object_class;
6858                         else if ((sig->params [i]->type == MONO_TYPE_VALUETYPE) && sig->params [i]->data.klass->enumtype) {
6859                                 /* For enums, types [i] contains the base type */
6860
6861                                         type->type = MONO_TYPE_VALUETYPE;
6862                                         type->data.klass = mono_class_from_mono_type (sig->params [i]);
6863                         } else
6864                                 type->data.klass = mono_class_from_mono_type (type);
6865
6866                         MONO_OBJECT_SETREF (param, DefaultValueImpl, mono_get_object_from_blob (domain, type, blobs [i]));
6867
6868                         /* Type in the Constant table is MONO_TYPE_CLASS for nulls */
6869                         if (types [i] != MONO_TYPE_CLASS && !param->DefaultValueImpl) {
6870                                 if (param->AttrsImpl & PARAM_ATTRIBUTE_OPTIONAL)
6871                                         MONO_OBJECT_SETREF (param, DefaultValueImpl, get_reflection_missing (domain, &missing));
6872                                 else
6873                                         MONO_OBJECT_SETREF (param, DefaultValueImpl, get_dbnull (domain, &dbnull));
6874                         }
6875                         
6876                 }
6877
6878                 if (mspecs [i + 1])
6879                         MONO_OBJECT_SETREF (param, MarshalAsImpl, (MonoObject*)mono_reflection_marshal_as_attribute_from_marshal_spec (domain, method->klass, mspecs [i + 1]));
6880                 
6881                 mono_array_setref (res, i, param);
6882         }
6883         g_free (names);
6884         g_free (blobs);
6885         g_free (types);
6886         g_free (type);
6887
6888         for (i = mono_method_signature (method)->param_count; i >= 0; i--)
6889                 if (mspecs [i])
6890                         mono_metadata_free_marshal_spec (mspecs [i]);
6891         g_free (mspecs);
6892         
6893         CACHE_OBJECT (MonoArray *, &(method->signature), res, refclass);
6894 }
6895
6896 MonoArray*
6897 mono_param_get_objects (MonoDomain *domain, MonoMethod *method)
6898 {
6899         return mono_param_get_objects_internal (domain, method, NULL);
6900 }
6901
6902 /*
6903  * mono_method_body_get_object:
6904  * @domain: an app domain
6905  * @method: a method
6906  *
6907  * Return an System.Reflection.MethodBody object representing the method @method.
6908  */
6909 MonoReflectionMethodBody*
6910 mono_method_body_get_object (MonoDomain *domain, MonoMethod *method)
6911 {
6912         static MonoClass *System_Reflection_MethodBody = NULL;
6913         static MonoClass *System_Reflection_LocalVariableInfo = NULL;
6914         static MonoClass *System_Reflection_ExceptionHandlingClause = NULL;
6915         MonoReflectionMethodBody *ret;
6916         MonoMethodHeader *header;
6917         MonoImage *image;
6918         guint32 method_rva, local_var_sig_token;
6919     char *ptr;
6920         unsigned char format, flags;
6921         int i;
6922
6923         /* for compatibility with .net */
6924     if (method->dynamic)
6925         mono_raise_exception (mono_get_exception_invalid_operation (NULL));
6926
6927         if (!System_Reflection_MethodBody)
6928                 System_Reflection_MethodBody = mono_class_from_name (mono_defaults.corlib, "System.Reflection", "MethodBody");
6929         if (!System_Reflection_LocalVariableInfo)
6930                 System_Reflection_LocalVariableInfo = mono_class_from_name (mono_defaults.corlib, "System.Reflection", "LocalVariableInfo");
6931         if (!System_Reflection_ExceptionHandlingClause)
6932                 System_Reflection_ExceptionHandlingClause = mono_class_from_name (mono_defaults.corlib, "System.Reflection", "ExceptionHandlingClause");
6933
6934         CHECK_OBJECT (MonoReflectionMethodBody *, method, NULL);
6935
6936         if ((method->flags & METHOD_ATTRIBUTE_PINVOKE_IMPL) ||
6937                 (method->flags & METHOD_ATTRIBUTE_ABSTRACT) ||
6938             (method->iflags & METHOD_IMPL_ATTRIBUTE_INTERNAL_CALL) ||
6939             (method->iflags & METHOD_IMPL_ATTRIBUTE_RUNTIME))
6940                 return NULL;
6941
6942         image = method->klass->image;
6943         header = mono_method_get_header (method);
6944
6945         if (!image->dynamic) {
6946                 /* Obtain local vars signature token */
6947                 method_rva = mono_metadata_decode_row_col (&image->tables [MONO_TABLE_METHOD], mono_metadata_token_index (method->token) - 1, MONO_METHOD_RVA);
6948                 ptr = mono_image_rva_map (image, method_rva);
6949                 flags = *(const unsigned char *) ptr;
6950                 format = flags & METHOD_HEADER_FORMAT_MASK;
6951                 switch (format){
6952                 case METHOD_HEADER_TINY_FORMAT:
6953                         local_var_sig_token = 0;
6954                         break;
6955                 case METHOD_HEADER_FAT_FORMAT:
6956                         ptr += 2;
6957                         ptr += 2;
6958                         ptr += 4;
6959                         local_var_sig_token = read32 (ptr);
6960                         break;
6961                 default:
6962                         g_assert_not_reached ();
6963                 }
6964         } else
6965                 local_var_sig_token = 0; //FIXME
6966
6967         ret = (MonoReflectionMethodBody*)mono_object_new (domain, System_Reflection_MethodBody);
6968
6969         ret->init_locals = header->init_locals;
6970         ret->max_stack = header->max_stack;
6971         ret->local_var_sig_token = local_var_sig_token;
6972         MONO_OBJECT_SETREF (ret, il, mono_array_new_cached (domain, mono_defaults.byte_class, header->code_size));
6973         memcpy (mono_array_addr (ret->il, guint8, 0), header->code, header->code_size);
6974
6975         /* Locals */
6976         MONO_OBJECT_SETREF (ret, locals, mono_array_new_cached (domain, System_Reflection_LocalVariableInfo, header->num_locals));
6977         for (i = 0; i < header->num_locals; ++i) {
6978                 MonoReflectionLocalVariableInfo *info = (MonoReflectionLocalVariableInfo*)mono_object_new (domain, System_Reflection_LocalVariableInfo);
6979                 MONO_OBJECT_SETREF (info, local_type, mono_type_get_object (domain, header->locals [i]));
6980                 info->is_pinned = header->locals [i]->pinned;
6981                 info->local_index = i;
6982                 mono_array_setref (ret->locals, i, info);
6983         }
6984
6985         /* Exceptions */
6986         MONO_OBJECT_SETREF (ret, clauses, mono_array_new_cached (domain, System_Reflection_ExceptionHandlingClause, header->num_clauses));
6987         for (i = 0; i < header->num_clauses; ++i) {
6988                 MonoReflectionExceptionHandlingClause *info = (MonoReflectionExceptionHandlingClause*)mono_object_new (domain, System_Reflection_ExceptionHandlingClause);
6989                 MonoExceptionClause *clause = &header->clauses [i];
6990
6991                 info->flags = clause->flags;
6992                 info->try_offset = clause->try_offset;
6993                 info->try_length = clause->try_len;
6994                 info->handler_offset = clause->handler_offset;
6995                 info->handler_length = clause->handler_len;
6996                 if (clause->flags == MONO_EXCEPTION_CLAUSE_FILTER)
6997                         info->filter_offset = clause->data.filter_offset;
6998                 else if (clause->data.catch_class)
6999                         MONO_OBJECT_SETREF (info, catch_type, mono_type_get_object (mono_domain_get (), &clause->data.catch_class->byval_arg));
7000
7001                 mono_array_setref (ret->clauses, i, info);
7002         }
7003
7004         mono_metadata_free_mh (header);
7005         CACHE_OBJECT (MonoReflectionMethodBody *, method, ret, NULL);
7006         return ret;
7007 }
7008
7009 /**
7010  * mono_get_dbnull_object:
7011  * @domain: Domain where the object lives
7012  *
7013  * Returns the System.DBNull.Value singleton object
7014  *
7015  * Used as the value for ParameterInfo.DefaultValue 
7016  */
7017 MonoObject *
7018 mono_get_dbnull_object (MonoDomain *domain)
7019 {
7020         MonoObject *obj;
7021         static MonoClassField *dbnull_value_field = NULL;
7022         
7023         if (!dbnull_value_field) {
7024                 MonoClass *dbnull_klass;
7025                 dbnull_klass = mono_class_from_name (mono_defaults.corlib, "System", "DBNull");
7026                 mono_class_init (dbnull_klass);
7027                 dbnull_value_field = mono_class_get_field_from_name (dbnull_klass, "Value");
7028                 g_assert (dbnull_value_field);
7029         }
7030         obj = mono_field_get_value_object (domain, dbnull_value_field, NULL); 
7031         g_assert (obj);
7032         return obj;
7033 }
7034
7035 static void
7036 get_default_param_value_blobs (MonoMethod *method, char **blobs, guint32 *types)
7037 {
7038         guint32 param_index, i, lastp, crow = 0;
7039         guint32 param_cols [MONO_PARAM_SIZE], const_cols [MONO_CONSTANT_SIZE];
7040         gint32 idx;
7041
7042         MonoClass *klass = method->klass;
7043         MonoImage *image = klass->image;
7044         MonoMethodSignature *methodsig = mono_method_signature (method);
7045
7046         MonoTableInfo *constt;
7047         MonoTableInfo *methodt;
7048         MonoTableInfo *paramt;
7049
7050         if (!methodsig->param_count)
7051                 return;
7052
7053         mono_class_init (klass);
7054
7055         if (klass->image->dynamic) {
7056                 MonoReflectionMethodAux *aux;
7057                 if (method->is_inflated)
7058                         method = ((MonoMethodInflated*)method)->declaring;
7059                 aux = g_hash_table_lookup (((MonoDynamicImage*)method->klass->image)->method_aux_hash, method);
7060                 if (aux && aux->param_defaults) {
7061                         memcpy (blobs, &(aux->param_defaults [1]), methodsig->param_count * sizeof (char*));
7062                         memcpy (types, &(aux->param_default_types [1]), methodsig->param_count * sizeof (guint32));
7063                 }
7064                 return;
7065         }
7066
7067         methodt = &klass->image->tables [MONO_TABLE_METHOD];
7068         paramt = &klass->image->tables [MONO_TABLE_PARAM];
7069         constt = &image->tables [MONO_TABLE_CONSTANT];
7070
7071         idx = mono_method_get_index (method) - 1;
7072         g_assert (idx != -1);
7073
7074         param_index = mono_metadata_decode_row_col (methodt, idx, MONO_METHOD_PARAMLIST);
7075         if (idx + 1 < methodt->rows)
7076                 lastp = mono_metadata_decode_row_col (methodt, idx + 1, MONO_METHOD_PARAMLIST);
7077         else
7078                 lastp = paramt->rows + 1;
7079
7080         for (i = param_index; i < lastp; ++i) {
7081                 guint32 paramseq;
7082
7083                 mono_metadata_decode_row (paramt, i - 1, param_cols, MONO_PARAM_SIZE);
7084                 paramseq = param_cols [MONO_PARAM_SEQUENCE];
7085
7086                 if (!(param_cols [MONO_PARAM_FLAGS] & PARAM_ATTRIBUTE_HAS_DEFAULT))
7087                         continue;
7088
7089                 crow = mono_metadata_get_constant_index (image, MONO_TOKEN_PARAM_DEF | i, crow + 1);
7090                 if (!crow) {
7091                         continue;
7092                 }
7093         
7094                 mono_metadata_decode_row (constt, crow - 1, const_cols, MONO_CONSTANT_SIZE);
7095                 blobs [paramseq - 1] = (gpointer) mono_metadata_blob_heap (image, const_cols [MONO_CONSTANT_VALUE]);
7096                 types [paramseq - 1] = const_cols [MONO_CONSTANT_TYPE];
7097         }
7098
7099         return;
7100 }
7101
7102 MonoObject *
7103 mono_get_object_from_blob (MonoDomain *domain, MonoType *type, const char *blob)
7104 {
7105         void *retval;
7106         MonoClass *klass;
7107         MonoObject *object;
7108         MonoType *basetype = type;
7109
7110         if (!blob)
7111                 return NULL;
7112         
7113         klass = mono_class_from_mono_type (type);
7114         if (klass->valuetype) {
7115                 object = mono_object_new (domain, klass);
7116                 retval = ((gchar *) object + sizeof (MonoObject));
7117                 if (klass->enumtype)
7118                         basetype = mono_class_enum_basetype (klass);
7119         } else {
7120                 retval = &object;
7121         }
7122                         
7123         if (!mono_get_constant_value_from_blob (domain, basetype->type,  blob, retval))
7124                 return object;
7125         else
7126                 return NULL;
7127 }
7128
7129 static int
7130 assembly_name_to_aname (MonoAssemblyName *assembly, char *p) {
7131         int found_sep;
7132         char *s;
7133         gboolean quoted = FALSE;
7134
7135         memset (assembly, 0, sizeof (MonoAssemblyName));
7136         assembly->culture = "";
7137         memset (assembly->public_key_token, 0, MONO_PUBLIC_KEY_TOKEN_LENGTH);
7138
7139         if (*p == '"') {
7140                 quoted = TRUE;
7141                 p++;
7142         }
7143         assembly->name = p;
7144         while (*p && (isalnum (*p) || *p == '.' || *p == '-' || *p == '_' || *p == '$' || *p == '@' || g_ascii_isspace (*p)))
7145                 p++;
7146         if (quoted) {
7147                 if (*p != '"')
7148                         return 1;
7149                 *p = 0;
7150                 p++;
7151         }
7152         if (*p != ',')
7153                 return 1;
7154         *p = 0;
7155         /* Remove trailing whitespace */
7156         s = p - 1;
7157         while (*s && g_ascii_isspace (*s))
7158                 *s-- = 0;
7159         p ++;
7160         while (g_ascii_isspace (*p))
7161                 p++;
7162         while (*p) {
7163                 if (*p == 'V' && g_ascii_strncasecmp (p, "Version=", 8) == 0) {
7164                         p += 8;
7165                         assembly->major = strtoul (p, &s, 10);
7166                         if (s == p || *s != '.')
7167                                 return 1;
7168                         p = ++s;
7169                         assembly->minor = strtoul (p, &s, 10);
7170                         if (s == p || *s != '.')
7171                                 return 1;
7172                         p = ++s;
7173                         assembly->build = strtoul (p, &s, 10);
7174                         if (s == p || *s != '.')
7175                                 return 1;
7176                         p = ++s;
7177                         assembly->revision = strtoul (p, &s, 10);
7178                         if (s == p)
7179                                 return 1;
7180                         p = s;
7181                 } else if (*p == 'C' && g_ascii_strncasecmp (p, "Culture=", 8) == 0) {
7182                         p += 8;
7183                         if (g_ascii_strncasecmp (p, "neutral", 7) == 0) {
7184                                 assembly->culture = "";
7185                                 p += 7;
7186                         } else {
7187                                 assembly->culture = p;
7188                                 while (*p && *p != ',') {
7189                                         p++;
7190                                 }
7191                         }
7192                 } else if (*p == 'P' && g_ascii_strncasecmp (p, "PublicKeyToken=", 15) == 0) {
7193                         p += 15;
7194                         if (strncmp (p, "null", 4) == 0) {
7195                                 p += 4;
7196                         } else {
7197                                 int len;
7198                                 gchar *start = p;
7199                                 while (*p && *p != ',') {
7200                                         p++;
7201                                 }
7202                                 len = (p - start + 1);
7203                                 if (len > MONO_PUBLIC_KEY_TOKEN_LENGTH)
7204                                         len = MONO_PUBLIC_KEY_TOKEN_LENGTH;
7205                                 g_strlcpy ((char*)assembly->public_key_token, start, len);
7206                         }
7207                 } else {
7208                         while (*p && *p != ',')
7209                                 p++;
7210                 }
7211                 found_sep = 0;
7212                 while (g_ascii_isspace (*p) || *p == ',') {
7213                         *p++ = 0;
7214                         found_sep = 1;
7215                         continue;
7216                 }
7217                 /* failed */
7218                 if (!found_sep)
7219                         return 1;
7220         }
7221
7222         return 0;
7223 }
7224
7225 /*
7226  * mono_reflection_parse_type:
7227  * @name: type name
7228  *
7229  * Parse a type name as accepted by the GetType () method and output the info
7230  * extracted in the info structure.
7231  * the name param will be mangled, so, make a copy before passing it to this function.
7232  * The fields in info will be valid until the memory pointed to by name is valid.
7233  *
7234  * See also mono_type_get_name () below.
7235  *
7236  * Returns: 0 on parse error.
7237  */
7238 static int
7239 _mono_reflection_parse_type (char *name, char **endptr, gboolean is_recursed,
7240                              MonoTypeNameParse *info)
7241 {
7242         char *start, *p, *w, *last_point, *startn;
7243         int in_modifiers = 0;
7244         int isbyref = 0, rank = 0;
7245
7246         start = p = w = name;
7247
7248         //FIXME could we just zero the whole struct? memset (&info, 0, sizeof (MonoTypeNameParse))
7249         memset (&info->assembly, 0, sizeof (MonoAssemblyName));
7250         info->name = info->name_space = NULL;
7251         info->nested = NULL;
7252         info->modifiers = NULL;
7253         info->type_arguments = NULL;
7254
7255         /* last_point separates the namespace from the name */
7256         last_point = NULL;
7257         /* Skips spaces */
7258         while (*p == ' ') p++, start++, w++, name++;
7259
7260         while (*p) {
7261                 switch (*p) {
7262                 case '+':
7263                         *p = 0; /* NULL terminate the name */
7264                         startn = p + 1;
7265                         info->nested = g_list_append (info->nested, startn);
7266                         /* we have parsed the nesting namespace + name */
7267                         if (info->name)
7268                                 break;
7269                         if (last_point) {
7270                                 info->name_space = start;
7271                                 *last_point = 0;
7272                                 info->name = last_point + 1;
7273                         } else {
7274                                 info->name_space = (char *)"";
7275                                 info->name = start;
7276                         }
7277                         break;
7278                 case '.':
7279                         last_point = p;
7280                         break;
7281                 case '\\':
7282                         ++p;
7283                         break;
7284                 case '&':
7285                 case '*':
7286                 case '[':
7287                 case ',':
7288                 case ']':
7289                         in_modifiers = 1;
7290                         break;
7291                 default:
7292                         break;
7293                 }
7294                 if (in_modifiers)
7295                         break;
7296                 // *w++ = *p++;
7297                 p++;
7298         }
7299         
7300         if (!info->name) {
7301                 if (last_point) {
7302                         info->name_space = start;
7303                         *last_point = 0;
7304                         info->name = last_point + 1;
7305                 } else {
7306                         info->name_space = (char *)"";
7307                         info->name = start;
7308                 }
7309         }
7310         while (*p) {
7311                 switch (*p) {
7312                 case '&':
7313                         if (isbyref) /* only one level allowed by the spec */
7314                                 return 0;
7315                         isbyref = 1;
7316                         info->modifiers = g_list_append (info->modifiers, GUINT_TO_POINTER (0));
7317                         *p++ = 0;
7318                         break;
7319                 case '*':
7320                         info->modifiers = g_list_append (info->modifiers, GUINT_TO_POINTER (-1));
7321                         *p++ = 0;
7322                         break;
7323                 case '[':
7324                         //Decide if it's an array of a generic argument list
7325                         *p++ = 0;
7326
7327                         if (!*p) //XXX test
7328                                 return 0;
7329                         if (*p  == ',' || *p == '*' || *p == ']') { //array
7330                                 rank = 1;
7331                                 while (*p) {
7332                                         if (*p == ']')
7333                                                 break;
7334                                         if (*p == ',')
7335                                                 rank++;
7336                                         else if (*p == '*') /* '*' means unknown lower bound */
7337                                                 info->modifiers = g_list_append (info->modifiers, GUINT_TO_POINTER (-2));
7338                                         else
7339                                                 return 0;
7340                                         ++p;
7341                                 }
7342                                 if (*p++ != ']')
7343                                         return 0;
7344                                 info->modifiers = g_list_append (info->modifiers, GUINT_TO_POINTER (rank));
7345                         } else {
7346                                 if (rank) /* generic args after array spec*/ //XXX test
7347                                         return 0;
7348                                 info->type_arguments = g_ptr_array_new ();
7349                                 while (*p) {
7350                                         MonoTypeNameParse *subinfo = g_new0 (MonoTypeNameParse, 1);
7351                                         gboolean fqname = FALSE;
7352
7353                                         g_ptr_array_add (info->type_arguments, subinfo);
7354
7355                                         if (*p == '[') {
7356                                                 p++;
7357                                                 fqname = TRUE;
7358                                         }
7359
7360                                         if (!_mono_reflection_parse_type (p, &p, TRUE, subinfo))
7361                                                 return 0;
7362
7363                                         /*MS is lenient on [] delimited parameters that aren't fqn - and F# uses them.*/
7364                                         if (fqname && (*p != ']')) {
7365                                                 char *aname;
7366
7367                                                 if (*p != ',')
7368                                                         return 0;
7369                                                 *p++ = 0;
7370
7371                                                 aname = p;
7372                                                 while (*p && (*p != ']'))
7373                                                         p++;
7374
7375                                                 if (*p != ']')
7376                                                         return 0;
7377
7378                                                 *p++ = 0;
7379                                                 while (*aname) {
7380                                                         if (g_ascii_isspace (*aname)) {
7381                                                                 ++aname;
7382                                                                 continue;
7383                                                         }
7384                                                         break;
7385                                                 }
7386                                                 if (!*aname ||
7387                                                     !assembly_name_to_aname (&subinfo->assembly, aname))
7388                                                         return 0;
7389                                         } else if (fqname && (*p == ']')) {
7390                                                 *p++ = 0;
7391                                         }
7392                                         if (*p == ']') {
7393                                                 *p++ = 0;
7394                                                 break;
7395                                         } else if (!*p) {
7396                                                 return 0;
7397                                         }
7398                                         *p++ = 0;
7399                                 }
7400                         }
7401                         break;
7402                 case ']':
7403                         if (is_recursed)
7404                                 goto end;
7405                         return 0;
7406                 case ',':
7407                         if (is_recursed)
7408                                 goto end;
7409                         *p++ = 0;
7410                         while (*p) {
7411                                 if (g_ascii_isspace (*p)) {
7412                                         ++p;
7413                                         continue;
7414                                 }
7415                                 break;
7416                         }
7417                         if (!*p)
7418                                 return 0; /* missing assembly name */
7419                         if (!assembly_name_to_aname (&info->assembly, p))
7420                                 return 0;
7421                         break;
7422                 default:
7423                         return 0;
7424                 }
7425                 if (info->assembly.name)
7426                         break;
7427         }
7428         // *w = 0; /* terminate class name */
7429  end:
7430         if (!info->name || !*info->name)
7431                 return 0;
7432         if (endptr)
7433                 *endptr = p;
7434         /* add other consistency checks */
7435         return 1;
7436 }
7437
7438 int
7439 mono_reflection_parse_type (char *name, MonoTypeNameParse *info)
7440 {
7441         return _mono_reflection_parse_type (name, NULL, FALSE, info);
7442 }
7443
7444 static MonoType*
7445 _mono_reflection_get_type_from_info (MonoTypeNameParse *info, MonoImage *image, gboolean ignorecase)
7446 {
7447         gboolean type_resolve = FALSE;
7448         MonoType *type;
7449         MonoImage *rootimage = image;
7450
7451         if (info->assembly.name) {
7452                 MonoAssembly *assembly = mono_assembly_loaded (&info->assembly);
7453                 if (!assembly && image && image->assembly && mono_assembly_names_equal (&info->assembly, &image->assembly->aname))
7454                         /* 
7455                          * This could happen in the AOT compiler case when the search hook is not
7456                          * installed.
7457                          */
7458                         assembly = image->assembly;
7459                 if (!assembly) {
7460                         /* then we must load the assembly ourselve - see #60439 */
7461                         assembly = mono_assembly_load (&info->assembly, NULL, NULL);
7462                         if (!assembly)
7463                                 return NULL;
7464                 }
7465                 image = assembly->image;
7466         } else if (!image) {
7467                 image = mono_defaults.corlib;
7468         }
7469
7470         type = mono_reflection_get_type_with_rootimage (rootimage, image, info, ignorecase, &type_resolve);
7471         if (type == NULL && !info->assembly.name && image != mono_defaults.corlib) {
7472                 image = mono_defaults.corlib;
7473                 type = mono_reflection_get_type_with_rootimage (rootimage, image, info, ignorecase, &type_resolve);
7474         }
7475
7476         return type;
7477 }
7478
7479 static MonoType*
7480 mono_reflection_get_type_internal (MonoImage *rootimage, MonoImage* image, MonoTypeNameParse *info, gboolean ignorecase)
7481 {
7482         MonoClass *klass;
7483         GList *mod;
7484         int modval;
7485         gboolean bounded = FALSE;
7486         
7487         if (!image)
7488                 image = mono_defaults.corlib;
7489
7490         if (ignorecase)
7491                 klass = mono_class_from_name_case (image, info->name_space, info->name);
7492         else
7493                 klass = mono_class_from_name (image, info->name_space, info->name);
7494         if (!klass)
7495                 return NULL;
7496         for (mod = info->nested; mod; mod = mod->next) {
7497                 gpointer iter = NULL;
7498                 MonoClass *parent;
7499
7500                 parent = klass;
7501                 mono_class_init (parent);
7502
7503                 while ((klass = mono_class_get_nested_types (parent, &iter))) {
7504                         if (ignorecase) {
7505                                 if (mono_utf8_strcasecmp (klass->name, mod->data) == 0)
7506                                         break;
7507                         } else {
7508                                 if (strcmp (klass->name, mod->data) == 0)
7509                                         break;
7510                         }
7511                 }
7512                 if (!klass)
7513                         break;
7514         }
7515         if (!klass)
7516                 return NULL;
7517
7518         if (info->type_arguments) {
7519                 MonoType **type_args = g_new0 (MonoType *, info->type_arguments->len);
7520                 MonoReflectionType *the_type;
7521                 MonoType *instance;
7522                 int i;
7523
7524                 for (i = 0; i < info->type_arguments->len; i++) {
7525                         MonoTypeNameParse *subinfo = g_ptr_array_index (info->type_arguments, i);
7526
7527                         type_args [i] = _mono_reflection_get_type_from_info (subinfo, rootimage, ignorecase);
7528                         if (!type_args [i]) {
7529                                 g_free (type_args);
7530                                 return NULL;
7531                         }
7532                 }
7533
7534                 the_type = mono_type_get_object (mono_domain_get (), &klass->byval_arg);
7535
7536                 instance = mono_reflection_bind_generic_parameters (
7537                         the_type, info->type_arguments->len, type_args);
7538
7539                 g_free (type_args);
7540                 if (!instance)
7541                         return NULL;
7542
7543                 klass = mono_class_from_mono_type (instance);
7544         }
7545
7546         for (mod = info->modifiers; mod; mod = mod->next) {
7547                 modval = GPOINTER_TO_UINT (mod->data);
7548                 if (!modval) { /* byref: must be last modifier */
7549                         return &klass->this_arg;
7550                 } else if (modval == -1) {
7551                         klass = mono_ptr_class_get (&klass->byval_arg);
7552                 } else if (modval == -2) {
7553                         bounded = TRUE;
7554                 } else { /* array rank */
7555                         klass = mono_bounded_array_class_get (klass, modval, bounded);
7556                 }
7557         }
7558
7559         return &klass->byval_arg;
7560 }
7561
7562 /*
7563  * mono_reflection_get_type:
7564  * @image: a metadata context
7565  * @info: type description structure
7566  * @ignorecase: flag for case-insensitive string compares
7567  * @type_resolve: whenever type resolve was already tried
7568  *
7569  * Build a MonoType from the type description in @info.
7570  * 
7571  */
7572
7573 MonoType*
7574 mono_reflection_get_type (MonoImage* image, MonoTypeNameParse *info, gboolean ignorecase, gboolean *type_resolve) {
7575         return mono_reflection_get_type_with_rootimage(image, image, info, ignorecase, type_resolve);
7576 }
7577
7578 static MonoType*
7579 mono_reflection_get_type_internal_dynamic (MonoImage *rootimage, MonoAssembly *assembly, MonoTypeNameParse *info, gboolean ignorecase)
7580 {
7581         MonoReflectionAssemblyBuilder *abuilder;
7582         MonoType *type;
7583         int i;
7584
7585         g_assert (assembly->dynamic);
7586         abuilder = (MonoReflectionAssemblyBuilder*)mono_assembly_get_object (((MonoDynamicAssembly*)assembly)->domain, assembly);
7587
7588         /* Enumerate all modules */
7589
7590         type = NULL;
7591         if (abuilder->modules) {
7592                 for (i = 0; i < mono_array_length (abuilder->modules); ++i) {
7593                         MonoReflectionModuleBuilder *mb = mono_array_get (abuilder->modules, MonoReflectionModuleBuilder*, i);
7594                         type = mono_reflection_get_type_internal (rootimage, &mb->dynamic_image->image, info, ignorecase);
7595                         if (type)
7596                                 break;
7597                 }
7598         }
7599
7600         if (!type && abuilder->loaded_modules) {
7601                 for (i = 0; i < mono_array_length (abuilder->loaded_modules); ++i) {
7602                         MonoReflectionModule *mod = mono_array_get (abuilder->loaded_modules, MonoReflectionModule*, i);
7603                         type = mono_reflection_get_type_internal (rootimage, mod->image, info, ignorecase);
7604                         if (type)
7605                                 break;
7606                 }
7607         }
7608
7609         return type;
7610 }
7611         
7612 MonoType*
7613 mono_reflection_get_type_with_rootimage (MonoImage *rootimage, MonoImage* image, MonoTypeNameParse *info, gboolean ignorecase, gboolean *type_resolve)
7614 {
7615         MonoType *type;
7616         MonoReflectionAssembly *assembly;
7617         GString *fullName;
7618         GList *mod;
7619
7620         if (image && image->dynamic)
7621                 type = mono_reflection_get_type_internal_dynamic (rootimage, image->assembly, info, ignorecase);
7622         else
7623                 type = mono_reflection_get_type_internal (rootimage, image, info, ignorecase);
7624         if (type)
7625                 return type;
7626         if (!mono_domain_has_type_resolve (mono_domain_get ()))
7627                 return NULL;
7628
7629         if (type_resolve) {
7630                 if (*type_resolve) 
7631                         return NULL;
7632                 else
7633                         *type_resolve = TRUE;
7634         }
7635         
7636         /* Reconstruct the type name */
7637         fullName = g_string_new ("");
7638         if (info->name_space && (info->name_space [0] != '\0'))
7639                 g_string_printf (fullName, "%s.%s", info->name_space, info->name);
7640         else
7641                 g_string_printf (fullName, "%s", info->name);
7642         for (mod = info->nested; mod; mod = mod->next)
7643                 g_string_append_printf (fullName, "+%s", (char*)mod->data);
7644
7645         assembly = mono_domain_try_type_resolve ( mono_domain_get (), fullName->str, NULL);
7646         if (assembly) {
7647                 if (assembly->assembly->dynamic)
7648                         type = mono_reflection_get_type_internal_dynamic (rootimage, assembly->assembly, info, ignorecase);
7649                 else
7650                         type = mono_reflection_get_type_internal (rootimage, assembly->assembly->image, 
7651                                                                                                           info, ignorecase);
7652         }
7653         g_string_free (fullName, TRUE);
7654         return type;
7655 }
7656
7657 void
7658 mono_reflection_free_type_info (MonoTypeNameParse *info)
7659 {
7660         g_list_free (info->modifiers);
7661         g_list_free (info->nested);
7662
7663         if (info->type_arguments) {
7664                 int i;
7665
7666                 for (i = 0; i < info->type_arguments->len; i++) {
7667                         MonoTypeNameParse *subinfo = g_ptr_array_index (info->type_arguments, i);
7668
7669                         mono_reflection_free_type_info (subinfo);
7670                         /*We free the subinfo since it is allocated by _mono_reflection_parse_type*/
7671                         g_free (subinfo);
7672                 }
7673
7674                 g_ptr_array_free (info->type_arguments, TRUE);
7675         }
7676 }
7677
7678 /*
7679  * mono_reflection_type_from_name:
7680  * @name: type name.
7681  * @image: a metadata context (can be NULL).
7682  *
7683  * Retrieves a MonoType from its @name. If the name is not fully qualified,
7684  * it defaults to get the type from @image or, if @image is NULL or loading
7685  * from it fails, uses corlib.
7686  * 
7687  */
7688 MonoType*
7689 mono_reflection_type_from_name (char *name, MonoImage *image)
7690 {
7691         MonoType *type = NULL;
7692         MonoTypeNameParse info;
7693         char *tmp;
7694
7695         /* Make a copy since parse_type modifies its argument */
7696         tmp = g_strdup (name);
7697         
7698         /*g_print ("requested type %s\n", str);*/
7699         if (mono_reflection_parse_type (tmp, &info)) {
7700                 type = _mono_reflection_get_type_from_info (&info, image, FALSE);
7701         }
7702
7703         g_free (tmp);
7704         mono_reflection_free_type_info (&info);
7705         return type;
7706 }
7707
7708 /*
7709  * mono_reflection_get_token:
7710  *
7711  *   Return the metadata token of OBJ which should be an object
7712  * representing a metadata element.
7713  */
7714 guint32
7715 mono_reflection_get_token (MonoObject *obj)
7716 {
7717         MonoClass *klass;
7718         guint32 token = 0;
7719
7720         klass = obj->vtable->klass;
7721
7722         if (strcmp (klass->name, "MethodBuilder") == 0) {
7723                 MonoReflectionMethodBuilder *mb = (MonoReflectionMethodBuilder *)obj;
7724
7725                 token = mb->table_idx | MONO_TOKEN_METHOD_DEF;
7726         } else if (strcmp (klass->name, "ConstructorBuilder") == 0) {
7727                 MonoReflectionCtorBuilder *mb = (MonoReflectionCtorBuilder *)obj;
7728
7729                 token = mb->table_idx | MONO_TOKEN_METHOD_DEF;
7730         } else if (strcmp (klass->name, "FieldBuilder") == 0) {
7731                 MonoReflectionFieldBuilder *fb = (MonoReflectionFieldBuilder *)obj;
7732
7733                 token = fb->table_idx | MONO_TOKEN_FIELD_DEF;
7734         } else if (strcmp (klass->name, "TypeBuilder") == 0) {
7735                 MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder *)obj;
7736                 token = tb->table_idx | MONO_TOKEN_TYPE_DEF;
7737         } else if (strcmp (klass->name, "MonoType") == 0) {
7738                 MonoType *type = mono_reflection_type_get_handle ((MonoReflectionType*)obj);
7739                 MonoClass *mc = mono_class_from_mono_type (type);
7740                 if (!mono_class_init (mc))
7741                         mono_raise_exception (mono_class_get_exception_for_failure (mc));
7742
7743                 token = mc->type_token;
7744         } else if (strcmp (klass->name, "MonoCMethod") == 0 ||
7745                    strcmp (klass->name, "MonoMethod") == 0 ||
7746                    strcmp (klass->name, "MonoGenericMethod") == 0 ||
7747                    strcmp (klass->name, "MonoGenericCMethod") == 0) {
7748                 MonoReflectionMethod *m = (MonoReflectionMethod *)obj;
7749                 if (m->method->is_inflated) {
7750                         MonoMethodInflated *inflated = (MonoMethodInflated *) m->method;
7751                         return inflated->declaring->token;
7752                 } else {
7753                         token = m->method->token;
7754                 }
7755         } else if (strcmp (klass->name, "MonoField") == 0) {
7756                 MonoReflectionField *f = (MonoReflectionField*)obj;
7757
7758                 if (is_field_on_inst (f->field)) {
7759                         MonoDynamicGenericClass *dgclass = (MonoDynamicGenericClass*)f->field->parent->generic_class;
7760                         int field_index = f->field - dgclass->fields;
7761                         MonoObject *obj;
7762
7763                         g_assert (field_index >= 0 && field_index < dgclass->count_fields);
7764                         obj = dgclass->field_objects [field_index];
7765                         return mono_reflection_get_token (obj);
7766                 }
7767                 token = mono_class_get_field_token (f->field);
7768         } else if (strcmp (klass->name, "MonoProperty") == 0) {
7769                 MonoReflectionProperty *p = (MonoReflectionProperty*)obj;
7770
7771                 token = mono_class_get_property_token (p->property);
7772         } else if (strcmp (klass->name, "MonoEvent") == 0) {
7773                 MonoReflectionMonoEvent *p = (MonoReflectionMonoEvent*)obj;
7774
7775                 token = mono_class_get_event_token (p->event);
7776         } else if (strcmp (klass->name, "ParameterInfo") == 0 || strcmp (klass->name, "MonoParameterInfo") == 0) {
7777                 MonoReflectionParameter *p = (MonoReflectionParameter*)obj;
7778                 MonoClass *member_class = mono_object_class (p->MemberImpl);
7779                 g_assert (mono_class_is_reflection_method_or_constructor (member_class));
7780
7781                 token = mono_method_get_param_token (((MonoReflectionMethod*)p->MemberImpl)->method, p->PositionImpl);
7782         } else if (strcmp (klass->name, "Module") == 0 || strcmp (klass->name, "MonoModule") == 0) {
7783                 MonoReflectionModule *m = (MonoReflectionModule*)obj;
7784
7785                 token = m->token;
7786         } else if (strcmp (klass->name, "Assembly") == 0 || strcmp (klass->name, "MonoAssembly") == 0) {
7787                 token = mono_metadata_make_token (MONO_TABLE_ASSEMBLY, 1);
7788         } else {
7789                 gchar *msg = g_strdup_printf ("MetadataToken is not supported for type '%s.%s'", klass->name_space, klass->name);
7790                 MonoException *ex = mono_get_exception_not_implemented (msg);
7791                 g_free (msg);
7792                 mono_raise_exception (ex);
7793         }
7794
7795         return token;
7796 }
7797
7798 static MonoClass*
7799 load_cattr_enum_type (MonoImage *image, const char *p, const char **end, MonoError *error)
7800 {
7801         char *n;
7802         MonoType *t;
7803         int slen = mono_metadata_decode_value (p, &p);
7804
7805         mono_error_init (error);
7806
7807         n = g_memdup (p, slen + 1);
7808         n [slen] = 0;
7809         t = mono_reflection_type_from_name (n, image);
7810         if (!t) {
7811                 /* FIXME the error should come from mono_reflection_type_from_name as it will have type/assembly names split */
7812                 /* We don't free n, it's consumed by mono_error */
7813                 mono_error_set_type_load_name (error, n, NULL, "Could not load enum type %s while decoding custom attribute", n);
7814                 return NULL;
7815         }
7816         g_free (n);
7817         p += slen;
7818         *end = p;
7819         return mono_class_from_mono_type (t);
7820 }
7821
7822 static void*
7823 load_cattr_value (MonoImage *image, MonoType *t, const char *p, const char **end, MonoError *error)
7824 {
7825         int slen, type = t->type;
7826         MonoClass *tklass = t->data.klass;
7827
7828         mono_error_init (error);
7829
7830 handle_enum:
7831         switch (type) {
7832         case MONO_TYPE_U1:
7833         case MONO_TYPE_I1:
7834         case MONO_TYPE_BOOLEAN: {
7835                 MonoBoolean *bval = g_malloc (sizeof (MonoBoolean));
7836                 *bval = *p;
7837                 *end = p + 1;
7838                 return bval;
7839         }
7840         case MONO_TYPE_CHAR:
7841         case MONO_TYPE_U2:
7842         case MONO_TYPE_I2: {
7843                 guint16 *val = g_malloc (sizeof (guint16));
7844                 *val = read16 (p);
7845                 *end = p + 2;
7846                 return val;
7847         }
7848 #if SIZEOF_VOID_P == 4
7849         case MONO_TYPE_U:
7850         case MONO_TYPE_I:
7851 #endif
7852         case MONO_TYPE_R4:
7853         case MONO_TYPE_U4:
7854         case MONO_TYPE_I4: {
7855                 guint32 *val = g_malloc (sizeof (guint32));
7856                 *val = read32 (p);
7857                 *end = p + 4;
7858                 return val;
7859         }
7860 #if SIZEOF_VOID_P == 8
7861         case MONO_TYPE_U: /* error out instead? this should probably not happen */
7862         case MONO_TYPE_I:
7863 #endif
7864         case MONO_TYPE_U8:
7865         case MONO_TYPE_I8: {
7866                 guint64 *val = g_malloc (sizeof (guint64));
7867                 *val = read64 (p);
7868                 *end = p + 8;
7869                 return val;
7870         }
7871         case MONO_TYPE_R8: {
7872                 double *val = g_malloc (sizeof (double));
7873                 readr8 (p, val);
7874                 *end = p + 8;
7875                 return val;
7876         }
7877         case MONO_TYPE_VALUETYPE:
7878                 if (t->data.klass->enumtype) {
7879                         type = mono_class_enum_basetype (t->data.klass)->type;
7880                         goto handle_enum;
7881                 } else {
7882                         MonoClass *k =  t->data.klass;
7883                         
7884                         if (mono_is_corlib_image (k->image) && strcmp (k->name_space, "System") == 0 && strcmp (k->name, "DateTime") == 0){
7885                                 guint64 *val = g_malloc (sizeof (guint64));
7886                                 *val = read64 (p);
7887                                 *end = p + 8;
7888                                 return val;
7889                         }
7890                 }
7891                 g_error ("generic valutype %s not handled in custom attr value decoding", t->data.klass->name);
7892                 break;
7893                 
7894         case MONO_TYPE_STRING:
7895                 if (*p == (char)0xFF) {
7896                         *end = p + 1;
7897                         return NULL;
7898                 }
7899                 slen = mono_metadata_decode_value (p, &p);
7900                 *end = p + slen;
7901                 return mono_string_new_len (mono_domain_get (), p, slen);
7902         case MONO_TYPE_CLASS: {
7903                 char *n;
7904                 MonoType *t;
7905                 if (*p == (char)0xFF) {
7906                         *end = p + 1;
7907                         return NULL;
7908                 }
7909 handle_type:
7910                 slen = mono_metadata_decode_value (p, &p);
7911                 n = g_memdup (p, slen + 1);
7912                 n [slen] = 0;
7913                 t = mono_reflection_type_from_name (n, image);
7914                 if (!t) {
7915                         /* FIXME the error should come from mono_reflection_type_from_name as it will have type/assembly names split */
7916                         /* We don't free n, it's consumed by mono_error */
7917                         mono_error_set_type_load_name (error, n, NULL, "Could not load type %s while decoding custom attribute", n);
7918                         return NULL;
7919                 }
7920                 g_free (n);
7921                 *end = p + slen;
7922                 return mono_type_get_object (mono_domain_get (), t);
7923         }
7924         case MONO_TYPE_OBJECT: {
7925                 char subt = *p++;
7926                 MonoObject *obj;
7927                 MonoClass *subc = NULL;
7928                 void *val;
7929
7930                 if (subt == 0x50) {
7931                         goto handle_type;
7932                 } else if (subt == 0x0E) {
7933                         type = MONO_TYPE_STRING;
7934                         goto handle_enum;
7935                 } else if (subt == 0x1D) {
7936                         MonoType simple_type = {{0}};
7937                         int etype = *p;
7938                         p ++;
7939
7940                         type = MONO_TYPE_SZARRAY;
7941                         if (etype == 0x50) {
7942                                 tklass = mono_defaults.systemtype_class;
7943                         } else if (etype == 0x55) {
7944                                 tklass = load_cattr_enum_type (image, p, &p, error);
7945                                 if (!mono_error_ok (error))
7946                                         return NULL;
7947                         } else {
7948                                 if (etype == 0x51)
7949                                         /* See Partition II, Appendix B3 */
7950                                         etype = MONO_TYPE_OBJECT;
7951                                 simple_type.type = etype;
7952                                 tklass = mono_class_from_mono_type (&simple_type);
7953                         }
7954                         goto handle_enum;
7955                 } else if (subt == 0x55) {
7956                         char *n;
7957                         MonoType *t;
7958                         slen = mono_metadata_decode_value (p, &p);
7959                         n = g_memdup (p, slen + 1);
7960                         n [slen] = 0;
7961                         t = mono_reflection_type_from_name (n, image);
7962                         if (!t) {
7963                                 /* FIXME the error should come from mono_reflection_type_from_name as it will have type/assembly names split */
7964                                 /* We don't free n, it's consumed by mono_error */
7965                                 mono_error_set_type_load_name (error, n, NULL, "Could not load type %s while decoding custom attribute", n);
7966                                 return NULL;
7967                         }
7968                         g_free (n);
7969                         p += slen;
7970                         subc = mono_class_from_mono_type (t);
7971                 } else if (subt >= MONO_TYPE_BOOLEAN && subt <= MONO_TYPE_R8) {
7972                         MonoType simple_type = {{0}};
7973                         simple_type.type = subt;
7974                         subc = mono_class_from_mono_type (&simple_type);
7975                 } else {
7976                         g_error ("Unknown type 0x%02x for object type encoding in custom attr", subt);
7977                 }
7978                 val = load_cattr_value (image, &subc->byval_arg, p, end, error);
7979                 obj = NULL;
7980                 if (mono_error_ok (error)) {
7981                         obj = mono_object_new (mono_domain_get (), subc);
7982                         g_assert (!subc->has_references);
7983                         mono_gc_memmove_atomic ((char*)obj + sizeof (MonoObject), val, mono_class_value_size (subc, NULL));
7984                 }
7985
7986                 g_free (val);
7987                 return obj;
7988         }
7989         case MONO_TYPE_SZARRAY: {
7990                 MonoArray *arr;
7991                 guint32 i, alen, basetype;
7992                 alen = read32 (p);
7993                 p += 4;
7994                 if (alen == 0xffffffff) {
7995                         *end = p;
7996                         return NULL;
7997                 }
7998                 arr = mono_array_new (mono_domain_get(), tklass, alen);
7999                 basetype = tklass->byval_arg.type;
8000                 if (basetype == MONO_TYPE_VALUETYPE && tklass->enumtype)
8001                         basetype = mono_class_enum_basetype (tklass)->type;
8002                 switch (basetype)
8003                 {
8004                         case MONO_TYPE_U1:
8005                         case MONO_TYPE_I1:
8006                         case MONO_TYPE_BOOLEAN:
8007                                 for (i = 0; i < alen; i++) {
8008                                         MonoBoolean val = *p++;
8009                                         mono_array_set (arr, MonoBoolean, i, val);
8010                                 }
8011                                 break;
8012                         case MONO_TYPE_CHAR:
8013                         case MONO_TYPE_U2:
8014                         case MONO_TYPE_I2:
8015                                 for (i = 0; i < alen; i++) {
8016                                         guint16 val = read16 (p);
8017                                         mono_array_set (arr, guint16, i, val);
8018                                         p += 2;
8019                                 }
8020                                 break;
8021                         case MONO_TYPE_R4:
8022                         case MONO_TYPE_U4:
8023                         case MONO_TYPE_I4:
8024                                 for (i = 0; i < alen; i++) {
8025                                         guint32 val = read32 (p);
8026                                         mono_array_set (arr, guint32, i, val);
8027                                         p += 4;
8028                                 }
8029                                 break;
8030                         case MONO_TYPE_R8:
8031                                 for (i = 0; i < alen; i++) {
8032                                         double val;
8033                                         readr8 (p, &val);
8034                                         mono_array_set (arr, double, i, val);
8035                                         p += 8;
8036                                 }
8037                                 break;
8038                         case MONO_TYPE_U8:
8039                         case MONO_TYPE_I8:
8040                                 for (i = 0; i < alen; i++) {
8041                                         guint64 val = read64 (p);
8042                                         mono_array_set (arr, guint64, i, val);
8043                                         p += 8;
8044                                 }
8045                                 break;
8046                         case MONO_TYPE_CLASS:
8047                         case MONO_TYPE_OBJECT:
8048                         case MONO_TYPE_STRING:
8049                         case MONO_TYPE_SZARRAY:
8050                                 for (i = 0; i < alen; i++) {
8051                                         MonoObject *item = load_cattr_value (image, &tklass->byval_arg, p, &p, error);
8052                                         if (!mono_error_ok (error))
8053                                                 return NULL;
8054                                         mono_array_setref (arr, i, item);
8055                                 }
8056                                 break;
8057                         default:
8058                                 g_error ("Type 0x%02x not handled in custom attr array decoding", basetype);
8059                 }
8060                 *end=p;
8061                 return arr;
8062         }
8063         default:
8064                 g_error ("Type 0x%02x not handled in custom attr value decoding", type);
8065         }
8066         return NULL;
8067 }
8068
8069 static MonoObject*
8070 create_cattr_typed_arg (MonoType *t, MonoObject *val)
8071 {
8072         static MonoClass *klass;
8073         static MonoMethod *ctor;
8074         MonoObject *retval;
8075         void *params [2], *unboxed;
8076
8077         if (!klass)
8078                 klass = mono_class_from_name (mono_defaults.corlib, "System.Reflection", "CustomAttributeTypedArgument");
8079         if (!ctor)
8080                 ctor = mono_class_get_method_from_name (klass, ".ctor", 2);
8081         
8082         params [0] = mono_type_get_object (mono_domain_get (), t);
8083         params [1] = val;
8084         retval = mono_object_new (mono_domain_get (), klass);
8085         unboxed = mono_object_unbox (retval);
8086         mono_runtime_invoke (ctor, unboxed, params, NULL);
8087
8088         return retval;
8089 }
8090
8091 static MonoObject*
8092 create_cattr_named_arg (void *minfo, MonoObject *typedarg)
8093 {
8094         static MonoClass *klass;
8095         static MonoMethod *ctor;
8096         MonoObject *retval;
8097         void *unboxed, *params [2];
8098
8099         if (!klass)
8100                 klass = mono_class_from_name (mono_defaults.corlib, "System.Reflection", "CustomAttributeNamedArgument");
8101         if (!ctor)
8102                 ctor = mono_class_get_method_from_name (klass, ".ctor", 2);
8103
8104         params [0] = minfo;
8105         params [1] = typedarg;
8106         retval = mono_object_new (mono_domain_get (), klass);
8107         unboxed = mono_object_unbox (retval);
8108         mono_runtime_invoke (ctor, unboxed, params, NULL);
8109
8110         return retval;
8111 }
8112
8113 static gboolean
8114 type_is_reference (MonoType *type)
8115 {
8116         switch (type->type) {
8117         case MONO_TYPE_BOOLEAN:
8118         case MONO_TYPE_CHAR:
8119         case MONO_TYPE_U:
8120         case MONO_TYPE_I:
8121         case MONO_TYPE_U1:
8122         case MONO_TYPE_I1:
8123         case MONO_TYPE_U2:
8124         case MONO_TYPE_I2:
8125         case MONO_TYPE_U4:
8126         case MONO_TYPE_I4:
8127         case MONO_TYPE_U8:
8128         case MONO_TYPE_I8:
8129         case MONO_TYPE_R8:
8130         case MONO_TYPE_R4:
8131         case MONO_TYPE_VALUETYPE:
8132                 return FALSE;
8133         default:
8134                 return TRUE;
8135         }
8136 }
8137
8138 static void
8139 free_param_data (MonoMethodSignature *sig, void **params) {
8140         int i;
8141         for (i = 0; i < sig->param_count; ++i) {
8142                 if (!type_is_reference (sig->params [i]))
8143                         g_free (params [i]);
8144         }
8145 }
8146
8147 /*
8148  * Find the field index in the metadata FieldDef table.
8149  */
8150 static guint32
8151 find_field_index (MonoClass *klass, MonoClassField *field) {
8152         int i;
8153
8154         for (i = 0; i < klass->field.count; ++i) {
8155                 if (field == &klass->fields [i])
8156                         return klass->field.first + 1 + i;
8157         }
8158         return 0;
8159 }
8160
8161 /*
8162  * Find the property index in the metadata Property table.
8163  */
8164 static guint32
8165 find_property_index (MonoClass *klass, MonoProperty *property) {
8166         int i;
8167
8168         for (i = 0; i < klass->ext->property.count; ++i) {
8169                 if (property == &klass->ext->properties [i])
8170                         return klass->ext->property.first + 1 + i;
8171         }
8172         return 0;
8173 }
8174
8175 /*
8176  * Find the event index in the metadata Event table.
8177  */
8178 static guint32
8179 find_event_index (MonoClass *klass, MonoEvent *event) {
8180         int i;
8181
8182         for (i = 0; i < klass->ext->event.count; ++i) {
8183                 if (event == &klass->ext->events [i])
8184                         return klass->ext->event.first + 1 + i;
8185         }
8186         return 0;
8187 }
8188
8189 static MonoObject*
8190 create_custom_attr (MonoImage *image, MonoMethod *method, const guchar *data, guint32 len, MonoError *error)
8191 {
8192         const char *p = (const char*)data;
8193         const char *named;
8194         guint32 i, j, num_named;
8195         MonoObject *attr;
8196         void *params_buf [32];
8197         void **params = NULL;
8198         MonoMethodSignature *sig;
8199         MonoObject *exc = NULL;
8200
8201         mono_error_init (error);
8202
8203         mono_class_init (method->klass);
8204
8205         if (!mono_verifier_verify_cattr_content (image, method, data, len, NULL)) {
8206                 mono_error_set_generic_error (error, "System.Reflection", "CustomAttributeFormatException", "Binary format of the specified custom attribute was invalid.");
8207                 return NULL;
8208         }
8209
8210         if (len == 0) {
8211                 attr = mono_object_new (mono_domain_get (), method->klass);
8212                 mono_runtime_invoke (method, attr, NULL, NULL);
8213                 return attr;
8214         }
8215
8216         if (len < 2 || read16 (p) != 0x0001) /* Prolog */
8217                 return NULL;
8218
8219         /*g_print ("got attr %s\n", method->klass->name);*/
8220
8221         sig = mono_method_signature (method);
8222         if (sig->param_count < 32) {
8223                 params = params_buf;
8224                 memset (params, 0, sizeof (void*) * sig->param_count);
8225         } else {
8226                 /* Allocate using GC so it gets GC tracking */
8227                 params = mono_gc_alloc_fixed (sig->param_count * sizeof (void*), NULL);
8228         }
8229
8230         /* skip prolog */
8231         p += 2;
8232         for (i = 0; i < mono_method_signature (method)->param_count; ++i) {
8233                 params [i] = load_cattr_value (image, mono_method_signature (method)->params [i], p, &p, error);
8234                 if (!mono_error_ok (error))
8235                         goto fail;
8236         }
8237
8238         named = p;
8239         attr = mono_object_new (mono_domain_get (), method->klass);
8240
8241         mono_runtime_invoke (method, attr, params, &exc);
8242         if (exc)
8243                 goto fail;
8244         num_named = read16 (named);
8245         named += 2;
8246         for (j = 0; j < num_named; j++) {
8247                 gint name_len;
8248                 char *name, named_type, data_type;
8249                 named_type = *named++;
8250                 data_type = *named++; /* type of data */
8251                 if (data_type == MONO_TYPE_SZARRAY)
8252                         data_type = *named++;
8253                 if (data_type == MONO_TYPE_ENUM) {
8254                         gint type_len;
8255                         char *type_name;
8256                         type_len = mono_metadata_decode_blob_size (named, &named);
8257                         type_name = g_malloc (type_len + 1);
8258                         memcpy (type_name, named, type_len);
8259                         type_name [type_len] = 0;
8260                         named += type_len;
8261                         /* FIXME: lookup the type and check type consistency */
8262                         g_free (type_name);
8263                 }
8264                 name_len = mono_metadata_decode_blob_size (named, &named);
8265                 name = g_malloc (name_len + 1);
8266                 memcpy (name, named, name_len);
8267                 name [name_len] = 0;
8268                 named += name_len;
8269                 if (named_type == 0x53) {
8270                         MonoClassField *field;
8271                         void *val;
8272
8273                         /* how this fail is a blackbox */
8274                         field = mono_class_get_field_from_name (mono_object_class (attr), name);
8275                         if (!field) {
8276                                 mono_error_set_generic_error (error, "System.Reflection", "CustomAttributeFormatException", "Could not find a field with name %s", name);
8277                                 g_free (name);
8278                                 goto fail;
8279                         }
8280
8281                         val = load_cattr_value (image, field->type, named, &named, error);
8282                         if (!mono_error_ok (error)) {
8283                                 g_free (name);
8284                                 if (!type_is_reference (field->type))
8285                                         g_free (val);
8286                                 goto fail;
8287                         }
8288
8289                         mono_field_set_value (attr, field, val);
8290                         if (!type_is_reference (field->type))
8291                                 g_free (val);
8292                 } else if (named_type == 0x54) {
8293                         MonoProperty *prop;
8294                         void *pparams [1];
8295                         MonoType *prop_type;
8296
8297                         prop = mono_class_get_property_from_name (mono_object_class (attr), name);
8298
8299                         if (!prop) {
8300                                 mono_error_set_generic_error (error, "System.Reflection", "CustomAttributeFormatException", "Could not find a property with name %s", name);
8301                                 g_free (name);
8302                                 goto fail;
8303                         }
8304
8305                         if (!prop->set) {
8306                                 mono_error_set_generic_error (error, "System.Reflection", "CustomAttributeFormatException", "Could not find the setter for %s", name);
8307                                 g_free (name);
8308                                 goto fail;
8309                         }
8310
8311                         /* can we have more that 1 arg in a custom attr named property? */
8312                         prop_type = prop->get? mono_method_signature (prop->get)->ret :
8313                              mono_method_signature (prop->set)->params [mono_method_signature (prop->set)->param_count - 1];
8314
8315                         pparams [0] = load_cattr_value (image, prop_type, named, &named, error);
8316                         if (!mono_error_ok (error)) {
8317                                 g_free (name);
8318                                 if (!type_is_reference (prop_type))
8319                                         g_free (pparams [0]);
8320                                 goto fail;
8321                         }
8322
8323
8324                         mono_property_set_value (prop, attr, pparams, NULL);
8325                         if (!type_is_reference (prop_type))
8326                                 g_free (pparams [0]);
8327                 }
8328                 g_free (name);
8329         }
8330
8331         free_param_data (method->signature, params);
8332         if (params != params_buf)
8333                 mono_gc_free_fixed (params);
8334
8335         return attr;
8336
8337 fail:
8338         free_param_data (method->signature, params);
8339         if (params != params_buf)
8340                 mono_gc_free_fixed (params);
8341         if (exc)
8342                 mono_raise_exception ((MonoException*)exc);
8343         return NULL;
8344 }
8345         
8346 /*
8347  * mono_reflection_create_custom_attr_data_args:
8348  *
8349  *   Create an array of typed and named arguments from the cattr blob given by DATA.
8350  * TYPED_ARGS and NAMED_ARGS will contain the objects representing the arguments,
8351  * NAMED_ARG_INFO will contain information about the named arguments.
8352  */
8353 void
8354 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)
8355 {
8356         MonoArray *typedargs, *namedargs;
8357         MonoClass *attrklass;
8358         MonoDomain *domain;
8359         const char *p = (const char*)data;
8360         const char *named;
8361         guint32 i, j, num_named;
8362         CattrNamedArg *arginfo = NULL;
8363
8364         *typed_args = NULL;
8365         *named_args = NULL;
8366         *named_arg_info = NULL;
8367
8368         mono_error_init (error);
8369
8370         if (!mono_verifier_verify_cattr_content (image, method, data, len, NULL)) {
8371                 mono_error_set_generic_error (error, "System.Reflection", "CustomAttributeFormatException", "Binary format of the specified custom attribute was invalid.");
8372                 return;
8373         }
8374
8375         mono_class_init (method->klass);
8376         
8377         domain = mono_domain_get ();
8378
8379         if (len < 2 || read16 (p) != 0x0001) /* Prolog */
8380                 return;
8381
8382         typedargs = mono_array_new (domain, mono_get_object_class (), mono_method_signature (method)->param_count);
8383         
8384         /* skip prolog */
8385         p += 2;
8386         for (i = 0; i < mono_method_signature (method)->param_count; ++i) {
8387                 MonoObject *obj;
8388                 void *val;
8389
8390                 val = load_cattr_value (image, mono_method_signature (method)->params [i], p, &p, error);
8391                 if (!mono_error_ok (error)) {
8392                         if (!type_is_reference (mono_method_signature (method)->params [i]))
8393                                 g_free (val);
8394                         return;
8395                 }
8396
8397                 obj = type_is_reference (mono_method_signature (method)->params [i]) ? 
8398                         val : mono_value_box (domain, mono_class_from_mono_type (mono_method_signature (method)->params [i]), val);
8399                 mono_array_setref (typedargs, i, obj);
8400
8401                 if (!type_is_reference (mono_method_signature (method)->params [i]))
8402                         g_free (val);
8403         }
8404
8405         named = p;
8406         num_named = read16 (named);
8407         namedargs = mono_array_new (domain, mono_get_object_class (), num_named);
8408         named += 2;
8409         attrklass = method->klass;
8410
8411         arginfo = g_new0 (CattrNamedArg, num_named);
8412         *named_arg_info = arginfo;
8413
8414         for (j = 0; j < num_named; j++) {
8415                 gint name_len;
8416                 char *name, named_type, data_type;
8417                 named_type = *named++;
8418                 data_type = *named++; /* type of data */
8419                 if (data_type == MONO_TYPE_SZARRAY)
8420                         data_type = *named++;
8421                 if (data_type == MONO_TYPE_ENUM) {
8422                         gint type_len;
8423                         char *type_name;
8424                         type_len = mono_metadata_decode_blob_size (named, &named);
8425                         if (ADDP_IS_GREATER_OR_OVF ((const guchar*)named, type_len, data + len))
8426                                 goto fail;
8427
8428                         type_name = g_malloc (type_len + 1);
8429                         memcpy (type_name, named, type_len);
8430                         type_name [type_len] = 0;
8431                         named += type_len;
8432                         /* FIXME: lookup the type and check type consistency */
8433                         g_free (type_name);
8434                 }
8435                 name_len = mono_metadata_decode_blob_size (named, &named);
8436                 if (ADDP_IS_GREATER_OR_OVF ((const guchar*)named, name_len, data + len))
8437                         goto fail;
8438                 name = g_malloc (name_len + 1);
8439                 memcpy (name, named, name_len);
8440                 name [name_len] = 0;
8441                 named += name_len;
8442                 if (named_type == 0x53) {
8443                         MonoObject *obj;
8444                         MonoClassField *field = mono_class_get_field_from_name (attrklass, name);
8445                         void *val;
8446
8447                         if (!field) {
8448                                 g_free (name);
8449                                 goto fail;
8450                         }
8451
8452                         arginfo [j].type = field->type;
8453                         arginfo [j].field = field;
8454
8455                         val = load_cattr_value (image, field->type, named, &named, error);
8456                         if (!mono_error_ok (error)) {
8457                                 if (!type_is_reference (field->type))
8458                                         g_free (val);
8459                                 g_free (name);
8460                                 return;
8461                         }
8462
8463                         obj = type_is_reference (field->type) ? val : mono_value_box (domain, mono_class_from_mono_type (field->type), val);
8464                         mono_array_setref (namedargs, j, obj);
8465                         if (!type_is_reference (field->type))
8466                                 g_free (val);
8467                 } else if (named_type == 0x54) {
8468                         MonoObject *obj;
8469                         MonoType *prop_type;
8470                         MonoProperty *prop = mono_class_get_property_from_name (attrklass, name);
8471                         void *val;
8472
8473                         if (!prop || !prop->set) {
8474                                 g_free (name);
8475                                 goto fail;
8476                         }
8477
8478                         prop_type = prop->get? mono_method_signature (prop->get)->ret :
8479                              mono_method_signature (prop->set)->params [mono_method_signature (prop->set)->param_count - 1];
8480
8481                         arginfo [j].type = prop_type;
8482                         arginfo [j].prop = prop;
8483
8484                         val = load_cattr_value (image, prop_type, named, &named, error);
8485                         if (!mono_error_ok (error)) {
8486                                 if (!type_is_reference (prop_type))
8487                                         g_free (val);
8488                                 g_free (name);
8489                                 return;
8490                         }
8491
8492                         obj = type_is_reference (prop_type) ? val : mono_value_box (domain, mono_class_from_mono_type (prop_type), val);
8493                         mono_array_setref (namedargs, j, obj);
8494                         if (!type_is_reference (prop_type))
8495                                 g_free (val);
8496                 }
8497                 g_free (name);
8498         }
8499
8500         *typed_args = typedargs;
8501         *named_args = namedargs;
8502         return;
8503 fail:
8504         mono_error_set_generic_error (error, "System.Reflection", "CustomAttributeFormatException", "Binary format of the specified custom attribute was invalid.");
8505         g_free (arginfo);
8506         *named_arg_info = NULL;
8507 }
8508
8509 void
8510 mono_reflection_resolve_custom_attribute_data (MonoReflectionMethod *ref_method, MonoReflectionAssembly *assembly, gpointer data, guint32 len, MonoArray **ctor_args, MonoArray **named_args)
8511 {
8512         MonoDomain *domain;
8513         MonoArray *typedargs, *namedargs;
8514         MonoImage *image;
8515         MonoMethod *method;
8516         CattrNamedArg *arginfo = NULL;
8517         MonoError error;
8518         int i;
8519
8520         *ctor_args = NULL;
8521         *named_args = NULL;
8522
8523         if (len == 0)
8524                 return;
8525
8526         image = assembly->assembly->image;
8527         method = ref_method->method;
8528         domain = mono_object_domain (ref_method);
8529
8530         if (!mono_class_init (method->klass))
8531                 mono_raise_exception (mono_class_get_exception_for_failure (method->klass));
8532
8533         mono_reflection_create_custom_attr_data_args (image, method, data, len, &typedargs, &namedargs, &arginfo, &error);
8534         if (!mono_error_ok (&error))
8535                 mono_error_raise_exception (&error);
8536         if (mono_loader_get_last_error ())
8537                 mono_raise_exception (mono_loader_error_prepare_exception (mono_loader_get_last_error ()));
8538
8539         if (!typedargs || !namedargs) {
8540                 g_free (arginfo);
8541                 return;
8542         }
8543
8544         for (i = 0; i < mono_method_signature (method)->param_count; ++i) {
8545                 MonoObject *obj = mono_array_get (typedargs, MonoObject*, i);
8546                 MonoObject *typedarg;
8547
8548                 typedarg = create_cattr_typed_arg (mono_method_signature (method)->params [i], obj);
8549                 mono_array_setref (typedargs, i, typedarg);
8550         }
8551
8552         for (i = 0; i < mono_array_length (namedargs); ++i) {
8553                 MonoObject *obj = mono_array_get (namedargs, MonoObject*, i);
8554                 MonoObject *typedarg, *namedarg, *minfo;
8555
8556                 if (arginfo [i].prop)
8557                         minfo = (MonoObject*)mono_property_get_object (domain, NULL, arginfo [i].prop);
8558                 else
8559                         minfo = (MonoObject*)mono_field_get_object (domain, NULL, arginfo [i].field);
8560
8561                 typedarg = create_cattr_typed_arg (arginfo [i].type, obj);
8562                 namedarg = create_cattr_named_arg (minfo, typedarg);
8563
8564                 mono_array_setref (namedargs, i, namedarg);
8565         }
8566
8567         *ctor_args = typedargs;
8568         *named_args = namedargs;
8569         g_free (arginfo);
8570 }
8571
8572 static MonoObject*
8573 create_custom_attr_data (MonoImage *image, MonoCustomAttrEntry *cattr)
8574 {
8575         static MonoMethod *ctor;
8576         MonoDomain *domain;
8577         MonoObject *attr;
8578         void *params [4];
8579
8580         g_assert (image->assembly);
8581
8582         if (!ctor)
8583                 ctor = mono_class_get_method_from_name (mono_defaults.customattribute_data_class, ".ctor", 4);
8584
8585         domain = mono_domain_get ();
8586         attr = mono_object_new (domain, mono_defaults.customattribute_data_class);
8587         params [0] = mono_method_get_object (domain, cattr->ctor, NULL);
8588         params [1] = mono_assembly_get_object (domain, image->assembly);
8589         params [2] = (gpointer)&cattr->data;
8590         params [3] = &cattr->data_size;
8591         mono_runtime_invoke (ctor, attr, params, NULL);
8592         return attr;
8593 }
8594
8595 static MonoArray*
8596 mono_custom_attrs_construct_by_type (MonoCustomAttrInfo *cinfo, MonoClass *attr_klass, MonoError *error)
8597 {
8598         MonoArray *result;
8599         MonoObject *attr;
8600         int i, n;
8601
8602         mono_error_init (error);
8603
8604         n = 0;
8605         for (i = 0; i < cinfo->num_attrs; ++i) {
8606                 if (!attr_klass || mono_class_is_assignable_from (attr_klass, cinfo->attrs [i].ctor->klass))
8607                         n ++;
8608         }
8609
8610         result = mono_array_new_cached (mono_domain_get (), mono_defaults.attribute_class, n);
8611         n = 0;
8612         for (i = 0; i < cinfo->num_attrs; ++i) {
8613                 if (!cinfo->attrs [i].ctor)
8614                         /* The cattr type is not finished yet */
8615                         /* We should include the type name but cinfo doesn't contain it */
8616                         mono_raise_exception (mono_get_exception_type_load (NULL, NULL));
8617                 if (!attr_klass || mono_class_is_assignable_from (attr_klass, cinfo->attrs [i].ctor->klass)) {
8618                         attr = create_custom_attr (cinfo->image, cinfo->attrs [i].ctor, cinfo->attrs [i].data, cinfo->attrs [i].data_size, error);
8619                         if (!mono_error_ok (error))
8620                                 return result;
8621                         mono_array_setref (result, n, attr);
8622                         n ++;
8623                 }
8624         }
8625         return result;
8626 }
8627
8628 MonoArray*
8629 mono_custom_attrs_construct (MonoCustomAttrInfo *cinfo)
8630 {
8631         MonoError error;
8632         MonoArray *result = mono_custom_attrs_construct_by_type (cinfo, NULL, &error);
8633         g_assert (mono_error_ok (&error)); /*FIXME proper error handling*/
8634
8635         return result;
8636 }
8637
8638 static MonoArray*
8639 mono_custom_attrs_data_construct (MonoCustomAttrInfo *cinfo)
8640 {
8641         MonoArray *result;
8642         MonoObject *attr;
8643         int i;
8644         
8645         result = mono_array_new (mono_domain_get (), mono_defaults.customattribute_data_class, cinfo->num_attrs);
8646         for (i = 0; i < cinfo->num_attrs; ++i) {
8647                 attr = create_custom_attr_data (cinfo->image, &cinfo->attrs [i]);
8648                 mono_array_setref (result, i, attr);
8649         }
8650         return result;
8651 }
8652
8653 /**
8654  * mono_custom_attrs_from_index:
8655  *
8656  * Returns: NULL if no attributes are found or if a loading error occurs.
8657  */
8658 MonoCustomAttrInfo*
8659 mono_custom_attrs_from_index (MonoImage *image, guint32 idx)
8660 {
8661         guint32 mtoken, i, len;
8662         guint32 cols [MONO_CUSTOM_ATTR_SIZE];
8663         MonoTableInfo *ca;
8664         MonoCustomAttrInfo *ainfo;
8665         GList *tmp, *list = NULL;
8666         const char *data;
8667
8668         ca = &image->tables [MONO_TABLE_CUSTOMATTRIBUTE];
8669
8670         i = mono_metadata_custom_attrs_from_index (image, idx);
8671         if (!i)
8672                 return NULL;
8673         i --;
8674         while (i < ca->rows) {
8675                 if (mono_metadata_decode_row_col (ca, i, MONO_CUSTOM_ATTR_PARENT) != idx)
8676                         break;
8677                 list = g_list_prepend (list, GUINT_TO_POINTER (i));
8678                 ++i;
8679         }
8680         len = g_list_length (list);
8681         if (!len)
8682                 return NULL;
8683         ainfo = g_malloc0 (MONO_SIZEOF_CUSTOM_ATTR_INFO + sizeof (MonoCustomAttrEntry) * len);
8684         ainfo->num_attrs = len;
8685         ainfo->image = image;
8686         for (i = 0, tmp = list; i < len; ++i, tmp = tmp->next) {
8687                 mono_metadata_decode_row (ca, GPOINTER_TO_UINT (tmp->data), cols, MONO_CUSTOM_ATTR_SIZE);
8688                 mtoken = cols [MONO_CUSTOM_ATTR_TYPE] >> MONO_CUSTOM_ATTR_TYPE_BITS;
8689                 switch (cols [MONO_CUSTOM_ATTR_TYPE] & MONO_CUSTOM_ATTR_TYPE_MASK) {
8690                 case MONO_CUSTOM_ATTR_TYPE_METHODDEF:
8691                         mtoken |= MONO_TOKEN_METHOD_DEF;
8692                         break;
8693                 case MONO_CUSTOM_ATTR_TYPE_MEMBERREF:
8694                         mtoken |= MONO_TOKEN_MEMBER_REF;
8695                         break;
8696                 default:
8697                         g_error ("Unknown table for custom attr type %08x", cols [MONO_CUSTOM_ATTR_TYPE]);
8698                         break;
8699                 }
8700                 ainfo->attrs [i].ctor = mono_get_method (image, mtoken, NULL);
8701                 if (!ainfo->attrs [i].ctor) {
8702                         g_warning ("Can't find custom attr constructor image: %s mtoken: 0x%08x", image->name, mtoken);
8703                         g_list_free (list);
8704                         g_free (ainfo);
8705                         return NULL;
8706                 }
8707
8708                 if (!mono_verifier_verify_cattr_blob (image, cols [MONO_CUSTOM_ATTR_VALUE], NULL)) {
8709                         /*FIXME raising an exception here doesn't make any sense*/
8710                         g_warning ("Invalid custom attribute blob on image %s for index %x", image->name, idx);
8711                         g_list_free (list);
8712                         g_free (ainfo);
8713                         return NULL;
8714                 }
8715                 data = mono_metadata_blob_heap (image, cols [MONO_CUSTOM_ATTR_VALUE]);
8716                 ainfo->attrs [i].data_size = mono_metadata_decode_value (data, &data);
8717                 ainfo->attrs [i].data = (guchar*)data;
8718         }
8719         g_list_free (list);
8720
8721         return ainfo;
8722 }
8723
8724 MonoCustomAttrInfo*
8725 mono_custom_attrs_from_method (MonoMethod *method)
8726 {
8727         guint32 idx;
8728
8729         /*
8730          * An instantiated method has the same cattrs as the generic method definition.
8731          *
8732          * LAMESPEC: The .NET SRE throws an exception for instantiations of generic method builders
8733          *           Note that this stanza is not necessary for non-SRE types, but it's a micro-optimization
8734          */
8735         if (method->is_inflated)
8736                 method = ((MonoMethodInflated *) method)->declaring;
8737         
8738         if (method->dynamic || method->klass->image->dynamic)
8739                 return lookup_custom_attr (method->klass->image, method);
8740
8741         if (!method->token)
8742                 /* Synthetic methods */
8743                 return NULL;
8744
8745         idx = mono_method_get_index (method);
8746         idx <<= MONO_CUSTOM_ATTR_BITS;
8747         idx |= MONO_CUSTOM_ATTR_METHODDEF;
8748         return mono_custom_attrs_from_index (method->klass->image, idx);
8749 }
8750
8751 MonoCustomAttrInfo*
8752 mono_custom_attrs_from_class (MonoClass *klass)
8753 {
8754         guint32 idx;
8755
8756         if (klass->generic_class)
8757                 klass = klass->generic_class->container_class;
8758
8759         if (klass->image->dynamic)
8760                 return lookup_custom_attr (klass->image, klass);
8761
8762         if (klass->byval_arg.type == MONO_TYPE_VAR || klass->byval_arg.type == MONO_TYPE_MVAR) {
8763                 idx = mono_metadata_token_index (klass->sizes.generic_param_token);
8764                 idx <<= MONO_CUSTOM_ATTR_BITS;
8765                 idx |= MONO_CUSTOM_ATTR_GENERICPAR;
8766         } else {
8767                 idx = mono_metadata_token_index (klass->type_token);
8768                 idx <<= MONO_CUSTOM_ATTR_BITS;
8769                 idx |= MONO_CUSTOM_ATTR_TYPEDEF;
8770         }
8771         return mono_custom_attrs_from_index (klass->image, idx);
8772 }
8773
8774 MonoCustomAttrInfo*
8775 mono_custom_attrs_from_assembly (MonoAssembly *assembly)
8776 {
8777         guint32 idx;
8778         
8779         if (assembly->image->dynamic)
8780                 return lookup_custom_attr (assembly->image, assembly);
8781         idx = 1; /* there is only one assembly */
8782         idx <<= MONO_CUSTOM_ATTR_BITS;
8783         idx |= MONO_CUSTOM_ATTR_ASSEMBLY;
8784         return mono_custom_attrs_from_index (assembly->image, idx);
8785 }
8786
8787 static MonoCustomAttrInfo*
8788 mono_custom_attrs_from_module (MonoImage *image)
8789 {
8790         guint32 idx;
8791         
8792         if (image->dynamic)
8793                 return lookup_custom_attr (image, image);
8794         idx = 1; /* there is only one module */
8795         idx <<= MONO_CUSTOM_ATTR_BITS;
8796         idx |= MONO_CUSTOM_ATTR_MODULE;
8797         return mono_custom_attrs_from_index (image, idx);
8798 }
8799
8800 MonoCustomAttrInfo*
8801 mono_custom_attrs_from_property (MonoClass *klass, MonoProperty *property)
8802 {
8803         guint32 idx;
8804         
8805         if (klass->image->dynamic) {
8806                 property = mono_metadata_get_corresponding_property_from_generic_type_definition (property);
8807                 return lookup_custom_attr (klass->image, property);
8808         }
8809         idx = find_property_index (klass, property);
8810         idx <<= MONO_CUSTOM_ATTR_BITS;
8811         idx |= MONO_CUSTOM_ATTR_PROPERTY;
8812         return mono_custom_attrs_from_index (klass->image, idx);
8813 }
8814
8815 MonoCustomAttrInfo*
8816 mono_custom_attrs_from_event (MonoClass *klass, MonoEvent *event)
8817 {
8818         guint32 idx;
8819         
8820         if (klass->image->dynamic) {
8821                 event = mono_metadata_get_corresponding_event_from_generic_type_definition (event);
8822                 return lookup_custom_attr (klass->image, event);
8823         }
8824         idx = find_event_index (klass, event);
8825         idx <<= MONO_CUSTOM_ATTR_BITS;
8826         idx |= MONO_CUSTOM_ATTR_EVENT;
8827         return mono_custom_attrs_from_index (klass->image, idx);
8828 }
8829
8830 MonoCustomAttrInfo*
8831 mono_custom_attrs_from_field (MonoClass *klass, MonoClassField *field)
8832 {
8833         guint32 idx;
8834         if (klass->image->dynamic) {
8835                 field = mono_metadata_get_corresponding_field_from_generic_type_definition (field);
8836                 return lookup_custom_attr (klass->image, field);
8837         }
8838         idx = find_field_index (klass, field);
8839         idx <<= MONO_CUSTOM_ATTR_BITS;
8840         idx |= MONO_CUSTOM_ATTR_FIELDDEF;
8841         return mono_custom_attrs_from_index (klass->image, idx);
8842 }
8843
8844 /**
8845  * mono_custom_attrs_from_param:
8846  * @method: handle to the method that we want to retrieve custom parameter information from
8847  * @param: parameter number, where zero represent the return value, and one is the first parameter in the method
8848  *
8849  * The result must be released with mono_custom_attrs_free().
8850  *
8851  * Returns: the custom attribute object for the specified parameter, or NULL if there are none.
8852  */
8853 MonoCustomAttrInfo*
8854 mono_custom_attrs_from_param (MonoMethod *method, guint32 param)
8855 {
8856         MonoTableInfo *ca;
8857         guint32 i, idx, method_index;
8858         guint32 param_list, param_last, param_pos, found;
8859         MonoImage *image;
8860         MonoReflectionMethodAux *aux;
8861
8862         /*
8863          * An instantiated method has the same cattrs as the generic method definition.
8864          *
8865          * LAMESPEC: The .NET SRE throws an exception for instantiations of generic method builders
8866          *           Note that this stanza is not necessary for non-SRE types, but it's a micro-optimization
8867          */
8868         if (method->is_inflated)
8869                 method = ((MonoMethodInflated *) method)->declaring;
8870
8871         if (method->klass->image->dynamic) {
8872                 MonoCustomAttrInfo *res, *ainfo;
8873                 int size;
8874
8875                 aux = g_hash_table_lookup (((MonoDynamicImage*)method->klass->image)->method_aux_hash, method);
8876                 if (!aux || !aux->param_cattr)
8877                         return NULL;
8878
8879                 /* Need to copy since it will be freed later */
8880                 ainfo = aux->param_cattr [param];
8881                 if (!ainfo)
8882                         return NULL;
8883                 size = MONO_SIZEOF_CUSTOM_ATTR_INFO + sizeof (MonoCustomAttrEntry) * ainfo->num_attrs;
8884                 res = g_malloc0 (size);
8885                 memcpy (res, ainfo, size);
8886                 return res;
8887         }
8888
8889         image = method->klass->image;
8890         method_index = mono_method_get_index (method);
8891         if (!method_index)
8892                 return NULL;
8893         ca = &image->tables [MONO_TABLE_METHOD];
8894
8895         param_list = mono_metadata_decode_row_col (ca, method_index - 1, MONO_METHOD_PARAMLIST);
8896         if (method_index == ca->rows) {
8897                 ca = &image->tables [MONO_TABLE_PARAM];
8898                 param_last = ca->rows + 1;
8899         } else {
8900                 param_last = mono_metadata_decode_row_col (ca, method_index, MONO_METHOD_PARAMLIST);
8901                 ca = &image->tables [MONO_TABLE_PARAM];
8902         }
8903         found = FALSE;
8904         for (i = param_list; i < param_last; ++i) {
8905                 param_pos = mono_metadata_decode_row_col (ca, i - 1, MONO_PARAM_SEQUENCE);
8906                 if (param_pos == param) {
8907                         found = TRUE;
8908                         break;
8909                 }
8910         }
8911         if (!found)
8912                 return NULL;
8913         idx = i;
8914         idx <<= MONO_CUSTOM_ATTR_BITS;
8915         idx |= MONO_CUSTOM_ATTR_PARAMDEF;
8916         return mono_custom_attrs_from_index (image, idx);
8917 }
8918
8919 gboolean
8920 mono_custom_attrs_has_attr (MonoCustomAttrInfo *ainfo, MonoClass *attr_klass)
8921 {
8922         int i;
8923         MonoClass *klass;
8924         for (i = 0; i < ainfo->num_attrs; ++i) {
8925                 klass = ainfo->attrs [i].ctor->klass;
8926                 if (mono_class_has_parent (klass, attr_klass) || (MONO_CLASS_IS_INTERFACE (attr_klass) && mono_class_is_assignable_from (attr_klass, klass)))
8927                         return TRUE;
8928         }
8929         return FALSE;
8930 }
8931
8932 MonoObject*
8933 mono_custom_attrs_get_attr (MonoCustomAttrInfo *ainfo, MonoClass *attr_klass)
8934 {
8935         MonoError error;
8936         MonoObject *res = mono_custom_attrs_get_attr_checked (ainfo, attr_klass, &error);
8937         g_assert (mono_error_ok (&error)); /*FIXME proper error handling*/
8938         return res;
8939 }
8940
8941 MonoObject*
8942 mono_custom_attrs_get_attr_checked (MonoCustomAttrInfo *ainfo, MonoClass *attr_klass, MonoError *error)
8943 {
8944         int i, attr_index;
8945         MonoClass *klass;
8946         MonoArray *attrs;
8947
8948         mono_error_init (error);
8949
8950         attr_index = -1;
8951         for (i = 0; i < ainfo->num_attrs; ++i) {
8952                 klass = ainfo->attrs [i].ctor->klass;
8953                 if (mono_class_has_parent (klass, attr_klass)) {
8954                         attr_index = i;
8955                         break;
8956                 }
8957         }
8958         if (attr_index == -1)
8959                 return NULL;
8960
8961         attrs = mono_custom_attrs_construct_by_type (ainfo, NULL, error);
8962         if (!mono_error_ok (error))
8963                 return NULL;
8964         return mono_array_get (attrs, MonoObject*, attr_index);
8965 }
8966
8967 /*
8968  * mono_reflection_get_custom_attrs_info:
8969  * @obj: a reflection object handle
8970  *
8971  * Return the custom attribute info for attributes defined for the
8972  * reflection handle @obj. The objects.
8973  *
8974  * FIXME this function leaks like a sieve for SRE objects.
8975  */
8976 MonoCustomAttrInfo*
8977 mono_reflection_get_custom_attrs_info (MonoObject *obj)
8978 {
8979         MonoClass *klass;
8980         MonoCustomAttrInfo *cinfo = NULL;
8981         
8982         klass = obj->vtable->klass;
8983         if (klass == mono_defaults.monotype_class) {
8984                 MonoType *type = mono_reflection_type_get_handle ((MonoReflectionType *)obj);
8985                 klass = mono_class_from_mono_type (type);
8986                 /*We cannot mono_class_init the class from which we'll load the custom attributes since this must work with broken types.*/
8987                 cinfo = mono_custom_attrs_from_class (klass);
8988         } else if (strcmp ("Assembly", klass->name) == 0 || strcmp ("MonoAssembly", klass->name) == 0) {
8989                 MonoReflectionAssembly *rassembly = (MonoReflectionAssembly*)obj;
8990                 cinfo = mono_custom_attrs_from_assembly (rassembly->assembly);
8991         } else if (strcmp ("Module", klass->name) == 0 || strcmp ("MonoModule", klass->name) == 0) {
8992                 MonoReflectionModule *module = (MonoReflectionModule*)obj;
8993                 cinfo = mono_custom_attrs_from_module (module->image);
8994         } else if (strcmp ("MonoProperty", klass->name) == 0) {
8995                 MonoReflectionProperty *rprop = (MonoReflectionProperty*)obj;
8996                 cinfo = mono_custom_attrs_from_property (rprop->property->parent, rprop->property);
8997         } else if (strcmp ("MonoEvent", klass->name) == 0) {
8998                 MonoReflectionMonoEvent *revent = (MonoReflectionMonoEvent*)obj;
8999                 cinfo = mono_custom_attrs_from_event (revent->event->parent, revent->event);
9000         } else if (strcmp ("MonoField", klass->name) == 0) {
9001                 MonoReflectionField *rfield = (MonoReflectionField*)obj;
9002                 cinfo = mono_custom_attrs_from_field (rfield->field->parent, rfield->field);
9003         } else if ((strcmp ("MonoMethod", klass->name) == 0) || (strcmp ("MonoCMethod", klass->name) == 0)) {
9004                 MonoReflectionMethod *rmethod = (MonoReflectionMethod*)obj;
9005                 cinfo = mono_custom_attrs_from_method (rmethod->method);
9006         } else if ((strcmp ("MonoGenericMethod", klass->name) == 0) || (strcmp ("MonoGenericCMethod", klass->name) == 0)) {
9007                 MonoReflectionMethod *rmethod = (MonoReflectionMethod*)obj;
9008                 cinfo = mono_custom_attrs_from_method (rmethod->method);
9009         } else if (strcmp ("ParameterInfo", klass->name) == 0 || strcmp ("MonoParameterInfo", klass->name) == 0) {
9010                 MonoReflectionParameter *param = (MonoReflectionParameter*)obj;
9011                 MonoClass *member_class = mono_object_class (param->MemberImpl);
9012                 if (mono_class_is_reflection_method_or_constructor (member_class)) {
9013                         MonoReflectionMethod *rmethod = (MonoReflectionMethod*)param->MemberImpl;
9014                         cinfo = mono_custom_attrs_from_param (rmethod->method, param->PositionImpl + 1);
9015                 } else if (is_sr_mono_property (member_class)) {
9016                         MonoReflectionProperty *prop = (MonoReflectionProperty *)param->MemberImpl;
9017                         MonoMethod *method;
9018                         if (!(method = prop->property->get))
9019                                 method = prop->property->set;
9020                         g_assert (method);
9021
9022                         cinfo = mono_custom_attrs_from_param (method, param->PositionImpl + 1);
9023                 } 
9024 #ifndef DISABLE_REFLECTION_EMIT
9025                 else if (is_sre_method_on_tb_inst (member_class)) {/*XXX This is a workaround for Compiler Context*/
9026                         MonoMethod *method = mono_reflection_method_on_tb_inst_get_handle ((MonoReflectionMethodOnTypeBuilderInst*)param->MemberImpl);
9027                         cinfo = mono_custom_attrs_from_param (method, param->PositionImpl + 1);
9028                 } else if (is_sre_ctor_on_tb_inst (member_class)) { /*XX This is a workaround for Compiler Context*/
9029                         MonoReflectionCtorOnTypeBuilderInst *c = (MonoReflectionCtorOnTypeBuilderInst*)param->MemberImpl;
9030                         MonoMethod *method = NULL;
9031                         if (is_sre_ctor_builder (mono_object_class (c->cb)))
9032                                 method = ((MonoReflectionCtorBuilder *)c->cb)->mhandle;
9033                         else if (is_sr_mono_cmethod (mono_object_class (c->cb)))
9034                                 method = ((MonoReflectionMethod *)c->cb)->method;
9035                         else
9036                                 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));
9037
9038                         cinfo = mono_custom_attrs_from_param (method, param->PositionImpl + 1);
9039                 } 
9040 #endif
9041                 else {
9042                         char *type_name = mono_type_get_full_name (member_class);
9043                         char *msg = g_strdup_printf ("Custom attributes on a ParamInfo with member %s are not supported", type_name);
9044                         MonoException *ex = mono_get_exception_not_supported  (msg);
9045                         g_free (type_name);
9046                         g_free (msg);
9047                         mono_raise_exception (ex);
9048                 }
9049         } else if (strcmp ("AssemblyBuilder", klass->name) == 0) {
9050                 MonoReflectionAssemblyBuilder *assemblyb = (MonoReflectionAssemblyBuilder*)obj;
9051                 cinfo = mono_custom_attrs_from_builders (NULL, assemblyb->assembly.assembly->image, assemblyb->cattrs);
9052         } else if (strcmp ("TypeBuilder", klass->name) == 0) {
9053                 MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder*)obj;
9054                 cinfo = mono_custom_attrs_from_builders (NULL, &tb->module->dynamic_image->image, tb->cattrs);
9055         } else if (strcmp ("ModuleBuilder", klass->name) == 0) {
9056                 MonoReflectionModuleBuilder *mb = (MonoReflectionModuleBuilder*)obj;
9057                 cinfo = mono_custom_attrs_from_builders (NULL, &mb->dynamic_image->image, mb->cattrs);
9058         } else if (strcmp ("ConstructorBuilder", klass->name) == 0) {
9059                 MonoReflectionCtorBuilder *cb = (MonoReflectionCtorBuilder*)obj;
9060                 cinfo = mono_custom_attrs_from_builders (NULL, cb->mhandle->klass->image, cb->cattrs);
9061         } else if (strcmp ("MethodBuilder", klass->name) == 0) {
9062                 MonoReflectionMethodBuilder *mb = (MonoReflectionMethodBuilder*)obj;
9063                 cinfo = mono_custom_attrs_from_builders (NULL, mb->mhandle->klass->image, mb->cattrs);
9064         } else if (strcmp ("FieldBuilder", klass->name) == 0) {
9065                 MonoReflectionFieldBuilder *fb = (MonoReflectionFieldBuilder*)obj;
9066                 cinfo = mono_custom_attrs_from_builders (NULL, &((MonoReflectionTypeBuilder*)fb->typeb)->module->dynamic_image->image, fb->cattrs);
9067         } else if (strcmp ("MonoGenericClass", klass->name) == 0) {
9068                 MonoReflectionGenericClass *gclass = (MonoReflectionGenericClass*)obj;
9069                 cinfo = mono_reflection_get_custom_attrs_info ((MonoObject*)gclass->generic_type);
9070         } else { /* handle other types here... */
9071                 g_error ("get custom attrs not yet supported for %s", klass->name);
9072         }
9073
9074         return cinfo;
9075 }
9076
9077 /*
9078  * mono_reflection_get_custom_attrs_by_type:
9079  * @obj: a reflection object handle
9080  *
9081  * Return an array with all the custom attributes defined of the
9082  * reflection handle @obj. If @attr_klass is non-NULL, only custom attributes 
9083  * of that type are returned. The objects are fully build. Return NULL if a loading error
9084  * occurs.
9085  */
9086 MonoArray*
9087 mono_reflection_get_custom_attrs_by_type (MonoObject *obj, MonoClass *attr_klass, MonoError *error)
9088 {
9089         MonoArray *result;
9090         MonoCustomAttrInfo *cinfo;
9091
9092         mono_error_init (error);
9093
9094         cinfo = mono_reflection_get_custom_attrs_info (obj);
9095         if (cinfo) {
9096                 result = mono_custom_attrs_construct_by_type (cinfo, attr_klass, error);
9097                 if (!cinfo->cached)
9098                         mono_custom_attrs_free (cinfo);
9099         } else {
9100                 /* FIXME add MonoError to mono_reflection_get_custom_attrs_info */
9101                 if (mono_loader_get_last_error ())
9102                         return NULL;
9103                 result = mono_array_new_cached (mono_domain_get (), mono_defaults.attribute_class, 0);
9104         }
9105
9106         return result;
9107 }
9108
9109 /*
9110  * mono_reflection_get_custom_attrs:
9111  * @obj: a reflection object handle
9112  *
9113  * Return an array with all the custom attributes defined of the
9114  * reflection handle @obj. The objects are fully build. Return NULL if a loading error
9115  * occurs.
9116  */
9117 MonoArray*
9118 mono_reflection_get_custom_attrs (MonoObject *obj)
9119 {
9120         MonoError error;
9121
9122         return mono_reflection_get_custom_attrs_by_type (obj, NULL, &error);
9123 }
9124
9125 /*
9126  * mono_reflection_get_custom_attrs_data:
9127  * @obj: a reflection obj handle
9128  *
9129  * Returns an array of System.Reflection.CustomAttributeData,
9130  * which include information about attributes reflected on
9131  * types loaded using the Reflection Only methods
9132  */
9133 MonoArray*
9134 mono_reflection_get_custom_attrs_data (MonoObject *obj)
9135 {
9136         MonoArray *result;
9137         MonoCustomAttrInfo *cinfo;
9138
9139         cinfo = mono_reflection_get_custom_attrs_info (obj);
9140         if (cinfo) {
9141                 result = mono_custom_attrs_data_construct (cinfo);
9142                 if (!cinfo->cached)
9143                         mono_custom_attrs_free (cinfo);
9144         } else
9145                 result = mono_array_new (mono_domain_get (), mono_defaults.customattribute_data_class, 0);
9146
9147         return result;
9148 }
9149
9150 static MonoReflectionType*
9151 mono_reflection_type_get_underlying_system_type (MonoReflectionType* t)
9152 {
9153         static MonoMethod *method_get_underlying_system_type = NULL;
9154         MonoMethod *usertype_method;
9155
9156         if (!method_get_underlying_system_type)
9157                 method_get_underlying_system_type = mono_class_get_method_from_name (mono_defaults.systemtype_class, "get_UnderlyingSystemType", 0);
9158         usertype_method = mono_object_get_virtual_method ((MonoObject *) t, method_get_underlying_system_type);
9159         return (MonoReflectionType *) mono_runtime_invoke (usertype_method, t, NULL, NULL);
9160 }
9161
9162
9163 static gboolean
9164 is_corlib_type (MonoClass *class)
9165 {
9166         return class->image == mono_defaults.corlib;
9167 }
9168
9169 #define check_corlib_type_cached(_class, _namespace, _name) do { \
9170         static MonoClass *cached_class; \
9171         if (cached_class) \
9172                 return cached_class == _class; \
9173         if (is_corlib_type (_class) && !strcmp (_name, _class->name) && !strcmp (_namespace, _class->name_space)) { \
9174                 cached_class = _class; \
9175                 return TRUE; \
9176         } \
9177         return FALSE; \
9178 } while (0) \
9179
9180
9181 #ifndef DISABLE_REFLECTION_EMIT
9182 static gboolean
9183 is_sre_array (MonoClass *class)
9184 {
9185         check_corlib_type_cached (class, "System.Reflection.Emit", "ArrayType");
9186 }
9187
9188 static gboolean
9189 is_sre_byref (MonoClass *class)
9190 {
9191         check_corlib_type_cached (class, "System.Reflection.Emit", "ByRefType");
9192 }
9193
9194 static gboolean
9195 is_sre_pointer (MonoClass *class)
9196 {
9197         check_corlib_type_cached (class, "System.Reflection.Emit", "PointerType");
9198 }
9199
9200 static gboolean
9201 is_sre_generic_instance (MonoClass *class)
9202 {
9203         check_corlib_type_cached (class, "System.Reflection", "MonoGenericClass");
9204 }
9205
9206 static gboolean
9207 is_sre_type_builder (MonoClass *class)
9208 {
9209         check_corlib_type_cached (class, "System.Reflection.Emit", "TypeBuilder");
9210 }
9211
9212 static gboolean
9213 is_sre_method_builder (MonoClass *class)
9214 {
9215         check_corlib_type_cached (class, "System.Reflection.Emit", "MethodBuilder");
9216 }
9217
9218 static gboolean
9219 is_sre_ctor_builder (MonoClass *class)
9220 {
9221         check_corlib_type_cached (class, "System.Reflection.Emit", "ConstructorBuilder");
9222 }
9223
9224 static gboolean
9225 is_sre_field_builder (MonoClass *class)
9226 {
9227         check_corlib_type_cached (class, "System.Reflection.Emit", "FieldBuilder");
9228 }
9229
9230 static gboolean
9231 is_sre_method_on_tb_inst (MonoClass *class)
9232 {
9233         check_corlib_type_cached (class, "System.Reflection.Emit", "MethodOnTypeBuilderInst");
9234 }
9235
9236 static gboolean
9237 is_sre_ctor_on_tb_inst (MonoClass *class)
9238 {
9239         check_corlib_type_cached (class, "System.Reflection.Emit", "ConstructorOnTypeBuilderInst");
9240 }
9241
9242 MonoType*
9243 mono_reflection_type_get_handle (MonoReflectionType* ref)
9244 {
9245         MonoClass *class;
9246         if (!ref)
9247                 return NULL;
9248         if (ref->type)
9249                 return ref->type;
9250
9251         if (is_usertype (ref)) {
9252                 ref = mono_reflection_type_get_underlying_system_type (ref);
9253                 if (ref == NULL || is_usertype (ref))
9254                         return NULL;
9255                 if (ref->type)
9256                         return ref->type;
9257         }
9258
9259         class = mono_object_class (ref);
9260
9261         if (is_sre_array (class)) {
9262                 MonoType *res;
9263                 MonoReflectionArrayType *sre_array = (MonoReflectionArrayType*)ref;
9264                 MonoType *base = mono_reflection_type_get_handle (sre_array->element_type);
9265                 g_assert (base);
9266                 if (sre_array->rank == 0) //single dimentional array
9267                         res = &mono_array_class_get (mono_class_from_mono_type (base), 1)->byval_arg;
9268                 else
9269                         res = &mono_bounded_array_class_get (mono_class_from_mono_type (base), sre_array->rank, TRUE)->byval_arg;
9270                 sre_array->type.type = res;
9271                 return res;
9272         } else if (is_sre_byref (class)) {
9273                 MonoType *res;
9274                 MonoReflectionDerivedType *sre_byref = (MonoReflectionDerivedType*)ref;
9275                 MonoType *base = mono_reflection_type_get_handle (sre_byref->element_type);
9276                 g_assert (base);
9277                 res = &mono_class_from_mono_type (base)->this_arg;
9278                 sre_byref->type.type = res;
9279                 return res;
9280         } else if (is_sre_pointer (class)) {
9281                 MonoType *res;
9282                 MonoReflectionDerivedType *sre_pointer = (MonoReflectionDerivedType*)ref;
9283                 MonoType *base = mono_reflection_type_get_handle (sre_pointer->element_type);
9284                 g_assert (base);
9285                 res = &mono_ptr_class_get (base)->byval_arg;
9286                 sre_pointer->type.type = res;
9287                 return res;
9288         } else if (is_sre_generic_instance (class)) {
9289                 MonoType *res, **types;
9290                 MonoReflectionGenericClass *gclass = (MonoReflectionGenericClass*)ref;
9291                 int i, count;
9292
9293                 count = mono_array_length (gclass->type_arguments);
9294                 types = g_new0 (MonoType*, count);
9295                 for (i = 0; i < count; ++i) {
9296                         MonoReflectionType *t = mono_array_get (gclass->type_arguments, gpointer, i);
9297                         types [i] = mono_reflection_type_get_handle (t);
9298                         if (!types[i]) {
9299                                 g_free (types);
9300                                 return NULL;
9301                         }
9302                 }
9303
9304                 res = mono_reflection_bind_generic_parameters (gclass->generic_type, count, types);
9305                 g_free (types);
9306                 g_assert (res);
9307                 gclass->type.type = res;
9308                 return res;
9309         }
9310
9311         g_error ("Cannot handle corlib user type %s", mono_type_full_name (&mono_object_class(ref)->byval_arg));
9312         return NULL;
9313 }
9314
9315
9316
9317 void
9318 mono_reflection_create_unmanaged_type (MonoReflectionType *type)
9319 {
9320         mono_reflection_type_get_handle (type);
9321 }
9322
9323 void
9324 mono_reflection_register_with_runtime (MonoReflectionType *type)
9325 {
9326         MonoType *res = mono_reflection_type_get_handle (type);
9327         MonoDomain *domain = mono_object_domain ((MonoObject*)type);
9328         MonoClass *class;
9329
9330         if (!res)
9331                 mono_raise_exception (mono_get_exception_argument (NULL, "Invalid generic instantiation, one or more arguments are not proper user types"));
9332
9333         class = mono_class_from_mono_type (res);
9334
9335         mono_loader_lock (); /*same locking as mono_type_get_object*/
9336         mono_domain_lock (domain);
9337
9338         if (!class->image->dynamic) {
9339                 mono_class_setup_supertypes (class);
9340         } else {
9341                 if (!domain->type_hash)
9342                         domain->type_hash = mono_g_hash_table_new_type ((GHashFunc)mono_metadata_type_hash, 
9343                                         (GCompareFunc)mono_metadata_type_equal, MONO_HASH_VALUE_GC);
9344                 mono_g_hash_table_insert (domain->type_hash, res, type);
9345         }
9346         mono_domain_unlock (domain);
9347         mono_loader_unlock ();
9348 }
9349
9350 /**
9351  * LOCKING: Assumes the loader lock is held.
9352  */
9353 static MonoMethodSignature*
9354 parameters_to_signature (MonoImage *image, MonoArray *parameters) {
9355         MonoMethodSignature *sig;
9356         int count, i;
9357
9358         count = parameters? mono_array_length (parameters): 0;
9359
9360         sig = image_g_malloc0 (image, MONO_SIZEOF_METHOD_SIGNATURE + sizeof (MonoType*) * count);
9361         sig->param_count = count;
9362         sig->sentinelpos = -1; /* FIXME */
9363         for (i = 0; i < count; ++i)
9364                 sig->params [i] = mono_type_array_get_and_resolve (parameters, i);
9365         return sig;
9366 }
9367
9368 /**
9369  * LOCKING: Assumes the loader lock is held.
9370  */
9371 static MonoMethodSignature*
9372 ctor_builder_to_signature (MonoImage *image, MonoReflectionCtorBuilder *ctor) {
9373         MonoMethodSignature *sig;
9374
9375         sig = parameters_to_signature (image, ctor->parameters);
9376         sig->hasthis = ctor->attrs & METHOD_ATTRIBUTE_STATIC? 0: 1;
9377         sig->ret = &mono_defaults.void_class->byval_arg;
9378         return sig;
9379 }
9380
9381 /**
9382  * LOCKING: Assumes the loader lock is held.
9383  */
9384 static MonoMethodSignature*
9385 method_builder_to_signature (MonoImage *image, MonoReflectionMethodBuilder *method) {
9386         MonoMethodSignature *sig;
9387
9388         sig = parameters_to_signature (image, method->parameters);
9389         sig->hasthis = method->attrs & METHOD_ATTRIBUTE_STATIC? 0: 1;
9390         sig->ret = method->rtype? mono_reflection_type_get_handle ((MonoReflectionType*)method->rtype): &mono_defaults.void_class->byval_arg;
9391         sig->generic_param_count = method->generic_params ? mono_array_length (method->generic_params) : 0;
9392         return sig;
9393 }
9394
9395 static MonoMethodSignature*
9396 dynamic_method_to_signature (MonoReflectionDynamicMethod *method) {
9397         MonoMethodSignature *sig;
9398
9399         sig = parameters_to_signature (NULL, method->parameters);
9400         sig->hasthis = method->attrs & METHOD_ATTRIBUTE_STATIC? 0: 1;
9401         sig->ret = method->rtype? mono_reflection_type_get_handle (method->rtype): &mono_defaults.void_class->byval_arg;
9402         sig->generic_param_count = 0;
9403         return sig;
9404 }
9405
9406 static void
9407 get_prop_name_and_type (MonoObject *prop, char **name, MonoType **type)
9408 {
9409         MonoClass *klass = mono_object_class (prop);
9410         if (strcmp (klass->name, "PropertyBuilder") == 0) {
9411                 MonoReflectionPropertyBuilder *pb = (MonoReflectionPropertyBuilder *)prop;
9412                 *name = mono_string_to_utf8 (pb->name);
9413                 *type = mono_reflection_type_get_handle ((MonoReflectionType*)pb->type);
9414         } else {
9415                 MonoReflectionProperty *p = (MonoReflectionProperty *)prop;
9416                 *name = g_strdup (p->property->name);
9417                 if (p->property->get)
9418                         *type = mono_method_signature (p->property->get)->ret;
9419                 else
9420                         *type = mono_method_signature (p->property->set)->params [mono_method_signature (p->property->set)->param_count - 1];
9421         }
9422 }
9423
9424 static void
9425 get_field_name_and_type (MonoObject *field, char **name, MonoType **type)
9426 {
9427         MonoClass *klass = mono_object_class (field);
9428         if (strcmp (klass->name, "FieldBuilder") == 0) {
9429                 MonoReflectionFieldBuilder *fb = (MonoReflectionFieldBuilder *)field;
9430                 *name = mono_string_to_utf8 (fb->name);
9431                 *type = mono_reflection_type_get_handle ((MonoReflectionType*)fb->type);
9432         } else {
9433                 MonoReflectionField *f = (MonoReflectionField *)field;
9434                 *name = g_strdup (mono_field_get_name (f->field));
9435                 *type = f->field->type;
9436         }
9437 }
9438
9439 #else /* DISABLE_REFLECTION_EMIT */
9440
9441 void
9442 mono_reflection_register_with_runtime (MonoReflectionType *type)
9443 {
9444         /* This is empty */
9445 }
9446
9447 static gboolean
9448 is_sre_type_builder (MonoClass *class)
9449 {
9450         return FALSE;
9451 }
9452
9453 static gboolean
9454 is_sre_generic_instance (MonoClass *class)
9455 {
9456         return FALSE;
9457 }
9458
9459 static void
9460 init_type_builder_generics (MonoObject *type)
9461 {
9462 }
9463
9464 #endif /* !DISABLE_REFLECTION_EMIT */
9465
9466
9467 static gboolean
9468 is_sr_mono_field (MonoClass *class)
9469 {
9470         check_corlib_type_cached (class, "System.Reflection", "MonoField");
9471 }
9472
9473 static gboolean
9474 is_sr_mono_property (MonoClass *class)
9475 {
9476         check_corlib_type_cached (class, "System.Reflection", "MonoProperty");
9477 }
9478
9479 static gboolean
9480 is_sr_mono_method (MonoClass *class)
9481 {
9482         check_corlib_type_cached (class, "System.Reflection", "MonoMethod");
9483 }
9484
9485 static gboolean
9486 is_sr_mono_cmethod (MonoClass *class)
9487 {
9488         check_corlib_type_cached (class, "System.Reflection", "MonoCMethod");
9489 }
9490
9491 static gboolean
9492 is_sr_mono_generic_method (MonoClass *class)
9493 {
9494         check_corlib_type_cached (class, "System.Reflection", "MonoGenericMethod");
9495 }
9496
9497 static gboolean
9498 is_sr_mono_generic_cmethod (MonoClass *class)
9499 {
9500         check_corlib_type_cached (class, "System.Reflection", "MonoGenericCMethod");
9501 }
9502
9503 gboolean
9504 mono_class_is_reflection_method_or_constructor (MonoClass *class)
9505 {
9506         return is_sr_mono_method (class) || is_sr_mono_cmethod (class) || is_sr_mono_generic_method (class) || is_sr_mono_generic_cmethod (class);
9507 }
9508
9509 static gboolean
9510 is_usertype (MonoReflectionType *ref)
9511 {
9512         MonoClass *class = mono_object_class (ref);
9513         return class->image != mono_defaults.corlib || strcmp ("TypeDelegator", class->name) == 0;
9514 }
9515
9516 static MonoReflectionType*
9517 mono_reflection_type_resolve_user_types (MonoReflectionType *type)
9518 {
9519         if (!type || type->type)
9520                 return type;
9521
9522         if (is_usertype (type)) {
9523                 type = mono_reflection_type_get_underlying_system_type (type);
9524                 if (is_usertype (type))
9525                         mono_raise_exception (mono_get_exception_not_supported ("User defined subclasses of System.Type are not yet supported22"));
9526         }
9527
9528         return type;
9529 }
9530 /*
9531  * Encode a value in a custom attribute stream of bytes.
9532  * The value to encode is either supplied as an object in argument val
9533  * (valuetypes are boxed), or as a pointer to the data in the
9534  * argument argval.
9535  * @type represents the type of the value
9536  * @buffer is the start of the buffer
9537  * @p the current position in the buffer
9538  * @buflen contains the size of the buffer and is used to return the new buffer size
9539  * if this needs to be realloced.
9540  * @retbuffer and @retp return the start and the position of the buffer
9541  */
9542 static void
9543 encode_cattr_value (MonoAssembly *assembly, char *buffer, char *p, char **retbuffer, char **retp, guint32 *buflen, MonoType *type, MonoObject *arg, char *argval)
9544 {
9545         MonoTypeEnum simple_type;
9546         
9547         if ((p-buffer) + 10 >= *buflen) {
9548                 char *newbuf;
9549                 *buflen *= 2;
9550                 newbuf = g_realloc (buffer, *buflen);
9551                 p = newbuf + (p-buffer);
9552                 buffer = newbuf;
9553         }
9554         if (!argval)
9555                 argval = ((char*)arg + sizeof (MonoObject));
9556         simple_type = type->type;
9557 handle_enum:
9558         switch (simple_type) {
9559         case MONO_TYPE_BOOLEAN:
9560         case MONO_TYPE_U1:
9561         case MONO_TYPE_I1:
9562                 *p++ = *argval;
9563                 break;
9564         case MONO_TYPE_CHAR:
9565         case MONO_TYPE_U2:
9566         case MONO_TYPE_I2:
9567                 swap_with_size (p, argval, 2, 1);
9568                 p += 2;
9569                 break;
9570         case MONO_TYPE_U4:
9571         case MONO_TYPE_I4:
9572         case MONO_TYPE_R4:
9573                 swap_with_size (p, argval, 4, 1);
9574                 p += 4;
9575                 break;
9576         case MONO_TYPE_R8:
9577                 swap_with_size (p, argval, 8, 1);
9578                 p += 8;
9579                 break;
9580         case MONO_TYPE_U8:
9581         case MONO_TYPE_I8:
9582                 swap_with_size (p, argval, 8, 1);
9583                 p += 8;
9584                 break;
9585         case MONO_TYPE_VALUETYPE:
9586                 if (type->data.klass->enumtype) {
9587                         simple_type = mono_class_enum_basetype (type->data.klass)->type;
9588                         goto handle_enum;
9589                 } else {
9590                         g_warning ("generic valutype %s not handled in custom attr value decoding", type->data.klass->name);
9591                 }
9592                 break;
9593         case MONO_TYPE_STRING: {
9594                 char *str;
9595                 guint32 slen;
9596                 if (!arg) {
9597                         *p++ = 0xFF;
9598                         break;
9599                 }
9600                 str = mono_string_to_utf8 ((MonoString*)arg);
9601                 slen = strlen (str);
9602                 if ((p-buffer) + 10 + slen >= *buflen) {
9603                         char *newbuf;
9604                         *buflen *= 2;
9605                         *buflen += slen;
9606                         newbuf = g_realloc (buffer, *buflen);
9607                         p = newbuf + (p-buffer);
9608                         buffer = newbuf;
9609                 }
9610                 mono_metadata_encode_value (slen, p, &p);
9611                 memcpy (p, str, slen);
9612                 p += slen;
9613                 g_free (str);
9614                 break;
9615         }
9616         case MONO_TYPE_CLASS: {
9617                 char *str;
9618                 guint32 slen;
9619                 if (!arg) {
9620                         *p++ = 0xFF;
9621                         break;
9622                 }
9623 handle_type:
9624                 str = type_get_qualified_name (mono_reflection_type_get_handle ((MonoReflectionType*)arg), NULL);
9625                 slen = strlen (str);
9626                 if ((p-buffer) + 10 + slen >= *buflen) {
9627                         char *newbuf;
9628                         *buflen *= 2;
9629                         *buflen += slen;
9630                         newbuf = g_realloc (buffer, *buflen);
9631                         p = newbuf + (p-buffer);
9632                         buffer = newbuf;
9633                 }
9634                 mono_metadata_encode_value (slen, p, &p);
9635                 memcpy (p, str, slen);
9636                 p += slen;
9637                 g_free (str);
9638                 break;
9639         }
9640         case MONO_TYPE_SZARRAY: {
9641                 int len, i;
9642                 MonoClass *eclass, *arg_eclass;
9643
9644                 if (!arg) {
9645                         *p++ = 0xff; *p++ = 0xff; *p++ = 0xff; *p++ = 0xff;
9646                         break;
9647                 }
9648                 len = mono_array_length ((MonoArray*)arg);
9649                 *p++ = len & 0xff;
9650                 *p++ = (len >> 8) & 0xff;
9651                 *p++ = (len >> 16) & 0xff;
9652                 *p++ = (len >> 24) & 0xff;
9653                 *retp = p;
9654                 *retbuffer = buffer;
9655                 eclass = type->data.klass;
9656                 arg_eclass = mono_object_class (arg)->element_class;
9657
9658                 if (!eclass) {
9659                         /* Happens when we are called from the MONO_TYPE_OBJECT case below */
9660                         eclass = mono_defaults.object_class;
9661                 }
9662                 if (eclass == mono_defaults.object_class && arg_eclass->valuetype) {
9663                         char *elptr = mono_array_addr ((MonoArray*)arg, char, 0);
9664                         int elsize = mono_class_array_element_size (arg_eclass);
9665                         for (i = 0; i < len; ++i) {
9666                                 encode_cattr_value (assembly, buffer, p, &buffer, &p, buflen, &arg_eclass->byval_arg, NULL, elptr);
9667                                 elptr += elsize;
9668                         }
9669                 } else if (eclass->valuetype && arg_eclass->valuetype) {
9670                         char *elptr = mono_array_addr ((MonoArray*)arg, char, 0);
9671                         int elsize = mono_class_array_element_size (eclass);
9672                         for (i = 0; i < len; ++i) {
9673                                 encode_cattr_value (assembly, buffer, p, &buffer, &p, buflen, &eclass->byval_arg, NULL, elptr);
9674                                 elptr += elsize;
9675                         }
9676                 } else {
9677                         for (i = 0; i < len; ++i) {
9678                                 encode_cattr_value (assembly, buffer, p, &buffer, &p, buflen, &eclass->byval_arg, mono_array_get ((MonoArray*)arg, MonoObject*, i), NULL);
9679                         }
9680                 }
9681                 break;
9682         }
9683         case MONO_TYPE_OBJECT: {
9684                 MonoClass *klass;
9685                 char *str;
9686                 guint32 slen;
9687
9688                 /*
9689                  * The parameter type is 'object' but the type of the actual
9690                  * argument is not. So we have to add type information to the blob
9691                  * too. This is completely undocumented in the spec.
9692                  */
9693
9694                 if (arg == NULL) {
9695                         *p++ = MONO_TYPE_STRING;        // It's same hack as MS uses
9696                         *p++ = 0xFF;
9697                         break;
9698                 }
9699                 
9700                 klass = mono_object_class (arg);
9701
9702                 if (mono_object_isinst (arg, mono_defaults.systemtype_class)) {
9703                         *p++ = 0x50;
9704                         goto handle_type;
9705                 } else if (klass->enumtype) {
9706                         *p++ = 0x55;
9707                 } else if (klass == mono_defaults.string_class) {
9708                         simple_type = MONO_TYPE_STRING;
9709                         *p++ = 0x0E;
9710                         goto handle_enum;
9711                 } else if (klass->rank == 1) {
9712                         *p++ = 0x1D;
9713                         if (klass->element_class->byval_arg.type == MONO_TYPE_OBJECT)
9714                                 /* See Partition II, Appendix B3 */
9715                                 *p++ = 0x51;
9716                         else
9717                                 *p++ = klass->element_class->byval_arg.type;
9718                         encode_cattr_value (assembly, buffer, p, &buffer, &p, buflen, &klass->byval_arg, arg, NULL);
9719                         break;
9720                 } else if (klass->byval_arg.type >= MONO_TYPE_BOOLEAN && klass->byval_arg.type <= MONO_TYPE_R8) {
9721                         *p++ = simple_type = klass->byval_arg.type;
9722                         goto handle_enum;
9723                 } else {
9724                         g_error ("unhandled type in custom attr");
9725                 }
9726                 str = type_get_qualified_name (mono_class_get_type(klass), NULL);
9727                 slen = strlen (str);
9728                 if ((p-buffer) + 10 + slen >= *buflen) {
9729                         char *newbuf;
9730                         *buflen *= 2;
9731                         *buflen += slen;
9732                         newbuf = g_realloc (buffer, *buflen);
9733                         p = newbuf + (p-buffer);
9734                         buffer = newbuf;
9735                 }
9736                 mono_metadata_encode_value (slen, p, &p);
9737                 memcpy (p, str, slen);
9738                 p += slen;
9739                 g_free (str);
9740                 simple_type = mono_class_enum_basetype (klass)->type;
9741                 goto handle_enum;
9742         }
9743         default:
9744                 g_error ("type 0x%02x not yet supported in custom attr encoder", simple_type);
9745         }
9746         *retp = p;
9747         *retbuffer = buffer;
9748 }
9749
9750 static void
9751 encode_field_or_prop_type (MonoType *type, char *p, char **retp)
9752 {
9753         if (type->type == MONO_TYPE_VALUETYPE && type->data.klass->enumtype) {
9754                 char *str = type_get_qualified_name (type, NULL);
9755                 int slen = strlen (str);
9756
9757                 *p++ = 0x55;
9758                 /*
9759                  * This seems to be optional...
9760                  * *p++ = 0x80;
9761                  */
9762                 mono_metadata_encode_value (slen, p, &p);
9763                 memcpy (p, str, slen);
9764                 p += slen;
9765                 g_free (str);
9766         } else if (type->type == MONO_TYPE_OBJECT) {
9767                 *p++ = 0x51;
9768         } else if (type->type == MONO_TYPE_CLASS) {
9769                 /* it should be a type: encode_cattr_value () has the check */
9770                 *p++ = 0x50;
9771         } else {
9772                 mono_metadata_encode_value (type->type, p, &p);
9773                 if (type->type == MONO_TYPE_SZARRAY)
9774                         /* See the examples in Partition VI, Annex B */
9775                         encode_field_or_prop_type (&type->data.klass->byval_arg, p, &p);
9776         }
9777
9778         *retp = p;
9779 }
9780
9781 #ifndef DISABLE_REFLECTION_EMIT
9782 static void
9783 encode_named_val (MonoReflectionAssembly *assembly, char *buffer, char *p, char **retbuffer, char **retp, guint32 *buflen, MonoType *type, char *name, MonoObject *value)
9784 {
9785         int len;
9786         /* Preallocate a large enough buffer */
9787         if (type->type == MONO_TYPE_VALUETYPE && type->data.klass->enumtype) {
9788                 char *str = type_get_qualified_name (type, NULL);
9789                 len = strlen (str);
9790                 g_free (str);
9791         } else if (type->type == MONO_TYPE_SZARRAY && type->data.klass->enumtype) {
9792                 char *str = type_get_qualified_name (&type->data.klass->byval_arg, NULL);
9793                 len = strlen (str);
9794                 g_free (str);
9795         } else {
9796                 len = 0;
9797         }
9798         len += strlen (name);
9799
9800         if ((p-buffer) + 20 + len >= *buflen) {
9801                 char *newbuf;
9802                 *buflen *= 2;
9803                 *buflen += len;
9804                 newbuf = g_realloc (buffer, *buflen);
9805                 p = newbuf + (p-buffer);
9806                 buffer = newbuf;
9807         }
9808
9809         encode_field_or_prop_type (type, p, &p);
9810
9811         len = strlen (name);
9812         mono_metadata_encode_value (len, p, &p);
9813         memcpy (p, name, len);
9814         p += len;
9815         encode_cattr_value (assembly->assembly, buffer, p, &buffer, &p, buflen, type, value, NULL);
9816         *retp = p;
9817         *retbuffer = buffer;
9818 }
9819
9820 /*
9821  * mono_reflection_get_custom_attrs_blob:
9822  * @ctor: custom attribute constructor
9823  * @ctorArgs: arguments o the constructor
9824  * @properties:
9825  * @propValues:
9826  * @fields:
9827  * @fieldValues:
9828  * 
9829  * Creates the blob of data that needs to be saved in the metadata and that represents
9830  * the custom attributed described by @ctor, @ctorArgs etc.
9831  * Returns: a Byte array representing the blob of data.
9832  */
9833 MonoArray*
9834 mono_reflection_get_custom_attrs_blob (MonoReflectionAssembly *assembly, MonoObject *ctor, MonoArray *ctorArgs, MonoArray *properties, MonoArray *propValues, MonoArray *fields, MonoArray* fieldValues) 
9835 {
9836         MonoArray *result;
9837         MonoMethodSignature *sig;
9838         MonoObject *arg;
9839         char *buffer, *p;
9840         guint32 buflen, i;
9841
9842         MONO_ARCH_SAVE_REGS;
9843
9844         if (strcmp (ctor->vtable->klass->name, "MonoCMethod")) {
9845                 /* sig is freed later so allocate it in the heap */
9846                 sig = ctor_builder_to_signature (NULL, (MonoReflectionCtorBuilder*)ctor);
9847         } else {
9848                 sig = mono_method_signature (((MonoReflectionMethod*)ctor)->method);
9849         }
9850
9851         g_assert (mono_array_length (ctorArgs) == sig->param_count);
9852         buflen = 256;
9853         p = buffer = g_malloc (buflen);
9854         /* write the prolog */
9855         *p++ = 1;
9856         *p++ = 0;
9857         for (i = 0; i < sig->param_count; ++i) {
9858                 arg = mono_array_get (ctorArgs, MonoObject*, i);
9859                 encode_cattr_value (assembly->assembly, buffer, p, &buffer, &p, &buflen, sig->params [i], arg, NULL);
9860         }
9861         i = 0;
9862         if (properties)
9863                 i += mono_array_length (properties);
9864         if (fields)
9865                 i += mono_array_length (fields);
9866         *p++ = i & 0xff;
9867         *p++ = (i >> 8) & 0xff;
9868         if (properties) {
9869                 MonoObject *prop;
9870                 for (i = 0; i < mono_array_length (properties); ++i) {
9871                         MonoType *ptype;
9872                         char *pname;
9873
9874                         prop = mono_array_get (properties, gpointer, i);
9875                         get_prop_name_and_type (prop, &pname, &ptype);
9876                         *p++ = 0x54; /* PROPERTY signature */
9877                         encode_named_val (assembly, buffer, p, &buffer, &p, &buflen, ptype, pname, (MonoObject*)mono_array_get (propValues, gpointer, i));
9878                         g_free (pname);
9879                 }
9880         }
9881
9882         if (fields) {
9883                 MonoObject *field;
9884                 for (i = 0; i < mono_array_length (fields); ++i) {
9885                         MonoType *ftype;
9886                         char *fname;
9887
9888                         field = mono_array_get (fields, gpointer, i);
9889                         get_field_name_and_type (field, &fname, &ftype);
9890                         *p++ = 0x53; /* FIELD signature */
9891                         encode_named_val (assembly, buffer, p, &buffer, &p, &buflen, ftype, fname, (MonoObject*)mono_array_get (fieldValues, gpointer, i));
9892                         g_free (fname);
9893                 }
9894         }
9895
9896         g_assert (p - buffer <= buflen);
9897         buflen = p - buffer;
9898         result = mono_array_new (mono_domain_get (), mono_defaults.byte_class, buflen);
9899         p = mono_array_addr (result, char, 0);
9900         memcpy (p, buffer, buflen);
9901         g_free (buffer);
9902         if (strcmp (ctor->vtable->klass->name, "MonoCMethod"))
9903                 g_free (sig);
9904         return result;
9905 }
9906
9907 /*
9908  * mono_reflection_setup_internal_class:
9909  * @tb: a TypeBuilder object
9910  *
9911  * Creates a MonoClass that represents the TypeBuilder.
9912  * This is a trick that lets us simplify a lot of reflection code
9913  * (and will allow us to support Build and Run assemblies easier).
9914  */
9915 void
9916 mono_reflection_setup_internal_class (MonoReflectionTypeBuilder *tb)
9917 {
9918         MonoError error;
9919         MonoClass *klass, *parent;
9920
9921         MONO_ARCH_SAVE_REGS;
9922
9923         RESOLVE_TYPE (tb->parent);
9924
9925         mono_loader_lock ();
9926
9927         if (tb->parent) {
9928                 /* check so we can compile corlib correctly */
9929                 if (strcmp (mono_object_class (tb->parent)->name, "TypeBuilder") == 0) {
9930                         /* mono_class_setup_mono_type () guaranteess type->data.klass is valid */
9931                         parent = mono_reflection_type_get_handle ((MonoReflectionType*)tb->parent)->data.klass;
9932                 } else {
9933                         parent = mono_class_from_mono_type (mono_reflection_type_get_handle ((MonoReflectionType*)tb->parent));
9934                 }
9935         } else {
9936                 parent = NULL;
9937         }
9938         
9939         /* the type has already being created: it means we just have to change the parent */
9940         if (tb->type.type) {
9941                 klass = mono_class_from_mono_type (tb->type.type);
9942                 klass->parent = NULL;
9943                 /* fool mono_class_setup_parent */
9944                 klass->supertypes = NULL;
9945                 mono_class_setup_parent (klass, parent);
9946                 mono_class_setup_mono_type (klass);
9947                 mono_loader_unlock ();
9948                 return;
9949         }
9950
9951         klass = mono_image_alloc0 (&tb->module->dynamic_image->image, sizeof (MonoClass));
9952
9953         klass->image = &tb->module->dynamic_image->image;
9954
9955         klass->inited = 1; /* we lie to the runtime */
9956         klass->name = mono_string_to_utf8_image (klass->image, tb->name, &error);
9957         if (!mono_error_ok (&error))
9958                 goto failure;
9959         klass->name_space = mono_string_to_utf8_image (klass->image, tb->nspace, &error);
9960         if (!mono_error_ok (&error))
9961                 goto failure;
9962         klass->type_token = MONO_TOKEN_TYPE_DEF | tb->table_idx;
9963         klass->flags = tb->attrs;
9964         
9965         mono_profiler_class_event (klass, MONO_PROFILE_START_LOAD);
9966
9967         klass->element_class = klass;
9968
9969         if (mono_class_get_ref_info (klass) == NULL) {
9970
9971                 mono_class_set_ref_info (klass, tb);
9972
9973                 /* Put into cache so mono_class_get () will find it.
9974                 Skip nested types as those should not be available on the global scope. */
9975                 if (!tb->nesting_type)
9976                         mono_image_add_to_name_cache (klass->image, klass->name_space, klass->name, tb->table_idx);
9977
9978                 /*
9979                 We must register all types as we cannot rely on the name_cache hashtable since we find the class
9980                 by performing a mono_class_get which does the full resolution.
9981
9982                 Working around this semantics would require us to write a lot of code for no clear advantage.
9983                 */
9984                 mono_image_append_class_to_reflection_info_set (klass);
9985         } else {
9986                 g_assert (mono_class_get_ref_info (klass) == tb);
9987         }
9988
9989         mono_g_hash_table_insert (tb->module->dynamic_image->tokens,
9990                 GUINT_TO_POINTER (MONO_TOKEN_TYPE_DEF | tb->table_idx), tb);
9991
9992         if (parent != NULL) {
9993                 mono_class_setup_parent (klass, parent);
9994         } else if (strcmp (klass->name, "Object") == 0 && strcmp (klass->name_space, "System") == 0) {
9995                 const char *old_n = klass->name;
9996                 /* trick to get relative numbering right when compiling corlib */
9997                 klass->name = "BuildingObject";
9998                 mono_class_setup_parent (klass, mono_defaults.object_class);
9999                 klass->name = old_n;
10000         }
10001
10002         if ((!strcmp (klass->name, "ValueType") && !strcmp (klass->name_space, "System")) ||
10003                         (!strcmp (klass->name, "Object") && !strcmp (klass->name_space, "System")) ||
10004                         (!strcmp (klass->name, "Enum") && !strcmp (klass->name_space, "System"))) {
10005                 klass->instance_size = sizeof (MonoObject);
10006                 klass->size_inited = 1;
10007                 mono_class_setup_vtable_general (klass, NULL, 0, NULL);
10008         }
10009
10010         mono_class_setup_mono_type (klass);
10011
10012         mono_class_setup_supertypes (klass);
10013
10014         /*
10015          * FIXME: handle interfaces.
10016          */
10017
10018         tb->type.type = &klass->byval_arg;
10019
10020         if (tb->nesting_type) {
10021                 g_assert (tb->nesting_type->type);
10022                 klass->nested_in = mono_class_from_mono_type (mono_reflection_type_get_handle (tb->nesting_type));
10023         }
10024
10025         /*g_print ("setup %s as %s (%p)\n", klass->name, ((MonoObject*)tb)->vtable->klass->name, tb);*/
10026
10027         mono_profiler_class_loaded (klass, MONO_PROFILE_OK);
10028         
10029         mono_loader_unlock ();
10030         return;
10031
10032 failure:
10033         mono_loader_unlock ();
10034         mono_error_raise_exception (&error);
10035 }
10036
10037 /*
10038  * mono_reflection_setup_generic_class:
10039  * @tb: a TypeBuilder object
10040  *
10041  * Setup the generic class before adding the first generic parameter.
10042  */
10043 void
10044 mono_reflection_setup_generic_class (MonoReflectionTypeBuilder *tb)
10045 {
10046 }
10047
10048 /*
10049  * mono_reflection_create_generic_class:
10050  * @tb: a TypeBuilder object
10051  *
10052  * Creates the generic class after all generic parameters have been added.
10053  */
10054 void
10055 mono_reflection_create_generic_class (MonoReflectionTypeBuilder *tb)
10056 {
10057         MonoClass *klass;
10058         int count, i;
10059
10060         MONO_ARCH_SAVE_REGS;
10061
10062         klass = mono_class_from_mono_type (tb->type.type);
10063
10064         count = tb->generic_params ? mono_array_length (tb->generic_params) : 0;
10065
10066         if (klass->generic_container || (count == 0))
10067                 return;
10068
10069         g_assert (tb->generic_container && (tb->generic_container->owner.klass == klass));
10070
10071         klass->generic_container = mono_image_alloc0 (klass->image, sizeof (MonoGenericContainer));
10072
10073         klass->generic_container->owner.klass = klass;
10074         klass->generic_container->type_argc = count;
10075         klass->generic_container->type_params = mono_image_alloc0 (klass->image, sizeof (MonoGenericParamFull) * count);
10076
10077         klass->is_generic = 1;
10078
10079         for (i = 0; i < count; i++) {
10080                 MonoReflectionGenericParam *gparam = mono_array_get (tb->generic_params, gpointer, i);
10081                 MonoGenericParamFull *param = (MonoGenericParamFull *) mono_reflection_type_get_handle ((MonoReflectionType*)gparam)->data.generic_param;
10082                 klass->generic_container->type_params [i] = *param;
10083                 /*Make sure we are a diferent type instance */
10084                 klass->generic_container->type_params [i].param.owner = klass->generic_container;
10085                 klass->generic_container->type_params [i].info.pklass = NULL;
10086                 klass->generic_container->type_params [i].info.flags = gparam->attrs;
10087
10088                 g_assert (klass->generic_container->type_params [i].param.owner);
10089         }
10090
10091         klass->generic_container->context.class_inst = mono_get_shared_generic_inst (klass->generic_container);
10092 }
10093
10094 /*
10095  * mono_reflection_create_internal_class:
10096  * @tb: a TypeBuilder object
10097  *
10098  * Actually create the MonoClass that is associated with the TypeBuilder.
10099  */
10100 void
10101 mono_reflection_create_internal_class (MonoReflectionTypeBuilder *tb)
10102 {
10103         MonoClass *klass;
10104
10105         MONO_ARCH_SAVE_REGS;
10106
10107         klass = mono_class_from_mono_type (tb->type.type);
10108
10109         mono_loader_lock ();
10110         if (klass->enumtype && mono_class_enum_basetype (klass) == NULL) {
10111                 MonoReflectionFieldBuilder *fb;
10112                 MonoClass *ec;
10113                 MonoType *enum_basetype;
10114
10115                 g_assert (tb->fields != NULL);
10116                 g_assert (mono_array_length (tb->fields) >= 1);
10117
10118                 fb = mono_array_get (tb->fields, MonoReflectionFieldBuilder*, 0);
10119
10120                 if (!mono_type_is_valid_enum_basetype (mono_reflection_type_get_handle ((MonoReflectionType*)fb->type))) {
10121                         mono_loader_unlock ();
10122                         return;
10123                 }
10124
10125                 enum_basetype = mono_reflection_type_get_handle ((MonoReflectionType*)fb->type);
10126                 klass->element_class = mono_class_from_mono_type (enum_basetype);
10127                 if (!klass->element_class)
10128                         klass->element_class = mono_class_from_mono_type (enum_basetype);
10129
10130                 /*
10131                  * get the element_class from the current corlib.
10132                  */
10133                 ec = default_class_from_mono_type (enum_basetype);
10134                 klass->instance_size = ec->instance_size;
10135                 klass->size_inited = 1;
10136                 /* 
10137                  * this is almost safe to do with enums and it's needed to be able
10138                  * to create objects of the enum type (for use in SetConstant).
10139                  */
10140                 /* FIXME: Does this mean enums can't have method overrides ? */
10141                 mono_class_setup_vtable_general (klass, NULL, 0, NULL);
10142         }
10143         mono_loader_unlock ();
10144 }
10145
10146 static MonoMarshalSpec*
10147 mono_marshal_spec_from_builder (MonoImage *image, MonoAssembly *assembly,
10148                                                                 MonoReflectionMarshal *minfo)
10149 {
10150         MonoMarshalSpec *res;
10151
10152         res = image_g_new0 (image, MonoMarshalSpec, 1);
10153         res->native = minfo->type;
10154
10155         switch (minfo->type) {
10156         case MONO_NATIVE_LPARRAY:
10157                 res->data.array_data.elem_type = minfo->eltype;
10158                 if (minfo->has_size) {
10159                         res->data.array_data.param_num = minfo->param_num;
10160                         res->data.array_data.num_elem = minfo->count;
10161                         res->data.array_data.elem_mult = minfo->param_num == -1 ? 0 : 1;
10162                 }
10163                 else {
10164                         res->data.array_data.param_num = -1;
10165                         res->data.array_data.num_elem = -1;
10166                         res->data.array_data.elem_mult = -1;
10167                 }
10168                 break;
10169
10170         case MONO_NATIVE_BYVALTSTR:
10171         case MONO_NATIVE_BYVALARRAY:
10172                 res->data.array_data.num_elem = minfo->count;
10173                 break;
10174
10175         case MONO_NATIVE_CUSTOM:
10176                 if (minfo->marshaltyperef)
10177                         res->data.custom_data.custom_name =
10178                                 type_get_fully_qualified_name (mono_reflection_type_get_handle ((MonoReflectionType*)minfo->marshaltyperef));
10179                 if (minfo->mcookie)
10180                         res->data.custom_data.cookie = mono_string_to_utf8 (minfo->mcookie);
10181                 break;
10182
10183         default:
10184                 break;
10185         }
10186
10187         return res;
10188 }
10189 #endif /* !DISABLE_REFLECTION_EMIT */
10190
10191 MonoReflectionMarshalAsAttribute*
10192 mono_reflection_marshal_as_attribute_from_marshal_spec (MonoDomain *domain, MonoClass *klass,
10193                                                                                    MonoMarshalSpec *spec)
10194 {
10195         static MonoClass *System_Reflection_Emit_MarshalAsAttribute;
10196         MonoReflectionMarshalAsAttribute *minfo;
10197         MonoType *mtype;
10198
10199         if (!System_Reflection_Emit_MarshalAsAttribute) {
10200                 System_Reflection_Emit_MarshalAsAttribute = mono_class_from_name (
10201                    mono_defaults.corlib, "System.Runtime.InteropServices", "MarshalAsAttribute");
10202                 g_assert (System_Reflection_Emit_MarshalAsAttribute);
10203         }
10204
10205         minfo = (MonoReflectionMarshalAsAttribute*)mono_object_new (domain, System_Reflection_Emit_MarshalAsAttribute);
10206         minfo->utype = spec->native;
10207
10208         switch (minfo->utype) {
10209         case MONO_NATIVE_LPARRAY:
10210                 minfo->array_subtype = spec->data.array_data.elem_type;
10211                 minfo->size_const = spec->data.array_data.num_elem;
10212                 if (spec->data.array_data.param_num != -1)
10213                         minfo->size_param_index = spec->data.array_data.param_num;
10214                 break;
10215
10216         case MONO_NATIVE_BYVALTSTR:
10217         case MONO_NATIVE_BYVALARRAY:
10218                 minfo->size_const = spec->data.array_data.num_elem;
10219                 break;
10220
10221         case MONO_NATIVE_CUSTOM:
10222                 if (spec->data.custom_data.custom_name) {
10223                         mtype = mono_reflection_type_from_name (spec->data.custom_data.custom_name, klass->image);
10224                         if (mtype)
10225                                 MONO_OBJECT_SETREF (minfo, marshal_type_ref, mono_type_get_object (domain, mtype));
10226
10227                         MONO_OBJECT_SETREF (minfo, marshal_type, mono_string_new (domain, spec->data.custom_data.custom_name));
10228                 }
10229                 if (spec->data.custom_data.cookie)
10230                         MONO_OBJECT_SETREF (minfo, marshal_cookie, mono_string_new (domain, spec->data.custom_data.cookie));
10231                 break;
10232
10233         default:
10234                 break;
10235         }
10236
10237         return minfo;
10238 }
10239
10240 #ifndef DISABLE_REFLECTION_EMIT
10241 static MonoMethod*
10242 reflection_methodbuilder_to_mono_method (MonoClass *klass,
10243                                          ReflectionMethodBuilder *rmb,
10244                                          MonoMethodSignature *sig)
10245 {
10246         MonoError error;
10247         MonoMethod *m;
10248         MonoMethodWrapper *wrapperm;
10249         MonoMarshalSpec **specs;
10250         MonoReflectionMethodAux *method_aux;
10251         MonoImage *image;
10252         gboolean dynamic;
10253         int i;
10254
10255         mono_error_init (&error);
10256         /*
10257          * Methods created using a MethodBuilder should have their memory allocated
10258          * inside the image mempool, while dynamic methods should have their memory
10259          * malloc'd.
10260          */
10261         dynamic = rmb->refs != NULL;
10262         image = dynamic ? NULL : klass->image;
10263
10264         if (!dynamic)
10265                 g_assert (!klass->generic_class);
10266
10267         mono_loader_lock ();
10268
10269         if ((rmb->attrs & METHOD_ATTRIBUTE_PINVOKE_IMPL) ||
10270                         (rmb->iattrs & METHOD_IMPL_ATTRIBUTE_INTERNAL_CALL))
10271                 m = (MonoMethod *)image_g_new0 (image, MonoMethodPInvoke, 1);
10272         else
10273                 m = (MonoMethod *)image_g_new0 (image, MonoMethodWrapper, 1);
10274
10275         wrapperm = (MonoMethodWrapper*)m;
10276
10277         m->dynamic = dynamic;
10278         m->slot = -1;
10279         m->flags = rmb->attrs;
10280         m->iflags = rmb->iattrs;
10281         m->name = mono_string_to_utf8_image_ignore (image, rmb->name);
10282         m->klass = klass;
10283         m->signature = sig;
10284         m->sre_method = TRUE;
10285         m->skip_visibility = rmb->skip_visibility;
10286         if (rmb->table_idx)
10287                 m->token = MONO_TOKEN_METHOD_DEF | (*rmb->table_idx);
10288
10289         if (m->iflags & METHOD_IMPL_ATTRIBUTE_INTERNAL_CALL) {
10290                 if (klass == mono_defaults.string_class && !strcmp (m->name, ".ctor"))
10291                         m->string_ctor = 1;
10292
10293                 m->signature->pinvoke = 1;
10294         } else if (m->flags & METHOD_ATTRIBUTE_PINVOKE_IMPL) {
10295                 m->signature->pinvoke = 1;
10296
10297                 method_aux = image_g_new0 (image, MonoReflectionMethodAux, 1);
10298
10299                 method_aux->dllentry = rmb->dllentry ? mono_string_to_utf8_image (image, rmb->dllentry, &error) : image_strdup (image, m->name);
10300                 g_assert (mono_error_ok (&error));
10301                 method_aux->dll = mono_string_to_utf8_image (image, rmb->dll, &error);
10302                 g_assert (mono_error_ok (&error));
10303                 
10304                 ((MonoMethodPInvoke*)m)->piflags = (rmb->native_cc << 8) | (rmb->charset ? (rmb->charset - 1) * 2 : 0) | rmb->extra_flags;
10305
10306                 if (klass->image->dynamic)
10307                         g_hash_table_insert (((MonoDynamicImage*)klass->image)->method_aux_hash, m, method_aux);
10308
10309                 mono_loader_unlock ();
10310
10311                 return m;
10312         } else if (!(m->flags & METHOD_ATTRIBUTE_ABSTRACT) &&
10313                            !(m->iflags & METHOD_IMPL_ATTRIBUTE_RUNTIME)) {
10314                 MonoMethodHeader *header;
10315                 guint32 code_size;
10316                 gint32 max_stack, i;
10317                 gint32 num_locals = 0;
10318                 gint32 num_clauses = 0;
10319                 guint8 *code;
10320
10321                 if (rmb->ilgen) {
10322                         code = mono_array_addr (rmb->ilgen->code, guint8, 0);
10323                         code_size = rmb->ilgen->code_len;
10324                         max_stack = rmb->ilgen->max_stack;
10325                         num_locals = rmb->ilgen->locals ? mono_array_length (rmb->ilgen->locals) : 0;
10326                         if (rmb->ilgen->ex_handlers)
10327                                 num_clauses = method_count_clauses (rmb->ilgen);
10328                 } else {
10329                         if (rmb->code) {
10330                                 code = mono_array_addr (rmb->code, guint8, 0);
10331                                 code_size = mono_array_length (rmb->code);
10332                                 /* we probably need to run a verifier on the code... */
10333                                 max_stack = 8; 
10334                         }
10335                         else {
10336                                 code = NULL;
10337                                 code_size = 0;
10338                                 max_stack = 8;
10339                         }
10340                 }
10341
10342                 header = image_g_malloc0 (image, MONO_SIZEOF_METHOD_HEADER + num_locals * sizeof (MonoType*));
10343                 header->code_size = code_size;
10344                 header->code = image_g_malloc (image, code_size);
10345                 memcpy ((char*)header->code, code, code_size);
10346                 header->max_stack = max_stack;
10347                 header->init_locals = rmb->init_locals;
10348                 header->num_locals = num_locals;
10349
10350                 for (i = 0; i < num_locals; ++i) {
10351                         MonoReflectionLocalBuilder *lb = 
10352                                 mono_array_get (rmb->ilgen->locals, MonoReflectionLocalBuilder*, i);
10353
10354                         header->locals [i] = image_g_new0 (image, MonoType, 1);
10355                         memcpy (header->locals [i], mono_reflection_type_get_handle ((MonoReflectionType*)lb->type), MONO_SIZEOF_TYPE);
10356                 }
10357
10358                 header->num_clauses = num_clauses;
10359                 if (num_clauses) {
10360                         header->clauses = method_encode_clauses (image, (MonoDynamicImage*)klass->image,
10361                                  rmb->ilgen, num_clauses);
10362                 }
10363
10364                 wrapperm->header = header;
10365         }
10366
10367         if (rmb->generic_params) {
10368                 int count = mono_array_length (rmb->generic_params);
10369                 MonoGenericContainer *container = rmb->generic_container;
10370
10371                 g_assert (container);
10372
10373                 container->type_argc = count;
10374                 container->type_params = image_g_new0 (image, MonoGenericParamFull, count);
10375                 container->owner.method = m;
10376
10377                 m->is_generic = TRUE;
10378                 mono_method_set_generic_container (m, container);
10379
10380                 for (i = 0; i < count; i++) {
10381                         MonoReflectionGenericParam *gp =
10382                                 mono_array_get (rmb->generic_params, MonoReflectionGenericParam*, i);
10383                         MonoGenericParamFull *param = (MonoGenericParamFull *) mono_reflection_type_get_handle ((MonoReflectionType*)gp)->data.generic_param;
10384                         container->type_params [i] = *param;
10385                 }
10386
10387                 /*
10388                  * The method signature might have pointers to generic parameters that belong to other methods.
10389                  * This is a valid SRE case, but the resulting method signature must be encoded using the proper
10390                  * generic parameters.
10391                  */
10392                 for (i = 0; i < m->signature->param_count; ++i) {
10393                         MonoType *t = m->signature->params [i];
10394                         if (t->type == MONO_TYPE_MVAR) {
10395                                 MonoGenericParam *gparam =  t->data.generic_param;
10396                                 if (gparam->num < count) {
10397                                         m->signature->params [i] = mono_metadata_type_dup (image, m->signature->params [i]);
10398                                         m->signature->params [i]->data.generic_param = mono_generic_container_get_param (container, gparam->num);
10399                                 }
10400
10401                         }
10402                 }
10403
10404                 if (klass->generic_container) {
10405                         container->parent = klass->generic_container;
10406                         container->context.class_inst = klass->generic_container->context.class_inst;
10407                 }
10408                 container->context.method_inst = mono_get_shared_generic_inst (container);
10409         }
10410
10411         if (rmb->refs) {
10412                 MonoMethodWrapper *mw = (MonoMethodWrapper*)m;
10413                 int i;
10414                 void **data;
10415
10416                 m->wrapper_type = MONO_WRAPPER_DYNAMIC_METHOD;
10417
10418                 mw->method_data = data = image_g_new (image, gpointer, rmb->nrefs + 1);
10419                 data [0] = GUINT_TO_POINTER (rmb->nrefs);
10420                 for (i = 0; i < rmb->nrefs; ++i)
10421                         data [i + 1] = rmb->refs [i];
10422         }
10423
10424         method_aux = NULL;
10425
10426         /* Parameter info */
10427         if (rmb->pinfo) {
10428                 if (!method_aux)
10429                         method_aux = image_g_new0 (image, MonoReflectionMethodAux, 1);
10430                 method_aux->param_names = image_g_new0 (image, char *, mono_method_signature (m)->param_count + 1);
10431                 for (i = 0; i <= m->signature->param_count; ++i) {
10432                         MonoReflectionParamBuilder *pb;
10433                         if ((pb = mono_array_get (rmb->pinfo, MonoReflectionParamBuilder*, i))) {
10434                                 if ((i > 0) && (pb->attrs)) {
10435                                         /* Make a copy since it might point to a shared type structure */
10436                                         m->signature->params [i - 1] = mono_metadata_type_dup (klass->image, m->signature->params [i - 1]);
10437                                         m->signature->params [i - 1]->attrs = pb->attrs;
10438                                 }
10439
10440                                 if (pb->attrs & PARAM_ATTRIBUTE_HAS_DEFAULT) {
10441                                         MonoDynamicImage *assembly;
10442                                         guint32 idx, def_type, len;
10443                                         char *p;
10444                                         const char *p2;
10445
10446                                         if (!method_aux->param_defaults) {
10447                                                 method_aux->param_defaults = image_g_new0 (image, guint8*, m->signature->param_count + 1);
10448                                                 method_aux->param_default_types = image_g_new0 (image, guint32, m->signature->param_count + 1);
10449                                         }
10450                                         assembly = (MonoDynamicImage*)klass->image;
10451                                         idx = encode_constant (assembly, pb->def_value, &def_type);
10452                                         /* Copy the data from the blob since it might get realloc-ed */
10453                                         p = assembly->blob.data + idx;
10454                                         len = mono_metadata_decode_blob_size (p, &p2);
10455                                         len += p2 - p;
10456                                         method_aux->param_defaults [i] = image_g_malloc (image, len);
10457                                         method_aux->param_default_types [i] = def_type;
10458                                         memcpy ((gpointer)method_aux->param_defaults [i], p, len);
10459                                 }
10460
10461                                 if (pb->name) {
10462                                         method_aux->param_names [i] = mono_string_to_utf8_image (image, pb->name, &error);
10463                                         g_assert (mono_error_ok (&error));
10464                                 }
10465                                 if (pb->cattrs) {
10466                                         if (!method_aux->param_cattr)
10467                                                 method_aux->param_cattr = image_g_new0 (image, MonoCustomAttrInfo*, m->signature->param_count + 1);
10468                                         method_aux->param_cattr [i] = mono_custom_attrs_from_builders (image, klass->image, pb->cattrs);
10469                                 }
10470                         }
10471                 }
10472         }
10473
10474         /* Parameter marshalling */
10475         specs = NULL;
10476         if (rmb->pinfo)         
10477                 for (i = 0; i < mono_array_length (rmb->pinfo); ++i) {
10478                         MonoReflectionParamBuilder *pb;
10479                         if ((pb = mono_array_get (rmb->pinfo, MonoReflectionParamBuilder*, i))) {
10480                                 if (pb->marshal_info) {
10481                                         if (specs == NULL)
10482                                                 specs = image_g_new0 (image, MonoMarshalSpec*, sig->param_count + 1);
10483                                         specs [pb->position] = 
10484                                                 mono_marshal_spec_from_builder (image, klass->image->assembly, pb->marshal_info);
10485                                 }
10486                         }
10487                 }
10488         if (specs != NULL) {
10489                 if (!method_aux)
10490                         method_aux = image_g_new0 (image, MonoReflectionMethodAux, 1);
10491                 method_aux->param_marshall = specs;
10492         }
10493
10494         if (klass->image->dynamic && method_aux)
10495                 g_hash_table_insert (((MonoDynamicImage*)klass->image)->method_aux_hash, m, method_aux);
10496
10497         mono_loader_unlock ();
10498
10499         return m;
10500 }       
10501
10502 static MonoMethod*
10503 ctorbuilder_to_mono_method (MonoClass *klass, MonoReflectionCtorBuilder* mb)
10504 {
10505         ReflectionMethodBuilder rmb;
10506         MonoMethodSignature *sig;
10507
10508         mono_loader_lock ();
10509         sig = ctor_builder_to_signature (klass->image, mb);
10510         mono_loader_unlock ();
10511
10512         reflection_methodbuilder_from_ctor_builder (&rmb, mb);
10513
10514         mb->mhandle = reflection_methodbuilder_to_mono_method (klass, &rmb, sig);
10515         mono_save_custom_attrs (klass->image, mb->mhandle, mb->cattrs);
10516
10517         /* If we are in a generic class, we might be called multiple times from inflate_method */
10518         if (!((MonoDynamicImage*)(MonoDynamicImage*)klass->image)->save && !klass->generic_container) {
10519                 /* ilgen is no longer needed */
10520                 mb->ilgen = NULL;
10521         }
10522
10523         return mb->mhandle;
10524 }
10525
10526 static MonoMethod*
10527 methodbuilder_to_mono_method (MonoClass *klass, MonoReflectionMethodBuilder* mb)
10528 {
10529         ReflectionMethodBuilder rmb;
10530         MonoMethodSignature *sig;
10531
10532         mono_loader_lock ();
10533         sig = method_builder_to_signature (klass->image, mb);
10534         mono_loader_unlock ();
10535
10536         reflection_methodbuilder_from_method_builder (&rmb, mb);
10537
10538         mb->mhandle = reflection_methodbuilder_to_mono_method (klass, &rmb, sig);
10539         mono_save_custom_attrs (klass->image, mb->mhandle, mb->cattrs);
10540
10541         /* If we are in a generic class, we might be called multiple times from inflate_method */
10542         if (!((MonoDynamicImage*)(MonoDynamicImage*)klass->image)->save && !klass->generic_container) {
10543                 /* ilgen is no longer needed */
10544                 mb->ilgen = NULL;
10545         }
10546         return mb->mhandle;
10547 }
10548
10549 static MonoClassField*
10550 fieldbuilder_to_mono_class_field (MonoClass *klass, MonoReflectionFieldBuilder* fb)
10551 {
10552         MonoClassField *field;
10553         MonoType *custom;
10554         MonoError error;
10555
10556         field = g_new0 (MonoClassField, 1);
10557
10558         field->name = mono_string_to_utf8_image (klass->image, fb->name, &error);
10559         g_assert (mono_error_ok (&error));
10560         if (fb->attrs || fb->modreq || fb->modopt) {
10561                 field->type = mono_metadata_type_dup (NULL, mono_reflection_type_get_handle ((MonoReflectionType*)fb->type));
10562                 field->type->attrs = fb->attrs;
10563
10564                 g_assert (klass->image->dynamic);
10565                 custom = add_custom_modifiers ((MonoDynamicImage*)klass->image, field->type, fb->modreq, fb->modopt);
10566                 g_free (field->type);
10567                 field->type = mono_metadata_type_dup (klass->image, custom);
10568                 g_free (custom);
10569         } else {
10570                 field->type = mono_reflection_type_get_handle ((MonoReflectionType*)fb->type);
10571         }
10572         if (fb->offset != -1)
10573                 field->offset = fb->offset;
10574         field->parent = klass;
10575         mono_save_custom_attrs (klass->image, field, fb->cattrs);
10576
10577         // FIXME: Can't store fb->def_value/RVA, is it needed for field_on_insts ?
10578
10579         return field;
10580 }
10581 #endif
10582
10583 MonoType*
10584 mono_reflection_bind_generic_parameters (MonoReflectionType *type, int type_argc, MonoType **types)
10585 {
10586         MonoClass *klass;
10587         MonoReflectionTypeBuilder *tb = NULL;
10588         gboolean is_dynamic = FALSE;
10589         MonoDomain *domain;
10590         MonoClass *geninst;
10591
10592         mono_loader_lock ();
10593
10594         domain = mono_object_domain (type);
10595
10596         if (is_sre_type_builder (mono_object_class (type))) {
10597                 tb = (MonoReflectionTypeBuilder *) type;
10598
10599                 is_dynamic = TRUE;
10600         } else if (is_sre_generic_instance (mono_object_class (type))) {
10601                 MonoReflectionGenericClass *rgi = (MonoReflectionGenericClass *) type;
10602                 MonoReflectionType *gtd = rgi->generic_type;
10603
10604                 if (is_sre_type_builder (mono_object_class (gtd))) {
10605                         tb = (MonoReflectionTypeBuilder *)gtd;
10606                         is_dynamic = TRUE;
10607                 }
10608         }
10609
10610         /* FIXME: fix the CreateGenericParameters protocol to avoid the two stage setup of TypeBuilders */
10611         if (tb && tb->generic_container)
10612                 mono_reflection_create_generic_class (tb);
10613
10614         klass = mono_class_from_mono_type (mono_reflection_type_get_handle (type));
10615         if (!klass->generic_container) {
10616                 mono_loader_unlock ();
10617                 return NULL;
10618         }
10619
10620         if (klass->wastypebuilder) {
10621                 tb = (MonoReflectionTypeBuilder *) mono_class_get_ref_info (klass);
10622
10623                 is_dynamic = TRUE;
10624         }
10625
10626         mono_loader_unlock ();
10627
10628         geninst = mono_class_bind_generic_parameters (klass, type_argc, types, is_dynamic);
10629
10630         return &geninst->byval_arg;
10631 }
10632
10633 MonoClass*
10634 mono_class_bind_generic_parameters (MonoClass *klass, int type_argc, MonoType **types, gboolean is_dynamic)
10635 {
10636         MonoGenericClass *gclass;
10637         MonoGenericInst *inst;
10638
10639         g_assert (klass->generic_container);
10640
10641         inst = mono_metadata_get_generic_inst (type_argc, types);
10642         gclass = mono_metadata_lookup_generic_class (klass, inst, is_dynamic);
10643
10644         return mono_generic_class_get_class (gclass);
10645 }
10646
10647 MonoReflectionMethod*
10648 mono_reflection_bind_generic_method_parameters (MonoReflectionMethod *rmethod, MonoArray *types)
10649 {
10650         MonoClass *klass;
10651         MonoMethod *method, *inflated;
10652         MonoMethodInflated *imethod;
10653         MonoGenericContext tmp_context;
10654         MonoGenericInst *ginst;
10655         MonoType **type_argv;
10656         int count, i;
10657
10658         MONO_ARCH_SAVE_REGS;
10659
10660         /*FIXME but this no longer should happen*/
10661         if (!strcmp (rmethod->object.vtable->klass->name, "MethodBuilder")) {
10662 #ifndef DISABLE_REFLECTION_EMIT
10663                 MonoReflectionMethodBuilder *mb = NULL;
10664                 MonoReflectionTypeBuilder *tb;
10665                 MonoClass *klass;
10666
10667                 mb = (MonoReflectionMethodBuilder *) rmethod;
10668                 tb = (MonoReflectionTypeBuilder *) mb->type;
10669                 klass = mono_class_from_mono_type (mono_reflection_type_get_handle ((MonoReflectionType*)tb));
10670
10671                 method = methodbuilder_to_mono_method (klass, mb);
10672 #else
10673                 g_assert_not_reached ();
10674                 method = NULL;
10675 #endif
10676         } else {
10677                 method = rmethod->method;
10678         }
10679
10680         klass = method->klass;
10681
10682         if (method->is_inflated)
10683                 method = ((MonoMethodInflated *) method)->declaring;
10684
10685         count = mono_method_signature (method)->generic_param_count;
10686         if (count != mono_array_length (types))
10687                 return NULL;
10688
10689         type_argv = g_new0 (MonoType *, count);
10690         for (i = 0; i < count; i++) {
10691                 MonoReflectionType *garg = mono_array_get (types, gpointer, i);
10692                 type_argv [i] = mono_reflection_type_get_handle (garg);
10693         }
10694         ginst = mono_metadata_get_generic_inst (count, type_argv);
10695         g_free (type_argv);
10696
10697         tmp_context.class_inst = klass->generic_class ? klass->generic_class->context.class_inst : NULL;
10698         tmp_context.method_inst = ginst;
10699
10700         inflated = mono_class_inflate_generic_method (method, &tmp_context);
10701         imethod = (MonoMethodInflated *) inflated;
10702
10703         /*FIXME but I think this is no longer necessary*/
10704         if (method->klass->image->dynamic) {
10705                 MonoDynamicImage *image = (MonoDynamicImage*)method->klass->image;
10706                 /*
10707                  * This table maps metadata structures representing inflated methods/fields
10708                  * to the reflection objects representing their generic definitions.
10709                  */
10710                 mono_image_lock ((MonoImage*)image);
10711                 mono_g_hash_table_insert (image->generic_def_objects, imethod, rmethod);
10712                 mono_image_unlock ((MonoImage*)image);
10713         }
10714
10715         if (!mono_verifier_is_method_valid_generic_instantiation (inflated))
10716                 mono_raise_exception (mono_get_exception_argument ("typeArguments", "Invalid generic arguments"));
10717         
10718         return mono_method_get_object (mono_object_domain (rmethod), inflated, NULL);
10719 }
10720
10721 #ifndef DISABLE_REFLECTION_EMIT
10722
10723 static MonoMethod *
10724 inflate_mono_method (MonoClass *klass, MonoMethod *method, MonoObject *obj)
10725 {
10726         MonoMethodInflated *imethod;
10727         MonoGenericContext *context;
10728         int i;
10729
10730         /*
10731          * With generic code sharing the klass might not be inflated.
10732          * This can happen because classes inflated with their own
10733          * type arguments are "normalized" to the uninflated class.
10734          */
10735         if (!klass->generic_class)
10736                 return method;
10737
10738         context = mono_class_get_context (klass);
10739
10740         if (klass->method.count && klass->methods) {
10741                 /* Find the already created inflated method */
10742                 for (i = 0; i < klass->method.count; ++i) {
10743                         g_assert (klass->methods [i]->is_inflated);
10744                         if (((MonoMethodInflated*)klass->methods [i])->declaring == method)
10745                                 break;
10746                 }
10747                 g_assert (i < klass->method.count);
10748                 imethod = (MonoMethodInflated*)klass->methods [i];
10749         } else {
10750                 imethod = (MonoMethodInflated *) mono_class_inflate_generic_method_full (method, klass, context);
10751         }
10752
10753         if (method->is_generic && method->klass->image->dynamic) {
10754                 MonoDynamicImage *image = (MonoDynamicImage*)method->klass->image;
10755
10756                 mono_image_lock ((MonoImage*)image);
10757                 mono_g_hash_table_insert (image->generic_def_objects, imethod, obj);
10758                 mono_image_unlock ((MonoImage*)image);
10759         }
10760         return (MonoMethod *) imethod;
10761 }
10762
10763 static MonoMethod *
10764 inflate_method (MonoReflectionType *type, MonoObject *obj)
10765 {
10766         MonoMethod *method;
10767         MonoClass *gklass;
10768
10769         MonoClass *type_class = mono_object_class (type);
10770
10771         if (is_sre_generic_instance (type_class)) {
10772                 MonoReflectionGenericClass *mgc = (MonoReflectionGenericClass*)type;
10773                 gklass = mono_class_from_mono_type (mono_reflection_type_get_handle ((MonoReflectionType*)mgc->generic_type));
10774         } else if (is_sre_type_builder (type_class)) {
10775                 gklass = mono_class_from_mono_type (mono_reflection_type_get_handle (type));
10776         } else if (type->type) {
10777                 gklass = mono_class_from_mono_type (type->type);
10778                 gklass = mono_class_get_generic_type_definition (gklass);
10779         } else {
10780                 g_error ("Can't handle type %s", mono_type_get_full_name (mono_object_class (type)));
10781         }
10782
10783         if (!strcmp (obj->vtable->klass->name, "MethodBuilder"))
10784                 if (((MonoReflectionMethodBuilder*)obj)->mhandle)
10785                         method = ((MonoReflectionMethodBuilder*)obj)->mhandle;
10786                 else
10787                         method = methodbuilder_to_mono_method (gklass, (MonoReflectionMethodBuilder *) obj);
10788         else if (!strcmp (obj->vtable->klass->name, "ConstructorBuilder"))
10789                 method = ctorbuilder_to_mono_method (gklass, (MonoReflectionCtorBuilder *) obj);
10790         else if (!strcmp (obj->vtable->klass->name, "MonoMethod") || !strcmp (obj->vtable->klass->name, "MonoCMethod"))
10791                 method = ((MonoReflectionMethod *) obj)->method;
10792         else {
10793                 method = NULL; /* prevent compiler warning */
10794                 g_error ("can't handle type %s", obj->vtable->klass->name);
10795         }
10796
10797         return inflate_mono_method (mono_class_from_mono_type (mono_reflection_type_get_handle ((MonoReflectionType*)type)), method, obj);
10798 }
10799
10800 /*TODO avoid saving custom attrs for generic classes as it's enough to have them on the generic type definition.*/
10801 void
10802 mono_reflection_generic_class_initialize (MonoReflectionGenericClass *type, MonoArray *fields)
10803 {
10804         MonoGenericClass *gclass;
10805         MonoDynamicGenericClass *dgclass;
10806         MonoClass *klass, *gklass;
10807         MonoType *gtype;
10808         int i;
10809
10810         MONO_ARCH_SAVE_REGS;
10811
10812         gtype = mono_reflection_type_get_handle ((MonoReflectionType*)type);
10813         klass = mono_class_from_mono_type (gtype);
10814         g_assert (gtype->type == MONO_TYPE_GENERICINST);
10815         gclass = gtype->data.generic_class;
10816
10817         if (!gclass->is_dynamic)
10818                 return;
10819
10820         dgclass = (MonoDynamicGenericClass *) gclass;
10821
10822         if (dgclass->initialized)
10823                 return;
10824
10825         gklass = gclass->container_class;
10826         mono_class_init (gklass);
10827
10828         dgclass->count_fields = fields ? mono_array_length (fields) : 0;
10829
10830         dgclass->fields = mono_image_set_new0 (gclass->owner, MonoClassField, dgclass->count_fields);
10831         dgclass->field_objects = mono_image_set_new0 (gclass->owner, MonoObject*, dgclass->count_fields);
10832         dgclass->field_generic_types = mono_image_set_new0 (gclass->owner, MonoType*, dgclass->count_fields);
10833
10834         for (i = 0; i < dgclass->count_fields; i++) {
10835                 MonoObject *obj = mono_array_get (fields, gpointer, i);
10836                 MonoClassField *field, *inflated_field = NULL;
10837
10838                 if (!strcmp (obj->vtable->klass->name, "FieldBuilder"))
10839                         inflated_field = field = fieldbuilder_to_mono_class_field (klass, (MonoReflectionFieldBuilder *) obj);
10840                 else if (!strcmp (obj->vtable->klass->name, "MonoField"))
10841                         field = ((MonoReflectionField *) obj)->field;
10842                 else {
10843                         field = NULL; /* prevent compiler warning */
10844                         g_assert_not_reached ();
10845                 }
10846
10847                 dgclass->fields [i] = *field;
10848                 dgclass->fields [i].parent = klass;
10849                 dgclass->fields [i].type = mono_class_inflate_generic_type (
10850                         field->type, mono_generic_class_get_context ((MonoGenericClass *) dgclass));
10851                 dgclass->field_generic_types [i] = field->type;
10852                 MONO_GC_REGISTER_ROOT_IF_MOVING (dgclass->field_objects [i]);
10853                 dgclass->field_objects [i] = obj;
10854
10855                 if (inflated_field) {
10856                         g_free (inflated_field);
10857                 } else {
10858                         dgclass->fields [i].name = mono_image_set_strdup (gclass->owner, dgclass->fields [i].name);
10859                 }
10860         }
10861
10862         dgclass->initialized = TRUE;
10863 }
10864
10865 void
10866 mono_reflection_free_dynamic_generic_class (MonoGenericClass *gclass)
10867 {
10868         MonoDynamicGenericClass *dgclass;
10869         int i;
10870
10871         g_assert (gclass->is_dynamic);
10872
10873         dgclass = (MonoDynamicGenericClass *)gclass;
10874
10875         for (i = 0; i < dgclass->count_fields; ++i) {
10876                 MonoClassField *field = dgclass->fields + i;
10877                 mono_metadata_free_type (field->type);
10878                 MONO_GC_UNREGISTER_ROOT_IF_MOVING (dgclass->field_objects [i]);
10879         }
10880 }
10881
10882 static void
10883 fix_partial_generic_class (MonoClass *klass)
10884 {
10885         MonoClass *gklass = klass->generic_class->container_class;
10886         MonoDynamicGenericClass *dgclass;
10887         int i;
10888
10889         if (klass->wastypebuilder)
10890                 return;
10891
10892         dgclass = (MonoDynamicGenericClass *)  klass->generic_class;
10893         if (klass->parent != gklass->parent) {
10894                 MonoError error;
10895                 MonoType *parent_type = mono_class_inflate_generic_type_checked (&gklass->parent->byval_arg, &klass->generic_class->context, &error);
10896                 if (mono_error_ok (&error)) {
10897                         MonoClass *parent = mono_class_from_mono_type (parent_type);
10898                         mono_metadata_free_type (parent_type);
10899                         if (parent != klass->parent) {
10900                                 /*fool mono_class_setup_parent*/
10901                                 klass->supertypes = NULL;
10902                                 mono_class_setup_parent (klass, parent);
10903                         }
10904                 } else {
10905                         mono_class_set_failure (klass, MONO_EXCEPTION_TYPE_LOAD, NULL);
10906                         mono_error_cleanup (&error);
10907                         if (gklass->wastypebuilder)
10908                                 klass->wastypebuilder = TRUE;
10909                         return;
10910                 }
10911         }
10912
10913         if (!dgclass->initialized)
10914                 return;
10915
10916         if (klass->method.count != gklass->method.count) {
10917                 klass->method.count = gklass->method.count;
10918                 klass->methods = mono_image_alloc (klass->image, sizeof (MonoMethod*) * (klass->method.count + 1));
10919
10920                 for (i = 0; i < klass->method.count; i++) {
10921                         klass->methods [i] = mono_class_inflate_generic_method_full (
10922                                 gklass->methods [i], klass, mono_class_get_context (klass));
10923                 }
10924         }
10925
10926         if (klass->interface_count && klass->interface_count != gklass->interface_count) {
10927                 klass->interface_count = gklass->interface_count;
10928                 klass->interfaces = mono_image_alloc (klass->image, sizeof (MonoClass*) * gklass->interface_count);
10929                 klass->interfaces_packed = NULL; /*make setup_interface_offsets happy*/
10930
10931                 for (i = 0; i < gklass->interface_count; ++i) {
10932                         MonoType *iface_type = mono_class_inflate_generic_type (&gklass->interfaces [i]->byval_arg, mono_class_get_context (klass));
10933                         klass->interfaces [i] = mono_class_from_mono_type (iface_type);
10934                         mono_metadata_free_type (iface_type);
10935
10936                         ensure_runtime_vtable (klass->interfaces [i]);
10937                 }
10938                 klass->interfaces_inited = 1;
10939         }
10940
10941         if (klass->field.count != gklass->field.count) {
10942                 klass->field.count = gklass->field.count;
10943                 klass->fields = image_g_new0 (klass->image, MonoClassField, klass->field.count);
10944
10945                 for (i = 0; i < klass->field.count; i++) {
10946                         klass->fields [i] = gklass->fields [i];
10947                         klass->fields [i].parent = klass;
10948                         klass->fields [i].type = mono_class_inflate_generic_type (gklass->fields [i].type, mono_class_get_context (klass));
10949                 }
10950         }
10951
10952         /*We can only finish with this klass once it's parent has as well*/
10953         if (gklass->wastypebuilder)
10954                 klass->wastypebuilder = TRUE;
10955         return;
10956 }
10957
10958 static void
10959 ensure_generic_class_runtime_vtable (MonoClass *klass)
10960 {
10961         MonoClass *gklass = klass->generic_class->container_class;
10962
10963         ensure_runtime_vtable (gklass); 
10964
10965         fix_partial_generic_class (klass);
10966 }
10967
10968 static void
10969 ensure_runtime_vtable (MonoClass *klass)
10970 {
10971         MonoReflectionTypeBuilder *tb = mono_class_get_ref_info (klass);
10972         int i, num, j;
10973
10974         if (!klass->image->dynamic || (!tb && !klass->generic_class) || klass->wastypebuilder)
10975                 return;
10976         if (klass->parent)
10977                 ensure_runtime_vtable (klass->parent);
10978
10979         if (tb) {
10980                 num = tb->ctors? mono_array_length (tb->ctors): 0;
10981                 num += tb->num_methods;
10982                 klass->method.count = num;
10983                 klass->methods = mono_image_alloc (klass->image, sizeof (MonoMethod*) * num);
10984                 num = tb->ctors? mono_array_length (tb->ctors): 0;
10985                 for (i = 0; i < num; ++i)
10986                         klass->methods [i] = ctorbuilder_to_mono_method (klass, mono_array_get (tb->ctors, MonoReflectionCtorBuilder*, i));
10987                 num = tb->num_methods;
10988                 j = i;
10989                 for (i = 0; i < num; ++i)
10990                         klass->methods [j++] = methodbuilder_to_mono_method (klass, mono_array_get (tb->methods, MonoReflectionMethodBuilder*, i));
10991         
10992                 if (tb->interfaces) {
10993                         klass->interface_count = mono_array_length (tb->interfaces);
10994                         klass->interfaces = mono_image_alloc (klass->image, sizeof (MonoClass*) * klass->interface_count);
10995                         for (i = 0; i < klass->interface_count; ++i) {
10996                                 MonoType *iface = mono_type_array_get_and_resolve (tb->interfaces, i);
10997                                 klass->interfaces [i] = mono_class_from_mono_type (iface);
10998                                 ensure_runtime_vtable (klass->interfaces [i]);
10999                         }
11000                         klass->interfaces_inited = 1;
11001                 }
11002         } else if (klass->generic_class){
11003                 ensure_generic_class_runtime_vtable (klass);
11004         }
11005
11006         if (klass->flags & TYPE_ATTRIBUTE_INTERFACE) {
11007                 int slot_num = 0;
11008                 for (i = 0; i < klass->method.count; ++i) {
11009                         MonoMethod *im = klass->methods [i];
11010                         if (!(im->flags & METHOD_ATTRIBUTE_STATIC))
11011                                 im->slot = slot_num++;
11012                 }
11013                 
11014                 klass->interfaces_packed = NULL; /*make setup_interface_offsets happy*/
11015                 mono_class_setup_interface_offsets (klass);
11016                 mono_class_setup_interface_id (klass);
11017         }
11018
11019         /*
11020          * The generic vtable is needed even if image->run is not set since some
11021          * runtime code like ves_icall_Type_GetMethodsByName depends on 
11022          * method->slot being defined.
11023          */
11024
11025         /* 
11026          * tb->methods could not be freed since it is used for determining 
11027          * overrides during dynamic vtable construction.
11028          */
11029 }
11030
11031 static MonoMethod*
11032 mono_reflection_method_get_handle (MonoObject *method)
11033 {
11034         MonoClass *class = mono_object_class (method);
11035         if (is_sr_mono_method (class) || is_sr_mono_generic_method (class)) {
11036                 MonoReflectionMethod *sr_method = (MonoReflectionMethod*)method;
11037                 return sr_method->method;
11038         }
11039         if (is_sre_method_builder (class)) {
11040                 MonoReflectionMethodBuilder *mb = (MonoReflectionMethodBuilder*)method;
11041                 return mb->mhandle;
11042         }
11043         if (is_sre_method_on_tb_inst (class)) {
11044                 MonoReflectionMethodOnTypeBuilderInst *m = (MonoReflectionMethodOnTypeBuilderInst*)method;
11045                 MonoMethod *result;
11046                 /*FIXME move this to a proper method and unify with resolve_object*/
11047                 if (m->method_args) {
11048                         result = mono_reflection_method_on_tb_inst_get_handle (m);
11049                 } else {
11050                         MonoType *type = mono_reflection_type_get_handle ((MonoReflectionType*)m->inst);
11051                         MonoClass *inflated_klass = mono_class_from_mono_type (type);
11052                         MonoMethod *mono_method;
11053
11054                         if (is_sre_method_builder (mono_object_class (m->mb)))
11055                                 mono_method = ((MonoReflectionMethodBuilder *)m->mb)->mhandle;
11056                         else if (is_sr_mono_method (mono_object_class (m->mb)))
11057                                 mono_method = ((MonoReflectionMethod *)m->mb)->method;
11058                         else
11059                                 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)));
11060
11061                         result = inflate_mono_method (inflated_klass, mono_method, (MonoObject*)m->mb);
11062                 }
11063                 return result;
11064         }
11065
11066         g_error ("Can't handle methods of type %s:%s", class->name_space, class->name);
11067         return NULL;
11068 }
11069
11070 void
11071 mono_reflection_get_dynamic_overrides (MonoClass *klass, MonoMethod ***overrides, int *num_overrides)
11072 {
11073         MonoReflectionTypeBuilder *tb;
11074         int i, j, onum;
11075         MonoReflectionMethod *m;
11076
11077         *overrides = NULL;
11078         *num_overrides = 0;
11079
11080         g_assert (klass->image->dynamic);
11081
11082         if (!mono_class_get_ref_info (klass))
11083                 return;
11084
11085         g_assert (strcmp (((MonoObject*)mono_class_get_ref_info (klass))->vtable->klass->name, "TypeBuilder") == 0);
11086
11087         tb = (MonoReflectionTypeBuilder*)mono_class_get_ref_info (klass);
11088
11089         onum = 0;
11090         if (tb->methods) {
11091                 for (i = 0; i < tb->num_methods; ++i) {
11092                         MonoReflectionMethodBuilder *mb = 
11093                                 mono_array_get (tb->methods, MonoReflectionMethodBuilder*, i);
11094                         if (mb->override_methods)
11095                                 onum += mono_array_length (mb->override_methods);
11096                 }
11097         }
11098
11099         if (onum) {
11100                 *overrides = g_new0 (MonoMethod*, onum * 2);
11101
11102                 onum = 0;
11103                 for (i = 0; i < tb->num_methods; ++i) {
11104                         MonoReflectionMethodBuilder *mb = 
11105                                 mono_array_get (tb->methods, MonoReflectionMethodBuilder*, i);
11106                         if (mb->override_methods) {
11107                                 for (j = 0; j < mono_array_length (mb->override_methods); ++j) {
11108                                         m = mono_array_get (mb->override_methods, MonoReflectionMethod*, j);
11109
11110                                         (*overrides) [onum * 2] = mono_reflection_method_get_handle ((MonoObject*)m);
11111                                         (*overrides) [onum * 2 + 1] = mb->mhandle;
11112
11113                                         g_assert (mb->mhandle);
11114
11115                                         onum ++;
11116                                 }
11117                         }
11118                 }
11119         }
11120
11121         *num_overrides = onum;
11122 }
11123
11124 static void
11125 typebuilder_setup_fields (MonoClass *klass, MonoError *error)
11126 {
11127         MonoReflectionTypeBuilder *tb = mono_class_get_ref_info (klass);
11128         MonoReflectionFieldBuilder *fb;
11129         MonoClassField *field;
11130         MonoImage *image = klass->image;
11131         const char *p, *p2;
11132         int i;
11133         guint32 len, idx, real_size = 0;
11134
11135         klass->field.count = tb->num_fields;
11136         klass->field.first = 0;
11137
11138         mono_error_init (error);
11139
11140         if (tb->class_size) {
11141                 if ((tb->packing_size & 0xfffffff0) != 0) {
11142                         char *err_msg = g_strdup_printf ("Could not load struct '%s' with packing size %d >= 16", klass->name, tb->packing_size);
11143                         mono_class_set_failure (klass, MONO_EXCEPTION_TYPE_LOAD, err_msg);
11144                         return;
11145                 }
11146                 klass->packing_size = tb->packing_size;
11147                 real_size = klass->instance_size + tb->class_size;
11148         }
11149
11150         if (!klass->field.count) {
11151                 klass->instance_size = MAX (klass->instance_size, real_size);
11152                 return;
11153         }
11154         
11155         klass->fields = image_g_new0 (image, MonoClassField, klass->field.count);
11156         mono_class_alloc_ext (klass);
11157         klass->ext->field_def_values = image_g_new0 (image, MonoFieldDefaultValue, klass->field.count);
11158         /*
11159         This is, guess what, a hack.
11160         The issue is that the runtime doesn't know how to setup the fields of a typebuider and crash.
11161         On the static path no field class is resolved, only types are built. This is the right thing to do
11162         but we suck.
11163         Setting size_inited is harmless because we're doing the same job as mono_class_setup_fields anyway.
11164         */
11165         klass->size_inited = 1;
11166
11167         for (i = 0; i < klass->field.count; ++i) {
11168                 MonoArray *rva_data;
11169                 fb = mono_array_get (tb->fields, gpointer, i);
11170                 field = &klass->fields [i];
11171                 field->name = mono_string_to_utf8_image (image, fb->name, error);
11172                 if (!mono_error_ok (error))
11173                         return;
11174                 if (fb->attrs) {
11175                         field->type = mono_metadata_type_dup (klass->image, mono_reflection_type_get_handle ((MonoReflectionType*)fb->type));
11176                         field->type->attrs = fb->attrs;
11177                 } else {
11178                         field->type = mono_reflection_type_get_handle ((MonoReflectionType*)fb->type);
11179                 }
11180
11181                 if ((fb->attrs & FIELD_ATTRIBUTE_HAS_FIELD_RVA) && (rva_data = fb->rva_data)) {
11182                         char *base = mono_array_addr (rva_data, char, 0);
11183                         size_t size = mono_array_length (rva_data);
11184                         char *data = mono_image_alloc (klass->image, size);
11185                         memcpy (data, base, size);
11186                         klass->ext->field_def_values [i].data = data;
11187                 }
11188                 if (fb->offset != -1)
11189                         field->offset = fb->offset;
11190                 field->parent = klass;
11191                 fb->handle = field;
11192                 mono_save_custom_attrs (klass->image, field, fb->cattrs);
11193
11194                 if (klass->enumtype && !(field->type->attrs & FIELD_ATTRIBUTE_STATIC)) {
11195                         klass->cast_class = klass->element_class = mono_class_from_mono_type (field->type);
11196                 }
11197                 if (fb->def_value) {
11198                         MonoDynamicImage *assembly = (MonoDynamicImage*)klass->image;
11199                         field->type->attrs |= FIELD_ATTRIBUTE_HAS_DEFAULT;
11200                         idx = encode_constant (assembly, fb->def_value, &klass->ext->field_def_values [i].def_type);
11201                         /* Copy the data from the blob since it might get realloc-ed */
11202                         p = assembly->blob.data + idx;
11203                         len = mono_metadata_decode_blob_size (p, &p2);
11204                         len += p2 - p;
11205                         klass->ext->field_def_values [i].data = mono_image_alloc (image, len);
11206                         memcpy ((gpointer)klass->ext->field_def_values [i].data, p, len);
11207                 }
11208         }
11209
11210         klass->instance_size = MAX (klass->instance_size, real_size);
11211         mono_class_layout_fields (klass);
11212 }
11213
11214 static void
11215 typebuilder_setup_properties (MonoClass *klass, MonoError *error)
11216 {
11217         MonoReflectionTypeBuilder *tb = mono_class_get_ref_info (klass);
11218         MonoReflectionPropertyBuilder *pb;
11219         MonoImage *image = klass->image;
11220         MonoProperty *properties;
11221         int i;
11222
11223         mono_error_init (error);
11224
11225         if (!klass->ext)
11226                 klass->ext = image_g_new0 (image, MonoClassExt, 1);
11227
11228         klass->ext->property.count = tb->properties ? mono_array_length (tb->properties) : 0;
11229         klass->ext->property.first = 0;
11230
11231         properties = image_g_new0 (image, MonoProperty, klass->ext->property.count);
11232         klass->ext->properties = properties;
11233         for (i = 0; i < klass->ext->property.count; ++i) {
11234                 pb = mono_array_get (tb->properties, MonoReflectionPropertyBuilder*, i);
11235                 properties [i].parent = klass;
11236                 properties [i].attrs = pb->attrs;
11237                 properties [i].name = mono_string_to_utf8_image (image, pb->name, error);
11238                 if (!mono_error_ok (error))
11239                         return;
11240                 if (pb->get_method)
11241                         properties [i].get = pb->get_method->mhandle;
11242                 if (pb->set_method)
11243                         properties [i].set = pb->set_method->mhandle;
11244
11245                 mono_save_custom_attrs (klass->image, &properties [i], pb->cattrs);
11246                 if (pb->def_value) {
11247                         guint32 len, idx;
11248                         const char *p, *p2;
11249                         MonoDynamicImage *assembly = (MonoDynamicImage*)klass->image;
11250                         if (!klass->ext->prop_def_values)
11251                                 klass->ext->prop_def_values = image_g_new0 (image, MonoFieldDefaultValue, klass->ext->property.count);
11252                         properties [i].attrs |= PROPERTY_ATTRIBUTE_HAS_DEFAULT;
11253                         idx = encode_constant (assembly, pb->def_value, &klass->ext->prop_def_values [i].def_type);
11254                         /* Copy the data from the blob since it might get realloc-ed */
11255                         p = assembly->blob.data + idx;
11256                         len = mono_metadata_decode_blob_size (p, &p2);
11257                         len += p2 - p;
11258                         klass->ext->prop_def_values [i].data = mono_image_alloc (image, len);
11259                         memcpy ((gpointer)klass->ext->prop_def_values [i].data, p, len);
11260                 }
11261         }
11262 }
11263
11264 MonoReflectionEvent *
11265 mono_reflection_event_builder_get_event_info (MonoReflectionTypeBuilder *tb, MonoReflectionEventBuilder *eb)
11266 {
11267         MonoEvent *event = g_new0 (MonoEvent, 1);
11268         MonoClass *klass;
11269
11270         klass = mono_class_from_mono_type (mono_reflection_type_get_handle ((MonoReflectionType*)tb));
11271
11272         event->parent = klass;
11273         event->attrs = eb->attrs;
11274         event->name = mono_string_to_utf8 (eb->name);
11275         if (eb->add_method)
11276                 event->add = eb->add_method->mhandle;
11277         if (eb->remove_method)
11278                 event->remove = eb->remove_method->mhandle;
11279         if (eb->raise_method)
11280                 event->raise = eb->raise_method->mhandle;
11281
11282 #ifndef MONO_SMALL_CONFIG
11283         if (eb->other_methods) {
11284                 int j;
11285                 event->other = g_new0 (MonoMethod*, mono_array_length (eb->other_methods) + 1);
11286                 for (j = 0; j < mono_array_length (eb->other_methods); ++j) {
11287                         MonoReflectionMethodBuilder *mb = 
11288                                 mono_array_get (eb->other_methods,
11289                                                 MonoReflectionMethodBuilder*, j);
11290                         event->other [j] = mb->mhandle;
11291                 }
11292         }
11293 #endif
11294
11295         return mono_event_get_object (mono_object_domain (tb), klass, event);
11296 }
11297
11298 static void
11299 typebuilder_setup_events (MonoClass *klass, MonoError *error)
11300 {
11301         MonoReflectionTypeBuilder *tb = mono_class_get_ref_info (klass);
11302         MonoReflectionEventBuilder *eb;
11303         MonoImage *image = klass->image;
11304         MonoEvent *events;
11305         int i;
11306
11307         mono_error_init (error);
11308
11309         if (!klass->ext)
11310                 klass->ext = image_g_new0 (image, MonoClassExt, 1);
11311
11312         klass->ext->event.count = tb->events ? mono_array_length (tb->events) : 0;
11313         klass->ext->event.first = 0;
11314
11315         events = image_g_new0 (image, MonoEvent, klass->ext->event.count);
11316         klass->ext->events = events;
11317         for (i = 0; i < klass->ext->event.count; ++i) {
11318                 eb = mono_array_get (tb->events, MonoReflectionEventBuilder*, i);
11319                 events [i].parent = klass;
11320                 events [i].attrs = eb->attrs;
11321                 events [i].name = mono_string_to_utf8_image (image, eb->name, error);
11322                 if (!mono_error_ok (error))
11323                         return;
11324                 if (eb->add_method)
11325                         events [i].add = eb->add_method->mhandle;
11326                 if (eb->remove_method)
11327                         events [i].remove = eb->remove_method->mhandle;
11328                 if (eb->raise_method)
11329                         events [i].raise = eb->raise_method->mhandle;
11330
11331 #ifndef MONO_SMALL_CONFIG
11332                 if (eb->other_methods) {
11333                         int j;
11334                         events [i].other = image_g_new0 (image, MonoMethod*, mono_array_length (eb->other_methods) + 1);
11335                         for (j = 0; j < mono_array_length (eb->other_methods); ++j) {
11336                                 MonoReflectionMethodBuilder *mb = 
11337                                         mono_array_get (eb->other_methods,
11338                                                                         MonoReflectionMethodBuilder*, j);
11339                                 events [i].other [j] = mb->mhandle;
11340                         }
11341                 }
11342 #endif
11343                 mono_save_custom_attrs (klass->image, &events [i], eb->cattrs);
11344         }
11345 }
11346
11347 static gboolean
11348 remove_instantiations_of_and_ensure_contents (gpointer key,
11349                                                   gpointer value,
11350                                                   gpointer user_data)
11351 {
11352         MonoType *type = (MonoType*)key;
11353         MonoClass *klass = (MonoClass*)user_data;
11354
11355         if ((type->type == MONO_TYPE_GENERICINST) && (type->data.generic_class->container_class == klass)) {
11356                 fix_partial_generic_class (mono_class_from_mono_type (type)); //Ensure it's safe to use it.
11357                 return TRUE;
11358         } else
11359                 return FALSE;
11360 }
11361
11362 static void
11363 check_array_for_usertypes (MonoArray *arr)
11364 {
11365         int i;
11366
11367         if (!arr)
11368                 return;
11369
11370         for (i = 0; i < mono_array_length (arr); ++i)
11371                 RESOLVE_ARRAY_TYPE_ELEMENT (arr, i);
11372 }
11373
11374 MonoReflectionType*
11375 mono_reflection_create_runtime_class (MonoReflectionTypeBuilder *tb)
11376 {
11377         MonoError error;
11378         MonoClass *klass;
11379         MonoDomain* domain;
11380         MonoReflectionType* res;
11381         int i, j;
11382
11383         MONO_ARCH_SAVE_REGS;
11384
11385         domain = mono_object_domain (tb);
11386         klass = mono_class_from_mono_type (tb->type.type);
11387
11388         /*
11389          * Check for user defined Type subclasses.
11390          */
11391         RESOLVE_TYPE (tb->parent);
11392         check_array_for_usertypes (tb->interfaces);
11393         if (tb->fields) {
11394                 for (i = 0; i < mono_array_length (tb->fields); ++i) {
11395                         MonoReflectionFieldBuilder *fb = mono_array_get (tb->fields, gpointer, i);
11396                         if (fb) {
11397                                 RESOLVE_TYPE (fb->type);
11398                                 check_array_for_usertypes (fb->modreq);
11399                                 check_array_for_usertypes (fb->modopt);
11400                                 if (fb->marshal_info && fb->marshal_info->marshaltyperef)
11401                                         RESOLVE_TYPE (fb->marshal_info->marshaltyperef);
11402                         }
11403                 }
11404         }
11405         if (tb->methods) {
11406                 for (i = 0; i < mono_array_length (tb->methods); ++i) {
11407                         MonoReflectionMethodBuilder *mb = mono_array_get (tb->methods, gpointer, i);
11408                         if (mb) {
11409                                 RESOLVE_TYPE (mb->rtype);
11410                                 check_array_for_usertypes (mb->return_modreq);
11411                                 check_array_for_usertypes (mb->return_modopt);
11412                                 check_array_for_usertypes (mb->parameters);
11413                                 if (mb->param_modreq)
11414                                         for (j = 0; j < mono_array_length (mb->param_modreq); ++j)
11415                                                 check_array_for_usertypes (mono_array_get (mb->param_modreq, MonoArray*, j));
11416                                 if (mb->param_modopt)
11417                                         for (j = 0; j < mono_array_length (mb->param_modopt); ++j)
11418                                                 check_array_for_usertypes (mono_array_get (mb->param_modopt, MonoArray*, j));
11419                         }
11420                 }
11421         }
11422         if (tb->ctors) {
11423                 for (i = 0; i < mono_array_length (tb->ctors); ++i) {
11424                         MonoReflectionCtorBuilder *mb = mono_array_get (tb->ctors, gpointer, i);
11425                         if (mb) {
11426                                 check_array_for_usertypes (mb->parameters);
11427                                 if (mb->param_modreq)
11428                                         for (j = 0; j < mono_array_length (mb->param_modreq); ++j)
11429                                                 check_array_for_usertypes (mono_array_get (mb->param_modreq, MonoArray*, j));
11430                                 if (mb->param_modopt)
11431                                         for (j = 0; j < mono_array_length (mb->param_modopt); ++j)
11432                                                 check_array_for_usertypes (mono_array_get (mb->param_modopt, MonoArray*, j));
11433                         }
11434                 }
11435         }
11436
11437         mono_save_custom_attrs (klass->image, klass, tb->cattrs);
11438
11439         /* 
11440          * we need to lock the domain because the lock will be taken inside
11441          * So, we need to keep the locking order correct.
11442          */
11443         mono_loader_lock ();
11444         mono_domain_lock (domain);
11445         if (klass->wastypebuilder) {
11446                 mono_domain_unlock (domain);
11447                 mono_loader_unlock ();
11448                 return mono_type_get_object (mono_object_domain (tb), &klass->byval_arg);
11449         }
11450         /*
11451          * Fields to set in klass:
11452          * the various flags: delegate/unicode/contextbound etc.
11453          */
11454         klass->flags = tb->attrs;
11455         klass->has_cctor = 1;
11456         klass->has_finalize = 1;
11457         klass->has_finalize_inited = 1;
11458
11459         /* fool mono_class_setup_parent */
11460         klass->supertypes = NULL;
11461         mono_class_setup_parent (klass, klass->parent);
11462         mono_class_setup_mono_type (klass);
11463
11464 #if 0
11465         if (!((MonoDynamicImage*)klass->image)->run) {
11466                 if (klass->generic_container) {
11467                         /* FIXME: The code below can't handle generic classes */
11468                         klass->wastypebuilder = TRUE;
11469                         mono_loader_unlock ();
11470                         mono_domain_unlock (domain);
11471                         return mono_type_get_object (mono_object_domain (tb), &klass->byval_arg);
11472                 }
11473         }
11474 #endif
11475
11476         /* enums are done right away */
11477         if (!klass->enumtype)
11478                 ensure_runtime_vtable (klass);
11479
11480         if (tb->subtypes) {
11481                 for (i = 0; i < mono_array_length (tb->subtypes); ++i) {
11482                         MonoReflectionTypeBuilder *subtb = mono_array_get (tb->subtypes, MonoReflectionTypeBuilder*, i);
11483                         mono_class_alloc_ext (klass);
11484                         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)));
11485                 }
11486         }
11487
11488         klass->nested_classes_inited = TRUE;
11489
11490         /* fields and object layout */
11491         if (klass->parent) {
11492                 if (!klass->parent->size_inited)
11493                         mono_class_init (klass->parent);
11494                 klass->instance_size = klass->parent->instance_size;
11495                 klass->sizes.class_size = 0;
11496                 klass->min_align = klass->parent->min_align;
11497                 /* if the type has no fields we won't call the field_setup
11498                  * routine which sets up klass->has_references.
11499                  */
11500                 klass->has_references |= klass->parent->has_references;
11501         } else {
11502                 klass->instance_size = sizeof (MonoObject);
11503                 klass->min_align = 1;
11504         }
11505
11506         /* FIXME: handle packing_size and instance_size */
11507         typebuilder_setup_fields (klass, &error);
11508         if (!mono_error_ok (&error))
11509                 goto failure;
11510         typebuilder_setup_properties (klass, &error);
11511         if (!mono_error_ok (&error))
11512                 goto failure;
11513
11514         typebuilder_setup_events (klass, &error);
11515         if (!mono_error_ok (&error))
11516                 goto failure;
11517
11518         klass->wastypebuilder = TRUE;
11519
11520         /* 
11521          * If we are a generic TypeBuilder, there might be instantiations in the type cache
11522          * which have type System.Reflection.MonoGenericClass, but after the type is created, 
11523          * we want to return normal System.MonoType objects, so clear these out from the cache.
11524          *
11525          * Together with this we must ensure the contents of all instances to match the created type.
11526          */
11527         if (domain->type_hash && klass->generic_container)
11528                 mono_g_hash_table_foreach_remove (domain->type_hash, remove_instantiations_of_and_ensure_contents, klass);
11529
11530         mono_domain_unlock (domain);
11531         mono_loader_unlock ();
11532
11533         if (klass->enumtype && !mono_class_is_valid_enum (klass)) {
11534                 mono_class_set_failure (klass, MONO_EXCEPTION_TYPE_LOAD, NULL);
11535                 mono_raise_exception (mono_get_exception_type_load (tb->name, NULL));
11536         }
11537
11538         res = mono_type_get_object (mono_object_domain (tb), &klass->byval_arg);
11539         g_assert (res != (MonoReflectionType*)tb);
11540
11541         return res;
11542
11543 failure:
11544         mono_class_set_failure (klass, MONO_EXCEPTION_TYPE_LOAD, NULL);
11545         klass->wastypebuilder = TRUE;
11546         mono_domain_unlock (domain);
11547         mono_loader_unlock ();
11548         mono_error_raise_exception (&error);
11549         return NULL;
11550 }
11551
11552 void
11553 mono_reflection_initialize_generic_parameter (MonoReflectionGenericParam *gparam)
11554 {
11555         MonoGenericParamFull *param;
11556         MonoImage *image;
11557         MonoClass *pklass;
11558         MonoError error;
11559
11560         MONO_ARCH_SAVE_REGS;
11561
11562         image = &gparam->tbuilder->module->dynamic_image->image;
11563
11564         param = mono_image_new0 (image, MonoGenericParamFull, 1);
11565
11566         param->info.name = mono_string_to_utf8_image (image, gparam->name, &error);
11567         g_assert (mono_error_ok (&error));
11568         param->param.num = gparam->index;
11569
11570         if (gparam->mbuilder) {
11571                 if (!gparam->mbuilder->generic_container) {
11572                         MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder *)gparam->mbuilder->type;
11573                         MonoClass *klass = mono_class_from_mono_type (mono_reflection_type_get_handle ((MonoReflectionType*)tb));
11574                         gparam->mbuilder->generic_container = mono_image_alloc0 (klass->image, sizeof (MonoGenericContainer));
11575                         gparam->mbuilder->generic_container->is_method = TRUE;
11576                         /* 
11577                          * Cannot set owner.method, since the MonoMethod is not created yet.
11578                          * Set the image field instead, so type_in_image () works.
11579                          */
11580                         gparam->mbuilder->generic_container->image = klass->image;
11581                 }
11582                 param->param.owner = gparam->mbuilder->generic_container;
11583         } else if (gparam->tbuilder) {
11584                 if (!gparam->tbuilder->generic_container) {
11585                         MonoClass *klass = mono_class_from_mono_type (mono_reflection_type_get_handle ((MonoReflectionType*)gparam->tbuilder));
11586                         gparam->tbuilder->generic_container = mono_image_alloc0 (klass->image, sizeof (MonoGenericContainer));
11587                         gparam->tbuilder->generic_container->owner.klass = klass;
11588                 }
11589                 param->param.owner = gparam->tbuilder->generic_container;
11590         }
11591
11592         pklass = mono_class_from_generic_parameter ((MonoGenericParam *) param, image, gparam->mbuilder != NULL);
11593
11594         gparam->type.type = &pklass->byval_arg;
11595
11596         mono_class_set_ref_info (pklass, gparam);
11597         mono_image_append_class_to_reflection_info_set (pklass);
11598 }
11599
11600 MonoArray *
11601 mono_reflection_sighelper_get_signature_local (MonoReflectionSigHelper *sig)
11602 {
11603         MonoReflectionModuleBuilder *module = sig->module;
11604         MonoDynamicImage *assembly = module != NULL ? module->dynamic_image : NULL;
11605         guint32 na = sig->arguments ? mono_array_length (sig->arguments) : 0;
11606         guint32 buflen, i;
11607         MonoArray *result;
11608         SigBuffer buf;
11609
11610         check_array_for_usertypes (sig->arguments);
11611
11612         sigbuffer_init (&buf, 32);
11613
11614         sigbuffer_add_value (&buf, 0x07);
11615         sigbuffer_add_value (&buf, na);
11616         if (assembly != NULL){
11617                 for (i = 0; i < na; ++i) {
11618                         MonoReflectionType *type = mono_array_get (sig->arguments, MonoReflectionType*, i);
11619                         encode_reflection_type (assembly, type, &buf);
11620                 }
11621         }
11622
11623         buflen = buf.p - buf.buf;
11624         result = mono_array_new (mono_domain_get (), mono_defaults.byte_class, buflen);
11625         memcpy (mono_array_addr (result, char, 0), buf.buf, buflen);
11626         sigbuffer_free (&buf);
11627
11628         return result;
11629 }
11630
11631 MonoArray *
11632 mono_reflection_sighelper_get_signature_field (MonoReflectionSigHelper *sig)
11633 {
11634         MonoDynamicImage *assembly = sig->module->dynamic_image;
11635         guint32 na = sig->arguments ? mono_array_length (sig->arguments) : 0;
11636         guint32 buflen, i;
11637         MonoArray *result;
11638         SigBuffer buf;
11639
11640         check_array_for_usertypes (sig->arguments);
11641
11642         sigbuffer_init (&buf, 32);
11643
11644         sigbuffer_add_value (&buf, 0x06);
11645         for (i = 0; i < na; ++i) {
11646                 MonoReflectionType *type = mono_array_get (sig->arguments, MonoReflectionType*, i);
11647                 encode_reflection_type (assembly, type, &buf);
11648         }
11649
11650         buflen = buf.p - buf.buf;
11651         result = mono_array_new (mono_domain_get (), mono_defaults.byte_class, buflen);
11652         memcpy (mono_array_addr (result, char, 0), buf.buf, buflen);
11653         sigbuffer_free (&buf);
11654
11655         return result;
11656 }
11657
11658 typedef struct {
11659         MonoMethod *handle;
11660         MonoDomain *domain;
11661 } DynamicMethodReleaseData;
11662
11663 /*
11664  * The runtime automatically clean up those after finalization.
11665 */      
11666 static MonoReferenceQueue *dynamic_method_queue;
11667
11668 static void
11669 free_dynamic_method (void *dynamic_method)
11670 {
11671         DynamicMethodReleaseData *data = dynamic_method;
11672
11673         mono_runtime_free_method (data->domain, data->handle);
11674         g_free (data);
11675 }
11676
11677 void 
11678 mono_reflection_create_dynamic_method (MonoReflectionDynamicMethod *mb)
11679 {
11680         MonoReferenceQueue *queue;
11681         MonoMethod *handle;
11682         DynamicMethodReleaseData *release_data;
11683         ReflectionMethodBuilder rmb;
11684         MonoMethodSignature *sig;
11685         MonoClass *klass;
11686         GSList *l;
11687         int i;
11688
11689         if (mono_runtime_is_shutting_down ())
11690                 mono_raise_exception (mono_get_exception_invalid_operation (""));
11691
11692         if (!(queue = dynamic_method_queue)) {
11693                 mono_loader_lock ();
11694                 if (!(queue = dynamic_method_queue))
11695                         queue = dynamic_method_queue = mono_gc_reference_queue_new (free_dynamic_method);
11696                 mono_loader_unlock ();
11697         }
11698
11699         sig = dynamic_method_to_signature (mb);
11700
11701         reflection_methodbuilder_from_dynamic_method (&rmb, mb);
11702
11703         /*
11704          * Resolve references.
11705          */
11706         /* 
11707          * Every second entry in the refs array is reserved for storing handle_class,
11708          * which is needed by the ldtoken implementation in the JIT.
11709          */
11710         rmb.nrefs = mb->nrefs;
11711         rmb.refs = g_new0 (gpointer, mb->nrefs + 1);
11712         for (i = 0; i < mb->nrefs; i += 2) {
11713                 MonoClass *handle_class;
11714                 gpointer ref;
11715                 MonoObject *obj = mono_array_get (mb->refs, MonoObject*, i);
11716
11717                 if (strcmp (obj->vtable->klass->name, "DynamicMethod") == 0) {
11718                         MonoReflectionDynamicMethod *method = (MonoReflectionDynamicMethod*)obj;
11719                         /*
11720                          * The referenced DynamicMethod should already be created by the managed
11721                          * code, except in the case of circular references. In that case, we store
11722                          * method in the refs array, and fix it up later when the referenced 
11723                          * DynamicMethod is created.
11724                          */
11725                         if (method->mhandle) {
11726                                 ref = method->mhandle;
11727                         } else {
11728                                 /* FIXME: GC object stored in unmanaged memory */
11729                                 ref = method;
11730
11731                                 /* FIXME: GC object stored in unmanaged memory */
11732                                 method->referenced_by = g_slist_append (method->referenced_by, mb);
11733                         }
11734                         handle_class = mono_defaults.methodhandle_class;
11735                 } else {
11736                         MonoException *ex = NULL;
11737                         ref = resolve_object (mb->module->image, obj, &handle_class, NULL);
11738                         if (!ref)
11739                                 ex = mono_get_exception_type_load (NULL, NULL);
11740                         else if (mono_security_core_clr_enabled ())
11741                                 ex = mono_security_core_clr_ensure_dynamic_method_resolved_object (ref, handle_class);
11742
11743                         if (ex) {
11744                                 g_free (rmb.refs);
11745                                 mono_raise_exception (ex);
11746                                 return;
11747                         }
11748                 }
11749
11750                 rmb.refs [i] = ref; /* FIXME: GC object stored in unmanaged memory (change also resolve_object() signature) */
11751                 rmb.refs [i + 1] = handle_class;
11752         }               
11753
11754         klass = mb->owner ? mono_class_from_mono_type (mono_reflection_type_get_handle ((MonoReflectionType*)mb->owner)) : mono_defaults.object_class;
11755
11756         mb->mhandle = handle = reflection_methodbuilder_to_mono_method (klass, &rmb, sig);
11757         release_data = g_new (DynamicMethodReleaseData, 1);
11758         release_data->handle = handle;
11759         release_data->domain = mono_object_get_domain ((MonoObject*)mb);
11760         if (!mono_gc_reference_queue_add (queue, (MonoObject*)mb, release_data))
11761                 g_free (release_data);
11762
11763         /* Fix up refs entries pointing at us */
11764         for (l = mb->referenced_by; l; l = l->next) {
11765                 MonoReflectionDynamicMethod *method = (MonoReflectionDynamicMethod*)l->data;
11766                 MonoMethodWrapper *wrapper = (MonoMethodWrapper*)method->mhandle;
11767                 gpointer *data;
11768                 
11769                 g_assert (method->mhandle);
11770
11771                 data = (gpointer*)wrapper->method_data;
11772                 for (i = 0; i < GPOINTER_TO_UINT (data [0]); i += 2) {
11773                         if ((data [i + 1] == mb) && (data [i + 1 + 1] == mono_defaults.methodhandle_class))
11774                                 data [i + 1] = mb->mhandle;
11775                 }
11776         }
11777         g_slist_free (mb->referenced_by);
11778
11779         g_free (rmb.refs);
11780
11781         /* ilgen is no longer needed */
11782         mb->ilgen = NULL;
11783 }
11784
11785 #endif /* DISABLE_REFLECTION_EMIT */
11786
11787 /**
11788  * 
11789  * mono_reflection_is_valid_dynamic_token:
11790  * 
11791  * Returns TRUE if token is valid.
11792  * 
11793  */
11794 gboolean
11795 mono_reflection_is_valid_dynamic_token (MonoDynamicImage *image, guint32 token)
11796 {
11797         return mono_g_hash_table_lookup (image->tokens, GUINT_TO_POINTER (token)) != NULL;
11798 }
11799
11800 MonoMethodSignature *
11801 mono_reflection_lookup_signature (MonoImage *image, MonoMethod *method, guint32 token)
11802 {
11803         MonoMethodSignature *sig;
11804         g_assert (image->dynamic);
11805
11806         sig = g_hash_table_lookup (((MonoDynamicImage*)image)->vararg_aux_hash, GUINT_TO_POINTER (token));
11807         if (sig)
11808                 return sig;
11809
11810         return mono_method_signature (method);
11811 }
11812
11813 #ifndef DISABLE_REFLECTION_EMIT
11814
11815 /**
11816  * mono_reflection_lookup_dynamic_token:
11817  *
11818  * Finish the Builder object pointed to by TOKEN and return the corresponding
11819  * runtime structure. If HANDLE_CLASS is not NULL, it is set to the class required by 
11820  * mono_ldtoken. If valid_token is TRUE, assert if it is not found in the token->object
11821  * mapping table.
11822  *
11823  * LOCKING: Take the loader lock
11824  */
11825 gpointer
11826 mono_reflection_lookup_dynamic_token (MonoImage *image, guint32 token, gboolean valid_token, MonoClass **handle_class, MonoGenericContext *context)
11827 {
11828         MonoDynamicImage *assembly = (MonoDynamicImage*)image;
11829         MonoObject *obj;
11830         MonoClass *klass;
11831
11832         mono_loader_lock ();
11833         obj = mono_g_hash_table_lookup (assembly->tokens, GUINT_TO_POINTER (token));
11834         mono_loader_unlock ();
11835         if (!obj) {
11836                 if (valid_token)
11837                         g_error ("Could not find required dynamic token 0x%08x", token);
11838                 else
11839                         return NULL;
11840         }
11841
11842         if (!handle_class)
11843                 handle_class = &klass;
11844         return resolve_object (image, obj, handle_class, context);
11845 }
11846
11847 /*
11848  * ensure_complete_type:
11849  *
11850  *   Ensure that KLASS is completed if it is a dynamic type, or references
11851  * dynamic types.
11852  */
11853 static void
11854 ensure_complete_type (MonoClass *klass)
11855 {
11856         if (klass->image->dynamic && !klass->wastypebuilder && mono_class_get_ref_info (klass)) {
11857                 MonoReflectionTypeBuilder *tb = mono_class_get_ref_info (klass);
11858
11859                 mono_domain_try_type_resolve (mono_domain_get (), NULL, (MonoObject*)tb);
11860
11861                 // Asserting here could break a lot of code
11862                 //g_assert (klass->wastypebuilder);
11863         }
11864
11865         if (klass->generic_class) {
11866                 MonoGenericInst *inst = klass->generic_class->context.class_inst;
11867                 int i;
11868
11869                 for (i = 0; i < inst->type_argc; ++i) {
11870                         ensure_complete_type (mono_class_from_mono_type (inst->type_argv [i]));
11871                 }
11872         }
11873 }
11874
11875 static gpointer
11876 resolve_object (MonoImage *image, MonoObject *obj, MonoClass **handle_class, MonoGenericContext *context)
11877 {
11878         gpointer result = NULL;
11879
11880         if (strcmp (obj->vtable->klass->name, "String") == 0) {
11881                 result = mono_string_intern ((MonoString*)obj);
11882                 *handle_class = mono_defaults.string_class;
11883                 g_assert (result);
11884         } else if (strcmp (obj->vtable->klass->name, "MonoType") == 0) {
11885                 MonoType *type = mono_reflection_type_get_handle ((MonoReflectionType*)obj);
11886                 MonoClass *mc = mono_class_from_mono_type (type);
11887                 if (!mono_class_init (mc))
11888                         mono_raise_exception (mono_class_get_exception_for_failure (mc));
11889
11890                 if (context) {
11891                         MonoType *inflated = mono_class_inflate_generic_type (type, context);
11892                         result = mono_class_from_mono_type (inflated);
11893                         mono_metadata_free_type (inflated);
11894                 } else {
11895                         result = mono_class_from_mono_type (type);
11896                 }
11897                 *handle_class = mono_defaults.typehandle_class;
11898                 g_assert (result);
11899         } else if (strcmp (obj->vtable->klass->name, "MonoMethod") == 0 ||
11900                    strcmp (obj->vtable->klass->name, "MonoCMethod") == 0 ||
11901                    strcmp (obj->vtable->klass->name, "MonoGenericCMethod") == 0 ||
11902                    strcmp (obj->vtable->klass->name, "MonoGenericMethod") == 0) {
11903                 result = ((MonoReflectionMethod*)obj)->method;
11904                 if (context)
11905                         result = mono_class_inflate_generic_method (result, context);
11906                 *handle_class = mono_defaults.methodhandle_class;
11907                 g_assert (result);
11908         } else if (strcmp (obj->vtable->klass->name, "MethodBuilder") == 0) {
11909                 MonoReflectionMethodBuilder *mb = (MonoReflectionMethodBuilder*)obj;
11910                 result = mb->mhandle;
11911                 if (!result) {
11912                         /* Type is not yet created */
11913                         MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder*)mb->type;
11914
11915                         mono_domain_try_type_resolve (mono_domain_get (), NULL, (MonoObject*)tb);
11916
11917                         /*
11918                          * Hopefully this has been filled in by calling CreateType() on the
11919                          * TypeBuilder.
11920                          */
11921                         /*
11922                          * TODO: This won't work if the application finishes another 
11923                          * TypeBuilder instance instead of this one.
11924                          */
11925                         result = mb->mhandle;
11926                 }
11927                 if (context)
11928                         result = mono_class_inflate_generic_method (result, context);
11929                 *handle_class = mono_defaults.methodhandle_class;
11930         } else if (strcmp (obj->vtable->klass->name, "ConstructorBuilder") == 0) {
11931                 MonoReflectionCtorBuilder *cb = (MonoReflectionCtorBuilder*)obj;
11932
11933                 result = cb->mhandle;
11934                 if (!result) {
11935                         MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder*)cb->type;
11936
11937                         mono_domain_try_type_resolve (mono_domain_get (), NULL, (MonoObject*)tb);
11938                         result = cb->mhandle;
11939                 }
11940                 if (context)
11941                         result = mono_class_inflate_generic_method (result, context);
11942                 *handle_class = mono_defaults.methodhandle_class;
11943         } else if (strcmp (obj->vtable->klass->name, "MonoField") == 0) {
11944                 MonoClassField *field = ((MonoReflectionField*)obj)->field;
11945
11946                 ensure_complete_type (field->parent);
11947                 if (context) {
11948                         MonoType *inflated = mono_class_inflate_generic_type (&field->parent->byval_arg, context);
11949                         MonoClass *class = mono_class_from_mono_type (inflated);
11950                         MonoClassField *inflated_field;
11951                         gpointer iter = NULL;
11952                         mono_metadata_free_type (inflated);
11953                         while ((inflated_field = mono_class_get_fields (class, &iter))) {
11954                                 if (!strcmp (field->name, inflated_field->name))
11955                                         break;
11956                         }
11957                         g_assert (inflated_field && !strcmp (field->name, inflated_field->name));
11958                         result = inflated_field;
11959                 } else {
11960                         result = field;
11961                 }
11962                 *handle_class = mono_defaults.fieldhandle_class;
11963                 g_assert (result);
11964         } else if (strcmp (obj->vtable->klass->name, "FieldBuilder") == 0) {
11965                 MonoReflectionFieldBuilder *fb = (MonoReflectionFieldBuilder*)obj;
11966                 result = fb->handle;
11967
11968                 if (!result) {
11969                         MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder*)fb->typeb;
11970
11971                         mono_domain_try_type_resolve (mono_domain_get (), NULL, (MonoObject*)tb);
11972                         result = fb->handle;
11973                 }
11974
11975                 if (fb->handle && fb->handle->parent->generic_container) {
11976                         MonoClass *klass = fb->handle->parent;
11977                         MonoType *type = mono_class_inflate_generic_type (&klass->byval_arg, context);
11978                         MonoClass *inflated = mono_class_from_mono_type (type);
11979
11980                         result = mono_class_get_field_from_name (inflated, mono_field_get_name (fb->handle));
11981                         g_assert (result);
11982                         mono_metadata_free_type (type);
11983                 }
11984                 *handle_class = mono_defaults.fieldhandle_class;
11985         } else if (strcmp (obj->vtable->klass->name, "TypeBuilder") == 0) {
11986                 MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder*)obj;
11987                 MonoType *type = mono_reflection_type_get_handle ((MonoReflectionType*)tb); 
11988                 MonoClass *klass;
11989
11990                 klass = type->data.klass;
11991                 if (klass->wastypebuilder) {
11992                         /* Already created */
11993                         result = klass;
11994                 }
11995                 else {
11996                         mono_domain_try_type_resolve (mono_domain_get (), NULL, (MonoObject*)tb);
11997                         result = type->data.klass;
11998                         g_assert (result);
11999                 }
12000                 *handle_class = mono_defaults.typehandle_class;
12001         } else if (strcmp (obj->vtable->klass->name, "SignatureHelper") == 0) {
12002                 MonoReflectionSigHelper *helper = (MonoReflectionSigHelper*)obj;
12003                 MonoMethodSignature *sig;
12004                 int nargs, i;
12005
12006                 if (helper->arguments)
12007                         nargs = mono_array_length (helper->arguments);
12008                 else
12009                         nargs = 0;
12010
12011                 sig = mono_metadata_signature_alloc (image, nargs);
12012                 sig->explicit_this = helper->call_conv & 64 ? 1 : 0;
12013                 sig->hasthis = helper->call_conv & 32 ? 1 : 0;
12014
12015                 if (helper->unmanaged_call_conv) { /* unmanaged */
12016                         sig->call_convention = helper->unmanaged_call_conv - 1;
12017                         sig->pinvoke = TRUE;
12018                 } else if (helper->call_conv & 0x02) {
12019                         sig->call_convention = MONO_CALL_VARARG;
12020                 } else {
12021                         sig->call_convention = MONO_CALL_DEFAULT;
12022                 }
12023
12024                 sig->param_count = nargs;
12025                 /* TODO: Copy type ? */
12026                 sig->ret = helper->return_type->type;
12027                 for (i = 0; i < nargs; ++i)
12028                         sig->params [i] = mono_type_array_get_and_resolve (helper->arguments, i);
12029
12030                 result = sig;
12031                 *handle_class = NULL;
12032         } else if (strcmp (obj->vtable->klass->name, "DynamicMethod") == 0) {
12033                 MonoReflectionDynamicMethod *method = (MonoReflectionDynamicMethod*)obj;
12034                 /* Already created by the managed code */
12035                 g_assert (method->mhandle);
12036                 result = method->mhandle;
12037                 *handle_class = mono_defaults.methodhandle_class;
12038         } else if (strcmp (obj->vtable->klass->name, "GenericTypeParameterBuilder") == 0) {
12039                 MonoType *type = mono_reflection_type_get_handle ((MonoReflectionType*)obj);
12040                 type = mono_class_inflate_generic_type (type, context);
12041                 result = mono_class_from_mono_type (type);
12042                 *handle_class = mono_defaults.typehandle_class;
12043                 g_assert (result);
12044                 mono_metadata_free_type (type);
12045         } else if (strcmp (obj->vtable->klass->name, "MonoGenericClass") == 0) {
12046                 MonoType *type = mono_reflection_type_get_handle ((MonoReflectionType*)obj);
12047                 type = mono_class_inflate_generic_type (type, context);
12048                 result = mono_class_from_mono_type (type);
12049                 *handle_class = mono_defaults.typehandle_class;
12050                 g_assert (result);
12051                 mono_metadata_free_type (type);
12052         } else if (strcmp (obj->vtable->klass->name, "FieldOnTypeBuilderInst") == 0) {
12053                 MonoReflectionFieldOnTypeBuilderInst *f = (MonoReflectionFieldOnTypeBuilderInst*)obj;
12054                 MonoClass *inflated;
12055                 MonoType *type;
12056                 MonoClassField *field;
12057
12058                 if (is_sre_field_builder (mono_object_class (f->fb)))
12059                         field = ((MonoReflectionFieldBuilder*)f->fb)->handle;
12060                 else if (is_sr_mono_field (mono_object_class (f->fb)))
12061                         field = ((MonoReflectionField*)f->fb)->field;
12062                 else
12063                         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)));
12064
12065                 type = mono_class_inflate_generic_type (mono_reflection_type_get_handle ((MonoReflectionType*)f->inst), context);
12066                 inflated = mono_class_from_mono_type (type);
12067
12068                 result = field = mono_class_get_field_from_name (inflated, mono_field_get_name (field));
12069                 ensure_complete_type (field->parent);
12070                 g_assert (result);
12071                 mono_metadata_free_type (type);
12072                 *handle_class = mono_defaults.fieldhandle_class;
12073         } else if (strcmp (obj->vtable->klass->name, "ConstructorOnTypeBuilderInst") == 0) {
12074                 MonoReflectionCtorOnTypeBuilderInst *c = (MonoReflectionCtorOnTypeBuilderInst*)obj;
12075                 MonoType *type = mono_class_inflate_generic_type (mono_reflection_type_get_handle ((MonoReflectionType*)c->inst), context);
12076                 MonoClass *inflated_klass = mono_class_from_mono_type (type);
12077                 MonoMethod *method;
12078
12079                 if (is_sre_ctor_builder (mono_object_class (c->cb)))
12080                         method = ((MonoReflectionCtorBuilder *)c->cb)->mhandle;
12081                 else if (is_sr_mono_cmethod (mono_object_class (c->cb)))
12082                         method = ((MonoReflectionMethod *)c->cb)->method;
12083                 else
12084                         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)));
12085
12086                 result = inflate_mono_method (inflated_klass, method, (MonoObject*)c->cb);
12087                 *handle_class = mono_defaults.methodhandle_class;
12088                 mono_metadata_free_type (type);
12089         } else if (strcmp (obj->vtable->klass->name, "MethodOnTypeBuilderInst") == 0) {
12090                 MonoReflectionMethodOnTypeBuilderInst *m = (MonoReflectionMethodOnTypeBuilderInst*)obj;
12091                 if (m->method_args) {
12092                         result = mono_reflection_method_on_tb_inst_get_handle (m);
12093                         if (context)
12094                                 result = mono_class_inflate_generic_method (result, context);
12095                 } else {
12096                         MonoType *type = mono_class_inflate_generic_type (mono_reflection_type_get_handle ((MonoReflectionType*)m->inst), context);
12097                         MonoClass *inflated_klass = mono_class_from_mono_type (type);
12098                         MonoMethod *method;
12099
12100                         if (is_sre_method_builder (mono_object_class (m->mb)))
12101                                 method = ((MonoReflectionMethodBuilder *)m->mb)->mhandle;
12102                         else if (is_sr_mono_method (mono_object_class (m->mb)))
12103                                 method = ((MonoReflectionMethod *)m->mb)->method;
12104                         else
12105                                 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)));
12106
12107                         result = inflate_mono_method (inflated_klass, method, (MonoObject*)m->mb);
12108                         mono_metadata_free_type (type);
12109                 }
12110                 *handle_class = mono_defaults.methodhandle_class;
12111         } else if (strcmp (obj->vtable->klass->name, "MonoArrayMethod") == 0) {
12112                 MonoReflectionArrayMethod *m = (MonoReflectionArrayMethod*)obj;
12113                 MonoType *mtype;
12114                 MonoClass *klass;
12115                 MonoMethod *method;
12116                 gpointer iter;
12117                 char *name;
12118
12119                 mtype = mono_reflection_type_get_handle (m->parent);
12120                 klass = mono_class_from_mono_type (mtype);
12121
12122                 /* Find the method */
12123
12124                 name = mono_string_to_utf8 (m->name);
12125                 iter = NULL;
12126                 while ((method = mono_class_get_methods (klass, &iter))) {
12127                         if (!strcmp (method->name, name))
12128                                 break;
12129                 }
12130                 g_free (name);
12131
12132                 // FIXME:
12133                 g_assert (method);
12134                 // FIXME: Check parameters/return value etc. match
12135
12136                 result = method;
12137                 *handle_class = mono_defaults.methodhandle_class;
12138         } else if (is_sre_array (mono_object_get_class(obj)) ||
12139                                 is_sre_byref (mono_object_get_class(obj)) ||
12140                                 is_sre_pointer (mono_object_get_class(obj))) {
12141                 MonoReflectionType *ref_type = (MonoReflectionType *)obj;
12142                 MonoType *type = mono_reflection_type_get_handle (ref_type);
12143
12144                 if (context) {
12145                         MonoType *inflated = mono_class_inflate_generic_type (type, context);
12146                         result = mono_class_from_mono_type (inflated);
12147                         mono_metadata_free_type (inflated);
12148                 } else {
12149                         result = mono_class_from_mono_type (type);
12150                 }
12151                 *handle_class = mono_defaults.typehandle_class;
12152         } else {
12153                 g_print ("%s\n", obj->vtable->klass->name);
12154                 g_assert_not_reached ();
12155         }
12156         return result;
12157 }
12158
12159 #else /* DISABLE_REFLECTION_EMIT */
12160
12161 MonoArray*
12162 mono_reflection_get_custom_attrs_blob (MonoReflectionAssembly *assembly, MonoObject *ctor, MonoArray *ctorArgs, MonoArray *properties, MonoArray *propValues, MonoArray *fields, MonoArray* fieldValues) 
12163 {
12164         g_assert_not_reached ();
12165         return NULL;
12166 }
12167
12168 void
12169 mono_reflection_setup_internal_class (MonoReflectionTypeBuilder *tb)
12170 {
12171         g_assert_not_reached ();
12172 }
12173
12174 void
12175 mono_reflection_setup_generic_class (MonoReflectionTypeBuilder *tb)
12176 {
12177         g_assert_not_reached ();
12178 }
12179
12180 void
12181 mono_reflection_create_generic_class (MonoReflectionTypeBuilder *tb)
12182 {
12183         g_assert_not_reached ();
12184 }
12185
12186 void
12187 mono_reflection_create_internal_class (MonoReflectionTypeBuilder *tb)
12188 {
12189         g_assert_not_reached ();
12190 }
12191
12192 void
12193 mono_image_basic_init (MonoReflectionAssemblyBuilder *assemblyb)
12194 {
12195         g_error ("This mono runtime was configured with --enable-minimal=reflection_emit, so System.Reflection.Emit is not supported.");
12196 }
12197
12198 void
12199 mono_image_module_basic_init (MonoReflectionModuleBuilder *moduleb)
12200 {
12201         g_assert_not_reached ();
12202 }
12203
12204 void
12205 mono_image_set_wrappers_type (MonoReflectionModuleBuilder *moduleb, MonoReflectionType *type)
12206 {
12207         g_assert_not_reached ();
12208 }
12209
12210 MonoReflectionModule *
12211 mono_image_load_module_dynamic (MonoReflectionAssemblyBuilder *ab, MonoString *fileName)
12212 {
12213         g_assert_not_reached ();
12214         return NULL;
12215 }
12216
12217 guint32
12218 mono_image_insert_string (MonoReflectionModuleBuilder *module, MonoString *str)
12219 {
12220         g_assert_not_reached ();
12221         return 0;
12222 }
12223
12224 guint32
12225 mono_image_create_method_token (MonoDynamicImage *assembly, MonoObject *obj, MonoArray *opt_param_types)
12226 {
12227         g_assert_not_reached ();
12228         return 0;
12229 }
12230
12231 guint32
12232 mono_image_create_token (MonoDynamicImage *assembly, MonoObject *obj, 
12233                                                  gboolean create_open_instance, gboolean register_token)
12234 {
12235         g_assert_not_reached ();
12236         return 0;
12237 }
12238
12239 void
12240 mono_image_register_token (MonoDynamicImage *assembly, guint32 token, MonoObject *obj)
12241 {
12242 }
12243
12244 void
12245 mono_reflection_generic_class_initialize (MonoReflectionGenericClass *type, MonoArray *fields)
12246 {
12247         g_assert_not_reached ();
12248 }
12249
12250 void
12251 mono_reflection_get_dynamic_overrides (MonoClass *klass, MonoMethod ***overrides, int *num_overrides)
12252 {
12253         *overrides = NULL;
12254         *num_overrides = 0;
12255 }
12256
12257 MonoReflectionEvent *
12258 mono_reflection_event_builder_get_event_info (MonoReflectionTypeBuilder *tb, MonoReflectionEventBuilder *eb)
12259 {
12260         g_assert_not_reached ();
12261         return NULL;
12262 }
12263
12264 MonoReflectionType*
12265 mono_reflection_create_runtime_class (MonoReflectionTypeBuilder *tb)
12266 {
12267         g_assert_not_reached ();
12268         return NULL;
12269 }
12270
12271 void
12272 mono_reflection_initialize_generic_parameter (MonoReflectionGenericParam *gparam)
12273 {
12274         g_assert_not_reached ();
12275 }
12276
12277 MonoArray *
12278 mono_reflection_sighelper_get_signature_local (MonoReflectionSigHelper *sig)
12279 {
12280         g_assert_not_reached ();
12281         return NULL;
12282 }
12283
12284 MonoArray *
12285 mono_reflection_sighelper_get_signature_field (MonoReflectionSigHelper *sig)
12286 {
12287         g_assert_not_reached ();
12288         return NULL;
12289 }
12290
12291 void 
12292 mono_reflection_create_dynamic_method (MonoReflectionDynamicMethod *mb)
12293 {
12294 }
12295
12296 gpointer
12297 mono_reflection_lookup_dynamic_token (MonoImage *image, guint32 token, gboolean valid_token, MonoClass **handle_class, MonoGenericContext *context)
12298 {
12299         return NULL;
12300 }
12301
12302 MonoType*
12303 mono_reflection_type_get_handle (MonoReflectionType* ref)
12304 {
12305         if (!ref)
12306                 return NULL;
12307         return ref->type;
12308 }
12309
12310 void
12311 mono_reflection_free_dynamic_generic_class (MonoGenericClass *gclass)
12312 {
12313         g_assert_not_reached ();
12314 }
12315
12316 #endif /* DISABLE_REFLECTION_EMIT */
12317
12318 /* SECURITY_ACTION_* are defined in mono/metadata/tabledefs.h */
12319 const static guint32 declsec_flags_map[] = {
12320         0x00000000,                                     /* empty */
12321         MONO_DECLSEC_FLAG_REQUEST,                      /* SECURITY_ACTION_REQUEST                      (x01) */
12322         MONO_DECLSEC_FLAG_DEMAND,                       /* SECURITY_ACTION_DEMAND                       (x02) */
12323         MONO_DECLSEC_FLAG_ASSERT,                       /* SECURITY_ACTION_ASSERT                       (x03) */
12324         MONO_DECLSEC_FLAG_DENY,                         /* SECURITY_ACTION_DENY                         (x04) */
12325         MONO_DECLSEC_FLAG_PERMITONLY,                   /* SECURITY_ACTION_PERMITONLY                   (x05) */
12326         MONO_DECLSEC_FLAG_LINKDEMAND,                   /* SECURITY_ACTION_LINKDEMAND                   (x06) */
12327         MONO_DECLSEC_FLAG_INHERITANCEDEMAND,            /* SECURITY_ACTION_INHERITANCEDEMAND            (x07) */
12328         MONO_DECLSEC_FLAG_REQUEST_MINIMUM,              /* SECURITY_ACTION_REQUEST_MINIMUM              (x08) */
12329         MONO_DECLSEC_FLAG_REQUEST_OPTIONAL,             /* SECURITY_ACTION_REQUEST_OPTIONAL             (x09) */
12330         MONO_DECLSEC_FLAG_REQUEST_REFUSE,               /* SECURITY_ACTION_REQUEST_REFUSE               (x0A) */
12331         MONO_DECLSEC_FLAG_PREJIT_GRANT,                 /* SECURITY_ACTION_PREJIT_GRANT                 (x0B) */
12332         MONO_DECLSEC_FLAG_PREJIT_DENY,                  /* SECURITY_ACTION_PREJIT_DENY                  (x0C) */
12333         MONO_DECLSEC_FLAG_NONCAS_DEMAND,                /* SECURITY_ACTION_NONCAS_DEMAND                (x0D) */
12334         MONO_DECLSEC_FLAG_NONCAS_LINKDEMAND,            /* SECURITY_ACTION_NONCAS_LINKDEMAND            (x0E) */
12335         MONO_DECLSEC_FLAG_NONCAS_INHERITANCEDEMAND,     /* SECURITY_ACTION_NONCAS_INHERITANCEDEMAND     (x0F) */
12336         MONO_DECLSEC_FLAG_LINKDEMAND_CHOICE,            /* SECURITY_ACTION_LINKDEMAND_CHOICE            (x10) */
12337         MONO_DECLSEC_FLAG_INHERITANCEDEMAND_CHOICE,     /* SECURITY_ACTION_INHERITANCEDEMAND_CHOICE     (x11) */
12338         MONO_DECLSEC_FLAG_DEMAND_CHOICE,                /* SECURITY_ACTION_DEMAND_CHOICE                (x12) */
12339 };
12340
12341 /*
12342  * Returns flags that includes all available security action associated to the handle.
12343  * @token: metadata token (either for a class or a method)
12344  * @image: image where resides the metadata.
12345  */
12346 static guint32
12347 mono_declsec_get_flags (MonoImage *image, guint32 token)
12348 {
12349         int index = mono_metadata_declsec_from_index (image, token);
12350         MonoTableInfo *t = &image->tables [MONO_TABLE_DECLSECURITY];
12351         guint32 result = 0;
12352         guint32 action;
12353         int i;
12354
12355         /* HasSecurity can be present for other, not specially encoded, attributes,
12356            e.g. SuppressUnmanagedCodeSecurityAttribute */
12357         if (index < 0)
12358                 return 0;
12359
12360         for (i = index; i < t->rows; i++) {
12361                 guint32 cols [MONO_DECL_SECURITY_SIZE];
12362
12363                 mono_metadata_decode_row (t, i, cols, MONO_DECL_SECURITY_SIZE);
12364                 if (cols [MONO_DECL_SECURITY_PARENT] != token)
12365                         break;
12366
12367                 action = cols [MONO_DECL_SECURITY_ACTION];
12368                 if ((action >= MONO_DECLSEC_ACTION_MIN) && (action <= MONO_DECLSEC_ACTION_MAX)) {
12369                         result |= declsec_flags_map [action];
12370                 } else {
12371                         g_assert_not_reached ();
12372                 }
12373         }
12374         return result;
12375 }
12376
12377 /*
12378  * Get the security actions (in the form of flags) associated with the specified method.
12379  *
12380  * @method: The method for which we want the declarative security flags.
12381  * Return the declarative security flags for the method (only).
12382  *
12383  * Note: To keep MonoMethod size down we do not cache the declarative security flags
12384  *       (except for the stack modifiers which are kept in the MonoJitInfo structure)
12385  */
12386 guint32
12387 mono_declsec_flags_from_method (MonoMethod *method)
12388 {
12389         if (method->flags & METHOD_ATTRIBUTE_HAS_SECURITY) {
12390                 /* FIXME: No cache (for the moment) */
12391                 guint32 idx = mono_method_get_index (method);
12392                 idx <<= MONO_HAS_DECL_SECURITY_BITS;
12393                 idx |= MONO_HAS_DECL_SECURITY_METHODDEF;
12394                 return mono_declsec_get_flags (method->klass->image, idx);
12395         }
12396         return 0;
12397 }
12398
12399 /*
12400  * Get the security actions (in the form of flags) associated with the specified class.
12401  *
12402  * @klass: The class for which we want the declarative security flags.
12403  * Return the declarative security flags for the class.
12404  *
12405  * Note: We cache the flags inside the MonoClass structure as this will get 
12406  *       called very often (at least for each method).
12407  */
12408 guint32
12409 mono_declsec_flags_from_class (MonoClass *klass)
12410 {
12411         if (klass->flags & TYPE_ATTRIBUTE_HAS_SECURITY) {
12412                 if (!klass->ext || !klass->ext->declsec_flags) {
12413                         guint32 idx;
12414
12415                         idx = mono_metadata_token_index (klass->type_token);
12416                         idx <<= MONO_HAS_DECL_SECURITY_BITS;
12417                         idx |= MONO_HAS_DECL_SECURITY_TYPEDEF;
12418                         mono_loader_lock ();
12419                         mono_class_alloc_ext (klass);
12420                         mono_loader_unlock ();
12421                         /* we cache the flags on classes */
12422                         klass->ext->declsec_flags = mono_declsec_get_flags (klass->image, idx);
12423                 }
12424                 return klass->ext->declsec_flags;
12425         }
12426         return 0;
12427 }
12428
12429 /*
12430  * Get the security actions (in the form of flags) associated with the specified assembly.
12431  *
12432  * @assembly: The assembly for which we want the declarative security flags.
12433  * Return the declarative security flags for the assembly.
12434  */
12435 guint32
12436 mono_declsec_flags_from_assembly (MonoAssembly *assembly)
12437 {
12438         guint32 idx = 1; /* there is only one assembly */
12439         idx <<= MONO_HAS_DECL_SECURITY_BITS;
12440         idx |= MONO_HAS_DECL_SECURITY_ASSEMBLY;
12441         return mono_declsec_get_flags (assembly->image, idx);
12442 }
12443
12444
12445 /*
12446  * Fill actions for the specific index (which may either be an encoded class token or
12447  * an encoded method token) from the metadata image.
12448  * Returns TRUE if some actions requiring code generation are present, FALSE otherwise.
12449  */
12450 static MonoBoolean
12451 fill_actions_from_index (MonoImage *image, guint32 token, MonoDeclSecurityActions* actions,
12452         guint32 id_std, guint32 id_noncas, guint32 id_choice)
12453 {
12454         MonoBoolean result = FALSE;
12455         MonoTableInfo *t;
12456         guint32 cols [MONO_DECL_SECURITY_SIZE];
12457         int index = mono_metadata_declsec_from_index (image, token);
12458         int i;
12459
12460         t  = &image->tables [MONO_TABLE_DECLSECURITY];
12461         for (i = index; i < t->rows; i++) {
12462                 mono_metadata_decode_row (t, i, cols, MONO_DECL_SECURITY_SIZE);
12463
12464                 if (cols [MONO_DECL_SECURITY_PARENT] != token)
12465                         return result;
12466
12467                 /* if present only replace (class) permissions with method permissions */
12468                 /* if empty accept either class or method permissions */
12469                 if (cols [MONO_DECL_SECURITY_ACTION] == id_std) {
12470                         if (!actions->demand.blob) {
12471                                 const char *blob = mono_metadata_blob_heap (image, cols [MONO_DECL_SECURITY_PERMISSIONSET]);
12472                                 actions->demand.index = cols [MONO_DECL_SECURITY_PERMISSIONSET];
12473                                 actions->demand.blob = (char*) (blob + 2);
12474                                 actions->demand.size = mono_metadata_decode_blob_size (blob, &blob);
12475                                 result = TRUE;
12476                         }
12477                 } else if (cols [MONO_DECL_SECURITY_ACTION] == id_noncas) {
12478                         if (!actions->noncasdemand.blob) {
12479                                 const char *blob = mono_metadata_blob_heap (image, cols [MONO_DECL_SECURITY_PERMISSIONSET]);
12480                                 actions->noncasdemand.index = cols [MONO_DECL_SECURITY_PERMISSIONSET];
12481                                 actions->noncasdemand.blob = (char*) (blob + 2);
12482                                 actions->noncasdemand.size = mono_metadata_decode_blob_size (blob, &blob);
12483                                 result = TRUE;
12484                         }
12485                 } else if (cols [MONO_DECL_SECURITY_ACTION] == id_choice) {
12486                         if (!actions->demandchoice.blob) {
12487                                 const char *blob = mono_metadata_blob_heap (image, cols [MONO_DECL_SECURITY_PERMISSIONSET]);
12488                                 actions->demandchoice.index = cols [MONO_DECL_SECURITY_PERMISSIONSET];
12489                                 actions->demandchoice.blob = (char*) (blob + 2);
12490                                 actions->demandchoice.size = mono_metadata_decode_blob_size (blob, &blob);
12491                                 result = TRUE;
12492                         }
12493                 }
12494         }
12495
12496         return result;
12497 }
12498
12499 static MonoBoolean
12500 mono_declsec_get_class_demands_params (MonoClass *klass, MonoDeclSecurityActions* demands, 
12501         guint32 id_std, guint32 id_noncas, guint32 id_choice)
12502 {
12503         guint32 idx = mono_metadata_token_index (klass->type_token);
12504         idx <<= MONO_HAS_DECL_SECURITY_BITS;
12505         idx |= MONO_HAS_DECL_SECURITY_TYPEDEF;
12506         return fill_actions_from_index (klass->image, idx, demands, id_std, id_noncas, id_choice);
12507 }
12508
12509 static MonoBoolean
12510 mono_declsec_get_method_demands_params (MonoMethod *method, MonoDeclSecurityActions* demands, 
12511         guint32 id_std, guint32 id_noncas, guint32 id_choice)
12512 {
12513         guint32 idx = mono_method_get_index (method);
12514         idx <<= MONO_HAS_DECL_SECURITY_BITS;
12515         idx |= MONO_HAS_DECL_SECURITY_METHODDEF;
12516         return fill_actions_from_index (method->klass->image, idx, demands, id_std, id_noncas, id_choice);
12517 }
12518
12519 /*
12520  * Collect all actions (that requires to generate code in mini) assigned for
12521  * the specified method.
12522  * Note: Don't use the content of actions if the function return FALSE.
12523  */
12524 MonoBoolean
12525 mono_declsec_get_demands (MonoMethod *method, MonoDeclSecurityActions* demands)
12526 {
12527         guint32 mask = MONO_DECLSEC_FLAG_DEMAND | MONO_DECLSEC_FLAG_NONCAS_DEMAND | 
12528                 MONO_DECLSEC_FLAG_DEMAND_CHOICE;
12529         MonoBoolean result = FALSE;
12530         guint32 flags;
12531
12532         /* quick exit if no declarative security is present in the metadata */
12533         if (!method->klass->image->tables [MONO_TABLE_DECLSECURITY].rows)
12534                 return FALSE;
12535
12536         /* we want the original as the wrapper is "free" of the security informations */
12537         if (method->wrapper_type == MONO_WRAPPER_MANAGED_TO_NATIVE || method->wrapper_type == MONO_WRAPPER_MANAGED_TO_MANAGED) {
12538                 method = mono_marshal_method_from_wrapper (method);
12539                 if (!method)
12540                         return FALSE;
12541         }
12542
12543         /* First we look for method-level attributes */
12544         if (method->flags & METHOD_ATTRIBUTE_HAS_SECURITY) {
12545                 mono_class_init (method->klass);
12546                 memset (demands, 0, sizeof (MonoDeclSecurityActions));
12547
12548                 result = mono_declsec_get_method_demands_params (method, demands, 
12549                         SECURITY_ACTION_DEMAND, SECURITY_ACTION_NONCASDEMAND, SECURITY_ACTION_DEMANDCHOICE);
12550         }
12551
12552         /* Here we use (or create) the class declarative cache to look for demands */
12553         flags = mono_declsec_flags_from_class (method->klass);
12554         if (flags & mask) {
12555                 if (!result) {
12556                         mono_class_init (method->klass);
12557                         memset (demands, 0, sizeof (MonoDeclSecurityActions));
12558                 }
12559                 result |= mono_declsec_get_class_demands_params (method->klass, demands, 
12560                         SECURITY_ACTION_DEMAND, SECURITY_ACTION_NONCASDEMAND, SECURITY_ACTION_DEMANDCHOICE);
12561         }
12562
12563         /* The boolean return value is used as a shortcut in case nothing needs to
12564            be generated (e.g. LinkDemand[Choice] and InheritanceDemand[Choice]) */
12565         return result;
12566 }
12567
12568
12569 /*
12570  * Collect all Link actions: LinkDemand, NonCasLinkDemand and LinkDemandChoice (2.0).
12571  *
12572  * Note: Don't use the content of actions if the function return FALSE.
12573  */
12574 MonoBoolean
12575 mono_declsec_get_linkdemands (MonoMethod *method, MonoDeclSecurityActions* klass, MonoDeclSecurityActions *cmethod)
12576 {
12577         MonoBoolean result = FALSE;
12578         guint32 flags;
12579
12580         /* quick exit if no declarative security is present in the metadata */
12581         if (!method->klass->image->tables [MONO_TABLE_DECLSECURITY].rows)
12582                 return FALSE;
12583
12584         /* we want the original as the wrapper is "free" of the security informations */
12585         if (method->wrapper_type == MONO_WRAPPER_MANAGED_TO_NATIVE || method->wrapper_type == MONO_WRAPPER_MANAGED_TO_MANAGED) {
12586                 method = mono_marshal_method_from_wrapper (method);
12587                 if (!method)
12588                         return FALSE;
12589         }
12590
12591         /* results are independant - zeroize both */
12592         memset (cmethod, 0, sizeof (MonoDeclSecurityActions));
12593         memset (klass, 0, sizeof (MonoDeclSecurityActions));
12594
12595         /* First we look for method-level attributes */
12596         if (method->flags & METHOD_ATTRIBUTE_HAS_SECURITY) {
12597                 mono_class_init (method->klass);
12598
12599                 result = mono_declsec_get_method_demands_params (method, cmethod, 
12600                         SECURITY_ACTION_LINKDEMAND, SECURITY_ACTION_NONCASLINKDEMAND, SECURITY_ACTION_LINKDEMANDCHOICE);
12601         }
12602
12603         /* Here we use (or create) the class declarative cache to look for demands */
12604         flags = mono_declsec_flags_from_class (method->klass);
12605         if (flags & (MONO_DECLSEC_FLAG_LINKDEMAND | MONO_DECLSEC_FLAG_NONCAS_LINKDEMAND | MONO_DECLSEC_FLAG_LINKDEMAND_CHOICE)) {
12606                 mono_class_init (method->klass);
12607
12608                 result |= mono_declsec_get_class_demands_params (method->klass, klass, 
12609                         SECURITY_ACTION_LINKDEMAND, SECURITY_ACTION_NONCASLINKDEMAND, SECURITY_ACTION_LINKDEMANDCHOICE);
12610         }
12611
12612         return result;
12613 }
12614
12615 /*
12616  * Collect all Inherit actions: InheritanceDemand, NonCasInheritanceDemand and InheritanceDemandChoice (2.0).
12617  *
12618  * @klass       The inherited class - this is the class that provides the security check (attributes)
12619  * @demans      
12620  * return TRUE if inheritance demands (any kind) are present, FALSE otherwise.
12621  * 
12622  * Note: Don't use the content of actions if the function return FALSE.
12623  */
12624 MonoBoolean
12625 mono_declsec_get_inheritdemands_class (MonoClass *klass, MonoDeclSecurityActions* demands)
12626 {
12627         MonoBoolean result = FALSE;
12628         guint32 flags;
12629
12630         /* quick exit if no declarative security is present in the metadata */
12631         if (!klass->image->tables [MONO_TABLE_DECLSECURITY].rows)
12632                 return FALSE;
12633
12634         /* Here we use (or create) the class declarative cache to look for demands */
12635         flags = mono_declsec_flags_from_class (klass);
12636         if (flags & (MONO_DECLSEC_FLAG_INHERITANCEDEMAND | MONO_DECLSEC_FLAG_NONCAS_INHERITANCEDEMAND | MONO_DECLSEC_FLAG_INHERITANCEDEMAND_CHOICE)) {
12637                 mono_class_init (klass);
12638                 memset (demands, 0, sizeof (MonoDeclSecurityActions));
12639
12640                 result |= mono_declsec_get_class_demands_params (klass, demands, 
12641                         SECURITY_ACTION_INHERITDEMAND, SECURITY_ACTION_NONCASINHERITANCE, SECURITY_ACTION_INHERITDEMANDCHOICE);
12642         }
12643
12644         return result;
12645 }
12646
12647 /*
12648  * Collect all Inherit actions: InheritanceDemand, NonCasInheritanceDemand and InheritanceDemandChoice (2.0).
12649  *
12650  * Note: Don't use the content of actions if the function return FALSE.
12651  */
12652 MonoBoolean
12653 mono_declsec_get_inheritdemands_method (MonoMethod *method, MonoDeclSecurityActions* demands)
12654 {
12655         /* quick exit if no declarative security is present in the metadata */
12656         if (!method->klass->image->tables [MONO_TABLE_DECLSECURITY].rows)
12657                 return FALSE;
12658
12659         /* we want the original as the wrapper is "free" of the security informations */
12660         if (method->wrapper_type == MONO_WRAPPER_MANAGED_TO_NATIVE || method->wrapper_type == MONO_WRAPPER_MANAGED_TO_MANAGED) {
12661                 method = mono_marshal_method_from_wrapper (method);
12662                 if (!method)
12663                         return FALSE;
12664         }
12665
12666         if (method->flags & METHOD_ATTRIBUTE_HAS_SECURITY) {
12667                 mono_class_init (method->klass);
12668                 memset (demands, 0, sizeof (MonoDeclSecurityActions));
12669
12670                 return mono_declsec_get_method_demands_params (method, demands, 
12671                         SECURITY_ACTION_INHERITDEMAND, SECURITY_ACTION_NONCASINHERITANCE, SECURITY_ACTION_INHERITDEMANDCHOICE);
12672         }
12673         return FALSE;
12674 }
12675
12676
12677 static MonoBoolean
12678 get_declsec_action (MonoImage *image, guint32 token, guint32 action, MonoDeclSecurityEntry *entry)
12679 {
12680         guint32 cols [MONO_DECL_SECURITY_SIZE];
12681         MonoTableInfo *t;
12682         int i;
12683
12684         int index = mono_metadata_declsec_from_index (image, token);
12685         if (index == -1)
12686                 return FALSE;
12687
12688         t =  &image->tables [MONO_TABLE_DECLSECURITY];
12689         for (i = index; i < t->rows; i++) {
12690                 mono_metadata_decode_row (t, i, cols, MONO_DECL_SECURITY_SIZE);
12691
12692                 /* shortcut - index are ordered */
12693                 if (token != cols [MONO_DECL_SECURITY_PARENT])
12694                         return FALSE;
12695
12696                 if (cols [MONO_DECL_SECURITY_ACTION] == action) {
12697                         const char *metadata = mono_metadata_blob_heap (image, cols [MONO_DECL_SECURITY_PERMISSIONSET]);
12698                         entry->blob = (char*) (metadata + 2);
12699                         entry->size = mono_metadata_decode_blob_size (metadata, &metadata);
12700                         return TRUE;
12701                 }
12702         }
12703
12704         return FALSE;
12705 }
12706
12707 MonoBoolean
12708 mono_declsec_get_method_action (MonoMethod *method, guint32 action, MonoDeclSecurityEntry *entry)
12709 {
12710         if (method->flags & METHOD_ATTRIBUTE_HAS_SECURITY) {
12711                 guint32 idx = mono_method_get_index (method);
12712                 idx <<= MONO_HAS_DECL_SECURITY_BITS;
12713                 idx |= MONO_HAS_DECL_SECURITY_METHODDEF;
12714                 return get_declsec_action (method->klass->image, idx, action, entry);
12715         }
12716         return FALSE;
12717 }
12718
12719 MonoBoolean
12720 mono_declsec_get_class_action (MonoClass *klass, guint32 action, MonoDeclSecurityEntry *entry)
12721 {
12722         /* use cache */
12723         guint32 flags = mono_declsec_flags_from_class (klass);
12724         if (declsec_flags_map [action] & flags) {
12725                 guint32 idx = mono_metadata_token_index (klass->type_token);
12726                 idx <<= MONO_HAS_DECL_SECURITY_BITS;
12727                 idx |= MONO_HAS_DECL_SECURITY_TYPEDEF;
12728                 return get_declsec_action (klass->image, idx, action, entry);
12729         }
12730         return FALSE;
12731 }
12732
12733 MonoBoolean
12734 mono_declsec_get_assembly_action (MonoAssembly *assembly, guint32 action, MonoDeclSecurityEntry *entry)
12735 {
12736         guint32 idx = 1; /* there is only one assembly */
12737         idx <<= MONO_HAS_DECL_SECURITY_BITS;
12738         idx |= MONO_HAS_DECL_SECURITY_ASSEMBLY;
12739
12740         return get_declsec_action (assembly->image, idx, action, entry);
12741 }
12742
12743 gboolean
12744 mono_reflection_call_is_assignable_to (MonoClass *klass, MonoClass *oklass)
12745 {
12746         MonoObject *res, *exc;
12747         void *params [1];
12748         static MonoClass *System_Reflection_Emit_TypeBuilder = NULL;
12749         static MonoMethod *method = NULL;
12750
12751         if (!System_Reflection_Emit_TypeBuilder) {
12752                 System_Reflection_Emit_TypeBuilder = mono_class_from_name (mono_defaults.corlib, "System.Reflection.Emit", "TypeBuilder");
12753                 g_assert (System_Reflection_Emit_TypeBuilder);
12754         }
12755         if (method == NULL) {
12756                 method = mono_class_get_method_from_name (System_Reflection_Emit_TypeBuilder, "IsAssignableTo", 1);
12757                 g_assert (method);
12758         }
12759
12760         /* 
12761          * The result of mono_type_get_object () might be a System.MonoType but we
12762          * need a TypeBuilder so use mono_class_get_ref_info (klass).
12763          */
12764         g_assert (mono_class_get_ref_info (klass));
12765         g_assert (!strcmp (((MonoObject*)(mono_class_get_ref_info (klass)))->vtable->klass->name, "TypeBuilder"));
12766
12767         params [0] = mono_type_get_object (mono_domain_get (), &oklass->byval_arg);
12768
12769         res = mono_runtime_invoke (method, (MonoObject*)(mono_class_get_ref_info (klass)), params, &exc);
12770         if (exc)
12771                 return FALSE;
12772         else
12773                 return *(MonoBoolean*)mono_object_unbox (res);
12774 }
12775
12776 /**
12777  * mono_reflection_type_get_type:
12778  * @reftype: the System.Type object
12779  *
12780  * Returns the MonoType* associated with the C# System.Type object @reftype.
12781  */
12782 MonoType*
12783 mono_reflection_type_get_type (MonoReflectionType *reftype)
12784 {
12785         g_assert (reftype);
12786
12787         return mono_reflection_type_get_handle (reftype);
12788 }
12789