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