2009-08-19 Rodrigo Kumpera <rkumpera@novell.com>
[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  *
10  */
11 #include <config.h>
12 #include "mono/utils/mono-digest.h"
13 #include "mono/utils/mono-membar.h"
14 #include "mono/metadata/reflection.h"
15 #include "mono/metadata/tabledefs.h"
16 #include "mono/metadata/metadata-internals.h"
17 #include <mono/metadata/profiler-private.h>
18 #include "mono/metadata/class-internals.h"
19 #include "mono/metadata/gc-internal.h"
20 #include "mono/metadata/tokentype.h"
21 #include "mono/metadata/domain-internals.h"
22 #include "mono/metadata/opcodes.h"
23 #include "mono/metadata/assembly.h"
24 #include "mono/metadata/object-internals.h"
25 #include <mono/metadata/exception.h>
26 #include <mono/metadata/marshal.h>
27 #include <mono/metadata/security-manager.h>
28 #include <stdio.h>
29 #include <glib.h>
30 #include <errno.h>
31 #include <time.h>
32 #include <string.h>
33 #include <ctype.h>
34 #include "image.h"
35 #include "cil-coff.h"
36 #include "mono-endian.h"
37 #include <mono/metadata/gc-internal.h>
38 #include <mono/metadata/mempool-internals.h>
39 #include <mono/metadata/security-core-clr.h>
40 #include <mono/metadata/debug-helpers.h>
41
42 #if HAVE_SGEN_GC
43 static void* reflection_info_desc = NULL;
44 #define MOVING_GC_REGISTER(addr) do {   \
45                 if (!reflection_info_desc) {    \
46                         gsize bmap = 1;         \
47                         reflection_info_desc = mono_gc_make_descr_from_bitmap (&bmap, 1);       \
48                 }       \
49                 mono_gc_register_root ((char*)(addr), sizeof (gpointer), reflection_info_desc); \
50         } while (0)
51 #else
52 #define MOVING_GC_REGISTER(addr)
53 #endif
54
55 typedef struct {
56         char *p;
57         char *buf;
58         char *end;
59 } SigBuffer;
60
61 #define TEXT_OFFSET 512
62 #define CLI_H_SIZE 136
63 #define FILE_ALIGN 512
64 #define VIRT_ALIGN 8192
65 #define START_TEXT_RVA  0x00002000
66
67 typedef struct {
68         MonoReflectionILGen *ilgen;
69         MonoReflectionType *rtype;
70         MonoArray *parameters;
71         MonoArray *generic_params;
72         MonoGenericContainer *generic_container;
73         MonoArray *pinfo;
74         MonoArray *opt_types;
75         guint32 attrs;
76         guint32 iattrs;
77         guint32 call_conv;
78         guint32 *table_idx; /* note: it's a pointer */
79         MonoArray *code;
80         MonoObject *type;
81         MonoString *name;
82         MonoBoolean init_locals;
83         MonoBoolean skip_visibility;
84         MonoArray *return_modreq;
85         MonoArray *return_modopt;
86         MonoArray *param_modreq;
87         MonoArray *param_modopt;
88         MonoArray *permissions;
89         MonoMethod *mhandle;
90         guint32 nrefs;
91         gpointer *refs;
92         /* for PInvoke */
93         int charset, extra_flags, native_cc;
94         MonoString *dll, *dllentry;
95 } ReflectionMethodBuilder;
96
97 typedef struct {
98         guint32 owner;
99         MonoReflectionGenericParam *gparam;
100 } GenericParamTableEntry;
101
102 const unsigned char table_sizes [MONO_TABLE_NUM] = {
103         MONO_MODULE_SIZE,
104         MONO_TYPEREF_SIZE,
105         MONO_TYPEDEF_SIZE,
106         0,
107         MONO_FIELD_SIZE,
108         0,
109         MONO_METHOD_SIZE,
110         0,
111         MONO_PARAM_SIZE,
112         MONO_INTERFACEIMPL_SIZE,
113         MONO_MEMBERREF_SIZE,    /* 0x0A */
114         MONO_CONSTANT_SIZE,
115         MONO_CUSTOM_ATTR_SIZE,
116         MONO_FIELD_MARSHAL_SIZE,
117         MONO_DECL_SECURITY_SIZE,
118         MONO_CLASS_LAYOUT_SIZE,
119         MONO_FIELD_LAYOUT_SIZE, /* 0x10 */
120         MONO_STAND_ALONE_SIGNATURE_SIZE,
121         MONO_EVENT_MAP_SIZE,
122         0,
123         MONO_EVENT_SIZE,
124         MONO_PROPERTY_MAP_SIZE,
125         0,
126         MONO_PROPERTY_SIZE,
127         MONO_METHOD_SEMA_SIZE,
128         MONO_METHODIMPL_SIZE,
129         MONO_MODULEREF_SIZE,    /* 0x1A */
130         MONO_TYPESPEC_SIZE,
131         MONO_IMPLMAP_SIZE,      
132         MONO_FIELD_RVA_SIZE,
133         0,
134         0,
135         MONO_ASSEMBLY_SIZE,     /* 0x20 */
136         MONO_ASSEMBLY_PROCESSOR_SIZE,
137         MONO_ASSEMBLYOS_SIZE,
138         MONO_ASSEMBLYREF_SIZE,
139         MONO_ASSEMBLYREFPROC_SIZE,
140         MONO_ASSEMBLYREFOS_SIZE,
141         MONO_FILE_SIZE,
142         MONO_EXP_TYPE_SIZE,
143         MONO_MANIFEST_SIZE,
144         MONO_NESTED_CLASS_SIZE,
145
146         MONO_GENERICPARAM_SIZE, /* 0x2A */
147         MONO_METHODSPEC_SIZE,
148         MONO_GENPARCONSTRAINT_SIZE
149
150 };
151
152 #ifndef DISABLE_REFLECTION_EMIT
153 static guint32 mono_image_get_methodref_token (MonoDynamicImage *assembly, MonoMethod *method, gboolean create_typespec);
154 static guint32 mono_image_get_methodbuilder_token (MonoDynamicImage *assembly, MonoReflectionMethodBuilder *mb, gboolean create_methodspec);
155 static guint32 mono_image_get_ctorbuilder_token (MonoDynamicImage *assembly, MonoReflectionCtorBuilder *cb);
156 static guint32 mono_image_get_sighelper_token (MonoDynamicImage *assembly, MonoReflectionSigHelper *helper);
157 static void    ensure_runtime_vtable (MonoClass *klass);
158 static gpointer resolve_object (MonoImage *image, MonoObject *obj, MonoClass **handle_class, MonoGenericContext *context);
159 static guint32 mono_image_get_methodref_token_for_methodbuilder (MonoDynamicImage *assembly, MonoReflectionMethodBuilder *method);
160 static guint32 encode_generic_method_sig (MonoDynamicImage *assembly, MonoGenericContext *context);
161 static gpointer register_assembly (MonoDomain *domain, MonoReflectionAssembly *res, MonoAssembly *assembly);
162 #endif
163
164 static void reflection_methodbuilder_from_method_builder (ReflectionMethodBuilder *rmb, MonoReflectionMethodBuilder *mb);
165 static void reflection_methodbuilder_from_ctor_builder (ReflectionMethodBuilder *rmb, MonoReflectionCtorBuilder *mb);
166 static guint32 mono_image_typedef_or_ref (MonoDynamicImage *assembly, MonoType *type);
167 static guint32 mono_image_typedef_or_ref_full (MonoDynamicImage *assembly, MonoType *type, gboolean try_typespec);
168 static void    mono_image_get_generic_param_info (MonoReflectionGenericParam *gparam, guint32 owner, MonoDynamicImage *assembly);
169 static guint32 encode_marshal_blob (MonoDynamicImage *assembly, MonoReflectionMarshal *minfo);
170 static guint32 encode_constant (MonoDynamicImage *assembly, MonoObject *val, guint32 *ret_type);
171 static char*   type_get_qualified_name (MonoType *type, MonoAssembly *ass);
172 static void    encode_type (MonoDynamicImage *assembly, MonoType *type, SigBuffer *buf);
173 static void get_default_param_value_blobs (MonoMethod *method, char **blobs, guint32 *types);
174 static MonoObject *mono_get_object_from_blob (MonoDomain *domain, MonoType *type, const char *blob);
175 static MonoReflectionType *mono_reflection_type_get_underlying_system_type (MonoReflectionType* t);
176 static MonoType* mono_reflection_get_type_with_rootimage (MonoImage *rootimage, MonoImage* image, MonoTypeNameParse *info, gboolean ignorecase, gboolean *type_resolve);
177 static MonoReflectionType* mono_reflection_type_resolve_user_types (MonoReflectionType *type);
178 static gboolean is_sre_array (MonoClass *class);
179 static gboolean is_sre_byref (MonoClass *class);
180 static gboolean is_sre_pointer (MonoClass *class);
181 static guint32 mono_image_get_methodspec_token (MonoDynamicImage *assembly, MonoMethod *method);
182 static guint32 mono_image_get_inflated_method_token (MonoDynamicImage *assembly, MonoMethod *m);
183 static MonoMethod * inflate_method (MonoReflectionGenericClass *type, MonoObject *obj);
184
185 #define RESOLVE_TYPE(type) do { type = (void*)mono_reflection_type_resolve_user_types ((MonoReflectionType*)type); } while (0)
186 #define RESOLVE_ARRAY_TYPE_ELEMENT(array, index) do {   \
187         MonoReflectionType *__type = mono_array_get (array, MonoReflectionType*, index);        \
188         __type = mono_reflection_type_resolve_user_types (__type);      \
189         mono_array_set (arr, MonoReflectionType*, index, __type);       \
190 } while (0)
191
192 #define mono_type_array_get_and_resolve(array, index) mono_reflection_type_get_handle ((MonoReflectionType*)mono_array_get (array, gpointer, index))
193
194 void
195 mono_reflection_init (void)
196 {
197 }
198
199 static void
200 sigbuffer_init (SigBuffer *buf, int size)
201 {
202         buf->buf = g_malloc (size);
203         buf->p = buf->buf;
204         buf->end = buf->buf + size;
205 }
206
207 static void
208 sigbuffer_make_room (SigBuffer *buf, int size)
209 {
210         if (buf->end - buf->p < size) {
211                 int new_size = buf->end - buf->buf + size + 32;
212                 char *p = g_realloc (buf->buf, new_size);
213                 size = buf->p - buf->buf;
214                 buf->buf = p;
215                 buf->p = p + size;
216                 buf->end = buf->buf + new_size;
217         }
218 }
219
220 static void
221 sigbuffer_add_value (SigBuffer *buf, guint32 val)
222 {
223         sigbuffer_make_room (buf, 6);
224         mono_metadata_encode_value (val, buf->p, &buf->p);
225 }
226
227 static void
228 sigbuffer_add_byte (SigBuffer *buf, guint8 val)
229 {
230         sigbuffer_make_room (buf, 1);
231         buf->p [0] = val;
232         buf->p++;
233 }
234
235 static void
236 sigbuffer_add_mem (SigBuffer *buf, char *p, guint32 size)
237 {
238         sigbuffer_make_room (buf, size);
239         memcpy (buf->p, p, size);
240         buf->p += size;
241 }
242
243 static void
244 sigbuffer_free (SigBuffer *buf)
245 {
246         g_free (buf->buf);
247 }
248
249 #ifndef DISABLE_REFLECTION_EMIT
250 /**
251  * mp_g_alloc:
252  *
253  * Allocate memory from the @image mempool if it is non-NULL. Otherwise, allocate memory
254  * from the C heap.
255  */
256 static gpointer
257 image_g_malloc (MonoImage *image, guint size)
258 {
259         if (image)
260                 return mono_image_alloc (image, size);
261         else
262                 return g_malloc (size);
263 }
264 #endif /* !DISABLE_REFLECTION_EMIT */
265
266 /**
267  * image_g_alloc0:
268  *
269  * Allocate memory from the @image mempool if it is non-NULL. Otherwise, allocate memory
270  * from the C heap.
271  */
272 static gpointer
273 image_g_malloc0 (MonoImage *image, guint size)
274 {
275         if (image)
276                 return mono_image_alloc0 (image, size);
277         else
278                 return g_malloc0 (size);
279 }
280
281 #ifndef DISABLE_REFLECTION_EMIT
282 static char*
283 image_strdup (MonoImage *image, const char *s)
284 {
285         if (image)
286                 return mono_image_strdup (image, s);
287         else
288                 return g_strdup (s);
289 }
290 #endif
291
292 #define image_g_new(image,struct_type, n_structs)               \
293     ((struct_type *) image_g_malloc (image, ((gsize) sizeof (struct_type)) * ((gsize) (n_structs))))
294
295 #define image_g_new0(image,struct_type, n_structs)              \
296     ((struct_type *) image_g_malloc0 (image, ((gsize) sizeof (struct_type)) * ((gsize) (n_structs))))
297
298
299 static void
300 alloc_table (MonoDynamicTable *table, guint nrows)
301 {
302         table->rows = nrows;
303         g_assert (table->columns);
304         if (nrows + 1 >= table->alloc_rows) {
305                 while (nrows + 1 >= table->alloc_rows) {
306                         if (table->alloc_rows == 0)
307                                 table->alloc_rows = 16;
308                         else
309                                 table->alloc_rows *= 2;
310                 }
311
312                 table->values = g_renew (guint32, table->values, (table->alloc_rows) * table->columns);
313         }
314 }
315
316 static void
317 make_room_in_stream (MonoDynamicStream *stream, int size)
318 {
319         if (size <= stream->alloc_size)
320                 return;
321         
322         while (stream->alloc_size <= size) {
323                 if (stream->alloc_size < 4096)
324                         stream->alloc_size = 4096;
325                 else
326                         stream->alloc_size *= 2;
327         }
328         
329         stream->data = g_realloc (stream->data, stream->alloc_size);
330 }
331
332 static guint32
333 string_heap_insert (MonoDynamicStream *sh, const char *str)
334 {
335         guint32 idx;
336         guint32 len;
337         gpointer oldkey, oldval;
338
339         if (g_hash_table_lookup_extended (sh->hash, str, &oldkey, &oldval))
340                 return GPOINTER_TO_UINT (oldval);
341
342         len = strlen (str) + 1;
343         idx = sh->index;
344         
345         make_room_in_stream (sh, idx + len);
346
347         /*
348          * We strdup the string even if we already copy them in sh->data
349          * so that the string pointers in the hash remain valid even if
350          * we need to realloc sh->data. We may want to avoid that later.
351          */
352         g_hash_table_insert (sh->hash, g_strdup (str), GUINT_TO_POINTER (idx));
353         memcpy (sh->data + idx, str, len);
354         sh->index += len;
355         return idx;
356 }
357
358 static guint32
359 string_heap_insert_mstring (MonoDynamicStream *sh, MonoString *str)
360 {
361         char *name = mono_string_to_utf8 (str);
362         guint32 idx;
363         idx = string_heap_insert (sh, name);
364         g_free (name);
365         return idx;
366 }
367
368 #ifndef DISABLE_REFLECTION_EMIT
369 static void
370 string_heap_init (MonoDynamicStream *sh)
371 {
372         sh->index = 0;
373         sh->alloc_size = 4096;
374         sh->data = g_malloc (4096);
375         sh->hash = g_hash_table_new_full (g_str_hash, g_str_equal, g_free, NULL);
376         string_heap_insert (sh, "");
377 }
378 #endif
379
380 static guint32
381 mono_image_add_stream_data (MonoDynamicStream *stream, const char *data, guint32 len)
382 {
383         guint32 idx;
384         
385         make_room_in_stream (stream, stream->index + len);
386         memcpy (stream->data + stream->index, data, len);
387         idx = stream->index;
388         stream->index += len;
389         /* 
390          * align index? Not without adding an additional param that controls it since
391          * we may store a blob value in pieces.
392          */
393         return idx;
394 }
395
396 static guint32
397 mono_image_add_stream_zero (MonoDynamicStream *stream, guint32 len)
398 {
399         guint32 idx;
400         
401         make_room_in_stream (stream, stream->index + len);
402         memset (stream->data + stream->index, 0, len);
403         idx = stream->index;
404         stream->index += len;
405         return idx;
406 }
407
408 static void
409 stream_data_align (MonoDynamicStream *stream)
410 {
411         char buf [4] = {0};
412         guint32 count = stream->index % 4;
413
414         /* we assume the stream data will be aligned */
415         if (count)
416                 mono_image_add_stream_data (stream, buf, 4 - count);
417 }
418
419 #ifndef DISABLE_REFLECTION_EMIT
420 static int
421 mono_blob_entry_hash (const char* str)
422 {
423         guint len, h;
424         const char *end;
425         len = mono_metadata_decode_blob_size (str, &str);
426         if (len > 0) {
427                 end = str + len;
428                 h = *str;
429                 for (str += 1; str < end; str++)
430                         h = (h << 5) - h + *str;
431                 return h;
432         } else {
433                 return 0;
434         }
435 }
436
437 static gboolean
438 mono_blob_entry_equal (const char *str1, const char *str2) {
439         int len, len2;
440         const char *end1;
441         const char *end2;
442         len = mono_metadata_decode_blob_size (str1, &end1);
443         len2 = mono_metadata_decode_blob_size (str2, &end2);
444         if (len != len2)
445                 return 0;
446         return memcmp (end1, end2, len) == 0;
447 }
448 #endif
449 static guint32
450 add_to_blob_cached (MonoDynamicImage *assembly, char *b1, int s1, char *b2, int s2)
451 {
452         guint32 idx;
453         char *copy;
454         gpointer oldkey, oldval;
455
456         copy = g_malloc (s1+s2);
457         memcpy (copy, b1, s1);
458         memcpy (copy + s1, b2, s2);
459         if (g_hash_table_lookup_extended (assembly->blob_cache, copy, &oldkey, &oldval)) {
460                 g_free (copy);
461                 idx = GPOINTER_TO_UINT (oldval);
462         } else {
463                 idx = mono_image_add_stream_data (&assembly->blob, b1, s1);
464                 mono_image_add_stream_data (&assembly->blob, b2, s2);
465                 g_hash_table_insert (assembly->blob_cache, copy, GUINT_TO_POINTER (idx));
466         }
467         return idx;
468 }
469
470 static guint32
471 sigbuffer_add_to_blob_cached (MonoDynamicImage *assembly, SigBuffer *buf)
472 {
473         char blob_size [8];
474         char *b = blob_size;
475         guint32 size = buf->p - buf->buf;
476         /* store length */
477         g_assert (size <= (buf->end - buf->buf));
478         mono_metadata_encode_value (size, b, &b);
479         return add_to_blob_cached (assembly, blob_size, b-blob_size, buf->buf, size);
480 }
481
482 /*
483  * Copy len * nelem bytes from val to dest, swapping bytes to LE if necessary.
484  * dest may be misaligned.
485  */
486 static void
487 swap_with_size (char *dest, const char* val, int len, int nelem) {
488 #if G_BYTE_ORDER != G_LITTLE_ENDIAN
489         int elem;
490
491         for (elem = 0; elem < nelem; ++elem) {
492                 switch (len) {
493                 case 1:
494                         *dest = *val;
495                         break;
496                 case 2:
497                         dest [0] = val [1];
498                         dest [1] = val [0];
499                         break;
500                 case 4:
501                         dest [0] = val [3];
502                         dest [1] = val [2];
503                         dest [2] = val [1];
504                         dest [3] = val [0];
505                         break;
506                 case 8:
507                         dest [0] = val [7];
508                         dest [1] = val [6];
509                         dest [2] = val [5];
510                         dest [3] = val [4];
511                         dest [4] = val [3];
512                         dest [5] = val [2];
513                         dest [6] = val [1];
514                         dest [7] = val [0];
515                         break;
516                 default:
517                         g_assert_not_reached ();
518                 }
519                 dest += len;
520                 val += len;
521         }
522 #else
523         memcpy (dest, val, len * nelem);
524 #endif
525 }
526
527 static guint32
528 add_mono_string_to_blob_cached (MonoDynamicImage *assembly, MonoString *str)
529 {
530         char blob_size [64];
531         char *b = blob_size;
532         guint32 idx = 0, len;
533
534         len = str->length * 2;
535         mono_metadata_encode_value (len, b, &b);
536 #if G_BYTE_ORDER != G_LITTLE_ENDIAN
537         {
538                 char *swapped = g_malloc (2 * mono_string_length (str));
539                 const char *p = (const char*)mono_string_chars (str);
540
541                 swap_with_size (swapped, p, 2, mono_string_length (str));
542                 idx = add_to_blob_cached (assembly, blob_size, b-blob_size, swapped, len);
543                 g_free (swapped);
544         }
545 #else
546         idx = add_to_blob_cached (assembly, blob_size, b-blob_size, (char*)mono_string_chars (str), len);
547 #endif
548         return idx;
549 }
550
551 #ifndef DISABLE_REFLECTION_EMIT
552 static MonoClass *
553 default_class_from_mono_type (MonoType *type)
554 {
555         switch (type->type) {
556         case MONO_TYPE_OBJECT:
557                 return mono_defaults.object_class;
558         case MONO_TYPE_VOID:
559                 return mono_defaults.void_class;
560         case MONO_TYPE_BOOLEAN:
561                 return mono_defaults.boolean_class;
562         case MONO_TYPE_CHAR:
563                 return mono_defaults.char_class;
564         case MONO_TYPE_I1:
565                 return mono_defaults.sbyte_class;
566         case MONO_TYPE_U1:
567                 return mono_defaults.byte_class;
568         case MONO_TYPE_I2:
569                 return mono_defaults.int16_class;
570         case MONO_TYPE_U2:
571                 return mono_defaults.uint16_class;
572         case MONO_TYPE_I4:
573                 return mono_defaults.int32_class;
574         case MONO_TYPE_U4:
575                 return mono_defaults.uint32_class;
576         case MONO_TYPE_I:
577                 return mono_defaults.int_class;
578         case MONO_TYPE_U:
579                 return mono_defaults.uint_class;
580         case MONO_TYPE_I8:
581                 return mono_defaults.int64_class;
582         case MONO_TYPE_U8:
583                 return mono_defaults.uint64_class;
584         case MONO_TYPE_R4:
585                 return mono_defaults.single_class;
586         case MONO_TYPE_R8:
587                 return mono_defaults.double_class;
588         case MONO_TYPE_STRING:
589                 return mono_defaults.string_class;
590         default:
591                 g_warning ("default_class_from_mono_type: implement me 0x%02x\n", type->type);
592                 g_assert_not_reached ();
593         }
594         
595         return NULL;
596 }
597 #endif
598
599 static void
600 encode_generic_class (MonoDynamicImage *assembly, MonoGenericClass *gclass, SigBuffer *buf)
601 {
602         int i;
603         MonoGenericInst *class_inst;
604         MonoClass *klass;
605
606         g_assert (gclass);
607
608         class_inst = gclass->context.class_inst;
609
610         sigbuffer_add_value (buf, MONO_TYPE_GENERICINST);
611         klass = gclass->container_class;
612         sigbuffer_add_value (buf, klass->byval_arg.type);
613         sigbuffer_add_value (buf, mono_image_typedef_or_ref_full (assembly, &klass->byval_arg, FALSE));
614
615         sigbuffer_add_value (buf, class_inst->type_argc);
616         for (i = 0; i < class_inst->type_argc; ++i)
617                 encode_type (assembly, class_inst->type_argv [i], buf);
618
619 }
620
621 static void
622 encode_type (MonoDynamicImage *assembly, MonoType *type, SigBuffer *buf)
623 {
624         if (!type) {
625                 g_assert_not_reached ();
626                 return;
627         }
628                 
629         if (type->byref)
630                 sigbuffer_add_value (buf, MONO_TYPE_BYREF);
631
632         switch (type->type){
633         case MONO_TYPE_VOID:
634         case MONO_TYPE_BOOLEAN:
635         case MONO_TYPE_CHAR:
636         case MONO_TYPE_I1:
637         case MONO_TYPE_U1:
638         case MONO_TYPE_I2:
639         case MONO_TYPE_U2:
640         case MONO_TYPE_I4:
641         case MONO_TYPE_U4:
642         case MONO_TYPE_I8:
643         case MONO_TYPE_U8:
644         case MONO_TYPE_R4:
645         case MONO_TYPE_R8:
646         case MONO_TYPE_I:
647         case MONO_TYPE_U:
648         case MONO_TYPE_STRING:
649         case MONO_TYPE_OBJECT:
650         case MONO_TYPE_TYPEDBYREF:
651                 sigbuffer_add_value (buf, type->type);
652                 break;
653         case MONO_TYPE_PTR:
654                 sigbuffer_add_value (buf, type->type);
655                 encode_type (assembly, type->data.type, buf);
656                 break;
657         case MONO_TYPE_SZARRAY:
658                 sigbuffer_add_value (buf, type->type);
659                 encode_type (assembly, &type->data.klass->byval_arg, buf);
660                 break;
661         case MONO_TYPE_VALUETYPE:
662         case MONO_TYPE_CLASS: {
663                 MonoClass *k = mono_class_from_mono_type (type);
664
665                 if (k->generic_container) {
666                         MonoGenericClass *gclass = mono_metadata_lookup_generic_class (k, k->generic_container->context.class_inst, TRUE);
667                         encode_generic_class (assembly, gclass, buf);
668                 } else {
669                         /*
670                          * Make sure we use the correct type.
671                          */
672                         sigbuffer_add_value (buf, k->byval_arg.type);
673                         /*
674                          * ensure only non-byref gets passed to mono_image_typedef_or_ref(),
675                          * otherwise two typerefs could point to the same type, leading to
676                          * verification errors.
677                          */
678                         sigbuffer_add_value (buf, mono_image_typedef_or_ref (assembly, &k->byval_arg));
679                 }
680                 break;
681         }
682         case MONO_TYPE_ARRAY:
683                 sigbuffer_add_value (buf, type->type);
684                 encode_type (assembly, &type->data.array->eklass->byval_arg, buf);
685                 sigbuffer_add_value (buf, type->data.array->rank);
686                 sigbuffer_add_value (buf, 0); /* FIXME: set to 0 for now */
687                 sigbuffer_add_value (buf, 0);
688                 break;
689         case MONO_TYPE_GENERICINST:
690                 encode_generic_class (assembly, type->data.generic_class, buf);
691                 break;
692         case MONO_TYPE_VAR:
693         case MONO_TYPE_MVAR:
694                 sigbuffer_add_value (buf, type->type);
695                 sigbuffer_add_value (buf, mono_type_get_generic_param_num (type));
696                 break;
697         default:
698                 g_error ("need to encode type %x", type->type);
699         }
700 }
701
702 static void
703 encode_reflection_type (MonoDynamicImage *assembly, MonoReflectionType *type, SigBuffer *buf)
704 {
705         if (!type) {
706                 sigbuffer_add_value (buf, MONO_TYPE_VOID);
707                 return;
708         }
709
710         encode_type (assembly, mono_reflection_type_get_handle (type), buf);
711 }
712
713 static void
714 encode_custom_modifiers (MonoDynamicImage *assembly, MonoArray *modreq, MonoArray *modopt, SigBuffer *buf)
715 {
716         int i;
717
718         if (modreq) {
719                 for (i = 0; i < mono_array_length (modreq); ++i) {
720                         MonoType *mod = mono_type_array_get_and_resolve (modreq, i);
721                         sigbuffer_add_byte (buf, MONO_TYPE_CMOD_REQD);
722                         sigbuffer_add_value (buf, mono_image_typedef_or_ref (assembly, mod));
723                 }
724         }
725         if (modopt) {
726                 for (i = 0; i < mono_array_length (modopt); ++i) {
727                         MonoType *mod = mono_type_array_get_and_resolve (modopt, i);
728                         sigbuffer_add_byte (buf, MONO_TYPE_CMOD_OPT);
729                         sigbuffer_add_value (buf, mono_image_typedef_or_ref (assembly, mod));
730                 }
731         }
732 }
733
734 #ifndef DISABLE_REFLECTION_EMIT
735 static guint32
736 method_encode_signature (MonoDynamicImage *assembly, MonoMethodSignature *sig)
737 {
738         SigBuffer buf;
739         int i;
740         guint32 nparams =  sig->param_count;
741         guint32 idx;
742
743         if (!assembly->save)
744                 return 0;
745
746         sigbuffer_init (&buf, 32);
747         /*
748          * FIXME: vararg, explicit_this, differenc call_conv values...
749          */
750         idx = sig->call_convention;
751         if (sig->hasthis)
752                 idx |= 0x20; /* hasthis */
753         if (sig->generic_param_count)
754                 idx |= 0x10; /* generic */
755         sigbuffer_add_byte (&buf, idx);
756         if (sig->generic_param_count)
757                 sigbuffer_add_value (&buf, sig->generic_param_count);
758         sigbuffer_add_value (&buf, nparams);
759         encode_type (assembly, sig->ret, &buf);
760         for (i = 0; i < nparams; ++i) {
761                 if (i == sig->sentinelpos)
762                         sigbuffer_add_byte (&buf, MONO_TYPE_SENTINEL);
763                 encode_type (assembly, sig->params [i], &buf);
764         }
765         idx = sigbuffer_add_to_blob_cached (assembly, &buf);
766         sigbuffer_free (&buf);
767         return idx;
768 }
769 #endif
770
771 static guint32
772 method_builder_encode_signature (MonoDynamicImage *assembly, ReflectionMethodBuilder *mb)
773 {
774         /*
775          * FIXME: reuse code from method_encode_signature().
776          */
777         SigBuffer buf;
778         int i;
779         guint32 nparams =  mb->parameters ? mono_array_length (mb->parameters): 0;
780         guint32 ngparams = mb->generic_params ? mono_array_length (mb->generic_params): 0;
781         guint32 notypes = mb->opt_types ? mono_array_length (mb->opt_types): 0;
782         guint32 idx;
783
784         sigbuffer_init (&buf, 32);
785         /* LAMESPEC: all the call conv spec is foobared */
786         idx = mb->call_conv & 0x60; /* has-this, explicit-this */
787         if (mb->call_conv & 2)
788                 idx |= 0x5; /* vararg */
789         if (!(mb->attrs & METHOD_ATTRIBUTE_STATIC))
790                 idx |= 0x20; /* hasthis */
791         if (ngparams)
792                 idx |= 0x10; /* generic */
793         sigbuffer_add_byte (&buf, idx);
794         if (ngparams)
795                 sigbuffer_add_value (&buf, ngparams);
796         sigbuffer_add_value (&buf, nparams + notypes);
797         encode_custom_modifiers (assembly, mb->return_modreq, mb->return_modopt, &buf);
798         encode_reflection_type (assembly, mb->rtype, &buf);
799         for (i = 0; i < nparams; ++i) {
800                 MonoArray *modreq = NULL;
801                 MonoArray *modopt = NULL;
802                 MonoReflectionType *pt;
803
804                 if (mb->param_modreq && (i < mono_array_length (mb->param_modreq)))
805                         modreq = mono_array_get (mb->param_modreq, MonoArray*, i);
806                 if (mb->param_modopt && (i < mono_array_length (mb->param_modopt)))
807                         modopt = mono_array_get (mb->param_modopt, MonoArray*, i);
808                 encode_custom_modifiers (assembly, modreq, modopt, &buf);
809                 pt = mono_array_get (mb->parameters, MonoReflectionType*, i);
810                 encode_reflection_type (assembly, pt, &buf);
811         }
812         if (notypes)
813                 sigbuffer_add_byte (&buf, MONO_TYPE_SENTINEL);
814         for (i = 0; i < notypes; ++i) {
815                 MonoReflectionType *pt;
816
817                 pt = mono_array_get (mb->opt_types, MonoReflectionType*, i);
818                 encode_reflection_type (assembly, pt, &buf);
819         }
820
821         idx = sigbuffer_add_to_blob_cached (assembly, &buf);
822         sigbuffer_free (&buf);
823         return idx;
824 }
825
826 static guint32
827 encode_locals (MonoDynamicImage *assembly, MonoReflectionILGen *ilgen)
828 {
829         MonoDynamicTable *table;
830         guint32 *values;
831         guint32 idx, sig_idx;
832         guint nl = mono_array_length (ilgen->locals);
833         SigBuffer buf;
834         int i;
835
836         sigbuffer_init (&buf, 32);
837         sigbuffer_add_value (&buf, 0x07);
838         sigbuffer_add_value (&buf, nl);
839         for (i = 0; i < nl; ++i) {
840                 MonoReflectionLocalBuilder *lb = mono_array_get (ilgen->locals, MonoReflectionLocalBuilder*, i);
841                 
842                 if (lb->is_pinned)
843                         sigbuffer_add_value (&buf, MONO_TYPE_PINNED);
844                 
845                 encode_reflection_type (assembly, (MonoReflectionType*)lb->type, &buf);
846         }
847         sig_idx = sigbuffer_add_to_blob_cached (assembly, &buf);
848         sigbuffer_free (&buf);
849
850         if (assembly->standalonesig_cache == NULL)
851                 assembly->standalonesig_cache = g_hash_table_new (NULL, NULL);
852         idx = GPOINTER_TO_UINT (g_hash_table_lookup (assembly->standalonesig_cache, GUINT_TO_POINTER (sig_idx)));
853         if (idx)
854                 return idx;
855
856         table = &assembly->tables [MONO_TABLE_STANDALONESIG];
857         idx = table->next_idx ++;
858         table->rows ++;
859         alloc_table (table, table->rows);
860         values = table->values + idx * MONO_STAND_ALONE_SIGNATURE_SIZE;
861
862         values [MONO_STAND_ALONE_SIGNATURE] = sig_idx;
863
864         g_hash_table_insert (assembly->standalonesig_cache, GUINT_TO_POINTER (sig_idx), GUINT_TO_POINTER (idx));
865
866         return idx;
867 }
868
869 static guint32
870 method_count_clauses (MonoReflectionILGen *ilgen)
871 {
872         guint32 num_clauses = 0;
873         int i;
874
875         MonoILExceptionInfo *ex_info;
876         for (i = 0; i < mono_array_length (ilgen->ex_handlers); ++i) {
877                 ex_info = (MonoILExceptionInfo*)mono_array_addr (ilgen->ex_handlers, MonoILExceptionInfo, i);
878                 if (ex_info->handlers)
879                         num_clauses += mono_array_length (ex_info->handlers);
880                 else
881                         num_clauses++;
882         }
883
884         return num_clauses;
885 }
886
887 #ifndef DISABLE_REFLECTION_EMIT
888 static MonoExceptionClause*
889 method_encode_clauses (MonoImage *image, MonoDynamicImage *assembly, MonoReflectionILGen *ilgen, guint32 num_clauses)
890 {
891         MonoExceptionClause *clauses;
892         MonoExceptionClause *clause;
893         MonoILExceptionInfo *ex_info;
894         MonoILExceptionBlock *ex_block;
895         guint32 finally_start;
896         int i, j, clause_index;;
897
898         clauses = image_g_new0 (image, MonoExceptionClause, num_clauses);
899
900         clause_index = 0;
901         for (i = mono_array_length (ilgen->ex_handlers) - 1; i >= 0; --i) {
902                 ex_info = (MonoILExceptionInfo*)mono_array_addr (ilgen->ex_handlers, MonoILExceptionInfo, i);
903                 finally_start = ex_info->start + ex_info->len;
904                 if (!ex_info->handlers)
905                         continue;
906                 for (j = 0; j < mono_array_length (ex_info->handlers); ++j) {
907                         ex_block = (MonoILExceptionBlock*)mono_array_addr (ex_info->handlers, MonoILExceptionBlock, j);
908                         clause = &(clauses [clause_index]);
909
910                         clause->flags = ex_block->type;
911                         clause->try_offset = ex_info->start;
912
913                         if (ex_block->type == MONO_EXCEPTION_CLAUSE_FINALLY)
914                                 clause->try_len = finally_start - ex_info->start;
915                         else
916                                 clause->try_len = ex_info->len;
917                         clause->handler_offset = ex_block->start;
918                         clause->handler_len = ex_block->len;
919                         if (ex_block->extype) {
920                                 clause->data.catch_class = mono_class_from_mono_type (mono_reflection_type_get_handle ((MonoReflectionType*)ex_block->extype));
921                         } else {
922                                 if (ex_block->type == MONO_EXCEPTION_CLAUSE_FILTER)
923                                         clause->data.filter_offset = ex_block->filter_offset;
924                                 else
925                                         clause->data.filter_offset = 0;
926                         }
927                         finally_start = ex_block->start + ex_block->len;
928
929                         clause_index ++;
930                 }
931         }
932
933         return clauses;
934 }
935 #endif /* !DISABLE_REFLECTION_EMIT */
936
937 static guint32
938 method_encode_code (MonoDynamicImage *assembly, ReflectionMethodBuilder *mb)
939 {
940         char flags = 0;
941         guint32 idx;
942         guint32 code_size;
943         gint32 max_stack, i;
944         gint32 num_locals = 0;
945         gint32 num_exception = 0;
946         gint maybe_small;
947         guint32 fat_flags;
948         char fat_header [12];
949         guint32 int_value;
950         guint16 short_value;
951         guint32 local_sig = 0;
952         guint32 header_size = 12;
953         MonoArray *code;
954
955         if ((mb->attrs & (METHOD_ATTRIBUTE_PINVOKE_IMPL | METHOD_ATTRIBUTE_ABSTRACT)) ||
956                         (mb->iattrs & (METHOD_IMPL_ATTRIBUTE_INTERNAL_CALL | METHOD_IMPL_ATTRIBUTE_RUNTIME)))
957                 return 0;
958
959         /*if (mb->name)
960                 g_print ("Encode method %s\n", mono_string_to_utf8 (mb->name));*/
961         if (mb->ilgen) {
962                 code = mb->ilgen->code;
963                 code_size = mb->ilgen->code_len;
964                 max_stack = mb->ilgen->max_stack;
965                 num_locals = mb->ilgen->locals ? mono_array_length (mb->ilgen->locals) : 0;
966                 if (mb->ilgen->ex_handlers)
967                         num_exception = method_count_clauses (mb->ilgen);
968         } else {
969                 code = mb->code;
970                 if (code == NULL){
971                         char *name = mono_string_to_utf8 (mb->name);
972                         char *str = g_strdup_printf ("Method %s does not have any IL associated", name);
973                         MonoException *exception = mono_get_exception_argument (NULL, "a method does not have any IL associated");
974                         g_free (str);
975                         g_free (name);
976                         mono_raise_exception (exception);
977                 }
978
979                 code_size = mono_array_length (code);
980                 max_stack = 8; /* we probably need to run a verifier on the code... */
981         }
982
983         stream_data_align (&assembly->code);
984
985         /* check for exceptions, maxstack, locals */
986         maybe_small = (max_stack <= 8) && (!num_locals) && (!num_exception);
987         if (maybe_small) {
988                 if (code_size < 64 && !(code_size & 1)) {
989                         flags = (code_size << 2) | 0x2;
990                 } else if (code_size < 32 && (code_size & 1)) {
991                         flags = (code_size << 2) | 0x6; /* LAMESPEC: see metadata.c */
992                 } else {
993                         goto fat_header;
994                 }
995                 idx = mono_image_add_stream_data (&assembly->code, &flags, 1);
996                 /* add to the fixup todo list */
997                 if (mb->ilgen && mb->ilgen->num_token_fixups)
998                         mono_g_hash_table_insert (assembly->token_fixups, mb->ilgen, GUINT_TO_POINTER (idx + 1));
999                 mono_image_add_stream_data (&assembly->code, mono_array_addr (code, char, 0), code_size);
1000                 return assembly->text_rva + idx;
1001         } 
1002 fat_header:
1003         if (num_locals)
1004                 local_sig = MONO_TOKEN_SIGNATURE | encode_locals (assembly, mb->ilgen);
1005         /* 
1006          * FIXME: need to set also the header size in fat_flags.
1007          * (and more sects and init locals flags)
1008          */
1009         fat_flags =  0x03;
1010         if (num_exception)
1011                 fat_flags |= METHOD_HEADER_MORE_SECTS;
1012         if (mb->init_locals)
1013                 fat_flags |= METHOD_HEADER_INIT_LOCALS;
1014         fat_header [0] = fat_flags;
1015         fat_header [1] = (header_size / 4 ) << 4;
1016         short_value = GUINT16_TO_LE (max_stack);
1017         memcpy (fat_header + 2, &short_value, 2);
1018         int_value = GUINT32_TO_LE (code_size);
1019         memcpy (fat_header + 4, &int_value, 4);
1020         int_value = GUINT32_TO_LE (local_sig);
1021         memcpy (fat_header + 8, &int_value, 4);
1022         idx = mono_image_add_stream_data (&assembly->code, fat_header, 12);
1023         /* add to the fixup todo list */
1024         if (mb->ilgen && mb->ilgen->num_token_fixups)
1025                 mono_g_hash_table_insert (assembly->token_fixups, mb->ilgen, GUINT_TO_POINTER (idx + 12));
1026         
1027         mono_image_add_stream_data (&assembly->code, mono_array_addr (code, char, 0), code_size);
1028         if (num_exception) {
1029                 unsigned char sheader [4];
1030                 MonoILExceptionInfo * ex_info;
1031                 MonoILExceptionBlock * ex_block;
1032                 int j;
1033
1034                 stream_data_align (&assembly->code);
1035                 /* always use fat format for now */
1036                 sheader [0] = METHOD_HEADER_SECTION_FAT_FORMAT | METHOD_HEADER_SECTION_EHTABLE;
1037                 num_exception *= 6 * sizeof (guint32);
1038                 num_exception += 4; /* include the size of the header */
1039                 sheader [1] = num_exception & 0xff;
1040                 sheader [2] = (num_exception >> 8) & 0xff;
1041                 sheader [3] = (num_exception >> 16) & 0xff;
1042                 mono_image_add_stream_data (&assembly->code, (char*)sheader, 4);
1043                 /* fat header, so we are already aligned */
1044                 /* reverse order */
1045                 for (i = mono_array_length (mb->ilgen->ex_handlers) - 1; i >= 0; --i) {
1046                         ex_info = (MonoILExceptionInfo *)mono_array_addr (mb->ilgen->ex_handlers, MonoILExceptionInfo, i);
1047                         if (ex_info->handlers) {
1048                                 int finally_start = ex_info->start + ex_info->len;
1049                                 for (j = 0; j < mono_array_length (ex_info->handlers); ++j) {
1050                                         guint32 val;
1051                                         ex_block = (MonoILExceptionBlock*)mono_array_addr (ex_info->handlers, MonoILExceptionBlock, j);
1052                                         /* the flags */
1053                                         val = GUINT32_TO_LE (ex_block->type);
1054                                         mono_image_add_stream_data (&assembly->code, (char*)&val, sizeof (guint32));
1055                                         /* try offset */
1056                                         val = GUINT32_TO_LE (ex_info->start);
1057                                         mono_image_add_stream_data (&assembly->code, (char*)&val, sizeof (guint32));
1058                                         /* need fault, too, probably */
1059                                         if (ex_block->type == MONO_EXCEPTION_CLAUSE_FINALLY)
1060                                                 val = GUINT32_TO_LE (finally_start - ex_info->start);
1061                                         else
1062                                                 val = GUINT32_TO_LE (ex_info->len);
1063                                         mono_image_add_stream_data (&assembly->code, (char*)&val, sizeof (guint32));
1064                                         /* handler offset */
1065                                         val = GUINT32_TO_LE (ex_block->start);
1066                                         mono_image_add_stream_data (&assembly->code, (char*)&val, sizeof (guint32));
1067                                         /* handler len */
1068                                         val = GUINT32_TO_LE (ex_block->len);
1069                                         mono_image_add_stream_data (&assembly->code, (char*)&val, sizeof (guint32));
1070                                         finally_start = ex_block->start + ex_block->len;
1071                                         if (ex_block->extype) {
1072                                                 val = mono_metadata_token_from_dor (mono_image_typedef_or_ref (assembly, mono_reflection_type_get_handle ((MonoReflectionType*)ex_block->extype)));
1073                                         } else {
1074                                                 if (ex_block->type == MONO_EXCEPTION_CLAUSE_FILTER)
1075                                                         val = ex_block->filter_offset;
1076                                                 else
1077                                                         val = 0;
1078                                         }
1079                                         val = GUINT32_TO_LE (val);
1080                                         mono_image_add_stream_data (&assembly->code, (char*)&val, sizeof (guint32));
1081                                         /*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", 
1082                                                         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);*/
1083                                 }
1084                         } else {
1085                                 g_error ("No clauses for ex info block %d", i);
1086                         }
1087                 }
1088         }
1089         return assembly->text_rva + idx;
1090 }
1091
1092 static guint32
1093 find_index_in_table (MonoDynamicImage *assembly, int table_idx, int col, guint32 token)
1094 {
1095         int i;
1096         MonoDynamicTable *table;
1097         guint32 *values;
1098         
1099         table = &assembly->tables [table_idx];
1100
1101         g_assert (col < table->columns);
1102
1103         values = table->values + table->columns;
1104         for (i = 1; i <= table->rows; ++i) {
1105                 if (values [col] == token)
1106                         return i;
1107                 values += table->columns;
1108         }
1109         return 0;
1110 }
1111
1112 /*
1113  * LOCKING: Acquires the loader lock. 
1114  */
1115 static MonoCustomAttrInfo*
1116 lookup_custom_attr (MonoImage *image, gpointer member)
1117 {
1118         MonoCustomAttrInfo* res;
1119
1120         res = mono_image_property_lookup (image, member, MONO_PROP_DYNAMIC_CATTR);
1121
1122         if (!res)
1123                 return NULL;
1124
1125         return g_memdup (res, MONO_SIZEOF_CUSTOM_ATTR_INFO + sizeof (MonoCustomAttrEntry) * res->num_attrs);
1126 }
1127
1128 static gboolean
1129 custom_attr_visible (MonoImage *image, MonoReflectionCustomAttr *cattr)
1130 {
1131         /* FIXME: Need to do more checks */
1132         if (cattr->ctor->method && (cattr->ctor->method->klass->image != image)) {
1133                 int visibility = cattr->ctor->method->klass->flags & TYPE_ATTRIBUTE_VISIBILITY_MASK;
1134
1135                 if ((visibility != TYPE_ATTRIBUTE_PUBLIC) && (visibility != TYPE_ATTRIBUTE_NESTED_PUBLIC))
1136                         return FALSE;
1137         }
1138
1139         return TRUE;
1140 }
1141
1142 static MonoCustomAttrInfo*
1143 mono_custom_attrs_from_builders (MonoImage *alloc_img, MonoImage *image, MonoArray *cattrs)
1144 {
1145         int i, index, count, not_visible;
1146         MonoCustomAttrInfo *ainfo;
1147         MonoReflectionCustomAttr *cattr;
1148
1149         if (!cattrs)
1150                 return NULL;
1151         /* FIXME: check in assembly the Run flag is set */
1152
1153         count = mono_array_length (cattrs);
1154
1155         /* Skip nonpublic attributes since MS.NET seems to do the same */
1156         /* FIXME: This needs to be done more globally */
1157         not_visible = 0;
1158         for (i = 0; i < count; ++i) {
1159                 cattr = (MonoReflectionCustomAttr*)mono_array_get (cattrs, gpointer, i);
1160                 if (!custom_attr_visible (image, cattr))
1161                         not_visible ++;
1162         }
1163         count -= not_visible;
1164
1165         ainfo = image_g_malloc0 (alloc_img, MONO_SIZEOF_CUSTOM_ATTR_INFO + sizeof (MonoCustomAttrEntry) * count);
1166
1167         ainfo->image = image;
1168         ainfo->num_attrs = count;
1169         ainfo->cached = alloc_img != NULL;
1170         index = 0;
1171         for (i = 0; i < count; ++i) {
1172                 cattr = (MonoReflectionCustomAttr*)mono_array_get (cattrs, gpointer, i);
1173                 if (custom_attr_visible (image, cattr)) {
1174                         unsigned char *saved = mono_image_alloc (image, mono_array_length (cattr->data));
1175                         memcpy (saved, mono_array_addr (cattr->data, char, 0), mono_array_length (cattr->data));
1176                         ainfo->attrs [index].ctor = cattr->ctor->method;
1177                         ainfo->attrs [index].data = saved;
1178                         ainfo->attrs [index].data_size = mono_array_length (cattr->data);
1179                         index ++;
1180                 }
1181         }
1182
1183         return ainfo;
1184 }
1185
1186 #ifndef DISABLE_REFLECTION_EMIT
1187 /*
1188  * LOCKING: Acquires the loader lock. 
1189  */
1190 static void
1191 mono_save_custom_attrs (MonoImage *image, void *obj, MonoArray *cattrs)
1192 {
1193         MonoCustomAttrInfo *ainfo, *tmp;
1194
1195         if (!cattrs || !mono_array_length (cattrs))
1196                 return;
1197
1198         ainfo = mono_custom_attrs_from_builders (image, image, cattrs);
1199
1200         mono_loader_lock ();
1201         tmp = mono_image_property_lookup (image, obj, MONO_PROP_DYNAMIC_CATTR);
1202         if (tmp)
1203                 mono_custom_attrs_free (tmp);
1204         mono_image_property_insert (image, obj, MONO_PROP_DYNAMIC_CATTR, ainfo);
1205         mono_loader_unlock ();
1206
1207 }
1208 #endif
1209
1210 void
1211 mono_custom_attrs_free (MonoCustomAttrInfo *ainfo)
1212 {
1213         if (!ainfo->cached)
1214                 g_free (ainfo);
1215 }
1216
1217 /*
1218  * idx is the table index of the object
1219  * type is one of MONO_CUSTOM_ATTR_*
1220  */
1221 static void
1222 mono_image_add_cattrs (MonoDynamicImage *assembly, guint32 idx, guint32 type, MonoArray *cattrs)
1223 {
1224         MonoDynamicTable *table;
1225         MonoReflectionCustomAttr *cattr;
1226         guint32 *values;
1227         guint32 count, i, token;
1228         char blob_size [6];
1229         char *p = blob_size;
1230         
1231         /* it is legal to pass a NULL cattrs: we avoid to use the if in a lot of places */
1232         if (!cattrs)
1233                 return;
1234         count = mono_array_length (cattrs);
1235         table = &assembly->tables [MONO_TABLE_CUSTOMATTRIBUTE];
1236         table->rows += count;
1237         alloc_table (table, table->rows);
1238         values = table->values + table->next_idx * MONO_CUSTOM_ATTR_SIZE;
1239         idx <<= MONO_CUSTOM_ATTR_BITS;
1240         idx |= type;
1241         for (i = 0; i < count; ++i) {
1242                 cattr = (MonoReflectionCustomAttr*)mono_array_get (cattrs, gpointer, i);
1243                 values [MONO_CUSTOM_ATTR_PARENT] = idx;
1244                 token = mono_image_create_token (assembly, (MonoObject*)cattr->ctor, FALSE, FALSE);
1245                 type = mono_metadata_token_index (token);
1246                 type <<= MONO_CUSTOM_ATTR_TYPE_BITS;
1247                 switch (mono_metadata_token_table (token)) {
1248                 case MONO_TABLE_METHOD:
1249                         type |= MONO_CUSTOM_ATTR_TYPE_METHODDEF;
1250                         break;
1251                 case MONO_TABLE_MEMBERREF:
1252                         type |= MONO_CUSTOM_ATTR_TYPE_MEMBERREF;
1253                         break;
1254                 default:
1255                         g_warning ("got wrong token in custom attr");
1256                         continue;
1257                 }
1258                 values [MONO_CUSTOM_ATTR_TYPE] = type;
1259                 p = blob_size;
1260                 mono_metadata_encode_value (mono_array_length (cattr->data), p, &p);
1261                 values [MONO_CUSTOM_ATTR_VALUE] = add_to_blob_cached (assembly, blob_size, p - blob_size,
1262                         mono_array_addr (cattr->data, char, 0), mono_array_length (cattr->data));
1263                 values += MONO_CUSTOM_ATTR_SIZE;
1264                 ++table->next_idx;
1265         }
1266 }
1267
1268 static void
1269 mono_image_add_decl_security (MonoDynamicImage *assembly, guint32 parent_token, MonoArray *permissions)
1270 {
1271         MonoDynamicTable *table;
1272         guint32 *values;
1273         guint32 count, i, idx;
1274         MonoReflectionPermissionSet *perm;
1275
1276         if (!permissions)
1277                 return;
1278
1279         count = mono_array_length (permissions);
1280         table = &assembly->tables [MONO_TABLE_DECLSECURITY];
1281         table->rows += count;
1282         alloc_table (table, table->rows);
1283
1284         for (i = 0; i < mono_array_length (permissions); ++i) {
1285                 perm = (MonoReflectionPermissionSet*)mono_array_addr (permissions, MonoReflectionPermissionSet, i);
1286
1287                 values = table->values + table->next_idx * MONO_DECL_SECURITY_SIZE;
1288
1289                 idx = mono_metadata_token_index (parent_token);
1290                 idx <<= MONO_HAS_DECL_SECURITY_BITS;
1291                 switch (mono_metadata_token_table (parent_token)) {
1292                 case MONO_TABLE_TYPEDEF:
1293                         idx |= MONO_HAS_DECL_SECURITY_TYPEDEF;
1294                         break;
1295                 case MONO_TABLE_METHOD:
1296                         idx |= MONO_HAS_DECL_SECURITY_METHODDEF;
1297                         break;
1298                 case MONO_TABLE_ASSEMBLY:
1299                         idx |= MONO_HAS_DECL_SECURITY_ASSEMBLY;
1300                         break;
1301                 default:
1302                         g_assert_not_reached ();
1303                 }
1304
1305                 values [MONO_DECL_SECURITY_ACTION] = perm->action;
1306                 values [MONO_DECL_SECURITY_PARENT] = idx;
1307                 values [MONO_DECL_SECURITY_PERMISSIONSET] = add_mono_string_to_blob_cached (assembly, perm->pset);
1308
1309                 ++table->next_idx;
1310         }
1311 }
1312
1313 /*
1314  * Fill in the MethodDef and ParamDef tables for a method.
1315  * This is used for both normal methods and constructors.
1316  */
1317 static void
1318 mono_image_basic_method (ReflectionMethodBuilder *mb, MonoDynamicImage *assembly)
1319 {
1320         MonoDynamicTable *table;
1321         guint32 *values;
1322         guint i, count;
1323
1324         /* room in this table is already allocated */
1325         table = &assembly->tables [MONO_TABLE_METHOD];
1326         *mb->table_idx = table->next_idx ++;
1327         g_hash_table_insert (assembly->method_to_table_idx, mb->mhandle, GUINT_TO_POINTER ((*mb->table_idx)));
1328         values = table->values + *mb->table_idx * MONO_METHOD_SIZE;
1329         values [MONO_METHOD_NAME] = string_heap_insert_mstring (&assembly->sheap, mb->name);
1330         values [MONO_METHOD_FLAGS] = mb->attrs;
1331         values [MONO_METHOD_IMPLFLAGS] = mb->iattrs;
1332         values [MONO_METHOD_SIGNATURE] = method_builder_encode_signature (assembly, mb);
1333         values [MONO_METHOD_RVA] = method_encode_code (assembly, mb);
1334         
1335         table = &assembly->tables [MONO_TABLE_PARAM];
1336         values [MONO_METHOD_PARAMLIST] = table->next_idx;
1337
1338         mono_image_add_decl_security (assembly, 
1339                 mono_metadata_make_token (MONO_TABLE_METHOD, *mb->table_idx), mb->permissions);
1340
1341         if (mb->pinfo) {
1342                 MonoDynamicTable *mtable;
1343                 guint32 *mvalues;
1344                 
1345                 mtable = &assembly->tables [MONO_TABLE_FIELDMARSHAL];
1346                 mvalues = mtable->values + mtable->next_idx * MONO_FIELD_MARSHAL_SIZE;
1347                 
1348                 count = 0;
1349                 for (i = 0; i < mono_array_length (mb->pinfo); ++i) {
1350                         if (mono_array_get (mb->pinfo, gpointer, i))
1351                                 count++;
1352                 }
1353                 table->rows += count;
1354                 alloc_table (table, table->rows);
1355                 values = table->values + table->next_idx * MONO_PARAM_SIZE;
1356                 for (i = 0; i < mono_array_length (mb->pinfo); ++i) {
1357                         MonoReflectionParamBuilder *pb;
1358                         if ((pb = mono_array_get (mb->pinfo, MonoReflectionParamBuilder*, i))) {
1359                                 values [MONO_PARAM_FLAGS] = pb->attrs;
1360                                 values [MONO_PARAM_SEQUENCE] = i;
1361                                 if (pb->name != NULL) {
1362                                         values [MONO_PARAM_NAME] = string_heap_insert_mstring (&assembly->sheap, pb->name);
1363                                 } else {
1364                                         values [MONO_PARAM_NAME] = 0;
1365                                 }
1366                                 values += MONO_PARAM_SIZE;
1367                                 if (pb->marshal_info) {
1368                                         mtable->rows++;
1369                                         alloc_table (mtable, mtable->rows);
1370                                         mvalues = mtable->values + mtable->rows * MONO_FIELD_MARSHAL_SIZE;
1371                                         mvalues [MONO_FIELD_MARSHAL_PARENT] = (table->next_idx << MONO_HAS_FIELD_MARSHAL_BITS) | MONO_HAS_FIELD_MARSHAL_PARAMDEF;
1372                                         mvalues [MONO_FIELD_MARSHAL_NATIVE_TYPE] = encode_marshal_blob (assembly, pb->marshal_info);
1373                                 }
1374                                 pb->table_idx = table->next_idx++;
1375                                 if (pb->attrs & PARAM_ATTRIBUTE_HAS_DEFAULT) {
1376                                         guint32 field_type = 0;
1377                                         mtable = &assembly->tables [MONO_TABLE_CONSTANT];
1378                                         mtable->rows ++;
1379                                         alloc_table (mtable, mtable->rows);
1380                                         mvalues = mtable->values + mtable->rows * MONO_CONSTANT_SIZE;
1381                                         mvalues [MONO_CONSTANT_PARENT] = MONO_HASCONSTANT_PARAM | (pb->table_idx << MONO_HASCONSTANT_BITS);
1382                                         mvalues [MONO_CONSTANT_VALUE] = encode_constant (assembly, pb->def_value, &field_type);
1383                                         mvalues [MONO_CONSTANT_TYPE] = field_type;
1384                                         mvalues [MONO_CONSTANT_PADDING] = 0;
1385                                 }
1386                         }
1387                 }
1388         }
1389 }
1390
1391 static void
1392 reflection_methodbuilder_from_method_builder (ReflectionMethodBuilder *rmb, MonoReflectionMethodBuilder *mb)
1393 {
1394         memset (rmb, 0, sizeof (ReflectionMethodBuilder));
1395
1396         rmb->ilgen = mb->ilgen;
1397         rmb->rtype = mono_reflection_type_resolve_user_types ((MonoReflectionType*)mb->rtype);
1398         rmb->parameters = mb->parameters;
1399         rmb->generic_params = mb->generic_params;
1400         rmb->generic_container = mb->generic_container;
1401         rmb->opt_types = NULL;
1402         rmb->pinfo = mb->pinfo;
1403         rmb->attrs = mb->attrs;
1404         rmb->iattrs = mb->iattrs;
1405         rmb->call_conv = mb->call_conv;
1406         rmb->code = mb->code;
1407         rmb->type = mb->type;
1408         rmb->name = mb->name;
1409         rmb->table_idx = &mb->table_idx;
1410         rmb->init_locals = mb->init_locals;
1411         rmb->skip_visibility = FALSE;
1412         rmb->return_modreq = mb->return_modreq;
1413         rmb->return_modopt = mb->return_modopt;
1414         rmb->param_modreq = mb->param_modreq;
1415         rmb->param_modopt = mb->param_modopt;
1416         rmb->permissions = mb->permissions;
1417         rmb->mhandle = mb->mhandle;
1418         rmb->nrefs = 0;
1419         rmb->refs = NULL;
1420
1421         if (mb->dll) {
1422                 rmb->charset = mb->charset;
1423                 rmb->extra_flags = mb->extra_flags;
1424                 rmb->native_cc = mb->native_cc;
1425                 rmb->dllentry = mb->dllentry;
1426                 rmb->dll = mb->dll;
1427         }
1428 }
1429
1430 static void
1431 reflection_methodbuilder_from_ctor_builder (ReflectionMethodBuilder *rmb, MonoReflectionCtorBuilder *mb)
1432 {
1433         const char *name = mb->attrs & METHOD_ATTRIBUTE_STATIC ? ".cctor": ".ctor";
1434
1435         memset (rmb, 0, sizeof (ReflectionMethodBuilder));
1436
1437         rmb->ilgen = mb->ilgen;
1438         rmb->rtype = mono_type_get_object (mono_domain_get (), &mono_defaults.void_class->byval_arg);
1439         rmb->parameters = mb->parameters;
1440         rmb->generic_params = NULL;
1441         rmb->generic_container = NULL;
1442         rmb->opt_types = NULL;
1443         rmb->pinfo = mb->pinfo;
1444         rmb->attrs = mb->attrs;
1445         rmb->iattrs = mb->iattrs;
1446         rmb->call_conv = mb->call_conv;
1447         rmb->code = NULL;
1448         rmb->type = mb->type;
1449         rmb->name = mono_string_new (mono_domain_get (), name);
1450         rmb->table_idx = &mb->table_idx;
1451         rmb->init_locals = mb->init_locals;
1452         rmb->skip_visibility = FALSE;
1453         rmb->return_modreq = NULL;
1454         rmb->return_modopt = NULL;
1455         rmb->param_modreq = mb->param_modreq;
1456         rmb->param_modopt = mb->param_modopt;
1457         rmb->permissions = mb->permissions;
1458         rmb->mhandle = mb->mhandle;
1459         rmb->nrefs = 0;
1460         rmb->refs = NULL;
1461 }
1462
1463 #ifndef DISABLE_REFLECTION_EMIT
1464 static void
1465 reflection_methodbuilder_from_dynamic_method (ReflectionMethodBuilder *rmb, MonoReflectionDynamicMethod *mb)
1466 {
1467         memset (rmb, 0, sizeof (ReflectionMethodBuilder));
1468
1469         rmb->ilgen = mb->ilgen;
1470         rmb->rtype = mb->rtype;
1471         rmb->parameters = mb->parameters;
1472         rmb->generic_params = NULL;
1473         rmb->generic_container = NULL;
1474         rmb->opt_types = NULL;
1475         rmb->pinfo = NULL;
1476         rmb->attrs = mb->attrs;
1477         rmb->iattrs = 0;
1478         rmb->call_conv = mb->call_conv;
1479         rmb->code = NULL;
1480         rmb->type = (MonoObject *) mb->owner;
1481         rmb->name = mb->name;
1482         rmb->table_idx = NULL;
1483         rmb->init_locals = mb->init_locals;
1484         rmb->skip_visibility = mb->skip_visibility;
1485         rmb->return_modreq = NULL;
1486         rmb->return_modopt = NULL;
1487         rmb->param_modreq = NULL;
1488         rmb->param_modopt = NULL;
1489         rmb->permissions = NULL;
1490         rmb->mhandle = mb->mhandle;
1491         rmb->nrefs = 0;
1492         rmb->refs = NULL;
1493 }       
1494 #endif
1495
1496 static void
1497 mono_image_add_methodimpl (MonoDynamicImage *assembly, MonoReflectionMethodBuilder *mb)
1498 {
1499         MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder *)mb->type;
1500         MonoDynamicTable *table;
1501         guint32 *values;
1502         guint32 tok;
1503
1504         if (!mb->override_method)
1505                 return;
1506
1507         table = &assembly->tables [MONO_TABLE_METHODIMPL];
1508         table->rows ++;
1509         alloc_table (table, table->rows);
1510         values = table->values + table->rows * MONO_METHODIMPL_SIZE;
1511         values [MONO_METHODIMPL_CLASS] = tb->table_idx;
1512         values [MONO_METHODIMPL_BODY] = MONO_METHODDEFORREF_METHODDEF | (mb->table_idx << MONO_METHODDEFORREF_BITS);
1513
1514         tok = mono_image_create_token (assembly, (MonoObject*)mb->override_method, FALSE, FALSE);
1515         switch (mono_metadata_token_table (tok)) {
1516         case MONO_TABLE_MEMBERREF:
1517                 tok = (mono_metadata_token_index (tok) << MONO_METHODDEFORREF_BITS ) | MONO_METHODDEFORREF_METHODREF;
1518                 break;
1519         case MONO_TABLE_METHOD:
1520                 tok = (mono_metadata_token_index (tok) << MONO_METHODDEFORREF_BITS ) | MONO_METHODDEFORREF_METHODDEF;
1521                 break;
1522         default:
1523                 g_assert_not_reached ();
1524         }
1525         values [MONO_METHODIMPL_DECLARATION] = tok;
1526 }
1527
1528 static void
1529 mono_image_get_method_info (MonoReflectionMethodBuilder *mb, MonoDynamicImage *assembly)
1530 {
1531         MonoDynamicTable *table;
1532         guint32 *values;
1533         ReflectionMethodBuilder rmb;
1534         int i;
1535
1536         reflection_methodbuilder_from_method_builder (&rmb, mb);
1537
1538         mono_image_basic_method (&rmb, assembly);
1539         mb->table_idx = *rmb.table_idx;
1540
1541         if (mb->dll) { /* It's a P/Invoke method */
1542                 guint32 moduleref;
1543                 /* map CharSet values to on-disk values */
1544                 int ncharset = (mb->charset ? (mb->charset - 1) * 2 : 0);
1545                 int extra_flags = mb->extra_flags;
1546                 table = &assembly->tables [MONO_TABLE_IMPLMAP];
1547                 table->rows ++;
1548                 alloc_table (table, table->rows);
1549                 values = table->values + table->rows * MONO_IMPLMAP_SIZE;
1550                 
1551                 values [MONO_IMPLMAP_FLAGS] = (mb->native_cc << 8) | ncharset | extra_flags;
1552                 values [MONO_IMPLMAP_MEMBER] = (mb->table_idx << 1) | 1; /* memberforwarded: method */
1553                 if (mb->dllentry)
1554                         values [MONO_IMPLMAP_NAME] = string_heap_insert_mstring (&assembly->sheap, mb->dllentry);
1555                 else
1556                         values [MONO_IMPLMAP_NAME] = string_heap_insert_mstring (&assembly->sheap, mb->name);
1557                 moduleref = string_heap_insert_mstring (&assembly->sheap, mb->dll);
1558                 if (!(values [MONO_IMPLMAP_SCOPE] = find_index_in_table (assembly, MONO_TABLE_MODULEREF, MONO_MODULEREF_NAME, moduleref))) {
1559                         table = &assembly->tables [MONO_TABLE_MODULEREF];
1560                         table->rows ++;
1561                         alloc_table (table, table->rows);
1562                         table->values [table->rows * MONO_MODULEREF_SIZE + MONO_MODULEREF_NAME] = moduleref;
1563                         values [MONO_IMPLMAP_SCOPE] = table->rows;
1564                 }
1565         }
1566
1567         if (mb->generic_params) {
1568                 table = &assembly->tables [MONO_TABLE_GENERICPARAM];
1569                 table->rows += mono_array_length (mb->generic_params);
1570                 alloc_table (table, table->rows);
1571                 for (i = 0; i < mono_array_length (mb->generic_params); ++i) {
1572                         guint32 owner = MONO_TYPEORMETHOD_METHOD | (mb->table_idx << MONO_TYPEORMETHOD_BITS);
1573
1574                         mono_image_get_generic_param_info (
1575                                 mono_array_get (mb->generic_params, gpointer, i), owner, assembly);
1576                 }
1577         }
1578
1579 }
1580
1581 static void
1582 mono_image_get_ctor_info (MonoDomain *domain, MonoReflectionCtorBuilder *mb, MonoDynamicImage *assembly)
1583 {
1584         ReflectionMethodBuilder rmb;
1585
1586         reflection_methodbuilder_from_ctor_builder (&rmb, mb);
1587
1588         mono_image_basic_method (&rmb, assembly);
1589         mb->table_idx = *rmb.table_idx;
1590 }
1591
1592 static char*
1593 type_get_fully_qualified_name (MonoType *type)
1594 {
1595         return mono_type_get_name_full (type, MONO_TYPE_NAME_FORMAT_ASSEMBLY_QUALIFIED);
1596 }
1597
1598 static char*
1599 type_get_qualified_name (MonoType *type, MonoAssembly *ass) {
1600         MonoClass *klass;
1601         MonoAssembly *ta;
1602
1603         klass = mono_class_from_mono_type (type);
1604         if (!klass) 
1605                 return mono_type_get_name_full (type, MONO_TYPE_NAME_FORMAT_REFLECTION);
1606         ta = klass->image->assembly;
1607         if (ta->dynamic || (ta == ass)) {
1608                 if (klass->generic_class || klass->generic_container)
1609                         /* For generic type definitions, we want T, while REFLECTION returns T<K> */
1610                         return mono_type_get_name_full (type, MONO_TYPE_NAME_FORMAT_FULL_NAME);
1611                 else
1612                         return mono_type_get_name_full (type, MONO_TYPE_NAME_FORMAT_REFLECTION);
1613         }
1614
1615         return mono_type_get_name_full (type, MONO_TYPE_NAME_FORMAT_ASSEMBLY_QUALIFIED);
1616 }
1617
1618 #ifndef DISABLE_REFLECTION_EMIT
1619 static guint32
1620 fieldref_encode_signature (MonoDynamicImage *assembly, MonoType *type)
1621 {
1622         SigBuffer buf;
1623         guint32 idx, i;
1624
1625         if (!assembly->save)
1626                 return 0;
1627
1628         sigbuffer_init (&buf, 32);
1629         
1630         sigbuffer_add_value (&buf, 0x06);
1631         /* encode custom attributes before the type */
1632         /* FIXME: This should probably go in encode_type () */
1633         if (type->num_mods) {
1634                 for (i = 0; i < type->num_mods; ++i) {
1635                         if (type->modifiers [i].required)
1636                                 sigbuffer_add_byte (&buf, MONO_TYPE_CMOD_REQD);
1637                         else
1638                                 sigbuffer_add_byte (&buf, MONO_TYPE_CMOD_OPT);
1639                         sigbuffer_add_value (&buf, type->modifiers [i].token);
1640                 }
1641         }
1642         encode_type (assembly, type, &buf);
1643         idx = sigbuffer_add_to_blob_cached (assembly, &buf);
1644         sigbuffer_free (&buf);
1645         return idx;
1646 }
1647 #endif
1648
1649 static guint32
1650 field_encode_signature (MonoDynamicImage *assembly, MonoReflectionFieldBuilder *fb)
1651 {
1652         SigBuffer buf;
1653         guint32 idx;
1654
1655         sigbuffer_init (&buf, 32);
1656         
1657         sigbuffer_add_value (&buf, 0x06);
1658         encode_custom_modifiers (assembly, fb->modreq, fb->modopt, &buf);
1659         /* encode custom attributes before the type */
1660         encode_reflection_type (assembly, (MonoReflectionType*)fb->type, &buf);
1661         idx = sigbuffer_add_to_blob_cached (assembly, &buf);
1662         sigbuffer_free (&buf);
1663         return idx;
1664 }
1665
1666 static guint32
1667 encode_constant (MonoDynamicImage *assembly, MonoObject *val, guint32 *ret_type) {
1668         char blob_size [64];
1669         char *b = blob_size;
1670         char *p, *box_val;
1671         char* buf;
1672         guint32 idx = 0, len = 0, dummy = 0;
1673 #ifdef ARM_FPU_FPA
1674 #if G_BYTE_ORDER == G_LITTLE_ENDIAN
1675         guint32 fpa_double [2];
1676         guint32 *fpa_p;
1677 #endif
1678 #endif
1679         
1680         p = buf = g_malloc (64);
1681         if (!val) {
1682                 *ret_type = MONO_TYPE_CLASS;
1683                 len = 4;
1684                 box_val = (char*)&dummy;
1685         } else {
1686                 box_val = ((char*)val) + sizeof (MonoObject);
1687                 *ret_type = val->vtable->klass->byval_arg.type;
1688         }
1689 handle_enum:
1690         switch (*ret_type) {
1691         case MONO_TYPE_BOOLEAN:
1692         case MONO_TYPE_U1:
1693         case MONO_TYPE_I1:
1694                 len = 1;
1695                 break;
1696         case MONO_TYPE_CHAR:
1697         case MONO_TYPE_U2:
1698         case MONO_TYPE_I2:
1699                 len = 2;
1700                 break;
1701         case MONO_TYPE_U4:
1702         case MONO_TYPE_I4:
1703         case MONO_TYPE_R4:
1704                 len = 4;
1705                 break;
1706         case MONO_TYPE_U8:
1707         case MONO_TYPE_I8:
1708                 len = 8;
1709                 break;
1710         case MONO_TYPE_R8:
1711                 len = 8;
1712 #ifdef ARM_FPU_FPA
1713 #if G_BYTE_ORDER == G_LITTLE_ENDIAN
1714                 fpa_p = (guint32*)box_val;
1715                 fpa_double [0] = fpa_p [1];
1716                 fpa_double [1] = fpa_p [0];
1717                 box_val = (char*)fpa_double;
1718 #endif
1719 #endif
1720                 break;
1721         case MONO_TYPE_VALUETYPE:
1722                 if (val->vtable->klass->enumtype) {
1723                         *ret_type = mono_class_enum_basetype (val->vtable->klass)->type;
1724                         goto handle_enum;
1725                 } else
1726                         g_error ("we can't encode valuetypes");
1727         case MONO_TYPE_CLASS:
1728                 break;
1729         case MONO_TYPE_STRING: {
1730                 MonoString *str = (MonoString*)val;
1731                 /* there is no signature */
1732                 len = str->length * 2;
1733                 mono_metadata_encode_value (len, b, &b);
1734 #if G_BYTE_ORDER != G_LITTLE_ENDIAN
1735                 {
1736                         char *swapped = g_malloc (2 * mono_string_length (str));
1737                         const char *p = (const char*)mono_string_chars (str);
1738
1739                         swap_with_size (swapped, p, 2, mono_string_length (str));
1740                         idx = add_to_blob_cached (assembly, blob_size, b-blob_size, swapped, len);
1741                         g_free (swapped);
1742                 }
1743 #else
1744                 idx = add_to_blob_cached (assembly, blob_size, b-blob_size, (char*)mono_string_chars (str), len);
1745 #endif
1746
1747                 g_free (buf);
1748                 return idx;
1749         }
1750         case MONO_TYPE_GENERICINST:
1751                 *ret_type = val->vtable->klass->generic_class->container_class->byval_arg.type;
1752                 goto handle_enum;
1753         default:
1754                 g_error ("we don't encode constant type 0x%02x yet", *ret_type);
1755         }
1756
1757         /* there is no signature */
1758         mono_metadata_encode_value (len, b, &b);
1759 #if G_BYTE_ORDER != G_LITTLE_ENDIAN
1760         idx = mono_image_add_stream_data (&assembly->blob, blob_size, b-blob_size);
1761         swap_with_size (blob_size, box_val, len, 1);
1762         mono_image_add_stream_data (&assembly->blob, blob_size, len);
1763 #else
1764         idx = add_to_blob_cached (assembly, blob_size, b-blob_size, box_val, len);
1765 #endif
1766
1767         g_free (buf);
1768         return idx;
1769 }
1770
1771 static guint32
1772 encode_marshal_blob (MonoDynamicImage *assembly, MonoReflectionMarshal *minfo) {
1773         char *str;
1774         SigBuffer buf;
1775         guint32 idx, len;
1776
1777         sigbuffer_init (&buf, 32);
1778
1779         sigbuffer_add_value (&buf, minfo->type);
1780
1781         switch (minfo->type) {
1782         case MONO_NATIVE_BYVALTSTR:
1783         case MONO_NATIVE_BYVALARRAY:
1784                 sigbuffer_add_value (&buf, minfo->count);
1785                 break;
1786         case MONO_NATIVE_LPARRAY:
1787                 if (minfo->eltype || minfo->has_size) {
1788                         sigbuffer_add_value (&buf, minfo->eltype);
1789                         if (minfo->has_size) {
1790                                 sigbuffer_add_value (&buf, minfo->param_num != -1? minfo->param_num: 0);
1791                                 sigbuffer_add_value (&buf, minfo->count != -1? minfo->count: 0);
1792
1793                                 /* LAMESPEC: ElemMult is undocumented */
1794                                 sigbuffer_add_value (&buf, minfo->param_num != -1? 1: 0);
1795                         }
1796                 }
1797                 break;
1798         case MONO_NATIVE_SAFEARRAY:
1799                 if (minfo->eltype)
1800                         sigbuffer_add_value (&buf, minfo->eltype);
1801                 break;
1802         case MONO_NATIVE_CUSTOM:
1803                 if (minfo->guid) {
1804                         str = mono_string_to_utf8 (minfo->guid);
1805                         len = strlen (str);
1806                         sigbuffer_add_value (&buf, len);
1807                         sigbuffer_add_mem (&buf, str, len);
1808                         g_free (str);
1809                 } else {
1810                         sigbuffer_add_value (&buf, 0);
1811                 }
1812                 /* native type name */
1813                 sigbuffer_add_value (&buf, 0);
1814                 /* custom marshaler type name */
1815                 if (minfo->marshaltype || minfo->marshaltyperef) {
1816                         if (minfo->marshaltyperef)
1817                                 str = type_get_fully_qualified_name (mono_reflection_type_get_handle ((MonoReflectionType*)minfo->marshaltyperef));
1818                         else
1819                                 str = mono_string_to_utf8 (minfo->marshaltype);
1820                         len = strlen (str);
1821                         sigbuffer_add_value (&buf, len);
1822                         sigbuffer_add_mem (&buf, str, len);
1823                         g_free (str);
1824                 } else {
1825                         /* FIXME: Actually a bug, since this field is required.  Punting for now ... */
1826                         sigbuffer_add_value (&buf, 0);
1827                 }
1828                 if (minfo->mcookie) {
1829                         str = mono_string_to_utf8 (minfo->mcookie);
1830                         len = strlen (str);
1831                         sigbuffer_add_value (&buf, len);
1832                         sigbuffer_add_mem (&buf, str, len);
1833                         g_free (str);
1834                 } else {
1835                         sigbuffer_add_value (&buf, 0);
1836                 }
1837                 break;
1838         default:
1839                 break;
1840         }
1841         idx = sigbuffer_add_to_blob_cached (assembly, &buf);
1842         sigbuffer_free (&buf);
1843         return idx;
1844 }
1845
1846 static void
1847 mono_image_get_field_info (MonoReflectionFieldBuilder *fb, MonoDynamicImage *assembly)
1848 {
1849         MonoDynamicTable *table;
1850         guint32 *values;
1851
1852         /* maybe this fixup should be done in the C# code */
1853         if (fb->attrs & FIELD_ATTRIBUTE_LITERAL)
1854                 fb->attrs |= FIELD_ATTRIBUTE_HAS_DEFAULT;
1855         table = &assembly->tables [MONO_TABLE_FIELD];
1856         fb->table_idx = table->next_idx ++;
1857         g_hash_table_insert (assembly->field_to_table_idx, fb->handle, GUINT_TO_POINTER (fb->table_idx));
1858         values = table->values + fb->table_idx * MONO_FIELD_SIZE;
1859         values [MONO_FIELD_NAME] = string_heap_insert_mstring (&assembly->sheap, fb->name);
1860         values [MONO_FIELD_FLAGS] = fb->attrs;
1861         values [MONO_FIELD_SIGNATURE] = field_encode_signature (assembly, fb);
1862
1863         if (fb->offset != -1) {
1864                 table = &assembly->tables [MONO_TABLE_FIELDLAYOUT];
1865                 table->rows ++;
1866                 alloc_table (table, table->rows);
1867                 values = table->values + table->rows * MONO_FIELD_LAYOUT_SIZE;
1868                 values [MONO_FIELD_LAYOUT_FIELD] = fb->table_idx;
1869                 values [MONO_FIELD_LAYOUT_OFFSET] = fb->offset;
1870         }
1871         if (fb->attrs & FIELD_ATTRIBUTE_LITERAL) {
1872                 guint32 field_type = 0;
1873                 table = &assembly->tables [MONO_TABLE_CONSTANT];
1874                 table->rows ++;
1875                 alloc_table (table, table->rows);
1876                 values = table->values + table->rows * MONO_CONSTANT_SIZE;
1877                 values [MONO_CONSTANT_PARENT] = MONO_HASCONSTANT_FIEDDEF | (fb->table_idx << MONO_HASCONSTANT_BITS);
1878                 values [MONO_CONSTANT_VALUE] = encode_constant (assembly, fb->def_value, &field_type);
1879                 values [MONO_CONSTANT_TYPE] = field_type;
1880                 values [MONO_CONSTANT_PADDING] = 0;
1881         }
1882         if (fb->attrs & FIELD_ATTRIBUTE_HAS_FIELD_RVA) {
1883                 guint32 rva_idx;
1884                 table = &assembly->tables [MONO_TABLE_FIELDRVA];
1885                 table->rows ++;
1886                 alloc_table (table, table->rows);
1887                 values = table->values + table->rows * MONO_FIELD_RVA_SIZE;
1888                 values [MONO_FIELD_RVA_FIELD] = fb->table_idx;
1889                 /*
1890                  * We store it in the code section because it's simpler for now.
1891                  */
1892                 if (fb->rva_data) {
1893                         if (mono_array_length (fb->rva_data) >= 10)
1894                                 stream_data_align (&assembly->code);
1895                         rva_idx = mono_image_add_stream_data (&assembly->code, mono_array_addr (fb->rva_data, char, 0), mono_array_length (fb->rva_data));
1896                 } else
1897                         rva_idx = mono_image_add_stream_zero (&assembly->code, mono_class_value_size (fb->handle->parent, NULL));
1898                 values [MONO_FIELD_RVA_RVA] = rva_idx + assembly->text_rva;
1899         }
1900         if (fb->marshal_info) {
1901                 table = &assembly->tables [MONO_TABLE_FIELDMARSHAL];
1902                 table->rows ++;
1903                 alloc_table (table, table->rows);
1904                 values = table->values + table->rows * MONO_FIELD_MARSHAL_SIZE;
1905                 values [MONO_FIELD_MARSHAL_PARENT] = (fb->table_idx << MONO_HAS_FIELD_MARSHAL_BITS) | MONO_HAS_FIELD_MARSHAL_FIELDSREF;
1906                 values [MONO_FIELD_MARSHAL_NATIVE_TYPE] = encode_marshal_blob (assembly, fb->marshal_info);
1907         }
1908 }
1909
1910 static guint32
1911 property_encode_signature (MonoDynamicImage *assembly, MonoReflectionPropertyBuilder *fb)
1912 {
1913         SigBuffer buf;
1914         guint32 nparams = 0;
1915         MonoReflectionMethodBuilder *mb = fb->get_method;
1916         MonoReflectionMethodBuilder *smb = fb->set_method;
1917         guint32 idx, i;
1918
1919         if (mb && mb->parameters)
1920                 nparams = mono_array_length (mb->parameters);
1921         if (!mb && smb && smb->parameters)
1922                 nparams = mono_array_length (smb->parameters) - 1;
1923         sigbuffer_init (&buf, 32);
1924         sigbuffer_add_byte (&buf, 0x08);
1925         sigbuffer_add_value (&buf, nparams);
1926         if (mb) {
1927                 encode_reflection_type (assembly, (MonoReflectionType*)mb->rtype, &buf);
1928                 for (i = 0; i < nparams; ++i) {
1929                         MonoReflectionType *pt = mono_array_get (mb->parameters, MonoReflectionType*, i);
1930                         encode_reflection_type (assembly, pt, &buf);
1931                 }
1932         } else if (smb && smb->parameters) {
1933                 /* the property type is the last param */
1934                 encode_reflection_type (assembly, mono_array_get (smb->parameters, MonoReflectionType*, nparams), &buf);
1935                 for (i = 0; i < nparams; ++i) {
1936                         MonoReflectionType *pt = mono_array_get (smb->parameters, MonoReflectionType*, i);
1937                         encode_reflection_type (assembly, pt, &buf);
1938                 }
1939         } else {
1940                 encode_reflection_type (assembly, (MonoReflectionType*)fb->type, &buf);
1941         }
1942
1943         idx = sigbuffer_add_to_blob_cached (assembly, &buf);
1944         sigbuffer_free (&buf);
1945         return idx;
1946 }
1947
1948 static void
1949 mono_image_get_property_info (MonoReflectionPropertyBuilder *pb, MonoDynamicImage *assembly)
1950 {
1951         MonoDynamicTable *table;
1952         guint32 *values;
1953         guint num_methods = 0;
1954         guint32 semaidx;
1955
1956         /* 
1957          * we need to set things in the following tables:
1958          * PROPERTYMAP (info already filled in _get_type_info ())
1959          * PROPERTY    (rows already preallocated in _get_type_info ())
1960          * METHOD      (method info already done with the generic method code)
1961          * METHODSEMANTICS
1962          */
1963         table = &assembly->tables [MONO_TABLE_PROPERTY];
1964         pb->table_idx = table->next_idx ++;
1965         values = table->values + pb->table_idx * MONO_PROPERTY_SIZE;
1966         values [MONO_PROPERTY_NAME] = string_heap_insert_mstring (&assembly->sheap, pb->name);
1967         values [MONO_PROPERTY_FLAGS] = pb->attrs;
1968         values [MONO_PROPERTY_TYPE] = property_encode_signature (assembly, pb);
1969
1970         /* FIXME: we still don't handle 'other' methods */
1971         if (pb->get_method) num_methods ++;
1972         if (pb->set_method) num_methods ++;
1973
1974         table = &assembly->tables [MONO_TABLE_METHODSEMANTICS];
1975         table->rows += num_methods;
1976         alloc_table (table, table->rows);
1977
1978         if (pb->get_method) {
1979                 semaidx = table->next_idx ++;
1980                 values = table->values + semaidx * MONO_METHOD_SEMA_SIZE;
1981                 values [MONO_METHOD_SEMA_SEMANTICS] = METHOD_SEMANTIC_GETTER;
1982                 values [MONO_METHOD_SEMA_METHOD] = pb->get_method->table_idx;
1983                 values [MONO_METHOD_SEMA_ASSOCIATION] = (pb->table_idx << MONO_HAS_SEMANTICS_BITS) | MONO_HAS_SEMANTICS_PROPERTY;
1984         }
1985         if (pb->set_method) {
1986                 semaidx = table->next_idx ++;
1987                 values = table->values + semaidx * MONO_METHOD_SEMA_SIZE;
1988                 values [MONO_METHOD_SEMA_SEMANTICS] = METHOD_SEMANTIC_SETTER;
1989                 values [MONO_METHOD_SEMA_METHOD] = pb->set_method->table_idx;
1990                 values [MONO_METHOD_SEMA_ASSOCIATION] = (pb->table_idx << MONO_HAS_SEMANTICS_BITS) | MONO_HAS_SEMANTICS_PROPERTY;
1991         }
1992 }
1993
1994 static void
1995 mono_image_get_event_info (MonoReflectionEventBuilder *eb, MonoDynamicImage *assembly)
1996 {
1997         MonoDynamicTable *table;
1998         guint32 *values;
1999         guint num_methods = 0;
2000         guint32 semaidx;
2001
2002         /* 
2003          * we need to set things in the following tables:
2004          * EVENTMAP (info already filled in _get_type_info ())
2005          * EVENT    (rows already preallocated in _get_type_info ())
2006          * METHOD      (method info already done with the generic method code)
2007          * METHODSEMANTICS
2008          */
2009         table = &assembly->tables [MONO_TABLE_EVENT];
2010         eb->table_idx = table->next_idx ++;
2011         values = table->values + eb->table_idx * MONO_EVENT_SIZE;
2012         values [MONO_EVENT_NAME] = string_heap_insert_mstring (&assembly->sheap, eb->name);
2013         values [MONO_EVENT_FLAGS] = eb->attrs;
2014         values [MONO_EVENT_TYPE] = mono_image_typedef_or_ref (assembly, mono_reflection_type_get_handle (eb->type));
2015
2016         /*
2017          * FIXME: we still don't handle 'other' methods 
2018          */
2019         if (eb->add_method) num_methods ++;
2020         if (eb->remove_method) num_methods ++;
2021         if (eb->raise_method) num_methods ++;
2022
2023         table = &assembly->tables [MONO_TABLE_METHODSEMANTICS];
2024         table->rows += num_methods;
2025         alloc_table (table, table->rows);
2026
2027         if (eb->add_method) {
2028                 semaidx = table->next_idx ++;
2029                 values = table->values + semaidx * MONO_METHOD_SEMA_SIZE;
2030                 values [MONO_METHOD_SEMA_SEMANTICS] = METHOD_SEMANTIC_ADD_ON;
2031                 values [MONO_METHOD_SEMA_METHOD] = eb->add_method->table_idx;
2032                 values [MONO_METHOD_SEMA_ASSOCIATION] = (eb->table_idx << MONO_HAS_SEMANTICS_BITS) | MONO_HAS_SEMANTICS_EVENT;
2033         }
2034         if (eb->remove_method) {
2035                 semaidx = table->next_idx ++;
2036                 values = table->values + semaidx * MONO_METHOD_SEMA_SIZE;
2037                 values [MONO_METHOD_SEMA_SEMANTICS] = METHOD_SEMANTIC_REMOVE_ON;
2038                 values [MONO_METHOD_SEMA_METHOD] = eb->remove_method->table_idx;
2039                 values [MONO_METHOD_SEMA_ASSOCIATION] = (eb->table_idx << MONO_HAS_SEMANTICS_BITS) | MONO_HAS_SEMANTICS_EVENT;
2040         }
2041         if (eb->raise_method) {
2042                 semaidx = table->next_idx ++;
2043                 values = table->values + semaidx * MONO_METHOD_SEMA_SIZE;
2044                 values [MONO_METHOD_SEMA_SEMANTICS] = METHOD_SEMANTIC_FIRE;
2045                 values [MONO_METHOD_SEMA_METHOD] = eb->raise_method->table_idx;
2046                 values [MONO_METHOD_SEMA_ASSOCIATION] = (eb->table_idx << MONO_HAS_SEMANTICS_BITS) | MONO_HAS_SEMANTICS_EVENT;
2047         }
2048 }
2049
2050 static void
2051 encode_constraints (MonoReflectionGenericParam *gparam, guint32 owner, MonoDynamicImage *assembly)
2052 {
2053         MonoDynamicTable *table;
2054         guint32 num_constraints, i;
2055         guint32 *values;
2056         guint32 table_idx;
2057
2058         table = &assembly->tables [MONO_TABLE_GENERICPARAMCONSTRAINT];
2059         num_constraints = gparam->iface_constraints ?
2060                 mono_array_length (gparam->iface_constraints) : 0;
2061         table->rows += num_constraints;
2062         if (gparam->base_type)
2063                 table->rows++;
2064         alloc_table (table, table->rows);
2065
2066         if (gparam->base_type) {
2067                 table_idx = table->next_idx ++;
2068                 values = table->values + table_idx * MONO_GENPARCONSTRAINT_SIZE;
2069
2070                 values [MONO_GENPARCONSTRAINT_GENERICPAR] = owner;
2071                 values [MONO_GENPARCONSTRAINT_CONSTRAINT] = mono_image_typedef_or_ref (
2072                         assembly, mono_reflection_type_get_handle (gparam->base_type));
2073         }
2074
2075         for (i = 0; i < num_constraints; i++) {
2076                 MonoReflectionType *constraint = mono_array_get (
2077                         gparam->iface_constraints, gpointer, i);
2078
2079                 table_idx = table->next_idx ++;
2080                 values = table->values + table_idx * MONO_GENPARCONSTRAINT_SIZE;
2081
2082                 values [MONO_GENPARCONSTRAINT_GENERICPAR] = owner;
2083                 values [MONO_GENPARCONSTRAINT_CONSTRAINT] = mono_image_typedef_or_ref (
2084                         assembly, mono_reflection_type_get_handle (constraint));
2085         }
2086 }
2087
2088 static void
2089 mono_image_get_generic_param_info (MonoReflectionGenericParam *gparam, guint32 owner, MonoDynamicImage *assembly)
2090 {
2091         GenericParamTableEntry *entry;
2092
2093         /*
2094          * The GenericParam table must be sorted according to the `owner' field.
2095          * We need to do this sorting prior to writing the GenericParamConstraint
2096          * table, since we have to use the final GenericParam table indices there
2097          * and they must also be sorted.
2098          */
2099
2100         entry = g_new0 (GenericParamTableEntry, 1);
2101         entry->owner = owner;
2102         /* FIXME: track where gen_params should be freed and remove the GC root as well */
2103         MOVING_GC_REGISTER (&entry->gparam);
2104         entry->gparam = gparam;
2105
2106         g_ptr_array_add (assembly->gen_params, entry);
2107 }
2108
2109 static void
2110 write_generic_param_entry (MonoDynamicImage *assembly, GenericParamTableEntry *entry)
2111 {
2112         MonoDynamicTable *table;
2113         MonoGenericParam *param;
2114         guint32 *values;
2115         guint32 table_idx;
2116
2117         table = &assembly->tables [MONO_TABLE_GENERICPARAM];
2118         table_idx = table->next_idx ++;
2119         values = table->values + table_idx * MONO_GENERICPARAM_SIZE;
2120
2121         param = mono_reflection_type_get_handle ((MonoReflectionType*)entry->gparam)->data.generic_param;
2122
2123         values [MONO_GENERICPARAM_OWNER] = entry->owner;
2124         values [MONO_GENERICPARAM_FLAGS] = entry->gparam->attrs;
2125         values [MONO_GENERICPARAM_NUMBER] = mono_generic_param_num (param);
2126         values [MONO_GENERICPARAM_NAME] = string_heap_insert (&assembly->sheap, mono_generic_param_info (param)->name);
2127
2128         mono_image_add_cattrs (assembly, table_idx, MONO_CUSTOM_ATTR_GENERICPAR, entry->gparam->cattrs);
2129
2130         encode_constraints (entry->gparam, table_idx, assembly);
2131 }
2132
2133 static guint32
2134 resolution_scope_from_image (MonoDynamicImage *assembly, MonoImage *image)
2135 {
2136         MonoDynamicTable *table;
2137         guint32 token;
2138         guint32 *values;
2139         guint32 cols [MONO_ASSEMBLY_SIZE];
2140         const char *pubkey;
2141         guint32 publen;
2142
2143         if ((token = GPOINTER_TO_UINT (g_hash_table_lookup (assembly->handleref, image))))
2144                 return token;
2145
2146         if (image->assembly->dynamic && (image->assembly == assembly->image.assembly)) {
2147                 table = &assembly->tables [MONO_TABLE_MODULEREF];
2148                 token = table->next_idx ++;
2149                 table->rows ++;
2150                 alloc_table (table, table->rows);
2151                 values = table->values + token * MONO_MODULEREF_SIZE;
2152                 values [MONO_MODULEREF_NAME] = string_heap_insert (&assembly->sheap, image->module_name);
2153
2154                 token <<= MONO_RESOLTION_SCOPE_BITS;
2155                 token |= MONO_RESOLTION_SCOPE_MODULEREF;
2156                 g_hash_table_insert (assembly->handleref, image, GUINT_TO_POINTER (token));
2157
2158                 return token;
2159         }
2160         
2161         if (image->assembly->dynamic)
2162                 /* FIXME: */
2163                 memset (cols, 0, sizeof (cols));
2164         else {
2165                 /* image->assembly->image is the manifest module */
2166                 image = image->assembly->image;
2167                 mono_metadata_decode_row (&image->tables [MONO_TABLE_ASSEMBLY], 0, cols, MONO_ASSEMBLY_SIZE);
2168         }
2169
2170         table = &assembly->tables [MONO_TABLE_ASSEMBLYREF];
2171         token = table->next_idx ++;
2172         table->rows ++;
2173         alloc_table (table, table->rows);
2174         values = table->values + token * MONO_ASSEMBLYREF_SIZE;
2175         values [MONO_ASSEMBLYREF_NAME] = string_heap_insert (&assembly->sheap, image->assembly_name);
2176         values [MONO_ASSEMBLYREF_MAJOR_VERSION] = cols [MONO_ASSEMBLY_MAJOR_VERSION];
2177         values [MONO_ASSEMBLYREF_MINOR_VERSION] = cols [MONO_ASSEMBLY_MINOR_VERSION];
2178         values [MONO_ASSEMBLYREF_BUILD_NUMBER] = cols [MONO_ASSEMBLY_BUILD_NUMBER];
2179         values [MONO_ASSEMBLYREF_REV_NUMBER] = cols [MONO_ASSEMBLY_REV_NUMBER];
2180         values [MONO_ASSEMBLYREF_FLAGS] = 0;
2181         values [MONO_ASSEMBLYREF_CULTURE] = 0;
2182         values [MONO_ASSEMBLYREF_HASH_VALUE] = 0;
2183
2184         if (strcmp ("", image->assembly->aname.culture)) {
2185                 values [MONO_ASSEMBLYREF_CULTURE] = string_heap_insert (&assembly->sheap,
2186                                 image->assembly->aname.culture);
2187         }
2188
2189         if ((pubkey = mono_image_get_public_key (image, &publen))) {
2190                 guchar pubtoken [9];
2191                 pubtoken [0] = 8;
2192                 mono_digest_get_public_token (pubtoken + 1, (guchar*)pubkey, publen);
2193                 values [MONO_ASSEMBLYREF_PUBLIC_KEY] = mono_image_add_stream_data (&assembly->blob, (char*)pubtoken, 9);
2194         } else {
2195                 values [MONO_ASSEMBLYREF_PUBLIC_KEY] = 0;
2196         }
2197         token <<= MONO_RESOLTION_SCOPE_BITS;
2198         token |= MONO_RESOLTION_SCOPE_ASSEMBLYREF;
2199         g_hash_table_insert (assembly->handleref, image, GUINT_TO_POINTER (token));
2200         return token;
2201 }
2202
2203 static guint32
2204 create_typespec (MonoDynamicImage *assembly, MonoType *type)
2205 {
2206         MonoDynamicTable *table;
2207         guint32 *values;
2208         guint32 token;
2209         SigBuffer buf;
2210
2211         if ((token = GPOINTER_TO_UINT (g_hash_table_lookup (assembly->typespec, type))))
2212                 return token;
2213
2214         sigbuffer_init (&buf, 32);
2215         switch (type->type) {
2216         case MONO_TYPE_FNPTR:
2217         case MONO_TYPE_PTR:
2218         case MONO_TYPE_SZARRAY:
2219         case MONO_TYPE_ARRAY:
2220         case MONO_TYPE_VAR:
2221         case MONO_TYPE_MVAR:
2222         case MONO_TYPE_GENERICINST:
2223                 encode_type (assembly, type, &buf);
2224                 break;
2225         case MONO_TYPE_CLASS:
2226         case MONO_TYPE_VALUETYPE: {
2227                 MonoClass *k = mono_class_from_mono_type (type);
2228                 if (!k || !k->generic_container) {
2229                         sigbuffer_free (&buf);
2230                         return 0;
2231                 }
2232                 encode_type (assembly, type, &buf);
2233                 break;
2234         }
2235         default:
2236                 sigbuffer_free (&buf);
2237                 return 0;
2238         }
2239
2240         table = &assembly->tables [MONO_TABLE_TYPESPEC];
2241         if (assembly->save) {
2242                 token = sigbuffer_add_to_blob_cached (assembly, &buf);
2243                 alloc_table (table, table->rows + 1);
2244                 values = table->values + table->next_idx * MONO_TYPESPEC_SIZE;
2245                 values [MONO_TYPESPEC_SIGNATURE] = token;
2246         }
2247         sigbuffer_free (&buf);
2248
2249         token = MONO_TYPEDEFORREF_TYPESPEC | (table->next_idx << MONO_TYPEDEFORREF_BITS);
2250         g_hash_table_insert (assembly->typespec, type, GUINT_TO_POINTER(token));
2251         table->next_idx ++;
2252         return token;
2253 }
2254
2255 static guint32
2256 mono_image_typedef_or_ref_full (MonoDynamicImage *assembly, MonoType *type, gboolean try_typespec)
2257 {
2258         MonoDynamicTable *table;
2259         guint32 *values;
2260         guint32 token, scope, enclosing;
2261         MonoClass *klass;
2262
2263         /* if the type requires a typespec, we must try that first*/
2264         if (try_typespec && (token = create_typespec (assembly, type)))
2265                 return token;
2266         token = GPOINTER_TO_UINT (g_hash_table_lookup (assembly->typeref, type));
2267         if (token)
2268                 return token;
2269         klass = mono_class_from_mono_type (type);
2270         if (!klass)
2271                 klass = mono_class_from_mono_type (type);
2272
2273         /*
2274          * If it's in the same module and not a generic type parameter:
2275          */
2276         if ((klass->image == &assembly->image) && (type->type != MONO_TYPE_VAR) && 
2277                         (type->type != MONO_TYPE_MVAR)) {
2278                 MonoReflectionTypeBuilder *tb = klass->reflection_info;
2279                 token = MONO_TYPEDEFORREF_TYPEDEF | (tb->table_idx << MONO_TYPEDEFORREF_BITS);
2280                 mono_g_hash_table_insert (assembly->tokens, GUINT_TO_POINTER (token), klass->reflection_info);
2281                 return token;
2282         }
2283
2284         if (klass->nested_in) {
2285                 enclosing = mono_image_typedef_or_ref_full (assembly, &klass->nested_in->byval_arg, FALSE);
2286                 /* get the typeref idx of the enclosing type */
2287                 enclosing >>= MONO_TYPEDEFORREF_BITS;
2288                 scope = (enclosing << MONO_RESOLTION_SCOPE_BITS) | MONO_RESOLTION_SCOPE_TYPEREF;
2289         } else {
2290                 scope = resolution_scope_from_image (assembly, klass->image);
2291         }
2292         table = &assembly->tables [MONO_TABLE_TYPEREF];
2293         if (assembly->save) {
2294                 alloc_table (table, table->rows + 1);
2295                 values = table->values + table->next_idx * MONO_TYPEREF_SIZE;
2296                 values [MONO_TYPEREF_SCOPE] = scope;
2297                 values [MONO_TYPEREF_NAME] = string_heap_insert (&assembly->sheap, klass->name);
2298                 values [MONO_TYPEREF_NAMESPACE] = string_heap_insert (&assembly->sheap, klass->name_space);
2299         }
2300         token = MONO_TYPEDEFORREF_TYPEREF | (table->next_idx << MONO_TYPEDEFORREF_BITS); /* typeref */
2301         g_hash_table_insert (assembly->typeref, type, GUINT_TO_POINTER(token));
2302         table->next_idx ++;
2303         mono_g_hash_table_insert (assembly->tokens, GUINT_TO_POINTER (token), klass->reflection_info);
2304         return token;
2305 }
2306
2307 /*
2308  * Despite the name, we handle also TypeSpec (with the above helper).
2309  */
2310 static guint32
2311 mono_image_typedef_or_ref (MonoDynamicImage *assembly, MonoType *type)
2312 {
2313         return mono_image_typedef_or_ref_full (assembly, type, TRUE);
2314 }
2315
2316 #ifndef DISABLE_REFLECTION_EMIT
2317 /*
2318  * Insert a memberef row into the metadata: the token that point to the memberref
2319  * is returned. Caching is done in the caller (mono_image_get_methodref_token() or
2320  * mono_image_get_fieldref_token()).
2321  * The sig param is an index to an already built signature.
2322  */
2323 static guint32
2324 mono_image_get_memberref_token (MonoDynamicImage *assembly, MonoType *type, const char *name, guint32 sig)
2325 {
2326         MonoDynamicTable *table;
2327         guint32 *values;
2328         guint32 token, pclass;
2329         guint32 parent;
2330
2331         parent = mono_image_typedef_or_ref (assembly, type);
2332         switch (parent & MONO_TYPEDEFORREF_MASK) {
2333         case MONO_TYPEDEFORREF_TYPEREF:
2334                 pclass = MONO_MEMBERREF_PARENT_TYPEREF;
2335                 break;
2336         case MONO_TYPEDEFORREF_TYPESPEC:
2337                 pclass = MONO_MEMBERREF_PARENT_TYPESPEC;
2338                 break;
2339         case MONO_TYPEDEFORREF_TYPEDEF:
2340                 pclass = MONO_MEMBERREF_PARENT_TYPEDEF;
2341                 break;
2342         default:
2343                 g_warning ("unknown typeref or def token 0x%08x for %s", parent, name);
2344                 return 0;
2345         }
2346         /* extract the index */
2347         parent >>= MONO_TYPEDEFORREF_BITS;
2348
2349         table = &assembly->tables [MONO_TABLE_MEMBERREF];
2350
2351         if (assembly->save) {
2352                 alloc_table (table, table->rows + 1);
2353                 values = table->values + table->next_idx * MONO_MEMBERREF_SIZE;
2354                 values [MONO_MEMBERREF_CLASS] = pclass | (parent << MONO_MEMBERREF_PARENT_BITS);
2355                 values [MONO_MEMBERREF_NAME] = string_heap_insert (&assembly->sheap, name);
2356                 values [MONO_MEMBERREF_SIGNATURE] = sig;
2357         }
2358
2359         token = MONO_TOKEN_MEMBER_REF | table->next_idx;
2360         table->next_idx ++;
2361
2362         return token;
2363 }
2364
2365 static guint32
2366 mono_image_get_methodref_token (MonoDynamicImage *assembly, MonoMethod *method, gboolean create_typespec)
2367 {
2368         guint32 token;
2369         MonoMethodSignature *sig;
2370         
2371         create_typespec = create_typespec && method->is_generic && method->klass->image != &assembly->image;
2372
2373         if (create_typespec) {
2374                 token = GPOINTER_TO_UINT (g_hash_table_lookup (assembly->handleref, GUINT_TO_POINTER (GPOINTER_TO_UINT (method) + 1)));
2375                 if (token)
2376                         return token;
2377         } 
2378
2379         token = GPOINTER_TO_UINT (g_hash_table_lookup (assembly->handleref, method));
2380         if (token && !create_typespec)
2381                 return token;
2382
2383         g_assert (!method->is_inflated);
2384         if (!token) {
2385                 /*
2386                  * A methodref signature can't contain an unmanaged calling convention.
2387                  */
2388                 sig = mono_metadata_signature_dup (mono_method_signature (method));
2389                 if ((sig->call_convention != MONO_CALL_DEFAULT) && (sig->call_convention != MONO_CALL_VARARG))
2390                         sig->call_convention = MONO_CALL_DEFAULT;
2391                 token = mono_image_get_memberref_token (assembly, &method->klass->byval_arg,
2392                         method->name,  method_encode_signature (assembly, sig));
2393                 g_free (sig);
2394                 g_hash_table_insert (assembly->handleref, method, GUINT_TO_POINTER(token));
2395         }
2396
2397         if (create_typespec) {
2398                 MonoDynamicTable *table = &assembly->tables [MONO_TABLE_METHODSPEC];
2399                 g_assert (mono_metadata_token_table (token) == MONO_TABLE_MEMBERREF);
2400                 token = (mono_metadata_token_index (token) << MONO_METHODDEFORREF_BITS) | MONO_METHODDEFORREF_METHODREF;
2401
2402                 if (assembly->save) {
2403                         guint32 *values;
2404
2405                         alloc_table (table, table->rows + 1);
2406                         values = table->values + table->next_idx * MONO_METHODSPEC_SIZE;
2407                         values [MONO_METHODSPEC_METHOD] = token;
2408                         values [MONO_METHODSPEC_SIGNATURE] = encode_generic_method_sig (assembly, &mono_method_get_generic_container (method)->context);
2409                 }
2410
2411                 token = MONO_TOKEN_METHOD_SPEC | table->next_idx;
2412                 table->next_idx ++;
2413                 /*methodspec and memberef tokens are diferent, */
2414                 g_hash_table_insert (assembly->handleref, GUINT_TO_POINTER (GPOINTER_TO_UINT (method) + 1), GUINT_TO_POINTER (token));
2415                 return token;
2416         }
2417         return token;
2418 }
2419
2420 static guint32
2421 mono_image_get_methodref_token_for_methodbuilder (MonoDynamicImage *assembly, MonoReflectionMethodBuilder *method)
2422 {
2423         guint32 token;
2424         ReflectionMethodBuilder rmb;
2425         char *name;
2426         
2427         token = GPOINTER_TO_UINT (g_hash_table_lookup (assembly->handleref, method));
2428         if (token)
2429                 return token;
2430
2431         name = mono_string_to_utf8 (method->name);
2432         reflection_methodbuilder_from_method_builder (&rmb, method);
2433
2434         /*
2435          * A methodref signature can't contain an unmanaged calling convention.
2436          * Since some flags are encoded as part of call_conv, we need to check against it.
2437         */
2438         if ((rmb.call_conv & ~0x60) != MONO_CALL_DEFAULT && (rmb.call_conv & ~0x60) != MONO_CALL_VARARG)
2439                 rmb.call_conv = (rmb.call_conv & 0x60) | MONO_CALL_DEFAULT;
2440         token = mono_image_get_memberref_token (assembly, mono_reflection_type_get_handle ((MonoReflectionType*)rmb.type),
2441                                         name, method_builder_encode_signature (assembly, &rmb));
2442
2443         g_free (name);
2444         g_hash_table_insert (assembly->handleref, method, GUINT_TO_POINTER(token));
2445         return token;
2446 }
2447
2448 static guint32
2449 mono_image_get_varargs_method_token (MonoDynamicImage *assembly, guint32 original,
2450                                      const gchar *name, guint32 sig)
2451 {
2452         MonoDynamicTable *table;
2453         guint32 token;
2454         guint32 *values;
2455         
2456         table = &assembly->tables [MONO_TABLE_MEMBERREF];
2457
2458         if (assembly->save) {
2459                 alloc_table (table, table->rows + 1);
2460                 values = table->values + table->next_idx * MONO_MEMBERREF_SIZE;
2461                 values [MONO_MEMBERREF_CLASS] = original;
2462                 values [MONO_MEMBERREF_NAME] = string_heap_insert (&assembly->sheap, name);
2463                 values [MONO_MEMBERREF_SIGNATURE] = sig;
2464         }
2465
2466         token = MONO_TOKEN_MEMBER_REF | table->next_idx;
2467         table->next_idx ++;
2468
2469         return token;
2470 }
2471
2472 static guint32
2473 encode_generic_method_definition_sig (MonoDynamicImage *assembly, MonoReflectionMethodBuilder *mb)
2474 {
2475         SigBuffer buf;
2476         int i;
2477         guint32 nparams = mono_array_length (mb->generic_params);
2478         guint32 idx;
2479
2480         if (!assembly->save)
2481                 return 0;
2482
2483         sigbuffer_init (&buf, 32);
2484
2485         sigbuffer_add_value (&buf, 0xa);
2486         sigbuffer_add_value (&buf, nparams);
2487
2488         for (i = 0; i < nparams; i++) {
2489                 sigbuffer_add_value (&buf, MONO_TYPE_MVAR);
2490                 sigbuffer_add_value (&buf, i);
2491         }
2492
2493         idx = sigbuffer_add_to_blob_cached (assembly, &buf);
2494         sigbuffer_free (&buf);
2495         return idx;
2496 }
2497
2498 static guint32
2499 mono_image_get_methodspec_token_for_generic_method_definition (MonoDynamicImage *assembly, MonoReflectionMethodBuilder *mb)
2500 {
2501         MonoDynamicTable *table;
2502         guint32 *values;
2503         guint32 token, mtoken = 0;
2504
2505         token = GPOINTER_TO_UINT (mono_g_hash_table_lookup (assembly->methodspec, mb));
2506         if (token)
2507                 return token;
2508
2509         table = &assembly->tables [MONO_TABLE_METHODSPEC];
2510
2511         mtoken = mono_image_get_methodref_token_for_methodbuilder (assembly, mb);
2512         switch (mono_metadata_token_table (mtoken)) {
2513         case MONO_TABLE_MEMBERREF:
2514                 mtoken = (mono_metadata_token_index (mtoken) << MONO_METHODDEFORREF_BITS) | MONO_METHODDEFORREF_METHODREF;
2515                 break;
2516         case MONO_TABLE_METHOD:
2517                 mtoken = (mono_metadata_token_index (mtoken) << MONO_METHODDEFORREF_BITS) | MONO_METHODDEFORREF_METHODDEF;
2518                 break;
2519         default:
2520                 g_assert_not_reached ();
2521         }
2522
2523         if (assembly->save) {
2524                 alloc_table (table, table->rows + 1);
2525                 values = table->values + table->next_idx * MONO_METHODSPEC_SIZE;
2526                 values [MONO_METHODSPEC_METHOD] = mtoken;
2527                 values [MONO_METHODSPEC_SIGNATURE] = encode_generic_method_definition_sig (assembly, mb);
2528         }
2529
2530         token = MONO_TOKEN_METHOD_SPEC | table->next_idx;
2531         table->next_idx ++;
2532
2533         mono_g_hash_table_insert (assembly->methodspec, mb, GUINT_TO_POINTER(token));
2534         return token;
2535 }
2536
2537 static guint32
2538 mono_image_get_methodbuilder_token (MonoDynamicImage *assembly, MonoReflectionMethodBuilder *mb, gboolean create_methodspec)
2539 {
2540         guint32 token;
2541         
2542         if (mb->generic_params && create_methodspec) 
2543                 return mono_image_get_methodspec_token_for_generic_method_definition (assembly, mb);
2544
2545         token = GPOINTER_TO_UINT (g_hash_table_lookup (assembly->handleref, mb));
2546         if (token)
2547                 return token;
2548
2549         token = mono_image_get_methodref_token_for_methodbuilder (assembly, mb);
2550         g_hash_table_insert (assembly->handleref, mb, GUINT_TO_POINTER(token));
2551         return token;
2552 }
2553
2554 static guint32
2555 mono_image_get_ctorbuilder_token (MonoDynamicImage *assembly, MonoReflectionCtorBuilder *mb)
2556 {
2557         guint32 token;
2558         ReflectionMethodBuilder rmb;
2559         char *name;
2560         
2561         token = GPOINTER_TO_UINT (g_hash_table_lookup (assembly->handleref, mb));
2562         if (token)
2563                 return token;
2564
2565         reflection_methodbuilder_from_ctor_builder (&rmb, mb);
2566
2567         name = mono_string_to_utf8 (rmb.name);
2568         token = mono_image_get_memberref_token (assembly, mono_reflection_type_get_handle ((MonoReflectionType*)rmb.type),
2569                 name, method_builder_encode_signature (assembly, &rmb));
2570
2571         g_free (name);
2572         g_hash_table_insert (assembly->handleref, mb, GUINT_TO_POINTER(token));
2573         return token;
2574 }
2575 #endif
2576
2577 static gboolean
2578 is_field_on_inst (MonoClassField *field)
2579 {
2580         return (field->parent->generic_class && field->parent->generic_class->is_dynamic && ((MonoDynamicGenericClass*)field->parent->generic_class)->fields);
2581 }
2582
2583 /*
2584  * If FIELD is a field of a MonoDynamicGenericClass, return its non-inflated type.
2585  */
2586 static MonoType*
2587 get_field_on_inst_generic_type (MonoClassField *field)
2588 {
2589         MonoDynamicGenericClass *dgclass;
2590         int field_index;
2591
2592         g_assert (is_field_on_inst (field));
2593
2594         dgclass = (MonoDynamicGenericClass*)field->parent->generic_class;
2595         field_index = field - dgclass->fields;
2596
2597         g_assert (field_index >= 0 && field_index < dgclass->count_fields);
2598         return dgclass->field_generic_types [field_index];
2599 }
2600
2601 #ifndef DISABLE_REFLECTION_EMIT
2602 static guint32
2603 mono_image_get_fieldref_token (MonoDynamicImage *assembly, MonoReflectionField *f)
2604 {
2605         MonoType *type;
2606         guint32 token;
2607         MonoClassField *field;
2608
2609         token = GPOINTER_TO_UINT (g_hash_table_lookup (assembly->handleref, f));
2610         if (token)
2611                 return token;
2612         g_assert (f->field->parent);
2613
2614         field = f->field;
2615         if (field->parent->generic_class && field->parent->generic_class->container_class && field->parent->generic_class->container_class->fields) {
2616                 int index = field - field->parent->fields;
2617                 type = field->parent->generic_class->container_class->fields [index].type;
2618         } else {
2619                 if (is_field_on_inst (f->field))
2620                         type = get_field_on_inst_generic_type (f->field);
2621                 else
2622                         type = f->field->type;
2623         }
2624         token = mono_image_get_memberref_token (assembly, &f->field->parent->byval_arg, 
2625                                                                                         mono_field_get_name (f->field),  
2626                                                                                         fieldref_encode_signature (assembly, type));
2627         g_hash_table_insert (assembly->handleref, f, GUINT_TO_POINTER(token));
2628         return token;
2629 }
2630
2631 static guint32
2632 mono_image_get_field_on_inst_token (MonoDynamicImage *assembly, MonoReflectionFieldOnTypeBuilderInst *f)
2633 {
2634         guint32 token;
2635         MonoClass *klass;
2636         MonoGenericClass *gclass;
2637         MonoDynamicGenericClass *dgclass;
2638         MonoReflectionFieldBuilder *fb = f->fb;
2639         MonoType *type;
2640         char *name;
2641
2642         token = GPOINTER_TO_UINT (g_hash_table_lookup (assembly->handleref, f));
2643         if (token)
2644                 return token;
2645         type = mono_reflection_type_get_handle ((MonoReflectionType*)f->inst);
2646         klass = mono_class_from_mono_type (type);
2647         gclass = type->data.generic_class;
2648         g_assert (gclass->is_dynamic);
2649         dgclass = (MonoDynamicGenericClass *) gclass;
2650
2651         name = mono_string_to_utf8 (fb->name);
2652         token = mono_image_get_memberref_token (assembly, &klass->byval_arg, name, 
2653                                                                                         field_encode_signature (assembly, fb));
2654         g_free (name);
2655         g_hash_table_insert (assembly->handleref, f, GUINT_TO_POINTER (token));
2656         return token;
2657 }
2658
2659 static guint32
2660 mono_image_get_ctor_on_inst_token (MonoDynamicImage *assembly, MonoReflectionCtorOnTypeBuilderInst *c, gboolean create_methodspec)
2661 {
2662         guint32 sig, token;
2663         MonoClass *klass;
2664         MonoGenericClass *gclass;
2665         MonoDynamicGenericClass *dgclass;
2666         MonoReflectionCtorBuilder *cb = c->cb;
2667         ReflectionMethodBuilder rmb;
2668         MonoType *type;
2669         char *name;
2670
2671         /* A ctor cannot be a generic method, so we can ignore create_methodspec */
2672
2673         token = GPOINTER_TO_UINT (g_hash_table_lookup (assembly->handleref, c));
2674         if (token)
2675                 return token;
2676         type = mono_reflection_type_get_handle ((MonoReflectionType*)c->inst);
2677         klass = mono_class_from_mono_type (type);
2678         gclass = type->data.generic_class;
2679         g_assert (gclass->is_dynamic);
2680         dgclass = (MonoDynamicGenericClass *) gclass;
2681
2682         reflection_methodbuilder_from_ctor_builder (&rmb, cb);
2683
2684         name = mono_string_to_utf8 (rmb.name);
2685
2686         sig = method_builder_encode_signature (assembly, &rmb);
2687
2688         token = mono_image_get_memberref_token (assembly, &klass->byval_arg, name, sig);
2689         g_free (name);
2690
2691         g_hash_table_insert (assembly->handleref, c, GUINT_TO_POINTER (token));
2692         return token;
2693 }
2694
2695 static MonoMethod*
2696 mono_reflection_method_on_tb_inst_get_handle (MonoReflectionMethodOnTypeBuilderInst *m)
2697 {
2698         MonoClass *klass;
2699         MonoGenericContext tmp_context;
2700         MonoType **type_argv;
2701         MonoGenericInst *ginst;
2702         MonoMethod *method, *inflated;
2703         int count, i;
2704
2705         method = inflate_method (m->inst, (MonoObject*)m->mb);
2706
2707         klass = method->klass;
2708
2709         if (method->is_inflated)
2710                 method = ((MonoMethodInflated *) method)->declaring;
2711
2712         count = mono_array_length (m->method_args);
2713
2714         type_argv = g_new0 (MonoType *, count);
2715         for (i = 0; i < count; i++) {
2716                 MonoReflectionType *garg = mono_array_get (m->method_args, gpointer, i);
2717                 type_argv [i] = mono_reflection_type_get_handle (garg);
2718         }
2719         ginst = mono_metadata_get_generic_inst (count, type_argv);
2720         g_free (type_argv);
2721
2722         tmp_context.class_inst = klass->generic_class ? klass->generic_class->context.class_inst : NULL;
2723         tmp_context.method_inst = ginst;
2724
2725         inflated = mono_class_inflate_generic_method (method, &tmp_context);
2726         return inflated;
2727 }
2728
2729 static guint32
2730 mono_image_get_method_on_inst_token (MonoDynamicImage *assembly, MonoReflectionMethodOnTypeBuilderInst *m, gboolean create_methodspec)
2731 {
2732         guint32 sig, token;
2733         MonoClass *klass;
2734         MonoGenericClass *gclass;
2735         MonoReflectionMethodBuilder *mb = m->mb;
2736         ReflectionMethodBuilder rmb;
2737         MonoType *type;
2738         char *name;
2739
2740         if (m->method_args) {
2741                 MonoMethod *inflated;
2742
2743                 inflated = mono_reflection_method_on_tb_inst_get_handle (m);
2744                 if (create_methodspec)
2745                         token = mono_image_get_methodspec_token (assembly, inflated);
2746                 else
2747                         token = mono_image_get_inflated_method_token (assembly, inflated);
2748                 return token;
2749         }
2750
2751         token = GPOINTER_TO_UINT (g_hash_table_lookup (assembly->handleref, m));
2752         if (token)
2753                 return token;
2754         type = mono_reflection_type_get_handle ((MonoReflectionType*)m->inst);
2755         klass = mono_class_from_mono_type (type);
2756         gclass = type->data.generic_class;
2757         g_assert (gclass->is_dynamic);
2758
2759         reflection_methodbuilder_from_method_builder (&rmb, mb);
2760
2761         name = mono_string_to_utf8 (rmb.name);
2762
2763         sig = method_builder_encode_signature (assembly, &rmb);
2764
2765         token = mono_image_get_memberref_token (assembly, &klass->byval_arg, name, sig);
2766         g_free (name);
2767
2768         g_hash_table_insert (assembly->handleref, m, GUINT_TO_POINTER (token));
2769         return token;
2770 }
2771
2772 static guint32
2773 encode_generic_method_sig (MonoDynamicImage *assembly, MonoGenericContext *context)
2774 {
2775         SigBuffer buf;
2776         int i;
2777         guint32 nparams = context->method_inst->type_argc;
2778         guint32 idx;
2779
2780         if (!assembly->save)
2781                 return 0;
2782
2783         sigbuffer_init (&buf, 32);
2784         /*
2785          * FIXME: vararg, explicit_this, differenc call_conv values...
2786          */
2787         sigbuffer_add_value (&buf, 0xa); /* FIXME FIXME FIXME */
2788         sigbuffer_add_value (&buf, nparams);
2789
2790         for (i = 0; i < nparams; i++)
2791                 encode_type (assembly, context->method_inst->type_argv [i], &buf);
2792
2793         idx = sigbuffer_add_to_blob_cached (assembly, &buf);
2794         sigbuffer_free (&buf);
2795         return idx;
2796 }
2797
2798 static guint32
2799 method_encode_methodspec (MonoDynamicImage *assembly, MonoMethod *method)
2800 {
2801         MonoDynamicTable *table;
2802         guint32 *values;
2803         guint32 token, mtoken = 0, sig;
2804         MonoMethodInflated *imethod;
2805         MonoMethod *declaring;
2806
2807         table = &assembly->tables [MONO_TABLE_METHODSPEC];
2808
2809         g_assert (method->is_inflated);
2810         imethod = (MonoMethodInflated *) method;
2811         declaring = imethod->declaring;
2812
2813         sig = method_encode_signature (assembly, mono_method_signature (declaring));
2814         mtoken = mono_image_get_memberref_token (assembly, &method->klass->byval_arg, declaring->name, sig);
2815
2816         if (!mono_method_signature (declaring)->generic_param_count)
2817                 return mtoken;
2818
2819         switch (mono_metadata_token_table (mtoken)) {
2820         case MONO_TABLE_MEMBERREF:
2821                 mtoken = (mono_metadata_token_index (mtoken) << MONO_METHODDEFORREF_BITS) | MONO_METHODDEFORREF_METHODREF;
2822                 break;
2823         case MONO_TABLE_METHOD:
2824                 mtoken = (mono_metadata_token_index (mtoken) << MONO_METHODDEFORREF_BITS) | MONO_METHODDEFORREF_METHODDEF;
2825                 break;
2826         default:
2827                 g_assert_not_reached ();
2828         }
2829
2830         sig = encode_generic_method_sig (assembly, mono_method_get_context (method));
2831
2832         if (assembly->save) {
2833                 alloc_table (table, table->rows + 1);
2834                 values = table->values + table->next_idx * MONO_METHODSPEC_SIZE;
2835                 values [MONO_METHODSPEC_METHOD] = mtoken;
2836                 values [MONO_METHODSPEC_SIGNATURE] = sig;
2837         }
2838
2839         token = MONO_TOKEN_METHOD_SPEC | table->next_idx;
2840         table->next_idx ++;
2841
2842         return token;
2843 }
2844
2845 static guint32
2846 mono_image_get_methodspec_token (MonoDynamicImage *assembly, MonoMethod *method)
2847 {
2848         MonoMethodInflated *imethod;
2849         guint32 token;
2850         
2851         token = GPOINTER_TO_UINT (g_hash_table_lookup (assembly->handleref, method));
2852         if (token)
2853                 return token;
2854
2855         g_assert (method->is_inflated);
2856         imethod = (MonoMethodInflated *) method;
2857
2858         if (mono_method_signature (imethod->declaring)->generic_param_count) {
2859                 token = method_encode_methodspec (assembly, method);
2860         } else {
2861                 guint32 sig = method_encode_signature (
2862                         assembly, mono_method_signature (imethod->declaring));
2863                 token = mono_image_get_memberref_token (
2864                         assembly, &method->klass->byval_arg, method->name, sig);
2865         }
2866
2867         g_hash_table_insert (assembly->handleref, method, GUINT_TO_POINTER(token));
2868         return token;
2869 }
2870
2871 static guint32
2872 mono_image_get_inflated_method_token (MonoDynamicImage *assembly, MonoMethod *m)
2873 {
2874         MonoMethodInflated *imethod = (MonoMethodInflated *) m;
2875         guint32 sig, token;
2876
2877         sig = method_encode_signature (assembly, mono_method_signature (imethod->declaring));
2878         token = mono_image_get_memberref_token (
2879                 assembly, &m->klass->byval_arg, m->name, sig);
2880
2881         return token;
2882 }
2883
2884 static guint32
2885 create_generic_typespec (MonoDynamicImage *assembly, MonoReflectionTypeBuilder *tb)
2886 {
2887         MonoDynamicTable *table;
2888         MonoClass *klass;
2889         MonoType *type;
2890         guint32 *values;
2891         guint32 token;
2892         SigBuffer buf;
2893         int count, i;
2894
2895         /*
2896          * We're creating a TypeSpec for the TypeBuilder of a generic type declaration,
2897          * ie. what we'd normally use as the generic type in a TypeSpec signature.
2898          * Because of this, we must not insert it into the `typeref' hash table.
2899          */
2900         type = mono_reflection_type_get_handle ((MonoReflectionType*)tb);
2901         token = GPOINTER_TO_UINT (g_hash_table_lookup (assembly->typespec, type));
2902         if (token)
2903                 return token;
2904
2905         sigbuffer_init (&buf, 32);
2906
2907         g_assert (tb->generic_params);
2908         klass = mono_class_from_mono_type (type);
2909
2910         if (tb->generic_container)
2911                 mono_reflection_create_generic_class (tb);
2912
2913         sigbuffer_add_value (&buf, MONO_TYPE_GENERICINST);
2914         g_assert (klass->generic_container);
2915         sigbuffer_add_value (&buf, klass->byval_arg.type);
2916         sigbuffer_add_value (&buf, mono_image_typedef_or_ref_full (assembly, &klass->byval_arg, FALSE));
2917
2918         count = mono_array_length (tb->generic_params);
2919         sigbuffer_add_value (&buf, count);
2920         for (i = 0; i < count; i++) {
2921                 MonoReflectionGenericParam *gparam;
2922
2923                 gparam = mono_array_get (tb->generic_params, MonoReflectionGenericParam *, i);
2924
2925                 encode_type (assembly, mono_reflection_type_get_handle ((MonoReflectionType*)gparam), &buf);
2926         }
2927
2928         table = &assembly->tables [MONO_TABLE_TYPESPEC];
2929
2930         if (assembly->save) {
2931                 token = sigbuffer_add_to_blob_cached (assembly, &buf);
2932                 alloc_table (table, table->rows + 1);
2933                 values = table->values + table->next_idx * MONO_TYPESPEC_SIZE;
2934                 values [MONO_TYPESPEC_SIGNATURE] = token;
2935         }
2936         sigbuffer_free (&buf);
2937
2938         token = MONO_TYPEDEFORREF_TYPESPEC | (table->next_idx << MONO_TYPEDEFORREF_BITS);
2939         g_hash_table_insert (assembly->typespec, type, GUINT_TO_POINTER(token));
2940         table->next_idx ++;
2941         return token;
2942 }
2943
2944 /*
2945  * Return a copy of TYPE, adding the custom modifiers in MODREQ and MODOPT.
2946  */
2947 static MonoType*
2948 add_custom_modifiers (MonoDynamicImage *assembly, MonoType *type, MonoArray *modreq, MonoArray *modopt)
2949 {
2950         int i, count, len, pos;
2951         MonoType *t;
2952
2953         count = 0;
2954         if (modreq)
2955                 count += mono_array_length (modreq);
2956         if (modopt)
2957                 count += mono_array_length (modopt);
2958
2959         if (count == 0)
2960                 return mono_metadata_type_dup (NULL, type);
2961
2962         len = MONO_SIZEOF_TYPE + ((gint32)count) * sizeof (MonoCustomMod);
2963         t = g_malloc (len);
2964         memcpy (t, type, MONO_SIZEOF_TYPE);
2965
2966         t->num_mods = count;
2967         pos = 0;
2968         if (modreq) {
2969                 for (i = 0; i < mono_array_length (modreq); ++i) {
2970                         MonoType *mod = mono_type_array_get_and_resolve (modreq, i);
2971                         t->modifiers [pos].required = 1;
2972                         t->modifiers [pos].token = mono_image_typedef_or_ref (assembly, mod);
2973                         pos ++;
2974                 }
2975         }
2976         if (modopt) {
2977                 for (i = 0; i < mono_array_length (modopt); ++i) {
2978                         MonoType *mod = mono_type_array_get_and_resolve (modopt, i);
2979                         t->modifiers [pos].required = 0;
2980                         t->modifiers [pos].token = mono_image_typedef_or_ref (assembly, mod);
2981                         pos ++;
2982                 }
2983         }
2984
2985         return t;
2986 }
2987
2988 static guint32
2989 mono_image_get_generic_field_token (MonoDynamicImage *assembly, MonoReflectionFieldBuilder *fb)
2990 {
2991         MonoDynamicTable *table;
2992         MonoClass *klass;
2993         MonoType *custom = NULL;
2994         guint32 *values;
2995         guint32 token, pclass, parent, sig;
2996         gchar *name;
2997
2998         token = GPOINTER_TO_UINT (g_hash_table_lookup (assembly->handleref, fb));
2999         if (token)
3000                 return token;
3001
3002         klass = mono_class_from_mono_type (mono_reflection_type_get_handle (fb->typeb));
3003         name = mono_string_to_utf8 (fb->name);
3004
3005         /* fb->type does not include the custom modifiers */
3006         /* FIXME: We should do this in one place when a fieldbuilder is created */
3007         if (fb->modreq || fb->modopt) {
3008                 custom = add_custom_modifiers (assembly, mono_reflection_type_get_handle ((MonoReflectionType*)fb->type), fb->modreq, fb->modopt);
3009                 sig = fieldref_encode_signature (assembly, custom);
3010                 g_free (custom);
3011         } else {
3012                 sig = fieldref_encode_signature (assembly, mono_reflection_type_get_handle ((MonoReflectionType*)fb->type));
3013         }
3014
3015         parent = create_generic_typespec (assembly, (MonoReflectionTypeBuilder *) fb->typeb);
3016         g_assert ((parent & MONO_TYPEDEFORREF_MASK) == MONO_TYPEDEFORREF_TYPESPEC);
3017         
3018         pclass = MONO_MEMBERREF_PARENT_TYPESPEC;
3019         parent >>= MONO_TYPEDEFORREF_BITS;
3020
3021         table = &assembly->tables [MONO_TABLE_MEMBERREF];
3022
3023         if (assembly->save) {
3024                 alloc_table (table, table->rows + 1);
3025                 values = table->values + table->next_idx * MONO_MEMBERREF_SIZE;
3026                 values [MONO_MEMBERREF_CLASS] = pclass | (parent << MONO_MEMBERREF_PARENT_BITS);
3027                 values [MONO_MEMBERREF_NAME] = string_heap_insert (&assembly->sheap, name);
3028                 values [MONO_MEMBERREF_SIGNATURE] = sig;
3029         }
3030
3031         token = MONO_TOKEN_MEMBER_REF | table->next_idx;
3032         table->next_idx ++;
3033         g_hash_table_insert (assembly->handleref, fb, GUINT_TO_POINTER(token));
3034         g_free (name);
3035         return token;
3036 }
3037
3038 static guint32
3039 mono_reflection_encode_sighelper (MonoDynamicImage *assembly, MonoReflectionSigHelper *helper)
3040 {
3041         SigBuffer buf;
3042         guint32 nargs;
3043         guint32 size;
3044         guint32 i, idx;
3045
3046         if (!assembly->save)
3047                 return 0;
3048
3049         /* FIXME: this means SignatureHelper.SignatureHelpType.HELPER_METHOD */
3050         g_assert (helper->type == 2);
3051
3052         if (helper->arguments)
3053                 nargs = mono_array_length (helper->arguments);
3054         else
3055                 nargs = 0;
3056
3057         size = 10 + (nargs * 10);
3058         
3059         sigbuffer_init (&buf, 32);
3060
3061         /* Encode calling convention */
3062         /* Change Any to Standard */
3063         if ((helper->call_conv & 0x03) == 0x03)
3064                 helper->call_conv = 0x01;
3065         /* explicit_this implies has_this */
3066         if (helper->call_conv & 0x40)
3067                 helper->call_conv &= 0x20;
3068
3069         if (helper->call_conv == 0) { /* Unmanaged */
3070                 idx = helper->unmanaged_call_conv - 1;
3071         } else {
3072                 /* Managed */
3073                 idx = helper->call_conv & 0x60; /* has_this + explicit_this */
3074                 if (helper->call_conv & 0x02) /* varargs */
3075                         idx += 0x05;
3076         }
3077
3078         sigbuffer_add_byte (&buf, idx);
3079         sigbuffer_add_value (&buf, nargs);
3080         encode_reflection_type (assembly, helper->return_type, &buf);
3081         for (i = 0; i < nargs; ++i) {
3082                 MonoArray *modreqs = NULL;
3083                 MonoArray *modopts = NULL;
3084                 MonoReflectionType *pt;
3085
3086                 if (helper->modreqs && (i < mono_array_length (helper->modreqs)))
3087                         modreqs = mono_array_get (helper->modreqs, MonoArray*, i);
3088                 if (helper->modopts && (i < mono_array_length (helper->modopts)))
3089                         modopts = mono_array_get (helper->modopts, MonoArray*, i);
3090
3091                 encode_custom_modifiers (assembly, modreqs, modopts, &buf);
3092                 pt = mono_array_get (helper->arguments, MonoReflectionType*, i);
3093                 encode_reflection_type (assembly, pt, &buf);
3094         }
3095         idx = sigbuffer_add_to_blob_cached (assembly, &buf);
3096         sigbuffer_free (&buf);
3097
3098         return idx;
3099 }
3100
3101 static guint32 
3102 mono_image_get_sighelper_token (MonoDynamicImage *assembly, MonoReflectionSigHelper *helper)
3103 {
3104         guint32 idx;
3105         MonoDynamicTable *table;
3106         guint32 *values;
3107
3108         table = &assembly->tables [MONO_TABLE_STANDALONESIG];
3109         idx = table->next_idx ++;
3110         table->rows ++;
3111         alloc_table (table, table->rows);
3112         values = table->values + idx * MONO_STAND_ALONE_SIGNATURE_SIZE;
3113
3114         values [MONO_STAND_ALONE_SIGNATURE] =
3115                 mono_reflection_encode_sighelper (assembly, helper);
3116
3117         return idx;
3118 }
3119
3120 static int
3121 reflection_cc_to_file (int call_conv) {
3122         switch (call_conv & 0x3) {
3123         case 0:
3124         case 1: return MONO_CALL_DEFAULT;
3125         case 2: return MONO_CALL_VARARG;
3126         default:
3127                 g_assert_not_reached ();
3128         }
3129         return 0;
3130 }
3131 #endif /* !DISABLE_REFLECTION_EMIT */
3132
3133 typedef struct {
3134         MonoType *parent;
3135         MonoMethodSignature *sig;
3136         char *name;
3137         guint32 token;
3138 } ArrayMethod;
3139
3140 #ifndef DISABLE_REFLECTION_EMIT
3141 static guint32
3142 mono_image_get_array_token (MonoDynamicImage *assembly, MonoReflectionArrayMethod *m)
3143 {
3144         guint32 nparams, i;
3145         GList *tmp;
3146         char *name;
3147         MonoMethodSignature *sig;
3148         ArrayMethod *am;
3149         MonoType *mtype;
3150
3151         name = mono_string_to_utf8 (m->name);
3152         nparams = mono_array_length (m->parameters);
3153         sig = g_malloc0 (MONO_SIZEOF_METHOD_SIGNATURE + sizeof (MonoType*) * nparams);
3154         sig->hasthis = 1;
3155         sig->sentinelpos = -1;
3156         sig->call_convention = reflection_cc_to_file (m->call_conv);
3157         sig->param_count = nparams;
3158         sig->ret = m->ret ? mono_reflection_type_get_handle (m->ret): &mono_defaults.void_class->byval_arg;
3159         mtype = mono_reflection_type_get_handle (m->parent);
3160         for (i = 0; i < nparams; ++i)
3161                 sig->params [i] = mono_type_array_get_and_resolve (m->parameters, i);
3162
3163         for (tmp = assembly->array_methods; tmp; tmp = tmp->next) {
3164                 am = tmp->data;
3165                 if (strcmp (name, am->name) == 0 && 
3166                                 mono_metadata_type_equal (am->parent, mtype) &&
3167                                 mono_metadata_signature_equal (am->sig, sig)) {
3168                         g_free (name);
3169                         g_free (sig);
3170                         m->table_idx = am->token & 0xffffff;
3171                         return am->token;
3172                 }
3173         }
3174         am = g_new0 (ArrayMethod, 1);
3175         am->name = name;
3176         am->sig = sig;
3177         am->parent = mtype;
3178         am->token = mono_image_get_memberref_token (assembly, am->parent, name,
3179                 method_encode_signature (assembly, sig));
3180         assembly->array_methods = g_list_prepend (assembly->array_methods, am);
3181         m->table_idx = am->token & 0xffffff;
3182         return am->token;
3183 }
3184 #endif
3185
3186 /*
3187  * Insert into the metadata tables all the info about the TypeBuilder tb.
3188  * Data in the tables is inserted in a predefined order, since some tables need to be sorted.
3189  */
3190 static void
3191 mono_image_get_type_info (MonoDomain *domain, MonoReflectionTypeBuilder *tb, MonoDynamicImage *assembly)
3192 {
3193         MonoDynamicTable *table;
3194         guint *values;
3195         int i, is_object = 0, is_system = 0;
3196         char *n;
3197
3198         table = &assembly->tables [MONO_TABLE_TYPEDEF];
3199         values = table->values + tb->table_idx * MONO_TYPEDEF_SIZE;
3200         values [MONO_TYPEDEF_FLAGS] = tb->attrs;
3201         n = mono_string_to_utf8 (tb->name);
3202         if (strcmp (n, "Object") == 0)
3203                 is_object++;
3204         values [MONO_TYPEDEF_NAME] = string_heap_insert (&assembly->sheap, n);
3205         g_free (n);
3206         n = mono_string_to_utf8 (tb->nspace);
3207         if (strcmp (n, "System") == 0)
3208                 is_system++;
3209         values [MONO_TYPEDEF_NAMESPACE] = string_heap_insert (&assembly->sheap, n);
3210         g_free (n);
3211         if (tb->parent && !(is_system && is_object) && 
3212                         !(tb->attrs & TYPE_ATTRIBUTE_INTERFACE)) { /* interfaces don't have a parent */
3213                 values [MONO_TYPEDEF_EXTENDS] = mono_image_typedef_or_ref (assembly, mono_reflection_type_get_handle ((MonoReflectionType*)tb->parent));
3214         } else {
3215                 values [MONO_TYPEDEF_EXTENDS] = 0;
3216         }
3217         values [MONO_TYPEDEF_FIELD_LIST] = assembly->tables [MONO_TABLE_FIELD].next_idx;
3218         values [MONO_TYPEDEF_METHOD_LIST] = assembly->tables [MONO_TABLE_METHOD].next_idx;
3219
3220         /*
3221          * if we have explicitlayout or sequentiallayouts, output data in the
3222          * ClassLayout table.
3223          */
3224         if (((tb->attrs & TYPE_ATTRIBUTE_LAYOUT_MASK) != TYPE_ATTRIBUTE_AUTO_LAYOUT) &&
3225                         ((tb->class_size > 0) || (tb->packing_size > 0))) {
3226                 table = &assembly->tables [MONO_TABLE_CLASSLAYOUT];
3227                 table->rows++;
3228                 alloc_table (table, table->rows);
3229                 values = table->values + table->rows * MONO_CLASS_LAYOUT_SIZE;
3230                 values [MONO_CLASS_LAYOUT_PARENT] = tb->table_idx;
3231                 values [MONO_CLASS_LAYOUT_CLASS_SIZE] = tb->class_size;
3232                 values [MONO_CLASS_LAYOUT_PACKING_SIZE] = tb->packing_size;
3233         }
3234
3235         /* handle interfaces */
3236         if (tb->interfaces) {
3237                 table = &assembly->tables [MONO_TABLE_INTERFACEIMPL];
3238                 i = table->rows;
3239                 table->rows += mono_array_length (tb->interfaces);
3240                 alloc_table (table, table->rows);
3241                 values = table->values + (i + 1) * MONO_INTERFACEIMPL_SIZE;
3242                 for (i = 0; i < mono_array_length (tb->interfaces); ++i) {
3243                         MonoReflectionType* iface = (MonoReflectionType*) mono_array_get (tb->interfaces, gpointer, i);
3244                         values [MONO_INTERFACEIMPL_CLASS] = tb->table_idx;
3245                         values [MONO_INTERFACEIMPL_INTERFACE] = mono_image_typedef_or_ref (assembly, mono_reflection_type_get_handle (iface));
3246                         values += MONO_INTERFACEIMPL_SIZE;
3247                 }
3248         }
3249
3250         /* handle fields */
3251         if (tb->fields) {
3252                 table = &assembly->tables [MONO_TABLE_FIELD];
3253                 table->rows += tb->num_fields;
3254                 alloc_table (table, table->rows);
3255                 for (i = 0; i < tb->num_fields; ++i)
3256                         mono_image_get_field_info (
3257                                 mono_array_get (tb->fields, MonoReflectionFieldBuilder*, i), assembly);
3258         }
3259
3260         /* handle constructors */
3261         if (tb->ctors) {
3262                 table = &assembly->tables [MONO_TABLE_METHOD];
3263                 table->rows += mono_array_length (tb->ctors);
3264                 alloc_table (table, table->rows);
3265                 for (i = 0; i < mono_array_length (tb->ctors); ++i)
3266                         mono_image_get_ctor_info (domain,
3267                                 mono_array_get (tb->ctors, MonoReflectionCtorBuilder*, i), assembly);
3268         }
3269
3270         /* handle methods */
3271         if (tb->methods) {
3272                 table = &assembly->tables [MONO_TABLE_METHOD];
3273                 table->rows += tb->num_methods;
3274                 alloc_table (table, table->rows);
3275                 for (i = 0; i < tb->num_methods; ++i)
3276                         mono_image_get_method_info (
3277                                 mono_array_get (tb->methods, MonoReflectionMethodBuilder*, i), assembly);
3278         }
3279
3280         /* Do the same with properties etc.. */
3281         if (tb->events && mono_array_length (tb->events)) {
3282                 table = &assembly->tables [MONO_TABLE_EVENT];
3283                 table->rows += mono_array_length (tb->events);
3284                 alloc_table (table, table->rows);
3285                 table = &assembly->tables [MONO_TABLE_EVENTMAP];
3286                 table->rows ++;
3287                 alloc_table (table, table->rows);
3288                 values = table->values + table->rows * MONO_EVENT_MAP_SIZE;
3289                 values [MONO_EVENT_MAP_PARENT] = tb->table_idx;
3290                 values [MONO_EVENT_MAP_EVENTLIST] = assembly->tables [MONO_TABLE_EVENT].next_idx;
3291                 for (i = 0; i < mono_array_length (tb->events); ++i)
3292                         mono_image_get_event_info (
3293                                 mono_array_get (tb->events, MonoReflectionEventBuilder*, i), assembly);
3294         }
3295         if (tb->properties && mono_array_length (tb->properties)) {
3296                 table = &assembly->tables [MONO_TABLE_PROPERTY];
3297                 table->rows += mono_array_length (tb->properties);
3298                 alloc_table (table, table->rows);
3299                 table = &assembly->tables [MONO_TABLE_PROPERTYMAP];
3300                 table->rows ++;
3301                 alloc_table (table, table->rows);
3302                 values = table->values + table->rows * MONO_PROPERTY_MAP_SIZE;
3303                 values [MONO_PROPERTY_MAP_PARENT] = tb->table_idx;
3304                 values [MONO_PROPERTY_MAP_PROPERTY_LIST] = assembly->tables [MONO_TABLE_PROPERTY].next_idx;
3305                 for (i = 0; i < mono_array_length (tb->properties); ++i)
3306                         mono_image_get_property_info (
3307                                 mono_array_get (tb->properties, MonoReflectionPropertyBuilder*, i), assembly);
3308         }
3309
3310         /* handle generic parameters */
3311         if (tb->generic_params) {
3312                 table = &assembly->tables [MONO_TABLE_GENERICPARAM];
3313                 table->rows += mono_array_length (tb->generic_params);
3314                 alloc_table (table, table->rows);
3315                 for (i = 0; i < mono_array_length (tb->generic_params); ++i) {
3316                         guint32 owner = MONO_TYPEORMETHOD_TYPE | (tb->table_idx << MONO_TYPEORMETHOD_BITS);
3317
3318                         mono_image_get_generic_param_info (
3319                                 mono_array_get (tb->generic_params, MonoReflectionGenericParam*, i), owner, assembly);
3320                 }
3321         }
3322
3323         mono_image_add_decl_security (assembly, 
3324                 mono_metadata_make_token (MONO_TABLE_TYPEDEF, tb->table_idx), tb->permissions);
3325
3326         if (tb->subtypes) {
3327                 MonoDynamicTable *ntable;
3328                 
3329                 ntable = &assembly->tables [MONO_TABLE_NESTEDCLASS];
3330                 ntable->rows += mono_array_length (tb->subtypes);
3331                 alloc_table (ntable, ntable->rows);
3332                 values = ntable->values + ntable->next_idx * MONO_NESTED_CLASS_SIZE;
3333
3334                 for (i = 0; i < mono_array_length (tb->subtypes); ++i) {
3335                         MonoReflectionTypeBuilder *subtype = mono_array_get (tb->subtypes, MonoReflectionTypeBuilder*, i);
3336
3337                         values [MONO_NESTED_CLASS_NESTED] = subtype->table_idx;
3338                         values [MONO_NESTED_CLASS_ENCLOSING] = tb->table_idx;
3339                         /*g_print ("nesting %s (%d) in %s (%d) (rows %d/%d)\n",
3340                                 mono_string_to_utf8 (subtype->name), subtype->table_idx,
3341                                 mono_string_to_utf8 (tb->name), tb->table_idx,
3342                                 ntable->next_idx, ntable->rows);*/
3343                         values += MONO_NESTED_CLASS_SIZE;
3344                         ntable->next_idx++;
3345                 }
3346         }
3347 }
3348
3349 static void
3350 collect_types (GPtrArray *types, MonoReflectionTypeBuilder *type)
3351 {
3352         int i;
3353
3354         g_ptr_array_add (types, type); /* FIXME: GC object added to unmanaged memory */
3355
3356         if (!type->subtypes)
3357                 return;
3358
3359         for (i = 0; i < mono_array_length (type->subtypes); ++i) {
3360                 MonoReflectionTypeBuilder *subtype = mono_array_get (type->subtypes, MonoReflectionTypeBuilder*, i);
3361                 collect_types (types, subtype);
3362         }
3363 }
3364
3365 static gint
3366 compare_types_by_table_idx (MonoReflectionTypeBuilder **type1, MonoReflectionTypeBuilder **type2)
3367 {
3368         if ((*type1)->table_idx < (*type2)->table_idx)
3369                 return -1;
3370         else
3371                 if ((*type1)->table_idx > (*type2)->table_idx)
3372                         return 1;
3373         else
3374                 return 0;
3375 }
3376
3377 static void
3378 params_add_cattrs (MonoDynamicImage *assembly, MonoArray *pinfo) {
3379         int i;
3380
3381         if (!pinfo)
3382                 return;
3383         for (i = 0; i < mono_array_length (pinfo); ++i) {
3384                 MonoReflectionParamBuilder *pb;
3385                 pb = mono_array_get (pinfo, MonoReflectionParamBuilder *, i);
3386                 if (!pb)
3387                         continue;
3388                 mono_image_add_cattrs (assembly, pb->table_idx, MONO_CUSTOM_ATTR_PARAMDEF, pb->cattrs);
3389         }
3390 }
3391
3392 static void
3393 type_add_cattrs (MonoDynamicImage *assembly, MonoReflectionTypeBuilder *tb) {
3394         int i;
3395         
3396         mono_image_add_cattrs (assembly, tb->table_idx, MONO_CUSTOM_ATTR_TYPEDEF, tb->cattrs);
3397         if (tb->fields) {
3398                 for (i = 0; i < tb->num_fields; ++i) {
3399                         MonoReflectionFieldBuilder* fb;
3400                         fb = mono_array_get (tb->fields, MonoReflectionFieldBuilder*, i);
3401                         mono_image_add_cattrs (assembly, fb->table_idx, MONO_CUSTOM_ATTR_FIELDDEF, fb->cattrs);
3402                 }
3403         }
3404         if (tb->events) {
3405                 for (i = 0; i < mono_array_length (tb->events); ++i) {
3406                         MonoReflectionEventBuilder* eb;
3407                         eb = mono_array_get (tb->events, MonoReflectionEventBuilder*, i);
3408                         mono_image_add_cattrs (assembly, eb->table_idx, MONO_CUSTOM_ATTR_EVENT, eb->cattrs);
3409                 }
3410         }
3411         if (tb->properties) {
3412                 for (i = 0; i < mono_array_length (tb->properties); ++i) {
3413                         MonoReflectionPropertyBuilder* pb;
3414                         pb = mono_array_get (tb->properties, MonoReflectionPropertyBuilder*, i);
3415                         mono_image_add_cattrs (assembly, pb->table_idx, MONO_CUSTOM_ATTR_PROPERTY, pb->cattrs);
3416                 }
3417         }
3418         if (tb->ctors) {
3419                 for (i = 0; i < mono_array_length (tb->ctors); ++i) {
3420                         MonoReflectionCtorBuilder* cb;
3421                         cb = mono_array_get (tb->ctors, MonoReflectionCtorBuilder*, i);
3422                         mono_image_add_cattrs (assembly, cb->table_idx, MONO_CUSTOM_ATTR_METHODDEF, cb->cattrs);
3423                         params_add_cattrs (assembly, cb->pinfo);
3424                 }
3425         }
3426
3427         if (tb->methods) {
3428                 for (i = 0; i < tb->num_methods; ++i) {
3429                         MonoReflectionMethodBuilder* mb;
3430                         mb = mono_array_get (tb->methods, MonoReflectionMethodBuilder*, i);
3431                         mono_image_add_cattrs (assembly, mb->table_idx, MONO_CUSTOM_ATTR_METHODDEF, mb->cattrs);
3432                         params_add_cattrs (assembly, mb->pinfo);
3433                 }
3434         }
3435
3436         if (tb->subtypes) {
3437                 for (i = 0; i < mono_array_length (tb->subtypes); ++i)
3438                         type_add_cattrs (assembly, mono_array_get (tb->subtypes, MonoReflectionTypeBuilder*, i));
3439         }
3440 }
3441
3442 static void
3443 module_add_cattrs (MonoDynamicImage *assembly, MonoReflectionModuleBuilder *moduleb)
3444 {
3445         int i;
3446         
3447         mono_image_add_cattrs (assembly, moduleb->table_idx, MONO_CUSTOM_ATTR_MODULE, moduleb->cattrs);
3448
3449         if (moduleb->global_methods) {
3450                 for (i = 0; i < mono_array_length (moduleb->global_methods); ++i) {
3451                         MonoReflectionMethodBuilder* mb = mono_array_get (moduleb->global_methods, MonoReflectionMethodBuilder*, i);
3452                         mono_image_add_cattrs (assembly, mb->table_idx, MONO_CUSTOM_ATTR_METHODDEF, mb->cattrs);
3453                         params_add_cattrs (assembly, mb->pinfo);
3454                 }
3455         }
3456
3457         if (moduleb->global_fields) {
3458                 for (i = 0; i < mono_array_length (moduleb->global_fields); ++i) {
3459                         MonoReflectionFieldBuilder *fb = mono_array_get (moduleb->global_fields, MonoReflectionFieldBuilder*, i);
3460                         mono_image_add_cattrs (assembly, fb->table_idx, MONO_CUSTOM_ATTR_FIELDDEF, fb->cattrs);
3461                 }
3462         }
3463         
3464         if (moduleb->types) {
3465                 for (i = 0; i < moduleb->num_types; ++i)
3466                         type_add_cattrs (assembly, mono_array_get (moduleb->types, MonoReflectionTypeBuilder*, i));
3467         }
3468 }
3469
3470 static void
3471 mono_image_fill_file_table (MonoDomain *domain, MonoReflectionModule *module, MonoDynamicImage *assembly)
3472 {
3473         MonoDynamicTable *table;
3474         guint32 *values;
3475         char blob_size [6];
3476         guchar hash [20];
3477         char *b = blob_size;
3478         char *dir, *path;
3479
3480         table = &assembly->tables [MONO_TABLE_FILE];
3481         table->rows++;
3482         alloc_table (table, table->rows);
3483         values = table->values + table->next_idx * MONO_FILE_SIZE;
3484         values [MONO_FILE_FLAGS] = FILE_CONTAINS_METADATA;
3485         values [MONO_FILE_NAME] = string_heap_insert (&assembly->sheap, module->image->module_name);
3486         if (module->image->dynamic) {
3487                 /* This depends on the fact that the main module is emitted last */
3488                 dir = mono_string_to_utf8 (((MonoReflectionModuleBuilder*)module)->assemblyb->dir);
3489                 path = g_strdup_printf ("%s%c%s", dir, G_DIR_SEPARATOR, module->image->module_name);
3490         } else {
3491                 dir = NULL;
3492                 path = g_strdup (module->image->name);
3493         }
3494         mono_sha1_get_digest_from_file (path, hash);
3495         g_free (dir);
3496         g_free (path);
3497         mono_metadata_encode_value (20, b, &b);
3498         values [MONO_FILE_HASH_VALUE] = mono_image_add_stream_data (&assembly->blob, blob_size, b-blob_size);
3499         mono_image_add_stream_data (&assembly->blob, (char*)hash, 20);
3500         table->next_idx ++;
3501 }
3502
3503 static void
3504 mono_image_fill_module_table (MonoDomain *domain, MonoReflectionModuleBuilder *mb, MonoDynamicImage *assembly)
3505 {
3506         MonoDynamicTable *table;
3507         int i;
3508
3509         table = &assembly->tables [MONO_TABLE_MODULE];
3510         mb->table_idx = table->next_idx ++;
3511         table->values [mb->table_idx * MONO_MODULE_SIZE + MONO_MODULE_NAME] = string_heap_insert_mstring (&assembly->sheap, mb->module.name);
3512         i = mono_image_add_stream_data (&assembly->guid, mono_array_addr (mb->guid, char, 0), 16);
3513         i /= 16;
3514         ++i;
3515         table->values [mb->table_idx * MONO_MODULE_SIZE + MONO_MODULE_GENERATION] = 0;
3516         table->values [mb->table_idx * MONO_MODULE_SIZE + MONO_MODULE_MVID] = i;
3517         table->values [mb->table_idx * MONO_MODULE_SIZE + MONO_MODULE_ENC] = 0;
3518         table->values [mb->table_idx * MONO_MODULE_SIZE + MONO_MODULE_ENCBASE] = 0;
3519 }
3520
3521 static guint32
3522 mono_image_fill_export_table_from_class (MonoDomain *domain, MonoClass *klass,
3523         guint32 module_index, guint32 parent_index, MonoDynamicImage *assembly)
3524 {
3525         MonoDynamicTable *table;
3526         guint32 *values;
3527         guint32 visib, res;
3528
3529         visib = klass->flags & TYPE_ATTRIBUTE_VISIBILITY_MASK;
3530         if (! ((visib & TYPE_ATTRIBUTE_PUBLIC) || (visib & TYPE_ATTRIBUTE_NESTED_PUBLIC)))
3531                 return 0;
3532
3533         table = &assembly->tables [MONO_TABLE_EXPORTEDTYPE];
3534         table->rows++;
3535         alloc_table (table, table->rows);
3536         values = table->values + table->next_idx * MONO_EXP_TYPE_SIZE;
3537
3538         values [MONO_EXP_TYPE_FLAGS] = klass->flags;
3539         values [MONO_EXP_TYPE_TYPEDEF] = klass->type_token;
3540         if (klass->nested_in)
3541                 values [MONO_EXP_TYPE_IMPLEMENTATION] = (parent_index << MONO_IMPLEMENTATION_BITS) + MONO_IMPLEMENTATION_EXP_TYPE;
3542         else
3543                 values [MONO_EXP_TYPE_IMPLEMENTATION] = (module_index << MONO_IMPLEMENTATION_BITS) + MONO_IMPLEMENTATION_FILE;
3544         values [MONO_EXP_TYPE_NAME] = string_heap_insert (&assembly->sheap, klass->name);
3545         values [MONO_EXP_TYPE_NAMESPACE] = string_heap_insert (&assembly->sheap, klass->name_space);
3546
3547         res = table->next_idx;
3548
3549         table->next_idx ++;
3550
3551         /* Emit nested types */
3552         if (klass->ext && klass->ext->nested_classes) {
3553                 GList *tmp;
3554
3555                 for (tmp = klass->ext->nested_classes; tmp; tmp = tmp->next)
3556                         mono_image_fill_export_table_from_class (domain, tmp->data, module_index, table->next_idx - 1, assembly);
3557         }
3558
3559         return res;
3560 }
3561
3562 static void
3563 mono_image_fill_export_table (MonoDomain *domain, MonoReflectionTypeBuilder *tb,
3564         guint32 module_index, guint32 parent_index, MonoDynamicImage *assembly)
3565 {
3566         MonoClass *klass;
3567         guint32 idx, i;
3568
3569         klass = mono_class_from_mono_type (mono_reflection_type_get_handle ((MonoReflectionType*)tb));
3570
3571         klass->type_token = mono_metadata_make_token (MONO_TABLE_TYPEDEF, tb->table_idx);
3572
3573         idx = mono_image_fill_export_table_from_class (domain, klass, module_index, 
3574                                                                                                    parent_index, assembly);
3575
3576         /* 
3577          * Emit nested types
3578          * We need to do this ourselves since klass->nested_classes is not set up.
3579          */
3580         if (tb->subtypes) {
3581                 for (i = 0; i < mono_array_length (tb->subtypes); ++i)
3582                         mono_image_fill_export_table (domain, mono_array_get (tb->subtypes, MonoReflectionTypeBuilder*, i), module_index, idx, assembly);
3583         }
3584 }
3585
3586 static void
3587 mono_image_fill_export_table_from_module (MonoDomain *domain, MonoReflectionModule *module,
3588         guint32 module_index, MonoDynamicImage *assembly)
3589 {
3590         MonoImage *image = module->image;
3591         MonoTableInfo  *t;
3592         guint32 i;
3593
3594         t = &image->tables [MONO_TABLE_TYPEDEF];
3595
3596         for (i = 0; i < t->rows; ++i) {
3597                 MonoClass *klass = mono_class_get (image, mono_metadata_make_token (MONO_TABLE_TYPEDEF, i + 1));
3598
3599                 if (klass->flags & TYPE_ATTRIBUTE_PUBLIC)
3600                         mono_image_fill_export_table_from_class (domain, klass, module_index, 0, assembly);
3601         }
3602 }
3603
3604 static guint32
3605 add_exported_type (MonoReflectionAssemblyBuilder *assemblyb, MonoDynamicImage *assembly, MonoClass *klass)
3606 {
3607         MonoDynamicTable *table;
3608         guint32 *values;
3609         guint32 scope, idx, res, impl;
3610         gboolean forwarder = TRUE;
3611
3612         if (klass->nested_in) {
3613                 impl = add_exported_type (assemblyb, assembly, klass->nested_in);
3614                 forwarder = FALSE;
3615         } else {
3616                 scope = resolution_scope_from_image (assembly, klass->image);
3617                 g_assert ((scope & MONO_RESOLTION_SCOPE_MASK) == MONO_RESOLTION_SCOPE_ASSEMBLYREF);
3618                 idx = scope >> MONO_RESOLTION_SCOPE_BITS;
3619                 impl = (idx << MONO_IMPLEMENTATION_BITS) + MONO_IMPLEMENTATION_ASSEMBLYREF;
3620         }
3621
3622         table = &assembly->tables [MONO_TABLE_EXPORTEDTYPE];
3623
3624         table->rows++;
3625         alloc_table (table, table->rows);
3626         values = table->values + table->next_idx * MONO_EXP_TYPE_SIZE;
3627
3628         values [MONO_EXP_TYPE_FLAGS] = forwarder ? TYPE_ATTRIBUTE_FORWARDER : 0;
3629         values [MONO_EXP_TYPE_TYPEDEF] = 0;
3630         values [MONO_EXP_TYPE_IMPLEMENTATION] = impl;
3631         values [MONO_EXP_TYPE_NAME] = string_heap_insert (&assembly->sheap, klass->name);
3632         values [MONO_EXP_TYPE_NAMESPACE] = string_heap_insert (&assembly->sheap, klass->name_space);
3633
3634         res = (table->next_idx << MONO_IMPLEMENTATION_BITS) + MONO_IMPLEMENTATION_EXP_TYPE;
3635
3636         table->next_idx++;
3637
3638         return res;
3639 }
3640
3641 static void
3642 mono_image_fill_export_table_from_type_forwarders (MonoReflectionAssemblyBuilder *assemblyb, MonoDynamicImage *assembly)
3643 {
3644         MonoClass *klass;
3645         int i;
3646
3647         if (!assemblyb->type_forwarders)
3648                 return;
3649
3650         for (i = 0; i < mono_array_length (assemblyb->type_forwarders); ++i) {
3651                 MonoReflectionType *t = mono_array_get (assemblyb->type_forwarders, MonoReflectionType *, i);
3652                 MonoType *type;
3653                 if (!t)
3654                         continue;
3655
3656                 type = mono_reflection_type_get_handle (t);
3657                 g_assert (type);
3658
3659                 klass = mono_class_from_mono_type (type);
3660
3661                 add_exported_type (assemblyb, assembly, klass);
3662         }
3663 }
3664
3665 #define align_pointer(base,p)\
3666         do {\
3667                 guint32 __diff = (unsigned char*)(p)-(unsigned char*)(base);\
3668                 if (__diff & 3)\
3669                         (p) += 4 - (__diff & 3);\
3670         } while (0)
3671
3672 static int
3673 compare_constants (const void *a, const void *b)
3674 {
3675         const guint32 *a_values = a;
3676         const guint32 *b_values = b;
3677         return a_values [MONO_CONSTANT_PARENT] - b_values [MONO_CONSTANT_PARENT];
3678 }
3679
3680 static int
3681 compare_semantics (const void *a, const void *b)
3682 {
3683         const guint32 *a_values = a;
3684         const guint32 *b_values = b;
3685         int assoc = a_values [MONO_METHOD_SEMA_ASSOCIATION] - b_values [MONO_METHOD_SEMA_ASSOCIATION];
3686         if (assoc)
3687                 return assoc;
3688         return a_values [MONO_METHOD_SEMA_SEMANTICS] - b_values [MONO_METHOD_SEMA_SEMANTICS];
3689 }
3690
3691 static int
3692 compare_custom_attrs (const void *a, const void *b)
3693 {
3694         const guint32 *a_values = a;
3695         const guint32 *b_values = b;
3696
3697         return a_values [MONO_CUSTOM_ATTR_PARENT] - b_values [MONO_CUSTOM_ATTR_PARENT];
3698 }
3699
3700 static int
3701 compare_field_marshal (const void *a, const void *b)
3702 {
3703         const guint32 *a_values = a;
3704         const guint32 *b_values = b;
3705
3706         return a_values [MONO_FIELD_MARSHAL_PARENT] - b_values [MONO_FIELD_MARSHAL_PARENT];
3707 }
3708
3709 static int
3710 compare_nested (const void *a, const void *b)
3711 {
3712         const guint32 *a_values = a;
3713         const guint32 *b_values = b;
3714
3715         return a_values [MONO_NESTED_CLASS_NESTED] - b_values [MONO_NESTED_CLASS_NESTED];
3716 }
3717
3718 static int
3719 compare_genericparam (const void *a, const void *b)
3720 {
3721         const GenericParamTableEntry **a_entry = (const GenericParamTableEntry **) a;
3722         const GenericParamTableEntry **b_entry = (const GenericParamTableEntry **) b;
3723
3724         if ((*b_entry)->owner == (*a_entry)->owner)
3725                 return 
3726                         mono_type_get_generic_param_num (mono_reflection_type_get_handle ((MonoReflectionType*)(*a_entry)->gparam)) -
3727                         mono_type_get_generic_param_num (mono_reflection_type_get_handle ((MonoReflectionType*)(*b_entry)->gparam));
3728         else
3729                 return (*a_entry)->owner - (*b_entry)->owner;
3730 }
3731
3732 static int
3733 compare_declsecurity_attrs (const void *a, const void *b)
3734 {
3735         const guint32 *a_values = a;
3736         const guint32 *b_values = b;
3737
3738         return a_values [MONO_DECL_SECURITY_PARENT] - b_values [MONO_DECL_SECURITY_PARENT];
3739 }
3740
3741 static int
3742 compare_interface_impl (const void *a, const void *b)
3743 {
3744         const guint32 *a_values = a;
3745         const guint32 *b_values = b;
3746
3747         int klass = a_values [MONO_INTERFACEIMPL_CLASS] - b_values [MONO_INTERFACEIMPL_CLASS];
3748         if (klass)
3749                 return klass;
3750
3751         return a_values [MONO_INTERFACEIMPL_INTERFACE] - b_values [MONO_INTERFACEIMPL_INTERFACE];
3752 }
3753
3754 static void
3755 pad_heap (MonoDynamicStream *sh)
3756 {
3757         if (sh->index & 3) {
3758                 int sz = 4 - (sh->index & 3);
3759                 memset (sh->data + sh->index, 0, sz);
3760                 sh->index += sz;
3761         }
3762 }
3763
3764 struct StreamDesc {
3765         const char *name;
3766         MonoDynamicStream *stream;
3767 };
3768
3769 /*
3770  * build_compressed_metadata() fills in the blob of data that represents the 
3771  * raw metadata as it will be saved in the PE file. The five streams are output 
3772  * and the metadata tables are comnpressed from the guint32 array representation, 
3773  * to the compressed on-disk format.
3774  */
3775 static void
3776 build_compressed_metadata (MonoDynamicImage *assembly)
3777 {
3778         MonoDynamicTable *table;
3779         int i;
3780         guint64 valid_mask = 0;
3781         guint64 sorted_mask;
3782         guint32 heapt_size = 0;
3783         guint32 meta_size = 256; /* allow for header and other stuff */
3784         guint32 table_offset;
3785         guint32 ntables = 0;
3786         guint64 *int64val;
3787         guint32 *int32val;
3788         guint16 *int16val;
3789         MonoImage *meta;
3790         unsigned char *p;
3791         struct StreamDesc stream_desc [5];
3792
3793         qsort (assembly->gen_params->pdata, assembly->gen_params->len, sizeof (gpointer), compare_genericparam);
3794         for (i = 0; i < assembly->gen_params->len; i++){
3795                 GenericParamTableEntry *entry = g_ptr_array_index (assembly->gen_params, i);
3796                 write_generic_param_entry (assembly, entry);
3797         }
3798
3799         stream_desc [0].name  = "#~";
3800         stream_desc [0].stream = &assembly->tstream;
3801         stream_desc [1].name  = "#Strings";
3802         stream_desc [1].stream = &assembly->sheap;
3803         stream_desc [2].name  = "#US";
3804         stream_desc [2].stream = &assembly->us;
3805         stream_desc [3].name  = "#Blob";
3806         stream_desc [3].stream = &assembly->blob;
3807         stream_desc [4].name  = "#GUID";
3808         stream_desc [4].stream = &assembly->guid;
3809         
3810         /* tables that are sorted */
3811         sorted_mask = ((guint64)1 << MONO_TABLE_CONSTANT) | ((guint64)1 << MONO_TABLE_FIELDMARSHAL)
3812                 | ((guint64)1 << MONO_TABLE_METHODSEMANTICS) | ((guint64)1 << MONO_TABLE_CLASSLAYOUT)
3813                 | ((guint64)1 << MONO_TABLE_FIELDLAYOUT) | ((guint64)1 << MONO_TABLE_FIELDRVA)
3814                 | ((guint64)1 << MONO_TABLE_IMPLMAP) | ((guint64)1 << MONO_TABLE_NESTEDCLASS)
3815                 | ((guint64)1 << MONO_TABLE_METHODIMPL) | ((guint64)1 << MONO_TABLE_CUSTOMATTRIBUTE)
3816                 | ((guint64)1 << MONO_TABLE_DECLSECURITY) | ((guint64)1 << MONO_TABLE_GENERICPARAM)
3817                 | ((guint64)1 << MONO_TABLE_INTERFACEIMPL);
3818         
3819         /* Compute table sizes */
3820         /* the MonoImage has already been created in mono_image_basic_init() */
3821         meta = &assembly->image;
3822
3823         /* sizes should be multiple of 4 */
3824         pad_heap (&assembly->blob);
3825         pad_heap (&assembly->guid);
3826         pad_heap (&assembly->sheap);
3827         pad_heap (&assembly->us);
3828
3829         /* Setup the info used by compute_sizes () */
3830         meta->idx_blob_wide = assembly->blob.index >= 65536 ? 1 : 0;
3831         meta->idx_guid_wide = assembly->guid.index >= 65536 ? 1 : 0;
3832         meta->idx_string_wide = assembly->sheap.index >= 65536 ? 1 : 0;
3833
3834         meta_size += assembly->blob.index;
3835         meta_size += assembly->guid.index;
3836         meta_size += assembly->sheap.index;
3837         meta_size += assembly->us.index;
3838
3839         for (i=0; i < MONO_TABLE_NUM; ++i)
3840                 meta->tables [i].rows = assembly->tables [i].rows;
3841         
3842         for (i = 0; i < MONO_TABLE_NUM; i++){
3843                 if (meta->tables [i].rows == 0)
3844                         continue;
3845                 valid_mask |= (guint64)1 << i;
3846                 ntables ++;
3847                 meta->tables [i].row_size = mono_metadata_compute_size (
3848                         meta, i, &meta->tables [i].size_bitfield);
3849                 heapt_size += meta->tables [i].row_size * meta->tables [i].rows;
3850         }
3851         heapt_size += 24; /* #~ header size */
3852         heapt_size += ntables * 4;
3853         /* make multiple of 4 */
3854         heapt_size += 3;
3855         heapt_size &= ~3;
3856         meta_size += heapt_size;
3857         meta->raw_metadata = g_malloc0 (meta_size);
3858         p = (unsigned char*)meta->raw_metadata;
3859         /* the metadata signature */
3860         *p++ = 'B'; *p++ = 'S'; *p++ = 'J'; *p++ = 'B';
3861         /* version numbers and 4 bytes reserved */
3862         int16val = (guint16*)p;
3863         *int16val++ = GUINT16_TO_LE (meta->md_version_major);
3864         *int16val = GUINT16_TO_LE (meta->md_version_minor);
3865         p += 8;
3866         /* version string */
3867         int32val = (guint32*)p;
3868         *int32val = GUINT32_TO_LE ((strlen (meta->version) + 3) & (~3)); /* needs to be multiple of 4 */
3869         p += 4;
3870         memcpy (p, meta->version, strlen (meta->version));
3871         p += GUINT32_FROM_LE (*int32val);
3872         align_pointer (meta->raw_metadata, p);
3873         int16val = (guint16*)p;
3874         *int16val++ = GUINT16_TO_LE (0); /* flags must be 0 */
3875         *int16val = GUINT16_TO_LE (5); /* number of streams */
3876         p += 4;
3877
3878         /*
3879          * write the stream info.
3880          */
3881         table_offset = (p - (unsigned char*)meta->raw_metadata) + 5 * 8 + 40; /* room needed for stream headers */
3882         table_offset += 3; table_offset &= ~3;
3883
3884         assembly->tstream.index = heapt_size;
3885         for (i = 0; i < 5; ++i) {
3886                 int32val = (guint32*)p;
3887                 stream_desc [i].stream->offset = table_offset;
3888                 *int32val++ = GUINT32_TO_LE (table_offset);
3889                 *int32val = GUINT32_TO_LE (stream_desc [i].stream->index);
3890                 table_offset += GUINT32_FROM_LE (*int32val);
3891                 table_offset += 3; table_offset &= ~3;
3892                 p += 8;
3893                 strcpy ((char*)p, stream_desc [i].name);
3894                 p += strlen (stream_desc [i].name) + 1;
3895                 align_pointer (meta->raw_metadata, p);
3896         }
3897         /* 
3898          * now copy the data, the table stream header and contents goes first.
3899          */
3900         g_assert ((p - (unsigned char*)meta->raw_metadata) < assembly->tstream.offset);
3901         p = (guchar*)meta->raw_metadata + assembly->tstream.offset;
3902         int32val = (guint32*)p;
3903         *int32val = GUINT32_TO_LE (0); /* reserved */
3904         p += 4;
3905
3906         if (mono_framework_version () > 1) {
3907                 *p++ = 2; /* version */
3908                 *p++ = 0;
3909         } else {
3910                 *p++ = 1; /* version */
3911                 *p++ = 0;
3912         }
3913
3914         if (meta->idx_string_wide)
3915                 *p |= 0x01;
3916         if (meta->idx_guid_wide)
3917                 *p |= 0x02;
3918         if (meta->idx_blob_wide)
3919                 *p |= 0x04;
3920         ++p;
3921         *p++ = 1; /* reserved */
3922         int64val = (guint64*)p;
3923         *int64val++ = GUINT64_TO_LE (valid_mask);
3924         *int64val++ = GUINT64_TO_LE (valid_mask & sorted_mask); /* bitvector of sorted tables  */
3925         p += 16;
3926         int32val = (guint32*)p;
3927         for (i = 0; i < MONO_TABLE_NUM; i++){
3928                 if (meta->tables [i].rows == 0)
3929                         continue;
3930                 *int32val++ = GUINT32_TO_LE (meta->tables [i].rows);
3931         }
3932         p = (unsigned char*)int32val;
3933
3934         /* sort the tables that still need sorting */
3935         table = &assembly->tables [MONO_TABLE_CONSTANT];
3936         if (table->rows)
3937                 qsort (table->values + MONO_CONSTANT_SIZE, table->rows, sizeof (guint32) * MONO_CONSTANT_SIZE, compare_constants);
3938         table = &assembly->tables [MONO_TABLE_METHODSEMANTICS];
3939         if (table->rows)
3940                 qsort (table->values + MONO_METHOD_SEMA_SIZE, table->rows, sizeof (guint32) * MONO_METHOD_SEMA_SIZE, compare_semantics);
3941         table = &assembly->tables [MONO_TABLE_CUSTOMATTRIBUTE];
3942         if (table->rows)
3943                 qsort (table->values + MONO_CUSTOM_ATTR_SIZE, table->rows, sizeof (guint32) * MONO_CUSTOM_ATTR_SIZE, compare_custom_attrs);
3944         table = &assembly->tables [MONO_TABLE_FIELDMARSHAL];
3945         if (table->rows)
3946                 qsort (table->values + MONO_FIELD_MARSHAL_SIZE, table->rows, sizeof (guint32) * MONO_FIELD_MARSHAL_SIZE, compare_field_marshal);
3947         table = &assembly->tables [MONO_TABLE_NESTEDCLASS];
3948         if (table->rows)
3949                 qsort (table->values + MONO_NESTED_CLASS_SIZE, table->rows, sizeof (guint32) * MONO_NESTED_CLASS_SIZE, compare_nested);
3950         /* Section 21.11 DeclSecurity in Partition II doesn't specify this to be sorted by MS implementation requires it */
3951         table = &assembly->tables [MONO_TABLE_DECLSECURITY];
3952         if (table->rows)
3953                 qsort (table->values + MONO_DECL_SECURITY_SIZE, table->rows, sizeof (guint32) * MONO_DECL_SECURITY_SIZE, compare_declsecurity_attrs);
3954         table = &assembly->tables [MONO_TABLE_INTERFACEIMPL];
3955         if (table->rows)
3956                 qsort (table->values + MONO_INTERFACEIMPL_SIZE, table->rows, sizeof (guint32) * MONO_INTERFACEIMPL_SIZE, compare_interface_impl);
3957
3958         /* compress the tables */
3959         for (i = 0; i < MONO_TABLE_NUM; i++){
3960                 int row, col;
3961                 guint32 *values;
3962                 guint32 bitfield = meta->tables [i].size_bitfield;
3963                 if (!meta->tables [i].rows)
3964                         continue;
3965                 if (assembly->tables [i].columns != mono_metadata_table_count (bitfield))
3966                         g_error ("col count mismatch in %d: %d %d", i, assembly->tables [i].columns, mono_metadata_table_count (bitfield));
3967                 meta->tables [i].base = (char*)p;
3968                 for (row = 1; row <= meta->tables [i].rows; ++row) {
3969                         values = assembly->tables [i].values + row * assembly->tables [i].columns;
3970                         for (col = 0; col < assembly->tables [i].columns; ++col) {
3971                                 switch (mono_metadata_table_size (bitfield, col)) {
3972                                 case 1:
3973                                         *p++ = values [col];
3974                                         break;
3975                                 case 2:
3976                                         *p++ = values [col] & 0xff;
3977                                         *p++ = (values [col] >> 8) & 0xff;
3978                                         break;
3979                                 case 4:
3980                                         *p++ = values [col] & 0xff;
3981                                         *p++ = (values [col] >> 8) & 0xff;
3982                                         *p++ = (values [col] >> 16) & 0xff;
3983                                         *p++ = (values [col] >> 24) & 0xff;
3984                                         break;
3985                                 default:
3986                                         g_assert_not_reached ();
3987                                 }
3988                         }
3989                 }
3990                 g_assert ((p - (const unsigned char*)meta->tables [i].base) == (meta->tables [i].rows * meta->tables [i].row_size));
3991         }
3992         
3993         g_assert (assembly->guid.offset + assembly->guid.index < meta_size);
3994         memcpy (meta->raw_metadata + assembly->sheap.offset, assembly->sheap.data, assembly->sheap.index);
3995         memcpy (meta->raw_metadata + assembly->us.offset, assembly->us.data, assembly->us.index);
3996         memcpy (meta->raw_metadata + assembly->blob.offset, assembly->blob.data, assembly->blob.index);
3997         memcpy (meta->raw_metadata + assembly->guid.offset, assembly->guid.data, assembly->guid.index);
3998
3999         assembly->meta_size = assembly->guid.offset + assembly->guid.index;
4000 }
4001
4002 /*
4003  * Some tables in metadata need to be sorted according to some criteria, but
4004  * when methods and fields are first created with reflection, they may be assigned a token
4005  * that doesn't correspond to the final token they will get assigned after the sorting.
4006  * ILGenerator.cs keeps a fixup table that maps the position of tokens in the IL code stream
4007  * with the reflection objects that represent them. Once all the tables are set up, the 
4008  * reflection objects will contains the correct table index. fixup_method() will fixup the
4009  * tokens for the method with ILGenerator @ilgen.
4010  */
4011 static void
4012 fixup_method (MonoReflectionILGen *ilgen, gpointer value, MonoDynamicImage *assembly)
4013 {
4014         guint32 code_idx = GPOINTER_TO_UINT (value);
4015         MonoReflectionILTokenInfo *iltoken;
4016         MonoReflectionFieldBuilder *field;
4017         MonoReflectionCtorBuilder *ctor;
4018         MonoReflectionMethodBuilder *method;
4019         MonoReflectionTypeBuilder *tb;
4020         MonoReflectionArrayMethod *am;
4021         guint32 i, idx = 0;
4022         unsigned char *target;
4023
4024         for (i = 0; i < ilgen->num_token_fixups; ++i) {
4025                 iltoken = (MonoReflectionILTokenInfo *)mono_array_addr_with_size (ilgen->token_fixups, sizeof (MonoReflectionILTokenInfo), i);
4026                 target = (guchar*)assembly->code.data + code_idx + iltoken->code_pos;
4027                 switch (target [3]) {
4028                 case MONO_TABLE_FIELD:
4029                         if (!strcmp (iltoken->member->vtable->klass->name, "FieldBuilder")) {
4030                                 field = (MonoReflectionFieldBuilder *)iltoken->member;
4031                                 idx = field->table_idx;
4032                         } else if (!strcmp (iltoken->member->vtable->klass->name, "MonoField")) {
4033                                 MonoClassField *f = ((MonoReflectionField*)iltoken->member)->field;
4034                                 idx = GPOINTER_TO_UINT (g_hash_table_lookup (assembly->field_to_table_idx, f));
4035                         } else {
4036                                 g_assert_not_reached ();
4037                         }
4038                         break;
4039                 case MONO_TABLE_METHOD:
4040                         if (!strcmp (iltoken->member->vtable->klass->name, "MethodBuilder")) {
4041                                 method = (MonoReflectionMethodBuilder *)iltoken->member;
4042                                 idx = method->table_idx;
4043                         } else if (!strcmp (iltoken->member->vtable->klass->name, "ConstructorBuilder")) {
4044                                 ctor = (MonoReflectionCtorBuilder *)iltoken->member;
4045                                 idx = ctor->table_idx;
4046                         } else if (!strcmp (iltoken->member->vtable->klass->name, "MonoMethod") || 
4047                                            !strcmp (iltoken->member->vtable->klass->name, "MonoCMethod")) {
4048                                 MonoMethod *m = ((MonoReflectionMethod*)iltoken->member)->method;
4049                                 idx = GPOINTER_TO_UINT (g_hash_table_lookup (assembly->method_to_table_idx, m));
4050                         } else {
4051                                 g_assert_not_reached ();
4052                         }
4053                         break;
4054                 case MONO_TABLE_TYPEDEF:
4055                         if (strcmp (iltoken->member->vtable->klass->name, "TypeBuilder"))
4056                                 g_assert_not_reached ();
4057                         tb = (MonoReflectionTypeBuilder *)iltoken->member;
4058                         idx = tb->table_idx;
4059                         break;
4060                 case MONO_TABLE_MEMBERREF:
4061                         if (!strcmp (iltoken->member->vtable->klass->name, "MonoArrayMethod")) {
4062                                 am = (MonoReflectionArrayMethod*)iltoken->member;
4063                                 idx = am->table_idx;
4064                         } else if (!strcmp (iltoken->member->vtable->klass->name, "MonoMethod") ||
4065                                    !strcmp (iltoken->member->vtable->klass->name, "MonoCMethod") ||
4066                                    !strcmp (iltoken->member->vtable->klass->name, "MonoGenericMethod") ||
4067                                    !strcmp (iltoken->member->vtable->klass->name, "MonoGenericCMethod")) {
4068                                 MonoMethod *m = ((MonoReflectionMethod*)iltoken->member)->method;
4069                                 g_assert (m->klass->generic_class || m->klass->generic_container);
4070                                 continue;
4071                         } else if (!strcmp (iltoken->member->vtable->klass->name, "FieldBuilder")) {
4072                                 continue;
4073                         } else if (!strcmp (iltoken->member->vtable->klass->name, "MonoField")) {
4074                                 MonoClassField *f = ((MonoReflectionField*)iltoken->member)->field;
4075                                 g_assert (is_field_on_inst (f));
4076                                 continue;
4077                         } else if (!strcmp (iltoken->member->vtable->klass->name, "MethodBuilder") ||
4078                                         !strcmp (iltoken->member->vtable->klass->name, "ConstructorBuilder")) {
4079                                 continue;
4080                         } else if (!strcmp (iltoken->member->vtable->klass->name, "FieldOnTypeBuilderInst")) {
4081                                 continue;
4082                         } else if (!strcmp (iltoken->member->vtable->klass->name, "MethodOnTypeBuilderInst")) {
4083                                 continue;
4084                         } else if (!strcmp (iltoken->member->vtable->klass->name, "ConstructorOnTypeBuilderInst")) {
4085                                 continue;
4086                         } else {
4087                                 g_assert_not_reached ();
4088                         }
4089                         break;
4090                 case MONO_TABLE_METHODSPEC:
4091                         if (!strcmp (iltoken->member->vtable->klass->name, "MonoGenericMethod")) {
4092                                 MonoMethod *m = ((MonoReflectionMethod*)iltoken->member)->method;
4093                                 g_assert (mono_method_signature (m)->generic_param_count);
4094                                 continue;
4095                         } else if (!strcmp (iltoken->member->vtable->klass->name, "MethodBuilder")) {
4096                                 continue;
4097                         } else if (!strcmp (iltoken->member->vtable->klass->name, "MethodOnTypeBuilderInst")) {
4098                                 continue;
4099                         } else {
4100                                 g_assert_not_reached ();
4101                         }
4102                         break;
4103                 default:
4104                         g_error ("got unexpected table 0x%02x in fixup", target [3]);
4105                 }
4106                 target [0] = idx & 0xff;
4107                 target [1] = (idx >> 8) & 0xff;
4108                 target [2] = (idx >> 16) & 0xff;
4109         }
4110 }
4111
4112 /*
4113  * fixup_cattrs:
4114  *
4115  *   The CUSTOM_ATTRIBUTE table might contain METHODDEF tokens whose final
4116  * value is not known when the table is emitted.
4117  */
4118 static void
4119 fixup_cattrs (MonoDynamicImage *assembly)
4120 {
4121         MonoDynamicTable *table;
4122         guint32 *values;
4123         guint32 type, i, idx, token;
4124         MonoObject *ctor;
4125
4126         table = &assembly->tables [MONO_TABLE_CUSTOMATTRIBUTE];
4127
4128         for (i = 0; i < table->rows; ++i) {
4129                 values = table->values + ((i + 1) * MONO_CUSTOM_ATTR_SIZE);
4130
4131                 type = values [MONO_CUSTOM_ATTR_TYPE];
4132                 if ((type & MONO_CUSTOM_ATTR_TYPE_MASK) == MONO_CUSTOM_ATTR_TYPE_METHODDEF) {
4133                         idx = type >> MONO_CUSTOM_ATTR_TYPE_BITS;
4134                         token = mono_metadata_make_token (MONO_TABLE_METHOD, idx);
4135                         ctor = mono_g_hash_table_lookup (assembly->tokens, GUINT_TO_POINTER (token));
4136                         g_assert (ctor);
4137
4138                         if (!strcmp (ctor->vtable->klass->name, "MonoCMethod")) {
4139                                 MonoMethod *m = ((MonoReflectionMethod*)ctor)->method;
4140                                 idx = GPOINTER_TO_UINT (g_hash_table_lookup (assembly->method_to_table_idx, m));
4141                                 values [MONO_CUSTOM_ATTR_TYPE] = (idx << MONO_CUSTOM_ATTR_TYPE_BITS) | MONO_CUSTOM_ATTR_TYPE_METHODDEF;
4142                         }
4143                 }
4144         }
4145 }
4146
4147 static void
4148 assembly_add_resource_manifest (MonoReflectionModuleBuilder *mb, MonoDynamicImage *assembly, MonoReflectionResource *rsrc, guint32 implementation)
4149 {
4150         MonoDynamicTable *table;
4151         guint32 *values;
4152
4153         table = &assembly->tables [MONO_TABLE_MANIFESTRESOURCE];
4154         table->rows++;
4155         alloc_table (table, table->rows);
4156         values = table->values + table->next_idx * MONO_MANIFEST_SIZE;
4157         values [MONO_MANIFEST_OFFSET] = rsrc->offset;
4158         values [MONO_MANIFEST_FLAGS] = rsrc->attrs;
4159         values [MONO_MANIFEST_NAME] = string_heap_insert_mstring (&assembly->sheap, rsrc->name);
4160         values [MONO_MANIFEST_IMPLEMENTATION] = implementation;
4161         table->next_idx++;
4162 }
4163
4164 static void
4165 assembly_add_resource (MonoReflectionModuleBuilder *mb, MonoDynamicImage *assembly, MonoReflectionResource *rsrc)
4166 {
4167         MonoDynamicTable *table;
4168         guint32 *values;
4169         char blob_size [6];
4170         guchar hash [20];
4171         char *b = blob_size;
4172         char *name, *sname;
4173         guint32 idx, offset;
4174
4175         if (rsrc->filename) {
4176                 name = mono_string_to_utf8 (rsrc->filename);
4177                 sname = g_path_get_basename (name);
4178         
4179                 table = &assembly->tables [MONO_TABLE_FILE];
4180                 table->rows++;
4181                 alloc_table (table, table->rows);
4182                 values = table->values + table->next_idx * MONO_FILE_SIZE;
4183                 values [MONO_FILE_FLAGS] = FILE_CONTAINS_NO_METADATA;
4184                 values [MONO_FILE_NAME] = string_heap_insert (&assembly->sheap, sname);
4185                 g_free (sname);
4186
4187                 mono_sha1_get_digest_from_file (name, hash);
4188                 mono_metadata_encode_value (20, b, &b);
4189                 values [MONO_FILE_HASH_VALUE] = mono_image_add_stream_data (&assembly->blob, blob_size, b-blob_size);
4190                 mono_image_add_stream_data (&assembly->blob, (char*)hash, 20);
4191                 g_free (name);
4192                 idx = table->next_idx++;
4193                 rsrc->offset = 0;
4194                 idx = MONO_IMPLEMENTATION_FILE | (idx << MONO_IMPLEMENTATION_BITS);
4195         } else {
4196                 char sizebuf [4];
4197                 char *data;
4198                 guint len;
4199                 if (rsrc->data) {
4200                         data = mono_array_addr (rsrc->data, char, 0);
4201                         len = mono_array_length (rsrc->data);
4202                 } else {
4203                         data = NULL;
4204                         len = 0;
4205                 }
4206                 offset = len;
4207                 sizebuf [0] = offset; sizebuf [1] = offset >> 8;
4208                 sizebuf [2] = offset >> 16; sizebuf [3] = offset >> 24;
4209                 rsrc->offset = mono_image_add_stream_data (&assembly->resources, sizebuf, 4);
4210                 mono_image_add_stream_data (&assembly->resources, data, len);
4211
4212                 if (!mb->is_main)
4213                         /* 
4214                          * The entry should be emitted into the MANIFESTRESOURCE table of 
4215                          * the main module, but that needs to reference the FILE table
4216                          * which isn't emitted yet.
4217                          */
4218                         return;
4219                 else
4220                         idx = 0;
4221         }
4222
4223         assembly_add_resource_manifest (mb, assembly, rsrc, idx);
4224 }
4225
4226 static void
4227 set_version_from_string (MonoString *version, guint32 *values)
4228 {
4229         gchar *ver, *p, *str;
4230         guint32 i;
4231         
4232         values [MONO_ASSEMBLY_MAJOR_VERSION] = 0;
4233         values [MONO_ASSEMBLY_MINOR_VERSION] = 0;
4234         values [MONO_ASSEMBLY_REV_NUMBER] = 0;
4235         values [MONO_ASSEMBLY_BUILD_NUMBER] = 0;
4236         if (!version)
4237                 return;
4238         ver = str = mono_string_to_utf8 (version);
4239         for (i = 0; i < 4; ++i) {
4240                 values [MONO_ASSEMBLY_MAJOR_VERSION + i] = strtol (ver, &p, 10);
4241                 switch (*p) {
4242                 case '.':
4243                         p++;
4244                         break;
4245                 case '*':
4246                         /* handle Revision and Build */
4247                         p++;
4248                         break;
4249                 }
4250                 ver = p;
4251         }
4252         g_free (str);
4253 }
4254
4255 static guint32
4256 load_public_key (MonoArray *pkey, MonoDynamicImage *assembly) {
4257         gsize len;
4258         guint32 token = 0;
4259         char blob_size [6];
4260         char *b = blob_size;
4261
4262         if (!pkey)
4263                 return token;
4264
4265         len = mono_array_length (pkey);
4266         mono_metadata_encode_value (len, b, &b);
4267         token = mono_image_add_stream_data (&assembly->blob, blob_size, b - blob_size);
4268         mono_image_add_stream_data (&assembly->blob, mono_array_addr (pkey, char, 0), len);
4269
4270         assembly->public_key = g_malloc (len);
4271         memcpy (assembly->public_key, mono_array_addr (pkey, char, 0), len);
4272         assembly->public_key_len = len;
4273
4274         /* Special case: check for ECMA key (16 bytes) */
4275         if ((len == MONO_ECMA_KEY_LENGTH) && mono_is_ecma_key (mono_array_addr (pkey, char, 0), len)) {
4276                 /* In this case we must reserve 128 bytes (1024 bits) for the signature */
4277                 assembly->strong_name_size = MONO_DEFAULT_PUBLIC_KEY_LENGTH;
4278         } else if (len >= MONO_PUBLIC_KEY_HEADER_LENGTH + MONO_MINIMUM_PUBLIC_KEY_LENGTH) {
4279                 /* minimum key size (in 2.0) is 384 bits */
4280                 assembly->strong_name_size = len - MONO_PUBLIC_KEY_HEADER_LENGTH;
4281         } else {
4282                 /* FIXME - verifier */
4283                 g_warning ("Invalid public key length: %d bits (total: %d)", (int)MONO_PUBLIC_KEY_BIT_SIZE (len), (int)len);
4284                 assembly->strong_name_size = MONO_DEFAULT_PUBLIC_KEY_LENGTH; /* to be safe */
4285         }
4286         assembly->strong_name = g_malloc0 (assembly->strong_name_size);
4287
4288         return token;
4289 }
4290
4291 static void
4292 mono_image_emit_manifest (MonoReflectionModuleBuilder *moduleb)
4293 {
4294         MonoDynamicTable *table;
4295         MonoDynamicImage *assembly;
4296         MonoReflectionAssemblyBuilder *assemblyb;
4297         MonoDomain *domain;
4298         guint32 *values;
4299         int i;
4300         guint32 module_index;
4301
4302         assemblyb = moduleb->assemblyb;
4303         assembly = moduleb->dynamic_image;
4304         domain = mono_object_domain (assemblyb);
4305
4306         /* Emit ASSEMBLY table */
4307         table = &assembly->tables [MONO_TABLE_ASSEMBLY];
4308         alloc_table (table, 1);
4309         values = table->values + MONO_ASSEMBLY_SIZE;
4310         values [MONO_ASSEMBLY_HASH_ALG] = assemblyb->algid? assemblyb->algid: ASSEMBLY_HASH_SHA1;
4311         values [MONO_ASSEMBLY_NAME] = string_heap_insert_mstring (&assembly->sheap, assemblyb->name);
4312         if (assemblyb->culture) {
4313                 values [MONO_ASSEMBLY_CULTURE] = string_heap_insert_mstring (&assembly->sheap, assemblyb->culture);
4314         } else {
4315                 values [MONO_ASSEMBLY_CULTURE] = string_heap_insert (&assembly->sheap, "");
4316         }
4317         values [MONO_ASSEMBLY_PUBLIC_KEY] = load_public_key (assemblyb->public_key, assembly);
4318         values [MONO_ASSEMBLY_FLAGS] = assemblyb->flags;
4319         set_version_from_string (assemblyb->version, values);
4320
4321         /* Emit FILE + EXPORTED_TYPE table */
4322         module_index = 0;
4323         for (i = 0; i < mono_array_length (assemblyb->modules); ++i) {
4324                 int j;
4325                 MonoReflectionModuleBuilder *file_module = 
4326                         mono_array_get (assemblyb->modules, MonoReflectionModuleBuilder*, i);
4327                 if (file_module != moduleb) {
4328                         mono_image_fill_file_table (domain, (MonoReflectionModule*)file_module, assembly);
4329                         module_index ++;
4330                         if (file_module->types) {
4331                                 for (j = 0; j < file_module->num_types; ++j) {
4332                                         MonoReflectionTypeBuilder *tb = mono_array_get (file_module->types, MonoReflectionTypeBuilder*, j);
4333                                         mono_image_fill_export_table (domain, tb, module_index, 0, assembly);
4334                                 }
4335                         }
4336                 }
4337         }
4338         if (assemblyb->loaded_modules) {
4339                 for (i = 0; i < mono_array_length (assemblyb->loaded_modules); ++i) {
4340                         MonoReflectionModule *file_module = 
4341                                 mono_array_get (assemblyb->loaded_modules, MonoReflectionModule*, i);
4342                         mono_image_fill_file_table (domain, file_module, assembly);
4343                         module_index ++;
4344                         mono_image_fill_export_table_from_module (domain, file_module, module_index, assembly);
4345                 }
4346         }
4347         if (assemblyb->type_forwarders)
4348                 mono_image_fill_export_table_from_type_forwarders (assemblyb, assembly);
4349
4350         /* Emit MANIFESTRESOURCE table */
4351         module_index = 0;
4352         for (i = 0; i < mono_array_length (assemblyb->modules); ++i) {
4353                 int j;
4354                 MonoReflectionModuleBuilder *file_module = 
4355                         mono_array_get (assemblyb->modules, MonoReflectionModuleBuilder*, i);
4356                 /* The table for the main module is emitted later */
4357                 if (file_module != moduleb) {
4358                         module_index ++;
4359                         if (file_module->resources) {
4360                                 int len = mono_array_length (file_module->resources);
4361                                 for (j = 0; j < len; ++j) {
4362                                         MonoReflectionResource* res = (MonoReflectionResource*)mono_array_addr (file_module->resources, MonoReflectionResource, j);
4363                                         assembly_add_resource_manifest (file_module, assembly, res, MONO_IMPLEMENTATION_FILE | (module_index << MONO_IMPLEMENTATION_BITS));
4364                                 }
4365                         }
4366                 }
4367         }               
4368 }
4369
4370 #ifndef DISABLE_REFLECTION_EMIT_SAVE
4371
4372 /*
4373  * mono_image_build_metadata() will fill the info in all the needed metadata tables
4374  * for the modulebuilder @moduleb.
4375  * At the end of the process, method and field tokens are fixed up and the 
4376  * on-disk compressed metadata representation is created.
4377  */
4378 void
4379 mono_image_build_metadata (MonoReflectionModuleBuilder *moduleb)
4380 {
4381         MonoDynamicTable *table;
4382         MonoDynamicImage *assembly;
4383         MonoReflectionAssemblyBuilder *assemblyb;
4384         MonoDomain *domain;
4385         GPtrArray *types;
4386         guint32 *values;
4387         int i, j;
4388
4389         assemblyb = moduleb->assemblyb;
4390         assembly = moduleb->dynamic_image;
4391         domain = mono_object_domain (assemblyb);
4392
4393         if (assembly->text_rva)
4394                 return;
4395
4396         assembly->text_rva = START_TEXT_RVA;
4397
4398         if (moduleb->is_main) {
4399                 mono_image_emit_manifest (moduleb);
4400         }
4401
4402         table = &assembly->tables [MONO_TABLE_TYPEDEF];
4403         table->rows = 1; /* .<Module> */
4404         table->next_idx++;
4405         alloc_table (table, table->rows);
4406         /*
4407          * Set the first entry.
4408          */
4409         values = table->values + table->columns;
4410         values [MONO_TYPEDEF_FLAGS] = 0;
4411         values [MONO_TYPEDEF_NAME] = string_heap_insert (&assembly->sheap, "<Module>") ;
4412         values [MONO_TYPEDEF_NAMESPACE] = string_heap_insert (&assembly->sheap, "") ;
4413         values [MONO_TYPEDEF_EXTENDS] = 0;
4414         values [MONO_TYPEDEF_FIELD_LIST] = 1;
4415         values [MONO_TYPEDEF_METHOD_LIST] = 1;
4416
4417         /* 
4418          * handle global methods 
4419          * FIXME: test what to do when global methods are defined in multiple modules.
4420          */
4421         if (moduleb->global_methods) {
4422                 table = &assembly->tables [MONO_TABLE_METHOD];
4423                 table->rows += mono_array_length (moduleb->global_methods);
4424                 alloc_table (table, table->rows);
4425                 for (i = 0; i < mono_array_length (moduleb->global_methods); ++i)
4426                         mono_image_get_method_info (
4427                                 mono_array_get (moduleb->global_methods, MonoReflectionMethodBuilder*, i), assembly);
4428         }
4429         if (moduleb->global_fields) {
4430                 table = &assembly->tables [MONO_TABLE_FIELD];
4431                 table->rows += mono_array_length (moduleb->global_fields);
4432                 alloc_table (table, table->rows);
4433                 for (i = 0; i < mono_array_length (moduleb->global_fields); ++i)
4434                         mono_image_get_field_info (
4435                                 mono_array_get (moduleb->global_fields, MonoReflectionFieldBuilder*, i), assembly);
4436         }
4437
4438         table = &assembly->tables [MONO_TABLE_MODULE];
4439         alloc_table (table, 1);
4440         mono_image_fill_module_table (domain, moduleb, assembly);
4441
4442         /* Collect all types into a list sorted by their table_idx */
4443         types = g_ptr_array_new ();
4444
4445         if (moduleb->types)
4446                 for (i = 0; i < moduleb->num_types; ++i) {
4447                         MonoReflectionTypeBuilder *type = mono_array_get (moduleb->types, MonoReflectionTypeBuilder*, i);
4448                         collect_types (types, type);
4449                 }
4450
4451         g_ptr_array_sort (types, (GCompareFunc)compare_types_by_table_idx);
4452         table = &assembly->tables [MONO_TABLE_TYPEDEF];
4453         table->rows += types->len;
4454         alloc_table (table, table->rows);
4455
4456         /*
4457          * Emit type names + namespaces at one place inside the string heap,
4458          * so load_class_names () needs to touch fewer pages.
4459          */
4460         for (i = 0; i < types->len; ++i) {
4461                 MonoReflectionTypeBuilder *tb = g_ptr_array_index (types, i);
4462                 string_heap_insert_mstring (&assembly->sheap, tb->nspace);
4463         }
4464         for (i = 0; i < types->len; ++i) {
4465                 MonoReflectionTypeBuilder *tb = g_ptr_array_index (types, i);
4466                 string_heap_insert_mstring (&assembly->sheap, tb->name);
4467         }
4468
4469         for (i = 0; i < types->len; ++i) {
4470                 MonoReflectionTypeBuilder *type = g_ptr_array_index (types, i);
4471                 mono_image_get_type_info (domain, type, assembly);
4472         }
4473
4474         /* 
4475          * table->rows is already set above and in mono_image_fill_module_table.
4476          */
4477         /* add all the custom attributes at the end, once all the indexes are stable */
4478         mono_image_add_cattrs (assembly, 1, MONO_CUSTOM_ATTR_ASSEMBLY, assemblyb->cattrs);
4479
4480         /* CAS assembly permissions */
4481         if (assemblyb->permissions_minimum)
4482                 mono_image_add_decl_security (assembly, mono_metadata_make_token (MONO_TABLE_ASSEMBLY, 1), assemblyb->permissions_minimum);
4483         if (assemblyb->permissions_optional)
4484                 mono_image_add_decl_security (assembly, mono_metadata_make_token (MONO_TABLE_ASSEMBLY, 1), assemblyb->permissions_optional);
4485         if (assemblyb->permissions_refused)
4486                 mono_image_add_decl_security (assembly, mono_metadata_make_token (MONO_TABLE_ASSEMBLY, 1), assemblyb->permissions_refused);
4487
4488         module_add_cattrs (assembly, moduleb);
4489
4490         /* fixup tokens */
4491         mono_g_hash_table_foreach (assembly->token_fixups, (GHFunc)fixup_method, assembly);
4492
4493         /* Create the MethodImpl table.  We do this after emitting all methods so we already know
4494          * the final tokens and don't need another fixup pass. */
4495
4496         if (moduleb->global_methods) {
4497                 for (i = 0; i < mono_array_length (moduleb->global_methods); ++i) {
4498                         MonoReflectionMethodBuilder *mb = mono_array_get (
4499                                 moduleb->global_methods, MonoReflectionMethodBuilder*, i);
4500                         mono_image_add_methodimpl (assembly, mb);
4501                 }
4502         }
4503
4504         for (i = 0; i < types->len; ++i) {
4505                 MonoReflectionTypeBuilder *type = g_ptr_array_index (types, i);
4506                 if (type->methods) {
4507                         for (j = 0; j < type->num_methods; ++j) {
4508                                 MonoReflectionMethodBuilder *mb = mono_array_get (
4509                                         type->methods, MonoReflectionMethodBuilder*, j);
4510
4511                                 mono_image_add_methodimpl (assembly, mb);
4512                         }
4513                 }
4514         }
4515
4516         g_ptr_array_free (types, TRUE);
4517
4518         fixup_cattrs (assembly);
4519 }
4520
4521 #else /* DISABLE_REFLECTION_EMIT_SAVE */
4522
4523 void
4524 mono_image_build_metadata (MonoReflectionModuleBuilder *moduleb)
4525 {
4526         g_error ("This mono runtime was configured with --enable-minimal=reflection_emit_save, so saving of dynamic assemblies is not supported.");
4527 }
4528
4529 #endif /* DISABLE_REFLECTION_EMIT_SAVE */
4530
4531
4532 typedef struct {
4533         guint32 import_lookup_table;
4534         guint32 timestamp;
4535         guint32 forwarder;
4536         guint32 name_rva;
4537         guint32 import_address_table_rva;
4538 } MonoIDT;
4539
4540 typedef struct {
4541         guint32 name_rva;
4542         guint32 flags;
4543 } MonoILT;
4544
4545 #ifndef DISABLE_REFLECTION_EMIT
4546
4547 /*
4548  * mono_image_insert_string:
4549  * @module: module builder object
4550  * @str: a string
4551  *
4552  * Insert @str into the user string stream of @module.
4553  */
4554 guint32
4555 mono_image_insert_string (MonoReflectionModuleBuilder *module, MonoString *str)
4556 {
4557         MonoDynamicImage *assembly;
4558         guint32 idx;
4559         char buf [16];
4560         char *b = buf;
4561         
4562         MONO_ARCH_SAVE_REGS;
4563
4564         if (!module->dynamic_image)
4565                 mono_image_module_basic_init (module);
4566
4567         assembly = module->dynamic_image;
4568         
4569         if (assembly->save) {
4570                 mono_metadata_encode_value (1 | (str->length * 2), b, &b);
4571                 idx = mono_image_add_stream_data (&assembly->us, buf, b-buf);
4572 #if G_BYTE_ORDER != G_LITTLE_ENDIAN
4573         {
4574                 char *swapped = g_malloc (2 * mono_string_length (str));
4575                 const char *p = (const char*)mono_string_chars (str);
4576
4577                 swap_with_size (swapped, p, 2, mono_string_length (str));
4578                 mono_image_add_stream_data (&assembly->us, swapped, str->length * 2);
4579                 g_free (swapped);
4580         }
4581 #else
4582                 mono_image_add_stream_data (&assembly->us, (const char*)mono_string_chars (str), str->length * 2);
4583 #endif
4584                 mono_image_add_stream_data (&assembly->us, "", 1);
4585         } else {
4586                 idx = assembly->us.index ++;
4587         }
4588
4589         mono_g_hash_table_insert (assembly->tokens, GUINT_TO_POINTER (MONO_TOKEN_STRING | idx), str);
4590
4591         return MONO_TOKEN_STRING | idx;
4592 }
4593
4594 guint32
4595 mono_image_create_method_token (MonoDynamicImage *assembly, MonoObject *obj, MonoArray *opt_param_types)
4596 {
4597         MonoClass *klass;
4598         guint32 token = 0;
4599
4600         klass = obj->vtable->klass;
4601         if (strcmp (klass->name, "MonoMethod") == 0) {
4602                 MonoMethod *method = ((MonoReflectionMethod *)obj)->method;
4603                 MonoMethodSignature *sig, *old;
4604                 guint32 sig_token, parent;
4605                 int nargs, i;
4606
4607                 g_assert (opt_param_types && (mono_method_signature (method)->sentinelpos >= 0));
4608
4609                 nargs = mono_array_length (opt_param_types);
4610                 old = mono_method_signature (method);
4611                 sig = mono_metadata_signature_alloc ( &assembly->image, old->param_count + nargs);
4612
4613                 sig->hasthis = old->hasthis;
4614                 sig->explicit_this = old->explicit_this;
4615                 sig->call_convention = old->call_convention;
4616                 sig->generic_param_count = old->generic_param_count;
4617                 sig->param_count = old->param_count + nargs;
4618                 sig->sentinelpos = old->param_count;
4619                 sig->ret = old->ret;
4620
4621                 for (i = 0; i < old->param_count; i++)
4622                         sig->params [i] = old->params [i];
4623
4624                 for (i = 0; i < nargs; i++) {
4625                         MonoReflectionType *rt = mono_array_get (opt_param_types, MonoReflectionType *, i);
4626                         sig->params [old->param_count + i] = mono_reflection_type_get_handle (rt);
4627                 }
4628
4629                 parent = mono_image_typedef_or_ref (assembly, &method->klass->byval_arg);
4630                 g_assert ((parent & MONO_TYPEDEFORREF_MASK) == MONO_MEMBERREF_PARENT_TYPEREF);
4631                 parent >>= MONO_TYPEDEFORREF_BITS;
4632
4633                 parent <<= MONO_MEMBERREF_PARENT_BITS;
4634                 parent |= MONO_MEMBERREF_PARENT_TYPEREF;
4635
4636                 sig_token = method_encode_signature (assembly, sig);
4637                 token = mono_image_get_varargs_method_token (assembly, parent, method->name, sig_token);
4638         } else if (strcmp (klass->name, "MethodBuilder") == 0) {
4639                 MonoReflectionMethodBuilder *mb = (MonoReflectionMethodBuilder *)obj;
4640                 ReflectionMethodBuilder rmb;
4641                 guint32 parent, sig;
4642                 char *name;
4643
4644                 reflection_methodbuilder_from_method_builder (&rmb, mb);
4645                 rmb.opt_types = opt_param_types;
4646
4647                 sig = method_builder_encode_signature (assembly, &rmb);
4648
4649                 parent = mono_image_create_token (assembly, obj, TRUE, TRUE);
4650                 g_assert (mono_metadata_token_table (parent) == MONO_TABLE_METHOD);
4651
4652                 parent = mono_metadata_token_index (parent) << MONO_MEMBERREF_PARENT_BITS;
4653                 parent |= MONO_MEMBERREF_PARENT_METHODDEF;
4654
4655                 name = mono_string_to_utf8 (rmb.name);
4656                 token = mono_image_get_varargs_method_token (
4657                         assembly, parent, name, sig);
4658                 g_free (name);
4659         } else {
4660                 g_error ("requested method token for %s\n", klass->name);
4661         }
4662
4663         return token;
4664 }
4665
4666 /*
4667  * mono_image_create_token:
4668  * @assembly: a dynamic assembly
4669  * @obj:
4670  * @register_token: Whenever to register the token in the assembly->tokens hash. 
4671  *
4672  * Get a token to insert in the IL code stream for the given MemberInfo.
4673  * The metadata emission routines need to pass FALSE as REGISTER_TOKEN, since by that time, 
4674  * the table_idx-es were recomputed, so registering the token would overwrite an existing 
4675  * entry.
4676  */
4677 guint32
4678 mono_image_create_token (MonoDynamicImage *assembly, MonoObject *obj, 
4679                                                  gboolean create_methodspec, gboolean register_token)
4680 {
4681         MonoClass *klass;
4682         guint32 token = 0;
4683
4684         klass = obj->vtable->klass;
4685
4686         /* Check for user defined reflection objects */
4687         /* TypeDelegator is the only corlib type which doesn't look like a MonoReflectionType */
4688         if (klass->image != mono_defaults.corlib || (strcmp (klass->name, "TypeDelegator") == 0))
4689                 mono_raise_exception (mono_get_exception_not_supported ("User defined subclasses of System.Type are not yet supported")); \
4690
4691         if (strcmp (klass->name, "MethodBuilder") == 0) {
4692                 MonoReflectionMethodBuilder *mb = (MonoReflectionMethodBuilder *)obj;
4693                 MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder*)mb->type;
4694
4695                 if (tb->module->dynamic_image == assembly && !tb->generic_params && !mb->generic_params)
4696                         token = mb->table_idx | MONO_TOKEN_METHOD_DEF;
4697                 else
4698                         token = mono_image_get_methodbuilder_token (assembly, mb, create_methodspec);
4699                 /*g_print ("got token 0x%08x for %s\n", token, mono_string_to_utf8 (mb->name));*/
4700         } else if (strcmp (klass->name, "ConstructorBuilder") == 0) {
4701                 MonoReflectionCtorBuilder *mb = (MonoReflectionCtorBuilder *)obj;
4702                 MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder*)mb->type;
4703
4704                 if (tb->module->dynamic_image == assembly && !tb->generic_params)
4705                         token = mb->table_idx | MONO_TOKEN_METHOD_DEF;
4706                 else
4707                         token = mono_image_get_ctorbuilder_token (assembly, mb);
4708                 /*g_print ("got token 0x%08x for %s\n", token, mono_string_to_utf8 (mb->name));*/
4709         } else if (strcmp (klass->name, "FieldBuilder") == 0) {
4710                 MonoReflectionFieldBuilder *fb = (MonoReflectionFieldBuilder *)obj;
4711                 MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder *)fb->typeb;
4712                 if (tb->generic_params) {
4713                         token = mono_image_get_generic_field_token (assembly, fb);
4714                 } else {
4715                         token = fb->table_idx | MONO_TOKEN_FIELD_DEF;
4716                 }
4717         } else if (strcmp (klass->name, "TypeBuilder") == 0) {
4718                 MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder *)obj;
4719                 token = tb->table_idx | MONO_TOKEN_TYPE_DEF;
4720         } else if (strcmp (klass->name, "MonoType") == 0) {
4721                 MonoType *type = mono_reflection_type_get_handle ((MonoReflectionType *)obj);
4722                 MonoClass *mc = mono_class_from_mono_type (type);
4723                 token = mono_metadata_token_from_dor (
4724                         mono_image_typedef_or_ref_full (assembly, type, mc->generic_container == NULL));
4725         } else if (strcmp (klass->name, "GenericTypeParameterBuilder") == 0) {
4726                 MonoType *type = mono_reflection_type_get_handle ((MonoReflectionType *)obj);
4727                 token = mono_metadata_token_from_dor (
4728                         mono_image_typedef_or_ref (assembly, type));
4729         } else if (strcmp (klass->name, "MonoGenericClass") == 0) {
4730                 MonoType *type = mono_reflection_type_get_handle ((MonoReflectionType *)obj);
4731                 token = mono_metadata_token_from_dor (
4732                         mono_image_typedef_or_ref (assembly, type));
4733         } else if (strcmp (klass->name, "MonoCMethod") == 0 ||
4734                    strcmp (klass->name, "MonoMethod") == 0 ||
4735                    strcmp (klass->name, "MonoGenericMethod") == 0 ||
4736                    strcmp (klass->name, "MonoGenericCMethod") == 0) {
4737                 MonoReflectionMethod *m = (MonoReflectionMethod *)obj;
4738                 if (m->method->is_inflated) {
4739                         if (create_methodspec)
4740                                 token = mono_image_get_methodspec_token (assembly, m->method);
4741                         else
4742                                 token = mono_image_get_inflated_method_token (assembly, m->method);
4743                 } else if ((m->method->klass->image == &assembly->image) &&
4744                          !m->method->klass->generic_class) {
4745                         static guint32 method_table_idx = 0xffffff;
4746                         if (m->method->klass->wastypebuilder) {
4747                                 /* we use the same token as the one that was assigned
4748                                  * to the Methodbuilder.
4749                                  * FIXME: do the equivalent for Fields.
4750                                  */
4751                                 token = m->method->token;
4752                         } else {
4753                                 /*
4754                                  * Each token should have a unique index, but the indexes are
4755                                  * assigned by managed code, so we don't know about them. An
4756                                  * easy solution is to count backwards...
4757                                  */
4758                                 method_table_idx --;
4759                                 token = MONO_TOKEN_METHOD_DEF | method_table_idx;
4760                         }
4761                 } else {
4762                         token = mono_image_get_methodref_token (assembly, m->method, create_methodspec);
4763                 }
4764                 /*g_print ("got token 0x%08x for %s\n", token, m->method->name);*/
4765         } else if (strcmp (klass->name, "MonoField") == 0) {
4766                 MonoReflectionField *f = (MonoReflectionField *)obj;
4767                 if ((f->field->parent->image == &assembly->image) && !is_field_on_inst (f->field)) {
4768                         static guint32 field_table_idx = 0xffffff;
4769                         field_table_idx --;
4770                         token = MONO_TOKEN_FIELD_DEF | field_table_idx;
4771                 } else {
4772                         token = mono_image_get_fieldref_token (assembly, f);
4773                 }
4774                 /*g_print ("got token 0x%08x for %s\n", token, f->field->name);*/
4775         } else if (strcmp (klass->name, "MonoArrayMethod") == 0) {
4776                 MonoReflectionArrayMethod *m = (MonoReflectionArrayMethod *)obj;
4777                 token = mono_image_get_array_token (assembly, m);
4778         } else if (strcmp (klass->name, "SignatureHelper") == 0) {
4779                 MonoReflectionSigHelper *s = (MonoReflectionSigHelper*)obj;
4780                 token = MONO_TOKEN_SIGNATURE | mono_image_get_sighelper_token (assembly, s);
4781         } else if (strcmp (klass->name, "EnumBuilder") == 0) {
4782                 MonoType *type = mono_reflection_type_get_handle ((MonoReflectionType *)obj);
4783                 token = mono_metadata_token_from_dor (
4784                         mono_image_typedef_or_ref (assembly, type));
4785         } else if (strcmp (klass->name, "FieldOnTypeBuilderInst") == 0) {
4786                 MonoReflectionFieldOnTypeBuilderInst *f = (MonoReflectionFieldOnTypeBuilderInst*)obj;
4787                 token = mono_image_get_field_on_inst_token (assembly, f);
4788         } else if (strcmp (klass->name, "ConstructorOnTypeBuilderInst") == 0) {
4789                 MonoReflectionCtorOnTypeBuilderInst *c = (MonoReflectionCtorOnTypeBuilderInst*)obj;
4790                 token = mono_image_get_ctor_on_inst_token (assembly, c, create_methodspec);
4791         } else if (strcmp (klass->name, "MethodOnTypeBuilderInst") == 0) {
4792                 MonoReflectionMethodOnTypeBuilderInst *m = (MonoReflectionMethodOnTypeBuilderInst*)obj;
4793                 token = mono_image_get_method_on_inst_token (assembly, m, create_methodspec);
4794         } else if (is_sre_array (klass) || is_sre_byref (klass) || is_sre_pointer (klass)) {
4795                 MonoReflectionType *type = (MonoReflectionType *)obj;
4796                 token = mono_metadata_token_from_dor (
4797                                 mono_image_typedef_or_ref (assembly, mono_reflection_type_get_handle (type)));
4798         } else {
4799                 g_error ("requested token for %s\n", klass->name);
4800         }
4801
4802         if (register_token)
4803                 mono_image_register_token (assembly, token, obj);
4804
4805         return token;
4806 }
4807
4808 /*
4809  * mono_image_register_token:
4810  *
4811  *   Register the TOKEN->OBJ mapping in the mapping table in ASSEMBLY. This is required for
4812  * the Module.ResolveXXXToken () methods to work.
4813  */
4814 void
4815 mono_image_register_token (MonoDynamicImage *assembly, guint32 token, MonoObject *obj)
4816 {
4817         MonoObject *prev = mono_g_hash_table_lookup (assembly->tokens, GUINT_TO_POINTER (token));
4818         if (prev) {
4819                 /* There could be multiple MethodInfo objects with the same token */
4820                 //g_assert (prev == obj);
4821         } else {
4822                 mono_g_hash_table_insert (assembly->tokens, GUINT_TO_POINTER (token), obj);
4823         }
4824 }
4825
4826 static MonoDynamicImage*
4827 create_dynamic_mono_image (MonoDynamicAssembly *assembly, char *assembly_name, char *module_name)
4828 {
4829         static const guchar entrycode [16] = {0xff, 0x25, 0};
4830         MonoDynamicImage *image;
4831         int i;
4832
4833         const char *version;
4834
4835         if (!strcmp (mono_get_runtime_info ()->framework_version, "2.1"))
4836                 version = "v2.0.50727"; /* HACK: SL 2 enforces the .net 2 metadata version */
4837         else
4838                 version = mono_get_runtime_info ()->runtime_version;
4839
4840 #if HAVE_BOEHM_GC
4841         image = GC_MALLOC (sizeof (MonoDynamicImage));
4842 #else
4843         image = g_new0 (MonoDynamicImage, 1);
4844 #endif
4845         
4846         mono_profiler_module_event (&image->image, MONO_PROFILE_START_LOAD);
4847         
4848         /*g_print ("created image %p\n", image);*/
4849         /* keep in sync with image.c */
4850         image->image.name = assembly_name;
4851         image->image.assembly_name = image->image.name; /* they may be different */
4852         image->image.module_name = module_name;
4853         image->image.version = g_strdup (version);
4854         image->image.md_version_major = 1;
4855         image->image.md_version_minor = 1;
4856         image->image.dynamic = TRUE;
4857
4858         image->image.references = g_new0 (MonoAssembly*, 1);
4859         image->image.references [0] = NULL;
4860
4861         mono_image_init (&image->image);
4862
4863         image->token_fixups = mono_g_hash_table_new_type ((GHashFunc)mono_object_hash, NULL, MONO_HASH_KEY_GC);
4864         image->method_to_table_idx = g_hash_table_new (NULL, NULL);
4865         image->field_to_table_idx = g_hash_table_new (NULL, NULL);
4866         image->method_aux_hash = g_hash_table_new (NULL, NULL);
4867         image->handleref = g_hash_table_new (NULL, NULL);
4868         image->tokens = mono_g_hash_table_new_type (NULL, NULL, MONO_HASH_VALUE_GC);
4869         image->generic_def_objects = mono_g_hash_table_new_type (NULL, NULL, MONO_HASH_VALUE_GC);
4870         image->methodspec = mono_g_hash_table_new_type ((GHashFunc)mono_object_hash, NULL, MONO_HASH_KEY_GC);
4871         image->typespec = g_hash_table_new ((GHashFunc)mono_metadata_type_hash, (GCompareFunc)mono_metadata_type_equal);
4872         image->typeref = g_hash_table_new ((GHashFunc)mono_metadata_type_hash, (GCompareFunc)mono_metadata_type_equal);
4873         image->blob_cache = g_hash_table_new ((GHashFunc)mono_blob_entry_hash, (GCompareFunc)mono_blob_entry_equal);
4874         image->gen_params = g_ptr_array_new ();
4875
4876         /*g_print ("string heap create for image %p (%s)\n", image, module_name);*/
4877         string_heap_init (&image->sheap);
4878         mono_image_add_stream_data (&image->us, "", 1);
4879         add_to_blob_cached (image, (char*) "", 1, NULL, 0);
4880         /* import tables... */
4881         mono_image_add_stream_data (&image->code, (char*)entrycode, sizeof (entrycode));
4882         image->iat_offset = mono_image_add_stream_zero (&image->code, 8); /* two IAT entries */
4883         image->idt_offset = mono_image_add_stream_zero (&image->code, 2 * sizeof (MonoIDT)); /* two IDT entries */
4884         image->imp_names_offset = mono_image_add_stream_zero (&image->code, 2); /* flags for name entry */
4885         mono_image_add_stream_data (&image->code, "_CorExeMain", 12);
4886         mono_image_add_stream_data (&image->code, "mscoree.dll", 12);
4887         image->ilt_offset = mono_image_add_stream_zero (&image->code, 8); /* two ILT entries */
4888         stream_data_align (&image->code);
4889
4890         image->cli_header_offset = mono_image_add_stream_zero (&image->code, sizeof (MonoCLIHeader));
4891
4892         for (i=0; i < MONO_TABLE_NUM; ++i) {
4893                 image->tables [i].next_idx = 1;
4894                 image->tables [i].columns = table_sizes [i];
4895         }
4896
4897         image->image.assembly = (MonoAssembly*)assembly;
4898         image->run = assembly->run;
4899         image->save = assembly->save;
4900         image->pe_kind = 0x1; /* ILOnly */
4901         image->machine = 0x14c; /* I386 */
4902         
4903         mono_profiler_module_loaded (&image->image, MONO_PROFILE_OK);
4904
4905         return image;
4906 }
4907 #endif
4908
4909 static void
4910 free_blob_cache_entry (gpointer key, gpointer val, gpointer user_data)
4911 {
4912         g_free (key);
4913 }
4914
4915 void
4916 mono_dynamic_image_free (MonoDynamicImage *image)
4917 {
4918         MonoDynamicImage *di = image;
4919         GList *list;
4920         int i;
4921
4922         if (di->methodspec)
4923                 mono_g_hash_table_destroy (di->methodspec);
4924         if (di->typespec)
4925                 g_hash_table_destroy (di->typespec);
4926         if (di->typeref)
4927                 g_hash_table_destroy (di->typeref);
4928         if (di->handleref)
4929                 g_hash_table_destroy (di->handleref);
4930         if (di->tokens)
4931                 mono_g_hash_table_destroy (di->tokens);
4932         if (di->generic_def_objects)
4933                 mono_g_hash_table_destroy (di->generic_def_objects);
4934         if (di->blob_cache) {
4935                 g_hash_table_foreach (di->blob_cache, free_blob_cache_entry, NULL);
4936                 g_hash_table_destroy (di->blob_cache);
4937         }
4938         if (di->standalonesig_cache)
4939                 g_hash_table_destroy (di->standalonesig_cache);
4940         for (list = di->array_methods; list; list = list->next) {
4941                 ArrayMethod *am = (ArrayMethod *)list->data;
4942                 g_free (am->sig);
4943                 g_free (am->name);
4944                 g_free (am);
4945         }
4946         g_list_free (di->array_methods);
4947         if (di->gen_params) {
4948                 for (i = 0; i < di->gen_params->len; i++) {
4949                         GenericParamTableEntry *entry = g_ptr_array_index (di->gen_params, i);
4950                         if (entry->gparam->type.type) {
4951                                 MonoGenericParam *param = entry->gparam->type.type->data.generic_param;
4952                                 g_free ((char*)mono_generic_param_info (param)->name);
4953                                 g_free (param);
4954                         }
4955                         g_free (entry);
4956                 }
4957                 g_ptr_array_free (di->gen_params, TRUE);
4958         }
4959         if (di->token_fixups)
4960                 mono_g_hash_table_destroy (di->token_fixups);
4961         if (di->method_to_table_idx)
4962                 g_hash_table_destroy (di->method_to_table_idx);
4963         if (di->field_to_table_idx)
4964                 g_hash_table_destroy (di->field_to_table_idx);
4965         if (di->method_aux_hash)
4966                 g_hash_table_destroy (di->method_aux_hash);
4967         g_free (di->strong_name);
4968         g_free (di->win32_res);
4969         if (di->public_key)
4970                 g_free (di->public_key);
4971
4972         /*g_print ("string heap destroy for image %p\n", di);*/
4973         mono_dynamic_stream_reset (&di->sheap);
4974         mono_dynamic_stream_reset (&di->code);
4975         mono_dynamic_stream_reset (&di->resources);
4976         mono_dynamic_stream_reset (&di->us);
4977         mono_dynamic_stream_reset (&di->blob);
4978         mono_dynamic_stream_reset (&di->tstream);
4979         mono_dynamic_stream_reset (&di->guid);
4980         for (i = 0; i < MONO_TABLE_NUM; ++i) {
4981                 g_free (di->tables [i].values);
4982         }
4983 }       
4984
4985 #ifndef DISABLE_REFLECTION_EMIT
4986
4987 /*
4988  * mono_image_basic_init:
4989  * @assembly: an assembly builder object
4990  *
4991  * Create the MonoImage that represents the assembly builder and setup some
4992  * of the helper hash table and the basic metadata streams.
4993  */
4994 void
4995 mono_image_basic_init (MonoReflectionAssemblyBuilder *assemblyb)
4996 {
4997         MonoDynamicAssembly *assembly;
4998         MonoDynamicImage *image;
4999         MonoDomain *domain = mono_object_domain (assemblyb);
5000         
5001         MONO_ARCH_SAVE_REGS;
5002
5003         if (assemblyb->dynamic_assembly)
5004                 return;
5005
5006 #if HAVE_BOEHM_GC
5007         assembly = assemblyb->dynamic_assembly = GC_MALLOC (sizeof (MonoDynamicAssembly));
5008 #else
5009         assembly = assemblyb->dynamic_assembly = g_new0 (MonoDynamicAssembly, 1);
5010 #endif
5011
5012         mono_profiler_assembly_event (&assembly->assembly, MONO_PROFILE_START_LOAD);
5013         
5014         assembly->assembly.ref_count = 1;
5015         assembly->assembly.dynamic = TRUE;
5016         assembly->assembly.corlib_internal = assemblyb->corlib_internal;
5017         assemblyb->assembly.assembly = (MonoAssembly*)assembly;
5018         assembly->assembly.basedir = mono_string_to_utf8 (assemblyb->dir);
5019         if (assemblyb->culture)
5020                 assembly->assembly.aname.culture = mono_string_to_utf8 (assemblyb->culture);
5021         else
5022                 assembly->assembly.aname.culture = g_strdup ("");
5023
5024         if (assemblyb->version) {
5025                         char *vstr = mono_string_to_utf8 (assemblyb->version);
5026                         char **version = g_strsplit (vstr, ".", 4);
5027                         char **parts = version;
5028                         assembly->assembly.aname.major = atoi (*parts++);
5029                         assembly->assembly.aname.minor = atoi (*parts++);
5030                         assembly->assembly.aname.build = *parts != NULL ? atoi (*parts++) : 0;
5031                         assembly->assembly.aname.revision = *parts != NULL ? atoi (*parts) : 0;
5032
5033                         g_strfreev (version);
5034                         g_free (vstr);
5035         } else {
5036                         assembly->assembly.aname.major = 0;
5037                         assembly->assembly.aname.minor = 0;
5038                         assembly->assembly.aname.build = 0;
5039                         assembly->assembly.aname.revision = 0;
5040         }
5041
5042         assembly->run = assemblyb->access != 2;
5043         assembly->save = assemblyb->access != 1;
5044
5045         image = create_dynamic_mono_image (assembly, mono_string_to_utf8 (assemblyb->name), g_strdup ("RefEmit_YouForgotToDefineAModule"));
5046         image->initial_image = TRUE;
5047         assembly->assembly.aname.name = image->image.name;
5048         assembly->assembly.image = &image->image;
5049         if (assemblyb->pktoken && assemblyb->pktoken->max_length) {
5050                 /* -1 to correct for the trailing NULL byte */
5051                 if (assemblyb->pktoken->max_length != MONO_PUBLIC_KEY_TOKEN_LENGTH - 1) {
5052                         g_error ("Public key token length invalid for assembly %s: %i", assembly->assembly.aname.name, assemblyb->pktoken->max_length);
5053                 }
5054                 memcpy (&assembly->assembly.aname.public_key_token, mono_array_addr (assemblyb->pktoken, guint8, 0), assemblyb->pktoken->max_length);           
5055         }
5056
5057         mono_domain_assemblies_lock (domain);
5058         domain->domain_assemblies = g_slist_prepend (domain->domain_assemblies, assembly);
5059         mono_domain_assemblies_unlock (domain);
5060
5061         register_assembly (mono_object_domain (assemblyb), &assemblyb->assembly, &assembly->assembly);
5062         
5063         mono_profiler_assembly_loaded (&assembly->assembly, MONO_PROFILE_OK);
5064         
5065         mono_assembly_invoke_load_hook ((MonoAssembly*)assembly);
5066 }
5067
5068 #endif /* !DISABLE_REFLECTION_EMIT */
5069
5070 #ifndef DISABLE_REFLECTION_EMIT_SAVE
5071
5072 static int
5073 calc_section_size (MonoDynamicImage *assembly)
5074 {
5075         int nsections = 0;
5076
5077         /* alignment constraints */
5078         mono_image_add_stream_zero (&assembly->code, 4 - (assembly->code.index % 4));
5079         g_assert ((assembly->code.index % 4) == 0);
5080         assembly->meta_size += 3;
5081         assembly->meta_size &= ~3;
5082         mono_image_add_stream_zero (&assembly->resources, 4 - (assembly->resources.index % 4));
5083         g_assert ((assembly->resources.index % 4) == 0);
5084
5085         assembly->sections [MONO_SECTION_TEXT].size = assembly->meta_size + assembly->code.index + assembly->resources.index + assembly->strong_name_size;
5086         assembly->sections [MONO_SECTION_TEXT].attrs = SECT_FLAGS_HAS_CODE | SECT_FLAGS_MEM_EXECUTE | SECT_FLAGS_MEM_READ;
5087         nsections++;
5088
5089         if (assembly->win32_res) {
5090                 guint32 res_size = (assembly->win32_res_size + 3) & ~3;
5091
5092                 assembly->sections [MONO_SECTION_RSRC].size = res_size;
5093                 assembly->sections [MONO_SECTION_RSRC].attrs = SECT_FLAGS_HAS_INITIALIZED_DATA | SECT_FLAGS_MEM_READ;
5094                 nsections++;
5095         }
5096
5097         assembly->sections [MONO_SECTION_RELOC].size = 12;
5098         assembly->sections [MONO_SECTION_RELOC].attrs = SECT_FLAGS_MEM_READ | SECT_FLAGS_MEM_DISCARDABLE | SECT_FLAGS_HAS_INITIALIZED_DATA;
5099         nsections++;
5100
5101         return nsections;
5102 }
5103
5104 typedef struct {
5105         guint32 id;
5106         guint32 offset;
5107         GSList *children;
5108         MonoReflectionWin32Resource *win32_res; /* Only for leaf nodes */
5109 } ResTreeNode;
5110
5111 static int
5112 resource_tree_compare_by_id (gconstpointer a, gconstpointer b)
5113 {
5114         ResTreeNode *t1 = (ResTreeNode*)a;
5115         ResTreeNode *t2 = (ResTreeNode*)b;
5116
5117         return t1->id - t2->id;
5118 }
5119
5120 /*
5121  * resource_tree_create:
5122  *
5123  *  Organize the resources into a resource tree.
5124  */
5125 static ResTreeNode *
5126 resource_tree_create (MonoArray *win32_resources)
5127 {
5128         ResTreeNode *tree, *res_node, *type_node, *lang_node;
5129         GSList *l;
5130         int i;
5131
5132         tree = g_new0 (ResTreeNode, 1);
5133         
5134         for (i = 0; i < mono_array_length (win32_resources); ++i) {
5135                 MonoReflectionWin32Resource *win32_res =
5136                         (MonoReflectionWin32Resource*)mono_array_addr (win32_resources, MonoReflectionWin32Resource, i);
5137
5138                 /* Create node */
5139
5140                 /* FIXME: BUG: this stores managed references in unmanaged memory */
5141                 lang_node = g_new0 (ResTreeNode, 1);
5142                 lang_node->id = win32_res->lang_id;
5143                 lang_node->win32_res = win32_res;
5144
5145                 /* Create type node if neccesary */
5146                 type_node = NULL;
5147                 for (l = tree->children; l; l = l->next)
5148                         if (((ResTreeNode*)(l->data))->id == win32_res->res_type) {
5149                                 type_node = (ResTreeNode*)l->data;
5150                                 break;
5151                         }
5152
5153                 if (!type_node) {
5154                         type_node = g_new0 (ResTreeNode, 1);
5155                         type_node->id = win32_res->res_type;
5156
5157                         /* 
5158                          * The resource types have to be sorted otherwise
5159                          * Windows Explorer can't display the version information.
5160                          */
5161                         tree->children = g_slist_insert_sorted (tree->children, 
5162                                 type_node, resource_tree_compare_by_id);
5163                 }
5164
5165                 /* Create res node if neccesary */
5166                 res_node = NULL;
5167                 for (l = type_node->children; l; l = l->next)
5168                         if (((ResTreeNode*)(l->data))->id == win32_res->res_id) {
5169                                 res_node = (ResTreeNode*)l->data;
5170                                 break;
5171                         }
5172
5173                 if (!res_node) {
5174                         res_node = g_new0 (ResTreeNode, 1);
5175                         res_node->id = win32_res->res_id;
5176                         type_node->children = g_slist_append (type_node->children, res_node);
5177                 }
5178
5179                 res_node->children = g_slist_append (res_node->children, lang_node);
5180         }
5181
5182         return tree;
5183 }
5184
5185 /*
5186  * resource_tree_encode:
5187  * 
5188  *   Encode the resource tree into the format used in the PE file.
5189  */
5190 static void
5191 resource_tree_encode (ResTreeNode *node, char *begin, char *p, char **endbuf)
5192 {
5193         char *entries;
5194         MonoPEResourceDir dir;
5195         MonoPEResourceDirEntry dir_entry;
5196         MonoPEResourceDataEntry data_entry;
5197         GSList *l;
5198         guint32 res_id_entries;
5199
5200         /*
5201          * For the format of the resource directory, see the article
5202          * "An In-Depth Look into the Win32 Portable Executable File Format" by
5203          * Matt Pietrek
5204          */
5205
5206         memset (&dir, 0, sizeof (dir));
5207         memset (&dir_entry, 0, sizeof (dir_entry));
5208         memset (&data_entry, 0, sizeof (data_entry));
5209
5210         g_assert (sizeof (dir) == 16);
5211         g_assert (sizeof (dir_entry) == 8);
5212         g_assert (sizeof (data_entry) == 16);
5213
5214         node->offset = p - begin;
5215
5216         /* IMAGE_RESOURCE_DIRECTORY */
5217         res_id_entries = g_slist_length (node->children);
5218         dir.res_id_entries = GUINT16_TO_LE (res_id_entries);
5219
5220         memcpy (p, &dir, sizeof (dir));
5221         p += sizeof (dir);
5222
5223         /* Reserve space for entries */
5224         entries = p;
5225         p += sizeof (dir_entry) * res_id_entries;
5226
5227         /* Write children */
5228         for (l = node->children; l; l = l->next) {
5229                 ResTreeNode *child = (ResTreeNode*)l->data;
5230
5231                 if (child->win32_res) {
5232                         guint32 size;
5233
5234                         child->offset = p - begin;
5235
5236                         /* IMAGE_RESOURCE_DATA_ENTRY */
5237                         data_entry.rde_data_offset = GUINT32_TO_LE (p - begin + sizeof (data_entry));
5238                         size = mono_array_length (child->win32_res->res_data);
5239                         data_entry.rde_size = GUINT32_TO_LE (size);
5240
5241                         memcpy (p, &data_entry, sizeof (data_entry));
5242                         p += sizeof (data_entry);
5243
5244                         memcpy (p, mono_array_addr (child->win32_res->res_data, char, 0), size);
5245                         p += size;
5246                 } else {
5247                         resource_tree_encode (child, begin, p, &p);
5248                 }
5249         }
5250
5251         /* IMAGE_RESOURCE_ENTRY */
5252         for (l = node->children; l; l = l->next) {
5253                 ResTreeNode *child = (ResTreeNode*)l->data;
5254
5255                 MONO_PE_RES_DIR_ENTRY_SET_NAME (dir_entry, FALSE, child->id);
5256                 MONO_PE_RES_DIR_ENTRY_SET_DIR (dir_entry, !child->win32_res, child->offset);
5257
5258                 memcpy (entries, &dir_entry, sizeof (dir_entry));
5259                 entries += sizeof (dir_entry);
5260         }
5261
5262         *endbuf = p;
5263 }
5264
5265 static void
5266 resource_tree_free (ResTreeNode * node)
5267 {
5268         GSList * list;
5269         for (list = node->children; list; list = list->next)
5270                 resource_tree_free ((ResTreeNode*)list->data);
5271         g_slist_free(node->children);
5272         g_free (node);
5273 }
5274
5275 static void
5276 assembly_add_win32_resources (MonoDynamicImage *assembly, MonoReflectionAssemblyBuilder *assemblyb)
5277 {
5278         char *buf;
5279         char *p;
5280         guint32 size, i;
5281         MonoReflectionWin32Resource *win32_res;
5282         ResTreeNode *tree;
5283
5284         if (!assemblyb->win32_resources)
5285                 return;
5286
5287         /*
5288          * Resources are stored in a three level tree inside the PE file.
5289          * - level one contains a node for each type of resource
5290          * - level two contains a node for each resource
5291          * - level three contains a node for each instance of a resource for a
5292          *   specific language.
5293          */
5294
5295         tree = resource_tree_create (assemblyb->win32_resources);
5296
5297         /* Estimate the size of the encoded tree */
5298         size = 0;
5299         for (i = 0; i < mono_array_length (assemblyb->win32_resources); ++i) {
5300                 win32_res = (MonoReflectionWin32Resource*)mono_array_addr (assemblyb->win32_resources, MonoReflectionWin32Resource, i);
5301                 size += mono_array_length (win32_res->res_data);
5302         }
5303         /* Directory structure */
5304         size += mono_array_length (assemblyb->win32_resources) * 256;
5305         p = buf = g_malloc (size);
5306
5307         resource_tree_encode (tree, p, p, &p);
5308
5309         g_assert (p - buf <= size);
5310
5311         assembly->win32_res = g_malloc (p - buf);
5312         assembly->win32_res_size = p - buf;
5313         memcpy (assembly->win32_res, buf, p - buf);
5314
5315         g_free (buf);
5316         resource_tree_free (tree);
5317 }
5318
5319 static void
5320 fixup_resource_directory (char *res_section, char *p, guint32 rva)
5321 {
5322         MonoPEResourceDir *dir = (MonoPEResourceDir*)p;
5323         int i;
5324
5325         p += sizeof (MonoPEResourceDir);
5326         for (i = 0; i < GUINT16_FROM_LE (dir->res_named_entries) + GUINT16_FROM_LE (dir->res_id_entries); ++i) {
5327                 MonoPEResourceDirEntry *dir_entry = (MonoPEResourceDirEntry*)p;
5328                 char *child = res_section + MONO_PE_RES_DIR_ENTRY_DIR_OFFSET (*dir_entry);
5329                 if (MONO_PE_RES_DIR_ENTRY_IS_DIR (*dir_entry)) {
5330                         fixup_resource_directory (res_section, child, rva);
5331                 } else {
5332                         MonoPEResourceDataEntry *data_entry = (MonoPEResourceDataEntry*)child;
5333                         data_entry->rde_data_offset = GUINT32_TO_LE (GUINT32_FROM_LE (data_entry->rde_data_offset) + rva);
5334                 }
5335
5336                 p += sizeof (MonoPEResourceDirEntry);
5337         }
5338 }
5339
5340 static void
5341 checked_write_file (HANDLE f, gconstpointer buffer, guint32 numbytes)
5342 {
5343         guint32 dummy;
5344         if (!WriteFile (f, buffer, numbytes, &dummy, NULL))
5345                 g_error ("WriteFile returned %d\n", GetLastError ());
5346 }
5347
5348 /*
5349  * mono_image_create_pefile:
5350  * @mb: a module builder object
5351  * 
5352  * This function creates the PE-COFF header, the image sections, the CLI header  * etc. all the data is written in
5353  * assembly->pefile where it can be easily retrieved later in chunks.
5354  */
5355 void
5356 mono_image_create_pefile (MonoReflectionModuleBuilder *mb, HANDLE file)
5357 {
5358         MonoMSDOSHeader *msdos;
5359         MonoDotNetHeader *header;
5360         MonoSectionTable *section;
5361         MonoCLIHeader *cli_header;
5362         guint32 size, image_size, virtual_base, text_offset;
5363         guint32 header_start, section_start, file_offset, virtual_offset;
5364         MonoDynamicImage *assembly;
5365         MonoReflectionAssemblyBuilder *assemblyb;
5366         MonoDynamicStream pefile_stream = {0};
5367         MonoDynamicStream *pefile = &pefile_stream;
5368         int i, nsections;
5369         guint32 *rva, value;
5370         guchar *p;
5371         static const unsigned char msheader[] = {
5372                 0x4d, 0x5a, 0x90, 0x00, 0x03, 0x00, 0x00, 0x00,  0x04, 0x00, 0x00, 0x00, 0xff, 0xff, 0x00, 0x00,
5373                 0xb8, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,  0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
5374                 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
5375                 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,  0x00, 0x00, 0x00, 0x00, 0x80, 0x00, 0x00, 0x00,
5376                 0x0e, 0x1f, 0xba, 0x0e, 0x00, 0xb4, 0x09, 0xcd,  0x21, 0xb8, 0x01, 0x4c, 0xcd, 0x21, 0x54, 0x68,
5377                 0x69, 0x73, 0x20, 0x70, 0x72, 0x6f, 0x67, 0x72,  0x61, 0x6d, 0x20, 0x63, 0x61, 0x6e, 0x6e, 0x6f,
5378                 0x74, 0x20, 0x62, 0x65, 0x20, 0x72, 0x75, 0x6e,  0x20, 0x69, 0x6e, 0x20, 0x44, 0x4f, 0x53, 0x20,
5379                 0x6d, 0x6f, 0x64, 0x65, 0x2e, 0x0d, 0x0d, 0x0a,  0x24, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
5380         };
5381
5382         assemblyb = mb->assemblyb;
5383
5384         mono_image_basic_init (assemblyb);
5385         assembly = mb->dynamic_image;
5386
5387         assembly->pe_kind = assemblyb->pe_kind;
5388         assembly->machine = assemblyb->machine;
5389         ((MonoDynamicImage*)assemblyb->dynamic_assembly->assembly.image)->pe_kind = assemblyb->pe_kind;
5390         ((MonoDynamicImage*)assemblyb->dynamic_assembly->assembly.image)->machine = assemblyb->machine;
5391         
5392         mono_image_build_metadata (mb);
5393
5394         if (mb->is_main && assemblyb->resources) {
5395                 int len = mono_array_length (assemblyb->resources);
5396                 for (i = 0; i < len; ++i)
5397                         assembly_add_resource (mb, assembly, (MonoReflectionResource*)mono_array_addr (assemblyb->resources, MonoReflectionResource, i));
5398         }
5399
5400         if (mb->resources) {
5401                 int len = mono_array_length (mb->resources);
5402                 for (i = 0; i < len; ++i)
5403                         assembly_add_resource (mb, assembly, (MonoReflectionResource*)mono_array_addr (mb->resources, MonoReflectionResource, i));
5404         }
5405
5406         build_compressed_metadata (assembly);
5407
5408         if (mb->is_main)
5409                 assembly_add_win32_resources (assembly, assemblyb);
5410
5411         nsections = calc_section_size (assembly);
5412         
5413         /* The DOS header and stub */
5414         g_assert (sizeof (MonoMSDOSHeader) == sizeof (msheader));
5415         mono_image_add_stream_data (pefile, (char*)msheader, sizeof (msheader));
5416
5417         /* the dotnet header */
5418         header_start = mono_image_add_stream_zero (pefile, sizeof (MonoDotNetHeader));
5419
5420         /* the section tables */
5421         section_start = mono_image_add_stream_zero (pefile, sizeof (MonoSectionTable) * nsections);
5422
5423         file_offset = section_start + sizeof (MonoSectionTable) * nsections;
5424         virtual_offset = VIRT_ALIGN;
5425         image_size = 0;
5426
5427         for (i = 0; i < MONO_SECTION_MAX; ++i) {
5428                 if (!assembly->sections [i].size)
5429                         continue;
5430                 /* align offsets */
5431                 file_offset += FILE_ALIGN - 1;
5432                 file_offset &= ~(FILE_ALIGN - 1);
5433                 virtual_offset += VIRT_ALIGN - 1;
5434                 virtual_offset &= ~(VIRT_ALIGN - 1);
5435
5436                 assembly->sections [i].offset = file_offset;
5437                 assembly->sections [i].rva = virtual_offset;
5438
5439                 file_offset += assembly->sections [i].size;
5440                 virtual_offset += assembly->sections [i].size;
5441                 image_size += (assembly->sections [i].size + VIRT_ALIGN - 1) & ~(VIRT_ALIGN - 1);
5442         }
5443
5444         file_offset += FILE_ALIGN - 1;
5445         file_offset &= ~(FILE_ALIGN - 1);
5446
5447         image_size += section_start + sizeof (MonoSectionTable) * nsections;
5448
5449         /* back-patch info */
5450         msdos = (MonoMSDOSHeader*)pefile->data;
5451         msdos->pe_offset = GUINT32_FROM_LE (sizeof (MonoMSDOSHeader));
5452
5453         header = (MonoDotNetHeader*)(pefile->data + header_start);
5454         header->pesig [0] = 'P';
5455         header->pesig [1] = 'E';
5456         
5457         header->coff.coff_machine = GUINT16_FROM_LE (assemblyb->machine);
5458         header->coff.coff_sections = GUINT16_FROM_LE (nsections);
5459         header->coff.coff_time = GUINT32_FROM_LE (time (NULL));
5460         header->coff.coff_opt_header_size = GUINT16_FROM_LE (sizeof (MonoDotNetHeader) - sizeof (MonoCOFFHeader) - 4);
5461         if (assemblyb->pekind == 1) {
5462                 /* it's a dll */
5463                 header->coff.coff_attributes = GUINT16_FROM_LE (0x210e);
5464         } else {
5465                 /* it's an exe */
5466                 header->coff.coff_attributes = GUINT16_FROM_LE (0x010e);
5467         }
5468
5469         virtual_base = 0x400000; /* FIXME: 0x10000000 if a DLL */
5470
5471         header->pe.pe_magic = GUINT16_FROM_LE (0x10B);
5472         header->pe.pe_major = 6;
5473         header->pe.pe_minor = 0;
5474         size = assembly->sections [MONO_SECTION_TEXT].size;
5475         size += FILE_ALIGN - 1;
5476         size &= ~(FILE_ALIGN - 1);
5477         header->pe.pe_code_size = GUINT32_FROM_LE(size);
5478         size = assembly->sections [MONO_SECTION_RSRC].size;
5479         size += FILE_ALIGN - 1;
5480         size &= ~(FILE_ALIGN - 1);
5481         header->pe.pe_data_size = GUINT32_FROM_LE(size);
5482         g_assert (START_TEXT_RVA == assembly->sections [MONO_SECTION_TEXT].rva);
5483         header->pe.pe_rva_code_base = GUINT32_FROM_LE (assembly->sections [MONO_SECTION_TEXT].rva);
5484         header->pe.pe_rva_data_base = GUINT32_FROM_LE (assembly->sections [MONO_SECTION_RSRC].rva);
5485         /* pe_rva_entry_point always at the beginning of the text section */
5486         header->pe.pe_rva_entry_point = GUINT32_FROM_LE (assembly->sections [MONO_SECTION_TEXT].rva);
5487
5488         header->nt.pe_image_base = GUINT32_FROM_LE (virtual_base);
5489         header->nt.pe_section_align = GUINT32_FROM_LE (VIRT_ALIGN);
5490         header->nt.pe_file_alignment = GUINT32_FROM_LE (FILE_ALIGN);
5491         header->nt.pe_os_major = GUINT16_FROM_LE (4);
5492         header->nt.pe_os_minor = GUINT16_FROM_LE (0);
5493         header->nt.pe_subsys_major = GUINT16_FROM_LE (4);
5494         size = section_start;
5495         size += FILE_ALIGN - 1;
5496         size &= ~(FILE_ALIGN - 1);
5497         header->nt.pe_header_size = GUINT32_FROM_LE (size);
5498         size = image_size;
5499         size += VIRT_ALIGN - 1;
5500         size &= ~(VIRT_ALIGN - 1);
5501         header->nt.pe_image_size = GUINT32_FROM_LE (size);
5502
5503         /*
5504         // Translate the PEFileKind value to the value expected by the Windows loader
5505         */
5506         {
5507                 short kind;
5508
5509                 /*
5510                 // PEFileKinds.Dll == 1
5511                 // PEFileKinds.ConsoleApplication == 2
5512                 // PEFileKinds.WindowApplication == 3
5513                 //
5514                 // need to get:
5515                 //     IMAGE_SUBSYSTEM_WINDOWS_GUI 2 // Image runs in the Windows GUI subsystem.
5516                 //     IMAGE_SUBSYSTEM_WINDOWS_CUI 3 // Image runs in the Windows character subsystem.
5517                 */
5518                 if (assemblyb->pekind == 3)
5519                         kind = 2;
5520                 else
5521                         kind = 3;
5522                 
5523                 header->nt.pe_subsys_required = GUINT16_FROM_LE (kind);
5524         }    
5525         header->nt.pe_stack_reserve = GUINT32_FROM_LE (0x00100000);
5526         header->nt.pe_stack_commit = GUINT32_FROM_LE (0x00001000);
5527         header->nt.pe_heap_reserve = GUINT32_FROM_LE (0x00100000);
5528         header->nt.pe_heap_commit = GUINT32_FROM_LE (0x00001000);
5529         header->nt.pe_loader_flags = GUINT32_FROM_LE (0);
5530         header->nt.pe_data_dir_count = GUINT32_FROM_LE (16);
5531
5532         /* fill data directory entries */
5533
5534         header->datadir.pe_resource_table.size = GUINT32_FROM_LE (assembly->sections [MONO_SECTION_RSRC].size);
5535         header->datadir.pe_resource_table.rva = GUINT32_FROM_LE (assembly->sections [MONO_SECTION_RSRC].rva);
5536
5537         header->datadir.pe_reloc_table.size = GUINT32_FROM_LE (assembly->sections [MONO_SECTION_RELOC].size);
5538         header->datadir.pe_reloc_table.rva = GUINT32_FROM_LE (assembly->sections [MONO_SECTION_RELOC].rva);
5539
5540         header->datadir.pe_cli_header.size = GUINT32_FROM_LE (72);
5541         header->datadir.pe_cli_header.rva = GUINT32_FROM_LE (assembly->text_rva + assembly->cli_header_offset);
5542         header->datadir.pe_iat.size = GUINT32_FROM_LE (8);
5543         header->datadir.pe_iat.rva = GUINT32_FROM_LE (assembly->text_rva + assembly->iat_offset);
5544         /* patch entrypoint name */
5545         if (assemblyb->pekind == 1)
5546                 memcpy (assembly->code.data + assembly->imp_names_offset + 2, "_CorDllMain", 12);
5547         else
5548                 memcpy (assembly->code.data + assembly->imp_names_offset + 2, "_CorExeMain", 12);
5549         /* patch imported function RVA name */
5550         rva = (guint32*)(assembly->code.data + assembly->iat_offset);
5551         *rva = GUINT32_FROM_LE (assembly->text_rva + assembly->imp_names_offset);
5552
5553         /* the import table */
5554         header->datadir.pe_import_table.size = GUINT32_FROM_LE (79); /* FIXME: magic number? */
5555         header->datadir.pe_import_table.rva = GUINT32_FROM_LE (assembly->text_rva + assembly->idt_offset);
5556         /* patch imported dll RVA name and other entries in the dir */
5557         rva = (guint32*)(assembly->code.data + assembly->idt_offset + G_STRUCT_OFFSET (MonoIDT, name_rva));
5558         *rva = GUINT32_FROM_LE (assembly->text_rva + assembly->imp_names_offset + 14); /* 14 is hint+strlen+1 of func name */
5559         rva = (guint32*)(assembly->code.data + assembly->idt_offset + G_STRUCT_OFFSET (MonoIDT, import_address_table_rva));
5560         *rva = GUINT32_FROM_LE (assembly->text_rva + assembly->iat_offset);
5561         rva = (guint32*)(assembly->code.data + assembly->idt_offset + G_STRUCT_OFFSET (MonoIDT, import_lookup_table));
5562         *rva = GUINT32_FROM_LE (assembly->text_rva + assembly->ilt_offset);
5563
5564         p = (guchar*)(assembly->code.data + assembly->ilt_offset);
5565         value = (assembly->text_rva + assembly->imp_names_offset);
5566         *p++ = (value) & 0xff;
5567         *p++ = (value >> 8) & (0xff);
5568         *p++ = (value >> 16) & (0xff);
5569         *p++ = (value >> 24) & (0xff);
5570
5571         /* the CLI header info */
5572         cli_header = (MonoCLIHeader*)(assembly->code.data + assembly->cli_header_offset);
5573         cli_header->ch_size = GUINT32_FROM_LE (72);
5574         cli_header->ch_runtime_major = GUINT16_FROM_LE (2);
5575         if (mono_framework_version () > 1)
5576                 cli_header->ch_runtime_minor = GUINT16_FROM_LE (5);
5577         else 
5578                 cli_header->ch_runtime_minor = GUINT16_FROM_LE (0);
5579         cli_header->ch_flags = GUINT32_FROM_LE (assemblyb->pe_kind);
5580         if (assemblyb->entry_point) {
5581                 guint32 table_idx = 0;
5582                 if (!strcmp (assemblyb->entry_point->object.vtable->klass->name, "MethodBuilder")) {
5583                         MonoReflectionMethodBuilder *methodb = (MonoReflectionMethodBuilder*)assemblyb->entry_point;
5584                         table_idx = methodb->table_idx;
5585                 } else {
5586                         table_idx = GPOINTER_TO_UINT (g_hash_table_lookup (assembly->method_to_table_idx, assemblyb->entry_point->method));
5587                 }
5588                 cli_header->ch_entry_point = GUINT32_FROM_LE (table_idx | MONO_TOKEN_METHOD_DEF);
5589         } else {
5590                 cli_header->ch_entry_point = GUINT32_FROM_LE (0);
5591         }
5592         /* The embedded managed resources */
5593         text_offset = assembly->text_rva + assembly->code.index;
5594         cli_header->ch_resources.rva = GUINT32_FROM_LE (text_offset);
5595         cli_header->ch_resources.size = GUINT32_FROM_LE (assembly->resources.index);
5596         text_offset += assembly->resources.index;
5597         cli_header->ch_metadata.rva = GUINT32_FROM_LE (text_offset);
5598         cli_header->ch_metadata.size = GUINT32_FROM_LE (assembly->meta_size);
5599         text_offset += assembly->meta_size;
5600         if (assembly->strong_name_size) {
5601                 cli_header->ch_strong_name.rva = GUINT32_FROM_LE (text_offset);
5602                 cli_header->ch_strong_name.size = GUINT32_FROM_LE (assembly->strong_name_size);
5603                 text_offset += assembly->strong_name_size;
5604         }
5605
5606         /* write the section tables and section content */
5607         section = (MonoSectionTable*)(pefile->data + section_start);
5608         for (i = 0; i < MONO_SECTION_MAX; ++i) {
5609                 static const char section_names [][7] = {
5610                         ".text", ".rsrc", ".reloc"
5611                 };
5612                 if (!assembly->sections [i].size)
5613                         continue;
5614                 strcpy (section->st_name, section_names [i]);
5615                 /*g_print ("output section %s (%d), size: %d\n", section->st_name, i, assembly->sections [i].size);*/
5616                 section->st_virtual_address = GUINT32_FROM_LE (assembly->sections [i].rva);
5617                 section->st_virtual_size = GUINT32_FROM_LE (assembly->sections [i].size);
5618                 section->st_raw_data_size = GUINT32_FROM_LE (GUINT32_TO_LE (section->st_virtual_size) + (FILE_ALIGN - 1));
5619                 section->st_raw_data_size &= GUINT32_FROM_LE (~(FILE_ALIGN - 1));
5620                 section->st_raw_data_ptr = GUINT32_FROM_LE (assembly->sections [i].offset);
5621                 section->st_flags = GUINT32_FROM_LE (assembly->sections [i].attrs);
5622                 section ++;
5623         }
5624         
5625         checked_write_file (file, pefile->data, pefile->index);
5626         
5627         mono_dynamic_stream_reset (pefile);
5628         
5629         for (i = 0; i < MONO_SECTION_MAX; ++i) {
5630                 if (!assembly->sections [i].size)
5631                         continue;
5632                 
5633                 if (SetFilePointer (file, assembly->sections [i].offset, NULL, FILE_BEGIN) == INVALID_SET_FILE_POINTER)
5634                         g_error ("SetFilePointer returned %d\n", GetLastError ());
5635                 
5636                 switch (i) {
5637                 case MONO_SECTION_TEXT:
5638                         /* patch entry point */
5639                         p = (guchar*)(assembly->code.data + 2);
5640                         value = (virtual_base + assembly->text_rva + assembly->iat_offset);
5641                         *p++ = (value) & 0xff;
5642                         *p++ = (value >> 8) & 0xff;
5643                         *p++ = (value >> 16) & 0xff;
5644                         *p++ = (value >> 24) & 0xff;
5645                 
5646                         checked_write_file (file, assembly->code.data, assembly->code.index);
5647                         checked_write_file (file, assembly->resources.data, assembly->resources.index);
5648                         checked_write_file (file, assembly->image.raw_metadata, assembly->meta_size);
5649                         checked_write_file (file, assembly->strong_name, assembly->strong_name_size);
5650                                 
5651
5652                         g_free (assembly->image.raw_metadata);
5653                         break;
5654                 case MONO_SECTION_RELOC: {
5655                         struct {
5656                                 guint32 page_rva;
5657                                 guint32 block_size;
5658                                 guint16 type_and_offset;
5659                                 guint16 term;
5660                         } reloc;
5661                         
5662                         g_assert (sizeof (reloc) == 12);
5663                         
5664                         reloc.page_rva = GUINT32_FROM_LE (assembly->text_rva);
5665                         reloc.block_size = GUINT32_FROM_LE (12);
5666                         
5667                         /* 
5668                          * the entrypoint is always at the start of the text section 
5669                          * 3 is IMAGE_REL_BASED_HIGHLOW
5670                          * 2 is patch_size_rva - text_rva
5671                          */
5672                         reloc.type_and_offset = GUINT16_FROM_LE ((3 << 12) + (2));
5673                         reloc.term = 0;
5674                         
5675                         checked_write_file (file, &reloc, sizeof (reloc));
5676                         
5677                         break;
5678                 }
5679                 case MONO_SECTION_RSRC:
5680                         if (assembly->win32_res) {
5681
5682                                 /* Fixup the offsets in the IMAGE_RESOURCE_DATA_ENTRY structures */
5683                                 fixup_resource_directory (assembly->win32_res, assembly->win32_res, assembly->sections [i].rva);
5684                                 checked_write_file (file, assembly->win32_res, assembly->win32_res_size);
5685                         }
5686                         break;
5687                 default:
5688                         g_assert_not_reached ();
5689                 }
5690         }
5691         
5692         /* check that the file is properly padded */
5693         if (SetFilePointer (file, file_offset, NULL, FILE_BEGIN) == INVALID_SET_FILE_POINTER)
5694                 g_error ("SetFilePointer returned %d\n", GetLastError ());
5695         if (! SetEndOfFile (file))
5696                 g_error ("SetEndOfFile returned %d\n", GetLastError ());
5697         
5698         mono_dynamic_stream_reset (&assembly->code);
5699         mono_dynamic_stream_reset (&assembly->us);
5700         mono_dynamic_stream_reset (&assembly->blob);
5701         mono_dynamic_stream_reset (&assembly->guid);
5702         mono_dynamic_stream_reset (&assembly->sheap);
5703
5704         g_hash_table_foreach (assembly->blob_cache, (GHFunc)g_free, NULL);
5705         g_hash_table_destroy (assembly->blob_cache);
5706         assembly->blob_cache = NULL;
5707 }
5708
5709 #else /* DISABLE_REFLECTION_EMIT_SAVE */
5710
5711 void
5712 mono_image_create_pefile (MonoReflectionModuleBuilder *mb, HANDLE file)
5713 {
5714         g_assert_not_reached ();
5715 }
5716
5717 #endif /* DISABLE_REFLECTION_EMIT_SAVE */
5718
5719 #ifndef DISABLE_REFLECTION_EMIT
5720
5721 MonoReflectionModule *
5722 mono_image_load_module_dynamic (MonoReflectionAssemblyBuilder *ab, MonoString *fileName)
5723 {
5724         char *name;
5725         MonoImage *image;
5726         MonoImageOpenStatus status;
5727         MonoDynamicAssembly *assembly;
5728         guint32 module_count;
5729         MonoImage **new_modules;
5730         gboolean *new_modules_loaded;
5731         
5732         name = mono_string_to_utf8 (fileName);
5733
5734         image = mono_image_open (name, &status);
5735         if (!image) {
5736                 MonoException *exc;
5737                 if (status == MONO_IMAGE_ERROR_ERRNO)
5738                         exc = mono_get_exception_file_not_found (fileName);
5739                 else
5740                         exc = mono_get_exception_bad_image_format (name);
5741                 g_free (name);
5742                 mono_raise_exception (exc);
5743         }
5744
5745         g_free (name);
5746
5747         assembly = ab->dynamic_assembly;
5748         image->assembly = (MonoAssembly*)assembly;
5749
5750         module_count = image->assembly->image->module_count;
5751         new_modules = g_new0 (MonoImage *, module_count + 1);
5752         new_modules_loaded = g_new0 (gboolean, module_count + 1);
5753
5754         if (image->assembly->image->modules)
5755                 memcpy (new_modules, image->assembly->image->modules, module_count * sizeof (MonoImage *));
5756         if (image->assembly->image->modules_loaded)
5757                 memcpy (new_modules_loaded, image->assembly->image->modules_loaded, module_count * sizeof (gboolean));
5758         new_modules [module_count] = image;
5759         new_modules_loaded [module_count] = TRUE;
5760         mono_image_addref (image);
5761
5762         g_free (image->assembly->image->modules);
5763         image->assembly->image->modules = new_modules;
5764         image->assembly->image->modules_loaded = new_modules_loaded;
5765         image->assembly->image->module_count ++;
5766
5767         mono_assembly_load_references (image, &status);
5768         if (status) {
5769                 mono_image_close (image);
5770                 mono_raise_exception (mono_get_exception_file_not_found (fileName));
5771         }
5772
5773         return mono_module_get_object (mono_domain_get (), image);
5774 }
5775
5776 #endif /* DISABLE_REFLECTION_EMIT */
5777
5778 /*
5779  * We need to return always the same object for MethodInfo, FieldInfo etc..
5780  * but we need to consider the reflected type.
5781  * type uses a different hash, since it uses custom hash/equal functions.
5782  */
5783
5784 typedef struct {
5785         gpointer item;
5786         MonoClass *refclass;
5787 } ReflectedEntry;
5788
5789 static gboolean
5790 reflected_equal (gconstpointer a, gconstpointer b) {
5791         const ReflectedEntry *ea = a;
5792         const ReflectedEntry *eb = b;
5793
5794         return (ea->item == eb->item) && (ea->refclass == eb->refclass);
5795 }
5796
5797 static guint
5798 reflected_hash (gconstpointer a) {
5799         const ReflectedEntry *ea = a;
5800         return mono_aligned_addr_hash (ea->item);
5801 }
5802
5803 #define CHECK_OBJECT(t,p,k)     \
5804         do {    \
5805                 t _obj; \
5806                 ReflectedEntry e;       \
5807                 e.item = (p);   \
5808                 e.refclass = (k);       \
5809                 mono_domain_lock (domain);      \
5810                 if (!domain->refobject_hash)    \
5811                         domain->refobject_hash = mono_g_hash_table_new_type (reflected_hash, reflected_equal, MONO_HASH_VALUE_GC);      \
5812                 if ((_obj = mono_g_hash_table_lookup (domain->refobject_hash, &e))) {   \
5813                         mono_domain_unlock (domain);    \
5814                         return _obj;    \
5815                 }       \
5816         mono_domain_unlock (domain); \
5817         } while (0)
5818
5819 #ifdef HAVE_BOEHM_GC
5820 /* ReflectedEntry doesn't need to be GC tracked */
5821 #define ALLOC_REFENTRY g_new0 (ReflectedEntry, 1)
5822 #define FREE_REFENTRY(entry) g_free ((entry))
5823 #define REFENTRY_REQUIRES_CLEANUP
5824 #else
5825 #define ALLOC_REFENTRY mono_mempool_alloc (domain->mp, sizeof (ReflectedEntry))
5826 /* FIXME: */
5827 #define FREE_REFENTRY(entry)
5828 #endif
5829
5830 #define CACHE_OBJECT(t,p,o,k)   \
5831         do {    \
5832                 t _obj; \
5833         ReflectedEntry pe; \
5834         pe.item = (p); \
5835         pe.refclass = (k); \
5836         mono_domain_lock (domain); \
5837                 if (!domain->refobject_hash)    \
5838                         domain->refobject_hash = mono_g_hash_table_new_type (reflected_hash, reflected_equal, MONO_HASH_VALUE_GC);      \
5839         _obj = mono_g_hash_table_lookup (domain->refobject_hash, &pe); \
5840         if (!_obj) { \
5841                     ReflectedEntry *e = ALLOC_REFENTRY;         \
5842                     e->item = (p);      \
5843                     e->refclass = (k);  \
5844                     mono_g_hash_table_insert (domain->refobject_hash, e,o);     \
5845             _obj = o; \
5846         } \
5847                 mono_domain_unlock (domain);    \
5848         return _obj; \
5849         } while (0)
5850
5851 static void
5852 clear_cached_object (MonoDomain *domain, gpointer o, MonoClass *klass)
5853 {
5854         mono_domain_lock (domain);
5855         if (domain->refobject_hash) {
5856         ReflectedEntry pe;
5857                 gpointer orig_pe, orig_value;
5858
5859                 pe.item = o;
5860                 pe.refclass = klass;
5861                 if (mono_g_hash_table_lookup_extended (domain->refobject_hash, &pe, &orig_pe, &orig_value)) {
5862                         mono_g_hash_table_remove (domain->refobject_hash, &pe);
5863                         FREE_REFENTRY (orig_pe);
5864                 }
5865         }
5866         mono_domain_unlock (domain);
5867 }
5868
5869 #ifdef REFENTRY_REQUIRES_CLEANUP
5870 static void
5871 cleanup_refobject_hash (gpointer key, gpointer value, gpointer user_data)
5872 {
5873         FREE_REFENTRY (key);
5874 }
5875 #endif
5876
5877 void
5878 mono_reflection_cleanup_domain (MonoDomain *domain)
5879 {
5880         if (domain->refobject_hash) {
5881 /*let's avoid scanning the whole hashtable if not needed*/
5882 #ifdef REFENTRY_REQUIRES_CLEANUP
5883                 mono_g_hash_table_foreach (domain->refobject_hash, cleanup_refobject_hash, NULL);
5884 #endif
5885                 mono_g_hash_table_destroy (domain->refobject_hash);
5886                 domain->refobject_hash = NULL;
5887         }
5888 }
5889
5890 #ifndef DISABLE_REFLECTION_EMIT
5891 static gpointer
5892 register_assembly (MonoDomain *domain, MonoReflectionAssembly *res, MonoAssembly *assembly)
5893 {
5894         CACHE_OBJECT (MonoReflectionAssembly *, assembly, res, NULL);
5895 }
5896
5897 static gpointer
5898 register_module (MonoDomain *domain, MonoReflectionModuleBuilder *res, MonoDynamicImage *module)
5899 {
5900         CACHE_OBJECT (MonoReflectionModuleBuilder *, module, res, NULL);
5901 }
5902
5903 void
5904 mono_image_module_basic_init (MonoReflectionModuleBuilder *moduleb)
5905 {
5906         MonoDynamicImage *image = moduleb->dynamic_image;
5907         MonoReflectionAssemblyBuilder *ab = moduleb->assemblyb;
5908         if (!image) {
5909                 int module_count;
5910                 MonoImage **new_modules;
5911                 MonoImage *ass;
5912                 /*
5913                  * FIXME: we already created an image in mono_image_basic_init (), but
5914                  * we don't know which module it belongs to, since that is only 
5915                  * determined at assembly save time.
5916                  */
5917                 /*image = (MonoDynamicImage*)ab->dynamic_assembly->assembly.image; */
5918                 image = create_dynamic_mono_image (ab->dynamic_assembly, mono_string_to_utf8 (ab->name), mono_string_to_utf8 (moduleb->module.fqname));
5919
5920                 moduleb->module.image = &image->image;
5921                 moduleb->dynamic_image = image;
5922                 register_module (mono_object_domain (moduleb), moduleb, image);
5923
5924                 /* register the module with the assembly */
5925                 ass = ab->dynamic_assembly->assembly.image;
5926                 module_count = ass->module_count;
5927                 new_modules = g_new0 (MonoImage *, module_count + 1);
5928
5929                 if (ass->modules)
5930                         memcpy (new_modules, ass->modules, module_count * sizeof (MonoImage *));
5931                 new_modules [module_count] = &image->image;
5932                 mono_image_addref (&image->image);
5933
5934                 g_free (ass->modules);
5935                 ass->modules = new_modules;
5936                 ass->module_count ++;
5937         }
5938 }
5939
5940 void
5941 mono_image_set_wrappers_type (MonoReflectionModuleBuilder *moduleb, MonoReflectionType *type)
5942 {
5943         MonoDynamicImage *image = moduleb->dynamic_image;
5944
5945         g_assert (type->type);
5946         image->wrappers_type = mono_class_from_mono_type (type->type);
5947 }
5948
5949 #endif
5950
5951 /*
5952  * mono_assembly_get_object:
5953  * @domain: an app domain
5954  * @assembly: an assembly
5955  *
5956  * Return an System.Reflection.Assembly object representing the MonoAssembly @assembly.
5957  */
5958 MonoReflectionAssembly*
5959 mono_assembly_get_object (MonoDomain *domain, MonoAssembly *assembly)
5960 {
5961         static MonoClass *System_Reflection_Assembly;
5962         MonoReflectionAssembly *res;
5963         
5964         CHECK_OBJECT (MonoReflectionAssembly *, assembly, NULL);
5965         if (!System_Reflection_Assembly)
5966                 System_Reflection_Assembly = mono_class_from_name (
5967                         mono_defaults.corlib, "System.Reflection", "Assembly");
5968         res = (MonoReflectionAssembly *)mono_object_new (domain, System_Reflection_Assembly);
5969         res->assembly = assembly;
5970
5971         CACHE_OBJECT (MonoReflectionAssembly *, assembly, res, NULL);
5972 }
5973
5974
5975
5976 MonoReflectionModule*   
5977 mono_module_get_object   (MonoDomain *domain, MonoImage *image)
5978 {
5979         static MonoClass *System_Reflection_Module;
5980         MonoReflectionModule *res;
5981         char* basename;
5982         
5983         CHECK_OBJECT (MonoReflectionModule *, image, NULL);
5984         if (!System_Reflection_Module)
5985                 System_Reflection_Module = mono_class_from_name (
5986                         mono_defaults.corlib, "System.Reflection", "Module");
5987         res = (MonoReflectionModule *)mono_object_new (domain, System_Reflection_Module);
5988
5989         res->image = image;
5990         MONO_OBJECT_SETREF (res, assembly, (MonoReflectionAssembly *) mono_assembly_get_object(domain, image->assembly));
5991
5992         MONO_OBJECT_SETREF (res, fqname, mono_string_new (domain, image->name));
5993         basename = g_path_get_basename (image->name);
5994         MONO_OBJECT_SETREF (res, name, mono_string_new (domain, basename));
5995         MONO_OBJECT_SETREF (res, scopename, mono_string_new (domain, image->module_name));
5996         
5997         g_free (basename);
5998
5999         if (image->assembly->image == image) {
6000                 res->token = mono_metadata_make_token (MONO_TABLE_MODULE, 1);
6001         } else {
6002                 int i;
6003                 res->token = 0;
6004                 if (image->assembly->image->modules) {
6005                         for (i = 0; i < image->assembly->image->module_count; i++) {
6006                                 if (image->assembly->image->modules [i] == image)
6007                                         res->token = mono_metadata_make_token (MONO_TABLE_MODULEREF, i + 1);
6008                         }
6009                         g_assert (res->token);
6010                 }
6011         }
6012
6013         CACHE_OBJECT (MonoReflectionModule *, image, res, NULL);
6014 }
6015
6016 MonoReflectionModule*   
6017 mono_module_file_get_object (MonoDomain *domain, MonoImage *image, int table_index)
6018 {
6019         static MonoClass *System_Reflection_Module;
6020         MonoReflectionModule *res;
6021         MonoTableInfo *table;
6022         guint32 cols [MONO_FILE_SIZE];
6023         const char *name;
6024         guint32 i, name_idx;
6025         const char *val;
6026         
6027         if (!System_Reflection_Module)
6028                 System_Reflection_Module = mono_class_from_name (
6029                         mono_defaults.corlib, "System.Reflection", "Module");
6030         res = (MonoReflectionModule *)mono_object_new (domain, System_Reflection_Module);
6031
6032         table = &image->tables [MONO_TABLE_FILE];
6033         g_assert (table_index < table->rows);
6034         mono_metadata_decode_row (table, table_index, cols, MONO_FILE_SIZE);
6035
6036         res->image = NULL;
6037         MONO_OBJECT_SETREF (res, assembly, (MonoReflectionAssembly *) mono_assembly_get_object(domain, image->assembly));
6038         name = mono_metadata_string_heap (image, cols [MONO_FILE_NAME]);
6039
6040         /* Check whenever the row has a corresponding row in the moduleref table */
6041         table = &image->tables [MONO_TABLE_MODULEREF];
6042         for (i = 0; i < table->rows; ++i) {
6043                 name_idx = mono_metadata_decode_row_col (table, i, MONO_MODULEREF_NAME);
6044                 val = mono_metadata_string_heap (image, name_idx);
6045                 if (strcmp (val, name) == 0)
6046                         res->image = image->modules [i];
6047         }
6048
6049         MONO_OBJECT_SETREF (res, fqname, mono_string_new (domain, name));
6050         MONO_OBJECT_SETREF (res, name, mono_string_new (domain, name));
6051         MONO_OBJECT_SETREF (res, scopename, mono_string_new (domain, name));
6052         res->is_resource = cols [MONO_FILE_FLAGS] && FILE_CONTAINS_NO_METADATA;
6053         res->token = mono_metadata_make_token (MONO_TABLE_FILE, table_index + 1);
6054
6055         return res;
6056 }
6057
6058 static gboolean
6059 mymono_metadata_type_equal (MonoType *t1, MonoType *t2)
6060 {
6061         if ((t1->type != t2->type) ||
6062             (t1->byref != t2->byref))
6063                 return FALSE;
6064
6065         switch (t1->type) {
6066         case MONO_TYPE_VOID:
6067         case MONO_TYPE_BOOLEAN:
6068         case MONO_TYPE_CHAR:
6069         case MONO_TYPE_I1:
6070         case MONO_TYPE_U1:
6071         case MONO_TYPE_I2:
6072         case MONO_TYPE_U2:
6073         case MONO_TYPE_I4:
6074         case MONO_TYPE_U4:
6075         case MONO_TYPE_I8:
6076         case MONO_TYPE_U8:
6077         case MONO_TYPE_R4:
6078         case MONO_TYPE_R8:
6079         case MONO_TYPE_STRING:
6080         case MONO_TYPE_I:
6081         case MONO_TYPE_U:
6082         case MONO_TYPE_OBJECT:
6083         case MONO_TYPE_TYPEDBYREF:
6084                 return TRUE;
6085         case MONO_TYPE_VALUETYPE:
6086         case MONO_TYPE_CLASS:
6087         case MONO_TYPE_SZARRAY:
6088                 return t1->data.klass == t2->data.klass;
6089         case MONO_TYPE_PTR:
6090                 return mymono_metadata_type_equal (t1->data.type, t2->data.type);
6091         case MONO_TYPE_ARRAY:
6092                 if (t1->data.array->rank != t2->data.array->rank)
6093                         return FALSE;
6094                 return t1->data.array->eklass == t2->data.array->eklass;
6095         case MONO_TYPE_GENERICINST: {
6096                 int i;
6097                 MonoGenericInst *i1 = t1->data.generic_class->context.class_inst;
6098                 MonoGenericInst *i2 = t2->data.generic_class->context.class_inst;
6099                 if (i1->type_argc != i2->type_argc)
6100                         return FALSE;
6101                 if (!mono_metadata_type_equal (&t1->data.generic_class->container_class->byval_arg,
6102                                                &t2->data.generic_class->container_class->byval_arg))
6103                         return FALSE;
6104                 /* FIXME: we should probably just compare the instance pointers directly.  */
6105                 for (i = 0; i < i1->type_argc; ++i) {
6106                         if (!mono_metadata_type_equal (i1->type_argv [i], i2->type_argv [i]))
6107                                 return FALSE;
6108                 }
6109                 return TRUE;
6110         }
6111         case MONO_TYPE_VAR:
6112         case MONO_TYPE_MVAR:
6113                 return t1->data.generic_param == t2->data.generic_param;
6114         default:
6115                 g_error ("implement type compare for %0x!", t1->type);
6116                 return FALSE;
6117         }
6118
6119         return FALSE;
6120 }
6121
6122 static guint
6123 mymono_metadata_type_hash (MonoType *t1)
6124 {
6125         guint hash;
6126
6127         hash = t1->type;
6128
6129         hash |= t1->byref << 6; /* do not collide with t1->type values */
6130         switch (t1->type) {
6131         case MONO_TYPE_VALUETYPE:
6132         case MONO_TYPE_CLASS:
6133         case MONO_TYPE_SZARRAY:
6134                 /* check if the distribution is good enough */
6135                 return ((hash << 5) - hash) ^ g_str_hash (t1->data.klass->name);
6136         case MONO_TYPE_PTR:
6137                 return ((hash << 5) - hash) ^ mymono_metadata_type_hash (t1->data.type);
6138         case MONO_TYPE_GENERICINST: {
6139                 int i;
6140                 MonoGenericInst *inst = t1->data.generic_class->context.class_inst;
6141                 hash += g_str_hash (t1->data.generic_class->container_class->name);
6142                 hash *= 13;
6143                 for (i = 0; i < inst->type_argc; ++i) {
6144                         hash += mymono_metadata_type_hash (inst->type_argv [i]);
6145                         hash *= 13;
6146                 }
6147                 return hash;
6148         }
6149         }
6150         return hash;
6151 }
6152
6153 static MonoReflectionGenericClass*
6154 mono_generic_class_get_object (MonoDomain *domain, MonoType *geninst)
6155 {
6156         static MonoClass *System_Reflection_MonoGenericClass;
6157         MonoReflectionGenericClass *res;
6158         MonoClass *klass, *gklass;
6159         MonoGenericInst *ginst;
6160         MonoArray *type_args;
6161         int i;
6162
6163         if (!System_Reflection_MonoGenericClass) {
6164                 System_Reflection_MonoGenericClass = mono_class_from_name (
6165                         mono_defaults.corlib, "System.Reflection", "MonoGenericClass");
6166                 g_assert (System_Reflection_MonoGenericClass);
6167         }
6168
6169         klass = mono_class_from_mono_type (geninst);
6170         gklass = klass->generic_class->container_class;
6171
6172         mono_class_init (klass);
6173
6174 #ifdef HAVE_SGEN_GC
6175         res = (MonoReflectionGenericClass *) mono_gc_alloc_pinned_obj (mono_class_vtable (domain, System_Reflection_MonoGenericClass), mono_class_instance_size (System_Reflection_MonoGenericClass));
6176 #else
6177         res = (MonoReflectionGenericClass *) mono_object_new (domain, System_Reflection_MonoGenericClass);
6178 #endif
6179
6180         res->type.type = geninst;
6181         g_assert (gklass->reflection_info);
6182         g_assert (!strcmp (((MonoObject*)gklass->reflection_info)->vtable->klass->name, "TypeBuilder"));
6183         MONO_OBJECT_SETREF (res, generic_type, gklass->reflection_info);
6184
6185         ginst = klass->generic_class->context.class_inst;
6186         type_args = mono_array_new (domain, mono_defaults.systemtype_class, ginst->type_argc);
6187         for (i = 0; i < ginst->type_argc; ++i)
6188                 mono_array_setref (type_args, i, mono_type_get_object (domain, ginst->type_argv [i]));
6189         MONO_OBJECT_SETREF (res, type_arguments, type_args);
6190
6191         return res;
6192 }
6193
6194 static gboolean
6195 verify_safe_for_managed_space (MonoType *type)
6196 {
6197         switch (type->type) {
6198 #ifdef DEBUG_HARDER
6199         case MONO_TYPE_ARRAY:
6200                 return verify_safe_for_managed_space (&type->data.array->eklass->byval_arg);
6201         case MONO_TYPE_PTR:
6202                 return verify_safe_for_managed_space (type->data.type);
6203         case MONO_TYPE_SZARRAY:
6204                 return verify_safe_for_managed_space (&type->data.klass->byval_arg);
6205         case MONO_TYPE_GENERICINST: {
6206                 MonoGenericInst *inst = type->data.generic_class->inst;
6207                 int i;
6208                 if (!inst->is_open)
6209                         break;
6210                 for (i = 0; i < inst->type_argc; ++i)
6211                         if (!verify_safe_for_managed_space (inst->type_argv [i]))
6212                                 return FALSE;
6213                 break;
6214         }
6215 #endif
6216         case MONO_TYPE_VAR:
6217         case MONO_TYPE_MVAR:
6218                 return TRUE;
6219         }
6220         return TRUE;
6221 }
6222
6223 /*
6224  * mono_type_get_object:
6225  * @domain: an app domain
6226  * @type: a type
6227  *
6228  * Return an System.MonoType object representing the type @type.
6229  */
6230 MonoReflectionType*
6231 mono_type_get_object (MonoDomain *domain, MonoType *type)
6232 {
6233         MonoReflectionType *res;
6234         MonoClass *klass = mono_class_from_mono_type (type);
6235
6236         /*we must avoid using @type as it might have come
6237          * from a mono_metadata_type_dup and the caller
6238          * expects that is can be freed.
6239          * Using the right type from 
6240          */
6241         type = klass->byval_arg.byref == type->byref ? &klass->byval_arg : &klass->this_arg;
6242
6243         /* void is very common */
6244         if (type->type == MONO_TYPE_VOID && domain->typeof_void)
6245                 return (MonoReflectionType*)domain->typeof_void;
6246
6247         /*
6248          * If the vtable of the given class was already created, we can use
6249          * the MonoType from there and avoid all locking and hash table lookups.
6250          * 
6251          * We cannot do this for TypeBuilders as mono_reflection_create_runtime_class expects
6252          * that the resulting object is different.   
6253          */
6254         if (type == &klass->byval_arg && !klass->image->dynamic) {
6255                 MonoVTable *vtable = mono_class_try_get_vtable (domain, klass);
6256                 if (vtable && vtable->type)
6257                         return vtable->type;
6258         }
6259
6260         mono_loader_lock (); /*FIXME mono_class_init and mono_class_vtable acquire it*/
6261         mono_domain_lock (domain);
6262         if (!domain->type_hash)
6263                 domain->type_hash = mono_g_hash_table_new_type ((GHashFunc)mymono_metadata_type_hash, 
6264                                 (GCompareFunc)mymono_metadata_type_equal, MONO_HASH_VALUE_GC);
6265         if ((res = mono_g_hash_table_lookup (domain->type_hash, type))) {
6266                 mono_domain_unlock (domain);
6267                 mono_loader_unlock ();
6268                 return res;
6269         }
6270         /* Create a MonoGenericClass object for instantiations of not finished TypeBuilders */
6271         if ((type->type == MONO_TYPE_GENERICINST) && type->data.generic_class->is_dynamic && !type->data.generic_class->container_class->wastypebuilder) {
6272                 res = (MonoReflectionType *)mono_generic_class_get_object (domain, type);
6273                 mono_g_hash_table_insert (domain->type_hash, type, res);
6274                 mono_domain_unlock (domain);
6275                 mono_loader_unlock ();
6276                 return res;
6277         }
6278
6279         if (!verify_safe_for_managed_space (type)) {
6280                 mono_domain_unlock (domain);
6281                 mono_loader_unlock ();
6282                 mono_raise_exception (mono_get_exception_invalid_operation ("This type cannot be propagated to managed space"));
6283         }
6284
6285         if (klass->reflection_info && !klass->wastypebuilder) {
6286                 /* g_assert_not_reached (); */
6287                 /* should this be considered an error condition? */
6288                 if (!type->byref) {
6289                         mono_domain_unlock (domain);
6290                         mono_loader_unlock ();
6291                         return klass->reflection_info;
6292                 }
6293         }
6294         // FIXME: Get rid of this, do it in the icalls for Type
6295         mono_class_init (klass);
6296 #ifdef HAVE_SGEN_GC
6297         res = (MonoReflectionType *)mono_gc_alloc_pinned_obj (mono_class_vtable (domain, mono_defaults.monotype_class), mono_class_instance_size (mono_defaults.monotype_class));
6298 #else
6299         res = (MonoReflectionType *)mono_object_new (domain, mono_defaults.monotype_class);
6300 #endif
6301         res->type = type;
6302         mono_g_hash_table_insert (domain->type_hash, type, res);
6303
6304         if (type->type == MONO_TYPE_VOID)
6305                 domain->typeof_void = (MonoObject*)res;
6306
6307         mono_domain_unlock (domain);
6308         mono_loader_unlock ();
6309         return res;
6310 }
6311
6312 /*
6313  * mono_method_get_object:
6314  * @domain: an app domain
6315  * @method: a method
6316  * @refclass: the reflected type (can be NULL)
6317  *
6318  * Return an System.Reflection.MonoMethod object representing the method @method.
6319  */
6320 MonoReflectionMethod*
6321 mono_method_get_object (MonoDomain *domain, MonoMethod *method, MonoClass *refclass)
6322 {
6323         /*
6324          * We use the same C representation for methods and constructors, but the type 
6325          * name in C# is different.
6326          */
6327         static MonoClass *System_Reflection_MonoMethod = NULL;
6328         static MonoClass *System_Reflection_MonoCMethod = NULL;
6329         static MonoClass *System_Reflection_MonoGenericMethod = NULL;
6330         static MonoClass *System_Reflection_MonoGenericCMethod = NULL;
6331         MonoClass *klass;
6332         MonoReflectionMethod *ret;
6333
6334         if (method->is_inflated) {
6335                 MonoReflectionGenericMethod *gret;
6336
6337                 refclass = method->klass;
6338                 CHECK_OBJECT (MonoReflectionMethod *, method, refclass);
6339                 if ((*method->name == '.') && (!strcmp (method->name, ".ctor") || !strcmp (method->name, ".cctor"))) {
6340                         if (!System_Reflection_MonoGenericCMethod)
6341                                 System_Reflection_MonoGenericCMethod = mono_class_from_name (mono_defaults.corlib, "System.Reflection", "MonoGenericCMethod");
6342                         klass = System_Reflection_MonoGenericCMethod;
6343                 } else {
6344                         if (!System_Reflection_MonoGenericMethod)
6345                                 System_Reflection_MonoGenericMethod = mono_class_from_name (mono_defaults.corlib, "System.Reflection", "MonoGenericMethod");
6346                         klass = System_Reflection_MonoGenericMethod;
6347                 }
6348                 gret = (MonoReflectionGenericMethod*)mono_object_new (domain, klass);
6349                 gret->method.method = method;
6350                 MONO_OBJECT_SETREF (gret, method.name, mono_string_new (domain, method->name));
6351                 MONO_OBJECT_SETREF (gret, method.reftype, mono_type_get_object (domain, &refclass->byval_arg));
6352                 CACHE_OBJECT (MonoReflectionMethod *, method, (MonoReflectionMethod*)gret, refclass);
6353         }
6354
6355         if (!refclass)
6356                 refclass = method->klass;
6357
6358         CHECK_OBJECT (MonoReflectionMethod *, method, refclass);
6359         if (*method->name == '.' && (strcmp (method->name, ".ctor") == 0 || strcmp (method->name, ".cctor") == 0)) {
6360                 if (!System_Reflection_MonoCMethod)
6361                         System_Reflection_MonoCMethod = mono_class_from_name (mono_defaults.corlib, "System.Reflection", "MonoCMethod");
6362                 klass = System_Reflection_MonoCMethod;
6363         }
6364         else {
6365                 if (!System_Reflection_MonoMethod)
6366                         System_Reflection_MonoMethod = mono_class_from_name (mono_defaults.corlib, "System.Reflection", "MonoMethod");
6367                 klass = System_Reflection_MonoMethod;
6368         }
6369         ret = (MonoReflectionMethod*)mono_object_new (domain, klass);
6370         ret->method = method;
6371         MONO_OBJECT_SETREF (ret, reftype, mono_type_get_object (domain, &refclass->byval_arg));
6372         CACHE_OBJECT (MonoReflectionMethod *, method, ret, refclass);
6373 }
6374
6375 /*
6376  * mono_method_clear_object:
6377  *
6378  *   Clear the cached reflection objects for the dynamic method METHOD.
6379  */
6380 void
6381 mono_method_clear_object (MonoDomain *domain, MonoMethod *method)
6382 {
6383         MonoClass *klass;
6384         g_assert (method->dynamic);
6385
6386         klass = method->klass;
6387         while (klass) {
6388                 clear_cached_object (domain, method, klass);
6389                 klass = klass->parent;
6390         }
6391         /* Added by mono_param_get_objects () */
6392         clear_cached_object (domain, &(method->signature), NULL);
6393         klass = method->klass;
6394         while (klass) {
6395                 clear_cached_object (domain, &(method->signature), klass);
6396                 klass = klass->parent;
6397         }
6398 }
6399
6400 /*
6401  * mono_field_get_object:
6402  * @domain: an app domain
6403  * @klass: a type
6404  * @field: a field
6405  *
6406  * Return an System.Reflection.MonoField object representing the field @field
6407  * in class @klass.
6408  */
6409 MonoReflectionField*
6410 mono_field_get_object (MonoDomain *domain, MonoClass *klass, MonoClassField *field)
6411 {
6412         MonoReflectionField *res;
6413         static MonoClass *monofield_klass;
6414
6415         CHECK_OBJECT (MonoReflectionField *, field, klass);
6416         if (!monofield_klass)
6417                 monofield_klass = mono_class_from_name (mono_defaults.corlib, "System.Reflection", "MonoField");
6418         res = (MonoReflectionField *)mono_object_new (domain, monofield_klass);
6419         res->klass = klass;
6420         res->field = field;
6421         MONO_OBJECT_SETREF (res, name, mono_string_new (domain, mono_field_get_name (field)));
6422         if (is_field_on_inst (field))
6423                 res->attrs = get_field_on_inst_generic_type (field)->attrs;
6424         else
6425                 res->attrs = field->type->attrs;
6426         MONO_OBJECT_SETREF (res, type, mono_type_get_object (domain, field->type));
6427         CACHE_OBJECT (MonoReflectionField *, field, res, klass);
6428 }
6429
6430 /*
6431  * mono_property_get_object:
6432  * @domain: an app domain
6433  * @klass: a type
6434  * @property: a property
6435  *
6436  * Return an System.Reflection.MonoProperty object representing the property @property
6437  * in class @klass.
6438  */
6439 MonoReflectionProperty*
6440 mono_property_get_object (MonoDomain *domain, MonoClass *klass, MonoProperty *property)
6441 {
6442         MonoReflectionProperty *res;
6443         static MonoClass *monoproperty_klass;
6444
6445         CHECK_OBJECT (MonoReflectionProperty *, property, klass);
6446         if (!monoproperty_klass)
6447                 monoproperty_klass = mono_class_from_name (mono_defaults.corlib, "System.Reflection", "MonoProperty");
6448         res = (MonoReflectionProperty *)mono_object_new (domain, monoproperty_klass);
6449         res->klass = klass;
6450         res->property = property;
6451         CACHE_OBJECT (MonoReflectionProperty *, property, res, klass);
6452 }
6453
6454 /*
6455  * mono_event_get_object:
6456  * @domain: an app domain
6457  * @klass: a type
6458  * @event: a event
6459  *
6460  * Return an System.Reflection.MonoEvent object representing the event @event
6461  * in class @klass.
6462  */
6463 MonoReflectionEvent*
6464 mono_event_get_object (MonoDomain *domain, MonoClass *klass, MonoEvent *event)
6465 {
6466         MonoReflectionEvent *res;
6467         MonoReflectionMonoEvent *mono_event;
6468         static MonoClass *monoevent_klass;
6469
6470         CHECK_OBJECT (MonoReflectionEvent *, event, klass);
6471         if (!monoevent_klass)
6472                 monoevent_klass = mono_class_from_name (mono_defaults.corlib, "System.Reflection", "MonoEvent");
6473         mono_event = (MonoReflectionMonoEvent *)mono_object_new (domain, monoevent_klass);
6474         mono_event->klass = klass;
6475         mono_event->event = event;
6476         res = (MonoReflectionEvent*)mono_event;
6477         CACHE_OBJECT (MonoReflectionEvent *, event, res, klass);
6478 }
6479
6480 /**
6481  * mono_get_reflection_missing_object:
6482  * @domain: Domain where the object lives
6483  *
6484  * Returns the System.Reflection.Missing.Value singleton object
6485  * (of type System.Reflection.Missing).
6486  *
6487  * Used as the value for ParameterInfo.DefaultValue when Optional
6488  * is present
6489  */
6490 static MonoObject *
6491 mono_get_reflection_missing_object (MonoDomain *domain)
6492 {
6493         MonoObject *obj;
6494         static MonoClassField *missing_value_field = NULL;
6495         
6496         if (!missing_value_field) {
6497                 MonoClass *missing_klass;
6498                 missing_klass = mono_class_from_name (mono_defaults.corlib, "System.Reflection", "Missing");
6499                 mono_class_init (missing_klass);
6500                 missing_value_field = mono_class_get_field_from_name (missing_klass, "Value");
6501                 g_assert (missing_value_field);
6502         }
6503         obj = mono_field_get_value_object (domain, missing_value_field, NULL); 
6504         g_assert (obj);
6505         return obj;
6506 }
6507
6508 static MonoObject*
6509 get_dbnull (MonoDomain *domain, MonoObject **dbnull)
6510 {
6511         if (!*dbnull)
6512                 *dbnull = mono_get_dbnull_object (domain);
6513         return *dbnull;
6514 }
6515
6516 static MonoObject*
6517 get_reflection_missing (MonoDomain *domain, MonoObject **reflection_missing)
6518 {
6519         if (!*reflection_missing)
6520                 *reflection_missing = mono_get_reflection_missing_object (domain);
6521         return *reflection_missing;
6522 }
6523
6524 /*
6525  * mono_param_get_objects:
6526  * @domain: an app domain
6527  * @method: a method
6528  *
6529  * Return an System.Reflection.ParameterInfo array object representing the parameters
6530  * in the method @method.
6531  */
6532 MonoArray*
6533 mono_param_get_objects_internal (MonoDomain *domain, MonoMethod *method, MonoClass *refclass)
6534 {
6535         static MonoClass *System_Reflection_ParameterInfo;
6536         static MonoClass *System_Reflection_ParameterInfo_array;
6537         MonoArray *res = NULL;
6538         MonoReflectionMethod *member = NULL;
6539         MonoReflectionParameter *param = NULL;
6540         char **names, **blobs = NULL;
6541         guint32 *types = NULL;
6542         MonoType *type = NULL;
6543         MonoObject *dbnull = NULL;
6544         MonoObject *missing = NULL;
6545         MonoMarshalSpec **mspecs;
6546         MonoMethodSignature *sig;
6547         MonoVTable *pinfo_vtable;
6548         int i;
6549
6550         if (!System_Reflection_ParameterInfo_array) {
6551                 MonoClass *klass;
6552
6553                 klass = mono_class_from_name (mono_defaults.corlib, "System.Reflection", "ParameterInfo");
6554                 mono_memory_barrier ();
6555                 System_Reflection_ParameterInfo = klass; 
6556         
6557                 klass = mono_array_class_get (klass, 1);
6558                 mono_memory_barrier ();
6559                 System_Reflection_ParameterInfo_array = klass;
6560         }
6561         
6562         if (!mono_method_signature (method)->param_count)
6563                 return mono_array_new_specific (mono_class_vtable (domain, System_Reflection_ParameterInfo_array), 0);
6564
6565         /* Note: the cache is based on the address of the signature into the method
6566          * since we already cache MethodInfos with the method as keys.
6567          */
6568         CHECK_OBJECT (MonoArray*, &(method->signature), refclass);
6569
6570         sig = mono_method_signature (method);
6571         member = mono_method_get_object (domain, method, refclass);
6572         names = g_new (char *, sig->param_count);
6573         mono_method_get_param_names (method, (const char **) names);
6574
6575         mspecs = g_new (MonoMarshalSpec*, sig->param_count + 1);
6576         mono_method_get_marshal_info (method, mspecs);
6577
6578         res = mono_array_new_specific (mono_class_vtable (domain, System_Reflection_ParameterInfo_array), sig->param_count);
6579         pinfo_vtable = mono_class_vtable (domain, System_Reflection_ParameterInfo);
6580         for (i = 0; i < sig->param_count; ++i) {
6581                 param = (MonoReflectionParameter *)mono_object_new_specific (pinfo_vtable);
6582                 MONO_OBJECT_SETREF (param, ClassImpl, mono_type_get_object (domain, sig->params [i]));
6583                 MONO_OBJECT_SETREF (param, MemberImpl, (MonoObject*)member);
6584                 MONO_OBJECT_SETREF (param, NameImpl, mono_string_new (domain, names [i]));
6585                 param->PositionImpl = i;
6586                 param->AttrsImpl = sig->params [i]->attrs;
6587
6588                 if (!(param->AttrsImpl & PARAM_ATTRIBUTE_HAS_DEFAULT)) {
6589                         if (param->AttrsImpl & PARAM_ATTRIBUTE_OPTIONAL)
6590                                 MONO_OBJECT_SETREF (param, DefaultValueImpl, get_reflection_missing (domain, &missing));
6591                         else
6592                                 MONO_OBJECT_SETREF (param, DefaultValueImpl, get_dbnull (domain, &dbnull));
6593                 } else {
6594
6595                         if (!blobs) {
6596                                 blobs = g_new0 (char *, sig->param_count);
6597                                 types = g_new0 (guint32, sig->param_count);
6598                                 get_default_param_value_blobs (method, blobs, types); 
6599                         }
6600
6601                         /* Build MonoType for the type from the Constant Table */
6602                         if (!type)
6603                                 type = g_new0 (MonoType, 1);
6604                         type->type = types [i];
6605                         type->data.klass = NULL;
6606                         if (types [i] == MONO_TYPE_CLASS)
6607                                 type->data.klass = mono_defaults.object_class;
6608                         else if ((sig->params [i]->type == MONO_TYPE_VALUETYPE) && sig->params [i]->data.klass->enumtype) {
6609                                 /* For enums, types [i] contains the base type */
6610
6611                                         type->type = MONO_TYPE_VALUETYPE;
6612                                         type->data.klass = mono_class_from_mono_type (sig->params [i]);
6613                         } else
6614                                 type->data.klass = mono_class_from_mono_type (type);
6615
6616                         MONO_OBJECT_SETREF (param, DefaultValueImpl, mono_get_object_from_blob (domain, type, blobs [i]));
6617
6618                         /* Type in the Constant table is MONO_TYPE_CLASS for nulls */
6619                         if (types [i] != MONO_TYPE_CLASS && !param->DefaultValueImpl) {
6620                                 if (param->AttrsImpl & PARAM_ATTRIBUTE_OPTIONAL)
6621                                         MONO_OBJECT_SETREF (param, DefaultValueImpl, get_reflection_missing (domain, &missing));
6622                                 else
6623                                         MONO_OBJECT_SETREF (param, DefaultValueImpl, get_dbnull (domain, &dbnull));
6624                         }
6625                         
6626                 }
6627
6628                 if (mspecs [i + 1])
6629                         MONO_OBJECT_SETREF (param, MarshalAsImpl, (MonoObject*)mono_reflection_marshal_from_marshal_spec (domain, method->klass, mspecs [i + 1]));
6630                 
6631                 mono_array_setref (res, i, param);
6632         }
6633         g_free (names);
6634         g_free (blobs);
6635         g_free (types);
6636         g_free (type);
6637
6638         for (i = mono_method_signature (method)->param_count; i >= 0; i--)
6639                 if (mspecs [i])
6640                         mono_metadata_free_marshal_spec (mspecs [i]);
6641         g_free (mspecs);
6642         
6643         CACHE_OBJECT (MonoArray *, &(method->signature), res, refclass);
6644 }
6645
6646 MonoArray*
6647 mono_param_get_objects (MonoDomain *domain, MonoMethod *method)
6648 {
6649         return mono_param_get_objects_internal (domain, method, NULL);
6650 }
6651
6652 /*
6653  * mono_method_body_get_object:
6654  * @domain: an app domain
6655  * @method: a method
6656  *
6657  * Return an System.Reflection.MethodBody object representing the method @method.
6658  */
6659 MonoReflectionMethodBody*
6660 mono_method_body_get_object (MonoDomain *domain, MonoMethod *method)
6661 {
6662         static MonoClass *System_Reflection_MethodBody = NULL;
6663         static MonoClass *System_Reflection_LocalVariableInfo = NULL;
6664         static MonoClass *System_Reflection_ExceptionHandlingClause = NULL;
6665         MonoReflectionMethodBody *ret;
6666         MonoMethodNormal *mn;
6667         MonoMethodHeader *header;
6668         guint32 method_rva, local_var_sig_token;
6669     char *ptr;
6670         unsigned char format, flags;
6671         int i;
6672
6673         if (!System_Reflection_MethodBody)
6674                 System_Reflection_MethodBody = mono_class_from_name (mono_defaults.corlib, "System.Reflection", "MethodBody");
6675         if (!System_Reflection_LocalVariableInfo)
6676                 System_Reflection_LocalVariableInfo = mono_class_from_name (mono_defaults.corlib, "System.Reflection", "LocalVariableInfo");
6677         if (!System_Reflection_ExceptionHandlingClause)
6678                 System_Reflection_ExceptionHandlingClause = mono_class_from_name (mono_defaults.corlib, "System.Reflection", "ExceptionHandlingClause");
6679
6680         CHECK_OBJECT (MonoReflectionMethodBody *, method, NULL);
6681
6682         if ((method->flags & METHOD_ATTRIBUTE_PINVOKE_IMPL) ||
6683                 (method->flags & METHOD_ATTRIBUTE_ABSTRACT) ||
6684             (method->iflags & METHOD_IMPL_ATTRIBUTE_INTERNAL_CALL) ||
6685             (method->iflags & METHOD_IMPL_ATTRIBUTE_RUNTIME))
6686                 return NULL;
6687         mn = (MonoMethodNormal *)method;
6688         header = mono_method_get_header (method);
6689         
6690         /* Obtain local vars signature token */
6691         method_rva = mono_metadata_decode_row_col (&method->klass->image->tables [MONO_TABLE_METHOD], mono_metadata_token_index (method->token) - 1, MONO_METHOD_RVA);
6692         ptr = mono_image_rva_map (method->klass->image, method_rva);
6693         flags = *(const unsigned char *) ptr;
6694         format = flags & METHOD_HEADER_FORMAT_MASK;
6695         switch (format){
6696         case METHOD_HEADER_TINY_FORMAT:
6697                 local_var_sig_token = 0;
6698                 break;
6699         case METHOD_HEADER_FAT_FORMAT:
6700                 ptr += 2;
6701                 ptr += 2;
6702                 ptr += 4;
6703                 local_var_sig_token = read32 (ptr);
6704                 break;
6705         default:
6706                 g_assert_not_reached ();
6707         }
6708
6709         ret = (MonoReflectionMethodBody*)mono_object_new (domain, System_Reflection_MethodBody);
6710
6711         ret->init_locals = header->init_locals;
6712         ret->max_stack = header->max_stack;
6713         ret->local_var_sig_token = local_var_sig_token;
6714         MONO_OBJECT_SETREF (ret, il, mono_array_new_cached (domain, mono_defaults.byte_class, header->code_size));
6715         memcpy (mono_array_addr (ret->il, guint8, 0), header->code, header->code_size);
6716
6717         /* Locals */
6718         MONO_OBJECT_SETREF (ret, locals, mono_array_new_cached (domain, System_Reflection_LocalVariableInfo, header->num_locals));
6719         for (i = 0; i < header->num_locals; ++i) {
6720                 MonoReflectionLocalVariableInfo *info = (MonoReflectionLocalVariableInfo*)mono_object_new (domain, System_Reflection_LocalVariableInfo);
6721                 MONO_OBJECT_SETREF (info, local_type, mono_type_get_object (domain, header->locals [i]));
6722                 info->is_pinned = header->locals [i]->pinned;
6723                 info->local_index = i;
6724                 mono_array_setref (ret->locals, i, info);
6725         }
6726
6727         /* Exceptions */
6728         MONO_OBJECT_SETREF (ret, clauses, mono_array_new_cached (domain, System_Reflection_ExceptionHandlingClause, header->num_clauses));
6729         for (i = 0; i < header->num_clauses; ++i) {
6730                 MonoReflectionExceptionHandlingClause *info = (MonoReflectionExceptionHandlingClause*)mono_object_new (domain, System_Reflection_ExceptionHandlingClause);
6731                 MonoExceptionClause *clause = &header->clauses [i];
6732
6733                 info->flags = clause->flags;
6734                 info->try_offset = clause->try_offset;
6735                 info->try_length = clause->try_len;
6736                 info->handler_offset = clause->handler_offset;
6737                 info->handler_length = clause->handler_len;
6738                 if (clause->flags == MONO_EXCEPTION_CLAUSE_FILTER)
6739                         info->filter_offset = clause->data.filter_offset;
6740                 else if (clause->data.catch_class)
6741                         MONO_OBJECT_SETREF (info, catch_type, mono_type_get_object (mono_domain_get (), &clause->data.catch_class->byval_arg));
6742
6743                 mono_array_setref (ret->clauses, i, info);
6744         }
6745
6746         CACHE_OBJECT (MonoReflectionMethodBody *, method, ret, NULL);
6747         return ret;
6748 }
6749
6750 /**
6751  * mono_get_dbnull_object:
6752  * @domain: Domain where the object lives
6753  *
6754  * Returns the System.DBNull.Value singleton object
6755  *
6756  * Used as the value for ParameterInfo.DefaultValue 
6757  */
6758 MonoObject *
6759 mono_get_dbnull_object (MonoDomain *domain)
6760 {
6761         MonoObject *obj;
6762         static MonoClassField *dbnull_value_field = NULL;
6763         
6764         if (!dbnull_value_field) {
6765                 MonoClass *dbnull_klass;
6766                 dbnull_klass = mono_class_from_name (mono_defaults.corlib, "System", "DBNull");
6767                 mono_class_init (dbnull_klass);
6768                 dbnull_value_field = mono_class_get_field_from_name (dbnull_klass, "Value");
6769                 g_assert (dbnull_value_field);
6770         }
6771         obj = mono_field_get_value_object (domain, dbnull_value_field, NULL); 
6772         g_assert (obj);
6773         return obj;
6774 }
6775
6776 static void
6777 get_default_param_value_blobs (MonoMethod *method, char **blobs, guint32 *types)
6778 {
6779         guint32 param_index, i, lastp, crow = 0;
6780         guint32 param_cols [MONO_PARAM_SIZE], const_cols [MONO_CONSTANT_SIZE];
6781         gint32 idx;
6782
6783         MonoClass *klass = method->klass;
6784         MonoImage *image = klass->image;
6785         MonoMethodSignature *methodsig = mono_method_signature (method);
6786
6787         MonoTableInfo *constt;
6788         MonoTableInfo *methodt;
6789         MonoTableInfo *paramt;
6790
6791         if (!methodsig->param_count)
6792                 return;
6793
6794         mono_class_init (klass);
6795
6796         if (klass->image->dynamic) {
6797                 MonoReflectionMethodAux *aux;
6798                 if (method->is_inflated)
6799                         method = ((MonoMethodInflated*)method)->declaring;
6800                 aux = g_hash_table_lookup (((MonoDynamicImage*)method->klass->image)->method_aux_hash, method);
6801                 if (aux && aux->param_defaults) {
6802                         memcpy (blobs, &(aux->param_defaults [1]), methodsig->param_count * sizeof (char*));
6803                         memcpy (types, &(aux->param_default_types [1]), methodsig->param_count * sizeof (guint32));
6804                 }
6805                 return;
6806         }
6807
6808         methodt = &klass->image->tables [MONO_TABLE_METHOD];
6809         paramt = &klass->image->tables [MONO_TABLE_PARAM];
6810         constt = &image->tables [MONO_TABLE_CONSTANT];
6811
6812         idx = mono_method_get_index (method) - 1;
6813         g_assert (idx != -1);
6814
6815         param_index = mono_metadata_decode_row_col (methodt, idx, MONO_METHOD_PARAMLIST);
6816         if (idx + 1 < methodt->rows)
6817                 lastp = mono_metadata_decode_row_col (methodt, idx + 1, MONO_METHOD_PARAMLIST);
6818         else
6819                 lastp = paramt->rows + 1;
6820
6821         for (i = param_index; i < lastp; ++i) {
6822                 guint32 paramseq;
6823
6824                 mono_metadata_decode_row (paramt, i - 1, param_cols, MONO_PARAM_SIZE);
6825                 paramseq = param_cols [MONO_PARAM_SEQUENCE];
6826
6827                 if (!(param_cols [MONO_PARAM_FLAGS] & PARAM_ATTRIBUTE_HAS_DEFAULT))
6828                         continue;
6829
6830                 crow = mono_metadata_get_constant_index (image, MONO_TOKEN_PARAM_DEF | i, crow + 1);
6831                 if (!crow) {
6832                         continue;
6833                 }
6834         
6835                 mono_metadata_decode_row (constt, crow - 1, const_cols, MONO_CONSTANT_SIZE);
6836                 blobs [paramseq - 1] = (gpointer) mono_metadata_blob_heap (image, const_cols [MONO_CONSTANT_VALUE]);
6837                 types [paramseq - 1] = const_cols [MONO_CONSTANT_TYPE];
6838         }
6839
6840         return;
6841 }
6842
6843 static MonoObject *
6844 mono_get_object_from_blob (MonoDomain *domain, MonoType *type, const char *blob)
6845 {
6846         void *retval;
6847         MonoClass *klass;
6848         MonoObject *object;
6849         MonoType *basetype = type;
6850
6851         if (!blob)
6852                 return NULL;
6853         
6854         klass = mono_class_from_mono_type (type);
6855         if (klass->valuetype) {
6856                 object = mono_object_new (domain, klass);
6857                 retval = ((gchar *) object + sizeof (MonoObject));
6858                 if (klass->enumtype)
6859                         basetype = mono_class_enum_basetype (klass);
6860         } else {
6861                 retval = &object;
6862         }
6863                         
6864         if (!mono_get_constant_value_from_blob (domain, basetype->type,  blob, retval))
6865                 return object;
6866         else
6867                 return NULL;
6868 }
6869
6870 static int
6871 assembly_name_to_aname (MonoAssemblyName *assembly, char *p) {
6872         int found_sep;
6873         char *s;
6874
6875         memset (assembly, 0, sizeof (MonoAssemblyName));
6876         assembly->name = p;
6877         assembly->culture = "";
6878         memset (assembly->public_key_token, 0, MONO_PUBLIC_KEY_TOKEN_LENGTH);
6879
6880         while (*p && (isalnum (*p) || *p == '.' || *p == '-' || *p == '_' || *p == '$' || *p == '@'))
6881                 p++;
6882         found_sep = 0;
6883         while (g_ascii_isspace (*p) || *p == ',') {
6884                 *p++ = 0;
6885                 found_sep = 1;
6886                 continue;
6887         }
6888         /* failed */
6889         if (!found_sep)
6890                 return 1;
6891         while (*p) {
6892                 if (*p == 'V' && g_ascii_strncasecmp (p, "Version=", 8) == 0) {
6893                         p += 8;
6894                         assembly->major = strtoul (p, &s, 10);
6895                         if (s == p || *s != '.')
6896                                 return 1;
6897                         p = ++s;
6898                         assembly->minor = strtoul (p, &s, 10);
6899                         if (s == p || *s != '.')
6900                                 return 1;
6901                         p = ++s;
6902                         assembly->build = strtoul (p, &s, 10);
6903                         if (s == p || *s != '.')
6904                                 return 1;
6905                         p = ++s;
6906                         assembly->revision = strtoul (p, &s, 10);
6907                         if (s == p)
6908                                 return 1;
6909                         p = s;
6910                 } else if (*p == 'C' && g_ascii_strncasecmp (p, "Culture=", 8) == 0) {
6911                         p += 8;
6912                         if (g_ascii_strncasecmp (p, "neutral", 7) == 0) {
6913                                 assembly->culture = "";
6914                                 p += 7;
6915                         } else {
6916                                 assembly->culture = p;
6917                                 while (*p && *p != ',') {
6918                                         p++;
6919                                 }
6920                         }
6921                 } else if (*p == 'P' && g_ascii_strncasecmp (p, "PublicKeyToken=", 15) == 0) {
6922                         p += 15;
6923                         if (strncmp (p, "null", 4) == 0) {
6924                                 p += 4;
6925                         } else {
6926                                 int len;
6927                                 gchar *start = p;
6928                                 while (*p && *p != ',') {
6929                                         p++;
6930                                 }
6931                                 len = (p - start + 1);
6932                                 if (len > MONO_PUBLIC_KEY_TOKEN_LENGTH)
6933                                         len = MONO_PUBLIC_KEY_TOKEN_LENGTH;
6934                                 g_strlcpy ((char*)assembly->public_key_token, start, len);
6935                         }
6936                 } else {
6937                         while (*p && *p != ',')
6938                                 p++;
6939                 }
6940                 found_sep = 0;
6941                 while (g_ascii_isspace (*p) || *p == ',') {
6942                         *p++ = 0;
6943                         found_sep = 1;
6944                         continue;
6945                 }
6946                 /* failed */
6947                 if (!found_sep)
6948                         return 1;
6949         }
6950
6951         return 0;
6952 }
6953
6954 /*
6955  * mono_reflection_parse_type:
6956  * @name: type name
6957  *
6958  * Parse a type name as accepted by the GetType () method and output the info
6959  * extracted in the info structure.
6960  * the name param will be mangled, so, make a copy before passing it to this function.
6961  * The fields in info will be valid until the memory pointed to by name is valid.
6962  *
6963  * See also mono_type_get_name () below.
6964  *
6965  * Returns: 0 on parse error.
6966  */
6967 static int
6968 _mono_reflection_parse_type (char *name, char **endptr, gboolean is_recursed,
6969                              MonoTypeNameParse *info)
6970 {
6971         char *start, *p, *w, *temp, *last_point, *startn;
6972         int in_modifiers = 0;
6973         int isbyref = 0, rank, arity = 0, i;
6974
6975         start = p = w = name;
6976
6977         //FIXME could we just zero the whole struct? memset (&info, 0, sizeof (MonoTypeNameParse))
6978         memset (&info->assembly, 0, sizeof (MonoAssemblyName));
6979         info->name = info->name_space = NULL;
6980         info->nested = NULL;
6981         info->modifiers = NULL;
6982         info->type_arguments = NULL;
6983
6984         /* last_point separates the namespace from the name */
6985         last_point = NULL;
6986         /* Skips spaces */
6987         while (*p == ' ') p++, start++, w++, name++;
6988
6989         while (*p) {
6990                 switch (*p) {
6991                 case '+':
6992                         *p = 0; /* NULL terminate the name */
6993                         startn = p + 1;
6994                         info->nested = g_list_append (info->nested, startn);
6995                         /* we have parsed the nesting namespace + name */
6996                         if (info->name)
6997                                 break;
6998                         if (last_point) {
6999                                 info->name_space = start;
7000                                 *last_point = 0;
7001                                 info->name = last_point + 1;
7002                         } else {
7003                                 info->name_space = (char *)"";
7004                                 info->name = start;
7005                         }
7006                         break;
7007                 case '.':
7008                         last_point = p;
7009                         break;
7010                 case '\\':
7011                         ++p;
7012                         break;
7013                 case '&':
7014                 case '*':
7015                 case '[':
7016                 case ',':
7017                 case ']':
7018                         in_modifiers = 1;
7019                         break;
7020                 case '`':
7021                         ++p;
7022                         i = strtol (p, &temp, 10);
7023                         arity += i;
7024                         if (p == temp)
7025                                 return 0;
7026                         p = temp-1;
7027                         break;
7028                 default:
7029                         break;
7030                 }
7031                 if (in_modifiers)
7032                         break;
7033                 // *w++ = *p++;
7034                 p++;
7035         }
7036         
7037         if (!info->name) {
7038                 if (last_point) {
7039                         info->name_space = start;
7040                         *last_point = 0;
7041                         info->name = last_point + 1;
7042                 } else {
7043                         info->name_space = (char *)"";
7044                         info->name = start;
7045                 }
7046         }
7047         while (*p) {
7048                 switch (*p) {
7049                 case '&':
7050                         if (isbyref) /* only one level allowed by the spec */
7051                                 return 0;
7052                         isbyref = 1;
7053                         info->modifiers = g_list_append (info->modifiers, GUINT_TO_POINTER (0));
7054                         *p++ = 0;
7055                         break;
7056                 case '*':
7057                         info->modifiers = g_list_append (info->modifiers, GUINT_TO_POINTER (-1));
7058                         *p++ = 0;
7059                         break;
7060                 case '[':
7061                         if (arity != 0) {
7062                                 *p++ = 0;
7063                                 info->type_arguments = g_ptr_array_new ();
7064                                 for (i = 0; i < arity; i++) {
7065                                         MonoTypeNameParse *subinfo = g_new0 (MonoTypeNameParse, 1);
7066                                         gboolean fqname = FALSE;
7067
7068                                         g_ptr_array_add (info->type_arguments, subinfo);
7069
7070                                         if (*p == '[') {
7071                                                 p++;
7072                                                 fqname = TRUE;
7073                                         }
7074
7075                                         if (!_mono_reflection_parse_type (p, &p, TRUE, subinfo))
7076                                                 return 0;
7077
7078                                         if (fqname) {
7079                                                 char *aname;
7080
7081                                                 if (*p != ',')
7082                                                         return 0;
7083                                                 *p++ = 0;
7084
7085                                                 aname = p;
7086                                                 while (*p && (*p != ']'))
7087                                                         p++;
7088
7089                                                 if (*p != ']')
7090                                                         return 0;
7091
7092                                                 *p++ = 0;
7093                                                 while (*aname) {
7094                                                         if (g_ascii_isspace (*aname)) {
7095                                                                 ++aname;
7096                                                                 continue;
7097                                                         }
7098                                                         break;
7099                                                 }
7100                                                 if (!*aname ||
7101                                                     !assembly_name_to_aname (&subinfo->assembly, aname))
7102                                                         return 0;
7103                                         }
7104
7105                                         if (i + 1 < arity) {
7106                                                 if (*p != ',')
7107                                                         return 0;
7108                                         } else {
7109                                                 if (*p != ']')
7110                                                         return 0;
7111                                         }
7112                                         *p++ = 0;
7113                                 }
7114
7115                                 arity = 0;
7116                                 break;
7117                         }
7118                         rank = 1;
7119                         *p++ = 0;
7120                         while (*p) {
7121                                 if (*p == ']')
7122                                         break;
7123                                 if (*p == ',')
7124                                         rank++;
7125                                 else if (*p == '*') /* '*' means unknown lower bound */
7126                                         info->modifiers = g_list_append (info->modifiers, GUINT_TO_POINTER (-2));
7127                                 else
7128                                         return 0;
7129                                 ++p;
7130                         }
7131                         if (*p++ != ']')
7132                                 return 0;
7133                         info->modifiers = g_list_append (info->modifiers, GUINT_TO_POINTER (rank));
7134                         break;
7135                 case ']':
7136                         if (is_recursed)
7137                                 goto end;
7138                         return 0;
7139                 case ',':
7140                         if (is_recursed)
7141                                 goto end;
7142                         *p++ = 0;
7143                         while (*p) {
7144                                 if (g_ascii_isspace (*p)) {
7145                                         ++p;
7146                                         continue;
7147                                 }
7148                                 break;
7149                         }
7150                         if (!*p)
7151                                 return 0; /* missing assembly name */
7152                         if (!assembly_name_to_aname (&info->assembly, p))
7153                                 return 0;
7154                         break;
7155                 default:
7156                         return 0;
7157                 }
7158                 if (info->assembly.name)
7159                         break;
7160         }
7161         // *w = 0; /* terminate class name */
7162  end:
7163         if (!info->name || !*info->name)
7164                 return 0;
7165         if (endptr)
7166                 *endptr = p;
7167         /* add other consistency checks */
7168         return 1;
7169 }
7170
7171 int
7172 mono_reflection_parse_type (char *name, MonoTypeNameParse *info)
7173 {
7174         return _mono_reflection_parse_type (name, NULL, FALSE, info);
7175 }
7176
7177 static MonoType*
7178 _mono_reflection_get_type_from_info (MonoTypeNameParse *info, MonoImage *image, gboolean ignorecase)
7179 {
7180         gboolean type_resolve = FALSE;
7181         MonoType *type;
7182         MonoImage *rootimage = image;
7183
7184         if (info->assembly.name) {
7185                 MonoAssembly *assembly = mono_assembly_loaded (&info->assembly);
7186                 if (!assembly && image && image->assembly && mono_assembly_names_equal (&info->assembly, &image->assembly->aname))
7187                         /* 
7188                          * This could happen in the AOT compiler case when the search hook is not
7189                          * installed.
7190                          */
7191                         assembly = image->assembly;
7192                 if (!assembly) {
7193                         /* then we must load the assembly ourselve - see #60439 */
7194                         assembly = mono_assembly_load (&info->assembly, NULL, NULL);
7195                         if (!assembly)
7196                                 return NULL;
7197                 }
7198                 image = assembly->image;
7199         } else if (!image) {
7200                 image = mono_defaults.corlib;
7201         }
7202
7203         type = mono_reflection_get_type_with_rootimage (rootimage, image, info, ignorecase, &type_resolve);
7204         if (type == NULL && !info->assembly.name && image != mono_defaults.corlib) {
7205                 image = mono_defaults.corlib;
7206                 type = mono_reflection_get_type_with_rootimage (rootimage, image, info, ignorecase, &type_resolve);
7207         }
7208
7209         return type;
7210 }
7211
7212 static MonoType*
7213 mono_reflection_get_type_internal (MonoImage *rootimage, MonoImage* image, MonoTypeNameParse *info, gboolean ignorecase)
7214 {
7215         MonoClass *klass;
7216         GList *mod;
7217         int modval;
7218         gboolean bounded = FALSE;
7219         
7220         if (!image)
7221                 image = mono_defaults.corlib;
7222
7223         if (ignorecase)
7224                 klass = mono_class_from_name_case (image, info->name_space, info->name);
7225         else
7226                 klass = mono_class_from_name (image, info->name_space, info->name);
7227         if (!klass)
7228                 return NULL;
7229         for (mod = info->nested; mod; mod = mod->next) {
7230                 gpointer iter = NULL;
7231                 MonoClass *parent;
7232
7233                 parent = klass;
7234                 mono_class_init (parent);
7235
7236                 while ((klass = mono_class_get_nested_types (parent, &iter))) {
7237                         if (ignorecase) {
7238                                 if (g_strcasecmp (klass->name, mod->data) == 0)
7239                                         break;
7240                         } else {
7241                                 if (strcmp (klass->name, mod->data) == 0)
7242                                         break;
7243                         }
7244                 }
7245                 if (!klass)
7246                         break;
7247         }
7248         if (!klass)
7249                 return NULL;
7250         mono_class_init (klass);
7251
7252         if (info->type_arguments) {
7253                 MonoType **type_args = g_new0 (MonoType *, info->type_arguments->len);
7254                 MonoReflectionType *the_type;
7255                 MonoType *instance;
7256                 int i;
7257
7258                 for (i = 0; i < info->type_arguments->len; i++) {
7259                         MonoTypeNameParse *subinfo = g_ptr_array_index (info->type_arguments, i);
7260
7261                         type_args [i] = _mono_reflection_get_type_from_info (subinfo, rootimage, ignorecase);
7262                         if (!type_args [i]) {
7263                                 g_free (type_args);
7264                                 return NULL;
7265                         }
7266                 }
7267
7268                 the_type = mono_type_get_object (mono_domain_get (), &klass->byval_arg);
7269
7270                 instance = mono_reflection_bind_generic_parameters (
7271                         the_type, info->type_arguments->len, type_args);
7272
7273                 g_free (type_args);
7274                 if (!instance)
7275                         return NULL;
7276
7277                 klass = mono_class_from_mono_type (instance);
7278         }
7279
7280         for (mod = info->modifiers; mod; mod = mod->next) {
7281                 modval = GPOINTER_TO_UINT (mod->data);
7282                 if (!modval) { /* byref: must be last modifier */
7283                         return &klass->this_arg;
7284                 } else if (modval == -1) {
7285                         klass = mono_ptr_class_get (&klass->byval_arg);
7286                 } else if (modval == -2) {
7287                         bounded = TRUE;
7288                 } else { /* array rank */
7289                         klass = mono_bounded_array_class_get (klass, modval, bounded);
7290                 }
7291                 mono_class_init (klass);
7292         }
7293
7294         return &klass->byval_arg;
7295 }
7296
7297 /*
7298  * mono_reflection_get_type:
7299  * @image: a metadata context
7300  * @info: type description structure
7301  * @ignorecase: flag for case-insensitive string compares
7302  * @type_resolve: whenever type resolve was already tried
7303  *
7304  * Build a MonoType from the type description in @info.
7305  * 
7306  */
7307
7308 MonoType*
7309 mono_reflection_get_type (MonoImage* image, MonoTypeNameParse *info, gboolean ignorecase, gboolean *type_resolve) {
7310         return mono_reflection_get_type_with_rootimage(image, image, info, ignorecase, type_resolve);
7311 }
7312
7313 static MonoType*
7314 mono_reflection_get_type_internal_dynamic (MonoImage *rootimage, MonoAssembly *assembly, MonoTypeNameParse *info, gboolean ignorecase)
7315 {
7316         MonoReflectionAssemblyBuilder *abuilder = (MonoReflectionAssemblyBuilder*)mono_assembly_get_object (mono_domain_get (), assembly);
7317         MonoType *type;
7318         int i;
7319
7320         g_assert (assembly->dynamic);
7321
7322         /* Enumerate all modules */
7323
7324         type = NULL;
7325         if (abuilder->modules) {
7326                 for (i = 0; i < mono_array_length (abuilder->modules); ++i) {
7327                         MonoReflectionModuleBuilder *mb = mono_array_get (abuilder->modules, MonoReflectionModuleBuilder*, i);
7328                         type = mono_reflection_get_type_internal (rootimage, &mb->dynamic_image->image, info, ignorecase);
7329                         if (type)
7330                                 break;
7331                 }
7332         }
7333
7334         if (!type && abuilder->loaded_modules) {
7335                 for (i = 0; i < mono_array_length (abuilder->loaded_modules); ++i) {
7336                         MonoReflectionModule *mod = mono_array_get (abuilder->loaded_modules, MonoReflectionModule*, i);
7337                         type = mono_reflection_get_type_internal (rootimage, mod->image, info, ignorecase);
7338                         if (type)
7339                                 break;
7340                 }
7341         }
7342
7343         return type;
7344 }
7345         
7346 MonoType*
7347 mono_reflection_get_type_with_rootimage (MonoImage *rootimage, MonoImage* image, MonoTypeNameParse *info, gboolean ignorecase, gboolean *type_resolve)
7348 {
7349         MonoType *type;
7350         MonoReflectionAssembly *assembly;
7351         GString *fullName;
7352         GList *mod;
7353
7354         if (image && image->dynamic)
7355                 type = mono_reflection_get_type_internal_dynamic (rootimage, image->assembly, info, ignorecase);
7356         else
7357                 type = mono_reflection_get_type_internal (rootimage, image, info, ignorecase);
7358         if (type)
7359                 return type;
7360         if (!mono_domain_has_type_resolve (mono_domain_get ()))
7361                 return NULL;
7362
7363         if (type_resolve) {
7364                 if (*type_resolve) 
7365                         return NULL;
7366                 else
7367                         *type_resolve = TRUE;
7368         }
7369         
7370         /* Reconstruct the type name */
7371         fullName = g_string_new ("");
7372         if (info->name_space && (info->name_space [0] != '\0'))
7373                 g_string_printf (fullName, "%s.%s", info->name_space, info->name);
7374         else
7375                 g_string_printf (fullName, "%s", info->name);
7376         for (mod = info->nested; mod; mod = mod->next)
7377                 g_string_append_printf (fullName, "+%s", (char*)mod->data);
7378
7379         assembly = mono_domain_try_type_resolve ( mono_domain_get (), fullName->str, NULL);
7380         if (assembly) {
7381                 if (assembly->assembly->dynamic)
7382                         type = mono_reflection_get_type_internal_dynamic (rootimage, assembly->assembly, info, ignorecase);
7383                 else
7384                         type = mono_reflection_get_type_internal (rootimage, assembly->assembly->image, 
7385                                                                                                           info, ignorecase);
7386         }
7387         g_string_free (fullName, TRUE);
7388         return type;
7389 }
7390
7391 void
7392 mono_reflection_free_type_info (MonoTypeNameParse *info)
7393 {
7394         g_list_free (info->modifiers);
7395         g_list_free (info->nested);
7396
7397         if (info->type_arguments) {
7398                 int i;
7399
7400                 for (i = 0; i < info->type_arguments->len; i++) {
7401                         MonoTypeNameParse *subinfo = g_ptr_array_index (info->type_arguments, i);
7402
7403                         mono_reflection_free_type_info (subinfo);
7404                         /*We free the subinfo since it is allocated by _mono_reflection_parse_type*/
7405                         g_free (subinfo);
7406                 }
7407
7408                 g_ptr_array_free (info->type_arguments, TRUE);
7409         }
7410 }
7411
7412 /*
7413  * mono_reflection_type_from_name:
7414  * @name: type name.
7415  * @image: a metadata context (can be NULL).
7416  *
7417  * Retrieves a MonoType from its @name. If the name is not fully qualified,
7418  * it defaults to get the type from @image or, if @image is NULL or loading
7419  * from it fails, uses corlib.
7420  * 
7421  */
7422 MonoType*
7423 mono_reflection_type_from_name (char *name, MonoImage *image)
7424 {
7425         MonoType *type = NULL;
7426         MonoTypeNameParse info;
7427         char *tmp;
7428
7429         /* Make a copy since parse_type modifies its argument */
7430         tmp = g_strdup (name);
7431         
7432         /*g_print ("requested type %s\n", str);*/
7433         if (mono_reflection_parse_type (tmp, &info)) {
7434                 type = _mono_reflection_get_type_from_info (&info, image, FALSE);
7435         }
7436
7437         g_free (tmp);
7438         mono_reflection_free_type_info (&info);
7439         return type;
7440 }
7441
7442 /*
7443  * mono_reflection_get_token:
7444  *
7445  *   Return the metadata token of OBJ which should be an object
7446  * representing a metadata element.
7447  */
7448 guint32
7449 mono_reflection_get_token (MonoObject *obj)
7450 {
7451         MonoClass *klass;
7452         guint32 token = 0;
7453
7454         klass = obj->vtable->klass;
7455
7456         if (strcmp (klass->name, "MethodBuilder") == 0) {
7457                 MonoReflectionMethodBuilder *mb = (MonoReflectionMethodBuilder *)obj;
7458
7459                 token = mb->table_idx | MONO_TOKEN_METHOD_DEF;
7460         } else if (strcmp (klass->name, "ConstructorBuilder") == 0) {
7461                 MonoReflectionCtorBuilder *mb = (MonoReflectionCtorBuilder *)obj;
7462
7463                 token = mb->table_idx | MONO_TOKEN_METHOD_DEF;
7464         } else if (strcmp (klass->name, "FieldBuilder") == 0) {
7465                 MonoReflectionFieldBuilder *fb = (MonoReflectionFieldBuilder *)obj;
7466
7467                 /* Call mono_image_create_token so the object gets added to the tokens hash table */
7468                 token = mono_image_create_token (((MonoReflectionTypeBuilder*)fb->typeb)->module->dynamic_image, obj, FALSE, TRUE);
7469         } else if (strcmp (klass->name, "TypeBuilder") == 0) {
7470                 MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder *)obj;
7471                 token = tb->table_idx | MONO_TOKEN_TYPE_DEF;
7472         } else if (strcmp (klass->name, "MonoType") == 0) {
7473                 MonoType *type = mono_reflection_type_get_handle ((MonoReflectionType *)obj);
7474                 token = mono_class_from_mono_type (type)->type_token;
7475         } else if (strcmp (klass->name, "MonoCMethod") == 0 ||
7476                    strcmp (klass->name, "MonoMethod") == 0 ||
7477                    strcmp (klass->name, "MonoGenericMethod") == 0 ||
7478                    strcmp (klass->name, "MonoGenericCMethod") == 0) {
7479                 MonoReflectionMethod *m = (MonoReflectionMethod *)obj;
7480                 if (m->method->is_inflated) {
7481                         MonoMethodInflated *inflated = (MonoMethodInflated *) m->method;
7482                         return inflated->declaring->token;
7483                 } else {
7484                         token = m->method->token;
7485                 }
7486         } else if (strcmp (klass->name, "MonoField") == 0) {
7487                 MonoReflectionField *f = (MonoReflectionField*)obj;
7488
7489                 if (is_field_on_inst (f->field)) {
7490                         MonoDynamicGenericClass *dgclass = (MonoDynamicGenericClass*)f->field->parent->generic_class;
7491                         int field_index = f->field - dgclass->fields;
7492                         MonoObject *obj;
7493
7494                         g_assert (field_index >= 0 && field_index < dgclass->count_fields);
7495                         obj = dgclass->field_objects [field_index];
7496                         return mono_reflection_get_token (obj);
7497                 }
7498                 token = mono_class_get_field_token (f->field);
7499         } else if (strcmp (klass->name, "MonoProperty") == 0) {
7500                 MonoReflectionProperty *p = (MonoReflectionProperty*)obj;
7501
7502                 token = mono_class_get_property_token (p->property);
7503         } else if (strcmp (klass->name, "MonoEvent") == 0) {
7504                 MonoReflectionMonoEvent *p = (MonoReflectionMonoEvent*)obj;
7505
7506                 token = mono_class_get_event_token (p->event);
7507         } else if (strcmp (klass->name, "ParameterInfo") == 0) {
7508                 MonoReflectionParameter *p = (MonoReflectionParameter*)obj;
7509
7510                 token = mono_method_get_param_token (((MonoReflectionMethod*)p->MemberImpl)->method, p->PositionImpl);
7511         } else if (strcmp (klass->name, "Module") == 0) {
7512                 MonoReflectionModule *m = (MonoReflectionModule*)obj;
7513
7514                 token = m->token;
7515         } else if (strcmp (klass->name, "Assembly") == 0) {
7516                 token = mono_metadata_make_token (MONO_TABLE_ASSEMBLY, 1);
7517         } else {
7518                 gchar *msg = g_strdup_printf ("MetadataToken is not supported for type '%s.%s'", klass->name_space, klass->name);
7519                 MonoException *ex = mono_get_exception_not_implemented (msg);
7520                 g_free (msg);
7521                 mono_raise_exception (ex);
7522         }
7523
7524         return token;
7525 }
7526
7527 static void*
7528 load_cattr_value (MonoImage *image, MonoType *t, const char *p, const char **end)
7529 {
7530         int slen, type = t->type;
7531         MonoClass *tklass = t->data.klass;
7532
7533 handle_enum:
7534         switch (type) {
7535         case MONO_TYPE_U1:
7536         case MONO_TYPE_I1:
7537         case MONO_TYPE_BOOLEAN: {
7538                 MonoBoolean *bval = g_malloc (sizeof (MonoBoolean));
7539                 *bval = *p;
7540                 *end = p + 1;
7541                 return bval;
7542         }
7543         case MONO_TYPE_CHAR:
7544         case MONO_TYPE_U2:
7545         case MONO_TYPE_I2: {
7546                 guint16 *val = g_malloc (sizeof (guint16));
7547                 *val = read16 (p);
7548                 *end = p + 2;
7549                 return val;
7550         }
7551 #if SIZEOF_VOID_P == 4
7552         case MONO_TYPE_U:
7553         case MONO_TYPE_I:
7554 #endif
7555         case MONO_TYPE_R4:
7556         case MONO_TYPE_U4:
7557         case MONO_TYPE_I4: {
7558                 guint32 *val = g_malloc (sizeof (guint32));
7559                 *val = read32 (p);
7560                 *end = p + 4;
7561                 return val;
7562         }
7563 #if SIZEOF_VOID_P == 8
7564         case MONO_TYPE_U: /* error out instead? this should probably not happen */
7565         case MONO_TYPE_I:
7566 #endif
7567         case MONO_TYPE_U8:
7568         case MONO_TYPE_I8: {
7569                 guint64 *val = g_malloc (sizeof (guint64));
7570                 *val = read64 (p);
7571                 *end = p + 8;
7572                 return val;
7573         }
7574         case MONO_TYPE_R8: {
7575                 double *val = g_malloc (sizeof (double));
7576                 readr8 (p, val);
7577                 *end = p + 8;
7578                 return val;
7579         }
7580         case MONO_TYPE_VALUETYPE:
7581                 if (t->data.klass->enumtype) {
7582                         type = mono_class_enum_basetype (t->data.klass)->type;
7583                         goto handle_enum;
7584                 } else {
7585                         g_error ("generic valutype %s not handled in custom attr value decoding", t->data.klass->name);
7586                 }
7587                 break;
7588         case MONO_TYPE_STRING:
7589                 if (*p == (char)0xFF) {
7590                         *end = p + 1;
7591                         return NULL;
7592                 }
7593                 slen = mono_metadata_decode_value (p, &p);
7594                 *end = p + slen;
7595                 return mono_string_new_len (mono_domain_get (), p, slen);
7596         case MONO_TYPE_CLASS: {
7597                 char *n;
7598                 MonoType *t;
7599                 if (*p == (char)0xFF) {
7600                         *end = p + 1;
7601                         return NULL;
7602                 }
7603 handle_type:
7604                 slen = mono_metadata_decode_value (p, &p);
7605                 n = g_memdup (p, slen + 1);
7606                 n [slen] = 0;
7607                 t = mono_reflection_type_from_name (n, image);
7608                 if (!t)
7609                         g_warning ("Cannot load type '%s'", n);
7610                 g_free (n);
7611                 *end = p + slen;
7612                 if (t)
7613                         return mono_type_get_object (mono_domain_get (), t);
7614                 else
7615                         return NULL;
7616         }
7617         case MONO_TYPE_OBJECT: {
7618                 char subt = *p++;
7619                 MonoObject *obj;
7620                 MonoClass *subc = NULL;
7621                 void *val;
7622
7623                 if (subt == 0x50) {
7624                         goto handle_type;
7625                 } else if (subt == 0x0E) {
7626                         type = MONO_TYPE_STRING;
7627                         goto handle_enum;
7628                 } else if (subt == 0x1D) {
7629                         MonoType simple_type = {{0}};
7630                         int etype = *p;
7631                         p ++;
7632
7633                         if (etype == 0x51)
7634                                 /* See Partition II, Appendix B3 */
7635                                 etype = MONO_TYPE_OBJECT;
7636                         type = MONO_TYPE_SZARRAY;
7637                         simple_type.type = etype;
7638                         tklass = mono_class_from_mono_type (&simple_type);
7639                         goto handle_enum;
7640                 } else if (subt == 0x55) {
7641                         char *n;
7642                         MonoType *t;
7643                         slen = mono_metadata_decode_value (p, &p);
7644                         n = g_memdup (p, slen + 1);
7645                         n [slen] = 0;
7646                         t = mono_reflection_type_from_name (n, image);
7647                         if (!t)
7648                                 g_error ("Cannot load type '%s'", n);
7649                         g_free (n);
7650                         p += slen;
7651                         subc = mono_class_from_mono_type (t);
7652                 } else if (subt >= MONO_TYPE_BOOLEAN && subt <= MONO_TYPE_R8) {
7653                         MonoType simple_type = {{0}};
7654                         simple_type.type = subt;
7655                         subc = mono_class_from_mono_type (&simple_type);
7656                 } else {
7657                         g_error ("Unknown type 0x%02x for object type encoding in custom attr", subt);
7658                 }
7659                 val = load_cattr_value (image, &subc->byval_arg, p, end);
7660                 obj = mono_object_new (mono_domain_get (), subc);
7661                 memcpy ((char*)obj + sizeof (MonoObject), val, mono_class_value_size (subc, NULL));
7662                 g_free (val);
7663                 return obj;
7664         }
7665         case MONO_TYPE_SZARRAY: {
7666                 MonoArray *arr;
7667                 guint32 i, alen, basetype;
7668                 alen = read32 (p);
7669                 p += 4;
7670                 if (alen == 0xffffffff) {
7671                         *end = p;
7672                         return NULL;
7673                 }
7674                 arr = mono_array_new (mono_domain_get(), tklass, alen);
7675                 basetype = tklass->byval_arg.type;
7676                 if (basetype == MONO_TYPE_VALUETYPE && tklass->enumtype)
7677                         basetype = mono_class_enum_basetype (tklass)->type;
7678                 switch (basetype)
7679                 {
7680                         case MONO_TYPE_U1:
7681                         case MONO_TYPE_I1:
7682                         case MONO_TYPE_BOOLEAN:
7683                                 for (i = 0; i < alen; i++) {
7684                                         MonoBoolean val = *p++;
7685                                         mono_array_set (arr, MonoBoolean, i, val);
7686                                 }
7687                                 break;
7688                         case MONO_TYPE_CHAR:
7689                         case MONO_TYPE_U2:
7690                         case MONO_TYPE_I2:
7691                                 for (i = 0; i < alen; i++) {
7692                                         guint16 val = read16 (p);
7693                                         mono_array_set (arr, guint16, i, val);
7694                                         p += 2;
7695                                 }
7696                                 break;
7697                         case MONO_TYPE_R4:
7698                         case MONO_TYPE_U4:
7699                         case MONO_TYPE_I4:
7700                                 for (i = 0; i < alen; i++) {
7701                                         guint32 val = read32 (p);
7702                                         mono_array_set (arr, guint32, i, val);
7703                                         p += 4;
7704                                 }
7705                                 break;
7706                         case MONO_TYPE_R8:
7707                                 for (i = 0; i < alen; i++) {
7708                                         double val;
7709                                         readr8 (p, &val);
7710                                         mono_array_set (arr, double, i, val);
7711                                         p += 8;
7712                                 }
7713                                 break;
7714                         case MONO_TYPE_U8:
7715                         case MONO_TYPE_I8:
7716                                 for (i = 0; i < alen; i++) {
7717                                         guint64 val = read64 (p);
7718                                         mono_array_set (arr, guint64, i, val);
7719                                         p += 8;
7720                                 }
7721                                 break;
7722                         case MONO_TYPE_CLASS:
7723                         case MONO_TYPE_OBJECT:
7724                         case MONO_TYPE_STRING:
7725                                 for (i = 0; i < alen; i++) {
7726                                         MonoObject *item = load_cattr_value (image, &tklass->byval_arg, p, &p);
7727                                         mono_array_setref (arr, i, item);
7728                                 }
7729                                 break;
7730                         default:
7731                                 g_error ("Type 0x%02x not handled in custom attr array decoding", basetype);
7732                 }
7733                 *end=p;
7734                 return arr;
7735         }
7736         default:
7737                 g_error ("Type 0x%02x not handled in custom attr value decoding", type);
7738         }
7739         return NULL;
7740 }
7741
7742 static MonoObject*
7743 create_cattr_typed_arg (MonoType *t, MonoObject *val)
7744 {
7745         static MonoClass *klass;
7746         static MonoMethod *ctor;
7747         MonoObject *retval;
7748         void *params [2], *unboxed;
7749
7750         if (!klass)
7751                 klass = mono_class_from_name (mono_defaults.corlib, "System.Reflection", "CustomAttributeTypedArgument");
7752         if (!ctor)
7753                 ctor = mono_class_get_method_from_name (klass, ".ctor", 2);
7754         
7755         params [0] = mono_type_get_object (mono_domain_get (), t);
7756         params [1] = val;
7757         retval = mono_object_new (mono_domain_get (), klass);
7758         unboxed = mono_object_unbox (retval);
7759         mono_runtime_invoke (ctor, unboxed, params, NULL);
7760
7761         return retval;
7762 }
7763
7764 static MonoObject*
7765 create_cattr_named_arg (void *minfo, MonoObject *typedarg)
7766 {
7767         static MonoClass *klass;
7768         static MonoMethod *ctor;
7769         MonoObject *retval;
7770         void *unboxed, *params [2];
7771
7772         if (!klass)
7773                 klass = mono_class_from_name (mono_defaults.corlib, "System.Reflection", "CustomAttributeNamedArgument");
7774         if (!ctor)
7775                 ctor = mono_class_get_method_from_name (klass, ".ctor", 2);
7776
7777         params [0] = minfo;
7778         params [1] = typedarg;
7779         retval = mono_object_new (mono_domain_get (), klass);
7780         unboxed = mono_object_unbox (retval);
7781         mono_runtime_invoke (ctor, unboxed, params, NULL);
7782
7783         return retval;
7784 }
7785
7786 static gboolean
7787 type_is_reference (MonoType *type)
7788 {
7789         switch (type->type) {
7790         case MONO_TYPE_BOOLEAN:
7791         case MONO_TYPE_CHAR:
7792         case MONO_TYPE_U:
7793         case MONO_TYPE_I:
7794         case MONO_TYPE_U1:
7795         case MONO_TYPE_I1:
7796         case MONO_TYPE_U2:
7797         case MONO_TYPE_I2:
7798         case MONO_TYPE_U4:
7799         case MONO_TYPE_I4:
7800         case MONO_TYPE_U8:
7801         case MONO_TYPE_I8:
7802         case MONO_TYPE_R8:
7803         case MONO_TYPE_R4:
7804         case MONO_TYPE_VALUETYPE:
7805                 return FALSE;
7806         default:
7807                 return TRUE;
7808         }
7809 }
7810
7811 static void
7812 free_param_data (MonoMethodSignature *sig, void **params) {
7813         int i;
7814         for (i = 0; i < sig->param_count; ++i) {
7815                 if (!type_is_reference (sig->params [i]))
7816                         g_free (params [i]);
7817         }
7818 }
7819
7820 /*
7821  * Find the field index in the metadata FieldDef table.
7822  */
7823 static guint32
7824 find_field_index (MonoClass *klass, MonoClassField *field) {
7825         int i;
7826
7827         for (i = 0; i < klass->field.count; ++i) {
7828                 if (field == &klass->fields [i])
7829                         return klass->field.first + 1 + i;
7830         }
7831         return 0;
7832 }
7833
7834 /*
7835  * Find the property index in the metadata Property table.
7836  */
7837 static guint32
7838 find_property_index (MonoClass *klass, MonoProperty *property) {
7839         int i;
7840
7841         for (i = 0; i < klass->ext->property.count; ++i) {
7842                 if (property == &klass->ext->properties [i])
7843                         return klass->ext->property.first + 1 + i;
7844         }
7845         return 0;
7846 }
7847
7848 /*
7849  * Find the event index in the metadata Event table.
7850  */
7851 static guint32
7852 find_event_index (MonoClass *klass, MonoEvent *event) {
7853         int i;
7854
7855         for (i = 0; i < klass->ext->event.count; ++i) {
7856                 if (event == &klass->ext->events [i])
7857                         return klass->ext->event.first + 1 + i;
7858         }
7859         return 0;
7860 }
7861
7862 static MonoObject*
7863 create_custom_attr (MonoImage *image, MonoMethod *method, const guchar *data, guint32 len)
7864 {
7865         const char *p = (const char*)data;
7866         const char *named;
7867         guint32 i, j, num_named;
7868         MonoObject *attr;
7869         void *params_buf [32];
7870         void **params;
7871         MonoMethodSignature *sig;
7872
7873         mono_class_init (method->klass);
7874
7875         if (len == 0) {
7876                 attr = mono_object_new (mono_domain_get (), method->klass);
7877                 mono_runtime_invoke (method, attr, NULL, NULL);
7878                 return attr;
7879         }
7880
7881         if (len < 2 || read16 (p) != 0x0001) /* Prolog */
7882                 return NULL;
7883
7884         /*g_print ("got attr %s\n", method->klass->name);*/
7885
7886         sig = mono_method_signature (method);
7887         if (sig->param_count < 32)
7888                 params = params_buf;
7889         else
7890                 /* Allocate using GC so it gets GC tracking */
7891                 params = mono_gc_alloc_fixed (sig->param_count * sizeof (void*), NULL);
7892
7893         /* skip prolog */
7894         p += 2;
7895         for (i = 0; i < mono_method_signature (method)->param_count; ++i) {
7896                 params [i] = load_cattr_value (image, mono_method_signature (method)->params [i], p, &p);
7897         }
7898
7899         named = p;
7900         attr = mono_object_new (mono_domain_get (), method->klass);
7901         mono_runtime_invoke (method, attr, params, NULL);
7902         free_param_data (method->signature, params);
7903         num_named = read16 (named);
7904         named += 2;
7905         for (j = 0; j < num_named; j++) {
7906                 gint name_len;
7907                 char *name, named_type, data_type;
7908                 named_type = *named++;
7909                 data_type = *named++; /* type of data */
7910                 if (data_type == MONO_TYPE_SZARRAY)
7911                         data_type = *named++;
7912                 if (data_type == MONO_TYPE_ENUM) {
7913                         gint type_len;
7914                         char *type_name;
7915                         type_len = mono_metadata_decode_blob_size (named, &named);
7916                         type_name = g_malloc (type_len + 1);
7917                         memcpy (type_name, named, type_len);
7918                         type_name [type_len] = 0;
7919                         named += type_len;
7920                         /* FIXME: lookup the type and check type consistency */
7921                         g_free (type_name);
7922                 }
7923                 name_len = mono_metadata_decode_blob_size (named, &named);
7924                 name = g_malloc (name_len + 1);
7925                 memcpy (name, named, name_len);
7926                 name [name_len] = 0;
7927                 named += name_len;
7928                 if (named_type == 0x53) {
7929                         MonoClassField *field = mono_class_get_field_from_name (mono_object_class (attr), name);
7930                         void *val = load_cattr_value (image, field->type, named, &named);
7931                         mono_field_set_value (attr, field, val);
7932                         if (!type_is_reference (field->type))
7933                                 g_free (val);
7934                 } else if (named_type == 0x54) {
7935                         MonoProperty *prop;
7936                         void *pparams [1];
7937                         MonoType *prop_type;
7938
7939                         prop = mono_class_get_property_from_name (mono_object_class (attr), name);
7940                         /* can we have more that 1 arg in a custom attr named property? */
7941                         prop_type = prop->get? mono_method_signature (prop->get)->ret :
7942                              mono_method_signature (prop->set)->params [mono_method_signature (prop->set)->param_count - 1];
7943                         pparams [0] = load_cattr_value (image, prop_type, named, &named);
7944                         mono_property_set_value (prop, attr, pparams, NULL);
7945                         if (!type_is_reference (prop_type))
7946                                 g_free (pparams [0]);
7947                 }
7948                 g_free (name);
7949         }
7950
7951         if (params != params_buf)
7952                 mono_gc_free_fixed (params);
7953
7954         return attr;
7955 }
7956
7957 static MonoObject*
7958 create_custom_attr_data (MonoImage *image, MonoMethod *method, const guchar *data, guint32 len)
7959 {
7960         MonoArray *typedargs, *namedargs;
7961         MonoClass *attrklass;
7962         static MonoMethod *ctor;
7963         MonoDomain *domain;
7964         MonoObject *attr;
7965         const char *p = (const char*)data;
7966         const char *named;
7967         guint32 i, j, num_named;
7968         void *params [3];
7969
7970         mono_class_init (method->klass);
7971
7972         if (!ctor)
7973                 ctor = mono_class_get_method_from_name (mono_defaults.customattribute_data_class, ".ctor", 3);
7974
7975         domain = mono_domain_get ();
7976         if (len == 0) {
7977                 /* This is for Attributes with no parameters */
7978                 attr = mono_object_new (domain, mono_defaults.customattribute_data_class);
7979                 params [0] = mono_method_get_object (domain, method, NULL);
7980                 params [1] = params [2] = NULL;
7981                 mono_runtime_invoke (method, attr, params, NULL);
7982                 return attr;
7983         }
7984
7985         if (len < 2 || read16 (p) != 0x0001) /* Prolog */
7986                 return NULL;
7987
7988         typedargs = mono_array_new (domain, mono_get_object_class (), mono_method_signature (method)->param_count);
7989         
7990         /* skip prolog */
7991         p += 2;
7992         for (i = 0; i < mono_method_signature (method)->param_count; ++i) {
7993                 MonoObject *obj, *typedarg;
7994                 void *val;
7995
7996                 val = load_cattr_value (image, mono_method_signature (method)->params [i], p, &p);
7997                 obj = type_is_reference (mono_method_signature (method)->params [i]) ? 
7998                         val : mono_value_box (domain, mono_class_from_mono_type (mono_method_signature (method)->params [i]), val);
7999                 typedarg = create_cattr_typed_arg (mono_method_signature (method)->params [i], obj);
8000                 mono_array_setref (typedargs, i, typedarg);
8001
8002                 if (!type_is_reference (mono_method_signature (method)->params [i]))
8003                         g_free (val);
8004         }
8005
8006         named = p;
8007         num_named = read16 (named);
8008         namedargs = mono_array_new (domain, mono_get_object_class (), num_named);
8009         named += 2;
8010         attrklass = method->klass;
8011         for (j = 0; j < num_named; j++) {
8012                 gint name_len;
8013                 char *name, named_type, data_type;
8014                 named_type = *named++;
8015                 data_type = *named++; /* type of data */
8016                 if (data_type == MONO_TYPE_SZARRAY)
8017                         data_type = *named++;
8018                 if (data_type == MONO_TYPE_ENUM) {
8019                         gint type_len;
8020                         char *type_name;
8021                         type_len = mono_metadata_decode_blob_size (named, &named);
8022                         type_name = g_malloc (type_len + 1);
8023                         memcpy (type_name, named, type_len);
8024                         type_name [type_len] = 0;
8025                         named += type_len;
8026                         /* FIXME: lookup the type and check type consistency */
8027                         g_free (type_name);
8028                 }
8029                 name_len = mono_metadata_decode_blob_size (named, &named);
8030                 name = g_malloc (name_len + 1);
8031                 memcpy (name, named, name_len);
8032                 name [name_len] = 0;
8033                 named += name_len;
8034                 if (named_type == 0x53) {
8035                         MonoObject *obj, *typedarg, *namedarg;
8036                         MonoClassField *field = mono_class_get_field_from_name (attrklass, name);
8037                         void *minfo, *val = load_cattr_value (image, field->type, named, &named);
8038                         
8039                         minfo = mono_field_get_object (domain, NULL, field);
8040                         obj = type_is_reference (field->type) ? val : mono_value_box (domain, mono_class_from_mono_type (field->type), val);
8041                         typedarg = create_cattr_typed_arg (field->type, obj);
8042                         namedarg = create_cattr_named_arg (minfo, typedarg);
8043                         mono_array_setref (namedargs, j, namedarg);
8044                         if (!type_is_reference (field->type))
8045                                 g_free (val);
8046                 } else if (named_type == 0x54) {
8047                         MonoObject *obj, *typedarg, *namedarg;
8048                         MonoType *prop_type;
8049                         void *val, *minfo;
8050                         MonoProperty *prop = mono_class_get_property_from_name (attrklass, name);
8051
8052                         prop_type = prop->get? mono_method_signature (prop->get)->ret :
8053                              mono_method_signature (prop->set)->params [mono_method_signature (prop->set)->param_count - 1];
8054                         minfo =  mono_property_get_object (domain, NULL, prop);
8055                         val = load_cattr_value (image, prop_type, named, &named);
8056                         obj = type_is_reference (prop_type) ? val : mono_value_box (domain, mono_class_from_mono_type (prop_type), val);
8057                         typedarg = create_cattr_typed_arg (prop_type, obj);
8058                         namedarg = create_cattr_named_arg (minfo, typedarg);
8059                         mono_array_setref (namedargs, j, namedarg);
8060                         if (!type_is_reference (prop_type))
8061                                 g_free (val);
8062                 }
8063                 g_free (name);
8064         }
8065         attr = mono_object_new (domain, mono_defaults.customattribute_data_class);
8066         params [0] = mono_method_get_object (domain, method, NULL);
8067         params [1] = typedargs;
8068         params [2] = namedargs;
8069         mono_runtime_invoke (ctor, attr, params, NULL);
8070         return attr;
8071 }
8072
8073 MonoArray*
8074 mono_custom_attrs_construct (MonoCustomAttrInfo *cinfo)
8075 {
8076         MonoArray *result;
8077         MonoObject *attr;
8078         int i;
8079
8080         result = mono_array_new_cached (mono_domain_get (), mono_defaults.attribute_class, cinfo->num_attrs);
8081         for (i = 0; i < cinfo->num_attrs; ++i) {
8082                 if (!cinfo->attrs [i].ctor)
8083                         /* The cattr type is not finished yet */
8084                         /* We should include the type name but cinfo doesn't contain it */
8085                         mono_raise_exception (mono_get_exception_type_load (NULL, NULL));
8086                 attr = create_custom_attr (cinfo->image, cinfo->attrs [i].ctor, cinfo->attrs [i].data, cinfo->attrs [i].data_size);
8087                 mono_array_setref (result, i, attr);
8088         }
8089         return result;
8090 }
8091
8092 static MonoArray*
8093 mono_custom_attrs_construct_by_type (MonoCustomAttrInfo *cinfo, MonoClass *attr_klass)
8094 {
8095         MonoArray *result;
8096         MonoObject *attr;
8097         int i, n;
8098
8099         n = 0;
8100         for (i = 0; i < cinfo->num_attrs; ++i) {
8101                 if (mono_class_is_assignable_from (attr_klass, cinfo->attrs [i].ctor->klass))
8102                         n ++;
8103         }
8104
8105         result = mono_array_new_cached (mono_domain_get (), mono_defaults.attribute_class, n);
8106         n = 0;
8107         for (i = 0; i < cinfo->num_attrs; ++i) {
8108                 if (mono_class_is_assignable_from (attr_klass, cinfo->attrs [i].ctor->klass)) {
8109                         attr = create_custom_attr (cinfo->image, cinfo->attrs [i].ctor, cinfo->attrs [i].data, cinfo->attrs [i].data_size);
8110                         mono_array_setref (result, n, attr);
8111                         n ++;
8112                 }
8113         }
8114         return result;
8115 }
8116
8117 static MonoArray*
8118 mono_custom_attrs_data_construct (MonoCustomAttrInfo *cinfo)
8119 {
8120         MonoArray *result;
8121         MonoObject *attr;
8122         int i;
8123         
8124         result = mono_array_new (mono_domain_get (), mono_defaults.customattribute_data_class, cinfo->num_attrs);
8125         for (i = 0; i < cinfo->num_attrs; ++i) {
8126                 attr = create_custom_attr_data (cinfo->image, cinfo->attrs [i].ctor, cinfo->attrs [i].data, cinfo->attrs [i].data_size);
8127                 mono_array_setref (result, i, attr);
8128         }
8129         return result;
8130 }
8131
8132 /**
8133  * mono_custom_attrs_from_index:
8134  *
8135  * Returns: NULL if no attributes are found or if a loading error occurs.
8136  */
8137 MonoCustomAttrInfo*
8138 mono_custom_attrs_from_index (MonoImage *image, guint32 idx)
8139 {
8140         guint32 mtoken, i, len;
8141         guint32 cols [MONO_CUSTOM_ATTR_SIZE];
8142         MonoTableInfo *ca;
8143         MonoCustomAttrInfo *ainfo;
8144         GList *tmp, *list = NULL;
8145         const char *data;
8146
8147         ca = &image->tables [MONO_TABLE_CUSTOMATTRIBUTE];
8148
8149         i = mono_metadata_custom_attrs_from_index (image, idx);
8150         if (!i)
8151                 return NULL;
8152         i --;
8153         while (i < ca->rows) {
8154                 if (mono_metadata_decode_row_col (ca, i, MONO_CUSTOM_ATTR_PARENT) != idx)
8155                         break;
8156                 list = g_list_prepend (list, GUINT_TO_POINTER (i));
8157                 ++i;
8158         }
8159         len = g_list_length (list);
8160         if (!len)
8161                 return NULL;
8162         ainfo = g_malloc0 (MONO_SIZEOF_CUSTOM_ATTR_INFO + sizeof (MonoCustomAttrEntry) * len);
8163         ainfo->num_attrs = len;
8164         ainfo->image = image;
8165         for (i = 0, tmp = list; i < len; ++i, tmp = tmp->next) {
8166                 mono_metadata_decode_row (ca, GPOINTER_TO_UINT (tmp->data), cols, MONO_CUSTOM_ATTR_SIZE);
8167                 mtoken = cols [MONO_CUSTOM_ATTR_TYPE] >> MONO_CUSTOM_ATTR_TYPE_BITS;
8168                 switch (cols [MONO_CUSTOM_ATTR_TYPE] & MONO_CUSTOM_ATTR_TYPE_MASK) {
8169                 case MONO_CUSTOM_ATTR_TYPE_METHODDEF:
8170                         mtoken |= MONO_TOKEN_METHOD_DEF;
8171                         break;
8172                 case MONO_CUSTOM_ATTR_TYPE_MEMBERREF:
8173                         mtoken |= MONO_TOKEN_MEMBER_REF;
8174                         break;
8175                 default:
8176                         g_error ("Unknown table for custom attr type %08x", cols [MONO_CUSTOM_ATTR_TYPE]);
8177                         break;
8178                 }
8179                 ainfo->attrs [i].ctor = mono_get_method (image, mtoken, NULL);
8180                 if (!ainfo->attrs [i].ctor) {
8181                         g_warning ("Can't find custom attr constructor image: %s mtoken: 0x%08x", image->name, mtoken);
8182                         g_list_free (list);
8183                         g_free (ainfo);
8184                         return NULL;
8185                 }
8186                 data = mono_metadata_blob_heap (image, cols [MONO_CUSTOM_ATTR_VALUE]);
8187                 ainfo->attrs [i].data_size = mono_metadata_decode_value (data, &data);
8188                 ainfo->attrs [i].data = (guchar*)data;
8189         }
8190         g_list_free (list);
8191
8192         return ainfo;
8193 }
8194
8195 MonoCustomAttrInfo*
8196 mono_custom_attrs_from_method (MonoMethod *method)
8197 {
8198         guint32 idx;
8199
8200         /*
8201          * An instantiated method has the same cattrs as the generic method definition.
8202          *
8203          * LAMESPEC: The .NET SRE throws an exception for instantiations of generic method builders
8204          *           Note that this stanza is not necessary for non-SRE types, but it's a micro-optimization
8205          */
8206         if (method->is_inflated)
8207                 method = ((MonoMethodInflated *) method)->declaring;
8208         
8209         if (method->dynamic || method->klass->image->dynamic)
8210                 return lookup_custom_attr (method->klass->image, method);
8211
8212         if (!method->token)
8213                 /* Synthetic methods */
8214                 return NULL;
8215
8216         idx = mono_method_get_index (method);
8217         idx <<= MONO_CUSTOM_ATTR_BITS;
8218         idx |= MONO_CUSTOM_ATTR_METHODDEF;
8219         return mono_custom_attrs_from_index (method->klass->image, idx);
8220 }
8221
8222 MonoCustomAttrInfo*
8223 mono_custom_attrs_from_class (MonoClass *klass)
8224 {
8225         guint32 idx;
8226
8227         if (klass->generic_class)
8228                 klass = klass->generic_class->container_class;
8229
8230         if (klass->image->dynamic)
8231                 return lookup_custom_attr (klass->image, klass);
8232
8233         if (klass->byval_arg.type == MONO_TYPE_VAR || klass->byval_arg.type == MONO_TYPE_MVAR) {
8234                 idx = mono_metadata_token_index (klass->sizes.generic_param_token);
8235                 idx <<= MONO_CUSTOM_ATTR_BITS;
8236                 idx |= MONO_CUSTOM_ATTR_GENERICPAR;
8237         } else {
8238                 idx = mono_metadata_token_index (klass->type_token);
8239                 idx <<= MONO_CUSTOM_ATTR_BITS;
8240                 idx |= MONO_CUSTOM_ATTR_TYPEDEF;
8241         }
8242         return mono_custom_attrs_from_index (klass->image, idx);
8243 }
8244
8245 MonoCustomAttrInfo*
8246 mono_custom_attrs_from_assembly (MonoAssembly *assembly)
8247 {
8248         guint32 idx;
8249         
8250         if (assembly->image->dynamic)
8251                 return lookup_custom_attr (assembly->image, assembly);
8252         idx = 1; /* there is only one assembly */
8253         idx <<= MONO_CUSTOM_ATTR_BITS;
8254         idx |= MONO_CUSTOM_ATTR_ASSEMBLY;
8255         return mono_custom_attrs_from_index (assembly->image, idx);
8256 }
8257
8258 static MonoCustomAttrInfo*
8259 mono_custom_attrs_from_module (MonoImage *image)
8260 {
8261         guint32 idx;
8262         
8263         if (image->dynamic)
8264                 return lookup_custom_attr (image, image);
8265         idx = 1; /* there is only one module */
8266         idx <<= MONO_CUSTOM_ATTR_BITS;
8267         idx |= MONO_CUSTOM_ATTR_MODULE;
8268         return mono_custom_attrs_from_index (image, idx);
8269 }
8270
8271 MonoCustomAttrInfo*
8272 mono_custom_attrs_from_property (MonoClass *klass, MonoProperty *property)
8273 {
8274         guint32 idx;
8275         
8276         if (klass->image->dynamic) {
8277                 property = mono_metadata_get_corresponding_property_from_generic_type_definition (property);
8278                 return lookup_custom_attr (klass->image, property);
8279         }
8280         idx = find_property_index (klass, property);
8281         idx <<= MONO_CUSTOM_ATTR_BITS;
8282         idx |= MONO_CUSTOM_ATTR_PROPERTY;
8283         return mono_custom_attrs_from_index (klass->image, idx);
8284 }
8285
8286 MonoCustomAttrInfo*
8287 mono_custom_attrs_from_event (MonoClass *klass, MonoEvent *event)
8288 {
8289         guint32 idx;
8290         
8291         if (klass->image->dynamic) {
8292                 event = mono_metadata_get_corresponding_event_from_generic_type_definition (event);
8293                 return lookup_custom_attr (klass->image, event);
8294         }
8295         idx = find_event_index (klass, event);
8296         idx <<= MONO_CUSTOM_ATTR_BITS;
8297         idx |= MONO_CUSTOM_ATTR_EVENT;
8298         return mono_custom_attrs_from_index (klass->image, idx);
8299 }
8300
8301 MonoCustomAttrInfo*
8302 mono_custom_attrs_from_field (MonoClass *klass, MonoClassField *field)
8303 {
8304         guint32 idx;
8305         if (klass->image->dynamic) {
8306                 field = mono_metadata_get_corresponding_field_from_generic_type_definition (field);
8307                 return lookup_custom_attr (klass->image, field);
8308         }
8309         idx = find_field_index (klass, field);
8310         idx <<= MONO_CUSTOM_ATTR_BITS;
8311         idx |= MONO_CUSTOM_ATTR_FIELDDEF;
8312         return mono_custom_attrs_from_index (klass->image, idx);
8313 }
8314
8315 MonoCustomAttrInfo*
8316 mono_custom_attrs_from_param (MonoMethod *method, guint32 param)
8317 {
8318         MonoTableInfo *ca;
8319         guint32 i, idx, method_index;
8320         guint32 param_list, param_last, param_pos, found;
8321         MonoImage *image;
8322         MonoReflectionMethodAux *aux;
8323
8324         /*
8325          * An instantiated method has the same cattrs as the generic method definition.
8326          *
8327          * LAMESPEC: The .NET SRE throws an exception for instantiations of generic method builders
8328          *           Note that this stanza is not necessary for non-SRE types, but it's a micro-optimization
8329          */
8330         if (method->is_inflated)
8331                 method = ((MonoMethodInflated *) method)->declaring;
8332
8333         if (method->klass->image->dynamic) {
8334                 MonoCustomAttrInfo *res, *ainfo;
8335                 int size;
8336
8337                 aux = g_hash_table_lookup (((MonoDynamicImage*)method->klass->image)->method_aux_hash, method);
8338                 if (!aux || !aux->param_cattr)
8339                         return NULL;
8340
8341                 /* Need to copy since it will be freed later */
8342                 ainfo = aux->param_cattr [param];
8343                 size = MONO_SIZEOF_CUSTOM_ATTR_INFO + sizeof (MonoCustomAttrEntry) * ainfo->num_attrs;
8344                 res = g_malloc0 (size);
8345                 memcpy (res, ainfo, size);
8346                 return res;
8347         }
8348
8349         image = method->klass->image;
8350         method_index = mono_method_get_index (method);
8351         ca = &image->tables [MONO_TABLE_METHOD];
8352
8353         param_list = mono_metadata_decode_row_col (ca, method_index - 1, MONO_METHOD_PARAMLIST);
8354         if (method_index == ca->rows) {
8355                 ca = &image->tables [MONO_TABLE_PARAM];
8356                 param_last = ca->rows + 1;
8357         } else {
8358                 param_last = mono_metadata_decode_row_col (ca, method_index, MONO_METHOD_PARAMLIST);
8359                 ca = &image->tables [MONO_TABLE_PARAM];
8360         }
8361         found = FALSE;
8362         for (i = param_list; i < param_last; ++i) {
8363                 param_pos = mono_metadata_decode_row_col (ca, i - 1, MONO_PARAM_SEQUENCE);
8364                 if (param_pos == param) {
8365                         found = TRUE;
8366                         break;
8367                 }
8368         }
8369         if (!found)
8370                 return NULL;
8371         idx = i;
8372         idx <<= MONO_CUSTOM_ATTR_BITS;
8373         idx |= MONO_CUSTOM_ATTR_PARAMDEF;
8374         return mono_custom_attrs_from_index (image, idx);
8375 }
8376
8377 gboolean
8378 mono_custom_attrs_has_attr (MonoCustomAttrInfo *ainfo, MonoClass *attr_klass)
8379 {
8380         int i;
8381         MonoClass *klass;
8382         for (i = 0; i < ainfo->num_attrs; ++i) {
8383                 klass = ainfo->attrs [i].ctor->klass;
8384                 if (mono_class_has_parent (klass, attr_klass) || (MONO_CLASS_IS_INTERFACE (attr_klass) && mono_class_is_assignable_from (attr_klass, klass)))
8385                         return TRUE;
8386         }
8387         return FALSE;
8388 }
8389
8390 MonoObject*
8391 mono_custom_attrs_get_attr (MonoCustomAttrInfo *ainfo, MonoClass *attr_klass)
8392 {
8393         int i, attr_index;
8394         MonoClass *klass;
8395         MonoArray *attrs;
8396
8397         attr_index = -1;
8398         for (i = 0; i < ainfo->num_attrs; ++i) {
8399                 klass = ainfo->attrs [i].ctor->klass;
8400                 if (mono_class_has_parent (klass, attr_klass)) {
8401                         attr_index = i;
8402                         break;
8403                 }
8404         }
8405         if (attr_index == -1)
8406                 return NULL;
8407
8408         attrs = mono_custom_attrs_construct (ainfo);
8409         if (attrs)
8410                 return mono_array_get (attrs, MonoObject*, attr_index);
8411         else
8412                 return NULL;
8413 }
8414
8415 /*
8416  * mono_reflection_get_custom_attrs_info:
8417  * @obj: a reflection object handle
8418  *
8419  * Return the custom attribute info for attributes defined for the
8420  * reflection handle @obj. The objects.
8421  *
8422  * FIXME this function leaks like a sieve for SRE objects.
8423  */
8424 MonoCustomAttrInfo*
8425 mono_reflection_get_custom_attrs_info (MonoObject *obj)
8426 {
8427         MonoClass *klass;
8428         MonoCustomAttrInfo *cinfo = NULL;
8429         
8430         klass = obj->vtable->klass;
8431         if (klass == mono_defaults.monotype_class) {
8432                 MonoType *type = mono_reflection_type_get_handle ((MonoReflectionType *)obj);
8433                 klass = mono_class_from_mono_type (type);
8434                 cinfo = mono_custom_attrs_from_class (klass);
8435         } else if (strcmp ("Assembly", klass->name) == 0) {
8436                 MonoReflectionAssembly *rassembly = (MonoReflectionAssembly*)obj;
8437                 cinfo = mono_custom_attrs_from_assembly (rassembly->assembly);
8438         } else if (strcmp ("Module", klass->name) == 0) {
8439                 MonoReflectionModule *module = (MonoReflectionModule*)obj;
8440                 cinfo = mono_custom_attrs_from_module (module->image);
8441         } else if (strcmp ("MonoProperty", klass->name) == 0) {
8442                 MonoReflectionProperty *rprop = (MonoReflectionProperty*)obj;
8443                 cinfo = mono_custom_attrs_from_property (rprop->property->parent, rprop->property);
8444         } else if (strcmp ("MonoEvent", klass->name) == 0) {
8445                 MonoReflectionMonoEvent *revent = (MonoReflectionMonoEvent*)obj;
8446                 cinfo = mono_custom_attrs_from_event (revent->event->parent, revent->event);
8447         } else if (strcmp ("MonoField", klass->name) == 0) {
8448                 MonoReflectionField *rfield = (MonoReflectionField*)obj;
8449                 cinfo = mono_custom_attrs_from_field (rfield->field->parent, rfield->field);
8450         } else if ((strcmp ("MonoMethod", klass->name) == 0) || (strcmp ("MonoCMethod", klass->name) == 0)) {
8451                 MonoReflectionMethod *rmethod = (MonoReflectionMethod*)obj;
8452                 cinfo = mono_custom_attrs_from_method (rmethod->method);
8453         } else if ((strcmp ("MonoGenericMethod", klass->name) == 0) || (strcmp ("MonoGenericCMethod", klass->name) == 0)) {
8454                 MonoReflectionMethod *rmethod = (MonoReflectionMethod*)obj;
8455                 cinfo = mono_custom_attrs_from_method (rmethod->method);
8456         } else if (strcmp ("ParameterInfo", klass->name) == 0) {
8457                 MonoReflectionParameter *param = (MonoReflectionParameter*)obj;
8458                 MonoReflectionMethod *rmethod = (MonoReflectionMethod*)param->MemberImpl;
8459                 cinfo = mono_custom_attrs_from_param (rmethod->method, param->PositionImpl + 1);
8460         } else if (strcmp ("AssemblyBuilder", klass->name) == 0) {
8461                 MonoReflectionAssemblyBuilder *assemblyb = (MonoReflectionAssemblyBuilder*)obj;
8462                 cinfo = mono_custom_attrs_from_builders (NULL, assemblyb->assembly.assembly->image, assemblyb->cattrs);
8463         } else if (strcmp ("TypeBuilder", klass->name) == 0) {
8464                 MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder*)obj;
8465                 cinfo = mono_custom_attrs_from_builders (NULL, &tb->module->dynamic_image->image, tb->cattrs);
8466         } else if (strcmp ("ModuleBuilder", klass->name) == 0) {
8467                 MonoReflectionModuleBuilder *mb = (MonoReflectionModuleBuilder*)obj;
8468                 cinfo = mono_custom_attrs_from_builders (NULL, &mb->dynamic_image->image, mb->cattrs);
8469         } else if (strcmp ("ConstructorBuilder", klass->name) == 0) {
8470                 MonoReflectionCtorBuilder *cb = (MonoReflectionCtorBuilder*)obj;
8471                 cinfo = mono_custom_attrs_from_builders (NULL, cb->mhandle->klass->image, cb->cattrs);
8472         } else if (strcmp ("MethodBuilder", klass->name) == 0) {
8473                 MonoReflectionMethodBuilder *mb = (MonoReflectionMethodBuilder*)obj;
8474                 cinfo = mono_custom_attrs_from_builders (NULL, mb->mhandle->klass->image, mb->cattrs);
8475         } else if (strcmp ("FieldBuilder", klass->name) == 0) {
8476                 MonoReflectionFieldBuilder *fb = (MonoReflectionFieldBuilder*)obj;
8477                 cinfo = mono_custom_attrs_from_builders (NULL, &((MonoReflectionTypeBuilder*)fb->typeb)->module->dynamic_image->image, fb->cattrs);
8478         } else if (strcmp ("MonoGenericClass", klass->name) == 0) {
8479                 MonoReflectionGenericClass *gclass = (MonoReflectionGenericClass*)obj;
8480                 cinfo = mono_reflection_get_custom_attrs_info ((MonoObject*)gclass->generic_type);
8481         } else { /* handle other types here... */
8482                 g_error ("get custom attrs not yet supported for %s", klass->name);
8483         }
8484
8485         return cinfo;
8486 }
8487
8488 /*
8489  * mono_reflection_get_custom_attrs_by_type:
8490  * @obj: a reflection object handle
8491  *
8492  * Return an array with all the custom attributes defined of the
8493  * reflection handle @obj. If @attr_klass is non-NULL, only custom attributes 
8494  * of that type are returned. The objects are fully build. Return NULL if a loading error
8495  * occurs.
8496  */
8497 MonoArray*
8498 mono_reflection_get_custom_attrs_by_type (MonoObject *obj, MonoClass *attr_klass)
8499 {
8500         MonoArray *result;
8501         MonoCustomAttrInfo *cinfo;
8502
8503         cinfo = mono_reflection_get_custom_attrs_info (obj);
8504         if (cinfo) {
8505                 if (attr_klass)
8506                         result = mono_custom_attrs_construct_by_type (cinfo, attr_klass);
8507                 else
8508                         result = mono_custom_attrs_construct (cinfo);
8509                 if (!cinfo->cached)
8510                         mono_custom_attrs_free (cinfo);
8511         } else {
8512                 if (mono_loader_get_last_error ())
8513                         return NULL;
8514                 result = mono_array_new_cached (mono_domain_get (), mono_defaults.attribute_class, 0);
8515         }
8516
8517         return result;
8518 }
8519
8520 /*
8521  * mono_reflection_get_custom_attrs:
8522  * @obj: a reflection object handle
8523  *
8524  * Return an array with all the custom attributes defined of the
8525  * reflection handle @obj. The objects are fully build. Return NULL if a loading error
8526  * occurs.
8527  */
8528 MonoArray*
8529 mono_reflection_get_custom_attrs (MonoObject *obj)
8530 {
8531         return mono_reflection_get_custom_attrs_by_type (obj, NULL);
8532 }
8533
8534 /*
8535  * mono_reflection_get_custom_attrs_data:
8536  * @obj: a reflection obj handle
8537  *
8538  * Returns an array of System.Reflection.CustomAttributeData,
8539  * which include information about attributes reflected on
8540  * types loaded using the Reflection Only methods
8541  */
8542 MonoArray*
8543 mono_reflection_get_custom_attrs_data (MonoObject *obj)
8544 {
8545         MonoArray *result;
8546         MonoCustomAttrInfo *cinfo;
8547
8548         cinfo = mono_reflection_get_custom_attrs_info (obj);
8549         if (cinfo) {
8550                 result = mono_custom_attrs_data_construct (cinfo);
8551                 if (!cinfo->cached)
8552                         mono_custom_attrs_free (cinfo);
8553         } else
8554                 result = mono_array_new (mono_domain_get (), mono_defaults.customattribute_data_class, 0);
8555
8556         return result;
8557 }
8558
8559 static MonoReflectionType*
8560 mono_reflection_type_get_underlying_system_type (MonoReflectionType* t)
8561 {
8562         MonoMethod *method_get_underlying_system_type;
8563
8564         method_get_underlying_system_type = mono_object_get_virtual_method ((MonoObject *) t,
8565                                                                             mono_class_get_method_from_name (mono_object_class (t),
8566                                                                                                              "get_UnderlyingSystemType",
8567                                                                                                              0));
8568         return (MonoReflectionType *) mono_runtime_invoke (method_get_underlying_system_type, t, NULL, NULL);
8569 }
8570
8571 #ifndef DISABLE_REFLECTION_EMIT
8572
8573 static gboolean
8574 is_corlib_type (MonoClass *class)
8575 {
8576         return class->image == mono_defaults.corlib;
8577 }
8578
8579 static gboolean
8580 is_usertype (MonoReflectionType *ref)
8581 {
8582         MonoClass *class = mono_object_class (ref);
8583         return class->image != mono_defaults.corlib || strcmp ("TypeDelegator", class->name) == 0;
8584 }
8585
8586 #define check_corlib_type_cached(_class, _namespace, _name) do { \
8587         static MonoClass *cached_class; \
8588         if (cached_class) \
8589                 return cached_class == _class; \
8590         if (is_corlib_type (_class) && !strcmp (_name, _class->name) && !strcmp (_namespace, _class->name_space)) { \
8591                 cached_class = _class; \
8592                 return TRUE; \
8593         } \
8594         return FALSE; \
8595 } while (0) \
8596
8597 static gboolean
8598 is_sre_array (MonoClass *class)
8599 {
8600         check_corlib_type_cached (class, "System.Reflection.Emit", "ArrayType");
8601 }
8602
8603 static gboolean
8604 is_sre_byref (MonoClass *class)
8605 {
8606         check_corlib_type_cached (class, "System.Reflection.Emit", "ByRefType");
8607 }
8608
8609 static gboolean
8610 is_sre_pointer (MonoClass *class)
8611 {
8612         check_corlib_type_cached (class, "System.Reflection.Emit", "PointerType");
8613 }
8614
8615 static gboolean
8616 is_sre_generic_instance (MonoClass *class)
8617 {
8618         check_corlib_type_cached (class, "System.Reflection", "MonoGenericClass");
8619 }
8620
8621 MonoType*
8622 mono_reflection_type_get_handle (MonoReflectionType* ref)
8623 {
8624         MonoClass *class;
8625         if (!ref)
8626                 return NULL;
8627         if (ref->type)
8628                 return ref->type;
8629
8630         if (is_usertype (ref)) {
8631                 ref = mono_reflection_type_get_underlying_system_type (ref);
8632                 g_assert (!is_usertype (ref)); /*FIXME fail better*/
8633                 if (ref->type)
8634                         return ref->type;
8635         }
8636
8637         class = mono_object_class (ref);
8638
8639         if (is_sre_array (class)) {
8640                 MonoType *res;
8641                 MonoReflectionArrayType *sre_array = (MonoReflectionArrayType*)ref;
8642                 MonoType *base = mono_reflection_type_get_handle (sre_array->element_type);
8643                 g_assert (base);
8644                 if (sre_array->rank == 0) //single dimentional array
8645                         res = &mono_array_class_get (mono_class_from_mono_type (base), 1)->byval_arg;
8646                 else
8647                         res = &mono_bounded_array_class_get (mono_class_from_mono_type (base), sre_array->rank, TRUE)->byval_arg;
8648                 sre_array->type.type = res;
8649                 return res;
8650         } else if (is_sre_byref (class)) {
8651                 MonoType *res;
8652                 MonoReflectionDerivedType *sre_byref = (MonoReflectionDerivedType*)ref;
8653                 MonoType *base = mono_reflection_type_get_handle (sre_byref->element_type);
8654                 g_assert (base);
8655                 res = &mono_class_from_mono_type (base)->this_arg;
8656                 sre_byref->type.type = res;
8657                 return res;
8658         } else if (is_sre_pointer (class)) {
8659                 MonoType *res;
8660                 MonoReflectionDerivedType *sre_pointer = (MonoReflectionDerivedType*)ref;
8661                 MonoType *base = mono_reflection_type_get_handle (sre_pointer->element_type);
8662                 g_assert (base);
8663                 res = &mono_ptr_class_get (base)->byval_arg;
8664                 sre_pointer->type.type = res;
8665                 return res;
8666         } else if (is_sre_generic_instance (class)) {
8667                 MonoType *res, **types;
8668                 MonoReflectionGenericClass *gclass = (MonoReflectionGenericClass*)ref;
8669                 int i, count;
8670
8671                 count = mono_array_length (gclass->type_arguments);
8672                 types = g_new0 (MonoType*, count);
8673                 for (i = 0; i < count; ++i) {
8674                         MonoReflectionType *t = mono_array_get (gclass->type_arguments, gpointer, i);
8675                         types [i] = mono_reflection_type_get_handle (t);
8676                 }
8677
8678                 res = mono_reflection_bind_generic_parameters ((MonoReflectionType*)gclass->generic_type, count, types);
8679                 g_free (types);
8680                 g_assert (res);
8681                 gclass->type.type = res;
8682                 return res;
8683         }
8684
8685         g_error ("Cannot handle corlib user type %s", mono_type_full_name (&mono_object_class(ref)->byval_arg));
8686         return NULL;
8687 }
8688
8689 static MonoReflectionType*
8690 mono_reflection_type_resolve_user_types (MonoReflectionType *type)
8691 {
8692         if (!type || type->type)
8693                 return type;
8694
8695         if (is_usertype (type)) {
8696                 type = mono_reflection_type_get_underlying_system_type (type);
8697                 if (is_usertype (type))
8698                         mono_raise_exception (mono_get_exception_not_supported ("User defined subclasses of System.Type are not yet supported22"));
8699         }
8700
8701         return type;
8702 }
8703
8704 void
8705 mono_reflection_create_unmanaged_type (MonoReflectionType *type)
8706 {
8707         mono_reflection_type_get_handle (type);
8708 }
8709
8710 /**
8711  * LOCKING: Assumes the loader lock is held.
8712  */
8713 static MonoMethodSignature*
8714 parameters_to_signature (MonoImage *image, MonoArray *parameters) {
8715         MonoMethodSignature *sig;
8716         int count, i;
8717
8718         count = parameters? mono_array_length (parameters): 0;
8719
8720         sig = image_g_malloc0 (image, MONO_SIZEOF_METHOD_SIGNATURE + sizeof (MonoType*) * count);
8721         sig->param_count = count;
8722         sig->sentinelpos = -1; /* FIXME */
8723         for (i = 0; i < count; ++i)
8724                 sig->params [i] = mono_type_array_get_and_resolve (parameters, i);
8725         return sig;
8726 }
8727
8728 /**
8729  * LOCKING: Assumes the loader lock is held.
8730  */
8731 static MonoMethodSignature*
8732 ctor_builder_to_signature (MonoImage *image, MonoReflectionCtorBuilder *ctor) {
8733         MonoMethodSignature *sig;
8734
8735         sig = parameters_to_signature (image, ctor->parameters);
8736         sig->hasthis = ctor->attrs & METHOD_ATTRIBUTE_STATIC? 0: 1;
8737         sig->ret = &mono_defaults.void_class->byval_arg;
8738         return sig;
8739 }
8740
8741 /**
8742  * LOCKING: Assumes the loader lock is held.
8743  */
8744 static MonoMethodSignature*
8745 method_builder_to_signature (MonoImage *image, MonoReflectionMethodBuilder *method) {
8746         MonoMethodSignature *sig;
8747
8748         sig = parameters_to_signature (image, method->parameters);
8749         sig->hasthis = method->attrs & METHOD_ATTRIBUTE_STATIC? 0: 1;
8750         sig->ret = method->rtype? mono_reflection_type_get_handle ((MonoReflectionType*)method->rtype): &mono_defaults.void_class->byval_arg;
8751         sig->generic_param_count = method->generic_params ? mono_array_length (method->generic_params) : 0;
8752         return sig;
8753 }
8754
8755 static MonoMethodSignature*
8756 dynamic_method_to_signature (MonoReflectionDynamicMethod *method) {
8757         MonoMethodSignature *sig;
8758
8759         sig = parameters_to_signature (NULL, method->parameters);
8760         sig->hasthis = method->attrs & METHOD_ATTRIBUTE_STATIC? 0: 1;
8761         sig->ret = method->rtype? mono_reflection_type_get_handle (method->rtype): &mono_defaults.void_class->byval_arg;
8762         sig->generic_param_count = 0;
8763         return sig;
8764 }
8765
8766 static void
8767 get_prop_name_and_type (MonoObject *prop, char **name, MonoType **type)
8768 {
8769         MonoClass *klass = mono_object_class (prop);
8770         if (strcmp (klass->name, "PropertyBuilder") == 0) {
8771                 MonoReflectionPropertyBuilder *pb = (MonoReflectionPropertyBuilder *)prop;
8772                 *name = mono_string_to_utf8 (pb->name);
8773                 *type = mono_reflection_type_get_handle ((MonoReflectionType*)pb->type);
8774         } else {
8775                 MonoReflectionProperty *p = (MonoReflectionProperty *)prop;
8776                 *name = g_strdup (p->property->name);
8777                 if (p->property->get)
8778                         *type = mono_method_signature (p->property->get)->ret;
8779                 else
8780                         *type = mono_method_signature (p->property->set)->params [mono_method_signature (p->property->set)->param_count - 1];
8781         }
8782 }
8783
8784 static void
8785 get_field_name_and_type (MonoObject *field, char **name, MonoType **type)
8786 {
8787         MonoClass *klass = mono_object_class (field);
8788         if (strcmp (klass->name, "FieldBuilder") == 0) {
8789                 MonoReflectionFieldBuilder *fb = (MonoReflectionFieldBuilder *)field;
8790                 *name = mono_string_to_utf8 (fb->name);
8791                 *type = mono_reflection_type_get_handle ((MonoReflectionType*)fb->type);
8792         } else {
8793                 MonoReflectionField *f = (MonoReflectionField *)field;
8794                 *name = g_strdup (mono_field_get_name (f->field));
8795                 *type = f->field->type;
8796         }
8797 }
8798 #endif /* !DISABLE_REFLECTION_EMIT */
8799
8800 /*
8801  * Encode a value in a custom attribute stream of bytes.
8802  * The value to encode is either supplied as an object in argument val
8803  * (valuetypes are boxed), or as a pointer to the data in the
8804  * argument argval.
8805  * @type represents the type of the value
8806  * @buffer is the start of the buffer
8807  * @p the current position in the buffer
8808  * @buflen contains the size of the buffer and is used to return the new buffer size
8809  * if this needs to be realloced.
8810  * @retbuffer and @retp return the start and the position of the buffer
8811  */
8812 static void
8813 encode_cattr_value (MonoAssembly *assembly, char *buffer, char *p, char **retbuffer, char **retp, guint32 *buflen, MonoType *type, MonoObject *arg, char *argval)
8814 {
8815         MonoTypeEnum simple_type;
8816         
8817         if ((p-buffer) + 10 >= *buflen) {
8818                 char *newbuf;
8819                 *buflen *= 2;
8820                 newbuf = g_realloc (buffer, *buflen);
8821                 p = newbuf + (p-buffer);
8822                 buffer = newbuf;
8823         }
8824         if (!argval)
8825                 argval = ((char*)arg + sizeof (MonoObject));
8826         simple_type = type->type;
8827 handle_enum:
8828         switch (simple_type) {
8829         case MONO_TYPE_BOOLEAN:
8830         case MONO_TYPE_U1:
8831         case MONO_TYPE_I1:
8832                 *p++ = *argval;
8833                 break;
8834         case MONO_TYPE_CHAR:
8835         case MONO_TYPE_U2:
8836         case MONO_TYPE_I2:
8837                 swap_with_size (p, argval, 2, 1);
8838                 p += 2;
8839                 break;
8840         case MONO_TYPE_U4:
8841         case MONO_TYPE_I4:
8842         case MONO_TYPE_R4:
8843                 swap_with_size (p, argval, 4, 1);
8844                 p += 4;
8845                 break;
8846         case MONO_TYPE_R8:
8847 #if defined(ARM_FPU_FPA) && G_BYTE_ORDER == G_LITTLE_ENDIAN
8848                 p [0] = argval [4];
8849                 p [1] = argval [5];
8850                 p [2] = argval [6];
8851                 p [3] = argval [7];
8852                 p [4] = argval [0];
8853                 p [5] = argval [1];
8854                 p [6] = argval [2];
8855                 p [7] = argval [3];
8856 #else
8857                 swap_with_size (p, argval, 8, 1);
8858 #endif
8859                 p += 8;
8860                 break;
8861         case MONO_TYPE_U8:
8862         case MONO_TYPE_I8:
8863                 swap_with_size (p, argval, 8, 1);
8864                 p += 8;
8865                 break;
8866         case MONO_TYPE_VALUETYPE:
8867                 if (type->data.klass->enumtype) {
8868                         simple_type = mono_class_enum_basetype (type->data.klass)->type;
8869                         goto handle_enum;
8870                 } else {
8871                         g_warning ("generic valutype %s not handled in custom attr value decoding", type->data.klass->name);
8872                 }
8873                 break;
8874         case MONO_TYPE_STRING: {
8875                 char *str;
8876                 guint32 slen;
8877                 if (!arg) {
8878                         *p++ = 0xFF;
8879                         break;
8880                 }
8881                 str = mono_string_to_utf8 ((MonoString*)arg);
8882                 slen = strlen (str);
8883                 if ((p-buffer) + 10 + slen >= *buflen) {
8884                         char *newbuf;
8885                         *buflen *= 2;
8886                         *buflen += slen;
8887                         newbuf = g_realloc (buffer, *buflen);
8888                         p = newbuf + (p-buffer);
8889                         buffer = newbuf;
8890                 }
8891                 mono_metadata_encode_value (slen, p, &p);
8892                 memcpy (p, str, slen);
8893                 p += slen;
8894                 g_free (str);
8895                 break;
8896         }
8897         case MONO_TYPE_CLASS: {
8898                 char *str;
8899                 guint32 slen;
8900                 if (!arg) {
8901                         *p++ = 0xFF;
8902                         break;
8903                 }
8904 handle_type:
8905                 str = type_get_qualified_name (mono_reflection_type_get_handle ((MonoReflectionType*)arg), NULL);
8906                 slen = strlen (str);
8907                 if ((p-buffer) + 10 + slen >= *buflen) {
8908                         char *newbuf;
8909                         *buflen *= 2;
8910                         *buflen += slen;
8911                         newbuf = g_realloc (buffer, *buflen);
8912                         p = newbuf + (p-buffer);
8913                         buffer = newbuf;
8914                 }
8915                 mono_metadata_encode_value (slen, p, &p);
8916                 memcpy (p, str, slen);
8917                 p += slen;
8918                 g_free (str);
8919                 break;
8920         }
8921         case MONO_TYPE_SZARRAY: {
8922                 int len, i;
8923                 MonoClass *eclass, *arg_eclass;
8924
8925                 if (!arg) {
8926                         *p++ = 0xff; *p++ = 0xff; *p++ = 0xff; *p++ = 0xff;
8927                         break;
8928                 }
8929                 len = mono_array_length ((MonoArray*)arg);
8930                 *p++ = len & 0xff;
8931                 *p++ = (len >> 8) & 0xff;
8932                 *p++ = (len >> 16) & 0xff;
8933                 *p++ = (len >> 24) & 0xff;
8934                 *retp = p;
8935                 *retbuffer = buffer;
8936                 eclass = type->data.klass;
8937                 arg_eclass = mono_object_class (arg)->element_class;
8938
8939                 if (!eclass) {
8940                         /* Happens when we are called from the MONO_TYPE_OBJECT case below */
8941                         eclass = mono_defaults.object_class;
8942                 }
8943                 if (eclass == mono_defaults.object_class && arg_eclass->valuetype) {
8944                         char *elptr = mono_array_addr ((MonoArray*)arg, char, 0);
8945                         int elsize = mono_class_array_element_size (arg_eclass);
8946                         for (i = 0; i < len; ++i) {
8947                                 encode_cattr_value (assembly, buffer, p, &buffer, &p, buflen, &arg_eclass->byval_arg, NULL, elptr);
8948                                 elptr += elsize;
8949                         }
8950                 } else if (eclass->valuetype && arg_eclass->valuetype) {
8951                         char *elptr = mono_array_addr ((MonoArray*)arg, char, 0);
8952                         int elsize = mono_class_array_element_size (eclass);
8953                         for (i = 0; i < len; ++i) {
8954                                 encode_cattr_value (assembly, buffer, p, &buffer, &p, buflen, &eclass->byval_arg, NULL, elptr);
8955                                 elptr += elsize;
8956                         }
8957                 } else {
8958                         for (i = 0; i < len; ++i) {
8959                                 encode_cattr_value (assembly, buffer, p, &buffer, &p, buflen, &eclass->byval_arg, mono_array_get ((MonoArray*)arg, MonoObject*, i), NULL);
8960                         }
8961                 }
8962                 break;
8963         }
8964         case MONO_TYPE_OBJECT: {
8965                 MonoClass *klass;
8966                 char *str;
8967                 guint32 slen;
8968
8969                 /*
8970                  * The parameter type is 'object' but the type of the actual
8971                  * argument is not. So we have to add type information to the blob
8972                  * too. This is completely undocumented in the spec.
8973                  */
8974
8975                 if (arg == NULL) {
8976                         *p++ = MONO_TYPE_STRING;        // It's same hack as MS uses
8977                         *p++ = 0xFF;
8978                         break;
8979                 }
8980                 
8981                 klass = mono_object_class (arg);
8982
8983                 if (mono_object_isinst (arg, mono_defaults.systemtype_class)) {
8984                         *p++ = 0x50;
8985                         goto handle_type;
8986                 } else if (klass->enumtype) {
8987                         *p++ = 0x55;
8988                 } else if (klass == mono_defaults.string_class) {
8989                         simple_type = MONO_TYPE_STRING;
8990                         *p++ = 0x0E;
8991                         goto handle_enum;
8992                 } else if (klass->rank == 1) {
8993                         *p++ = 0x1D;
8994                         if (klass->element_class->byval_arg.type == MONO_TYPE_OBJECT)
8995                                 /* See Partition II, Appendix B3 */
8996                                 *p++ = 0x51;
8997                         else
8998                                 *p++ = klass->element_class->byval_arg.type;
8999                         encode_cattr_value (assembly, buffer, p, &buffer, &p, buflen, &klass->byval_arg, arg, NULL);
9000                         break;
9001                 } else if (klass->byval_arg.type >= MONO_TYPE_BOOLEAN && klass->byval_arg.type <= MONO_TYPE_R8) {
9002                         *p++ = simple_type = klass->byval_arg.type;
9003                         goto handle_enum;
9004                 } else {
9005                         g_error ("unhandled type in custom attr");
9006                 }
9007                 str = type_get_qualified_name (mono_class_get_type(klass), NULL);
9008                 slen = strlen (str);
9009                 if ((p-buffer) + 10 + slen >= *buflen) {
9010                         char *newbuf;
9011                         *buflen *= 2;
9012                         *buflen += slen;
9013                         newbuf = g_realloc (buffer, *buflen);
9014                         p = newbuf + (p-buffer);
9015                         buffer = newbuf;
9016                 }
9017                 mono_metadata_encode_value (slen, p, &p);
9018                 memcpy (p, str, slen);
9019                 p += slen;
9020                 g_free (str);
9021                 simple_type = mono_class_enum_basetype (klass)->type;
9022                 goto handle_enum;
9023         }
9024         default:
9025                 g_error ("type 0x%02x not yet supported in custom attr encoder", simple_type);
9026         }
9027         *retp = p;
9028         *retbuffer = buffer;
9029 }
9030
9031 static void
9032 encode_field_or_prop_type (MonoType *type, char *p, char **retp)
9033 {
9034         if (type->type == MONO_TYPE_VALUETYPE && type->data.klass->enumtype) {
9035                 char *str = type_get_qualified_name (type, NULL);
9036                 int slen = strlen (str);
9037
9038                 *p++ = 0x55;
9039                 /*
9040                  * This seems to be optional...
9041                  * *p++ = 0x80;
9042                  */
9043                 mono_metadata_encode_value (slen, p, &p);
9044                 memcpy (p, str, slen);
9045                 p += slen;
9046                 g_free (str);
9047         } else if (type->type == MONO_TYPE_OBJECT) {
9048                 *p++ = 0x51;
9049         } else if (type->type == MONO_TYPE_CLASS) {
9050                 /* it should be a type: encode_cattr_value () has the check */
9051                 *p++ = 0x50;
9052         } else {
9053                 mono_metadata_encode_value (type->type, p, &p);
9054                 if (type->type == MONO_TYPE_SZARRAY)
9055                         /* See the examples in Partition VI, Annex B */
9056                         encode_field_or_prop_type (&type->data.klass->byval_arg, p, &p);
9057         }
9058
9059         *retp = p;
9060 }
9061
9062 #ifndef DISABLE_REFLECTION_EMIT
9063 static void
9064 encode_named_val (MonoReflectionAssembly *assembly, char *buffer, char *p, char **retbuffer, char **retp, guint32 *buflen, MonoType *type, char *name, MonoObject *value)
9065 {
9066         int len;
9067         /* Preallocate a large enough buffer */
9068         if (type->type == MONO_TYPE_VALUETYPE && type->data.klass->enumtype) {
9069                 char *str = type_get_qualified_name (type, NULL);
9070                 len = strlen (str);
9071                 g_free (str);
9072         } else if (type->type == MONO_TYPE_SZARRAY && type->data.klass->enumtype) {
9073                 char *str = type_get_qualified_name (&type->data.klass->byval_arg, NULL);
9074                 len = strlen (str);
9075                 g_free (str);
9076         } else {
9077                 len = 0;
9078         }
9079         len += strlen (name);
9080
9081         if ((p-buffer) + 20 + len >= *buflen) {
9082                 char *newbuf;
9083                 *buflen *= 2;
9084                 *buflen += len;
9085                 newbuf = g_realloc (buffer, *buflen);
9086                 p = newbuf + (p-buffer);
9087                 buffer = newbuf;
9088         }
9089
9090         encode_field_or_prop_type (type, p, &p);
9091
9092         len = strlen (name);
9093         mono_metadata_encode_value (len, p, &p);
9094         memcpy (p, name, len);
9095         p += len;
9096         encode_cattr_value (assembly->assembly, buffer, p, &buffer, &p, buflen, type, value, NULL);
9097         *retp = p;
9098         *retbuffer = buffer;
9099 }
9100
9101 /*
9102  * mono_reflection_get_custom_attrs_blob:
9103  * @ctor: custom attribute constructor
9104  * @ctorArgs: arguments o the constructor
9105  * @properties:
9106  * @propValues:
9107  * @fields:
9108  * @fieldValues:
9109  * 
9110  * Creates the blob of data that needs to be saved in the metadata and that represents
9111  * the custom attributed described by @ctor, @ctorArgs etc.
9112  * Returns: a Byte array representing the blob of data.
9113  */
9114 MonoArray*
9115 mono_reflection_get_custom_attrs_blob (MonoReflectionAssembly *assembly, MonoObject *ctor, MonoArray *ctorArgs, MonoArray *properties, MonoArray *propValues, MonoArray *fields, MonoArray* fieldValues) 
9116 {
9117         MonoArray *result;
9118         MonoMethodSignature *sig;
9119         MonoObject *arg;
9120         char *buffer, *p;
9121         guint32 buflen, i;
9122
9123         MONO_ARCH_SAVE_REGS;
9124
9125         if (strcmp (ctor->vtable->klass->name, "MonoCMethod")) {
9126                 /* sig is freed later so allocate it in the heap */
9127                 sig = ctor_builder_to_signature (NULL, (MonoReflectionCtorBuilder*)ctor);
9128         } else {
9129                 sig = mono_method_signature (((MonoReflectionMethod*)ctor)->method);
9130         }
9131
9132         g_assert (mono_array_length (ctorArgs) == sig->param_count);
9133         buflen = 256;
9134         p = buffer = g_malloc (buflen);
9135         /* write the prolog */
9136         *p++ = 1;
9137         *p++ = 0;
9138         for (i = 0; i < sig->param_count; ++i) {
9139                 arg = mono_array_get (ctorArgs, MonoObject*, i);
9140                 encode_cattr_value (assembly->assembly, buffer, p, &buffer, &p, &buflen, sig->params [i], arg, NULL);
9141         }
9142         i = 0;
9143         if (properties)
9144                 i += mono_array_length (properties);
9145         if (fields)
9146                 i += mono_array_length (fields);
9147         *p++ = i & 0xff;
9148         *p++ = (i >> 8) & 0xff;
9149         if (properties) {
9150                 MonoObject *prop;
9151                 for (i = 0; i < mono_array_length (properties); ++i) {
9152                         MonoType *ptype;
9153                         char *pname;
9154
9155                         prop = mono_array_get (properties, gpointer, i);
9156                         get_prop_name_and_type (prop, &pname, &ptype);
9157                         *p++ = 0x54; /* PROPERTY signature */
9158                         encode_named_val (assembly, buffer, p, &buffer, &p, &buflen, ptype, pname, (MonoObject*)mono_array_get (propValues, gpointer, i));
9159                         g_free (pname);
9160                 }
9161         }
9162
9163         if (fields) {
9164                 MonoObject *field;
9165                 for (i = 0; i < mono_array_length (fields); ++i) {
9166                         MonoType *ftype;
9167                         char *fname;
9168
9169                         field = mono_array_get (fields, gpointer, i);
9170                         get_field_name_and_type (field, &fname, &ftype);
9171                         *p++ = 0x53; /* FIELD signature */
9172                         encode_named_val (assembly, buffer, p, &buffer, &p, &buflen, ftype, fname, (MonoObject*)mono_array_get (fieldValues, gpointer, i));
9173                         g_free (fname);
9174                 }
9175         }
9176
9177         g_assert (p - buffer <= buflen);
9178         buflen = p - buffer;
9179         result = mono_array_new (mono_domain_get (), mono_defaults.byte_class, buflen);
9180         p = mono_array_addr (result, char, 0);
9181         memcpy (p, buffer, buflen);
9182         g_free (buffer);
9183         if (strcmp (ctor->vtable->klass->name, "MonoCMethod"))
9184                 g_free (sig);
9185         return result;
9186 }
9187
9188 /*
9189  * mono_reflection_setup_internal_class:
9190  * @tb: a TypeBuilder object
9191  *
9192  * Creates a MonoClass that represents the TypeBuilder.
9193  * This is a trick that lets us simplify a lot of reflection code
9194  * (and will allow us to support Build and Run assemblies easier).
9195  */
9196 void
9197 mono_reflection_setup_internal_class (MonoReflectionTypeBuilder *tb)
9198 {
9199         MonoClass *klass, *parent;
9200
9201         MONO_ARCH_SAVE_REGS;
9202
9203         RESOLVE_TYPE (tb->parent);
9204
9205         mono_loader_lock ();
9206
9207         if (tb->parent) {
9208                 /* check so we can compile corlib correctly */
9209                 if (strcmp (mono_object_class (tb->parent)->name, "TypeBuilder") == 0) {
9210                         /* mono_class_setup_mono_type () guaranteess type->data.klass is valid */
9211                         parent = mono_reflection_type_get_handle ((MonoReflectionType*)tb->parent)->data.klass;
9212                 } else {
9213                         parent = mono_class_from_mono_type (mono_reflection_type_get_handle ((MonoReflectionType*)tb->parent));
9214                 }
9215         } else {
9216                 parent = NULL;
9217         }
9218         
9219         /* the type has already being created: it means we just have to change the parent */
9220         if (tb->type.type) {
9221                 klass = mono_class_from_mono_type (tb->type.type);
9222                 klass->parent = NULL;
9223                 /* fool mono_class_setup_parent */
9224                 klass->supertypes = NULL;
9225                 mono_class_setup_parent (klass, parent);
9226                 mono_class_setup_mono_type (klass);
9227                 mono_loader_unlock ();
9228                 return;
9229         }
9230
9231         klass = mono_image_alloc0 (&tb->module->dynamic_image->image, sizeof (MonoClass));
9232
9233         klass->image = &tb->module->dynamic_image->image;
9234
9235         klass->inited = 1; /* we lie to the runtime */
9236         klass->name = mono_string_to_utf8_image (klass->image, tb->name);
9237         klass->name_space = mono_string_to_utf8_image (klass->image, tb->nspace);
9238         klass->type_token = MONO_TOKEN_TYPE_DEF | tb->table_idx;
9239         klass->flags = tb->attrs;
9240         
9241         mono_profiler_class_event (klass, MONO_PROFILE_START_LOAD);
9242
9243         klass->element_class = klass;
9244
9245         MOVING_GC_REGISTER (&klass->reflection_info);
9246         klass->reflection_info = tb;
9247
9248         /* Put into cache so mono_class_get () will find it */
9249         mono_image_add_to_name_cache (klass->image, klass->name_space, klass->name, tb->table_idx);
9250
9251         mono_g_hash_table_insert (tb->module->dynamic_image->tokens,
9252                 GUINT_TO_POINTER (MONO_TOKEN_TYPE_DEF | tb->table_idx), tb);
9253
9254         if (parent != NULL) {
9255                 mono_class_setup_parent (klass, parent);
9256         } else if (strcmp (klass->name, "Object") == 0 && strcmp (klass->name_space, "System") == 0) {
9257                 const char *old_n = klass->name;
9258                 /* trick to get relative numbering right when compiling corlib */
9259                 klass->name = "BuildingObject";
9260                 mono_class_setup_parent (klass, mono_defaults.object_class);
9261                 klass->name = old_n;
9262         }
9263
9264         if ((!strcmp (klass->name, "ValueType") && !strcmp (klass->name_space, "System")) ||
9265                         (!strcmp (klass->name, "Object") && !strcmp (klass->name_space, "System")) ||
9266                         (!strcmp (klass->name, "Enum") && !strcmp (klass->name_space, "System"))) {
9267                 klass->instance_size = sizeof (MonoObject);
9268                 klass->size_inited = 1;
9269                 mono_class_setup_vtable_general (klass, NULL, 0);
9270         }
9271
9272         mono_class_setup_mono_type (klass);
9273
9274         mono_class_setup_supertypes (klass);
9275
9276         /*
9277          * FIXME: handle interfaces.
9278          */
9279
9280         tb->type.type = &klass->byval_arg;
9281
9282         if (tb->nesting_type) {
9283                 g_assert (tb->nesting_type->type);
9284                 klass->nested_in = mono_class_from_mono_type (mono_reflection_type_get_handle (tb->nesting_type));
9285         }
9286
9287         /*g_print ("setup %s as %s (%p)\n", klass->name, ((MonoObject*)tb)->vtable->klass->name, tb);*/
9288
9289         mono_profiler_class_loaded (klass, MONO_PROFILE_OK);
9290         
9291         mono_loader_unlock ();
9292 }
9293
9294 /*
9295  * mono_reflection_setup_generic_class:
9296  * @tb: a TypeBuilder object
9297  *
9298  * Setup the generic class before adding the first generic parameter.
9299  */
9300 void
9301 mono_reflection_setup_generic_class (MonoReflectionTypeBuilder *tb)
9302 {
9303 }
9304
9305 /*
9306  * mono_reflection_create_generic_class:
9307  * @tb: a TypeBuilder object
9308  *
9309  * Creates the generic class after all generic parameters have been added.
9310  */
9311 void
9312 mono_reflection_create_generic_class (MonoReflectionTypeBuilder *tb)
9313 {
9314         MonoClass *klass;
9315         int count, i;
9316
9317         MONO_ARCH_SAVE_REGS;
9318
9319         klass = mono_class_from_mono_type (tb->type.type);
9320
9321         count = tb->generic_params ? mono_array_length (tb->generic_params) : 0;
9322
9323         if (klass->generic_container || (count == 0))
9324                 return;
9325
9326         g_assert (tb->generic_container && (tb->generic_container->owner.klass == klass));
9327
9328         klass->generic_container = mono_image_alloc0 (klass->image, sizeof (MonoGenericContainer));
9329
9330         klass->generic_container->owner.klass = klass;
9331         klass->generic_container->type_argc = count;
9332         klass->generic_container->type_params = mono_image_alloc0 (klass->image, sizeof (MonoGenericParamFull) * count);
9333
9334         klass->is_generic = 1;
9335
9336         for (i = 0; i < count; i++) {
9337                 MonoReflectionGenericParam *gparam = mono_array_get (tb->generic_params, gpointer, i);
9338                 MonoGenericParamFull *param = (MonoGenericParamFull *) mono_reflection_type_get_handle ((MonoReflectionType*)gparam)->data.generic_param;
9339                 klass->generic_container->type_params [i] = *param;
9340                 /*Make sure we are a diferent type instance */
9341                 klass->generic_container->type_params [i].param.owner = klass->generic_container;
9342                 klass->generic_container->type_params [i].info.pklass = NULL;
9343
9344                 g_assert (klass->generic_container->type_params [i].param.owner);
9345         }
9346
9347         klass->generic_container->context.class_inst = mono_get_shared_generic_inst (klass->generic_container);
9348 }
9349
9350 /*
9351  * mono_reflection_create_internal_class:
9352  * @tb: a TypeBuilder object
9353  *
9354  * Actually create the MonoClass that is associated with the TypeBuilder.
9355  */
9356 void
9357 mono_reflection_create_internal_class (MonoReflectionTypeBuilder *tb)
9358 {
9359         MonoClass *klass;
9360
9361         MONO_ARCH_SAVE_REGS;
9362
9363         klass = mono_class_from_mono_type (tb->type.type);
9364
9365         mono_loader_lock ();
9366         if (klass->enumtype && mono_class_enum_basetype (klass) == NULL) {
9367                 MonoReflectionFieldBuilder *fb;
9368                 MonoClass *ec;
9369                 MonoType *enum_basetype;
9370
9371                 g_assert (tb->fields != NULL);
9372                 g_assert (mono_array_length (tb->fields) >= 1);
9373
9374                 fb = mono_array_get (tb->fields, MonoReflectionFieldBuilder*, 0);
9375
9376                 if (!mono_type_is_valid_enum_basetype (mono_reflection_type_get_handle ((MonoReflectionType*)fb->type))) {
9377                         mono_loader_unlock ();
9378                         return;
9379                 }
9380
9381                 enum_basetype = mono_reflection_type_get_handle ((MonoReflectionType*)fb->type);
9382                 klass->element_class = mono_class_from_mono_type (enum_basetype);
9383                 if (!klass->element_class)
9384                         klass->element_class = mono_class_from_mono_type (enum_basetype);
9385
9386                 /*
9387                  * get the element_class from the current corlib.
9388                  */
9389                 ec = default_class_from_mono_type (enum_basetype);
9390                 klass->instance_size = ec->instance_size;
9391                 klass->size_inited = 1;
9392                 /* 
9393                  * this is almost safe to do with enums and it's needed to be able
9394                  * to create objects of the enum type (for use in SetConstant).
9395                  */
9396                 /* FIXME: Does this mean enums can't have method overrides ? */
9397                 mono_class_setup_vtable_general (klass, NULL, 0);
9398         }
9399         mono_loader_unlock ();
9400 }
9401
9402 static MonoMarshalSpec*
9403 mono_marshal_spec_from_builder (MonoImage *image, MonoAssembly *assembly,
9404                                                                 MonoReflectionMarshal *minfo)
9405 {
9406         MonoMarshalSpec *res;
9407
9408         res = image_g_new0 (image, MonoMarshalSpec, 1);
9409         res->native = minfo->type;
9410
9411         switch (minfo->type) {
9412         case MONO_NATIVE_LPARRAY:
9413                 res->data.array_data.elem_type = minfo->eltype;
9414                 if (minfo->has_size) {
9415                         res->data.array_data.param_num = minfo->param_num;
9416                         res->data.array_data.num_elem = minfo->count;
9417                         res->data.array_data.elem_mult = minfo->param_num == -1 ? 0 : 1;
9418                 }
9419                 else {
9420                         res->data.array_data.param_num = -1;
9421                         res->data.array_data.num_elem = -1;
9422                         res->data.array_data.elem_mult = -1;
9423                 }
9424                 break;
9425
9426         case MONO_NATIVE_BYVALTSTR:
9427         case MONO_NATIVE_BYVALARRAY:
9428                 res->data.array_data.num_elem = minfo->count;
9429                 break;
9430
9431         case MONO_NATIVE_CUSTOM:
9432                 if (minfo->marshaltyperef)
9433                         res->data.custom_data.custom_name =
9434                                 type_get_fully_qualified_name (mono_reflection_type_get_handle ((MonoReflectionType*)minfo->marshaltyperef));
9435                 if (minfo->mcookie)
9436                         res->data.custom_data.cookie = mono_string_to_utf8 (minfo->mcookie);
9437                 break;
9438
9439         default:
9440                 break;
9441         }
9442
9443         return res;
9444 }
9445 #endif /* !DISABLE_REFLECTION_EMIT */
9446
9447 MonoReflectionMarshal*
9448 mono_reflection_marshal_from_marshal_spec (MonoDomain *domain, MonoClass *klass,
9449                                                                                    MonoMarshalSpec *spec)
9450 {
9451         static MonoClass *System_Reflection_Emit_UnmanagedMarshalClass;
9452         MonoReflectionMarshal *minfo;
9453         MonoType *mtype;
9454
9455         if (!System_Reflection_Emit_UnmanagedMarshalClass) {
9456                 System_Reflection_Emit_UnmanagedMarshalClass = mono_class_from_name (
9457                    mono_defaults.corlib, "System.Reflection.Emit", "UnmanagedMarshal");
9458                 g_assert (System_Reflection_Emit_UnmanagedMarshalClass);
9459         }
9460
9461         minfo = (MonoReflectionMarshal*)mono_object_new (domain, System_Reflection_Emit_UnmanagedMarshalClass);
9462         minfo->type = spec->native;
9463
9464         switch (minfo->type) {
9465         case MONO_NATIVE_LPARRAY:
9466                 minfo->eltype = spec->data.array_data.elem_type;
9467                 minfo->count = spec->data.array_data.num_elem;
9468                 minfo->param_num = spec->data.array_data.param_num;
9469                 break;
9470
9471         case MONO_NATIVE_BYVALTSTR:
9472         case MONO_NATIVE_BYVALARRAY:
9473                 minfo->count = spec->data.array_data.num_elem;
9474                 break;
9475
9476         case MONO_NATIVE_CUSTOM:
9477                 if (spec->data.custom_data.custom_name) {
9478                         mtype = mono_reflection_type_from_name (spec->data.custom_data.custom_name, klass->image);
9479                         if (mtype)
9480                                 MONO_OBJECT_SETREF (minfo, marshaltyperef, mono_type_get_object (domain, mtype));
9481
9482                         MONO_OBJECT_SETREF (minfo, marshaltype, mono_string_new (domain, spec->data.custom_data.custom_name));
9483                 }
9484                 if (spec->data.custom_data.cookie)
9485                         MONO_OBJECT_SETREF (minfo, mcookie, mono_string_new (domain, spec->data.custom_data.cookie));
9486                 break;
9487
9488         default:
9489                 break;
9490         }
9491
9492         return minfo;
9493 }
9494
9495 #ifndef DISABLE_REFLECTION_EMIT
9496 static MonoMethod*
9497 reflection_methodbuilder_to_mono_method (MonoClass *klass,
9498                                          ReflectionMethodBuilder *rmb,
9499                                          MonoMethodSignature *sig)
9500 {
9501         MonoMethod *m;
9502         MonoMethodNormal *pm;
9503         MonoMarshalSpec **specs;
9504         MonoReflectionMethodAux *method_aux;
9505         MonoImage *image;
9506         gboolean dynamic;
9507         int i;
9508
9509         /*
9510          * Methods created using a MethodBuilder should have their memory allocated
9511          * inside the image mempool, while dynamic methods should have their memory
9512          * malloc'd.
9513          */
9514         dynamic = rmb->refs != NULL;
9515         image = dynamic ? NULL : klass->image;
9516
9517         if (!dynamic)
9518                 g_assert (!klass->generic_class);
9519
9520         mono_loader_lock ();
9521
9522         if ((rmb->attrs & METHOD_ATTRIBUTE_PINVOKE_IMPL) ||
9523                         (rmb->iattrs & METHOD_IMPL_ATTRIBUTE_INTERNAL_CALL))
9524                 m = (MonoMethod *)image_g_new0 (image, MonoMethodPInvoke, 1);
9525         else if (rmb->refs)
9526                 m = (MonoMethod *)image_g_new0 (image, MonoMethodWrapper, 1);
9527         else
9528                 m = (MonoMethod *)image_g_new0 (image, MonoMethodNormal, 1);
9529
9530         pm = (MonoMethodNormal*)m;
9531
9532         m->dynamic = dynamic;
9533         m->slot = -1;
9534         m->flags = rmb->attrs;
9535         m->iflags = rmb->iattrs;
9536         m->name = mono_string_to_utf8_image (image, rmb->name);
9537         m->klass = klass;
9538         m->signature = sig;
9539         m->skip_visibility = rmb->skip_visibility;
9540         if (rmb->table_idx)
9541                 m->token = MONO_TOKEN_METHOD_DEF | (*rmb->table_idx);
9542
9543         if (m->iflags & METHOD_IMPL_ATTRIBUTE_INTERNAL_CALL) {
9544                 if (klass == mono_defaults.string_class && !strcmp (m->name, ".ctor"))
9545                         m->string_ctor = 1;
9546
9547                 m->signature->pinvoke = 1;
9548         } else if (m->flags & METHOD_ATTRIBUTE_PINVOKE_IMPL) {
9549                 m->signature->pinvoke = 1;
9550
9551                 method_aux = image_g_new0 (image, MonoReflectionMethodAux, 1);
9552
9553                 method_aux->dllentry = rmb->dllentry ? mono_string_to_utf8_image (image, rmb->dllentry) : image_strdup (image, m->name);
9554                 method_aux->dll = mono_string_to_utf8_image (image, rmb->dll);
9555                 
9556                 ((MonoMethodPInvoke*)m)->piflags = (rmb->native_cc << 8) | (rmb->charset ? (rmb->charset - 1) * 2 : 0) | rmb->extra_flags;
9557
9558                 if (klass->image->dynamic)
9559                         g_hash_table_insert (((MonoDynamicImage*)klass->image)->method_aux_hash, m, method_aux);
9560
9561                 mono_loader_unlock ();
9562
9563                 return m;
9564         } else if (!(m->flags & METHOD_ATTRIBUTE_ABSTRACT) &&
9565                            !(m->iflags & METHOD_IMPL_ATTRIBUTE_RUNTIME)) {
9566                 MonoMethodHeader *header;
9567                 guint32 code_size;
9568                 gint32 max_stack, i;
9569                 gint32 num_locals = 0;
9570                 gint32 num_clauses = 0;
9571                 guint8 *code;
9572
9573                 if (rmb->ilgen) {
9574                         code = mono_array_addr (rmb->ilgen->code, guint8, 0);
9575                         code_size = rmb->ilgen->code_len;
9576                         max_stack = rmb->ilgen->max_stack;
9577                         num_locals = rmb->ilgen->locals ? mono_array_length (rmb->ilgen->locals) : 0;
9578                         if (rmb->ilgen->ex_handlers)
9579                                 num_clauses = method_count_clauses (rmb->ilgen);
9580                 } else {
9581                         if (rmb->code) {
9582                                 code = mono_array_addr (rmb->code, guint8, 0);
9583                                 code_size = mono_array_length (rmb->code);
9584                                 /* we probably need to run a verifier on the code... */
9585                                 max_stack = 8; 
9586                         }
9587                         else {
9588                                 code = NULL;
9589                                 code_size = 0;
9590                                 max_stack = 8;
9591                         }
9592                 }
9593
9594                 header = image_g_malloc0 (image, MONO_SIZEOF_METHOD_HEADER + num_locals * sizeof (MonoType*));
9595                 header->code_size = code_size;
9596                 header->code = image_g_malloc (image, code_size);
9597                 memcpy ((char*)header->code, code, code_size);
9598                 header->max_stack = max_stack;
9599                 header->init_locals = rmb->init_locals;
9600                 header->num_locals = num_locals;
9601
9602                 for (i = 0; i < num_locals; ++i) {
9603                         MonoReflectionLocalBuilder *lb = 
9604                                 mono_array_get (rmb->ilgen->locals, MonoReflectionLocalBuilder*, i);
9605
9606                         header->locals [i] = image_g_new0 (image, MonoType, 1);
9607                         memcpy (header->locals [i], mono_reflection_type_get_handle ((MonoReflectionType*)lb->type), MONO_SIZEOF_TYPE);
9608                 }
9609
9610                 header->num_clauses = num_clauses;
9611                 if (num_clauses) {
9612                         header->clauses = method_encode_clauses (image, (MonoDynamicImage*)klass->image,
9613                                  rmb->ilgen, num_clauses);
9614                 }
9615
9616                 pm->header = header;
9617         }
9618
9619         if (rmb->generic_params) {
9620                 int count = mono_array_length (rmb->generic_params);
9621                 MonoGenericContainer *container;
9622
9623                 container = rmb->generic_container;
9624                 if (container) {
9625                         m->is_generic = TRUE;
9626                         mono_method_set_generic_container (m, container);
9627                 }
9628                 container->type_argc = count;
9629                 container->type_params = image_g_new0 (image, MonoGenericParamFull, count);
9630                 container->owner.method = m;
9631
9632                 for (i = 0; i < count; i++) {
9633                         MonoReflectionGenericParam *gp =
9634                                 mono_array_get (rmb->generic_params, MonoReflectionGenericParam*, i);
9635                         MonoGenericParamFull *param = (MonoGenericParamFull *) mono_reflection_type_get_handle ((MonoReflectionType*)gp)->data.generic_param;
9636                         container->type_params [i] = *param;
9637                 }
9638
9639                 if (klass->generic_container) {
9640                         container->parent = klass->generic_container;
9641                         container->context.class_inst = klass->generic_container->context.class_inst;
9642                 }
9643                 container->context.method_inst = mono_get_shared_generic_inst (container);
9644         }
9645
9646         if (rmb->refs) {
9647                 MonoMethodWrapper *mw = (MonoMethodWrapper*)m;
9648                 int i;
9649                 void **data;
9650
9651                 m->wrapper_type = MONO_WRAPPER_DYNAMIC_METHOD;
9652
9653                 mw->method_data = data = image_g_new (image, gpointer, rmb->nrefs + 1);
9654                 data [0] = GUINT_TO_POINTER (rmb->nrefs);
9655                 for (i = 0; i < rmb->nrefs; ++i)
9656                         data [i + 1] = rmb->refs [i];
9657         }
9658
9659         method_aux = NULL;
9660
9661         /* Parameter info */
9662         if (rmb->pinfo) {
9663                 if (!method_aux)
9664                         method_aux = image_g_new0 (image, MonoReflectionMethodAux, 1);
9665                 method_aux->param_names = image_g_new0 (image, char *, mono_method_signature (m)->param_count + 1);
9666                 for (i = 0; i <= m->signature->param_count; ++i) {
9667                         MonoReflectionParamBuilder *pb;
9668                         if ((pb = mono_array_get (rmb->pinfo, MonoReflectionParamBuilder*, i))) {
9669                                 if ((i > 0) && (pb->attrs)) {
9670                                         /* Make a copy since it might point to a shared type structure */
9671                                         m->signature->params [i - 1] = mono_metadata_type_dup (klass->image, m->signature->params [i - 1]);
9672                                         m->signature->params [i - 1]->attrs = pb->attrs;
9673                                 }
9674
9675                                 if (pb->attrs & PARAM_ATTRIBUTE_HAS_DEFAULT) {
9676                                         MonoDynamicImage *assembly;
9677                                         guint32 idx, def_type, len;
9678                                         char *p;
9679                                         const char *p2;
9680
9681                                         if (!method_aux->param_defaults) {
9682                                                 method_aux->param_defaults = image_g_new0 (image, guint8*, m->signature->param_count + 1);
9683                                                 method_aux->param_default_types = image_g_new0 (image, guint32, m->signature->param_count + 1);
9684                                         }
9685                                         assembly = (MonoDynamicImage*)klass->image;
9686                                         idx = encode_constant (assembly, pb->def_value, &def_type);
9687                                         /* Copy the data from the blob since it might get realloc-ed */
9688                                         p = assembly->blob.data + idx;
9689                                         len = mono_metadata_decode_blob_size (p, &p2);
9690                                         len += p2 - p;
9691                                         method_aux->param_defaults [i] = image_g_malloc (image, len);
9692                                         method_aux->param_default_types [i] = def_type;
9693                                         memcpy ((gpointer)method_aux->param_defaults [i], p, len);
9694                                 }
9695
9696                                 if (pb->name)
9697                                         method_aux->param_names [i] = mono_string_to_utf8_image (image, pb->name);
9698                                 if (pb->cattrs) {
9699                                         if (!method_aux->param_cattr)
9700                                                 method_aux->param_cattr = image_g_new0 (image, MonoCustomAttrInfo*, m->signature->param_count + 1);
9701                                         method_aux->param_cattr [i] = mono_custom_attrs_from_builders (image, klass->image, pb->cattrs);
9702                                 }
9703                         }
9704                 }
9705         }
9706
9707         /* Parameter marshalling */
9708         specs = NULL;
9709         if (rmb->pinfo)         
9710                 for (i = 0; i < mono_array_length (rmb->pinfo); ++i) {
9711                         MonoReflectionParamBuilder *pb;
9712                         if ((pb = mono_array_get (rmb->pinfo, MonoReflectionParamBuilder*, i))) {
9713                                 if (pb->marshal_info) {
9714                                         if (specs == NULL)
9715                                                 specs = image_g_new0 (image, MonoMarshalSpec*, sig->param_count + 1);
9716                                         specs [pb->position] = 
9717                                                 mono_marshal_spec_from_builder (image, klass->image->assembly, pb->marshal_info);
9718                                 }
9719                         }
9720                 }
9721         if (specs != NULL) {
9722                 if (!method_aux)
9723                         method_aux = image_g_new0 (image, MonoReflectionMethodAux, 1);
9724                 method_aux->param_marshall = specs;
9725         }
9726
9727         if (klass->image->dynamic && method_aux)
9728                 g_hash_table_insert (((MonoDynamicImage*)klass->image)->method_aux_hash, m, method_aux);
9729
9730         mono_loader_unlock ();
9731
9732         return m;
9733 }       
9734
9735 static MonoMethod*
9736 ctorbuilder_to_mono_method (MonoClass *klass, MonoReflectionCtorBuilder* mb)
9737 {
9738         ReflectionMethodBuilder rmb;
9739         MonoMethodSignature *sig;
9740
9741         mono_loader_lock ();
9742         sig = ctor_builder_to_signature (klass->image, mb);
9743         mono_loader_unlock ();
9744
9745         reflection_methodbuilder_from_ctor_builder (&rmb, mb);
9746
9747         mb->mhandle = reflection_methodbuilder_to_mono_method (klass, &rmb, sig);
9748         mono_save_custom_attrs (klass->image, mb->mhandle, mb->cattrs);
9749
9750         /* If we are in a generic class, we might be called multiple times from inflate_method */
9751         if (!((MonoDynamicImage*)(MonoDynamicImage*)klass->image)->save && !klass->generic_container) {
9752                 /* ilgen is no longer needed */
9753                 mb->ilgen = NULL;
9754         }
9755
9756         return mb->mhandle;
9757 }
9758
9759 static MonoMethod*
9760 methodbuilder_to_mono_method (MonoClass *klass, MonoReflectionMethodBuilder* mb)
9761 {
9762         ReflectionMethodBuilder rmb;
9763         MonoMethodSignature *sig;
9764
9765         mono_loader_lock ();
9766         sig = method_builder_to_signature (klass->image, mb);
9767         mono_loader_unlock ();
9768
9769         reflection_methodbuilder_from_method_builder (&rmb, mb);
9770
9771         mb->mhandle = reflection_methodbuilder_to_mono_method (klass, &rmb, sig);
9772         mono_save_custom_attrs (klass->image, mb->mhandle, mb->cattrs);
9773
9774         /* If we are in a generic class, we might be called multiple times from inflate_method */
9775         if (!((MonoDynamicImage*)(MonoDynamicImage*)klass->image)->save && !klass->generic_container) {
9776                 /* ilgen is no longer needed */
9777                 mb->ilgen = NULL;
9778         }
9779         return mb->mhandle;
9780 }
9781
9782 static MonoClassField*
9783 fieldbuilder_to_mono_class_field (MonoClass *klass, MonoReflectionFieldBuilder* fb)
9784 {
9785         MonoClassField *field;
9786         MonoType *custom;
9787
9788         field = g_new0 (MonoClassField, 1);
9789
9790         field->name = mono_string_to_utf8 (fb->name);
9791         if (fb->attrs || fb->modreq || fb->modopt) {
9792                 field->type = mono_metadata_type_dup (NULL, mono_reflection_type_get_handle ((MonoReflectionType*)fb->type));
9793                 field->type->attrs = fb->attrs;
9794
9795                 g_assert (klass->image->dynamic);
9796                 custom = add_custom_modifiers ((MonoDynamicImage*)klass->image, field->type, fb->modreq, fb->modopt);
9797                 g_free (field->type);
9798                 field->type = custom;
9799         } else {
9800                 field->type = mono_reflection_type_get_handle ((MonoReflectionType*)fb->type);
9801         }
9802         if (fb->offset != -1)
9803                 field->offset = fb->offset;
9804         field->parent = klass;
9805         mono_save_custom_attrs (klass->image, field, fb->cattrs);
9806
9807         // FIXME: Can't store fb->def_value/RVA, is it needed for field_on_insts ?
9808
9809         return field;
9810 }
9811 #endif
9812
9813 MonoType*
9814 mono_reflection_bind_generic_parameters (MonoReflectionType *type, int type_argc, MonoType **types)
9815 {
9816         MonoClass *klass;
9817         MonoReflectionTypeBuilder *tb = NULL;
9818         gboolean is_dynamic = FALSE;
9819         MonoDomain *domain;
9820         MonoClass *geninst;
9821
9822         mono_loader_lock ();
9823
9824         domain = mono_object_domain (type);
9825
9826         if (!strcmp (((MonoObject *) type)->vtable->klass->name, "TypeBuilder")) {
9827                 tb = (MonoReflectionTypeBuilder *) type;
9828
9829                 is_dynamic = TRUE;
9830         } else if (!strcmp (((MonoObject *) type)->vtable->klass->name, "MonoGenericClass")) {
9831                 MonoReflectionGenericClass *rgi = (MonoReflectionGenericClass *) type;
9832
9833                 tb = rgi->generic_type;
9834                 is_dynamic = TRUE;
9835         }
9836
9837         /* FIXME: fix the CreateGenericParameters protocol to avoid the two stage setup of TypeBuilders */
9838         if (tb && tb->generic_container)
9839                 mono_reflection_create_generic_class (tb);
9840
9841         klass = mono_class_from_mono_type (mono_reflection_type_get_handle (type));
9842         if (!klass->generic_container) {
9843                 mono_loader_unlock ();
9844                 return NULL;
9845         }
9846
9847         if (klass->wastypebuilder) {
9848                 tb = (MonoReflectionTypeBuilder *) klass->reflection_info;
9849
9850                 is_dynamic = TRUE;
9851         }
9852
9853         mono_loader_unlock ();
9854
9855         geninst = mono_class_bind_generic_parameters (klass, type_argc, types, is_dynamic);
9856
9857         return &geninst->byval_arg;
9858 }
9859
9860 MonoClass*
9861 mono_class_bind_generic_parameters (MonoClass *klass, int type_argc, MonoType **types, gboolean is_dynamic)
9862 {
9863         MonoGenericClass *gclass;
9864         MonoGenericInst *inst;
9865
9866         g_assert (klass->generic_container);
9867
9868         inst = mono_metadata_get_generic_inst (type_argc, types);
9869         gclass = mono_metadata_lookup_generic_class (klass, inst, is_dynamic);
9870
9871         return mono_generic_class_get_class (gclass);
9872 }
9873
9874 MonoReflectionMethod*
9875 mono_reflection_bind_generic_method_parameters (MonoReflectionMethod *rmethod, MonoArray *types)
9876 {
9877         MonoClass *klass;
9878         MonoMethod *method, *inflated;
9879         MonoMethodInflated *imethod;
9880         MonoGenericContext tmp_context;
9881         MonoGenericInst *ginst;
9882         MonoType **type_argv;
9883         int count, i;
9884
9885         MONO_ARCH_SAVE_REGS;
9886
9887         if (!strcmp (rmethod->object.vtable->klass->name, "MethodBuilder")) {
9888 #ifndef DISABLE_REFLECTION_EMIT
9889                 MonoReflectionMethodBuilder *mb = NULL;
9890                 MonoReflectionTypeBuilder *tb;
9891                 MonoClass *klass;
9892
9893                 mb = (MonoReflectionMethodBuilder *) rmethod;
9894                 tb = (MonoReflectionTypeBuilder *) mb->type;
9895                 klass = mono_class_from_mono_type (mono_reflection_type_get_handle ((MonoReflectionType*)tb));
9896
9897                 method = methodbuilder_to_mono_method (klass, mb);
9898 #else
9899                 g_assert_not_reached ();
9900                 method = NULL;
9901 #endif
9902         } else {
9903                 method = rmethod->method;
9904         }
9905
9906         klass = method->klass;
9907
9908         if (method->is_inflated)
9909                 method = ((MonoMethodInflated *) method)->declaring;
9910
9911         count = mono_method_signature (method)->generic_param_count;
9912         if (count != mono_array_length (types))
9913                 return NULL;
9914
9915         type_argv = g_new0 (MonoType *, count);
9916         for (i = 0; i < count; i++) {
9917                 MonoReflectionType *garg = mono_array_get (types, gpointer, i);
9918                 type_argv [i] = mono_reflection_type_get_handle (garg);
9919         }
9920         ginst = mono_metadata_get_generic_inst (count, type_argv);
9921         g_free (type_argv);
9922
9923         tmp_context.class_inst = klass->generic_class ? klass->generic_class->context.class_inst : NULL;
9924         tmp_context.method_inst = ginst;
9925
9926         inflated = mono_class_inflate_generic_method (method, &tmp_context);
9927         imethod = (MonoMethodInflated *) inflated;
9928
9929         if (method->klass->image->dynamic) {
9930                 MonoDynamicImage *image = (MonoDynamicImage*)method->klass->image;
9931                 /*
9932                  * This table maps metadata structures representing inflated methods/fields
9933                  * to the reflection objects representing their generic definitions.
9934                  */
9935                 mono_loader_lock ();
9936                 mono_g_hash_table_insert (image->generic_def_objects, imethod, rmethod);
9937                 mono_loader_unlock ();
9938         }
9939         
9940         return mono_method_get_object (mono_object_domain (rmethod), inflated, NULL);
9941 }
9942
9943 #ifndef DISABLE_REFLECTION_EMIT
9944
9945 static MonoMethod *
9946 inflate_mono_method (MonoClass *klass, MonoMethod *method, MonoObject *obj)
9947 {
9948         MonoMethodInflated *imethod;
9949         MonoGenericContext *context;
9950         int i;
9951
9952         /*
9953          * With generic code sharing the klass might not be inflated.
9954          * This can happen because classes inflated with their own
9955          * type arguments are "normalized" to the uninflated class.
9956          */
9957         if (!klass->generic_class)
9958                 return method;
9959
9960         context = mono_class_get_context (klass);
9961
9962         if (klass->method.count) {
9963                 /* Find the already created inflated method */
9964                 for (i = 0; i < klass->method.count; ++i) {
9965                         g_assert (klass->methods [i]->is_inflated);
9966                         if (((MonoMethodInflated*)klass->methods [i])->declaring == method)
9967                                 break;
9968                 }
9969                 g_assert (i < klass->method.count);
9970                 imethod = (MonoMethodInflated*)klass->methods [i];
9971         } else {
9972                 imethod = (MonoMethodInflated *) mono_class_inflate_generic_method_full (method, klass, context);
9973         }
9974
9975         if (method->is_generic && method->klass->image->dynamic) {
9976                 MonoDynamicImage *image = (MonoDynamicImage*)method->klass->image;
9977
9978                 mono_loader_lock ();
9979                 mono_g_hash_table_insert (image->generic_def_objects, imethod, obj);
9980                 mono_loader_unlock ();
9981         }
9982         return (MonoMethod *) imethod;
9983 }
9984
9985 static MonoMethod *
9986 inflate_method (MonoReflectionGenericClass *type, MonoObject *obj)
9987 {
9988         MonoMethod *method;
9989         MonoClass *gklass;
9990
9991         gklass = mono_class_from_mono_type (mono_reflection_type_get_handle ((MonoReflectionType*)type->generic_type));
9992
9993         if (!strcmp (obj->vtable->klass->name, "MethodBuilder"))
9994                 if (((MonoReflectionMethodBuilder*)obj)->mhandle)
9995                         method = ((MonoReflectionMethodBuilder*)obj)->mhandle;
9996                 else
9997                         method = methodbuilder_to_mono_method (gklass, (MonoReflectionMethodBuilder *) obj);
9998         else if (!strcmp (obj->vtable->klass->name, "ConstructorBuilder"))
9999                 method = ctorbuilder_to_mono_method (gklass, (MonoReflectionCtorBuilder *) obj);
10000         else if (!strcmp (obj->vtable->klass->name, "MonoMethod") || !strcmp (obj->vtable->klass->name, "MonoCMethod"))
10001                 method = ((MonoReflectionMethod *) obj)->method;
10002         else {
10003                 method = NULL; /* prevent compiler warning */
10004                 g_error ("can't handle type %s", obj->vtable->klass->name);
10005         }
10006
10007         return inflate_mono_method (mono_class_from_mono_type (mono_reflection_type_get_handle ((MonoReflectionType*)type)), method, obj);
10008 }
10009
10010 /*TODO avoid saving custom attrs for generic classes as it's enough to have them on the generic type definition.*/
10011 void
10012 mono_reflection_generic_class_initialize (MonoReflectionGenericClass *type, MonoArray *methods, 
10013                                           MonoArray *ctors, MonoArray *fields, MonoArray *properties,
10014                                           MonoArray *events)
10015 {
10016         MonoGenericClass *gclass;
10017         MonoDynamicGenericClass *dgclass;
10018         MonoClass *klass, *gklass;
10019         MonoType *gtype;
10020         int i;
10021
10022         MONO_ARCH_SAVE_REGS;
10023
10024         gtype = mono_reflection_type_get_handle ((MonoReflectionType*)type);
10025         klass = mono_class_from_mono_type (gtype);
10026         g_assert (gtype->type == MONO_TYPE_GENERICINST);
10027         gclass = gtype->data.generic_class;
10028
10029         g_assert (gclass->is_dynamic);
10030         dgclass = (MonoDynamicGenericClass *) gclass;
10031
10032         if (dgclass->initialized)
10033                 return;
10034
10035         gklass = gclass->container_class;
10036         mono_class_init (gklass);
10037
10038         dgclass->count_methods = methods ? mono_array_length (methods) : 0;
10039         dgclass->count_ctors = ctors ? mono_array_length (ctors) : 0;
10040         dgclass->count_fields = fields ? mono_array_length (fields) : 0;
10041         dgclass->count_properties = properties ? mono_array_length (properties) : 0;
10042         dgclass->count_events = events ? mono_array_length (events) : 0;
10043
10044         dgclass->methods = g_new0 (MonoMethod *, dgclass->count_methods);
10045         dgclass->ctors = g_new0 (MonoMethod *, dgclass->count_ctors);
10046         dgclass->fields = g_new0 (MonoClassField, dgclass->count_fields);
10047         dgclass->properties = g_new0 (MonoProperty, dgclass->count_properties);
10048         dgclass->events = g_new0 (MonoEvent, dgclass->count_events);
10049         dgclass->field_objects = g_new0 (MonoObject*, dgclass->count_fields);
10050         dgclass->field_generic_types = g_new0 (MonoType*, dgclass->count_fields);
10051
10052         for (i = 0; i < dgclass->count_methods; i++) {
10053                 MonoObject *obj = mono_array_get (methods, gpointer, i);
10054
10055                 dgclass->methods [i] = inflate_method (type, obj);
10056         }
10057
10058         for (i = 0; i < dgclass->count_ctors; i++) {
10059                 MonoObject *obj = mono_array_get (ctors, gpointer, i);
10060
10061                 dgclass->ctors [i] = inflate_method (type, obj);
10062         }
10063
10064         for (i = 0; i < dgclass->count_fields; i++) {
10065                 MonoObject *obj = mono_array_get (fields, gpointer, i);
10066                 MonoClassField *field, *inflated_field = NULL;
10067
10068                 if (!strcmp (obj->vtable->klass->name, "FieldBuilder"))
10069                         inflated_field = field = fieldbuilder_to_mono_class_field (klass, (MonoReflectionFieldBuilder *) obj);
10070                 else if (!strcmp (obj->vtable->klass->name, "MonoField"))
10071                         field = ((MonoReflectionField *) obj)->field;
10072                 else {
10073                         field = NULL; /* prevent compiler warning */
10074                         g_assert_not_reached ();
10075                 }
10076
10077                 dgclass->fields [i] = *field;
10078                 dgclass->fields [i].parent = klass;
10079                 dgclass->fields [i].type = mono_class_inflate_generic_type (
10080                         field->type, mono_generic_class_get_context ((MonoGenericClass *) dgclass));
10081                 dgclass->field_generic_types [i] = field->type;
10082                 MOVING_GC_REGISTER (&dgclass->field_objects [i]);
10083                 dgclass->field_objects [i] = obj;
10084
10085                 if (inflated_field) {
10086                         g_free (inflated_field);
10087                 } else {
10088                         dgclass->fields [i].name = g_strdup (dgclass->fields [i].name);
10089                 }
10090         }
10091
10092         for (i = 0; i < dgclass->count_properties; i++) {
10093                 MonoObject *obj = mono_array_get (properties, gpointer, i);
10094                 MonoProperty *property = &dgclass->properties [i];
10095
10096                 if (!strcmp (obj->vtable->klass->name, "PropertyBuilder")) {
10097                         MonoReflectionPropertyBuilder *pb = (MonoReflectionPropertyBuilder *) obj;
10098
10099                         property->parent = klass;
10100                         property->attrs = pb->attrs;
10101                         property->name = mono_string_to_utf8 (pb->name);
10102                         if (pb->get_method)
10103                                 property->get = inflate_method (type, (MonoObject *) pb->get_method);
10104                         if (pb->set_method)
10105                                 property->set = inflate_method (type, (MonoObject *) pb->set_method);
10106                 } else if (!strcmp (obj->vtable->klass->name, "MonoProperty")) {
10107                         *property = *((MonoReflectionProperty *) obj)->property;
10108                         property->name = g_strdup (property->name);
10109
10110                         if (property->get)
10111                                 property->get = inflate_mono_method (klass, property->get, NULL);
10112                         if (property->set)
10113                                 property->set = inflate_mono_method (klass, property->set, NULL);
10114                 } else
10115                         g_assert_not_reached ();
10116         }
10117
10118         for (i = 0; i < dgclass->count_events; i++) {
10119                 MonoObject *obj = mono_array_get (events, gpointer, i);
10120                 MonoEvent *event = &dgclass->events [i];
10121
10122                 if (!strcmp (obj->vtable->klass->name, "EventBuilder")) {
10123                         MonoReflectionEventBuilder *eb = (MonoReflectionEventBuilder *) obj;
10124
10125                         event->parent = klass;
10126                         event->attrs = eb->attrs;
10127                         event->name = mono_string_to_utf8 (eb->name);
10128                         if (eb->add_method)
10129                                 event->add = inflate_method (type, (MonoObject *) eb->add_method);
10130                         if (eb->remove_method)
10131                                 event->remove = inflate_method (type, (MonoObject *) eb->remove_method);
10132                 } else if (!strcmp (obj->vtable->klass->name, "MonoEvent")) {
10133                         *event = *((MonoReflectionMonoEvent *) obj)->event;
10134                         event->name = g_strdup (event->name);
10135
10136                         if (event->add)
10137                                 event->add = inflate_mono_method (klass, event->add, NULL);
10138                         if (event->remove)
10139                                 event->remove = inflate_mono_method (klass, event->remove, NULL);
10140                 } else
10141                         g_assert_not_reached ();
10142         }
10143
10144         dgclass->initialized = TRUE;
10145 }
10146
10147 static void
10148 ensure_generic_class_runtime_vtable (MonoClass *klass)
10149 {
10150         MonoClass *gklass = klass->generic_class->container_class;
10151         int i;
10152
10153         if (klass->wastypebuilder)
10154                 return;
10155
10156         ensure_runtime_vtable (gklass);
10157
10158         klass->method.count = gklass->method.count;
10159         klass->methods = mono_image_alloc (klass->image, sizeof (MonoMethod*) * (klass->method.count + 1));
10160
10161         for (i = 0; i < klass->method.count; i++) {
10162                 klass->methods [i] = mono_class_inflate_generic_method_full (
10163                         gklass->methods [i], klass, mono_class_get_context (klass));
10164         }
10165
10166         klass->interface_count = gklass->interface_count;
10167         klass->interfaces = mono_image_alloc (klass->image, sizeof (MonoClass*) * klass->interface_count);
10168         for (i = 0; i < klass->interface_count; ++i) {
10169                 MonoType *iface_type = mono_class_inflate_generic_type (&gklass->interfaces [i]->byval_arg, mono_class_get_context (klass));
10170                 klass->interfaces [i] = mono_class_from_mono_type (iface_type);
10171                 mono_metadata_free_type (iface_type);
10172
10173                 ensure_runtime_vtable (klass->interfaces [i]);
10174         }
10175         klass->interfaces_inited = 1;
10176
10177         /*We can only finish with this klass once it's parent has as well*/
10178         if (gklass->wastypebuilder)
10179                 klass->wastypebuilder = TRUE;
10180         return;
10181 }
10182
10183 static void
10184 ensure_runtime_vtable (MonoClass *klass)
10185 {
10186         MonoReflectionTypeBuilder *tb = klass->reflection_info;
10187         int i, num, j;
10188
10189         if (!klass->image->dynamic || (!tb && !klass->generic_class) || klass->wastypebuilder)
10190                 return;
10191         if (klass->parent)
10192                 ensure_runtime_vtable (klass->parent);
10193
10194         if (tb) {
10195                 num = tb->ctors? mono_array_length (tb->ctors): 0;
10196                 num += tb->num_methods;
10197                 klass->method.count = num;
10198                 klass->methods = mono_image_alloc (klass->image, sizeof (MonoMethod*) * num);
10199                 num = tb->ctors? mono_array_length (tb->ctors): 0;
10200                 for (i = 0; i < num; ++i)
10201                         klass->methods [i] = ctorbuilder_to_mono_method (klass, mono_array_get (tb->ctors, MonoReflectionCtorBuilder*, i));
10202                 num = tb->num_methods;
10203                 j = i;
10204                 for (i = 0; i < num; ++i)
10205                         klass->methods [j++] = methodbuilder_to_mono_method (klass, mono_array_get (tb->methods, MonoReflectionMethodBuilder*, i));
10206         
10207                 if (tb->interfaces) {
10208                         klass->interface_count = mono_array_length (tb->interfaces);
10209                         klass->interfaces = mono_image_alloc (klass->image, sizeof (MonoClass*) * klass->interface_count);
10210                         for (i = 0; i < klass->interface_count; ++i) {
10211                                 MonoType *iface = mono_type_array_get_and_resolve (tb->interfaces, i);
10212                                 klass->interfaces [i] = mono_class_from_mono_type (iface);
10213                                 ensure_runtime_vtable (klass->interfaces [i]);
10214                         }
10215                         klass->interfaces_inited = 1;
10216                 }
10217         } else if (klass->generic_class){
10218                 ensure_generic_class_runtime_vtable (klass);
10219         }
10220
10221         if (klass->flags & TYPE_ATTRIBUTE_INTERFACE) {
10222                 for (i = 0; i < klass->method.count; ++i)
10223                         klass->methods [i]->slot = i;
10224                 
10225                 mono_class_setup_interface_offsets (klass);
10226                 mono_class_setup_interface_id (klass);
10227         }
10228
10229         /*
10230          * The generic vtable is needed even if image->run is not set since some
10231          * runtime code like ves_icall_Type_GetMethodsByName depends on 
10232          * method->slot being defined.
10233          */
10234
10235         /* 
10236          * tb->methods could not be freed since it is used for determining 
10237          * overrides during dynamic vtable construction.
10238          */
10239 }
10240
10241 void
10242 mono_reflection_get_dynamic_overrides (MonoClass *klass, MonoMethod ***overrides, int *num_overrides)
10243 {
10244         MonoReflectionTypeBuilder *tb;
10245         int i, onum;
10246
10247         *overrides = NULL;
10248         *num_overrides = 0;
10249
10250         g_assert (klass->image->dynamic);
10251
10252         if (!klass->reflection_info)
10253                 return;
10254
10255         g_assert (strcmp (((MonoObject*)klass->reflection_info)->vtable->klass->name, "TypeBuilder") == 0);
10256
10257         tb = (MonoReflectionTypeBuilder*)klass->reflection_info;
10258
10259         onum = 0;
10260         if (tb->methods) {
10261                 for (i = 0; i < tb->num_methods; ++i) {
10262                         MonoReflectionMethodBuilder *mb = 
10263                                 mono_array_get (tb->methods, MonoReflectionMethodBuilder*, i);
10264                         if (mb->override_method)
10265                                 onum ++;
10266                 }
10267         }
10268
10269         if (onum) {
10270                 *overrides = g_new0 (MonoMethod*, onum * 2);
10271
10272                 onum = 0;
10273                 for (i = 0; i < tb->num_methods; ++i) {
10274                         MonoReflectionMethodBuilder *mb = 
10275                                 mono_array_get (tb->methods, MonoReflectionMethodBuilder*, i);
10276                         if (mb->override_method) {
10277                                 (*overrides) [onum * 2] = 
10278                                         mb->override_method->method;
10279                                 (*overrides) [onum * 2 + 1] =
10280                                         mb->mhandle;
10281
10282                                 /* FIXME: What if 'override_method' is a MethodBuilder ? */
10283                                 g_assert (mb->override_method->method);
10284                                 g_assert (mb->mhandle);
10285
10286                                 onum ++;
10287                         }
10288                 }
10289         }
10290
10291         *num_overrides = onum;
10292 }
10293
10294 static void
10295 typebuilder_setup_fields (MonoClass *klass)
10296 {
10297         MonoReflectionTypeBuilder *tb = klass->reflection_info;
10298         MonoReflectionFieldBuilder *fb;
10299         MonoClassField *field;
10300         MonoImage *image = klass->image;
10301         const char *p, *p2;
10302         int i;
10303         guint32 len, idx, real_size = 0;
10304
10305         klass->field.count = tb->num_fields;
10306         klass->field.first = 0;
10307
10308         if (tb->class_size) {
10309                 g_assert ((tb->packing_size & 0xfffffff0) == 0);
10310                 klass->packing_size = tb->packing_size;
10311                 real_size = klass->instance_size + tb->class_size;
10312         }
10313
10314         if (!klass->field.count) {
10315                 klass->instance_size = MAX (klass->instance_size, real_size);
10316                 return;
10317         }
10318         
10319         klass->fields = image_g_new0 (image, MonoClassField, klass->field.count);
10320         mono_class_alloc_ext (klass);
10321         klass->ext->field_def_values = image_g_new0 (image, MonoFieldDefaultValue, klass->field.count);
10322
10323         for (i = 0; i < klass->field.count; ++i) {
10324                 fb = mono_array_get (tb->fields, gpointer, i);
10325                 field = &klass->fields [i];
10326                 field->name = mono_string_to_utf8_image (image, fb->name);
10327                 if (fb->attrs) {
10328                         field->type = mono_metadata_type_dup (klass->image, mono_reflection_type_get_handle ((MonoReflectionType*)fb->type));
10329                         field->type->attrs = fb->attrs;
10330                 } else {
10331                         field->type = mono_reflection_type_get_handle ((MonoReflectionType*)fb->type);
10332                 }
10333                 if ((fb->attrs & FIELD_ATTRIBUTE_HAS_FIELD_RVA) && fb->rva_data)
10334                         klass->ext->field_def_values [i].data = mono_array_addr (fb->rva_data, char, 0);
10335                 if (fb->offset != -1)
10336                         field->offset = fb->offset;
10337                 field->parent = klass;
10338                 fb->handle = field;
10339                 mono_save_custom_attrs (klass->image, field, fb->cattrs);
10340
10341                 if (fb->def_value) {
10342                         MonoDynamicImage *assembly = (MonoDynamicImage*)klass->image;
10343                         field->type->attrs |= FIELD_ATTRIBUTE_HAS_DEFAULT;
10344                         idx = encode_constant (assembly, fb->def_value, &klass->ext->field_def_values [i].def_type);
10345                         /* Copy the data from the blob since it might get realloc-ed */
10346                         p = assembly->blob.data + idx;
10347                         len = mono_metadata_decode_blob_size (p, &p2);
10348                         len += p2 - p;
10349                         klass->ext->field_def_values [i].data = mono_image_alloc (image, len);
10350                         memcpy ((gpointer)klass->ext->field_def_values [i].data, p, len);
10351                 }
10352         }
10353
10354         klass->instance_size = MAX (klass->instance_size, real_size);
10355         mono_class_layout_fields (klass);
10356 }
10357
10358 static void
10359 typebuilder_setup_properties (MonoClass *klass)
10360 {
10361         MonoReflectionTypeBuilder *tb = klass->reflection_info;
10362         MonoReflectionPropertyBuilder *pb;
10363         MonoImage *image = klass->image;
10364         MonoProperty *properties;
10365         int i;
10366
10367         if (!klass->ext)
10368                 klass->ext = image_g_new0 (image, MonoClassExt, 1);
10369
10370         klass->ext->property.count = tb->properties ? mono_array_length (tb->properties) : 0;
10371         klass->ext->property.first = 0;
10372
10373         properties = image_g_new0 (image, MonoProperty, klass->ext->property.count);
10374         klass->ext->properties = properties;
10375         for (i = 0; i < klass->ext->property.count; ++i) {
10376                 pb = mono_array_get (tb->properties, MonoReflectionPropertyBuilder*, i);
10377                 properties [i].parent = klass;
10378                 properties [i].attrs = pb->attrs;
10379                 properties [i].name = mono_string_to_utf8_image (image, pb->name);
10380                 if (pb->get_method)
10381                         properties [i].get = pb->get_method->mhandle;
10382                 if (pb->set_method)
10383                         properties [i].set = pb->set_method->mhandle;
10384
10385                 mono_save_custom_attrs (klass->image, &properties [i], pb->cattrs);
10386         }
10387 }
10388
10389 MonoReflectionEvent *
10390 mono_reflection_event_builder_get_event_info (MonoReflectionTypeBuilder *tb, MonoReflectionEventBuilder *eb)
10391 {
10392         MonoEvent *event = g_new0 (MonoEvent, 1);
10393         MonoClass *klass;
10394         int j;
10395
10396         klass = mono_class_from_mono_type (mono_reflection_type_get_handle ((MonoReflectionType*)tb));
10397
10398         event->parent = klass;
10399         event->attrs = eb->attrs;
10400         event->name = mono_string_to_utf8 (eb->name);
10401         if (eb->add_method)
10402                 event->add = eb->add_method->mhandle;
10403         if (eb->remove_method)
10404                 event->remove = eb->remove_method->mhandle;
10405         if (eb->raise_method)
10406                 event->raise = eb->raise_method->mhandle;
10407
10408         if (eb->other_methods) {
10409                 event->other = g_new0 (MonoMethod*, mono_array_length (eb->other_methods) + 1);
10410                 for (j = 0; j < mono_array_length (eb->other_methods); ++j) {
10411                         MonoReflectionMethodBuilder *mb = 
10412                                 mono_array_get (eb->other_methods,
10413                                                 MonoReflectionMethodBuilder*, j);
10414                         event->other [j] = mb->mhandle;
10415                 }
10416         }
10417
10418         return mono_event_get_object (mono_object_domain (tb), klass, event);
10419 }
10420
10421 static void
10422 typebuilder_setup_events (MonoClass *klass)
10423 {
10424         MonoReflectionTypeBuilder *tb = klass->reflection_info;
10425         MonoReflectionEventBuilder *eb;
10426         MonoImage *image = klass->image;
10427         MonoEvent *events;
10428         int i, j;
10429
10430         if (!klass->ext)
10431                 klass->ext = image_g_new0 (image, MonoClassExt, 1);
10432
10433         klass->ext->event.count = tb->events ? mono_array_length (tb->events) : 0;
10434         klass->ext->event.first = 0;
10435
10436         events = image_g_new0 (image, MonoEvent, klass->ext->event.count);
10437         klass->ext->events = events;
10438         for (i = 0; i < klass->ext->event.count; ++i) {
10439                 eb = mono_array_get (tb->events, MonoReflectionEventBuilder*, i);
10440                 events [i].parent = klass;
10441                 events [i].attrs = eb->attrs;
10442                 events [i].name = mono_string_to_utf8_image (image, eb->name);
10443                 if (eb->add_method)
10444                         events [i].add = eb->add_method->mhandle;
10445                 if (eb->remove_method)
10446                         events [i].remove = eb->remove_method->mhandle;
10447                 if (eb->raise_method)
10448                         events [i].raise = eb->raise_method->mhandle;
10449
10450                 if (eb->other_methods) {
10451                         events [i].other = image_g_new0 (image, MonoMethod*, mono_array_length (eb->other_methods) + 1);
10452                         for (j = 0; j < mono_array_length (eb->other_methods); ++j) {
10453                                 MonoReflectionMethodBuilder *mb = 
10454                                         mono_array_get (eb->other_methods,
10455                                                                         MonoReflectionMethodBuilder*, j);
10456                                 events [i].other [j] = mb->mhandle;
10457                         }
10458                 }
10459                 mono_save_custom_attrs (klass->image, &events [i], eb->cattrs);
10460         }
10461 }
10462
10463 static gboolean
10464 remove_instantiations_of (gpointer key,
10465                                                   gpointer value,
10466                                                   gpointer user_data)
10467 {
10468         MonoType *type = (MonoType*)key;
10469         MonoClass *klass = (MonoClass*)user_data;
10470
10471         if ((type->type == MONO_TYPE_GENERICINST) && (type->data.generic_class->container_class == klass))
10472                 return TRUE;
10473         else
10474                 return FALSE;
10475 }
10476
10477 static void
10478 check_array_for_usertypes (MonoArray *arr)
10479 {
10480         int i;
10481
10482         if (!arr)
10483                 return;
10484
10485         for (i = 0; i < mono_array_length (arr); ++i)
10486                 RESOLVE_ARRAY_TYPE_ELEMENT (arr, i);
10487 }
10488
10489 MonoReflectionType*
10490 mono_reflection_create_runtime_class (MonoReflectionTypeBuilder *tb)
10491 {
10492         MonoClass *klass;
10493         MonoDomain* domain;
10494         MonoReflectionType* res;
10495         int i, j;
10496
10497         MONO_ARCH_SAVE_REGS;
10498
10499         domain = mono_object_domain (tb);
10500         klass = mono_class_from_mono_type (tb->type.type);
10501
10502         /*
10503          * Check for user defined Type subclasses.
10504          */
10505         RESOLVE_TYPE (tb->parent);
10506         check_array_for_usertypes (tb->interfaces);
10507         if (tb->fields) {
10508                 for (i = 0; i < mono_array_length (tb->fields); ++i) {
10509                         MonoReflectionFieldBuilder *fb = mono_array_get (tb->fields, gpointer, i);
10510                         if (fb) {
10511                                 RESOLVE_TYPE (fb->type);
10512                                 check_array_for_usertypes (fb->modreq);
10513                                 check_array_for_usertypes (fb->modopt);
10514                                 if (fb->marshal_info && fb->marshal_info->marshaltyperef)
10515                                         RESOLVE_TYPE (fb->marshal_info->marshaltyperef);
10516                         }
10517                 }
10518         }
10519         if (tb->methods) {
10520                 for (i = 0; i < mono_array_length (tb->methods); ++i) {
10521                         MonoReflectionMethodBuilder *mb = mono_array_get (tb->methods, gpointer, i);
10522                         if (mb) {
10523                                 RESOLVE_TYPE (mb->rtype);
10524                                 check_array_for_usertypes (mb->return_modreq);
10525                                 check_array_for_usertypes (mb->return_modopt);
10526                                 check_array_for_usertypes (mb->parameters);
10527                                 if (mb->param_modreq)
10528                                         for (j = 0; j < mono_array_length (mb->param_modreq); ++j)
10529                                                 check_array_for_usertypes (mono_array_get (mb->param_modreq, MonoArray*, j));
10530                                 if (mb->param_modopt)
10531                                         for (j = 0; j < mono_array_length (mb->param_modopt); ++j)
10532                                                 check_array_for_usertypes (mono_array_get (mb->param_modopt, MonoArray*, j));
10533                         }
10534                 }
10535         }
10536         if (tb->ctors) {
10537                 for (i = 0; i < mono_array_length (tb->ctors); ++i) {
10538                         MonoReflectionCtorBuilder *mb = mono_array_get (tb->ctors, gpointer, i);
10539                         if (mb) {
10540                                 check_array_for_usertypes (mb->parameters);
10541                                 if (mb->param_modreq)
10542                                         for (j = 0; j < mono_array_length (mb->param_modreq); ++j)
10543                                                 check_array_for_usertypes (mono_array_get (mb->param_modreq, MonoArray*, j));
10544                                 if (mb->param_modopt)
10545                                         for (j = 0; j < mono_array_length (mb->param_modopt); ++j)
10546                                                 check_array_for_usertypes (mono_array_get (mb->param_modopt, MonoArray*, j));
10547                         }
10548                 }
10549         }
10550
10551         mono_save_custom_attrs (klass->image, klass, tb->cattrs);
10552
10553         /* 
10554          * we need to lock the domain because the lock will be taken inside
10555          * So, we need to keep the locking order correct.
10556          */
10557         mono_loader_lock ();
10558         mono_domain_lock (domain);
10559         if (klass->wastypebuilder) {
10560                 mono_domain_unlock (domain);
10561                 mono_loader_unlock ();
10562                 return mono_type_get_object (mono_object_domain (tb), &klass->byval_arg);
10563         }
10564         /*
10565          * Fields to set in klass:
10566          * the various flags: delegate/unicode/contextbound etc.
10567          */
10568         klass->flags = tb->attrs;
10569         klass->has_cctor = 1;
10570         klass->has_finalize = 1;
10571
10572 #if 0
10573         if (!((MonoDynamicImage*)klass->image)->run) {
10574                 if (klass->generic_container) {
10575                         /* FIXME: The code below can't handle generic classes */
10576                         klass->wastypebuilder = TRUE;
10577                         mono_loader_unlock ();
10578                         mono_domain_unlock (domain);
10579                         return mono_type_get_object (mono_object_domain (tb), &klass->byval_arg);
10580                 }
10581         }
10582 #endif
10583
10584         /* enums are done right away */
10585         if (!klass->enumtype)
10586                 ensure_runtime_vtable (klass);
10587
10588         if (tb->subtypes) {
10589                 for (i = 0; i < mono_array_length (tb->subtypes); ++i) {
10590                         MonoReflectionTypeBuilder *subtb = mono_array_get (tb->subtypes, MonoReflectionTypeBuilder*, i);
10591                         mono_class_alloc_ext (klass);
10592                         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)));
10593                 }
10594         }
10595
10596         klass->nested_classes_inited = TRUE;
10597
10598         /* fields and object layout */
10599         if (klass->parent) {
10600                 if (!klass->parent->size_inited)
10601                         mono_class_init (klass->parent);
10602                 klass->instance_size = klass->parent->instance_size;
10603                 klass->sizes.class_size = 0;
10604                 klass->min_align = klass->parent->min_align;
10605                 /* if the type has no fields we won't call the field_setup
10606                  * routine which sets up klass->has_references.
10607                  */
10608                 klass->has_references |= klass->parent->has_references;
10609         } else {
10610                 klass->instance_size = sizeof (MonoObject);
10611                 klass->min_align = 1;
10612         }
10613
10614         /* FIXME: handle packing_size and instance_size */
10615         typebuilder_setup_fields (klass);
10616
10617         typebuilder_setup_properties (klass);
10618
10619         typebuilder_setup_events (klass);
10620         
10621         klass->wastypebuilder = TRUE;
10622
10623         /* 
10624          * If we are a generic TypeBuilder, there might be instantiations in the type cache
10625          * which have type System.Reflection.MonoGenericClass, but after the type is created, 
10626          * we want to return normal System.MonoType objects, so clear these out from the cache.
10627          */
10628         if (domain->type_hash && klass->generic_container)
10629                 mono_g_hash_table_foreach_remove (domain->type_hash, remove_instantiations_of, klass);
10630
10631         mono_domain_unlock (domain);
10632         mono_loader_unlock ();
10633
10634         if (klass->enumtype && !mono_class_is_valid_enum (klass)) {
10635                 mono_class_set_failure (klass, MONO_EXCEPTION_TYPE_LOAD, NULL);
10636                 mono_raise_exception (mono_get_exception_type_load (tb->name, NULL));
10637         }
10638
10639         res = mono_type_get_object (mono_object_domain (tb), &klass->byval_arg);
10640         g_assert (res != (MonoReflectionType*)tb);
10641
10642         return res;
10643 }
10644
10645 void
10646 mono_reflection_initialize_generic_parameter (MonoReflectionGenericParam *gparam)
10647 {
10648         MonoGenericParamFull *param;
10649         MonoImage *image;
10650         MonoClass *pklass;
10651
10652         MONO_ARCH_SAVE_REGS;
10653
10654         param = g_new0 (MonoGenericParamFull, 1);
10655
10656         if (gparam->mbuilder) {
10657                 if (!gparam->mbuilder->generic_container) {
10658                         MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder *)gparam->mbuilder->type;
10659                         MonoClass *klass = mono_class_from_mono_type (mono_reflection_type_get_handle ((MonoReflectionType*)tb));
10660                         gparam->mbuilder->generic_container = mono_image_alloc0 (klass->image, sizeof (MonoGenericContainer));
10661                         gparam->mbuilder->generic_container->is_method = TRUE;
10662                         /* 
10663                          * Cannot set owner.method, since the MonoMethod is not created yet.
10664                          * Set the image field instead, so type_in_image () works.
10665                          */
10666                         gparam->mbuilder->generic_container->image = klass->image;
10667                 }
10668                 param->param.owner = gparam->mbuilder->generic_container;
10669         } else if (gparam->tbuilder) {
10670                 if (!gparam->tbuilder->generic_container) {
10671                         MonoClass *klass = mono_class_from_mono_type (mono_reflection_type_get_handle ((MonoReflectionType*)gparam->tbuilder));
10672                         gparam->tbuilder->generic_container = mono_image_alloc0 (klass->image, sizeof (MonoGenericContainer));
10673                         gparam->tbuilder->generic_container->owner.klass = klass;
10674                 }
10675                 param->param.owner = gparam->tbuilder->generic_container;
10676         }
10677
10678         param->info.name = mono_string_to_utf8 (gparam->name);
10679         param->param.num = gparam->index;
10680
10681         image = &gparam->tbuilder->module->dynamic_image->image;
10682         pklass = mono_class_from_generic_parameter ((MonoGenericParam *) param, image, gparam->mbuilder != NULL);
10683
10684         gparam->type.type = &pklass->byval_arg;
10685
10686         MOVING_GC_REGISTER (&pklass->reflection_info);
10687         pklass->reflection_info = gparam; /* FIXME: GC pin gparam */
10688         mono_image_lock (image);
10689         image->reflection_info_unregister_classes = g_slist_prepend (image->reflection_info_unregister_classes, pklass);
10690         mono_image_unlock (image);
10691 }
10692
10693 MonoArray *
10694 mono_reflection_sighelper_get_signature_local (MonoReflectionSigHelper *sig)
10695 {
10696         MonoReflectionModuleBuilder *module = sig->module;
10697         MonoDynamicImage *assembly = module != NULL ? module->dynamic_image : NULL;
10698         guint32 na = sig->arguments ? mono_array_length (sig->arguments) : 0;
10699         guint32 buflen, i;
10700         MonoArray *result;
10701         SigBuffer buf;
10702
10703         check_array_for_usertypes (sig->arguments);
10704
10705         sigbuffer_init (&buf, 32);
10706
10707         sigbuffer_add_value (&buf, 0x07);
10708         sigbuffer_add_value (&buf, na);
10709         if (assembly != NULL){
10710                 for (i = 0; i < na; ++i) {
10711                         MonoReflectionType *type = mono_array_get (sig->arguments, MonoReflectionType*, i);
10712                         encode_reflection_type (assembly, type, &buf);
10713                 }
10714         }
10715
10716         buflen = buf.p - buf.buf;
10717         result = mono_array_new (mono_domain_get (), mono_defaults.byte_class, buflen);
10718         memcpy (mono_array_addr (result, char, 0), buf.buf, buflen);
10719         sigbuffer_free (&buf);
10720
10721         return result;
10722 }
10723
10724 MonoArray *
10725 mono_reflection_sighelper_get_signature_field (MonoReflectionSigHelper *sig)
10726 {
10727         MonoDynamicImage *assembly = sig->module->dynamic_image;
10728         guint32 na = sig->arguments ? mono_array_length (sig->arguments) : 0;
10729         guint32 buflen, i;
10730         MonoArray *result;
10731         SigBuffer buf;
10732
10733         check_array_for_usertypes (sig->arguments);
10734
10735         sigbuffer_init (&buf, 32);
10736
10737         sigbuffer_add_value (&buf, 0x06);
10738         for (i = 0; i < na; ++i) {
10739                 MonoReflectionType *type = mono_array_get (sig->arguments, MonoReflectionType*, i);
10740                 encode_reflection_type (assembly, type, &buf);
10741         }
10742
10743         buflen = buf.p - buf.buf;
10744         result = mono_array_new (mono_domain_get (), mono_defaults.byte_class, buflen);
10745         memcpy (mono_array_addr (result, char, 0), buf.buf, buflen);
10746         sigbuffer_free (&buf);
10747
10748         return result;
10749 }
10750
10751 void 
10752 mono_reflection_create_dynamic_method (MonoReflectionDynamicMethod *mb)
10753 {
10754         ReflectionMethodBuilder rmb;
10755         MonoMethodSignature *sig;
10756         MonoClass *klass;
10757         GSList *l;
10758         int i;
10759
10760         sig = dynamic_method_to_signature (mb);
10761
10762         reflection_methodbuilder_from_dynamic_method (&rmb, mb);
10763
10764         /*
10765          * Resolve references.
10766          */
10767         /* 
10768          * Every second entry in the refs array is reserved for storing handle_class,
10769          * which is needed by the ldtoken implementation in the JIT.
10770          */
10771         rmb.nrefs = mb->nrefs;
10772         rmb.refs = g_new0 (gpointer, mb->nrefs + 1);
10773         for (i = 0; i < mb->nrefs; i += 2) {
10774                 MonoClass *handle_class;
10775                 gpointer ref;
10776                 MonoObject *obj = mono_array_get (mb->refs, MonoObject*, i);
10777
10778                 if (strcmp (obj->vtable->klass->name, "DynamicMethod") == 0) {
10779                         MonoReflectionDynamicMethod *method = (MonoReflectionDynamicMethod*)obj;
10780                         /*
10781                          * The referenced DynamicMethod should already be created by the managed
10782                          * code, except in the case of circular references. In that case, we store
10783                          * method in the refs array, and fix it up later when the referenced 
10784                          * DynamicMethod is created.
10785                          */
10786                         if (method->mhandle) {
10787                                 ref = method->mhandle;
10788                         } else {
10789                                 /* FIXME: GC object stored in unmanaged memory */
10790                                 ref = method;
10791
10792                                 /* FIXME: GC object stored in unmanaged memory */
10793                                 method->referenced_by = g_slist_append (method->referenced_by, mb);
10794                         }
10795                         handle_class = mono_defaults.methodhandle_class;
10796                 } else {
10797                         MonoException *ex = NULL;
10798                         ref = resolve_object (mb->module->image, obj, &handle_class, NULL);
10799                         if (!ref)
10800                                 ex = mono_get_exception_type_load (NULL, NULL);
10801                         else if (mono_security_get_mode () == MONO_SECURITY_MODE_CORE_CLR)
10802                                 ex = mono_security_core_clr_ensure_dynamic_method_resolved_object (ref, handle_class);
10803
10804                         if (ex) {
10805                                 g_free (rmb.refs);
10806                                 mono_raise_exception (ex);
10807                                 return;
10808                         }
10809                 }
10810
10811                 rmb.refs [i] = ref; /* FIXME: GC object stored in unmanaged memory (change also resolve_object() signature) */
10812                 rmb.refs [i + 1] = handle_class;
10813         }               
10814
10815         klass = mb->owner ? mono_class_from_mono_type (mono_reflection_type_get_handle ((MonoReflectionType*)mb->owner)) : mono_defaults.object_class;
10816
10817         mb->mhandle = reflection_methodbuilder_to_mono_method (klass, &rmb, sig);
10818
10819         /* Fix up refs entries pointing at us */
10820         for (l = mb->referenced_by; l; l = l->next) {
10821                 MonoReflectionDynamicMethod *method = (MonoReflectionDynamicMethod*)l->data;
10822                 MonoMethodWrapper *wrapper = (MonoMethodWrapper*)method->mhandle;
10823                 gpointer *data;
10824                 
10825                 g_assert (method->mhandle);
10826
10827                 data = (gpointer*)wrapper->method_data;
10828                 for (i = 0; i < GPOINTER_TO_UINT (data [0]); i += 2) {
10829                         if ((data [i + 1] == mb) && (data [i + 1 + 1] == mono_defaults.methodhandle_class))
10830                                 data [i + 1] = mb->mhandle;
10831                 }
10832         }
10833         g_slist_free (mb->referenced_by);
10834
10835         g_free (rmb.refs);
10836
10837         /* ilgen is no longer needed */
10838         mb->ilgen = NULL;
10839 }
10840
10841 #endif /* DISABLE_REFLECTION_EMIT */
10842
10843 void
10844 mono_reflection_destroy_dynamic_method (MonoReflectionDynamicMethod *mb)
10845 {
10846         g_assert (mb);
10847
10848         if (mb->mhandle)
10849                 mono_runtime_free_method (
10850                         mono_object_get_domain ((MonoObject*)mb), mb->mhandle);
10851 }
10852
10853 /**
10854  * 
10855  * mono_reflection_is_valid_dynamic_token:
10856  * 
10857  * Returns TRUE if token is valid.
10858  * 
10859  */
10860 gboolean
10861 mono_reflection_is_valid_dynamic_token (MonoDynamicImage *image, guint32 token)
10862 {
10863         return mono_g_hash_table_lookup (image->tokens, GUINT_TO_POINTER (token)) != NULL;
10864 }
10865
10866 #ifndef DISABLE_REFLECTION_EMIT
10867
10868 /**
10869  * mono_reflection_lookup_dynamic_token:
10870  *
10871  * Finish the Builder object pointed to by TOKEN and return the corresponding
10872  * runtime structure. If HANDLE_CLASS is not NULL, it is set to the class required by 
10873  * mono_ldtoken. If valid_token is TRUE, assert if it is not found in the token->object
10874  * mapping table.
10875  *
10876  * LOCKING: Take the loader lock
10877  */
10878 gpointer
10879 mono_reflection_lookup_dynamic_token (MonoImage *image, guint32 token, gboolean valid_token, MonoClass **handle_class, MonoGenericContext *context)
10880 {
10881         MonoDynamicImage *assembly = (MonoDynamicImage*)image;
10882         MonoObject *obj;
10883         MonoClass *klass;
10884
10885         mono_loader_lock ();
10886         obj = mono_g_hash_table_lookup (assembly->tokens, GUINT_TO_POINTER (token));
10887         mono_loader_unlock ();
10888         if (!obj) {
10889                 if (valid_token)
10890                         g_error ("Could not find required dynamic token 0x%08x", token);
10891                 else
10892                         return NULL;
10893         }
10894
10895         if (!handle_class)
10896                 handle_class = &klass;
10897         return resolve_object (image, obj, handle_class, context);
10898 }
10899
10900 /*
10901  * ensure_complete_type:
10902  *
10903  *   Ensure that KLASS is completed if it is a dynamic type, or references
10904  * dynamic types.
10905  */
10906 static void
10907 ensure_complete_type (MonoClass *klass)
10908 {
10909         if (klass->image->dynamic && !klass->wastypebuilder) {
10910                 MonoReflectionTypeBuilder *tb = klass->reflection_info;
10911
10912                 mono_domain_try_type_resolve (mono_domain_get (), NULL, (MonoObject*)tb);
10913
10914                 // Asserting here could break a lot of code
10915                 //g_assert (klass->wastypebuilder);
10916         }
10917
10918         if (klass->generic_class) {
10919                 MonoGenericInst *inst = klass->generic_class->context.class_inst;
10920                 int i;
10921
10922                 for (i = 0; i < inst->type_argc; ++i) {
10923                         ensure_complete_type (mono_class_from_mono_type (inst->type_argv [i]));
10924                 }
10925         }
10926 }
10927
10928 static gpointer
10929 resolve_object (MonoImage *image, MonoObject *obj, MonoClass **handle_class, MonoGenericContext *context)
10930 {
10931         gpointer result = NULL;
10932
10933         if (strcmp (obj->vtable->klass->name, "String") == 0) {
10934                 result = mono_string_intern ((MonoString*)obj);
10935                 *handle_class = NULL;
10936                 g_assert (result);
10937         } else if (strcmp (obj->vtable->klass->name, "MonoType") == 0) {
10938                 MonoType *type = mono_reflection_type_get_handle ((MonoReflectionType*)obj);
10939                 if (context) {
10940                         MonoType *inflated = mono_class_inflate_generic_type (type, context);
10941                         result = mono_class_from_mono_type (inflated);
10942                         mono_metadata_free_type (inflated);
10943                 } else {
10944                         result = mono_class_from_mono_type (type);
10945                 }
10946                 *handle_class = mono_defaults.typehandle_class;
10947                 g_assert (result);
10948         } else if (strcmp (obj->vtable->klass->name, "MonoMethod") == 0 ||
10949                    strcmp (obj->vtable->klass->name, "MonoCMethod") == 0 ||
10950                    strcmp (obj->vtable->klass->name, "MonoGenericCMethod") == 0 ||
10951                    strcmp (obj->vtable->klass->name, "MonoGenericMethod") == 0) {
10952                 result = ((MonoReflectionMethod*)obj)->method;
10953                 if (context)
10954                         result = mono_class_inflate_generic_method (result, context);
10955                 *handle_class = mono_defaults.methodhandle_class;
10956                 g_assert (result);
10957         } else if (strcmp (obj->vtable->klass->name, "MethodBuilder") == 0) {
10958                 MonoReflectionMethodBuilder *mb = (MonoReflectionMethodBuilder*)obj;
10959                 result = mb->mhandle;
10960                 if (!result) {
10961                         /* Type is not yet created */
10962                         MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder*)mb->type;
10963
10964                         mono_domain_try_type_resolve (mono_domain_get (), NULL, (MonoObject*)tb);
10965
10966                         /*
10967                          * Hopefully this has been filled in by calling CreateType() on the
10968                          * TypeBuilder.
10969                          */
10970                         /*
10971                          * TODO: This won't work if the application finishes another 
10972                          * TypeBuilder instance instead of this one.
10973                          */
10974                         result = mb->mhandle;
10975                 }
10976                 if (context)
10977                         result = mono_class_inflate_generic_method (result, context);
10978                 *handle_class = mono_defaults.methodhandle_class;
10979         } else if (strcmp (obj->vtable->klass->name, "ConstructorBuilder") == 0) {
10980                 MonoReflectionCtorBuilder *cb = (MonoReflectionCtorBuilder*)obj;
10981
10982                 result = cb->mhandle;
10983                 if (!result) {
10984                         MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder*)cb->type;
10985
10986                         mono_domain_try_type_resolve (mono_domain_get (), NULL, (MonoObject*)tb);
10987                         result = cb->mhandle;
10988                 }
10989                 if (context)
10990                         result = mono_class_inflate_generic_method (result, context);
10991                 *handle_class = mono_defaults.methodhandle_class;
10992         } else if (strcmp (obj->vtable->klass->name, "MonoField") == 0) {
10993                 MonoClassField *field = ((MonoReflectionField*)obj)->field;
10994
10995                 ensure_complete_type (field->parent);
10996                 if (context) {
10997                         MonoType *inflated = mono_class_inflate_generic_type (&field->parent->byval_arg, context);
10998                         MonoClass *class = mono_class_from_mono_type (inflated);
10999                         MonoClassField *inflated_field;
11000                         gpointer iter = NULL;
11001                         mono_metadata_free_type (inflated);
11002                         while ((inflated_field = mono_class_get_fields (class, &iter))) {
11003                                 if (!strcmp (field->name, inflated_field->name))
11004                                         break;
11005                         }
11006                         g_assert (inflated_field && !strcmp (field->name, inflated_field->name));
11007                         result = inflated_field;
11008                 } else {
11009                         result = field;
11010                 }
11011                 *handle_class = mono_defaults.fieldhandle_class;
11012                 g_assert (result);
11013         } else if (strcmp (obj->vtable->klass->name, "FieldBuilder") == 0) {
11014                 MonoReflectionFieldBuilder *fb = (MonoReflectionFieldBuilder*)obj;
11015                 result = fb->handle;
11016
11017                 if (!result) {
11018                         MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder*)fb->typeb;
11019
11020                         mono_domain_try_type_resolve (mono_domain_get (), NULL, (MonoObject*)tb);
11021                         result = fb->handle;
11022                 }
11023
11024                 if (fb->handle && fb->handle->parent->generic_container) {
11025                         MonoClass *klass = fb->handle->parent;
11026                         MonoType *type = mono_class_inflate_generic_type (&klass->byval_arg, context);
11027                         MonoClass *inflated = mono_class_from_mono_type (type);
11028
11029                         result = mono_class_get_field_from_name (inflated, mono_field_get_name (fb->handle));
11030                         g_assert (result);
11031                         mono_metadata_free_type (type);
11032                 }
11033                 *handle_class = mono_defaults.fieldhandle_class;
11034         } else if (strcmp (obj->vtable->klass->name, "TypeBuilder") == 0) {
11035                 MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder*)obj;
11036                 MonoType *type = mono_reflection_type_get_handle ((MonoReflectionType*)tb); 
11037                 MonoClass *klass;
11038
11039                 klass = type->data.klass;
11040                 if (klass->wastypebuilder) {
11041                         /* Already created */
11042                         result = klass;
11043                 }
11044                 else {
11045                         mono_domain_try_type_resolve (mono_domain_get (), NULL, (MonoObject*)tb);
11046                         result = type->data.klass;
11047                         g_assert (result);
11048                 }
11049                 *handle_class = mono_defaults.typehandle_class;
11050         } else if (strcmp (obj->vtable->klass->name, "SignatureHelper") == 0) {
11051                 MonoReflectionSigHelper *helper = (MonoReflectionSigHelper*)obj;
11052                 MonoMethodSignature *sig;
11053                 int nargs, i;
11054
11055                 if (helper->arguments)
11056                         nargs = mono_array_length (helper->arguments);
11057                 else
11058                         nargs = 0;
11059
11060                 sig = mono_metadata_signature_alloc (image, nargs);
11061                 sig->explicit_this = helper->call_conv & 64 ? 1 : 0;
11062                 sig->hasthis = helper->call_conv & 32 ? 1 : 0;
11063
11064                 if (helper->call_conv == 0) /* unmanaged */
11065                         sig->call_convention = helper->unmanaged_call_conv - 1;
11066                 else
11067                         if (helper->call_conv & 0x02)
11068                                 sig->call_convention = MONO_CALL_VARARG;
11069                 else
11070                         sig->call_convention = MONO_CALL_DEFAULT;
11071
11072                 sig->param_count = nargs;
11073                 /* TODO: Copy type ? */
11074                 sig->ret = helper->return_type->type;
11075                 for (i = 0; i < nargs; ++i)
11076                         sig->params [i] = mono_type_array_get_and_resolve (helper->arguments, i);
11077
11078                 result = sig;
11079                 *handle_class = NULL;
11080         } else if (strcmp (obj->vtable->klass->name, "DynamicMethod") == 0) {
11081                 MonoReflectionDynamicMethod *method = (MonoReflectionDynamicMethod*)obj;
11082                 /* Already created by the managed code */
11083                 g_assert (method->mhandle);
11084                 result = method->mhandle;
11085                 *handle_class = mono_defaults.methodhandle_class;
11086         } else if (strcmp (obj->vtable->klass->name, "GenericTypeParameterBuilder") == 0) {
11087                 MonoType *type = mono_reflection_type_get_handle ((MonoReflectionType*)obj);
11088                 type = mono_class_inflate_generic_type (type, context);
11089                 result = mono_class_from_mono_type (type);
11090                 *handle_class = mono_defaults.typehandle_class;
11091                 g_assert (result);
11092                 mono_metadata_free_type (type);
11093         } else if (strcmp (obj->vtable->klass->name, "MonoGenericClass") == 0) {
11094                 MonoType *type = mono_reflection_type_get_handle ((MonoReflectionType*)obj);
11095                 type = mono_class_inflate_generic_type (type, context);
11096                 result = mono_class_from_mono_type (type);
11097                 *handle_class = mono_defaults.typehandle_class;
11098                 g_assert (result);
11099                 mono_metadata_free_type (type);
11100         } else if (strcmp (obj->vtable->klass->name, "FieldOnTypeBuilderInst") == 0) {
11101                 MonoReflectionFieldOnTypeBuilderInst *f = (MonoReflectionFieldOnTypeBuilderInst*)obj;
11102                 MonoClass *inflated;
11103                 MonoType *type;
11104
11105                 type = mono_class_inflate_generic_type (mono_reflection_type_get_handle ((MonoReflectionType*)f->inst), context);
11106                 inflated = mono_class_from_mono_type (type);
11107
11108                 g_assert (f->fb->handle);
11109                 result = mono_class_get_field_from_name (inflated, mono_field_get_name (f->fb->handle));
11110                 g_assert (result);
11111                 mono_metadata_free_type (type);
11112                 *handle_class = mono_defaults.fieldhandle_class;
11113         } else if (strcmp (obj->vtable->klass->name, "ConstructorOnTypeBuilderInst") == 0) {
11114                 MonoReflectionCtorOnTypeBuilderInst *c = (MonoReflectionCtorOnTypeBuilderInst*)obj;
11115                 MonoType *type = mono_class_inflate_generic_type (mono_reflection_type_get_handle ((MonoReflectionType*)c->inst), context);
11116                 MonoClass *inflated_klass = mono_class_from_mono_type (type);
11117                 g_assert (c->cb->mhandle);
11118                 result = inflate_mono_method (inflated_klass, c->cb->mhandle, (MonoObject*)c->cb);
11119                 *handle_class = mono_defaults.methodhandle_class;
11120                 mono_metadata_free_type (type);
11121         } else if (strcmp (obj->vtable->klass->name, "MethodOnTypeBuilderInst") == 0) {
11122                 MonoReflectionMethodOnTypeBuilderInst *m = (MonoReflectionMethodOnTypeBuilderInst*)obj;
11123                 if (m->method_args) {
11124                         result = mono_reflection_method_on_tb_inst_get_handle (m);
11125                 } else {
11126                         MonoType *type = mono_class_inflate_generic_type (mono_reflection_type_get_handle ((MonoReflectionType*)m->inst), context);
11127                         MonoClass *inflated_klass = mono_class_from_mono_type (type);
11128                         g_assert (m->mb->mhandle);
11129                         result = inflate_mono_method (inflated_klass, m->mb->mhandle, (MonoObject*)m->mb);
11130                         mono_metadata_free_type (type);
11131                 }
11132                 *handle_class = mono_defaults.methodhandle_class;
11133         } else if (is_sre_array (mono_object_get_class(obj)) ||
11134                                 is_sre_byref (mono_object_get_class(obj)) ||
11135                                 is_sre_pointer (mono_object_get_class(obj))) {
11136                 MonoReflectionType *ref_type = (MonoReflectionType *)obj;
11137                 MonoType *type = mono_reflection_type_get_handle (ref_type);
11138                 result = mono_class_from_mono_type (type);
11139                 *handle_class = mono_defaults.typehandle_class;
11140         } else {
11141                 g_print ("%s\n", obj->vtable->klass->name);
11142                 g_assert_not_reached ();
11143         }
11144         return result;
11145 }
11146
11147 #else /* DISABLE_REFLECTION_EMIT */
11148
11149 MonoArray*
11150 mono_reflection_get_custom_attrs_blob (MonoReflectionAssembly *assembly, MonoObject *ctor, MonoArray *ctorArgs, MonoArray *properties, MonoArray *propValues, MonoArray *fields, MonoArray* fieldValues) 
11151 {
11152         g_assert_not_reached ();
11153         return NULL;
11154 }
11155
11156 void
11157 mono_reflection_setup_internal_class (MonoReflectionTypeBuilder *tb)
11158 {
11159         g_assert_not_reached ();
11160 }
11161
11162 void
11163 mono_reflection_setup_generic_class (MonoReflectionTypeBuilder *tb)
11164 {
11165         g_assert_not_reached ();
11166 }
11167
11168 void
11169 mono_reflection_create_generic_class (MonoReflectionTypeBuilder *tb)
11170 {
11171         g_assert_not_reached ();
11172 }
11173
11174 void
11175 mono_reflection_create_internal_class (MonoReflectionTypeBuilder *tb)
11176 {
11177         g_assert_not_reached ();
11178 }
11179
11180 void
11181 mono_image_basic_init (MonoReflectionAssemblyBuilder *assemblyb)
11182 {
11183         g_error ("This mono runtime was configured with --enable-minimal=reflection_emit, so System.Reflection.Emit is not supported.");
11184 }
11185
11186 void
11187 mono_image_module_basic_init (MonoReflectionModuleBuilder *moduleb)
11188 {
11189         g_assert_not_reached ();
11190 }
11191
11192 void
11193 mono_image_set_wrappers_type (MonoReflectionModuleBuilder *moduleb, MonoReflectionType *type)
11194 {
11195         g_assert_not_reached ();
11196 }
11197
11198 MonoReflectionModule *
11199 mono_image_load_module_dynamic (MonoReflectionAssemblyBuilder *ab, MonoString *fileName)
11200 {
11201         g_assert_not_reached ();
11202         return NULL;
11203 }
11204
11205 guint32
11206 mono_image_insert_string (MonoReflectionModuleBuilder *module, MonoString *str)
11207 {
11208         g_assert_not_reached ();
11209         return 0;
11210 }
11211
11212 guint32
11213 mono_image_create_method_token (MonoDynamicImage *assembly, MonoObject *obj, MonoArray *opt_param_types)
11214 {
11215         g_assert_not_reached ();
11216         return 0;
11217 }
11218
11219 guint32
11220 mono_image_create_token (MonoDynamicImage *assembly, MonoObject *obj, 
11221                                                  gboolean create_methodspec, gboolean register_token)
11222 {
11223         g_assert_not_reached ();
11224         return 0;
11225 }
11226
11227 void
11228 mono_image_register_token (MonoDynamicImage *assembly, guint32 token, MonoObject *obj)
11229 {
11230 }
11231
11232 void
11233 mono_reflection_generic_class_initialize (MonoReflectionGenericClass *type, MonoArray *methods, 
11234                                           MonoArray *ctors, MonoArray *fields, MonoArray *properties,
11235                                           MonoArray *events)
11236 {
11237         g_assert_not_reached ();
11238 }
11239
11240 void
11241 mono_reflection_get_dynamic_overrides (MonoClass *klass, MonoMethod ***overrides, int *num_overrides)
11242 {
11243         *overrides = NULL;
11244         *num_overrides = 0;
11245 }
11246
11247 MonoReflectionEvent *
11248 mono_reflection_event_builder_get_event_info (MonoReflectionTypeBuilder *tb, MonoReflectionEventBuilder *eb)
11249 {
11250         g_assert_not_reached ();
11251         return NULL;
11252 }
11253
11254 MonoReflectionType*
11255 mono_reflection_create_runtime_class (MonoReflectionTypeBuilder *tb)
11256 {
11257         g_assert_not_reached ();
11258         return NULL;
11259 }
11260
11261 void
11262 mono_reflection_initialize_generic_parameter (MonoReflectionGenericParam *gparam)
11263 {
11264         g_assert_not_reached ();
11265 }
11266
11267 MonoArray *
11268 mono_reflection_sighelper_get_signature_local (MonoReflectionSigHelper *sig)
11269 {
11270         g_assert_not_reached ();
11271         return NULL;
11272 }
11273
11274 MonoArray *
11275 mono_reflection_sighelper_get_signature_field (MonoReflectionSigHelper *sig)
11276 {
11277         g_assert_not_reached ();
11278         return NULL;
11279 }
11280
11281 void 
11282 mono_reflection_create_dynamic_method (MonoReflectionDynamicMethod *mb)
11283 {
11284 }
11285
11286 gpointer
11287 mono_reflection_lookup_dynamic_token (MonoImage *image, guint32 token, gboolean valid_token, MonoClass **handle_class, MonoGenericContext *context)
11288 {
11289         return NULL;
11290 }
11291
11292 MonoType*
11293 mono_reflection_type_get_handle (MonoReflectionType* ref)
11294 {
11295         if (!ref)
11296                 return NULL;
11297         return ref->type;
11298 }
11299
11300 #endif /* DISABLE_REFLECTION_EMIT */
11301
11302 /* SECURITY_ACTION_* are defined in mono/metadata/tabledefs.h */
11303 const static guint32 declsec_flags_map[] = {
11304         0x00000000,                                     /* empty */
11305         MONO_DECLSEC_FLAG_REQUEST,                      /* SECURITY_ACTION_REQUEST                      (x01) */
11306         MONO_DECLSEC_FLAG_DEMAND,                       /* SECURITY_ACTION_DEMAND                       (x02) */
11307         MONO_DECLSEC_FLAG_ASSERT,                       /* SECURITY_ACTION_ASSERT                       (x03) */
11308         MONO_DECLSEC_FLAG_DENY,                         /* SECURITY_ACTION_DENY                         (x04) */
11309         MONO_DECLSEC_FLAG_PERMITONLY,                   /* SECURITY_ACTION_PERMITONLY                   (x05) */
11310         MONO_DECLSEC_FLAG_LINKDEMAND,                   /* SECURITY_ACTION_LINKDEMAND                   (x06) */
11311         MONO_DECLSEC_FLAG_INHERITANCEDEMAND,            /* SECURITY_ACTION_INHERITANCEDEMAND            (x07) */
11312         MONO_DECLSEC_FLAG_REQUEST_MINIMUM,              /* SECURITY_ACTION_REQUEST_MINIMUM              (x08) */
11313         MONO_DECLSEC_FLAG_REQUEST_OPTIONAL,             /* SECURITY_ACTION_REQUEST_OPTIONAL             (x09) */
11314         MONO_DECLSEC_FLAG_REQUEST_REFUSE,               /* SECURITY_ACTION_REQUEST_REFUSE               (x0A) */
11315         MONO_DECLSEC_FLAG_PREJIT_GRANT,                 /* SECURITY_ACTION_PREJIT_GRANT                 (x0B) */
11316         MONO_DECLSEC_FLAG_PREJIT_DENY,                  /* SECURITY_ACTION_PREJIT_DENY                  (x0C) */
11317         MONO_DECLSEC_FLAG_NONCAS_DEMAND,                /* SECURITY_ACTION_NONCAS_DEMAND                (x0D) */
11318         MONO_DECLSEC_FLAG_NONCAS_LINKDEMAND,            /* SECURITY_ACTION_NONCAS_LINKDEMAND            (x0E) */
11319         MONO_DECLSEC_FLAG_NONCAS_INHERITANCEDEMAND,     /* SECURITY_ACTION_NONCAS_INHERITANCEDEMAND     (x0F) */
11320         MONO_DECLSEC_FLAG_LINKDEMAND_CHOICE,            /* SECURITY_ACTION_LINKDEMAND_CHOICE            (x10) */
11321         MONO_DECLSEC_FLAG_INHERITANCEDEMAND_CHOICE,     /* SECURITY_ACTION_INHERITANCEDEMAND_CHOICE     (x11) */
11322         MONO_DECLSEC_FLAG_DEMAND_CHOICE,                /* SECURITY_ACTION_DEMAND_CHOICE                (x12) */
11323 };
11324
11325 /*
11326  * Returns flags that includes all available security action associated to the handle.
11327  * @token: metadata token (either for a class or a method)
11328  * @image: image where resides the metadata.
11329  */
11330 static guint32
11331 mono_declsec_get_flags (MonoImage *image, guint32 token)
11332 {
11333         int index = mono_metadata_declsec_from_index (image, token);
11334         MonoTableInfo *t = &image->tables [MONO_TABLE_DECLSECURITY];
11335         guint32 result = 0;
11336         guint32 action;
11337         int i;
11338
11339         /* HasSecurity can be present for other, not specially encoded, attributes,
11340            e.g. SuppressUnmanagedCodeSecurityAttribute */
11341         if (index < 0)
11342                 return 0;
11343
11344         for (i = index; i < t->rows; i++) {
11345                 guint32 cols [MONO_DECL_SECURITY_SIZE];
11346
11347                 mono_metadata_decode_row (t, i, cols, MONO_DECL_SECURITY_SIZE);
11348                 if (cols [MONO_DECL_SECURITY_PARENT] != token)
11349                         break;
11350
11351                 action = cols [MONO_DECL_SECURITY_ACTION];
11352                 if ((action >= MONO_DECLSEC_ACTION_MIN) && (action <= MONO_DECLSEC_ACTION_MAX)) {
11353                         result |= declsec_flags_map [action];
11354                 } else {
11355                         g_assert_not_reached ();
11356                 }
11357         }
11358         return result;
11359 }
11360
11361 /*
11362  * Get the security actions (in the form of flags) associated with the specified method.
11363  *
11364  * @method: The method for which we want the declarative security flags.
11365  * Return the declarative security flags for the method (only).
11366  *
11367  * Note: To keep MonoMethod size down we do not cache the declarative security flags
11368  *       (except for the stack modifiers which are kept in the MonoJitInfo structure)
11369  */
11370 guint32
11371 mono_declsec_flags_from_method (MonoMethod *method)
11372 {
11373         if (method->flags & METHOD_ATTRIBUTE_HAS_SECURITY) {
11374                 /* FIXME: No cache (for the moment) */
11375                 guint32 idx = mono_method_get_index (method);
11376                 idx <<= MONO_HAS_DECL_SECURITY_BITS;
11377                 idx |= MONO_HAS_DECL_SECURITY_METHODDEF;
11378                 return mono_declsec_get_flags (method->klass->image, idx);
11379         }
11380         return 0;
11381 }
11382
11383 /*
11384  * Get the security actions (in the form of flags) associated with the specified class.
11385  *
11386  * @klass: The class for which we want the declarative security flags.
11387  * Return the declarative security flags for the class.
11388  *
11389  * Note: We cache the flags inside the MonoClass structure as this will get 
11390  *       called very often (at least for each method).
11391  */
11392 guint32
11393 mono_declsec_flags_from_class (MonoClass *klass)
11394 {
11395         if (klass->flags & TYPE_ATTRIBUTE_HAS_SECURITY) {
11396                 if (!klass->ext || !klass->ext->declsec_flags) {
11397                         guint32 idx;
11398
11399                         idx = mono_metadata_token_index (klass->type_token);
11400                         idx <<= MONO_HAS_DECL_SECURITY_BITS;
11401                         idx |= MONO_HAS_DECL_SECURITY_TYPEDEF;
11402                         mono_loader_lock ();
11403                         mono_class_alloc_ext (klass);
11404                         mono_loader_unlock ();
11405                         /* we cache the flags on classes */
11406                         klass->ext->declsec_flags = mono_declsec_get_flags (klass->image, idx);
11407                 }
11408                 return klass->ext->declsec_flags;
11409         }
11410         return 0;
11411 }
11412
11413 /*
11414  * Get the security actions (in the form of flags) associated with the specified assembly.
11415  *
11416  * @assembly: The assembly for which we want the declarative security flags.
11417  * Return the declarative security flags for the assembly.
11418  */
11419 guint32
11420 mono_declsec_flags_from_assembly (MonoAssembly *assembly)
11421 {
11422         guint32 idx = 1; /* there is only one assembly */
11423         idx <<= MONO_HAS_DECL_SECURITY_BITS;
11424         idx |= MONO_HAS_DECL_SECURITY_ASSEMBLY;
11425         return mono_declsec_get_flags (assembly->image, idx);
11426 }
11427
11428
11429 /*
11430  * Fill actions for the specific index (which may either be an encoded class token or
11431  * an encoded method token) from the metadata image.
11432  * Returns TRUE if some actions requiring code generation are present, FALSE otherwise.
11433  */
11434 static MonoBoolean
11435 fill_actions_from_index (MonoImage *image, guint32 token, MonoDeclSecurityActions* actions,
11436         guint32 id_std, guint32 id_noncas, guint32 id_choice)
11437 {
11438         MonoBoolean result = FALSE;
11439         MonoTableInfo *t;
11440         guint32 cols [MONO_DECL_SECURITY_SIZE];
11441         int index = mono_metadata_declsec_from_index (image, token);
11442         int i;
11443
11444         t  = &image->tables [MONO_TABLE_DECLSECURITY];
11445         for (i = index; i < t->rows; i++) {
11446                 mono_metadata_decode_row (t, i, cols, MONO_DECL_SECURITY_SIZE);
11447
11448                 if (cols [MONO_DECL_SECURITY_PARENT] != token)
11449                         return result;
11450
11451                 /* if present only replace (class) permissions with method permissions */
11452                 /* if empty accept either class or method permissions */
11453                 if (cols [MONO_DECL_SECURITY_ACTION] == id_std) {
11454                         if (!actions->demand.blob) {
11455                                 const char *blob = mono_metadata_blob_heap (image, cols [MONO_DECL_SECURITY_PERMISSIONSET]);
11456                                 actions->demand.index = cols [MONO_DECL_SECURITY_PERMISSIONSET];
11457                                 actions->demand.blob = (char*) (blob + 2);
11458                                 actions->demand.size = mono_metadata_decode_blob_size (blob, &blob);
11459                                 result = TRUE;
11460                         }
11461                 } else if (cols [MONO_DECL_SECURITY_ACTION] == id_noncas) {
11462                         if (!actions->noncasdemand.blob) {
11463                                 const char *blob = mono_metadata_blob_heap (image, cols [MONO_DECL_SECURITY_PERMISSIONSET]);
11464                                 actions->noncasdemand.index = cols [MONO_DECL_SECURITY_PERMISSIONSET];
11465                                 actions->noncasdemand.blob = (char*) (blob + 2);
11466                                 actions->noncasdemand.size = mono_metadata_decode_blob_size (blob, &blob);
11467                                 result = TRUE;
11468                         }
11469                 } else if (cols [MONO_DECL_SECURITY_ACTION] == id_choice) {
11470                         if (!actions->demandchoice.blob) {
11471                                 const char *blob = mono_metadata_blob_heap (image, cols [MONO_DECL_SECURITY_PERMISSIONSET]);
11472                                 actions->demandchoice.index = cols [MONO_DECL_SECURITY_PERMISSIONSET];
11473                                 actions->demandchoice.blob = (char*) (blob + 2);
11474                                 actions->demandchoice.size = mono_metadata_decode_blob_size (blob, &blob);
11475                                 result = TRUE;
11476                         }
11477                 }
11478         }
11479
11480         return result;
11481 }
11482
11483 static MonoBoolean
11484 mono_declsec_get_class_demands_params (MonoClass *klass, MonoDeclSecurityActions* demands, 
11485         guint32 id_std, guint32 id_noncas, guint32 id_choice)
11486 {
11487         guint32 idx = mono_metadata_token_index (klass->type_token);
11488         idx <<= MONO_HAS_DECL_SECURITY_BITS;
11489         idx |= MONO_HAS_DECL_SECURITY_TYPEDEF;
11490         return fill_actions_from_index (klass->image, idx, demands, id_std, id_noncas, id_choice);
11491 }
11492
11493 static MonoBoolean
11494 mono_declsec_get_method_demands_params (MonoMethod *method, MonoDeclSecurityActions* demands, 
11495         guint32 id_std, guint32 id_noncas, guint32 id_choice)
11496 {
11497         guint32 idx = mono_method_get_index (method);
11498         idx <<= MONO_HAS_DECL_SECURITY_BITS;
11499         idx |= MONO_HAS_DECL_SECURITY_METHODDEF;
11500         return fill_actions_from_index (method->klass->image, idx, demands, id_std, id_noncas, id_choice);
11501 }
11502
11503 /*
11504  * Collect all actions (that requires to generate code in mini) assigned for
11505  * the specified method.
11506  * Note: Don't use the content of actions if the function return FALSE.
11507  */
11508 MonoBoolean
11509 mono_declsec_get_demands (MonoMethod *method, MonoDeclSecurityActions* demands)
11510 {
11511         guint32 mask = MONO_DECLSEC_FLAG_DEMAND | MONO_DECLSEC_FLAG_NONCAS_DEMAND | 
11512                 MONO_DECLSEC_FLAG_DEMAND_CHOICE;
11513         MonoBoolean result = FALSE;
11514         guint32 flags;
11515
11516         /* quick exit if no declarative security is present in the metadata */
11517         if (!method->klass->image->tables [MONO_TABLE_DECLSECURITY].rows)
11518                 return FALSE;
11519
11520         /* we want the original as the wrapper is "free" of the security informations */
11521         if (method->wrapper_type == MONO_WRAPPER_MANAGED_TO_NATIVE || method->wrapper_type == MONO_WRAPPER_MANAGED_TO_MANAGED) {
11522                 method = mono_marshal_method_from_wrapper (method);
11523                 if (!method)
11524                         return FALSE;
11525         }
11526
11527         /* First we look for method-level attributes */
11528         if (method->flags & METHOD_ATTRIBUTE_HAS_SECURITY) {
11529                 mono_class_init (method->klass);
11530                 memset (demands, 0, sizeof (MonoDeclSecurityActions));
11531
11532                 result = mono_declsec_get_method_demands_params (method, demands, 
11533                         SECURITY_ACTION_DEMAND, SECURITY_ACTION_NONCASDEMAND, SECURITY_ACTION_DEMANDCHOICE);
11534         }
11535
11536         /* Here we use (or create) the class declarative cache to look for demands */
11537         flags = mono_declsec_flags_from_class (method->klass);
11538         if (flags & mask) {
11539                 if (!result) {
11540                         mono_class_init (method->klass);
11541                         memset (demands, 0, sizeof (MonoDeclSecurityActions));
11542                 }
11543                 result |= mono_declsec_get_class_demands_params (method->klass, demands, 
11544                         SECURITY_ACTION_DEMAND, SECURITY_ACTION_NONCASDEMAND, SECURITY_ACTION_DEMANDCHOICE);
11545         }
11546
11547         /* The boolean return value is used as a shortcut in case nothing needs to
11548            be generated (e.g. LinkDemand[Choice] and InheritanceDemand[Choice]) */
11549         return result;
11550 }
11551
11552
11553 /*
11554  * Collect all Link actions: LinkDemand, NonCasLinkDemand and LinkDemandChoice (2.0).
11555  *
11556  * Note: Don't use the content of actions if the function return FALSE.
11557  */
11558 MonoBoolean
11559 mono_declsec_get_linkdemands (MonoMethod *method, MonoDeclSecurityActions* klass, MonoDeclSecurityActions *cmethod)
11560 {
11561         MonoBoolean result = FALSE;
11562         guint32 flags;
11563
11564         /* quick exit if no declarative security is present in the metadata */
11565         if (!method->klass->image->tables [MONO_TABLE_DECLSECURITY].rows)
11566                 return FALSE;
11567
11568         /* we want the original as the wrapper is "free" of the security informations */
11569         if (method->wrapper_type == MONO_WRAPPER_MANAGED_TO_NATIVE || method->wrapper_type == MONO_WRAPPER_MANAGED_TO_MANAGED) {
11570                 method = mono_marshal_method_from_wrapper (method);
11571                 if (!method)
11572                         return FALSE;
11573         }
11574
11575         /* results are independant - zeroize both */
11576         memset (cmethod, 0, sizeof (MonoDeclSecurityActions));
11577         memset (klass, 0, sizeof (MonoDeclSecurityActions));
11578
11579         /* First we look for method-level attributes */
11580         if (method->flags & METHOD_ATTRIBUTE_HAS_SECURITY) {
11581                 mono_class_init (method->klass);
11582
11583                 result = mono_declsec_get_method_demands_params (method, cmethod, 
11584                         SECURITY_ACTION_LINKDEMAND, SECURITY_ACTION_NONCASLINKDEMAND, SECURITY_ACTION_LINKDEMANDCHOICE);
11585         }
11586
11587         /* Here we use (or create) the class declarative cache to look for demands */
11588         flags = mono_declsec_flags_from_class (method->klass);
11589         if (flags & (MONO_DECLSEC_FLAG_LINKDEMAND | MONO_DECLSEC_FLAG_NONCAS_LINKDEMAND | MONO_DECLSEC_FLAG_LINKDEMAND_CHOICE)) {
11590                 mono_class_init (method->klass);
11591
11592                 result |= mono_declsec_get_class_demands_params (method->klass, klass, 
11593                         SECURITY_ACTION_LINKDEMAND, SECURITY_ACTION_NONCASLINKDEMAND, SECURITY_ACTION_LINKDEMANDCHOICE);
11594         }
11595
11596         return result;
11597 }
11598
11599 /*
11600  * Collect all Inherit actions: InheritanceDemand, NonCasInheritanceDemand and InheritanceDemandChoice (2.0).
11601  *
11602  * @klass       The inherited class - this is the class that provides the security check (attributes)
11603  * @demans      
11604  * return TRUE if inheritance demands (any kind) are present, FALSE otherwise.
11605  * 
11606  * Note: Don't use the content of actions if the function return FALSE.
11607  */
11608 MonoBoolean
11609 mono_declsec_get_inheritdemands_class (MonoClass *klass, MonoDeclSecurityActions* demands)
11610 {
11611         MonoBoolean result = FALSE;
11612         guint32 flags;
11613
11614         /* quick exit if no declarative security is present in the metadata */
11615         if (!klass->image->tables [MONO_TABLE_DECLSECURITY].rows)
11616                 return FALSE;
11617
11618         /* Here we use (or create) the class declarative cache to look for demands */
11619         flags = mono_declsec_flags_from_class (klass);
11620         if (flags & (MONO_DECLSEC_FLAG_INHERITANCEDEMAND | MONO_DECLSEC_FLAG_NONCAS_INHERITANCEDEMAND | MONO_DECLSEC_FLAG_INHERITANCEDEMAND_CHOICE)) {
11621                 mono_class_init (klass);
11622                 memset (demands, 0, sizeof (MonoDeclSecurityActions));
11623
11624                 result |= mono_declsec_get_class_demands_params (klass, demands, 
11625                         SECURITY_ACTION_INHERITDEMAND, SECURITY_ACTION_NONCASINHERITANCE, SECURITY_ACTION_INHERITDEMANDCHOICE);
11626         }
11627
11628         return result;
11629 }
11630
11631 /*
11632  * Collect all Inherit actions: InheritanceDemand, NonCasInheritanceDemand and InheritanceDemandChoice (2.0).
11633  *
11634  * Note: Don't use the content of actions if the function return FALSE.
11635  */
11636 MonoBoolean
11637 mono_declsec_get_inheritdemands_method (MonoMethod *method, MonoDeclSecurityActions* demands)
11638 {
11639         /* quick exit if no declarative security is present in the metadata */
11640         if (!method->klass->image->tables [MONO_TABLE_DECLSECURITY].rows)
11641                 return FALSE;
11642
11643         /* we want the original as the wrapper is "free" of the security informations */
11644         if (method->wrapper_type == MONO_WRAPPER_MANAGED_TO_NATIVE || method->wrapper_type == MONO_WRAPPER_MANAGED_TO_MANAGED) {
11645                 method = mono_marshal_method_from_wrapper (method);
11646                 if (!method)
11647                         return FALSE;
11648         }
11649
11650         if (method->flags & METHOD_ATTRIBUTE_HAS_SECURITY) {
11651                 mono_class_init (method->klass);
11652                 memset (demands, 0, sizeof (MonoDeclSecurityActions));
11653
11654                 return mono_declsec_get_method_demands_params (method, demands, 
11655                         SECURITY_ACTION_INHERITDEMAND, SECURITY_ACTION_NONCASINHERITANCE, SECURITY_ACTION_INHERITDEMANDCHOICE);
11656         }
11657         return FALSE;
11658 }
11659
11660
11661 static MonoBoolean
11662 get_declsec_action (MonoImage *image, guint32 token, guint32 action, MonoDeclSecurityEntry *entry)
11663 {
11664         guint32 cols [MONO_DECL_SECURITY_SIZE];
11665         MonoTableInfo *t;
11666         int i;
11667
11668         int index = mono_metadata_declsec_from_index (image, token);
11669         if (index == -1)
11670                 return FALSE;
11671
11672         t =  &image->tables [MONO_TABLE_DECLSECURITY];
11673         for (i = index; i < t->rows; i++) {
11674                 mono_metadata_decode_row (t, i, cols, MONO_DECL_SECURITY_SIZE);
11675
11676                 /* shortcut - index are ordered */
11677                 if (token != cols [MONO_DECL_SECURITY_PARENT])
11678                         return FALSE;
11679
11680                 if (cols [MONO_DECL_SECURITY_ACTION] == action) {
11681                         const char *metadata = mono_metadata_blob_heap (image, cols [MONO_DECL_SECURITY_PERMISSIONSET]);
11682                         entry->blob = (char*) (metadata + 2);
11683                         entry->size = mono_metadata_decode_blob_size (metadata, &metadata);
11684                         return TRUE;
11685                 }
11686         }
11687
11688         return FALSE;
11689 }
11690
11691 MonoBoolean
11692 mono_declsec_get_method_action (MonoMethod *method, guint32 action, MonoDeclSecurityEntry *entry)
11693 {
11694         if (method->flags & METHOD_ATTRIBUTE_HAS_SECURITY) {
11695                 guint32 idx = mono_method_get_index (method);
11696                 idx <<= MONO_HAS_DECL_SECURITY_BITS;
11697                 idx |= MONO_HAS_DECL_SECURITY_METHODDEF;
11698                 return get_declsec_action (method->klass->image, idx, action, entry);
11699         }
11700         return FALSE;
11701 }
11702
11703 MonoBoolean
11704 mono_declsec_get_class_action (MonoClass *klass, guint32 action, MonoDeclSecurityEntry *entry)
11705 {
11706         /* use cache */
11707         guint32 flags = mono_declsec_flags_from_class (klass);
11708         if (declsec_flags_map [action] & flags) {
11709                 guint32 idx = mono_metadata_token_index (klass->type_token);
11710                 idx <<= MONO_HAS_DECL_SECURITY_BITS;
11711                 idx |= MONO_HAS_DECL_SECURITY_TYPEDEF;
11712                 return get_declsec_action (klass->image, idx, action, entry);
11713         }
11714         return FALSE;
11715 }
11716
11717 MonoBoolean
11718 mono_declsec_get_assembly_action (MonoAssembly *assembly, guint32 action, MonoDeclSecurityEntry *entry)
11719 {
11720         guint32 idx = 1; /* there is only one assembly */
11721         idx <<= MONO_HAS_DECL_SECURITY_BITS;
11722         idx |= MONO_HAS_DECL_SECURITY_ASSEMBLY;
11723
11724         return get_declsec_action (assembly->image, idx, action, entry);
11725 }
11726
11727 gboolean
11728 mono_reflection_call_is_assignable_to (MonoClass *klass, MonoClass *oklass)
11729 {
11730         MonoObject *res, *exc;
11731         void *params [1];
11732         static MonoClass *System_Reflection_Emit_TypeBuilder = NULL;
11733         static MonoMethod *method = NULL;
11734
11735         if (!System_Reflection_Emit_TypeBuilder) {
11736                 System_Reflection_Emit_TypeBuilder = mono_class_from_name (mono_defaults.corlib, "System.Reflection.Emit", "TypeBuilder");
11737                 g_assert (System_Reflection_Emit_TypeBuilder);
11738         }
11739         if (method == NULL) {
11740                 method = mono_class_get_method_from_name (System_Reflection_Emit_TypeBuilder, "IsAssignableTo", 1);
11741                 g_assert (method);
11742         }
11743
11744         /* 
11745          * The result of mono_type_get_object () might be a System.MonoType but we
11746          * need a TypeBuilder so use klass->reflection_info.
11747          */
11748         g_assert (klass->reflection_info);
11749         g_assert (!strcmp (((MonoObject*)(klass->reflection_info))->vtable->klass->name, "TypeBuilder"));
11750
11751         params [0] = mono_type_get_object (mono_domain_get (), &oklass->byval_arg);
11752
11753         res = mono_runtime_invoke (method, (MonoObject*)(klass->reflection_info), params, &exc);
11754         if (exc)
11755                 return FALSE;
11756         else
11757                 return *(MonoBoolean*)mono_object_unbox (res);
11758 }