2009-08-14 Mark Probst <mark.probst@gmail.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         case METHOD_HEADER_TINY_FORMAT1:
6698                 local_var_sig_token = 0;
6699                 break;
6700         case METHOD_HEADER_FAT_FORMAT:
6701                 ptr += 2;
6702                 ptr += 2;
6703                 ptr += 4;
6704                 local_var_sig_token = read32 (ptr);
6705                 break;
6706         default:
6707                 g_assert_not_reached ();
6708         }
6709
6710         ret = (MonoReflectionMethodBody*)mono_object_new (domain, System_Reflection_MethodBody);
6711
6712         ret->init_locals = header->init_locals;
6713         ret->max_stack = header->max_stack;
6714         ret->local_var_sig_token = local_var_sig_token;
6715         MONO_OBJECT_SETREF (ret, il, mono_array_new_cached (domain, mono_defaults.byte_class, header->code_size));
6716         memcpy (mono_array_addr (ret->il, guint8, 0), header->code, header->code_size);
6717
6718         /* Locals */
6719         MONO_OBJECT_SETREF (ret, locals, mono_array_new_cached (domain, System_Reflection_LocalVariableInfo, header->num_locals));
6720         for (i = 0; i < header->num_locals; ++i) {
6721                 MonoReflectionLocalVariableInfo *info = (MonoReflectionLocalVariableInfo*)mono_object_new (domain, System_Reflection_LocalVariableInfo);
6722                 MONO_OBJECT_SETREF (info, local_type, mono_type_get_object (domain, header->locals [i]));
6723                 info->is_pinned = header->locals [i]->pinned;
6724                 info->local_index = i;
6725                 mono_array_setref (ret->locals, i, info);
6726         }
6727
6728         /* Exceptions */
6729         MONO_OBJECT_SETREF (ret, clauses, mono_array_new_cached (domain, System_Reflection_ExceptionHandlingClause, header->num_clauses));
6730         for (i = 0; i < header->num_clauses; ++i) {
6731                 MonoReflectionExceptionHandlingClause *info = (MonoReflectionExceptionHandlingClause*)mono_object_new (domain, System_Reflection_ExceptionHandlingClause);
6732                 MonoExceptionClause *clause = &header->clauses [i];
6733
6734                 info->flags = clause->flags;
6735                 info->try_offset = clause->try_offset;
6736                 info->try_length = clause->try_len;
6737                 info->handler_offset = clause->handler_offset;
6738                 info->handler_length = clause->handler_len;
6739                 if (clause->flags == MONO_EXCEPTION_CLAUSE_FILTER)
6740                         info->filter_offset = clause->data.filter_offset;
6741                 else if (clause->data.catch_class)
6742                         MONO_OBJECT_SETREF (info, catch_type, mono_type_get_object (mono_domain_get (), &clause->data.catch_class->byval_arg));
6743
6744                 mono_array_setref (ret->clauses, i, info);
6745         }
6746
6747         CACHE_OBJECT (MonoReflectionMethodBody *, method, ret, NULL);
6748         return ret;
6749 }
6750
6751 /**
6752  * mono_get_dbnull_object:
6753  * @domain: Domain where the object lives
6754  *
6755  * Returns the System.DBNull.Value singleton object
6756  *
6757  * Used as the value for ParameterInfo.DefaultValue 
6758  */
6759 MonoObject *
6760 mono_get_dbnull_object (MonoDomain *domain)
6761 {
6762         MonoObject *obj;
6763         static MonoClassField *dbnull_value_field = NULL;
6764         
6765         if (!dbnull_value_field) {
6766                 MonoClass *dbnull_klass;
6767                 dbnull_klass = mono_class_from_name (mono_defaults.corlib, "System", "DBNull");
6768                 mono_class_init (dbnull_klass);
6769                 dbnull_value_field = mono_class_get_field_from_name (dbnull_klass, "Value");
6770                 g_assert (dbnull_value_field);
6771         }
6772         obj = mono_field_get_value_object (domain, dbnull_value_field, NULL); 
6773         g_assert (obj);
6774         return obj;
6775 }
6776
6777 static void
6778 get_default_param_value_blobs (MonoMethod *method, char **blobs, guint32 *types)
6779 {
6780         guint32 param_index, i, lastp, crow = 0;
6781         guint32 param_cols [MONO_PARAM_SIZE], const_cols [MONO_CONSTANT_SIZE];
6782         gint32 idx;
6783
6784         MonoClass *klass = method->klass;
6785         MonoImage *image = klass->image;
6786         MonoMethodSignature *methodsig = mono_method_signature (method);
6787
6788         MonoTableInfo *constt;
6789         MonoTableInfo *methodt;
6790         MonoTableInfo *paramt;
6791
6792         if (!methodsig->param_count)
6793                 return;
6794
6795         mono_class_init (klass);
6796
6797         if (klass->image->dynamic) {
6798                 MonoReflectionMethodAux *aux;
6799                 if (method->is_inflated)
6800                         method = ((MonoMethodInflated*)method)->declaring;
6801                 aux = g_hash_table_lookup (((MonoDynamicImage*)method->klass->image)->method_aux_hash, method);
6802                 if (aux && aux->param_defaults) {
6803                         memcpy (blobs, &(aux->param_defaults [1]), methodsig->param_count * sizeof (char*));
6804                         memcpy (types, &(aux->param_default_types [1]), methodsig->param_count * sizeof (guint32));
6805                 }
6806                 return;
6807         }
6808
6809         methodt = &klass->image->tables [MONO_TABLE_METHOD];
6810         paramt = &klass->image->tables [MONO_TABLE_PARAM];
6811         constt = &image->tables [MONO_TABLE_CONSTANT];
6812
6813         idx = mono_method_get_index (method) - 1;
6814         g_assert (idx != -1);
6815
6816         param_index = mono_metadata_decode_row_col (methodt, idx, MONO_METHOD_PARAMLIST);
6817         if (idx + 1 < methodt->rows)
6818                 lastp = mono_metadata_decode_row_col (methodt, idx + 1, MONO_METHOD_PARAMLIST);
6819         else
6820                 lastp = paramt->rows + 1;
6821
6822         for (i = param_index; i < lastp; ++i) {
6823                 guint32 paramseq;
6824
6825                 mono_metadata_decode_row (paramt, i - 1, param_cols, MONO_PARAM_SIZE);
6826                 paramseq = param_cols [MONO_PARAM_SEQUENCE];
6827
6828                 if (!param_cols [MONO_PARAM_FLAGS] & PARAM_ATTRIBUTE_HAS_DEFAULT) 
6829                         continue;
6830
6831                 crow = mono_metadata_get_constant_index (image, MONO_TOKEN_PARAM_DEF | i, crow + 1);
6832                 if (!crow) {
6833                         continue;
6834                 }
6835         
6836                 mono_metadata_decode_row (constt, crow - 1, const_cols, MONO_CONSTANT_SIZE);
6837                 blobs [paramseq - 1] = (gpointer) mono_metadata_blob_heap (image, const_cols [MONO_CONSTANT_VALUE]);
6838                 types [paramseq - 1] = const_cols [MONO_CONSTANT_TYPE];
6839         }
6840
6841         return;
6842 }
6843
6844 static MonoObject *
6845 mono_get_object_from_blob (MonoDomain *domain, MonoType *type, const char *blob)
6846 {
6847         void *retval;
6848         MonoClass *klass;
6849         MonoObject *object;
6850         MonoType *basetype = type;
6851
6852         if (!blob)
6853                 return NULL;
6854         
6855         klass = mono_class_from_mono_type (type);
6856         if (klass->valuetype) {
6857                 object = mono_object_new (domain, klass);
6858                 retval = ((gchar *) object + sizeof (MonoObject));
6859                 if (klass->enumtype)
6860                         basetype = mono_class_enum_basetype (klass);
6861         } else {
6862                 retval = &object;
6863         }
6864                         
6865         if (!mono_get_constant_value_from_blob (domain, basetype->type,  blob, retval))
6866                 return object;
6867         else
6868                 return NULL;
6869 }
6870
6871 static int
6872 assembly_name_to_aname (MonoAssemblyName *assembly, char *p) {
6873         int found_sep;
6874         char *s;
6875
6876         memset (assembly, 0, sizeof (MonoAssemblyName));
6877         assembly->name = p;
6878         assembly->culture = "";
6879         memset (assembly->public_key_token, 0, MONO_PUBLIC_KEY_TOKEN_LENGTH);
6880
6881         while (*p && (isalnum (*p) || *p == '.' || *p == '-' || *p == '_' || *p == '$' || *p == '@'))
6882                 p++;
6883         found_sep = 0;
6884         while (g_ascii_isspace (*p) || *p == ',') {
6885                 *p++ = 0;
6886                 found_sep = 1;
6887                 continue;
6888         }
6889         /* failed */
6890         if (!found_sep)
6891                 return 1;
6892         while (*p) {
6893                 if (*p == 'V' && g_ascii_strncasecmp (p, "Version=", 8) == 0) {
6894                         p += 8;
6895                         assembly->major = strtoul (p, &s, 10);
6896                         if (s == p || *s != '.')
6897                                 return 1;
6898                         p = ++s;
6899                         assembly->minor = strtoul (p, &s, 10);
6900                         if (s == p || *s != '.')
6901                                 return 1;
6902                         p = ++s;
6903                         assembly->build = strtoul (p, &s, 10);
6904                         if (s == p || *s != '.')
6905                                 return 1;
6906                         p = ++s;
6907                         assembly->revision = strtoul (p, &s, 10);
6908                         if (s == p)
6909                                 return 1;
6910                         p = s;
6911                 } else if (*p == 'C' && g_ascii_strncasecmp (p, "Culture=", 8) == 0) {
6912                         p += 8;
6913                         if (g_ascii_strncasecmp (p, "neutral", 7) == 0) {
6914                                 assembly->culture = "";
6915                                 p += 7;
6916                         } else {
6917                                 assembly->culture = p;
6918                                 while (*p && *p != ',') {
6919                                         p++;
6920                                 }
6921                         }
6922                 } else if (*p == 'P' && g_ascii_strncasecmp (p, "PublicKeyToken=", 15) == 0) {
6923                         p += 15;
6924                         if (strncmp (p, "null", 4) == 0) {
6925                                 p += 4;
6926                         } else {
6927                                 int len;
6928                                 gchar *start = p;
6929                                 while (*p && *p != ',') {
6930                                         p++;
6931                                 }
6932                                 len = (p - start + 1);
6933                                 if (len > MONO_PUBLIC_KEY_TOKEN_LENGTH)
6934                                         len = MONO_PUBLIC_KEY_TOKEN_LENGTH;
6935                                 g_strlcpy ((char*)assembly->public_key_token, start, len);
6936                         }
6937                 } else {
6938                         while (*p && *p != ',')
6939                                 p++;
6940                 }
6941                 found_sep = 0;
6942                 while (g_ascii_isspace (*p) || *p == ',') {
6943                         *p++ = 0;
6944                         found_sep = 1;
6945                         continue;
6946                 }
6947                 /* failed */
6948                 if (!found_sep)
6949                         return 1;
6950         }
6951
6952         return 0;
6953 }
6954
6955 /*
6956  * mono_reflection_parse_type:
6957  * @name: type name
6958  *
6959  * Parse a type name as accepted by the GetType () method and output the info
6960  * extracted in the info structure.
6961  * the name param will be mangled, so, make a copy before passing it to this function.
6962  * The fields in info will be valid until the memory pointed to by name is valid.
6963  *
6964  * See also mono_type_get_name () below.
6965  *
6966  * Returns: 0 on parse error.
6967  */
6968 static int
6969 _mono_reflection_parse_type (char *name, char **endptr, gboolean is_recursed,
6970                              MonoTypeNameParse *info)
6971 {
6972         char *start, *p, *w, *temp, *last_point, *startn;
6973         int in_modifiers = 0;
6974         int isbyref = 0, rank, arity = 0, i;
6975
6976         start = p = w = name;
6977
6978         //FIXME could we just zero the whole struct? memset (&info, 0, sizeof (MonoTypeNameParse))
6979         memset (&info->assembly, 0, sizeof (MonoAssemblyName));
6980         info->name = info->name_space = NULL;
6981         info->nested = NULL;
6982         info->modifiers = NULL;
6983         info->type_arguments = NULL;
6984
6985         /* last_point separates the namespace from the name */
6986         last_point = NULL;
6987         /* Skips spaces */
6988         while (*p == ' ') p++, start++, w++, name++;
6989
6990         while (*p) {
6991                 switch (*p) {
6992                 case '+':
6993                         *p = 0; /* NULL terminate the name */
6994                         startn = p + 1;
6995                         info->nested = g_list_append (info->nested, startn);
6996                         /* we have parsed the nesting namespace + name */
6997                         if (info->name)
6998                                 break;
6999                         if (last_point) {
7000                                 info->name_space = start;
7001                                 *last_point = 0;
7002                                 info->name = last_point + 1;
7003                         } else {
7004                                 info->name_space = (char *)"";
7005                                 info->name = start;
7006                         }
7007                         break;
7008                 case '.':
7009                         last_point = p;
7010                         break;
7011                 case '\\':
7012                         ++p;
7013                         break;
7014                 case '&':
7015                 case '*':
7016                 case '[':
7017                 case ',':
7018                 case ']':
7019                         in_modifiers = 1;
7020                         break;
7021                 case '`':
7022                         ++p;
7023                         i = strtol (p, &temp, 10);
7024                         arity += i;
7025                         if (p == temp)
7026                                 return 0;
7027                         p = temp-1;
7028                         break;
7029                 default:
7030                         break;
7031                 }
7032                 if (in_modifiers)
7033                         break;
7034                 // *w++ = *p++;
7035                 p++;
7036         }
7037         
7038         if (!info->name) {
7039                 if (last_point) {
7040                         info->name_space = start;
7041                         *last_point = 0;
7042                         info->name = last_point + 1;
7043                 } else {
7044                         info->name_space = (char *)"";
7045                         info->name = start;
7046                 }
7047         }
7048         while (*p) {
7049                 switch (*p) {
7050                 case '&':
7051                         if (isbyref) /* only one level allowed by the spec */
7052                                 return 0;
7053                         isbyref = 1;
7054                         info->modifiers = g_list_append (info->modifiers, GUINT_TO_POINTER (0));
7055                         *p++ = 0;
7056                         break;
7057                 case '*':
7058                         info->modifiers = g_list_append (info->modifiers, GUINT_TO_POINTER (-1));
7059                         *p++ = 0;
7060                         break;
7061                 case '[':
7062                         if (arity != 0) {
7063                                 *p++ = 0;
7064                                 info->type_arguments = g_ptr_array_new ();
7065                                 for (i = 0; i < arity; i++) {
7066                                         MonoTypeNameParse *subinfo = g_new0 (MonoTypeNameParse, 1);
7067                                         gboolean fqname = FALSE;
7068
7069                                         g_ptr_array_add (info->type_arguments, subinfo);
7070
7071                                         if (*p == '[') {
7072                                                 p++;
7073                                                 fqname = TRUE;
7074                                         }
7075
7076                                         if (!_mono_reflection_parse_type (p, &p, TRUE, subinfo))
7077                                                 return 0;
7078
7079                                         if (fqname) {
7080                                                 char *aname;
7081
7082                                                 if (*p != ',')
7083                                                         return 0;
7084                                                 *p++ = 0;
7085
7086                                                 aname = p;
7087                                                 while (*p && (*p != ']'))
7088                                                         p++;
7089
7090                                                 if (*p != ']')
7091                                                         return 0;
7092
7093                                                 *p++ = 0;
7094                                                 while (*aname) {
7095                                                         if (g_ascii_isspace (*aname)) {
7096                                                                 ++aname;
7097                                                                 continue;
7098                                                         }
7099                                                         break;
7100                                                 }
7101                                                 if (!*aname ||
7102                                                     !assembly_name_to_aname (&subinfo->assembly, aname))
7103                                                         return 0;
7104                                         }
7105
7106                                         if (i + 1 < arity) {
7107                                                 if (*p != ',')
7108                                                         return 0;
7109                                         } else {
7110                                                 if (*p != ']')
7111                                                         return 0;
7112                                         }
7113                                         *p++ = 0;
7114                                 }
7115
7116                                 arity = 0;
7117                                 break;
7118                         }
7119                         rank = 1;
7120                         *p++ = 0;
7121                         while (*p) {
7122                                 if (*p == ']')
7123                                         break;
7124                                 if (*p == ',')
7125                                         rank++;
7126                                 else if (*p == '*') /* '*' means unknown lower bound */
7127                                         info->modifiers = g_list_append (info->modifiers, GUINT_TO_POINTER (-2));
7128                                 else
7129                                         return 0;
7130                                 ++p;
7131                         }
7132                         if (*p++ != ']')
7133                                 return 0;
7134                         info->modifiers = g_list_append (info->modifiers, GUINT_TO_POINTER (rank));
7135                         break;
7136                 case ']':
7137                         if (is_recursed)
7138                                 goto end;
7139                         return 0;
7140                 case ',':
7141                         if (is_recursed)
7142                                 goto end;
7143                         *p++ = 0;
7144                         while (*p) {
7145                                 if (g_ascii_isspace (*p)) {
7146                                         ++p;
7147                                         continue;
7148                                 }
7149                                 break;
7150                         }
7151                         if (!*p)
7152                                 return 0; /* missing assembly name */
7153                         if (!assembly_name_to_aname (&info->assembly, p))
7154                                 return 0;
7155                         break;
7156                 default:
7157                         return 0;
7158                 }
7159                 if (info->assembly.name)
7160                         break;
7161         }
7162         // *w = 0; /* terminate class name */
7163  end:
7164         if (!info->name || !*info->name)
7165                 return 0;
7166         if (endptr)
7167                 *endptr = p;
7168         /* add other consistency checks */
7169         return 1;
7170 }
7171
7172 int
7173 mono_reflection_parse_type (char *name, MonoTypeNameParse *info)
7174 {
7175         return _mono_reflection_parse_type (name, NULL, FALSE, info);
7176 }
7177
7178 static MonoType*
7179 _mono_reflection_get_type_from_info (MonoTypeNameParse *info, MonoImage *image, gboolean ignorecase)
7180 {
7181         gboolean type_resolve = FALSE;
7182         MonoType *type;
7183         MonoImage *rootimage = image;
7184
7185         if (info->assembly.name) {
7186                 MonoAssembly *assembly = mono_assembly_loaded (&info->assembly);
7187                 if (!assembly && image && image->assembly && mono_assembly_names_equal (&info->assembly, &image->assembly->aname))
7188                         /* 
7189                          * This could happen in the AOT compiler case when the search hook is not
7190                          * installed.
7191                          */
7192                         assembly = image->assembly;
7193                 if (!assembly) {
7194                         /* then we must load the assembly ourselve - see #60439 */
7195                         assembly = mono_assembly_load (&info->assembly, NULL, NULL);
7196                         if (!assembly)
7197                                 return NULL;
7198                 }
7199                 image = assembly->image;
7200         } else if (!image) {
7201                 image = mono_defaults.corlib;
7202         }
7203
7204         type = mono_reflection_get_type_with_rootimage (rootimage, image, info, ignorecase, &type_resolve);
7205         if (type == NULL && !info->assembly.name && image != mono_defaults.corlib) {
7206                 image = mono_defaults.corlib;
7207                 type = mono_reflection_get_type_with_rootimage (rootimage, image, info, ignorecase, &type_resolve);
7208         }
7209
7210         return type;
7211 }
7212
7213 static MonoType*
7214 mono_reflection_get_type_internal (MonoImage *rootimage, MonoImage* image, MonoTypeNameParse *info, gboolean ignorecase)
7215 {
7216         MonoClass *klass;
7217         GList *mod;
7218         int modval;
7219         gboolean bounded = FALSE;
7220         
7221         if (!image)
7222                 image = mono_defaults.corlib;
7223
7224         if (ignorecase)
7225                 klass = mono_class_from_name_case (image, info->name_space, info->name);
7226         else
7227                 klass = mono_class_from_name (image, info->name_space, info->name);
7228         if (!klass)
7229                 return NULL;
7230         for (mod = info->nested; mod; mod = mod->next) {
7231                 gpointer iter = NULL;
7232                 MonoClass *parent;
7233
7234                 parent = klass;
7235                 mono_class_init (parent);
7236
7237                 while ((klass = mono_class_get_nested_types (parent, &iter))) {
7238                         if (ignorecase) {
7239                                 if (g_strcasecmp (klass->name, mod->data) == 0)
7240                                         break;
7241                         } else {
7242                                 if (strcmp (klass->name, mod->data) == 0)
7243                                         break;
7244                         }
7245                 }
7246                 if (!klass)
7247                         break;
7248         }
7249         if (!klass)
7250                 return NULL;
7251         mono_class_init (klass);
7252
7253         if (info->type_arguments) {
7254                 MonoType **type_args = g_new0 (MonoType *, info->type_arguments->len);
7255                 MonoReflectionType *the_type;
7256                 MonoType *instance;
7257                 int i;
7258
7259                 for (i = 0; i < info->type_arguments->len; i++) {
7260                         MonoTypeNameParse *subinfo = g_ptr_array_index (info->type_arguments, i);
7261
7262                         type_args [i] = _mono_reflection_get_type_from_info (subinfo, rootimage, ignorecase);
7263                         if (!type_args [i]) {
7264                                 g_free (type_args);
7265                                 return NULL;
7266                         }
7267                 }
7268
7269                 the_type = mono_type_get_object (mono_domain_get (), &klass->byval_arg);
7270
7271                 instance = mono_reflection_bind_generic_parameters (
7272                         the_type, info->type_arguments->len, type_args);
7273
7274                 g_free (type_args);
7275                 if (!instance)
7276                         return NULL;
7277
7278                 klass = mono_class_from_mono_type (instance);
7279         }
7280
7281         for (mod = info->modifiers; mod; mod = mod->next) {
7282                 modval = GPOINTER_TO_UINT (mod->data);
7283                 if (!modval) { /* byref: must be last modifier */
7284                         return &klass->this_arg;
7285                 } else if (modval == -1) {
7286                         klass = mono_ptr_class_get (&klass->byval_arg);
7287                 } else if (modval == -2) {
7288                         bounded = TRUE;
7289                 } else { /* array rank */
7290                         klass = mono_bounded_array_class_get (klass, modval, bounded);
7291                 }
7292                 mono_class_init (klass);
7293         }
7294
7295         return &klass->byval_arg;
7296 }
7297
7298 /*
7299  * mono_reflection_get_type:
7300  * @image: a metadata context
7301  * @info: type description structure
7302  * @ignorecase: flag for case-insensitive string compares
7303  * @type_resolve: whenever type resolve was already tried
7304  *
7305  * Build a MonoType from the type description in @info.
7306  * 
7307  */
7308
7309 MonoType*
7310 mono_reflection_get_type (MonoImage* image, MonoTypeNameParse *info, gboolean ignorecase, gboolean *type_resolve) {
7311         return mono_reflection_get_type_with_rootimage(image, image, info, ignorecase, type_resolve);
7312 }
7313
7314 static MonoType*
7315 mono_reflection_get_type_internal_dynamic (MonoImage *rootimage, MonoAssembly *assembly, MonoTypeNameParse *info, gboolean ignorecase)
7316 {
7317         MonoReflectionAssemblyBuilder *abuilder = (MonoReflectionAssemblyBuilder*)mono_assembly_get_object (mono_domain_get (), assembly);
7318         MonoType *type;
7319         int i;
7320
7321         g_assert (assembly->dynamic);
7322
7323         /* Enumerate all modules */
7324
7325         type = NULL;
7326         if (abuilder->modules) {
7327                 for (i = 0; i < mono_array_length (abuilder->modules); ++i) {
7328                         MonoReflectionModuleBuilder *mb = mono_array_get (abuilder->modules, MonoReflectionModuleBuilder*, i);
7329                         type = mono_reflection_get_type_internal (rootimage, &mb->dynamic_image->image, info, ignorecase);
7330                         if (type)
7331                                 break;
7332                 }
7333         }
7334
7335         if (!type && abuilder->loaded_modules) {
7336                 for (i = 0; i < mono_array_length (abuilder->loaded_modules); ++i) {
7337                         MonoReflectionModule *mod = mono_array_get (abuilder->loaded_modules, MonoReflectionModule*, i);
7338                         type = mono_reflection_get_type_internal (rootimage, mod->image, info, ignorecase);
7339                         if (type)
7340                                 break;
7341                 }
7342         }
7343
7344         return type;
7345 }
7346         
7347 MonoType*
7348 mono_reflection_get_type_with_rootimage (MonoImage *rootimage, MonoImage* image, MonoTypeNameParse *info, gboolean ignorecase, gboolean *type_resolve)
7349 {
7350         MonoType *type;
7351         MonoReflectionAssembly *assembly;
7352         GString *fullName;
7353         GList *mod;
7354
7355         if (image && image->dynamic)
7356                 type = mono_reflection_get_type_internal_dynamic (rootimage, image->assembly, info, ignorecase);
7357         else
7358                 type = mono_reflection_get_type_internal (rootimage, image, info, ignorecase);
7359         if (type)
7360                 return type;
7361         if (!mono_domain_has_type_resolve (mono_domain_get ()))
7362                 return NULL;
7363
7364         if (type_resolve) {
7365                 if (*type_resolve) 
7366                         return NULL;
7367                 else
7368                         *type_resolve = TRUE;
7369         }
7370         
7371         /* Reconstruct the type name */
7372         fullName = g_string_new ("");
7373         if (info->name_space && (info->name_space [0] != '\0'))
7374                 g_string_printf (fullName, "%s.%s", info->name_space, info->name);
7375         else
7376                 g_string_printf (fullName, "%s", info->name);
7377         for (mod = info->nested; mod; mod = mod->next)
7378                 g_string_append_printf (fullName, "+%s", (char*)mod->data);
7379
7380         assembly = mono_domain_try_type_resolve ( mono_domain_get (), fullName->str, NULL);
7381         if (assembly) {
7382                 if (assembly->assembly->dynamic)
7383                         type = mono_reflection_get_type_internal_dynamic (rootimage, assembly->assembly, info, ignorecase);
7384                 else
7385                         type = mono_reflection_get_type_internal (rootimage, assembly->assembly->image, 
7386                                                                                                           info, ignorecase);
7387         }
7388         g_string_free (fullName, TRUE);
7389         return type;
7390 }
7391
7392 void
7393 mono_reflection_free_type_info (MonoTypeNameParse *info)
7394 {
7395         g_list_free (info->modifiers);
7396         g_list_free (info->nested);
7397
7398         if (info->type_arguments) {
7399                 int i;
7400
7401                 for (i = 0; i < info->type_arguments->len; i++) {
7402                         MonoTypeNameParse *subinfo = g_ptr_array_index (info->type_arguments, i);
7403
7404                         mono_reflection_free_type_info (subinfo);
7405                         /*We free the subinfo since it is allocated by _mono_reflection_parse_type*/
7406                         g_free (subinfo);
7407                 }
7408
7409                 g_ptr_array_free (info->type_arguments, TRUE);
7410         }
7411 }
7412
7413 /*
7414  * mono_reflection_type_from_name:
7415  * @name: type name.
7416  * @image: a metadata context (can be NULL).
7417  *
7418  * Retrieves a MonoType from its @name. If the name is not fully qualified,
7419  * it defaults to get the type from @image or, if @image is NULL or loading
7420  * from it fails, uses corlib.
7421  * 
7422  */
7423 MonoType*
7424 mono_reflection_type_from_name (char *name, MonoImage *image)
7425 {
7426         MonoType *type = NULL;
7427         MonoTypeNameParse info;
7428         char *tmp;
7429
7430         /* Make a copy since parse_type modifies its argument */
7431         tmp = g_strdup (name);
7432         
7433         /*g_print ("requested type %s\n", str);*/
7434         if (mono_reflection_parse_type (tmp, &info)) {
7435                 type = _mono_reflection_get_type_from_info (&info, image, FALSE);
7436         }
7437
7438         g_free (tmp);
7439         mono_reflection_free_type_info (&info);
7440         return type;
7441 }
7442
7443 /*
7444  * mono_reflection_get_token:
7445  *
7446  *   Return the metadata token of OBJ which should be an object
7447  * representing a metadata element.
7448  */
7449 guint32
7450 mono_reflection_get_token (MonoObject *obj)
7451 {
7452         MonoClass *klass;
7453         guint32 token = 0;
7454
7455         klass = obj->vtable->klass;
7456
7457         if (strcmp (klass->name, "MethodBuilder") == 0) {
7458                 MonoReflectionMethodBuilder *mb = (MonoReflectionMethodBuilder *)obj;
7459
7460                 token = mb->table_idx | MONO_TOKEN_METHOD_DEF;
7461         } else if (strcmp (klass->name, "ConstructorBuilder") == 0) {
7462                 MonoReflectionCtorBuilder *mb = (MonoReflectionCtorBuilder *)obj;
7463
7464                 token = mb->table_idx | MONO_TOKEN_METHOD_DEF;
7465         } else if (strcmp (klass->name, "FieldBuilder") == 0) {
7466                 MonoReflectionFieldBuilder *fb = (MonoReflectionFieldBuilder *)obj;
7467
7468                 /* Call mono_image_create_token so the object gets added to the tokens hash table */
7469                 token = mono_image_create_token (((MonoReflectionTypeBuilder*)fb->typeb)->module->dynamic_image, obj, FALSE, TRUE);
7470         } else if (strcmp (klass->name, "TypeBuilder") == 0) {
7471                 MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder *)obj;
7472                 token = tb->table_idx | MONO_TOKEN_TYPE_DEF;
7473         } else if (strcmp (klass->name, "MonoType") == 0) {
7474                 MonoType *type = mono_reflection_type_get_handle ((MonoReflectionType *)obj);
7475                 token = mono_class_from_mono_type (type)->type_token;
7476         } else if (strcmp (klass->name, "MonoCMethod") == 0 ||
7477                    strcmp (klass->name, "MonoMethod") == 0 ||
7478                    strcmp (klass->name, "MonoGenericMethod") == 0 ||
7479                    strcmp (klass->name, "MonoGenericCMethod") == 0) {
7480                 MonoReflectionMethod *m = (MonoReflectionMethod *)obj;
7481                 if (m->method->is_inflated) {
7482                         MonoMethodInflated *inflated = (MonoMethodInflated *) m->method;
7483                         return inflated->declaring->token;
7484                 } else {
7485                         token = m->method->token;
7486                 }
7487         } else if (strcmp (klass->name, "MonoField") == 0) {
7488                 MonoReflectionField *f = (MonoReflectionField*)obj;
7489
7490                 if (is_field_on_inst (f->field)) {
7491                         MonoDynamicGenericClass *dgclass = (MonoDynamicGenericClass*)f->field->parent->generic_class;
7492                         int field_index = f->field - dgclass->fields;
7493                         MonoObject *obj;
7494
7495                         g_assert (field_index >= 0 && field_index < dgclass->count_fields);
7496                         obj = dgclass->field_objects [field_index];
7497                         return mono_reflection_get_token (obj);
7498                 }
7499                 token = mono_class_get_field_token (f->field);
7500         } else if (strcmp (klass->name, "MonoProperty") == 0) {
7501                 MonoReflectionProperty *p = (MonoReflectionProperty*)obj;
7502
7503                 token = mono_class_get_property_token (p->property);
7504         } else if (strcmp (klass->name, "MonoEvent") == 0) {
7505                 MonoReflectionMonoEvent *p = (MonoReflectionMonoEvent*)obj;
7506
7507                 token = mono_class_get_event_token (p->event);
7508         } else if (strcmp (klass->name, "ParameterInfo") == 0) {
7509                 MonoReflectionParameter *p = (MonoReflectionParameter*)obj;
7510
7511                 token = mono_method_get_param_token (((MonoReflectionMethod*)p->MemberImpl)->method, p->PositionImpl);
7512         } else if (strcmp (klass->name, "Module") == 0) {
7513                 MonoReflectionModule *m = (MonoReflectionModule*)obj;
7514
7515                 token = m->token;
7516         } else if (strcmp (klass->name, "Assembly") == 0) {
7517                 token = mono_metadata_make_token (MONO_TABLE_ASSEMBLY, 1);
7518         } else {
7519                 gchar *msg = g_strdup_printf ("MetadataToken is not supported for type '%s.%s'", klass->name_space, klass->name);
7520                 MonoException *ex = mono_get_exception_not_implemented (msg);
7521                 g_free (msg);
7522                 mono_raise_exception (ex);
7523         }
7524
7525         return token;
7526 }
7527
7528 static void*
7529 load_cattr_value (MonoImage *image, MonoType *t, const char *p, const char **end)
7530 {
7531         int slen, type = t->type;
7532         MonoClass *tklass = t->data.klass;
7533
7534 handle_enum:
7535         switch (type) {
7536         case MONO_TYPE_U1:
7537         case MONO_TYPE_I1:
7538         case MONO_TYPE_BOOLEAN: {
7539                 MonoBoolean *bval = g_malloc (sizeof (MonoBoolean));
7540                 *bval = *p;
7541                 *end = p + 1;
7542                 return bval;
7543         }
7544         case MONO_TYPE_CHAR:
7545         case MONO_TYPE_U2:
7546         case MONO_TYPE_I2: {
7547                 guint16 *val = g_malloc (sizeof (guint16));
7548                 *val = read16 (p);
7549                 *end = p + 2;
7550                 return val;
7551         }
7552 #if SIZEOF_VOID_P == 4
7553         case MONO_TYPE_U:
7554         case MONO_TYPE_I:
7555 #endif
7556         case MONO_TYPE_R4:
7557         case MONO_TYPE_U4:
7558         case MONO_TYPE_I4: {
7559                 guint32 *val = g_malloc (sizeof (guint32));
7560                 *val = read32 (p);
7561                 *end = p + 4;
7562                 return val;
7563         }
7564 #if SIZEOF_VOID_P == 8
7565         case MONO_TYPE_U: /* error out instead? this should probably not happen */
7566         case MONO_TYPE_I:
7567 #endif
7568         case MONO_TYPE_U8:
7569         case MONO_TYPE_I8: {
7570                 guint64 *val = g_malloc (sizeof (guint64));
7571                 *val = read64 (p);
7572                 *end = p + 8;
7573                 return val;
7574         }
7575         case MONO_TYPE_R8: {
7576                 double *val = g_malloc (sizeof (double));
7577                 readr8 (p, val);
7578                 *end = p + 8;
7579                 return val;
7580         }
7581         case MONO_TYPE_VALUETYPE:
7582                 if (t->data.klass->enumtype) {
7583                         type = mono_class_enum_basetype (t->data.klass)->type;
7584                         goto handle_enum;
7585                 } else {
7586                         g_error ("generic valutype %s not handled in custom attr value decoding", t->data.klass->name);
7587                 }
7588                 break;
7589         case MONO_TYPE_STRING:
7590                 if (*p == (char)0xFF) {
7591                         *end = p + 1;
7592                         return NULL;
7593                 }
7594                 slen = mono_metadata_decode_value (p, &p);
7595                 *end = p + slen;
7596                 return mono_string_new_len (mono_domain_get (), p, slen);
7597         case MONO_TYPE_CLASS: {
7598                 char *n;
7599                 MonoType *t;
7600                 if (*p == (char)0xFF) {
7601                         *end = p + 1;
7602                         return NULL;
7603                 }
7604 handle_type:
7605                 slen = mono_metadata_decode_value (p, &p);
7606                 n = g_memdup (p, slen + 1);
7607                 n [slen] = 0;
7608                 t = mono_reflection_type_from_name (n, image);
7609                 if (!t)
7610                         g_warning ("Cannot load type '%s'", n);
7611                 g_free (n);
7612                 *end = p + slen;
7613                 if (t)
7614                         return mono_type_get_object (mono_domain_get (), t);
7615                 else
7616                         return NULL;
7617         }
7618         case MONO_TYPE_OBJECT: {
7619                 char subt = *p++;
7620                 MonoObject *obj;
7621                 MonoClass *subc = NULL;
7622                 void *val;
7623
7624                 if (subt == 0x50) {
7625                         goto handle_type;
7626                 } else if (subt == 0x0E) {
7627                         type = MONO_TYPE_STRING;
7628                         goto handle_enum;
7629                 } else if (subt == 0x1D) {
7630                         MonoType simple_type = {{0}};
7631                         int etype = *p;
7632                         p ++;
7633
7634                         if (etype == 0x51)
7635                                 /* See Partition II, Appendix B3 */
7636                                 etype = MONO_TYPE_OBJECT;
7637                         type = MONO_TYPE_SZARRAY;
7638                         simple_type.type = etype;
7639                         tklass = mono_class_from_mono_type (&simple_type);
7640                         goto handle_enum;
7641                 } else if (subt == 0x55) {
7642                         char *n;
7643                         MonoType *t;
7644                         slen = mono_metadata_decode_value (p, &p);
7645                         n = g_memdup (p, slen + 1);
7646                         n [slen] = 0;
7647                         t = mono_reflection_type_from_name (n, image);
7648                         if (!t)
7649                                 g_error ("Cannot load type '%s'", n);
7650                         g_free (n);
7651                         p += slen;
7652                         subc = mono_class_from_mono_type (t);
7653                 } else if (subt >= MONO_TYPE_BOOLEAN && subt <= MONO_TYPE_R8) {
7654                         MonoType simple_type = {{0}};
7655                         simple_type.type = subt;
7656                         subc = mono_class_from_mono_type (&simple_type);
7657                 } else {
7658                         g_error ("Unknown type 0x%02x for object type encoding in custom attr", subt);
7659                 }
7660                 val = load_cattr_value (image, &subc->byval_arg, p, end);
7661                 obj = mono_object_new (mono_domain_get (), subc);
7662                 memcpy ((char*)obj + sizeof (MonoObject), val, mono_class_value_size (subc, NULL));
7663                 g_free (val);
7664                 return obj;
7665         }
7666         case MONO_TYPE_SZARRAY: {
7667                 MonoArray *arr;
7668                 guint32 i, alen, basetype;
7669                 alen = read32 (p);
7670                 p += 4;
7671                 if (alen == 0xffffffff) {
7672                         *end = p;
7673                         return NULL;
7674                 }
7675                 arr = mono_array_new (mono_domain_get(), tklass, alen);
7676                 basetype = tklass->byval_arg.type;
7677                 if (basetype == MONO_TYPE_VALUETYPE && tklass->enumtype)
7678                         basetype = mono_class_enum_basetype (tklass)->type;
7679                 switch (basetype)
7680                 {
7681                         case MONO_TYPE_U1:
7682                         case MONO_TYPE_I1:
7683                         case MONO_TYPE_BOOLEAN:
7684                                 for (i = 0; i < alen; i++) {
7685                                         MonoBoolean val = *p++;
7686                                         mono_array_set (arr, MonoBoolean, i, val);
7687                                 }
7688                                 break;
7689                         case MONO_TYPE_CHAR:
7690                         case MONO_TYPE_U2:
7691                         case MONO_TYPE_I2:
7692                                 for (i = 0; i < alen; i++) {
7693                                         guint16 val = read16 (p);
7694                                         mono_array_set (arr, guint16, i, val);
7695                                         p += 2;
7696                                 }
7697                                 break;
7698                         case MONO_TYPE_R4:
7699                         case MONO_TYPE_U4:
7700                         case MONO_TYPE_I4:
7701                                 for (i = 0; i < alen; i++) {
7702                                         guint32 val = read32 (p);
7703                                         mono_array_set (arr, guint32, i, val);
7704                                         p += 4;
7705                                 }
7706                                 break;
7707                         case MONO_TYPE_R8:
7708                                 for (i = 0; i < alen; i++) {
7709                                         double val;
7710                                         readr8 (p, &val);
7711                                         mono_array_set (arr, double, i, val);
7712                                         p += 8;
7713                                 }
7714                                 break;
7715                         case MONO_TYPE_U8:
7716                         case MONO_TYPE_I8:
7717                                 for (i = 0; i < alen; i++) {
7718                                         guint64 val = read64 (p);
7719                                         mono_array_set (arr, guint64, i, val);
7720                                         p += 8;
7721                                 }
7722                                 break;
7723                         case MONO_TYPE_CLASS:
7724                         case MONO_TYPE_OBJECT:
7725                         case MONO_TYPE_STRING:
7726                                 for (i = 0; i < alen; i++) {
7727                                         MonoObject *item = load_cattr_value (image, &tklass->byval_arg, p, &p);
7728                                         mono_array_setref (arr, i, item);
7729                                 }
7730                                 break;
7731                         default:
7732                                 g_error ("Type 0x%02x not handled in custom attr array decoding", basetype);
7733                 }
7734                 *end=p;
7735                 return arr;
7736         }
7737         default:
7738                 g_error ("Type 0x%02x not handled in custom attr value decoding", type);
7739         }
7740         return NULL;
7741 }
7742
7743 static MonoObject*
7744 create_cattr_typed_arg (MonoType *t, MonoObject *val)
7745 {
7746         static MonoClass *klass;
7747         static MonoMethod *ctor;
7748         MonoObject *retval;
7749         void *params [2], *unboxed;
7750
7751         if (!klass)
7752                 klass = mono_class_from_name (mono_defaults.corlib, "System.Reflection", "CustomAttributeTypedArgument");
7753         if (!ctor)
7754                 ctor = mono_class_get_method_from_name (klass, ".ctor", 2);
7755         
7756         params [0] = mono_type_get_object (mono_domain_get (), t);
7757         params [1] = val;
7758         retval = mono_object_new (mono_domain_get (), klass);
7759         unboxed = mono_object_unbox (retval);
7760         mono_runtime_invoke (ctor, unboxed, params, NULL);
7761
7762         return retval;
7763 }
7764
7765 static MonoObject*
7766 create_cattr_named_arg (void *minfo, MonoObject *typedarg)
7767 {
7768         static MonoClass *klass;
7769         static MonoMethod *ctor;
7770         MonoObject *retval;
7771         void *unboxed, *params [2];
7772
7773         if (!klass)
7774                 klass = mono_class_from_name (mono_defaults.corlib, "System.Reflection", "CustomAttributeNamedArgument");
7775         if (!ctor)
7776                 ctor = mono_class_get_method_from_name (klass, ".ctor", 2);
7777
7778         params [0] = minfo;
7779         params [1] = typedarg;
7780         retval = mono_object_new (mono_domain_get (), klass);
7781         unboxed = mono_object_unbox (retval);
7782         mono_runtime_invoke (ctor, unboxed, params, NULL);
7783
7784         return retval;
7785 }
7786
7787 static gboolean
7788 type_is_reference (MonoType *type)
7789 {
7790         switch (type->type) {
7791         case MONO_TYPE_BOOLEAN:
7792         case MONO_TYPE_CHAR:
7793         case MONO_TYPE_U:
7794         case MONO_TYPE_I:
7795         case MONO_TYPE_U1:
7796         case MONO_TYPE_I1:
7797         case MONO_TYPE_U2:
7798         case MONO_TYPE_I2:
7799         case MONO_TYPE_U4:
7800         case MONO_TYPE_I4:
7801         case MONO_TYPE_U8:
7802         case MONO_TYPE_I8:
7803         case MONO_TYPE_R8:
7804         case MONO_TYPE_R4:
7805         case MONO_TYPE_VALUETYPE:
7806                 return FALSE;
7807         default:
7808                 return TRUE;
7809         }
7810 }
7811
7812 static void
7813 free_param_data (MonoMethodSignature *sig, void **params) {
7814         int i;
7815         for (i = 0; i < sig->param_count; ++i) {
7816                 if (!type_is_reference (sig->params [i]))
7817                         g_free (params [i]);
7818         }
7819 }
7820
7821 /*
7822  * Find the field index in the metadata FieldDef table.
7823  */
7824 static guint32
7825 find_field_index (MonoClass *klass, MonoClassField *field) {
7826         int i;
7827
7828         for (i = 0; i < klass->field.count; ++i) {
7829                 if (field == &klass->fields [i])
7830                         return klass->field.first + 1 + i;
7831         }
7832         return 0;
7833 }
7834
7835 /*
7836  * Find the property index in the metadata Property table.
7837  */
7838 static guint32
7839 find_property_index (MonoClass *klass, MonoProperty *property) {
7840         int i;
7841
7842         for (i = 0; i < klass->ext->property.count; ++i) {
7843                 if (property == &klass->ext->properties [i])
7844                         return klass->ext->property.first + 1 + i;
7845         }
7846         return 0;
7847 }
7848
7849 /*
7850  * Find the event index in the metadata Event table.
7851  */
7852 static guint32
7853 find_event_index (MonoClass *klass, MonoEvent *event) {
7854         int i;
7855
7856         for (i = 0; i < klass->ext->event.count; ++i) {
7857                 if (event == &klass->ext->events [i])
7858                         return klass->ext->event.first + 1 + i;
7859         }
7860         return 0;
7861 }
7862
7863 static MonoObject*
7864 create_custom_attr (MonoImage *image, MonoMethod *method, const guchar *data, guint32 len)
7865 {
7866         const char *p = (const char*)data;
7867         const char *named;
7868         guint32 i, j, num_named;
7869         MonoObject *attr;
7870         void *params_buf [32];
7871         void **params;
7872         MonoMethodSignature *sig;
7873
7874         mono_class_init (method->klass);
7875
7876         if (len == 0) {
7877                 attr = mono_object_new (mono_domain_get (), method->klass);
7878                 mono_runtime_invoke (method, attr, NULL, NULL);
7879                 return attr;
7880         }
7881
7882         if (len < 2 || read16 (p) != 0x0001) /* Prolog */
7883                 return NULL;
7884
7885         /*g_print ("got attr %s\n", method->klass->name);*/
7886
7887         sig = mono_method_signature (method);
7888         if (sig->param_count < 32)
7889                 params = params_buf;
7890         else
7891                 /* Allocate using GC so it gets GC tracking */
7892                 params = mono_gc_alloc_fixed (sig->param_count * sizeof (void*), NULL);
7893
7894         /* skip prolog */
7895         p += 2;
7896         for (i = 0; i < mono_method_signature (method)->param_count; ++i) {
7897                 params [i] = load_cattr_value (image, mono_method_signature (method)->params [i], p, &p);
7898         }
7899
7900         named = p;
7901         attr = mono_object_new (mono_domain_get (), method->klass);
7902         mono_runtime_invoke (method, attr, params, NULL);
7903         free_param_data (method->signature, params);
7904         num_named = read16 (named);
7905         named += 2;
7906         for (j = 0; j < num_named; j++) {
7907                 gint name_len;
7908                 char *name, named_type, data_type;
7909                 named_type = *named++;
7910                 data_type = *named++; /* type of data */
7911                 if (data_type == MONO_TYPE_SZARRAY)
7912                         data_type = *named++;
7913                 if (data_type == MONO_TYPE_ENUM) {
7914                         gint type_len;
7915                         char *type_name;
7916                         type_len = mono_metadata_decode_blob_size (named, &named);
7917                         type_name = g_malloc (type_len + 1);
7918                         memcpy (type_name, named, type_len);
7919                         type_name [type_len] = 0;
7920                         named += type_len;
7921                         /* FIXME: lookup the type and check type consistency */
7922                         g_free (type_name);
7923                 }
7924                 name_len = mono_metadata_decode_blob_size (named, &named);
7925                 name = g_malloc (name_len + 1);
7926                 memcpy (name, named, name_len);
7927                 name [name_len] = 0;
7928                 named += name_len;
7929                 if (named_type == 0x53) {
7930                         MonoClassField *field = mono_class_get_field_from_name (mono_object_class (attr), name);
7931                         void *val = load_cattr_value (image, field->type, named, &named);
7932                         mono_field_set_value (attr, field, val);
7933                         if (!type_is_reference (field->type))
7934                                 g_free (val);
7935                 } else if (named_type == 0x54) {
7936                         MonoProperty *prop;
7937                         void *pparams [1];
7938                         MonoType *prop_type;
7939
7940                         prop = mono_class_get_property_from_name (mono_object_class (attr), name);
7941                         /* can we have more that 1 arg in a custom attr named property? */
7942                         prop_type = prop->get? mono_method_signature (prop->get)->ret :
7943                              mono_method_signature (prop->set)->params [mono_method_signature (prop->set)->param_count - 1];
7944                         pparams [0] = load_cattr_value (image, prop_type, named, &named);
7945                         mono_property_set_value (prop, attr, pparams, NULL);
7946                         if (!type_is_reference (prop_type))
7947                                 g_free (pparams [0]);
7948                 }
7949                 g_free (name);
7950         }
7951
7952         if (params != params_buf)
7953                 mono_gc_free_fixed (params);
7954
7955         return attr;
7956 }
7957
7958 static MonoObject*
7959 create_custom_attr_data (MonoImage *image, MonoMethod *method, const guchar *data, guint32 len)
7960 {
7961         MonoArray *typedargs, *namedargs;
7962         MonoClass *attrklass;
7963         static MonoMethod *ctor;
7964         MonoDomain *domain;
7965         MonoObject *attr;
7966         const char *p = (const char*)data;
7967         const char *named;
7968         guint32 i, j, num_named;
7969         void *params [3];
7970
7971         mono_class_init (method->klass);
7972
7973         if (!ctor)
7974                 ctor = mono_class_get_method_from_name (mono_defaults.customattribute_data_class, ".ctor", 3);
7975
7976         domain = mono_domain_get ();
7977         if (len == 0) {
7978                 /* This is for Attributes with no parameters */
7979                 attr = mono_object_new (domain, mono_defaults.customattribute_data_class);
7980                 params [0] = mono_method_get_object (domain, method, NULL);
7981                 params [1] = params [2] = NULL;
7982                 mono_runtime_invoke (method, attr, params, NULL);
7983                 return attr;
7984         }
7985
7986         if (len < 2 || read16 (p) != 0x0001) /* Prolog */
7987                 return NULL;
7988
7989         typedargs = mono_array_new (domain, mono_get_object_class (), mono_method_signature (method)->param_count);
7990         
7991         /* skip prolog */
7992         p += 2;
7993         for (i = 0; i < mono_method_signature (method)->param_count; ++i) {
7994                 MonoObject *obj, *typedarg;
7995                 void *val;
7996
7997                 val = load_cattr_value (image, mono_method_signature (method)->params [i], p, &p);
7998                 obj = type_is_reference (mono_method_signature (method)->params [i]) ? 
7999                         val : mono_value_box (domain, mono_class_from_mono_type (mono_method_signature (method)->params [i]), val);
8000                 typedarg = create_cattr_typed_arg (mono_method_signature (method)->params [i], obj);
8001                 mono_array_setref (typedargs, i, typedarg);
8002
8003                 if (!type_is_reference (mono_method_signature (method)->params [i]))
8004                         g_free (val);
8005         }
8006
8007         named = p;
8008         num_named = read16 (named);
8009         namedargs = mono_array_new (domain, mono_get_object_class (), num_named);
8010         named += 2;
8011         attrklass = method->klass;
8012         for (j = 0; j < num_named; j++) {
8013                 gint name_len;
8014                 char *name, named_type, data_type;
8015                 named_type = *named++;
8016                 data_type = *named++; /* type of data */
8017                 if (data_type == MONO_TYPE_SZARRAY)
8018                         data_type = *named++;
8019                 if (data_type == MONO_TYPE_ENUM) {
8020                         gint type_len;
8021                         char *type_name;
8022                         type_len = mono_metadata_decode_blob_size (named, &named);
8023                         type_name = g_malloc (type_len + 1);
8024                         memcpy (type_name, named, type_len);
8025                         type_name [type_len] = 0;
8026                         named += type_len;
8027                         /* FIXME: lookup the type and check type consistency */
8028                         g_free (type_name);
8029                 }
8030                 name_len = mono_metadata_decode_blob_size (named, &named);
8031                 name = g_malloc (name_len + 1);
8032                 memcpy (name, named, name_len);
8033                 name [name_len] = 0;
8034                 named += name_len;
8035                 if (named_type == 0x53) {
8036                         MonoObject *obj, *typedarg, *namedarg;
8037                         MonoClassField *field = mono_class_get_field_from_name (attrklass, name);
8038                         void *minfo, *val = load_cattr_value (image, field->type, named, &named);
8039                         
8040                         minfo = mono_field_get_object (domain, NULL, field);
8041                         obj = type_is_reference (field->type) ? val : mono_value_box (domain, mono_class_from_mono_type (field->type), val);
8042                         typedarg = create_cattr_typed_arg (field->type, obj);
8043                         namedarg = create_cattr_named_arg (minfo, typedarg);
8044                         mono_array_setref (namedargs, j, namedarg);
8045                         if (!type_is_reference (field->type))
8046                                 g_free (val);
8047                 } else if (named_type == 0x54) {
8048                         MonoObject *obj, *typedarg, *namedarg;
8049                         MonoType *prop_type;
8050                         void *val, *minfo;
8051                         MonoProperty *prop = mono_class_get_property_from_name (attrklass, name);
8052
8053                         prop_type = prop->get? mono_method_signature (prop->get)->ret :
8054                              mono_method_signature (prop->set)->params [mono_method_signature (prop->set)->param_count - 1];
8055                         minfo =  mono_property_get_object (domain, NULL, prop);
8056                         val = load_cattr_value (image, prop_type, named, &named);
8057                         obj = type_is_reference (prop_type) ? val : mono_value_box (domain, mono_class_from_mono_type (prop_type), val);
8058                         typedarg = create_cattr_typed_arg (prop_type, obj);
8059                         namedarg = create_cattr_named_arg (minfo, typedarg);
8060                         mono_array_setref (namedargs, j, namedarg);
8061                         if (!type_is_reference (prop_type))
8062                                 g_free (val);
8063                 }
8064                 g_free (name);
8065         }
8066         attr = mono_object_new (domain, mono_defaults.customattribute_data_class);
8067         params [0] = mono_method_get_object (domain, method, NULL);
8068         params [1] = typedargs;
8069         params [2] = namedargs;
8070         mono_runtime_invoke (ctor, attr, params, NULL);
8071         return attr;
8072 }
8073
8074 MonoArray*
8075 mono_custom_attrs_construct (MonoCustomAttrInfo *cinfo)
8076 {
8077         MonoArray *result;
8078         MonoObject *attr;
8079         int i;
8080
8081         result = mono_array_new_cached (mono_domain_get (), mono_defaults.attribute_class, cinfo->num_attrs);
8082         for (i = 0; i < cinfo->num_attrs; ++i) {
8083                 if (!cinfo->attrs [i].ctor)
8084                         /* The cattr type is not finished yet */
8085                         /* We should include the type name but cinfo doesn't contain it */
8086                         mono_raise_exception (mono_get_exception_type_load (NULL, NULL));
8087                 attr = create_custom_attr (cinfo->image, cinfo->attrs [i].ctor, cinfo->attrs [i].data, cinfo->attrs [i].data_size);
8088                 mono_array_setref (result, i, attr);
8089         }
8090         return result;
8091 }
8092
8093 static MonoArray*
8094 mono_custom_attrs_construct_by_type (MonoCustomAttrInfo *cinfo, MonoClass *attr_klass)
8095 {
8096         MonoArray *result;
8097         MonoObject *attr;
8098         int i, n;
8099
8100         n = 0;
8101         for (i = 0; i < cinfo->num_attrs; ++i) {
8102                 if (mono_class_is_assignable_from (attr_klass, cinfo->attrs [i].ctor->klass))
8103                         n ++;
8104         }
8105
8106         result = mono_array_new_cached (mono_domain_get (), mono_defaults.attribute_class, n);
8107         n = 0;
8108         for (i = 0; i < cinfo->num_attrs; ++i) {
8109                 if (mono_class_is_assignable_from (attr_klass, cinfo->attrs [i].ctor->klass)) {
8110                         attr = create_custom_attr (cinfo->image, cinfo->attrs [i].ctor, cinfo->attrs [i].data, cinfo->attrs [i].data_size);
8111                         mono_array_setref (result, n, attr);
8112                         n ++;
8113                 }
8114         }
8115         return result;
8116 }
8117
8118 static MonoArray*
8119 mono_custom_attrs_data_construct (MonoCustomAttrInfo *cinfo)
8120 {
8121         MonoArray *result;
8122         MonoObject *attr;
8123         int i;
8124         
8125         result = mono_array_new (mono_domain_get (), mono_defaults.customattribute_data_class, cinfo->num_attrs);
8126         for (i = 0; i < cinfo->num_attrs; ++i) {
8127                 attr = create_custom_attr_data (cinfo->image, cinfo->attrs [i].ctor, cinfo->attrs [i].data, cinfo->attrs [i].data_size);
8128                 mono_array_setref (result, i, attr);
8129         }
8130         return result;
8131 }
8132
8133 /**
8134  * mono_custom_attrs_from_index:
8135  *
8136  * Returns: NULL if no attributes are found or if a loading error occurs.
8137  */
8138 MonoCustomAttrInfo*
8139 mono_custom_attrs_from_index (MonoImage *image, guint32 idx)
8140 {
8141         guint32 mtoken, i, len;
8142         guint32 cols [MONO_CUSTOM_ATTR_SIZE];
8143         MonoTableInfo *ca;
8144         MonoCustomAttrInfo *ainfo;
8145         GList *tmp, *list = NULL;
8146         const char *data;
8147
8148         ca = &image->tables [MONO_TABLE_CUSTOMATTRIBUTE];
8149
8150         i = mono_metadata_custom_attrs_from_index (image, idx);
8151         if (!i)
8152                 return NULL;
8153         i --;
8154         while (i < ca->rows) {
8155                 if (mono_metadata_decode_row_col (ca, i, MONO_CUSTOM_ATTR_PARENT) != idx)
8156                         break;
8157                 list = g_list_prepend (list, GUINT_TO_POINTER (i));
8158                 ++i;
8159         }
8160         len = g_list_length (list);
8161         if (!len)
8162                 return NULL;
8163         ainfo = g_malloc0 (MONO_SIZEOF_CUSTOM_ATTR_INFO + sizeof (MonoCustomAttrEntry) * len);
8164         ainfo->num_attrs = len;
8165         ainfo->image = image;
8166         for (i = 0, tmp = list; i < len; ++i, tmp = tmp->next) {
8167                 mono_metadata_decode_row (ca, GPOINTER_TO_UINT (tmp->data), cols, MONO_CUSTOM_ATTR_SIZE);
8168                 mtoken = cols [MONO_CUSTOM_ATTR_TYPE] >> MONO_CUSTOM_ATTR_TYPE_BITS;
8169                 switch (cols [MONO_CUSTOM_ATTR_TYPE] & MONO_CUSTOM_ATTR_TYPE_MASK) {
8170                 case MONO_CUSTOM_ATTR_TYPE_METHODDEF:
8171                         mtoken |= MONO_TOKEN_METHOD_DEF;
8172                         break;
8173                 case MONO_CUSTOM_ATTR_TYPE_MEMBERREF:
8174                         mtoken |= MONO_TOKEN_MEMBER_REF;
8175                         break;
8176                 default:
8177                         g_error ("Unknown table for custom attr type %08x", cols [MONO_CUSTOM_ATTR_TYPE]);
8178                         break;
8179                 }
8180                 ainfo->attrs [i].ctor = mono_get_method (image, mtoken, NULL);
8181                 if (!ainfo->attrs [i].ctor) {
8182                         g_warning ("Can't find custom attr constructor image: %s mtoken: 0x%08x", image->name, mtoken);
8183                         g_list_free (list);
8184                         g_free (ainfo);
8185                         return NULL;
8186                 }
8187                 data = mono_metadata_blob_heap (image, cols [MONO_CUSTOM_ATTR_VALUE]);
8188                 ainfo->attrs [i].data_size = mono_metadata_decode_value (data, &data);
8189                 ainfo->attrs [i].data = (guchar*)data;
8190         }
8191         g_list_free (list);
8192
8193         return ainfo;
8194 }
8195
8196 MonoCustomAttrInfo*
8197 mono_custom_attrs_from_method (MonoMethod *method)
8198 {
8199         guint32 idx;
8200
8201         /*
8202          * An instantiated method has the same cattrs as the generic method definition.
8203          *
8204          * LAMESPEC: The .NET SRE throws an exception for instantiations of generic method builders
8205          *           Note that this stanza is not necessary for non-SRE types, but it's a micro-optimization
8206          */
8207         if (method->is_inflated)
8208                 method = ((MonoMethodInflated *) method)->declaring;
8209         
8210         if (method->dynamic || method->klass->image->dynamic)
8211                 return lookup_custom_attr (method->klass->image, method);
8212
8213         if (!method->token)
8214                 /* Synthetic methods */
8215                 return NULL;
8216
8217         idx = mono_method_get_index (method);
8218         idx <<= MONO_CUSTOM_ATTR_BITS;
8219         idx |= MONO_CUSTOM_ATTR_METHODDEF;
8220         return mono_custom_attrs_from_index (method->klass->image, idx);
8221 }
8222
8223 MonoCustomAttrInfo*
8224 mono_custom_attrs_from_class (MonoClass *klass)
8225 {
8226         guint32 idx;
8227
8228         if (klass->generic_class)
8229                 klass = klass->generic_class->container_class;
8230
8231         if (klass->image->dynamic)
8232                 return lookup_custom_attr (klass->image, klass);
8233
8234         if (klass->byval_arg.type == MONO_TYPE_VAR || klass->byval_arg.type == MONO_TYPE_MVAR) {
8235                 idx = mono_metadata_token_index (klass->sizes.generic_param_token);
8236                 idx <<= MONO_CUSTOM_ATTR_BITS;
8237                 idx |= MONO_CUSTOM_ATTR_GENERICPAR;
8238         } else {
8239                 idx = mono_metadata_token_index (klass->type_token);
8240                 idx <<= MONO_CUSTOM_ATTR_BITS;
8241                 idx |= MONO_CUSTOM_ATTR_TYPEDEF;
8242         }
8243         return mono_custom_attrs_from_index (klass->image, idx);
8244 }
8245
8246 MonoCustomAttrInfo*
8247 mono_custom_attrs_from_assembly (MonoAssembly *assembly)
8248 {
8249         guint32 idx;
8250         
8251         if (assembly->image->dynamic)
8252                 return lookup_custom_attr (assembly->image, assembly);
8253         idx = 1; /* there is only one assembly */
8254         idx <<= MONO_CUSTOM_ATTR_BITS;
8255         idx |= MONO_CUSTOM_ATTR_ASSEMBLY;
8256         return mono_custom_attrs_from_index (assembly->image, idx);
8257 }
8258
8259 static MonoCustomAttrInfo*
8260 mono_custom_attrs_from_module (MonoImage *image)
8261 {
8262         guint32 idx;
8263         
8264         if (image->dynamic)
8265                 return lookup_custom_attr (image, image);
8266         idx = 1; /* there is only one module */
8267         idx <<= MONO_CUSTOM_ATTR_BITS;
8268         idx |= MONO_CUSTOM_ATTR_MODULE;
8269         return mono_custom_attrs_from_index (image, idx);
8270 }
8271
8272 MonoCustomAttrInfo*
8273 mono_custom_attrs_from_property (MonoClass *klass, MonoProperty *property)
8274 {
8275         guint32 idx;
8276         
8277         if (klass->image->dynamic) {
8278                 property = mono_metadata_get_corresponding_property_from_generic_type_definition (property);
8279                 return lookup_custom_attr (klass->image, property);
8280         }
8281         idx = find_property_index (klass, property);
8282         idx <<= MONO_CUSTOM_ATTR_BITS;
8283         idx |= MONO_CUSTOM_ATTR_PROPERTY;
8284         return mono_custom_attrs_from_index (klass->image, idx);
8285 }
8286
8287 MonoCustomAttrInfo*
8288 mono_custom_attrs_from_event (MonoClass *klass, MonoEvent *event)
8289 {
8290         guint32 idx;
8291         
8292         if (klass->image->dynamic) {
8293                 event = mono_metadata_get_corresponding_event_from_generic_type_definition (event);
8294                 return lookup_custom_attr (klass->image, event);
8295         }
8296         idx = find_event_index (klass, event);
8297         idx <<= MONO_CUSTOM_ATTR_BITS;
8298         idx |= MONO_CUSTOM_ATTR_EVENT;
8299         return mono_custom_attrs_from_index (klass->image, idx);
8300 }
8301
8302 MonoCustomAttrInfo*
8303 mono_custom_attrs_from_field (MonoClass *klass, MonoClassField *field)
8304 {
8305         guint32 idx;
8306         if (klass->image->dynamic) {
8307                 field = mono_metadata_get_corresponding_field_from_generic_type_definition (field);
8308                 return lookup_custom_attr (klass->image, field);
8309         }
8310         idx = find_field_index (klass, field);
8311         idx <<= MONO_CUSTOM_ATTR_BITS;
8312         idx |= MONO_CUSTOM_ATTR_FIELDDEF;
8313         return mono_custom_attrs_from_index (klass->image, idx);
8314 }
8315
8316 MonoCustomAttrInfo*
8317 mono_custom_attrs_from_param (MonoMethod *method, guint32 param)
8318 {
8319         MonoTableInfo *ca;
8320         guint32 i, idx, method_index;
8321         guint32 param_list, param_last, param_pos, found;
8322         MonoImage *image;
8323         MonoReflectionMethodAux *aux;
8324
8325         /*
8326          * An instantiated method has the same cattrs as the generic method definition.
8327          *
8328          * LAMESPEC: The .NET SRE throws an exception for instantiations of generic method builders
8329          *           Note that this stanza is not necessary for non-SRE types, but it's a micro-optimization
8330          */
8331         if (method->is_inflated)
8332                 method = ((MonoMethodInflated *) method)->declaring;
8333
8334         if (method->klass->image->dynamic) {
8335                 MonoCustomAttrInfo *res, *ainfo;
8336                 int size;
8337
8338                 aux = g_hash_table_lookup (((MonoDynamicImage*)method->klass->image)->method_aux_hash, method);
8339                 if (!aux || !aux->param_cattr)
8340                         return NULL;
8341
8342                 /* Need to copy since it will be freed later */
8343                 ainfo = aux->param_cattr [param];
8344                 size = MONO_SIZEOF_CUSTOM_ATTR_INFO + sizeof (MonoCustomAttrEntry) * ainfo->num_attrs;
8345                 res = g_malloc0 (size);
8346                 memcpy (res, ainfo, size);
8347                 return res;
8348         }
8349
8350         image = method->klass->image;
8351         method_index = mono_method_get_index (method);
8352         ca = &image->tables [MONO_TABLE_METHOD];
8353
8354         param_list = mono_metadata_decode_row_col (ca, method_index - 1, MONO_METHOD_PARAMLIST);
8355         if (method_index == ca->rows) {
8356                 ca = &image->tables [MONO_TABLE_PARAM];
8357                 param_last = ca->rows + 1;
8358         } else {
8359                 param_last = mono_metadata_decode_row_col (ca, method_index, MONO_METHOD_PARAMLIST);
8360                 ca = &image->tables [MONO_TABLE_PARAM];
8361         }
8362         found = FALSE;
8363         for (i = param_list; i < param_last; ++i) {
8364                 param_pos = mono_metadata_decode_row_col (ca, i - 1, MONO_PARAM_SEQUENCE);
8365                 if (param_pos == param) {
8366                         found = TRUE;
8367                         break;
8368                 }
8369         }
8370         if (!found)
8371                 return NULL;
8372         idx = i;
8373         idx <<= MONO_CUSTOM_ATTR_BITS;
8374         idx |= MONO_CUSTOM_ATTR_PARAMDEF;
8375         return mono_custom_attrs_from_index (image, idx);
8376 }
8377
8378 gboolean
8379 mono_custom_attrs_has_attr (MonoCustomAttrInfo *ainfo, MonoClass *attr_klass)
8380 {
8381         int i;
8382         MonoClass *klass;
8383         for (i = 0; i < ainfo->num_attrs; ++i) {
8384                 klass = ainfo->attrs [i].ctor->klass;
8385                 if (mono_class_has_parent (klass, attr_klass) || (MONO_CLASS_IS_INTERFACE (attr_klass) && mono_class_is_assignable_from (attr_klass, klass)))
8386                         return TRUE;
8387         }
8388         return FALSE;
8389 }
8390
8391 MonoObject*
8392 mono_custom_attrs_get_attr (MonoCustomAttrInfo *ainfo, MonoClass *attr_klass)
8393 {
8394         int i, attr_index;
8395         MonoClass *klass;
8396         MonoArray *attrs;
8397
8398         attr_index = -1;
8399         for (i = 0; i < ainfo->num_attrs; ++i) {
8400                 klass = ainfo->attrs [i].ctor->klass;
8401                 if (mono_class_has_parent (klass, attr_klass)) {
8402                         attr_index = i;
8403                         break;
8404                 }
8405         }
8406         if (attr_index == -1)
8407                 return NULL;
8408
8409         attrs = mono_custom_attrs_construct (ainfo);
8410         if (attrs)
8411                 return mono_array_get (attrs, MonoObject*, attr_index);
8412         else
8413                 return NULL;
8414 }
8415
8416 /*
8417  * mono_reflection_get_custom_attrs_info:
8418  * @obj: a reflection object handle
8419  *
8420  * Return the custom attribute info for attributes defined for the
8421  * reflection handle @obj. The objects.
8422  *
8423  * FIXME this function leaks like a sieve for SRE objects.
8424  */
8425 MonoCustomAttrInfo*
8426 mono_reflection_get_custom_attrs_info (MonoObject *obj)
8427 {
8428         MonoClass *klass;
8429         MonoCustomAttrInfo *cinfo = NULL;
8430         
8431         klass = obj->vtable->klass;
8432         if (klass == mono_defaults.monotype_class) {
8433                 MonoType *type = mono_reflection_type_get_handle ((MonoReflectionType *)obj);
8434                 klass = mono_class_from_mono_type (type);
8435                 cinfo = mono_custom_attrs_from_class (klass);
8436         } else if (strcmp ("Assembly", klass->name) == 0) {
8437                 MonoReflectionAssembly *rassembly = (MonoReflectionAssembly*)obj;
8438                 cinfo = mono_custom_attrs_from_assembly (rassembly->assembly);
8439         } else if (strcmp ("Module", klass->name) == 0) {
8440                 MonoReflectionModule *module = (MonoReflectionModule*)obj;
8441                 cinfo = mono_custom_attrs_from_module (module->image);
8442         } else if (strcmp ("MonoProperty", klass->name) == 0) {
8443                 MonoReflectionProperty *rprop = (MonoReflectionProperty*)obj;
8444                 cinfo = mono_custom_attrs_from_property (rprop->property->parent, rprop->property);
8445         } else if (strcmp ("MonoEvent", klass->name) == 0) {
8446                 MonoReflectionMonoEvent *revent = (MonoReflectionMonoEvent*)obj;
8447                 cinfo = mono_custom_attrs_from_event (revent->event->parent, revent->event);
8448         } else if (strcmp ("MonoField", klass->name) == 0) {
8449                 MonoReflectionField *rfield = (MonoReflectionField*)obj;
8450                 cinfo = mono_custom_attrs_from_field (rfield->field->parent, rfield->field);
8451         } else if ((strcmp ("MonoMethod", klass->name) == 0) || (strcmp ("MonoCMethod", klass->name) == 0)) {
8452                 MonoReflectionMethod *rmethod = (MonoReflectionMethod*)obj;
8453                 cinfo = mono_custom_attrs_from_method (rmethod->method);
8454         } else if ((strcmp ("MonoGenericMethod", klass->name) == 0) || (strcmp ("MonoGenericCMethod", klass->name) == 0)) {
8455                 MonoReflectionMethod *rmethod = (MonoReflectionMethod*)obj;
8456                 cinfo = mono_custom_attrs_from_method (rmethod->method);
8457         } else if (strcmp ("ParameterInfo", klass->name) == 0) {
8458                 MonoReflectionParameter *param = (MonoReflectionParameter*)obj;
8459                 MonoReflectionMethod *rmethod = (MonoReflectionMethod*)param->MemberImpl;
8460                 cinfo = mono_custom_attrs_from_param (rmethod->method, param->PositionImpl + 1);
8461         } else if (strcmp ("AssemblyBuilder", klass->name) == 0) {
8462                 MonoReflectionAssemblyBuilder *assemblyb = (MonoReflectionAssemblyBuilder*)obj;
8463                 cinfo = mono_custom_attrs_from_builders (NULL, assemblyb->assembly.assembly->image, assemblyb->cattrs);
8464         } else if (strcmp ("TypeBuilder", klass->name) == 0) {
8465                 MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder*)obj;
8466                 cinfo = mono_custom_attrs_from_builders (NULL, &tb->module->dynamic_image->image, tb->cattrs);
8467         } else if (strcmp ("ModuleBuilder", klass->name) == 0) {
8468                 MonoReflectionModuleBuilder *mb = (MonoReflectionModuleBuilder*)obj;
8469                 cinfo = mono_custom_attrs_from_builders (NULL, &mb->dynamic_image->image, mb->cattrs);
8470         } else if (strcmp ("ConstructorBuilder", klass->name) == 0) {
8471                 MonoReflectionCtorBuilder *cb = (MonoReflectionCtorBuilder*)obj;
8472                 cinfo = mono_custom_attrs_from_builders (NULL, cb->mhandle->klass->image, cb->cattrs);
8473         } else if (strcmp ("MethodBuilder", klass->name) == 0) {
8474                 MonoReflectionMethodBuilder *mb = (MonoReflectionMethodBuilder*)obj;
8475                 cinfo = mono_custom_attrs_from_builders (NULL, mb->mhandle->klass->image, mb->cattrs);
8476         } else if (strcmp ("FieldBuilder", klass->name) == 0) {
8477                 MonoReflectionFieldBuilder *fb = (MonoReflectionFieldBuilder*)obj;
8478                 cinfo = mono_custom_attrs_from_builders (NULL, &((MonoReflectionTypeBuilder*)fb->typeb)->module->dynamic_image->image, fb->cattrs);
8479         } else if (strcmp ("MonoGenericClass", klass->name) == 0) {
8480                 MonoReflectionGenericClass *gclass = (MonoReflectionGenericClass*)obj;
8481                 cinfo = mono_reflection_get_custom_attrs_info ((MonoObject*)gclass->generic_type);
8482         } else { /* handle other types here... */
8483                 g_error ("get custom attrs not yet supported for %s", klass->name);
8484         }
8485
8486         return cinfo;
8487 }
8488
8489 /*
8490  * mono_reflection_get_custom_attrs_by_type:
8491  * @obj: a reflection object handle
8492  *
8493  * Return an array with all the custom attributes defined of the
8494  * reflection handle @obj. If @attr_klass is non-NULL, only custom attributes 
8495  * of that type are returned. The objects are fully build. Return NULL if a loading error
8496  * occurs.
8497  */
8498 MonoArray*
8499 mono_reflection_get_custom_attrs_by_type (MonoObject *obj, MonoClass *attr_klass)
8500 {
8501         MonoArray *result;
8502         MonoCustomAttrInfo *cinfo;
8503
8504         cinfo = mono_reflection_get_custom_attrs_info (obj);
8505         if (cinfo) {
8506                 if (attr_klass)
8507                         result = mono_custom_attrs_construct_by_type (cinfo, attr_klass);
8508                 else
8509                         result = mono_custom_attrs_construct (cinfo);
8510                 if (!cinfo->cached)
8511                         mono_custom_attrs_free (cinfo);
8512         } else {
8513                 if (mono_loader_get_last_error ())
8514                         return NULL;
8515                 result = mono_array_new_cached (mono_domain_get (), mono_defaults.attribute_class, 0);
8516         }
8517
8518         return result;
8519 }
8520
8521 /*
8522  * mono_reflection_get_custom_attrs:
8523  * @obj: a reflection object handle
8524  *
8525  * Return an array with all the custom attributes defined of the
8526  * reflection handle @obj. The objects are fully build. Return NULL if a loading error
8527  * occurs.
8528  */
8529 MonoArray*
8530 mono_reflection_get_custom_attrs (MonoObject *obj)
8531 {
8532         return mono_reflection_get_custom_attrs_by_type (obj, NULL);
8533 }
8534
8535 /*
8536  * mono_reflection_get_custom_attrs_data:
8537  * @obj: a reflection obj handle
8538  *
8539  * Returns an array of System.Reflection.CustomAttributeData,
8540  * which include information about attributes reflected on
8541  * types loaded using the Reflection Only methods
8542  */
8543 MonoArray*
8544 mono_reflection_get_custom_attrs_data (MonoObject *obj)
8545 {
8546         MonoArray *result;
8547         MonoCustomAttrInfo *cinfo;
8548
8549         cinfo = mono_reflection_get_custom_attrs_info (obj);
8550         if (cinfo) {
8551                 result = mono_custom_attrs_data_construct (cinfo);
8552                 if (!cinfo->cached)
8553                         mono_custom_attrs_free (cinfo);
8554         } else
8555                 result = mono_array_new (mono_domain_get (), mono_defaults.customattribute_data_class, 0);
8556
8557         return result;
8558 }
8559
8560 static MonoReflectionType*
8561 mono_reflection_type_get_underlying_system_type (MonoReflectionType* t)
8562 {
8563         MonoMethod *method_get_underlying_system_type;
8564
8565         method_get_underlying_system_type = mono_object_get_virtual_method ((MonoObject *) t,
8566                                                                             mono_class_get_method_from_name (mono_object_class (t),
8567                                                                                                              "get_UnderlyingSystemType",
8568                                                                                                              0));
8569         return (MonoReflectionType *) mono_runtime_invoke (method_get_underlying_system_type, t, NULL, NULL);
8570 }
8571
8572 #ifndef DISABLE_REFLECTION_EMIT
8573
8574 static gboolean
8575 is_corlib_type (MonoClass *class)
8576 {
8577         return class->image == mono_defaults.corlib;
8578 }
8579
8580 static gboolean
8581 is_usertype (MonoReflectionType *ref)
8582 {
8583         MonoClass *class = mono_object_class (ref);
8584         return class->image != mono_defaults.corlib || strcmp ("TypeDelegator", class->name) == 0;
8585 }
8586
8587 #define check_corlib_type_cached(_class, _namespace, _name) do { \
8588         static MonoClass *cached_class; \
8589         if (cached_class) \
8590                 return cached_class == _class; \
8591         if (is_corlib_type (_class) && !strcmp (_name, _class->name) && !strcmp (_namespace, _class->name_space)) { \
8592                 cached_class = _class; \
8593                 return TRUE; \
8594         } \
8595         return FALSE; \
8596 } while (0) \
8597
8598 static gboolean
8599 is_sre_array (MonoClass *class)
8600 {
8601         check_corlib_type_cached (class, "System.Reflection.Emit", "ArrayType");
8602 }
8603
8604 static gboolean
8605 is_sre_byref (MonoClass *class)
8606 {
8607         check_corlib_type_cached (class, "System.Reflection.Emit", "ByRefType");
8608 }
8609
8610 static gboolean
8611 is_sre_pointer (MonoClass *class)
8612 {
8613         check_corlib_type_cached (class, "System.Reflection.Emit", "PointerType");
8614 }
8615
8616 static gboolean
8617 is_sre_generic_instance (MonoClass *class)
8618 {
8619         check_corlib_type_cached (class, "System.Reflection", "MonoGenericClass");
8620 }
8621
8622 MonoType*
8623 mono_reflection_type_get_handle (MonoReflectionType* ref)
8624 {
8625         MonoClass *class;
8626         if (!ref)
8627                 return NULL;
8628         if (ref->type)
8629                 return ref->type;
8630
8631         if (is_usertype (ref)) {
8632                 ref = mono_reflection_type_get_underlying_system_type (ref);
8633                 g_assert (!is_usertype (ref)); /*FIXME fail better*/
8634                 if (ref->type)
8635                         return ref->type;
8636         }
8637
8638         class = mono_object_class (ref);
8639
8640         if (is_sre_array (class)) {
8641                 MonoType *res;
8642                 MonoReflectionArrayType *sre_array = (MonoReflectionArrayType*)ref;
8643                 MonoType *base = mono_reflection_type_get_handle (sre_array->element_type);
8644                 g_assert (base);
8645                 if (sre_array->rank == 0) //single dimentional array
8646                         res = &mono_array_class_get (mono_class_from_mono_type (base), 1)->byval_arg;
8647                 else
8648                         res = &mono_bounded_array_class_get (mono_class_from_mono_type (base), sre_array->rank, TRUE)->byval_arg;
8649                 sre_array->type.type = res;
8650                 return res;
8651         } else if (is_sre_byref (class)) {
8652                 MonoType *res;
8653                 MonoReflectionDerivedType *sre_byref = (MonoReflectionDerivedType*)ref;
8654                 MonoType *base = mono_reflection_type_get_handle (sre_byref->element_type);
8655                 g_assert (base);
8656                 res = &mono_class_from_mono_type (base)->this_arg;
8657                 sre_byref->type.type = res;
8658                 return res;
8659         } else if (is_sre_pointer (class)) {
8660                 MonoType *res;
8661                 MonoReflectionDerivedType *sre_pointer = (MonoReflectionDerivedType*)ref;
8662                 MonoType *base = mono_reflection_type_get_handle (sre_pointer->element_type);
8663                 g_assert (base);
8664                 res = &mono_ptr_class_get (base)->byval_arg;
8665                 sre_pointer->type.type = res;
8666                 return res;
8667         } else if (is_sre_generic_instance (class)) {
8668                 MonoType *res, **types;
8669                 MonoReflectionGenericClass *gclass = (MonoReflectionGenericClass*)ref;
8670                 int i, count;
8671
8672                 count = mono_array_length (gclass->type_arguments);
8673                 types = g_new0 (MonoType*, count);
8674                 for (i = 0; i < count; ++i) {
8675                         MonoReflectionType *t = mono_array_get (gclass->type_arguments, gpointer, i);
8676                         types [i] = mono_reflection_type_get_handle (t);
8677                 }
8678
8679                 res = mono_reflection_bind_generic_parameters ((MonoReflectionType*)gclass->generic_type, count, types);
8680                 g_free (types);
8681                 g_assert (res);
8682                 gclass->type.type = res;
8683                 return res;
8684         }
8685
8686         g_error ("Cannot handle corlib user type %s", mono_type_full_name (&mono_object_class(ref)->byval_arg));
8687         return NULL;
8688 }
8689
8690 static MonoReflectionType*
8691 mono_reflection_type_resolve_user_types (MonoReflectionType *type)
8692 {
8693         if (!type || type->type)
8694                 return type;
8695
8696         if (is_usertype (type)) {
8697                 type = mono_reflection_type_get_underlying_system_type (type);
8698                 if (is_usertype (type))
8699                         mono_raise_exception (mono_get_exception_not_supported ("User defined subclasses of System.Type are not yet supported22"));
8700         }
8701
8702         return type;
8703 }
8704
8705 void
8706 mono_reflection_create_unmanaged_type (MonoReflectionType *type)
8707 {
8708         mono_reflection_type_get_handle (type);
8709 }
8710
8711 /**
8712  * LOCKING: Assumes the loader lock is held.
8713  */
8714 static MonoMethodSignature*
8715 parameters_to_signature (MonoImage *image, MonoArray *parameters) {
8716         MonoMethodSignature *sig;
8717         int count, i;
8718
8719         count = parameters? mono_array_length (parameters): 0;
8720
8721         sig = image_g_malloc0 (image, MONO_SIZEOF_METHOD_SIGNATURE + sizeof (MonoType*) * count);
8722         sig->param_count = count;
8723         sig->sentinelpos = -1; /* FIXME */
8724         for (i = 0; i < count; ++i)
8725                 sig->params [i] = mono_type_array_get_and_resolve (parameters, i);
8726         return sig;
8727 }
8728
8729 /**
8730  * LOCKING: Assumes the loader lock is held.
8731  */
8732 static MonoMethodSignature*
8733 ctor_builder_to_signature (MonoImage *image, MonoReflectionCtorBuilder *ctor) {
8734         MonoMethodSignature *sig;
8735
8736         sig = parameters_to_signature (image, ctor->parameters);
8737         sig->hasthis = ctor->attrs & METHOD_ATTRIBUTE_STATIC? 0: 1;
8738         sig->ret = &mono_defaults.void_class->byval_arg;
8739         return sig;
8740 }
8741
8742 /**
8743  * LOCKING: Assumes the loader lock is held.
8744  */
8745 static MonoMethodSignature*
8746 method_builder_to_signature (MonoImage *image, MonoReflectionMethodBuilder *method) {
8747         MonoMethodSignature *sig;
8748
8749         sig = parameters_to_signature (image, method->parameters);
8750         sig->hasthis = method->attrs & METHOD_ATTRIBUTE_STATIC? 0: 1;
8751         sig->ret = method->rtype? mono_reflection_type_get_handle ((MonoReflectionType*)method->rtype): &mono_defaults.void_class->byval_arg;
8752         sig->generic_param_count = method->generic_params ? mono_array_length (method->generic_params) : 0;
8753         return sig;
8754 }
8755
8756 static MonoMethodSignature*
8757 dynamic_method_to_signature (MonoReflectionDynamicMethod *method) {
8758         MonoMethodSignature *sig;
8759
8760         sig = parameters_to_signature (NULL, method->parameters);
8761         sig->hasthis = method->attrs & METHOD_ATTRIBUTE_STATIC? 0: 1;
8762         sig->ret = method->rtype? mono_reflection_type_get_handle (method->rtype): &mono_defaults.void_class->byval_arg;
8763         sig->generic_param_count = 0;
8764         return sig;
8765 }
8766
8767 static void
8768 get_prop_name_and_type (MonoObject *prop, char **name, MonoType **type)
8769 {
8770         MonoClass *klass = mono_object_class (prop);
8771         if (strcmp (klass->name, "PropertyBuilder") == 0) {
8772                 MonoReflectionPropertyBuilder *pb = (MonoReflectionPropertyBuilder *)prop;
8773                 *name = mono_string_to_utf8 (pb->name);
8774                 *type = mono_reflection_type_get_handle ((MonoReflectionType*)pb->type);
8775         } else {
8776                 MonoReflectionProperty *p = (MonoReflectionProperty *)prop;
8777                 *name = g_strdup (p->property->name);
8778                 if (p->property->get)
8779                         *type = mono_method_signature (p->property->get)->ret;
8780                 else
8781                         *type = mono_method_signature (p->property->set)->params [mono_method_signature (p->property->set)->param_count - 1];
8782         }
8783 }
8784
8785 static void
8786 get_field_name_and_type (MonoObject *field, char **name, MonoType **type)
8787 {
8788         MonoClass *klass = mono_object_class (field);
8789         if (strcmp (klass->name, "FieldBuilder") == 0) {
8790                 MonoReflectionFieldBuilder *fb = (MonoReflectionFieldBuilder *)field;
8791                 *name = mono_string_to_utf8 (fb->name);
8792                 *type = mono_reflection_type_get_handle ((MonoReflectionType*)fb->type);
8793         } else {
8794                 MonoReflectionField *f = (MonoReflectionField *)field;
8795                 *name = g_strdup (mono_field_get_name (f->field));
8796                 *type = f->field->type;
8797         }
8798 }
8799 #endif /* !DISABLE_REFLECTION_EMIT */
8800
8801 /*
8802  * Encode a value in a custom attribute stream of bytes.
8803  * The value to encode is either supplied as an object in argument val
8804  * (valuetypes are boxed), or as a pointer to the data in the
8805  * argument argval.
8806  * @type represents the type of the value
8807  * @buffer is the start of the buffer
8808  * @p the current position in the buffer
8809  * @buflen contains the size of the buffer and is used to return the new buffer size
8810  * if this needs to be realloced.
8811  * @retbuffer and @retp return the start and the position of the buffer
8812  */
8813 static void
8814 encode_cattr_value (MonoAssembly *assembly, char *buffer, char *p, char **retbuffer, char **retp, guint32 *buflen, MonoType *type, MonoObject *arg, char *argval)
8815 {
8816         MonoTypeEnum simple_type;
8817         
8818         if ((p-buffer) + 10 >= *buflen) {
8819                 char *newbuf;
8820                 *buflen *= 2;
8821                 newbuf = g_realloc (buffer, *buflen);
8822                 p = newbuf + (p-buffer);
8823                 buffer = newbuf;
8824         }
8825         if (!argval)
8826                 argval = ((char*)arg + sizeof (MonoObject));
8827         simple_type = type->type;
8828 handle_enum:
8829         switch (simple_type) {
8830         case MONO_TYPE_BOOLEAN:
8831         case MONO_TYPE_U1:
8832         case MONO_TYPE_I1:
8833                 *p++ = *argval;
8834                 break;
8835         case MONO_TYPE_CHAR:
8836         case MONO_TYPE_U2:
8837         case MONO_TYPE_I2:
8838                 swap_with_size (p, argval, 2, 1);
8839                 p += 2;
8840                 break;
8841         case MONO_TYPE_U4:
8842         case MONO_TYPE_I4:
8843         case MONO_TYPE_R4:
8844                 swap_with_size (p, argval, 4, 1);
8845                 p += 4;
8846                 break;
8847         case MONO_TYPE_R8:
8848 #if defined(ARM_FPU_FPA) && G_BYTE_ORDER == G_LITTLE_ENDIAN
8849                 p [0] = argval [4];
8850                 p [1] = argval [5];
8851                 p [2] = argval [6];
8852                 p [3] = argval [7];
8853                 p [4] = argval [0];
8854                 p [5] = argval [1];
8855                 p [6] = argval [2];
8856                 p [7] = argval [3];
8857 #else
8858                 swap_with_size (p, argval, 8, 1);
8859 #endif
8860                 p += 8;
8861                 break;
8862         case MONO_TYPE_U8:
8863         case MONO_TYPE_I8:
8864                 swap_with_size (p, argval, 8, 1);
8865                 p += 8;
8866                 break;
8867         case MONO_TYPE_VALUETYPE:
8868                 if (type->data.klass->enumtype) {
8869                         simple_type = mono_class_enum_basetype (type->data.klass)->type;
8870                         goto handle_enum;
8871                 } else {
8872                         g_warning ("generic valutype %s not handled in custom attr value decoding", type->data.klass->name);
8873                 }
8874                 break;
8875         case MONO_TYPE_STRING: {
8876                 char *str;
8877                 guint32 slen;
8878                 if (!arg) {
8879                         *p++ = 0xFF;
8880                         break;
8881                 }
8882                 str = mono_string_to_utf8 ((MonoString*)arg);
8883                 slen = strlen (str);
8884                 if ((p-buffer) + 10 + slen >= *buflen) {
8885                         char *newbuf;
8886                         *buflen *= 2;
8887                         *buflen += slen;
8888                         newbuf = g_realloc (buffer, *buflen);
8889                         p = newbuf + (p-buffer);
8890                         buffer = newbuf;
8891                 }
8892                 mono_metadata_encode_value (slen, p, &p);
8893                 memcpy (p, str, slen);
8894                 p += slen;
8895                 g_free (str);
8896                 break;
8897         }
8898         case MONO_TYPE_CLASS: {
8899                 char *str;
8900                 guint32 slen;
8901                 MonoClass *k;
8902                 if (!arg) {
8903                         *p++ = 0xFF;
8904                         break;
8905                 }
8906 handle_type:
8907                 str = type_get_qualified_name (mono_reflection_type_get_handle ((MonoReflectionType*)arg), NULL);
8908                 slen = strlen (str);
8909                 if ((p-buffer) + 10 + slen >= *buflen) {
8910                         char *newbuf;
8911                         *buflen *= 2;
8912                         *buflen += slen;
8913                         newbuf = g_realloc (buffer, *buflen);
8914                         p = newbuf + (p-buffer);
8915                         buffer = newbuf;
8916                 }
8917                 mono_metadata_encode_value (slen, p, &p);
8918                 memcpy (p, str, slen);
8919                 p += slen;
8920                 g_free (str);
8921                 break;
8922         }
8923         case MONO_TYPE_SZARRAY: {
8924                 int len, i;
8925                 MonoClass *eclass, *arg_eclass;
8926
8927                 if (!arg) {
8928                         *p++ = 0xff; *p++ = 0xff; *p++ = 0xff; *p++ = 0xff;
8929                         break;
8930                 }
8931                 len = mono_array_length ((MonoArray*)arg);
8932                 *p++ = len & 0xff;
8933                 *p++ = (len >> 8) & 0xff;
8934                 *p++ = (len >> 16) & 0xff;
8935                 *p++ = (len >> 24) & 0xff;
8936                 *retp = p;
8937                 *retbuffer = buffer;
8938                 eclass = type->data.klass;
8939                 arg_eclass = mono_object_class (arg)->element_class;
8940
8941                 if (!eclass) {
8942                         /* Happens when we are called from the MONO_TYPE_OBJECT case below */
8943                         eclass = mono_defaults.object_class;
8944                 }
8945                 if (eclass == mono_defaults.object_class && arg_eclass->valuetype) {
8946                         char *elptr = mono_array_addr ((MonoArray*)arg, char, 0);
8947                         int elsize = mono_class_array_element_size (arg_eclass);
8948                         for (i = 0; i < len; ++i) {
8949                                 encode_cattr_value (assembly, buffer, p, &buffer, &p, buflen, &arg_eclass->byval_arg, NULL, elptr);
8950                                 elptr += elsize;
8951                         }
8952                 } else if (eclass->valuetype && arg_eclass->valuetype) {
8953                         char *elptr = mono_array_addr ((MonoArray*)arg, char, 0);
8954                         int elsize = mono_class_array_element_size (eclass);
8955                         for (i = 0; i < len; ++i) {
8956                                 encode_cattr_value (assembly, buffer, p, &buffer, &p, buflen, &eclass->byval_arg, NULL, elptr);
8957                                 elptr += elsize;
8958                         }
8959                 } else {
8960                         for (i = 0; i < len; ++i) {
8961                                 encode_cattr_value (assembly, buffer, p, &buffer, &p, buflen, &eclass->byval_arg, mono_array_get ((MonoArray*)arg, MonoObject*, i), NULL);
8962                         }
8963                 }
8964                 break;
8965         }
8966         case MONO_TYPE_OBJECT: {
8967                 MonoClass *klass;
8968                 char *str;
8969                 guint32 slen;
8970
8971                 /*
8972                  * The parameter type is 'object' but the type of the actual
8973                  * argument is not. So we have to add type information to the blob
8974                  * too. This is completely undocumented in the spec.
8975                  */
8976
8977                 if (arg == NULL) {
8978                         *p++ = MONO_TYPE_STRING;        // It's same hack as MS uses
8979                         *p++ = 0xFF;
8980                         break;
8981                 }
8982                 
8983                 klass = mono_object_class (arg);
8984
8985                 if (mono_object_isinst (arg, mono_defaults.systemtype_class)) {
8986                         *p++ = 0x50;
8987                         goto handle_type;
8988                 } else if (klass->enumtype) {
8989                         *p++ = 0x55;
8990                 } else if (klass == mono_defaults.string_class) {
8991                         simple_type = MONO_TYPE_STRING;
8992                         *p++ = 0x0E;
8993                         goto handle_enum;
8994                 } else if (klass->rank == 1) {
8995                         *p++ = 0x1D;
8996                         if (klass->element_class->byval_arg.type == MONO_TYPE_OBJECT)
8997                                 /* See Partition II, Appendix B3 */
8998                                 *p++ = 0x51;
8999                         else
9000                                 *p++ = klass->element_class->byval_arg.type;
9001                         encode_cattr_value (assembly, buffer, p, &buffer, &p, buflen, &klass->byval_arg, arg, NULL);
9002                         break;
9003                 } else if (klass->byval_arg.type >= MONO_TYPE_BOOLEAN && klass->byval_arg.type <= MONO_TYPE_R8) {
9004                         *p++ = simple_type = klass->byval_arg.type;
9005                         goto handle_enum;
9006                 } else {
9007                         g_error ("unhandled type in custom attr");
9008                 }
9009                 str = type_get_qualified_name (mono_class_get_type(klass), NULL);
9010                 slen = strlen (str);
9011                 if ((p-buffer) + 10 + slen >= *buflen) {
9012                         char *newbuf;
9013                         *buflen *= 2;
9014                         *buflen += slen;
9015                         newbuf = g_realloc (buffer, *buflen);
9016                         p = newbuf + (p-buffer);
9017                         buffer = newbuf;
9018                 }
9019                 mono_metadata_encode_value (slen, p, &p);
9020                 memcpy (p, str, slen);
9021                 p += slen;
9022                 g_free (str);
9023                 simple_type = mono_class_enum_basetype (klass)->type;
9024                 goto handle_enum;
9025         }
9026         default:
9027                 g_error ("type 0x%02x not yet supported in custom attr encoder", simple_type);
9028         }
9029         *retp = p;
9030         *retbuffer = buffer;
9031 }
9032
9033 static void
9034 encode_field_or_prop_type (MonoType *type, char *p, char **retp)
9035 {
9036         if (type->type == MONO_TYPE_VALUETYPE && type->data.klass->enumtype) {
9037                 char *str = type_get_qualified_name (type, NULL);
9038                 int slen = strlen (str);
9039
9040                 *p++ = 0x55;
9041                 /*
9042                  * This seems to be optional...
9043                  * *p++ = 0x80;
9044                  */
9045                 mono_metadata_encode_value (slen, p, &p);
9046                 memcpy (p, str, slen);
9047                 p += slen;
9048                 g_free (str);
9049         } else if (type->type == MONO_TYPE_OBJECT) {
9050                 *p++ = 0x51;
9051         } else if (type->type == MONO_TYPE_CLASS) {
9052                 /* it should be a type: encode_cattr_value () has the check */
9053                 *p++ = 0x50;
9054         } else {
9055                 mono_metadata_encode_value (type->type, p, &p);
9056                 if (type->type == MONO_TYPE_SZARRAY)
9057                         /* See the examples in Partition VI, Annex B */
9058                         encode_field_or_prop_type (&type->data.klass->byval_arg, p, &p);
9059         }
9060
9061         *retp = p;
9062 }
9063
9064 #ifndef DISABLE_REFLECTION_EMIT
9065 static void
9066 encode_named_val (MonoReflectionAssembly *assembly, char *buffer, char *p, char **retbuffer, char **retp, guint32 *buflen, MonoType *type, char *name, MonoObject *value)
9067 {
9068         int len;
9069         /* Preallocate a large enough buffer */
9070         if (type->type == MONO_TYPE_VALUETYPE && type->data.klass->enumtype) {
9071                 char *str = type_get_qualified_name (type, NULL);
9072                 len = strlen (str);
9073                 g_free (str);
9074         } else if (type->type == MONO_TYPE_SZARRAY && type->data.klass->enumtype) {
9075                 char *str = type_get_qualified_name (&type->data.klass->byval_arg, NULL);
9076                 len = strlen (str);
9077                 g_free (str);
9078         } else {
9079                 len = 0;
9080         }
9081         len += strlen (name);
9082
9083         if ((p-buffer) + 20 + len >= *buflen) {
9084                 char *newbuf;
9085                 *buflen *= 2;
9086                 *buflen += len;
9087                 newbuf = g_realloc (buffer, *buflen);
9088                 p = newbuf + (p-buffer);
9089                 buffer = newbuf;
9090         }
9091
9092         encode_field_or_prop_type (type, p, &p);
9093
9094         len = strlen (name);
9095         mono_metadata_encode_value (len, p, &p);
9096         memcpy (p, name, len);
9097         p += len;
9098         encode_cattr_value (assembly->assembly, buffer, p, &buffer, &p, buflen, type, value, NULL);
9099         *retp = p;
9100         *retbuffer = buffer;
9101 }
9102
9103 /*
9104  * mono_reflection_get_custom_attrs_blob:
9105  * @ctor: custom attribute constructor
9106  * @ctorArgs: arguments o the constructor
9107  * @properties:
9108  * @propValues:
9109  * @fields:
9110  * @fieldValues:
9111  * 
9112  * Creates the blob of data that needs to be saved in the metadata and that represents
9113  * the custom attributed described by @ctor, @ctorArgs etc.
9114  * Returns: a Byte array representing the blob of data.
9115  */
9116 MonoArray*
9117 mono_reflection_get_custom_attrs_blob (MonoReflectionAssembly *assembly, MonoObject *ctor, MonoArray *ctorArgs, MonoArray *properties, MonoArray *propValues, MonoArray *fields, MonoArray* fieldValues) 
9118 {
9119         MonoArray *result;
9120         MonoMethodSignature *sig;
9121         MonoObject *arg;
9122         char *buffer, *p;
9123         guint32 buflen, i;
9124
9125         MONO_ARCH_SAVE_REGS;
9126
9127         if (strcmp (ctor->vtable->klass->name, "MonoCMethod")) {
9128                 /* sig is freed later so allocate it in the heap */
9129                 sig = ctor_builder_to_signature (NULL, (MonoReflectionCtorBuilder*)ctor);
9130         } else {
9131                 sig = mono_method_signature (((MonoReflectionMethod*)ctor)->method);
9132         }
9133
9134         g_assert (mono_array_length (ctorArgs) == sig->param_count);
9135         buflen = 256;
9136         p = buffer = g_malloc (buflen);
9137         /* write the prolog */
9138         *p++ = 1;
9139         *p++ = 0;
9140         for (i = 0; i < sig->param_count; ++i) {
9141                 arg = mono_array_get (ctorArgs, MonoObject*, i);
9142                 encode_cattr_value (assembly->assembly, buffer, p, &buffer, &p, &buflen, sig->params [i], arg, NULL);
9143         }
9144         i = 0;
9145         if (properties)
9146                 i += mono_array_length (properties);
9147         if (fields)
9148                 i += mono_array_length (fields);
9149         *p++ = i & 0xff;
9150         *p++ = (i >> 8) & 0xff;
9151         if (properties) {
9152                 MonoObject *prop;
9153                 for (i = 0; i < mono_array_length (properties); ++i) {
9154                         MonoType *ptype;
9155                         char *pname;
9156
9157                         prop = mono_array_get (properties, gpointer, i);
9158                         get_prop_name_and_type (prop, &pname, &ptype);
9159                         *p++ = 0x54; /* PROPERTY signature */
9160                         encode_named_val (assembly, buffer, p, &buffer, &p, &buflen, ptype, pname, (MonoObject*)mono_array_get (propValues, gpointer, i));
9161                         g_free (pname);
9162                 }
9163         }
9164
9165         if (fields) {
9166                 MonoObject *field;
9167                 for (i = 0; i < mono_array_length (fields); ++i) {
9168                         MonoType *ftype;
9169                         char *fname;
9170
9171                         field = mono_array_get (fields, gpointer, i);
9172                         get_field_name_and_type (field, &fname, &ftype);
9173                         *p++ = 0x53; /* FIELD signature */
9174                         encode_named_val (assembly, buffer, p, &buffer, &p, &buflen, ftype, fname, (MonoObject*)mono_array_get (fieldValues, gpointer, i));
9175                         g_free (fname);
9176                 }
9177         }
9178
9179         g_assert (p - buffer <= buflen);
9180         buflen = p - buffer;
9181         result = mono_array_new (mono_domain_get (), mono_defaults.byte_class, buflen);
9182         p = mono_array_addr (result, char, 0);
9183         memcpy (p, buffer, buflen);
9184         g_free (buffer);
9185         if (strcmp (ctor->vtable->klass->name, "MonoCMethod"))
9186                 g_free (sig);
9187         return result;
9188 }
9189
9190 /*
9191  * mono_reflection_setup_internal_class:
9192  * @tb: a TypeBuilder object
9193  *
9194  * Creates a MonoClass that represents the TypeBuilder.
9195  * This is a trick that lets us simplify a lot of reflection code
9196  * (and will allow us to support Build and Run assemblies easier).
9197  */
9198 void
9199 mono_reflection_setup_internal_class (MonoReflectionTypeBuilder *tb)
9200 {
9201         MonoClass *klass, *parent;
9202
9203         MONO_ARCH_SAVE_REGS;
9204
9205         RESOLVE_TYPE (tb->parent);
9206
9207         mono_loader_lock ();
9208
9209         if (tb->parent) {
9210                 /* check so we can compile corlib correctly */
9211                 if (strcmp (mono_object_class (tb->parent)->name, "TypeBuilder") == 0) {
9212                         /* mono_class_setup_mono_type () guaranteess type->data.klass is valid */
9213                         parent = mono_reflection_type_get_handle ((MonoReflectionType*)tb->parent)->data.klass;
9214                 } else {
9215                         parent = mono_class_from_mono_type (mono_reflection_type_get_handle ((MonoReflectionType*)tb->parent));
9216                 }
9217         } else {
9218                 parent = NULL;
9219         }
9220         
9221         /* the type has already being created: it means we just have to change the parent */
9222         if (tb->type.type) {
9223                 klass = mono_class_from_mono_type (tb->type.type);
9224                 klass->parent = NULL;
9225                 /* fool mono_class_setup_parent */
9226                 klass->supertypes = NULL;
9227                 mono_class_setup_parent (klass, parent);
9228                 mono_class_setup_mono_type (klass);
9229                 mono_loader_unlock ();
9230                 return;
9231         }
9232
9233         klass = mono_image_alloc0 (&tb->module->dynamic_image->image, sizeof (MonoClass));
9234
9235         klass->image = &tb->module->dynamic_image->image;
9236
9237         klass->inited = 1; /* we lie to the runtime */
9238         klass->name = mono_string_to_utf8_image (klass->image, tb->name);
9239         klass->name_space = mono_string_to_utf8_image (klass->image, tb->nspace);
9240         klass->type_token = MONO_TOKEN_TYPE_DEF | tb->table_idx;
9241         klass->flags = tb->attrs;
9242         
9243         mono_profiler_class_event (klass, MONO_PROFILE_START_LOAD);
9244
9245         klass->element_class = klass;
9246
9247         MOVING_GC_REGISTER (&klass->reflection_info);
9248         klass->reflection_info = tb;
9249
9250         /* Put into cache so mono_class_get () will find it */
9251         mono_image_add_to_name_cache (klass->image, klass->name_space, klass->name, tb->table_idx);
9252
9253         mono_g_hash_table_insert (tb->module->dynamic_image->tokens,
9254                 GUINT_TO_POINTER (MONO_TOKEN_TYPE_DEF | tb->table_idx), tb);
9255
9256         if (parent != NULL) {
9257                 mono_class_setup_parent (klass, parent);
9258         } else if (strcmp (klass->name, "Object") == 0 && strcmp (klass->name_space, "System") == 0) {
9259                 const char *old_n = klass->name;
9260                 /* trick to get relative numbering right when compiling corlib */
9261                 klass->name = "BuildingObject";
9262                 mono_class_setup_parent (klass, mono_defaults.object_class);
9263                 klass->name = old_n;
9264         }
9265
9266         if ((!strcmp (klass->name, "ValueType") && !strcmp (klass->name_space, "System")) ||
9267                         (!strcmp (klass->name, "Object") && !strcmp (klass->name_space, "System")) ||
9268                         (!strcmp (klass->name, "Enum") && !strcmp (klass->name_space, "System"))) {
9269                 klass->instance_size = sizeof (MonoObject);
9270                 klass->size_inited = 1;
9271                 mono_class_setup_vtable_general (klass, NULL, 0);
9272         }
9273
9274         mono_class_setup_mono_type (klass);
9275
9276         mono_class_setup_supertypes (klass);
9277
9278         /*
9279          * FIXME: handle interfaces.
9280          */
9281
9282         tb->type.type = &klass->byval_arg;
9283
9284         if (tb->nesting_type) {
9285                 g_assert (tb->nesting_type->type);
9286                 klass->nested_in = mono_class_from_mono_type (mono_reflection_type_get_handle (tb->nesting_type));
9287         }
9288
9289         /*g_print ("setup %s as %s (%p)\n", klass->name, ((MonoObject*)tb)->vtable->klass->name, tb);*/
9290
9291         mono_profiler_class_loaded (klass, MONO_PROFILE_OK);
9292         
9293         mono_loader_unlock ();
9294 }
9295
9296 /*
9297  * mono_reflection_setup_generic_class:
9298  * @tb: a TypeBuilder object
9299  *
9300  * Setup the generic class before adding the first generic parameter.
9301  */
9302 void
9303 mono_reflection_setup_generic_class (MonoReflectionTypeBuilder *tb)
9304 {
9305 }
9306
9307 /*
9308  * mono_reflection_create_generic_class:
9309  * @tb: a TypeBuilder object
9310  *
9311  * Creates the generic class after all generic parameters have been added.
9312  */
9313 void
9314 mono_reflection_create_generic_class (MonoReflectionTypeBuilder *tb)
9315 {
9316         MonoClass *klass;
9317         int count, i;
9318
9319         MONO_ARCH_SAVE_REGS;
9320
9321         klass = mono_class_from_mono_type (tb->type.type);
9322
9323         count = tb->generic_params ? mono_array_length (tb->generic_params) : 0;
9324
9325         if (klass->generic_container || (count == 0))
9326                 return;
9327
9328         g_assert (tb->generic_container && (tb->generic_container->owner.klass == klass));
9329
9330         klass->generic_container = mono_image_alloc0 (klass->image, sizeof (MonoGenericContainer));
9331
9332         klass->generic_container->owner.klass = klass;
9333         klass->generic_container->type_argc = count;
9334         klass->generic_container->type_params = mono_image_alloc0 (klass->image, sizeof (MonoGenericParamFull) * count);
9335
9336         klass->is_generic = 1;
9337
9338         for (i = 0; i < count; i++) {
9339                 MonoReflectionGenericParam *gparam = mono_array_get (tb->generic_params, gpointer, i);
9340                 MonoGenericParamFull *param = (MonoGenericParamFull *) mono_reflection_type_get_handle ((MonoReflectionType*)gparam)->data.generic_param;
9341                 klass->generic_container->type_params [i] = *param;
9342                 /*Make sure we are a diferent type instance */
9343                 klass->generic_container->type_params [i].param.owner = klass->generic_container;
9344                 klass->generic_container->type_params [i].info.pklass = NULL;
9345
9346                 g_assert (klass->generic_container->type_params [i].param.owner);
9347         }
9348
9349         klass->generic_container->context.class_inst = mono_get_shared_generic_inst (klass->generic_container);
9350 }
9351
9352 /*
9353  * mono_reflection_create_internal_class:
9354  * @tb: a TypeBuilder object
9355  *
9356  * Actually create the MonoClass that is associated with the TypeBuilder.
9357  */
9358 void
9359 mono_reflection_create_internal_class (MonoReflectionTypeBuilder *tb)
9360 {
9361         MonoClass *klass;
9362
9363         MONO_ARCH_SAVE_REGS;
9364
9365         klass = mono_class_from_mono_type (tb->type.type);
9366
9367         mono_loader_lock ();
9368         if (klass->enumtype && mono_class_enum_basetype (klass) == NULL) {
9369                 MonoReflectionFieldBuilder *fb;
9370                 MonoClass *ec;
9371                 MonoType *enum_basetype;
9372
9373                 g_assert (tb->fields != NULL);
9374                 g_assert (mono_array_length (tb->fields) >= 1);
9375
9376                 fb = mono_array_get (tb->fields, MonoReflectionFieldBuilder*, 0);
9377
9378                 if (!mono_type_is_valid_enum_basetype (mono_reflection_type_get_handle ((MonoReflectionType*)fb->type))) {
9379                         mono_loader_unlock ();
9380                         return;
9381                 }
9382
9383                 enum_basetype = mono_reflection_type_get_handle ((MonoReflectionType*)fb->type);
9384                 klass->element_class = mono_class_from_mono_type (enum_basetype);
9385                 if (!klass->element_class)
9386                         klass->element_class = mono_class_from_mono_type (enum_basetype);
9387
9388                 /*
9389                  * get the element_class from the current corlib.
9390                  */
9391                 ec = default_class_from_mono_type (enum_basetype);
9392                 klass->instance_size = ec->instance_size;
9393                 klass->size_inited = 1;
9394                 /* 
9395                  * this is almost safe to do with enums and it's needed to be able
9396                  * to create objects of the enum type (for use in SetConstant).
9397                  */
9398                 /* FIXME: Does this mean enums can't have method overrides ? */
9399                 mono_class_setup_vtable_general (klass, NULL, 0);
9400         }
9401         mono_loader_unlock ();
9402 }
9403
9404 static MonoMarshalSpec*
9405 mono_marshal_spec_from_builder (MonoImage *image, MonoAssembly *assembly,
9406                                                                 MonoReflectionMarshal *minfo)
9407 {
9408         MonoMarshalSpec *res;
9409
9410         res = image_g_new0 (image, MonoMarshalSpec, 1);
9411         res->native = minfo->type;
9412
9413         switch (minfo->type) {
9414         case MONO_NATIVE_LPARRAY:
9415                 res->data.array_data.elem_type = minfo->eltype;
9416                 if (minfo->has_size) {
9417                         res->data.array_data.param_num = minfo->param_num;
9418                         res->data.array_data.num_elem = minfo->count;
9419                         res->data.array_data.elem_mult = minfo->param_num == -1 ? 0 : 1;
9420                 }
9421                 else {
9422                         res->data.array_data.param_num = -1;
9423                         res->data.array_data.num_elem = -1;
9424                         res->data.array_data.elem_mult = -1;
9425                 }
9426                 break;
9427
9428         case MONO_NATIVE_BYVALTSTR:
9429         case MONO_NATIVE_BYVALARRAY:
9430                 res->data.array_data.num_elem = minfo->count;
9431                 break;
9432
9433         case MONO_NATIVE_CUSTOM:
9434                 if (minfo->marshaltyperef)
9435                         res->data.custom_data.custom_name =
9436                                 type_get_fully_qualified_name (mono_reflection_type_get_handle ((MonoReflectionType*)minfo->marshaltyperef));
9437                 if (minfo->mcookie)
9438                         res->data.custom_data.cookie = mono_string_to_utf8 (minfo->mcookie);
9439                 break;
9440
9441         default:
9442                 break;
9443         }
9444
9445         return res;
9446 }
9447 #endif /* !DISABLE_REFLECTION_EMIT */
9448
9449 MonoReflectionMarshal*
9450 mono_reflection_marshal_from_marshal_spec (MonoDomain *domain, MonoClass *klass,
9451                                                                                    MonoMarshalSpec *spec)
9452 {
9453         static MonoClass *System_Reflection_Emit_UnmanagedMarshalClass;
9454         MonoReflectionMarshal *minfo;
9455         MonoType *mtype;
9456
9457         if (!System_Reflection_Emit_UnmanagedMarshalClass) {
9458                 System_Reflection_Emit_UnmanagedMarshalClass = mono_class_from_name (
9459                    mono_defaults.corlib, "System.Reflection.Emit", "UnmanagedMarshal");
9460                 g_assert (System_Reflection_Emit_UnmanagedMarshalClass);
9461         }
9462
9463         minfo = (MonoReflectionMarshal*)mono_object_new (domain, System_Reflection_Emit_UnmanagedMarshalClass);
9464         minfo->type = spec->native;
9465
9466         switch (minfo->type) {
9467         case MONO_NATIVE_LPARRAY:
9468                 minfo->eltype = spec->data.array_data.elem_type;
9469                 minfo->count = spec->data.array_data.num_elem;
9470                 minfo->param_num = spec->data.array_data.param_num;
9471                 break;
9472
9473         case MONO_NATIVE_BYVALTSTR:
9474         case MONO_NATIVE_BYVALARRAY:
9475                 minfo->count = spec->data.array_data.num_elem;
9476                 break;
9477
9478         case MONO_NATIVE_CUSTOM:
9479                 if (spec->data.custom_data.custom_name) {
9480                         mtype = mono_reflection_type_from_name (spec->data.custom_data.custom_name, klass->image);
9481                         if (mtype)
9482                                 MONO_OBJECT_SETREF (minfo, marshaltyperef, mono_type_get_object (domain, mtype));
9483
9484                         MONO_OBJECT_SETREF (minfo, marshaltype, mono_string_new (domain, spec->data.custom_data.custom_name));
9485                 }
9486                 if (spec->data.custom_data.cookie)
9487                         MONO_OBJECT_SETREF (minfo, mcookie, mono_string_new (domain, spec->data.custom_data.cookie));
9488                 break;
9489
9490         default:
9491                 break;
9492         }
9493
9494         return minfo;
9495 }
9496
9497 #ifndef DISABLE_REFLECTION_EMIT
9498 static MonoMethod*
9499 reflection_methodbuilder_to_mono_method (MonoClass *klass,
9500                                          ReflectionMethodBuilder *rmb,
9501                                          MonoMethodSignature *sig)
9502 {
9503         MonoMethod *m;
9504         MonoMethodNormal *pm;
9505         MonoMarshalSpec **specs;
9506         MonoReflectionMethodAux *method_aux;
9507         MonoImage *image;
9508         gboolean dynamic;
9509         int i;
9510
9511         /*
9512          * Methods created using a MethodBuilder should have their memory allocated
9513          * inside the image mempool, while dynamic methods should have their memory
9514          * malloc'd.
9515          */
9516         dynamic = rmb->refs != NULL;
9517         image = dynamic ? NULL : klass->image;
9518
9519         if (!dynamic)
9520                 g_assert (!klass->generic_class);
9521
9522         mono_loader_lock ();
9523
9524         if ((rmb->attrs & METHOD_ATTRIBUTE_PINVOKE_IMPL) ||
9525                         (rmb->iattrs & METHOD_IMPL_ATTRIBUTE_INTERNAL_CALL))
9526                 m = (MonoMethod *)image_g_new0 (image, MonoMethodPInvoke, 1);
9527         else if (rmb->refs)
9528                 m = (MonoMethod *)image_g_new0 (image, MonoMethodWrapper, 1);
9529         else
9530                 m = (MonoMethod *)image_g_new0 (image, MonoMethodNormal, 1);
9531
9532         pm = (MonoMethodNormal*)m;
9533
9534         m->dynamic = dynamic;
9535         m->slot = -1;
9536         m->flags = rmb->attrs;
9537         m->iflags = rmb->iattrs;
9538         m->name = mono_string_to_utf8_image (image, rmb->name);
9539         m->klass = klass;
9540         m->signature = sig;
9541         m->skip_visibility = rmb->skip_visibility;
9542         if (rmb->table_idx)
9543                 m->token = MONO_TOKEN_METHOD_DEF | (*rmb->table_idx);
9544
9545         if (m->iflags & METHOD_IMPL_ATTRIBUTE_INTERNAL_CALL) {
9546                 if (klass == mono_defaults.string_class && !strcmp (m->name, ".ctor"))
9547                         m->string_ctor = 1;
9548
9549                 m->signature->pinvoke = 1;
9550         } else if (m->flags & METHOD_ATTRIBUTE_PINVOKE_IMPL) {
9551                 m->signature->pinvoke = 1;
9552
9553                 method_aux = image_g_new0 (image, MonoReflectionMethodAux, 1);
9554
9555                 method_aux->dllentry = rmb->dllentry ? mono_string_to_utf8_image (image, rmb->dllentry) : image_strdup (image, m->name);
9556                 method_aux->dll = mono_string_to_utf8_image (image, rmb->dll);
9557                 
9558                 ((MonoMethodPInvoke*)m)->piflags = (rmb->native_cc << 8) | (rmb->charset ? (rmb->charset - 1) * 2 : 0) | rmb->extra_flags;
9559
9560                 if (klass->image->dynamic)
9561                         g_hash_table_insert (((MonoDynamicImage*)klass->image)->method_aux_hash, m, method_aux);
9562
9563                 mono_loader_unlock ();
9564
9565                 return m;
9566         } else if (!(m->flags & METHOD_ATTRIBUTE_ABSTRACT) &&
9567                            !(m->iflags & METHOD_IMPL_ATTRIBUTE_RUNTIME)) {
9568                 MonoMethodHeader *header;
9569                 guint32 code_size;
9570                 gint32 max_stack, i;
9571                 gint32 num_locals = 0;
9572                 gint32 num_clauses = 0;
9573                 guint8 *code;
9574
9575                 if (rmb->ilgen) {
9576                         code = mono_array_addr (rmb->ilgen->code, guint8, 0);
9577                         code_size = rmb->ilgen->code_len;
9578                         max_stack = rmb->ilgen->max_stack;
9579                         num_locals = rmb->ilgen->locals ? mono_array_length (rmb->ilgen->locals) : 0;
9580                         if (rmb->ilgen->ex_handlers)
9581                                 num_clauses = method_count_clauses (rmb->ilgen);
9582                 } else {
9583                         if (rmb->code) {
9584                                 code = mono_array_addr (rmb->code, guint8, 0);
9585                                 code_size = mono_array_length (rmb->code);
9586                                 /* we probably need to run a verifier on the code... */
9587                                 max_stack = 8; 
9588                         }
9589                         else {
9590                                 code = NULL;
9591                                 code_size = 0;
9592                                 max_stack = 8;
9593                         }
9594                 }
9595
9596                 header = image_g_malloc0 (image, MONO_SIZEOF_METHOD_HEADER + num_locals * sizeof (MonoType*));
9597                 header->code_size = code_size;
9598                 header->code = image_g_malloc (image, code_size);
9599                 memcpy ((char*)header->code, code, code_size);
9600                 header->max_stack = max_stack;
9601                 header->init_locals = rmb->init_locals;
9602                 header->num_locals = num_locals;
9603
9604                 for (i = 0; i < num_locals; ++i) {
9605                         MonoReflectionLocalBuilder *lb = 
9606                                 mono_array_get (rmb->ilgen->locals, MonoReflectionLocalBuilder*, i);
9607
9608                         header->locals [i] = image_g_new0 (image, MonoType, 1);
9609                         memcpy (header->locals [i], mono_reflection_type_get_handle ((MonoReflectionType*)lb->type), MONO_SIZEOF_TYPE);
9610                 }
9611
9612                 header->num_clauses = num_clauses;
9613                 if (num_clauses) {
9614                         header->clauses = method_encode_clauses (image, (MonoDynamicImage*)klass->image,
9615                                  rmb->ilgen, num_clauses);
9616                 }
9617
9618                 pm->header = header;
9619         }
9620
9621         if (rmb->generic_params) {
9622                 int count = mono_array_length (rmb->generic_params);
9623                 MonoGenericContainer *container;
9624
9625                 container = rmb->generic_container;
9626                 if (container) {
9627                         m->is_generic = TRUE;
9628                         mono_method_set_generic_container (m, container);
9629                 }
9630                 container->type_argc = count;
9631                 container->type_params = image_g_new0 (image, MonoGenericParamFull, count);
9632                 container->owner.method = m;
9633
9634                 for (i = 0; i < count; i++) {
9635                         MonoReflectionGenericParam *gp =
9636                                 mono_array_get (rmb->generic_params, MonoReflectionGenericParam*, i);
9637                         MonoGenericParamFull *param = (MonoGenericParamFull *) mono_reflection_type_get_handle ((MonoReflectionType*)gp)->data.generic_param;
9638                         container->type_params [i] = *param;
9639                 }
9640
9641                 if (klass->generic_container) {
9642                         container->parent = klass->generic_container;
9643                         container->context.class_inst = klass->generic_container->context.class_inst;
9644                 }
9645                 container->context.method_inst = mono_get_shared_generic_inst (container);
9646         }
9647
9648         if (rmb->refs) {
9649                 MonoMethodWrapper *mw = (MonoMethodWrapper*)m;
9650                 int i;
9651                 void **data;
9652
9653                 m->wrapper_type = MONO_WRAPPER_DYNAMIC_METHOD;
9654
9655                 mw->method_data = data = image_g_new (image, gpointer, rmb->nrefs + 1);
9656                 data [0] = GUINT_TO_POINTER (rmb->nrefs);
9657                 for (i = 0; i < rmb->nrefs; ++i)
9658                         data [i + 1] = rmb->refs [i];
9659         }
9660
9661         method_aux = NULL;
9662
9663         /* Parameter info */
9664         if (rmb->pinfo) {
9665                 if (!method_aux)
9666                         method_aux = image_g_new0 (image, MonoReflectionMethodAux, 1);
9667                 method_aux->param_names = image_g_new0 (image, char *, mono_method_signature (m)->param_count + 1);
9668                 for (i = 0; i <= m->signature->param_count; ++i) {
9669                         MonoReflectionParamBuilder *pb;
9670                         if ((pb = mono_array_get (rmb->pinfo, MonoReflectionParamBuilder*, i))) {
9671                                 if ((i > 0) && (pb->attrs)) {
9672                                         /* Make a copy since it might point to a shared type structure */
9673                                         m->signature->params [i - 1] = mono_metadata_type_dup (klass->image, m->signature->params [i - 1]);
9674                                         m->signature->params [i - 1]->attrs = pb->attrs;
9675                                 }
9676
9677                                 if (pb->attrs & PARAM_ATTRIBUTE_HAS_DEFAULT) {
9678                                         MonoDynamicImage *assembly;
9679                                         guint32 idx, def_type, len;
9680                                         char *p;
9681                                         const char *p2;
9682
9683                                         if (!method_aux->param_defaults) {
9684                                                 method_aux->param_defaults = image_g_new0 (image, guint8*, m->signature->param_count + 1);
9685                                                 method_aux->param_default_types = image_g_new0 (image, guint32, m->signature->param_count + 1);
9686                                         }
9687                                         assembly = (MonoDynamicImage*)klass->image;
9688                                         idx = encode_constant (assembly, pb->def_value, &def_type);
9689                                         /* Copy the data from the blob since it might get realloc-ed */
9690                                         p = assembly->blob.data + idx;
9691                                         len = mono_metadata_decode_blob_size (p, &p2);
9692                                         len += p2 - p;
9693                                         method_aux->param_defaults [i] = image_g_malloc (image, len);
9694                                         method_aux->param_default_types [i] = def_type;
9695                                         memcpy ((gpointer)method_aux->param_defaults [i], p, len);
9696                                 }
9697
9698                                 if (pb->name)
9699                                         method_aux->param_names [i] = mono_string_to_utf8_image (image, pb->name);
9700                                 if (pb->cattrs) {
9701                                         if (!method_aux->param_cattr)
9702                                                 method_aux->param_cattr = image_g_new0 (image, MonoCustomAttrInfo*, m->signature->param_count + 1);
9703                                         method_aux->param_cattr [i] = mono_custom_attrs_from_builders (image, klass->image, pb->cattrs);
9704                                 }
9705                         }
9706                 }
9707         }
9708
9709         /* Parameter marshalling */
9710         specs = NULL;
9711         if (rmb->pinfo)         
9712                 for (i = 0; i < mono_array_length (rmb->pinfo); ++i) {
9713                         MonoReflectionParamBuilder *pb;
9714                         if ((pb = mono_array_get (rmb->pinfo, MonoReflectionParamBuilder*, i))) {
9715                                 if (pb->marshal_info) {
9716                                         if (specs == NULL)
9717                                                 specs = image_g_new0 (image, MonoMarshalSpec*, sig->param_count + 1);
9718                                         specs [pb->position] = 
9719                                                 mono_marshal_spec_from_builder (image, klass->image->assembly, pb->marshal_info);
9720                                 }
9721                         }
9722                 }
9723         if (specs != NULL) {
9724                 if (!method_aux)
9725                         method_aux = image_g_new0 (image, MonoReflectionMethodAux, 1);
9726                 method_aux->param_marshall = specs;
9727         }
9728
9729         if (klass->image->dynamic && method_aux)
9730                 g_hash_table_insert (((MonoDynamicImage*)klass->image)->method_aux_hash, m, method_aux);
9731
9732         mono_loader_unlock ();
9733
9734         return m;
9735 }       
9736
9737 static MonoMethod*
9738 ctorbuilder_to_mono_method (MonoClass *klass, MonoReflectionCtorBuilder* mb)
9739 {
9740         ReflectionMethodBuilder rmb;
9741         MonoMethodSignature *sig;
9742
9743         mono_loader_lock ();
9744         sig = ctor_builder_to_signature (klass->image, mb);
9745         mono_loader_unlock ();
9746
9747         reflection_methodbuilder_from_ctor_builder (&rmb, mb);
9748
9749         mb->mhandle = reflection_methodbuilder_to_mono_method (klass, &rmb, sig);
9750         mono_save_custom_attrs (klass->image, mb->mhandle, mb->cattrs);
9751
9752         /* If we are in a generic class, we might be called multiple times from inflate_method */
9753         if (!((MonoDynamicImage*)(MonoDynamicImage*)klass->image)->save && !klass->generic_container) {
9754                 /* ilgen is no longer needed */
9755                 mb->ilgen = NULL;
9756         }
9757
9758         return mb->mhandle;
9759 }
9760
9761 static MonoMethod*
9762 methodbuilder_to_mono_method (MonoClass *klass, MonoReflectionMethodBuilder* mb)
9763 {
9764         ReflectionMethodBuilder rmb;
9765         MonoMethodSignature *sig;
9766
9767         mono_loader_lock ();
9768         sig = method_builder_to_signature (klass->image, mb);
9769         mono_loader_unlock ();
9770
9771         reflection_methodbuilder_from_method_builder (&rmb, mb);
9772
9773         mb->mhandle = reflection_methodbuilder_to_mono_method (klass, &rmb, sig);
9774         mono_save_custom_attrs (klass->image, mb->mhandle, mb->cattrs);
9775
9776         /* If we are in a generic class, we might be called multiple times from inflate_method */
9777         if (!((MonoDynamicImage*)(MonoDynamicImage*)klass->image)->save && !klass->generic_container) {
9778                 /* ilgen is no longer needed */
9779                 mb->ilgen = NULL;
9780         }
9781         return mb->mhandle;
9782 }
9783
9784 static MonoClassField*
9785 fieldbuilder_to_mono_class_field (MonoClass *klass, MonoReflectionFieldBuilder* fb)
9786 {
9787         MonoClassField *field;
9788         MonoType *custom;
9789
9790         field = g_new0 (MonoClassField, 1);
9791
9792         field->name = mono_string_to_utf8 (fb->name);
9793         if (fb->attrs || fb->modreq || fb->modopt) {
9794                 field->type = mono_metadata_type_dup (NULL, mono_reflection_type_get_handle ((MonoReflectionType*)fb->type));
9795                 field->type->attrs = fb->attrs;
9796
9797                 g_assert (klass->image->dynamic);
9798                 custom = add_custom_modifiers ((MonoDynamicImage*)klass->image, field->type, fb->modreq, fb->modopt);
9799                 g_free (field->type);
9800                 field->type = custom;
9801         } else {
9802                 field->type = mono_reflection_type_get_handle ((MonoReflectionType*)fb->type);
9803         }
9804         if (fb->offset != -1)
9805                 field->offset = fb->offset;
9806         field->parent = klass;
9807         mono_save_custom_attrs (klass->image, field, fb->cattrs);
9808
9809         // FIXME: Can't store fb->def_value/RVA, is it needed for field_on_insts ?
9810
9811         return field;
9812 }
9813 #endif
9814
9815 MonoType*
9816 mono_reflection_bind_generic_parameters (MonoReflectionType *type, int type_argc, MonoType **types)
9817 {
9818         MonoClass *klass;
9819         MonoReflectionTypeBuilder *tb = NULL;
9820         gboolean is_dynamic = FALSE;
9821         MonoDomain *domain;
9822         MonoClass *geninst;
9823
9824         mono_loader_lock ();
9825
9826         domain = mono_object_domain (type);
9827
9828         if (!strcmp (((MonoObject *) type)->vtable->klass->name, "TypeBuilder")) {
9829                 tb = (MonoReflectionTypeBuilder *) type;
9830
9831                 is_dynamic = TRUE;
9832         } else if (!strcmp (((MonoObject *) type)->vtable->klass->name, "MonoGenericClass")) {
9833                 MonoReflectionGenericClass *rgi = (MonoReflectionGenericClass *) type;
9834
9835                 tb = rgi->generic_type;
9836                 is_dynamic = TRUE;
9837         }
9838
9839         /* FIXME: fix the CreateGenericParameters protocol to avoid the two stage setup of TypeBuilders */
9840         if (tb && tb->generic_container)
9841                 mono_reflection_create_generic_class (tb);
9842
9843         klass = mono_class_from_mono_type (mono_reflection_type_get_handle (type));
9844         if (!klass->generic_container) {
9845                 mono_loader_unlock ();
9846                 return NULL;
9847         }
9848
9849         if (klass->wastypebuilder) {
9850                 tb = (MonoReflectionTypeBuilder *) klass->reflection_info;
9851
9852                 is_dynamic = TRUE;
9853         }
9854
9855         mono_loader_unlock ();
9856
9857         geninst = mono_class_bind_generic_parameters (klass, type_argc, types, is_dynamic);
9858
9859         return &geninst->byval_arg;
9860 }
9861
9862 MonoClass*
9863 mono_class_bind_generic_parameters (MonoClass *klass, int type_argc, MonoType **types, gboolean is_dynamic)
9864 {
9865         MonoGenericClass *gclass;
9866         MonoGenericInst *inst;
9867
9868         g_assert (klass->generic_container);
9869
9870         inst = mono_metadata_get_generic_inst (type_argc, types);
9871         gclass = mono_metadata_lookup_generic_class (klass, inst, is_dynamic);
9872
9873         return mono_generic_class_get_class (gclass);
9874 }
9875
9876 MonoReflectionMethod*
9877 mono_reflection_bind_generic_method_parameters (MonoReflectionMethod *rmethod, MonoArray *types)
9878 {
9879         MonoClass *klass;
9880         MonoMethod *method, *inflated;
9881         MonoMethodInflated *imethod;
9882         MonoGenericContext tmp_context;
9883         MonoGenericInst *ginst;
9884         MonoType **type_argv;
9885         int count, i;
9886
9887         MONO_ARCH_SAVE_REGS;
9888
9889         if (!strcmp (rmethod->object.vtable->klass->name, "MethodBuilder")) {
9890 #ifndef DISABLE_REFLECTION_EMIT
9891                 MonoReflectionMethodBuilder *mb = NULL;
9892                 MonoReflectionTypeBuilder *tb;
9893                 MonoClass *klass;
9894
9895                 mb = (MonoReflectionMethodBuilder *) rmethod;
9896                 tb = (MonoReflectionTypeBuilder *) mb->type;
9897                 klass = mono_class_from_mono_type (mono_reflection_type_get_handle ((MonoReflectionType*)tb));
9898
9899                 method = methodbuilder_to_mono_method (klass, mb);
9900 #else
9901                 g_assert_not_reached ();
9902                 method = NULL;
9903 #endif
9904         } else {
9905                 method = rmethod->method;
9906         }
9907
9908         klass = method->klass;
9909
9910         if (method->is_inflated)
9911                 method = ((MonoMethodInflated *) method)->declaring;
9912
9913         count = mono_method_signature (method)->generic_param_count;
9914         if (count != mono_array_length (types))
9915                 return NULL;
9916
9917         type_argv = g_new0 (MonoType *, count);
9918         for (i = 0; i < count; i++) {
9919                 MonoReflectionType *garg = mono_array_get (types, gpointer, i);
9920                 type_argv [i] = mono_reflection_type_get_handle (garg);
9921         }
9922         ginst = mono_metadata_get_generic_inst (count, type_argv);
9923         g_free (type_argv);
9924
9925         tmp_context.class_inst = klass->generic_class ? klass->generic_class->context.class_inst : NULL;
9926         tmp_context.method_inst = ginst;
9927
9928         inflated = mono_class_inflate_generic_method (method, &tmp_context);
9929         imethod = (MonoMethodInflated *) inflated;
9930
9931         if (method->klass->image->dynamic) {
9932                 MonoDynamicImage *image = (MonoDynamicImage*)method->klass->image;
9933                 /*
9934                  * This table maps metadata structures representing inflated methods/fields
9935                  * to the reflection objects representing their generic definitions.
9936                  */
9937                 mono_loader_lock ();
9938                 mono_g_hash_table_insert (image->generic_def_objects, imethod, rmethod);
9939                 mono_loader_unlock ();
9940         }
9941         
9942         return mono_method_get_object (mono_object_domain (rmethod), inflated, NULL);
9943 }
9944
9945 #ifndef DISABLE_REFLECTION_EMIT
9946
9947 static MonoMethod *
9948 inflate_mono_method (MonoClass *klass, MonoMethod *method, MonoObject *obj)
9949 {
9950         MonoMethodInflated *imethod;
9951         MonoGenericContext *context;
9952         int i;
9953
9954         /*
9955          * With generic code sharing the klass might not be inflated.
9956          * This can happen because classes inflated with their own
9957          * type arguments are "normalized" to the uninflated class.
9958          */
9959         if (!klass->generic_class)
9960                 return method;
9961
9962         context = mono_class_get_context (klass);
9963
9964         if (klass->method.count) {
9965                 /* Find the already created inflated method */
9966                 for (i = 0; i < klass->method.count; ++i) {
9967                         g_assert (klass->methods [i]->is_inflated);
9968                         if (((MonoMethodInflated*)klass->methods [i])->declaring == method)
9969                                 break;
9970                 }
9971                 g_assert (i < klass->method.count);
9972                 imethod = (MonoMethodInflated*)klass->methods [i];
9973         } else {
9974                 imethod = (MonoMethodInflated *) mono_class_inflate_generic_method_full (method, klass, context);
9975         }
9976
9977         if (method->is_generic && method->klass->image->dynamic) {
9978                 MonoDynamicImage *image = (MonoDynamicImage*)method->klass->image;
9979
9980                 mono_loader_lock ();
9981                 mono_g_hash_table_insert (image->generic_def_objects, imethod, obj);
9982                 mono_loader_unlock ();
9983         }
9984         return (MonoMethod *) imethod;
9985 }
9986
9987 static MonoMethod *
9988 inflate_method (MonoReflectionGenericClass *type, MonoObject *obj)
9989 {
9990         MonoMethod *method;
9991         MonoClass *gklass;
9992
9993         gklass = mono_class_from_mono_type (mono_reflection_type_get_handle ((MonoReflectionType*)type->generic_type));
9994
9995         if (!strcmp (obj->vtable->klass->name, "MethodBuilder"))
9996                 if (((MonoReflectionMethodBuilder*)obj)->mhandle)
9997                         method = ((MonoReflectionMethodBuilder*)obj)->mhandle;
9998                 else
9999                         method = methodbuilder_to_mono_method (gklass, (MonoReflectionMethodBuilder *) obj);
10000         else if (!strcmp (obj->vtable->klass->name, "ConstructorBuilder"))
10001                 method = ctorbuilder_to_mono_method (gklass, (MonoReflectionCtorBuilder *) obj);
10002         else if (!strcmp (obj->vtable->klass->name, "MonoMethod") || !strcmp (obj->vtable->klass->name, "MonoCMethod"))
10003                 method = ((MonoReflectionMethod *) obj)->method;
10004         else {
10005                 method = NULL; /* prevent compiler warning */
10006                 g_error ("can't handle type %s", obj->vtable->klass->name);
10007         }
10008
10009         return inflate_mono_method (mono_class_from_mono_type (mono_reflection_type_get_handle ((MonoReflectionType*)type)), method, obj);
10010 }
10011
10012 /*TODO avoid saving custom attrs for generic classes as it's enough to have them on the generic type definition.*/
10013 void
10014 mono_reflection_generic_class_initialize (MonoReflectionGenericClass *type, MonoArray *methods, 
10015                                           MonoArray *ctors, MonoArray *fields, MonoArray *properties,
10016                                           MonoArray *events)
10017 {
10018         MonoGenericClass *gclass;
10019         MonoDynamicGenericClass *dgclass;
10020         MonoClass *klass, *gklass;
10021         MonoType *gtype;
10022         int i;
10023
10024         MONO_ARCH_SAVE_REGS;
10025
10026         gtype = mono_reflection_type_get_handle ((MonoReflectionType*)type);
10027         klass = mono_class_from_mono_type (gtype);
10028         g_assert (gtype->type == MONO_TYPE_GENERICINST);
10029         gclass = gtype->data.generic_class;
10030
10031         g_assert (gclass->is_dynamic);
10032         dgclass = (MonoDynamicGenericClass *) gclass;
10033
10034         if (dgclass->initialized)
10035                 return;
10036
10037         gklass = gclass->container_class;
10038         mono_class_init (gklass);
10039
10040         dgclass->count_methods = methods ? mono_array_length (methods) : 0;
10041         dgclass->count_ctors = ctors ? mono_array_length (ctors) : 0;
10042         dgclass->count_fields = fields ? mono_array_length (fields) : 0;
10043         dgclass->count_properties = properties ? mono_array_length (properties) : 0;
10044         dgclass->count_events = events ? mono_array_length (events) : 0;
10045
10046         dgclass->methods = g_new0 (MonoMethod *, dgclass->count_methods);
10047         dgclass->ctors = g_new0 (MonoMethod *, dgclass->count_ctors);
10048         dgclass->fields = g_new0 (MonoClassField, dgclass->count_fields);
10049         dgclass->properties = g_new0 (MonoProperty, dgclass->count_properties);
10050         dgclass->events = g_new0 (MonoEvent, dgclass->count_events);
10051         dgclass->field_objects = g_new0 (MonoObject*, dgclass->count_fields);
10052         dgclass->field_generic_types = g_new0 (MonoType*, dgclass->count_fields);
10053
10054         for (i = 0; i < dgclass->count_methods; i++) {
10055                 MonoObject *obj = mono_array_get (methods, gpointer, i);
10056
10057                 dgclass->methods [i] = inflate_method (type, obj);
10058         }
10059
10060         for (i = 0; i < dgclass->count_ctors; i++) {
10061                 MonoObject *obj = mono_array_get (ctors, gpointer, i);
10062
10063                 dgclass->ctors [i] = inflate_method (type, obj);
10064         }
10065
10066         for (i = 0; i < dgclass->count_fields; i++) {
10067                 MonoObject *obj = mono_array_get (fields, gpointer, i);
10068                 MonoClassField *field, *inflated_field = NULL;
10069
10070                 if (!strcmp (obj->vtable->klass->name, "FieldBuilder"))
10071                         inflated_field = field = fieldbuilder_to_mono_class_field (klass, (MonoReflectionFieldBuilder *) obj);
10072                 else if (!strcmp (obj->vtable->klass->name, "MonoField"))
10073                         field = ((MonoReflectionField *) obj)->field;
10074                 else {
10075                         field = NULL; /* prevent compiler warning */
10076                         g_assert_not_reached ();
10077                 }
10078
10079                 dgclass->fields [i] = *field;
10080                 dgclass->fields [i].parent = klass;
10081                 dgclass->fields [i].type = mono_class_inflate_generic_type (
10082                         field->type, mono_generic_class_get_context ((MonoGenericClass *) dgclass));
10083                 dgclass->field_generic_types [i] = field->type;
10084                 MOVING_GC_REGISTER (&dgclass->field_objects [i]);
10085                 dgclass->field_objects [i] = obj;
10086
10087                 if (inflated_field) {
10088                         g_free (inflated_field);
10089                 } else {
10090                         dgclass->fields [i].name = g_strdup (dgclass->fields [i].name);
10091                 }
10092         }
10093
10094         for (i = 0; i < dgclass->count_properties; i++) {
10095                 MonoObject *obj = mono_array_get (properties, gpointer, i);
10096                 MonoProperty *property = &dgclass->properties [i];
10097
10098                 if (!strcmp (obj->vtable->klass->name, "PropertyBuilder")) {
10099                         MonoReflectionPropertyBuilder *pb = (MonoReflectionPropertyBuilder *) obj;
10100
10101                         property->parent = klass;
10102                         property->attrs = pb->attrs;
10103                         property->name = mono_string_to_utf8 (pb->name);
10104                         if (pb->get_method)
10105                                 property->get = inflate_method (type, (MonoObject *) pb->get_method);
10106                         if (pb->set_method)
10107                                 property->set = inflate_method (type, (MonoObject *) pb->set_method);
10108                 } else if (!strcmp (obj->vtable->klass->name, "MonoProperty")) {
10109                         *property = *((MonoReflectionProperty *) obj)->property;
10110                         property->name = g_strdup (property->name);
10111
10112                         if (property->get)
10113                                 property->get = inflate_mono_method (klass, property->get, NULL);
10114                         if (property->set)
10115                                 property->set = inflate_mono_method (klass, property->set, NULL);
10116                 } else
10117                         g_assert_not_reached ();
10118         }
10119
10120         for (i = 0; i < dgclass->count_events; i++) {
10121                 MonoObject *obj = mono_array_get (events, gpointer, i);
10122                 MonoEvent *event = &dgclass->events [i];
10123
10124                 if (!strcmp (obj->vtable->klass->name, "EventBuilder")) {
10125                         MonoReflectionEventBuilder *eb = (MonoReflectionEventBuilder *) obj;
10126
10127                         event->parent = klass;
10128                         event->attrs = eb->attrs;
10129                         event->name = mono_string_to_utf8 (eb->name);
10130                         if (eb->add_method)
10131                                 event->add = inflate_method (type, (MonoObject *) eb->add_method);
10132                         if (eb->remove_method)
10133                                 event->remove = inflate_method (type, (MonoObject *) eb->remove_method);
10134                 } else if (!strcmp (obj->vtable->klass->name, "MonoEvent")) {
10135                         *event = *((MonoReflectionMonoEvent *) obj)->event;
10136                         event->name = g_strdup (event->name);
10137
10138                         if (event->add)
10139                                 event->add = inflate_mono_method (klass, event->add, NULL);
10140                         if (event->remove)
10141                                 event->remove = inflate_mono_method (klass, event->remove, NULL);
10142                 } else
10143                         g_assert_not_reached ();
10144         }
10145
10146         dgclass->initialized = TRUE;
10147 }
10148
10149 static void
10150 ensure_generic_class_runtime_vtable (MonoClass *klass)
10151 {
10152         MonoClass *gklass = klass->generic_class->container_class;
10153         int i;
10154
10155         if (klass->wastypebuilder)
10156                 return;
10157
10158         ensure_runtime_vtable (gklass);
10159
10160         klass->method.count = gklass->method.count;
10161         klass->methods = mono_image_alloc (klass->image, sizeof (MonoMethod*) * (klass->method.count + 1));
10162
10163         for (i = 0; i < klass->method.count; i++) {
10164                 klass->methods [i] = mono_class_inflate_generic_method_full (
10165                         gklass->methods [i], klass, mono_class_get_context (klass));
10166         }
10167
10168         klass->interface_count = gklass->interface_count;
10169         klass->interfaces = mono_image_alloc (klass->image, sizeof (MonoClass*) * klass->interface_count);
10170         for (i = 0; i < klass->interface_count; ++i) {
10171                 MonoType *iface_type = mono_class_inflate_generic_type (&gklass->interfaces [i]->byval_arg, mono_class_get_context (klass));
10172                 klass->interfaces [i] = mono_class_from_mono_type (iface_type);
10173                 mono_metadata_free_type (iface_type);
10174
10175                 ensure_runtime_vtable (klass->interfaces [i]);
10176         }
10177         klass->interfaces_inited = 1;
10178
10179         /*We can only finish with this klass once it's parent has as well*/
10180         if (gklass->wastypebuilder)
10181                 klass->wastypebuilder = TRUE;
10182         return;
10183 }
10184
10185 static void
10186 ensure_runtime_vtable (MonoClass *klass)
10187 {
10188         MonoReflectionTypeBuilder *tb = klass->reflection_info;
10189         int i, num, j;
10190
10191         if (!klass->image->dynamic || (!tb && !klass->generic_class) || klass->wastypebuilder)
10192                 return;
10193         if (klass->parent)
10194                 ensure_runtime_vtable (klass->parent);
10195
10196         if (tb) {
10197                 num = tb->ctors? mono_array_length (tb->ctors): 0;
10198                 num += tb->num_methods;
10199                 klass->method.count = num;
10200                 klass->methods = mono_image_alloc (klass->image, sizeof (MonoMethod*) * num);
10201                 num = tb->ctors? mono_array_length (tb->ctors): 0;
10202                 for (i = 0; i < num; ++i)
10203                         klass->methods [i] = ctorbuilder_to_mono_method (klass, mono_array_get (tb->ctors, MonoReflectionCtorBuilder*, i));
10204                 num = tb->num_methods;
10205                 j = i;
10206                 for (i = 0; i < num; ++i)
10207                         klass->methods [j++] = methodbuilder_to_mono_method (klass, mono_array_get (tb->methods, MonoReflectionMethodBuilder*, i));
10208         
10209                 if (tb->interfaces) {
10210                         klass->interface_count = mono_array_length (tb->interfaces);
10211                         klass->interfaces = mono_image_alloc (klass->image, sizeof (MonoClass*) * klass->interface_count);
10212                         for (i = 0; i < klass->interface_count; ++i) {
10213                                 MonoType *iface = mono_type_array_get_and_resolve (tb->interfaces, i);
10214                                 klass->interfaces [i] = mono_class_from_mono_type (iface);
10215                                 ensure_runtime_vtable (klass->interfaces [i]);
10216                         }
10217                         klass->interfaces_inited = 1;
10218                 }
10219         } else if (klass->generic_class){
10220                 ensure_generic_class_runtime_vtable (klass);
10221         }
10222
10223         if (klass->flags & TYPE_ATTRIBUTE_INTERFACE) {
10224                 for (i = 0; i < klass->method.count; ++i)
10225                         klass->methods [i]->slot = i;
10226                 
10227                 mono_class_setup_interface_offsets (klass);
10228                 mono_class_setup_interface_id (klass);
10229         }
10230
10231         /*
10232          * The generic vtable is needed even if image->run is not set since some
10233          * runtime code like ves_icall_Type_GetMethodsByName depends on 
10234          * method->slot being defined.
10235          */
10236
10237         /* 
10238          * tb->methods could not be freed since it is used for determining 
10239          * overrides during dynamic vtable construction.
10240          */
10241 }
10242
10243 void
10244 mono_reflection_get_dynamic_overrides (MonoClass *klass, MonoMethod ***overrides, int *num_overrides)
10245 {
10246         MonoReflectionTypeBuilder *tb;
10247         int i, onum;
10248
10249         *overrides = NULL;
10250         *num_overrides = 0;
10251
10252         g_assert (klass->image->dynamic);
10253
10254         if (!klass->reflection_info)
10255                 return;
10256
10257         g_assert (strcmp (((MonoObject*)klass->reflection_info)->vtable->klass->name, "TypeBuilder") == 0);
10258
10259         tb = (MonoReflectionTypeBuilder*)klass->reflection_info;
10260
10261         onum = 0;
10262         if (tb->methods) {
10263                 for (i = 0; i < tb->num_methods; ++i) {
10264                         MonoReflectionMethodBuilder *mb = 
10265                                 mono_array_get (tb->methods, MonoReflectionMethodBuilder*, i);
10266                         if (mb->override_method)
10267                                 onum ++;
10268                 }
10269         }
10270
10271         if (onum) {
10272                 *overrides = g_new0 (MonoMethod*, onum * 2);
10273
10274                 onum = 0;
10275                 for (i = 0; i < tb->num_methods; ++i) {
10276                         MonoReflectionMethodBuilder *mb = 
10277                                 mono_array_get (tb->methods, MonoReflectionMethodBuilder*, i);
10278                         if (mb->override_method) {
10279                                 (*overrides) [onum * 2] = 
10280                                         mb->override_method->method;
10281                                 (*overrides) [onum * 2 + 1] =
10282                                         mb->mhandle;
10283
10284                                 /* FIXME: What if 'override_method' is a MethodBuilder ? */
10285                                 g_assert (mb->override_method->method);
10286                                 g_assert (mb->mhandle);
10287
10288                                 onum ++;
10289                         }
10290                 }
10291         }
10292
10293         *num_overrides = onum;
10294 }
10295
10296 static void
10297 typebuilder_setup_fields (MonoClass *klass)
10298 {
10299         MonoReflectionTypeBuilder *tb = klass->reflection_info;
10300         MonoReflectionFieldBuilder *fb;
10301         MonoClassField *field;
10302         MonoImage *image = klass->image;
10303         const char *p, *p2;
10304         int i;
10305         guint32 len, idx, real_size = 0;
10306
10307         klass->field.count = tb->num_fields;
10308         klass->field.first = 0;
10309
10310         if (tb->class_size) {
10311                 g_assert ((tb->packing_size & 0xfffffff0) == 0);
10312                 klass->packing_size = tb->packing_size;
10313                 real_size = klass->instance_size + tb->class_size;
10314         }
10315
10316         if (!klass->field.count) {
10317                 klass->instance_size = MAX (klass->instance_size, real_size);
10318                 return;
10319         }
10320         
10321         klass->fields = image_g_new0 (image, MonoClassField, klass->field.count);
10322         mono_class_alloc_ext (klass);
10323         klass->ext->field_def_values = image_g_new0 (image, MonoFieldDefaultValue, klass->field.count);
10324
10325         for (i = 0; i < klass->field.count; ++i) {
10326                 fb = mono_array_get (tb->fields, gpointer, i);
10327                 field = &klass->fields [i];
10328                 field->name = mono_string_to_utf8_image (image, fb->name);
10329                 if (fb->attrs) {
10330                         field->type = mono_metadata_type_dup (klass->image, mono_reflection_type_get_handle ((MonoReflectionType*)fb->type));
10331                         field->type->attrs = fb->attrs;
10332                 } else {
10333                         field->type = mono_reflection_type_get_handle ((MonoReflectionType*)fb->type);
10334                 }
10335                 if ((fb->attrs & FIELD_ATTRIBUTE_HAS_FIELD_RVA) && fb->rva_data)
10336                         klass->ext->field_def_values [i].data = mono_array_addr (fb->rva_data, char, 0);
10337                 if (fb->offset != -1)
10338                         field->offset = fb->offset;
10339                 field->parent = klass;
10340                 fb->handle = field;
10341                 mono_save_custom_attrs (klass->image, field, fb->cattrs);
10342
10343                 if (fb->def_value) {
10344                         MonoDynamicImage *assembly = (MonoDynamicImage*)klass->image;
10345                         field->type->attrs |= FIELD_ATTRIBUTE_HAS_DEFAULT;
10346                         idx = encode_constant (assembly, fb->def_value, &klass->ext->field_def_values [i].def_type);
10347                         /* Copy the data from the blob since it might get realloc-ed */
10348                         p = assembly->blob.data + idx;
10349                         len = mono_metadata_decode_blob_size (p, &p2);
10350                         len += p2 - p;
10351                         klass->ext->field_def_values [i].data = mono_image_alloc (image, len);
10352                         memcpy ((gpointer)klass->ext->field_def_values [i].data, p, len);
10353                 }
10354         }
10355
10356         klass->instance_size = MAX (klass->instance_size, real_size);
10357         mono_class_layout_fields (klass);
10358 }
10359
10360 static void
10361 typebuilder_setup_properties (MonoClass *klass)
10362 {
10363         MonoReflectionTypeBuilder *tb = klass->reflection_info;
10364         MonoReflectionPropertyBuilder *pb;
10365         MonoImage *image = klass->image;
10366         MonoProperty *properties;
10367         int i;
10368
10369         if (!klass->ext)
10370                 klass->ext = image_g_new0 (image, MonoClassExt, 1);
10371
10372         klass->ext->property.count = tb->properties ? mono_array_length (tb->properties) : 0;
10373         klass->ext->property.first = 0;
10374
10375         properties = image_g_new0 (image, MonoProperty, klass->ext->property.count);
10376         klass->ext->properties = properties;
10377         for (i = 0; i < klass->ext->property.count; ++i) {
10378                 pb = mono_array_get (tb->properties, MonoReflectionPropertyBuilder*, i);
10379                 properties [i].parent = klass;
10380                 properties [i].attrs = pb->attrs;
10381                 properties [i].name = mono_string_to_utf8_image (image, pb->name);
10382                 if (pb->get_method)
10383                         properties [i].get = pb->get_method->mhandle;
10384                 if (pb->set_method)
10385                         properties [i].set = pb->set_method->mhandle;
10386
10387                 mono_save_custom_attrs (klass->image, &properties [i], pb->cattrs);
10388         }
10389 }
10390
10391 MonoReflectionEvent *
10392 mono_reflection_event_builder_get_event_info (MonoReflectionTypeBuilder *tb, MonoReflectionEventBuilder *eb)
10393 {
10394         MonoEvent *event = g_new0 (MonoEvent, 1);
10395         MonoClass *klass;
10396         int j;
10397
10398         klass = mono_class_from_mono_type (mono_reflection_type_get_handle ((MonoReflectionType*)tb));
10399
10400         event->parent = klass;
10401         event->attrs = eb->attrs;
10402         event->name = mono_string_to_utf8 (eb->name);
10403         if (eb->add_method)
10404                 event->add = eb->add_method->mhandle;
10405         if (eb->remove_method)
10406                 event->remove = eb->remove_method->mhandle;
10407         if (eb->raise_method)
10408                 event->raise = eb->raise_method->mhandle;
10409
10410         if (eb->other_methods) {
10411                 event->other = g_new0 (MonoMethod*, mono_array_length (eb->other_methods) + 1);
10412                 for (j = 0; j < mono_array_length (eb->other_methods); ++j) {
10413                         MonoReflectionMethodBuilder *mb = 
10414                                 mono_array_get (eb->other_methods,
10415                                                 MonoReflectionMethodBuilder*, j);
10416                         event->other [j] = mb->mhandle;
10417                 }
10418         }
10419
10420         return mono_event_get_object (mono_object_domain (tb), klass, event);
10421 }
10422
10423 static void
10424 typebuilder_setup_events (MonoClass *klass)
10425 {
10426         MonoReflectionTypeBuilder *tb = klass->reflection_info;
10427         MonoReflectionEventBuilder *eb;
10428         MonoImage *image = klass->image;
10429         MonoEvent *events;
10430         int i, j;
10431
10432         if (!klass->ext)
10433                 klass->ext = image_g_new0 (image, MonoClassExt, 1);
10434
10435         klass->ext->event.count = tb->events ? mono_array_length (tb->events) : 0;
10436         klass->ext->event.first = 0;
10437
10438         events = image_g_new0 (image, MonoEvent, klass->ext->event.count);
10439         klass->ext->events = events;
10440         for (i = 0; i < klass->ext->event.count; ++i) {
10441                 eb = mono_array_get (tb->events, MonoReflectionEventBuilder*, i);
10442                 events [i].parent = klass;
10443                 events [i].attrs = eb->attrs;
10444                 events [i].name = mono_string_to_utf8_image (image, eb->name);
10445                 if (eb->add_method)
10446                         events [i].add = eb->add_method->mhandle;
10447                 if (eb->remove_method)
10448                         events [i].remove = eb->remove_method->mhandle;
10449                 if (eb->raise_method)
10450                         events [i].raise = eb->raise_method->mhandle;
10451
10452                 if (eb->other_methods) {
10453                         events [i].other = image_g_new0 (image, MonoMethod*, mono_array_length (eb->other_methods) + 1);
10454                         for (j = 0; j < mono_array_length (eb->other_methods); ++j) {
10455                                 MonoReflectionMethodBuilder *mb = 
10456                                         mono_array_get (eb->other_methods,
10457                                                                         MonoReflectionMethodBuilder*, j);
10458                                 events [i].other [j] = mb->mhandle;
10459                         }
10460                 }
10461                 mono_save_custom_attrs (klass->image, &events [i], eb->cattrs);
10462         }
10463 }
10464
10465 static gboolean
10466 remove_instantiations_of (gpointer key,
10467                                                   gpointer value,
10468                                                   gpointer user_data)
10469 {
10470         MonoType *type = (MonoType*)key;
10471         MonoClass *klass = (MonoClass*)user_data;
10472
10473         if ((type->type == MONO_TYPE_GENERICINST) && (type->data.generic_class->container_class == klass))
10474                 return TRUE;
10475         else
10476                 return FALSE;
10477 }
10478
10479 static void
10480 check_array_for_usertypes (MonoArray *arr)
10481 {
10482         int i;
10483
10484         if (!arr)
10485                 return;
10486
10487         for (i = 0; i < mono_array_length (arr); ++i)
10488                 RESOLVE_ARRAY_TYPE_ELEMENT (arr, i);
10489 }
10490
10491 MonoReflectionType*
10492 mono_reflection_create_runtime_class (MonoReflectionTypeBuilder *tb)
10493 {
10494         MonoClass *klass;
10495         MonoDomain* domain;
10496         MonoReflectionType* res;
10497         int i, j;
10498
10499         MONO_ARCH_SAVE_REGS;
10500
10501         domain = mono_object_domain (tb);
10502         klass = mono_class_from_mono_type (tb->type.type);
10503
10504         /*
10505          * Check for user defined Type subclasses.
10506          */
10507         RESOLVE_TYPE (tb->parent);
10508         check_array_for_usertypes (tb->interfaces);
10509         if (tb->fields) {
10510                 for (i = 0; i < mono_array_length (tb->fields); ++i) {
10511                         MonoReflectionFieldBuilder *fb = mono_array_get (tb->fields, gpointer, i);
10512                         if (fb) {
10513                                 RESOLVE_TYPE (fb->type);
10514                                 check_array_for_usertypes (fb->modreq);
10515                                 check_array_for_usertypes (fb->modopt);
10516                                 if (fb->marshal_info && fb->marshal_info->marshaltyperef)
10517                                         RESOLVE_TYPE (fb->marshal_info->marshaltyperef);
10518                         }
10519                 }
10520         }
10521         if (tb->methods) {
10522                 for (i = 0; i < mono_array_length (tb->methods); ++i) {
10523                         MonoReflectionMethodBuilder *mb = mono_array_get (tb->methods, gpointer, i);
10524                         if (mb) {
10525                                 RESOLVE_TYPE (mb->rtype);
10526                                 check_array_for_usertypes (mb->return_modreq);
10527                                 check_array_for_usertypes (mb->return_modopt);
10528                                 check_array_for_usertypes (mb->parameters);
10529                                 if (mb->param_modreq)
10530                                         for (j = 0; j < mono_array_length (mb->param_modreq); ++j)
10531                                                 check_array_for_usertypes (mono_array_get (mb->param_modreq, MonoArray*, j));
10532                                 if (mb->param_modopt)
10533                                         for (j = 0; j < mono_array_length (mb->param_modopt); ++j)
10534                                                 check_array_for_usertypes (mono_array_get (mb->param_modopt, MonoArray*, j));
10535                         }
10536                 }
10537         }
10538         if (tb->ctors) {
10539                 for (i = 0; i < mono_array_length (tb->ctors); ++i) {
10540                         MonoReflectionCtorBuilder *mb = mono_array_get (tb->ctors, gpointer, i);
10541                         if (mb) {
10542                                 check_array_for_usertypes (mb->parameters);
10543                                 if (mb->param_modreq)
10544                                         for (j = 0; j < mono_array_length (mb->param_modreq); ++j)
10545                                                 check_array_for_usertypes (mono_array_get (mb->param_modreq, MonoArray*, j));
10546                                 if (mb->param_modopt)
10547                                         for (j = 0; j < mono_array_length (mb->param_modopt); ++j)
10548                                                 check_array_for_usertypes (mono_array_get (mb->param_modopt, MonoArray*, j));
10549                         }
10550                 }
10551         }
10552
10553         mono_save_custom_attrs (klass->image, klass, tb->cattrs);
10554
10555         /* 
10556          * we need to lock the domain because the lock will be taken inside
10557          * So, we need to keep the locking order correct.
10558          */
10559         mono_loader_lock ();
10560         mono_domain_lock (domain);
10561         if (klass->wastypebuilder) {
10562                 mono_domain_unlock (domain);
10563                 mono_loader_unlock ();
10564                 return mono_type_get_object (mono_object_domain (tb), &klass->byval_arg);
10565         }
10566         /*
10567          * Fields to set in klass:
10568          * the various flags: delegate/unicode/contextbound etc.
10569          */
10570         klass->flags = tb->attrs;
10571         klass->has_cctor = 1;
10572         klass->has_finalize = 1;
10573
10574 #if 0
10575         if (!((MonoDynamicImage*)klass->image)->run) {
10576                 if (klass->generic_container) {
10577                         /* FIXME: The code below can't handle generic classes */
10578                         klass->wastypebuilder = TRUE;
10579                         mono_loader_unlock ();
10580                         mono_domain_unlock (domain);
10581                         return mono_type_get_object (mono_object_domain (tb), &klass->byval_arg);
10582                 }
10583         }
10584 #endif
10585
10586         /* enums are done right away */
10587         if (!klass->enumtype)
10588                 ensure_runtime_vtable (klass);
10589
10590         if (tb->subtypes) {
10591                 for (i = 0; i < mono_array_length (tb->subtypes); ++i) {
10592                         MonoReflectionTypeBuilder *subtb = mono_array_get (tb->subtypes, MonoReflectionTypeBuilder*, i);
10593                         mono_class_alloc_ext (klass);
10594                         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)));
10595                 }
10596         }
10597
10598         klass->nested_classes_inited = TRUE;
10599
10600         /* fields and object layout */
10601         if (klass->parent) {
10602                 if (!klass->parent->size_inited)
10603                         mono_class_init (klass->parent);
10604                 klass->instance_size = klass->parent->instance_size;
10605                 klass->sizes.class_size = 0;
10606                 klass->min_align = klass->parent->min_align;
10607                 /* if the type has no fields we won't call the field_setup
10608                  * routine which sets up klass->has_references.
10609                  */
10610                 klass->has_references |= klass->parent->has_references;
10611         } else {
10612                 klass->instance_size = sizeof (MonoObject);
10613                 klass->min_align = 1;
10614         }
10615
10616         /* FIXME: handle packing_size and instance_size */
10617         typebuilder_setup_fields (klass);
10618
10619         typebuilder_setup_properties (klass);
10620
10621         typebuilder_setup_events (klass);
10622         
10623         klass->wastypebuilder = TRUE;
10624
10625         /* 
10626          * If we are a generic TypeBuilder, there might be instantiations in the type cache
10627          * which have type System.Reflection.MonoGenericClass, but after the type is created, 
10628          * we want to return normal System.MonoType objects, so clear these out from the cache.
10629          */
10630         if (domain->type_hash && klass->generic_container)
10631                 mono_g_hash_table_foreach_remove (domain->type_hash, remove_instantiations_of, klass);
10632
10633         mono_domain_unlock (domain);
10634         mono_loader_unlock ();
10635
10636         if (klass->enumtype && !mono_class_is_valid_enum (klass)) {
10637                 mono_class_set_failure (klass, MONO_EXCEPTION_TYPE_LOAD, NULL);
10638                 mono_raise_exception (mono_get_exception_type_load (tb->name, NULL));
10639         }
10640
10641         res = mono_type_get_object (mono_object_domain (tb), &klass->byval_arg);
10642         g_assert (res != (MonoReflectionType*)tb);
10643
10644         return res;
10645 }
10646
10647 void
10648 mono_reflection_initialize_generic_parameter (MonoReflectionGenericParam *gparam)
10649 {
10650         MonoGenericParamFull *param;
10651         MonoImage *image;
10652         MonoClass *pklass;
10653
10654         MONO_ARCH_SAVE_REGS;
10655
10656         param = g_new0 (MonoGenericParamFull, 1);
10657
10658         if (gparam->mbuilder) {
10659                 if (!gparam->mbuilder->generic_container) {
10660                         MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder *)gparam->mbuilder->type;
10661                         MonoClass *klass = mono_class_from_mono_type (mono_reflection_type_get_handle ((MonoReflectionType*)tb));
10662                         gparam->mbuilder->generic_container = mono_image_alloc0 (klass->image, sizeof (MonoGenericContainer));
10663                         gparam->mbuilder->generic_container->is_method = TRUE;
10664                         /* 
10665                          * Cannot set owner.method, since the MonoMethod is not created yet.
10666                          * Set the image field instead, so type_in_image () works.
10667                          */
10668                         gparam->mbuilder->generic_container->image = klass->image;
10669                 }
10670                 param->param.owner = gparam->mbuilder->generic_container;
10671         } else if (gparam->tbuilder) {
10672                 if (!gparam->tbuilder->generic_container) {
10673                         MonoClass *klass = mono_class_from_mono_type (mono_reflection_type_get_handle ((MonoReflectionType*)gparam->tbuilder));
10674                         gparam->tbuilder->generic_container = mono_image_alloc0 (klass->image, sizeof (MonoGenericContainer));
10675                         gparam->tbuilder->generic_container->owner.klass = klass;
10676                 }
10677                 param->param.owner = gparam->tbuilder->generic_container;
10678         }
10679
10680         param->info.name = mono_string_to_utf8 (gparam->name);
10681         param->param.num = gparam->index;
10682
10683         image = &gparam->tbuilder->module->dynamic_image->image;
10684         pklass = mono_class_from_generic_parameter ((MonoGenericParam *) param, image, gparam->mbuilder != NULL);
10685
10686         gparam->type.type = &pklass->byval_arg;
10687
10688         MOVING_GC_REGISTER (&pklass->reflection_info);
10689         pklass->reflection_info = gparam; /* FIXME: GC pin gparam */
10690         mono_image_lock (image);
10691         image->reflection_info_unregister_classes = g_slist_prepend (image->reflection_info_unregister_classes, pklass);
10692         mono_image_unlock (image);
10693 }
10694
10695 MonoArray *
10696 mono_reflection_sighelper_get_signature_local (MonoReflectionSigHelper *sig)
10697 {
10698         MonoReflectionModuleBuilder *module = sig->module;
10699         MonoDynamicImage *assembly = module != NULL ? module->dynamic_image : NULL;
10700         guint32 na = sig->arguments ? mono_array_length (sig->arguments) : 0;
10701         guint32 buflen, i;
10702         MonoArray *result;
10703         SigBuffer buf;
10704
10705         check_array_for_usertypes (sig->arguments);
10706
10707         sigbuffer_init (&buf, 32);
10708
10709         sigbuffer_add_value (&buf, 0x07);
10710         sigbuffer_add_value (&buf, na);
10711         if (assembly != NULL){
10712                 for (i = 0; i < na; ++i) {
10713                         MonoReflectionType *type = mono_array_get (sig->arguments, MonoReflectionType*, i);
10714                         encode_reflection_type (assembly, type, &buf);
10715                 }
10716         }
10717
10718         buflen = buf.p - buf.buf;
10719         result = mono_array_new (mono_domain_get (), mono_defaults.byte_class, buflen);
10720         memcpy (mono_array_addr (result, char, 0), buf.buf, buflen);
10721         sigbuffer_free (&buf);
10722
10723         return result;
10724 }
10725
10726 MonoArray *
10727 mono_reflection_sighelper_get_signature_field (MonoReflectionSigHelper *sig)
10728 {
10729         MonoDynamicImage *assembly = sig->module->dynamic_image;
10730         guint32 na = sig->arguments ? mono_array_length (sig->arguments) : 0;
10731         guint32 buflen, i;
10732         MonoArray *result;
10733         SigBuffer buf;
10734
10735         check_array_for_usertypes (sig->arguments);
10736
10737         sigbuffer_init (&buf, 32);
10738
10739         sigbuffer_add_value (&buf, 0x06);
10740         for (i = 0; i < na; ++i) {
10741                 MonoReflectionType *type = mono_array_get (sig->arguments, MonoReflectionType*, i);
10742                 encode_reflection_type (assembly, type, &buf);
10743         }
10744
10745         buflen = buf.p - buf.buf;
10746         result = mono_array_new (mono_domain_get (), mono_defaults.byte_class, buflen);
10747         memcpy (mono_array_addr (result, char, 0), buf.buf, buflen);
10748         sigbuffer_free (&buf);
10749
10750         return result;
10751 }
10752
10753 void 
10754 mono_reflection_create_dynamic_method (MonoReflectionDynamicMethod *mb)
10755 {
10756         ReflectionMethodBuilder rmb;
10757         MonoMethodSignature *sig;
10758         MonoClass *klass;
10759         GSList *l;
10760         int i;
10761
10762         sig = dynamic_method_to_signature (mb);
10763
10764         reflection_methodbuilder_from_dynamic_method (&rmb, mb);
10765
10766         /*
10767          * Resolve references.
10768          */
10769         /* 
10770          * Every second entry in the refs array is reserved for storing handle_class,
10771          * which is needed by the ldtoken implementation in the JIT.
10772          */
10773         rmb.nrefs = mb->nrefs;
10774         rmb.refs = g_new0 (gpointer, mb->nrefs + 1);
10775         for (i = 0; i < mb->nrefs; i += 2) {
10776                 MonoClass *handle_class;
10777                 gpointer ref;
10778                 MonoObject *obj = mono_array_get (mb->refs, MonoObject*, i);
10779
10780                 if (strcmp (obj->vtable->klass->name, "DynamicMethod") == 0) {
10781                         MonoReflectionDynamicMethod *method = (MonoReflectionDynamicMethod*)obj;
10782                         /*
10783                          * The referenced DynamicMethod should already be created by the managed
10784                          * code, except in the case of circular references. In that case, we store
10785                          * method in the refs array, and fix it up later when the referenced 
10786                          * DynamicMethod is created.
10787                          */
10788                         if (method->mhandle) {
10789                                 ref = method->mhandle;
10790                         } else {
10791                                 /* FIXME: GC object stored in unmanaged memory */
10792                                 ref = method;
10793
10794                                 /* FIXME: GC object stored in unmanaged memory */
10795                                 method->referenced_by = g_slist_append (method->referenced_by, mb);
10796                         }
10797                         handle_class = mono_defaults.methodhandle_class;
10798                 } else {
10799                         MonoException *ex = NULL;
10800                         ref = resolve_object (mb->module->image, obj, &handle_class, NULL);
10801                         if (!ref)
10802                                 ex = mono_get_exception_type_load (NULL, NULL);
10803                         else if (mono_security_get_mode () == MONO_SECURITY_MODE_CORE_CLR)
10804                                 ex = mono_security_core_clr_ensure_dynamic_method_resolved_object (ref, handle_class);
10805
10806                         if (ex) {
10807                                 g_free (rmb.refs);
10808                                 mono_raise_exception (ex);
10809                                 return;
10810                         }
10811                 }
10812
10813                 rmb.refs [i] = ref; /* FIXME: GC object stored in unmanaged memory (change also resolve_object() signature) */
10814                 rmb.refs [i + 1] = handle_class;
10815         }               
10816
10817         klass = mb->owner ? mono_class_from_mono_type (mono_reflection_type_get_handle ((MonoReflectionType*)mb->owner)) : mono_defaults.object_class;
10818
10819         mb->mhandle = reflection_methodbuilder_to_mono_method (klass, &rmb, sig);
10820
10821         /* Fix up refs entries pointing at us */
10822         for (l = mb->referenced_by; l; l = l->next) {
10823                 MonoReflectionDynamicMethod *method = (MonoReflectionDynamicMethod*)l->data;
10824                 MonoMethodWrapper *wrapper = (MonoMethodWrapper*)method->mhandle;
10825                 gpointer *data;
10826                 
10827                 g_assert (method->mhandle);
10828
10829                 data = (gpointer*)wrapper->method_data;
10830                 for (i = 0; i < GPOINTER_TO_UINT (data [0]); i += 2) {
10831                         if ((data [i + 1] == mb) && (data [i + 1 + 1] == mono_defaults.methodhandle_class))
10832                                 data [i + 1] = mb->mhandle;
10833                 }
10834         }
10835         g_slist_free (mb->referenced_by);
10836
10837         g_free (rmb.refs);
10838
10839         /* ilgen is no longer needed */
10840         mb->ilgen = NULL;
10841 }
10842
10843 #endif /* DISABLE_REFLECTION_EMIT */
10844
10845 void
10846 mono_reflection_destroy_dynamic_method (MonoReflectionDynamicMethod *mb)
10847 {
10848         g_assert (mb);
10849
10850         if (mb->mhandle)
10851                 mono_runtime_free_method (
10852                         mono_object_get_domain ((MonoObject*)mb), mb->mhandle);
10853 }
10854
10855 /**
10856  * 
10857  * mono_reflection_is_valid_dynamic_token:
10858  * 
10859  * Returns TRUE if token is valid.
10860  * 
10861  */
10862 gboolean
10863 mono_reflection_is_valid_dynamic_token (MonoDynamicImage *image, guint32 token)
10864 {
10865         return mono_g_hash_table_lookup (image->tokens, GUINT_TO_POINTER (token)) != NULL;
10866 }
10867
10868 #ifndef DISABLE_REFLECTION_EMIT
10869
10870 /**
10871  * mono_reflection_lookup_dynamic_token:
10872  *
10873  * Finish the Builder object pointed to by TOKEN and return the corresponding
10874  * runtime structure. If HANDLE_CLASS is not NULL, it is set to the class required by 
10875  * mono_ldtoken. If valid_token is TRUE, assert if it is not found in the token->object
10876  * mapping table.
10877  *
10878  * LOCKING: Take the loader lock
10879  */
10880 gpointer
10881 mono_reflection_lookup_dynamic_token (MonoImage *image, guint32 token, gboolean valid_token, MonoClass **handle_class, MonoGenericContext *context)
10882 {
10883         MonoDynamicImage *assembly = (MonoDynamicImage*)image;
10884         MonoObject *obj;
10885         MonoClass *klass;
10886
10887         mono_loader_lock ();
10888         obj = mono_g_hash_table_lookup (assembly->tokens, GUINT_TO_POINTER (token));
10889         mono_loader_unlock ();
10890         if (!obj) {
10891                 if (valid_token)
10892                         g_error ("Could not find required dynamic token 0x%08x", token);
10893                 else
10894                         return NULL;
10895         }
10896
10897         if (!handle_class)
10898                 handle_class = &klass;
10899         return resolve_object (image, obj, handle_class, context);
10900 }
10901
10902 /*
10903  * ensure_complete_type:
10904  *
10905  *   Ensure that KLASS is completed if it is a dynamic type, or references
10906  * dynamic types.
10907  */
10908 static void
10909 ensure_complete_type (MonoClass *klass)
10910 {
10911         if (klass->image->dynamic && !klass->wastypebuilder) {
10912                 MonoReflectionTypeBuilder *tb = klass->reflection_info;
10913
10914                 mono_domain_try_type_resolve (mono_domain_get (), NULL, (MonoObject*)tb);
10915
10916                 // Asserting here could break a lot of code
10917                 //g_assert (klass->wastypebuilder);
10918         }
10919
10920         if (klass->generic_class) {
10921                 MonoGenericInst *inst = klass->generic_class->context.class_inst;
10922                 int i;
10923
10924                 for (i = 0; i < inst->type_argc; ++i) {
10925                         ensure_complete_type (mono_class_from_mono_type (inst->type_argv [i]));
10926                 }
10927         }
10928 }
10929
10930 static gpointer
10931 resolve_object (MonoImage *image, MonoObject *obj, MonoClass **handle_class, MonoGenericContext *context)
10932 {
10933         gpointer result = NULL;
10934
10935         if (strcmp (obj->vtable->klass->name, "String") == 0) {
10936                 result = mono_string_intern ((MonoString*)obj);
10937                 *handle_class = NULL;
10938                 g_assert (result);
10939         } else if (strcmp (obj->vtable->klass->name, "MonoType") == 0) {
10940                 MonoType *type = mono_reflection_type_get_handle ((MonoReflectionType*)obj);
10941                 if (context) {
10942                         MonoType *inflated = mono_class_inflate_generic_type (type, context);
10943                         result = mono_class_from_mono_type (inflated);
10944                         mono_metadata_free_type (inflated);
10945                 } else {
10946                         result = mono_class_from_mono_type (type);
10947                 }
10948                 *handle_class = mono_defaults.typehandle_class;
10949                 g_assert (result);
10950         } else if (strcmp (obj->vtable->klass->name, "MonoMethod") == 0 ||
10951                    strcmp (obj->vtable->klass->name, "MonoCMethod") == 0 ||
10952                    strcmp (obj->vtable->klass->name, "MonoGenericCMethod") == 0 ||
10953                    strcmp (obj->vtable->klass->name, "MonoGenericMethod") == 0) {
10954                 result = ((MonoReflectionMethod*)obj)->method;
10955                 if (context)
10956                         result = mono_class_inflate_generic_method (result, context);
10957                 *handle_class = mono_defaults.methodhandle_class;
10958                 g_assert (result);
10959         } else if (strcmp (obj->vtable->klass->name, "MethodBuilder") == 0) {
10960                 MonoReflectionMethodBuilder *mb = (MonoReflectionMethodBuilder*)obj;
10961                 result = mb->mhandle;
10962                 if (!result) {
10963                         /* Type is not yet created */
10964                         MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder*)mb->type;
10965
10966                         mono_domain_try_type_resolve (mono_domain_get (), NULL, (MonoObject*)tb);
10967
10968                         /*
10969                          * Hopefully this has been filled in by calling CreateType() on the
10970                          * TypeBuilder.
10971                          */
10972                         /*
10973                          * TODO: This won't work if the application finishes another 
10974                          * TypeBuilder instance instead of this one.
10975                          */
10976                         result = mb->mhandle;
10977                 }
10978                 if (context)
10979                         result = mono_class_inflate_generic_method (result, context);
10980                 *handle_class = mono_defaults.methodhandle_class;
10981         } else if (strcmp (obj->vtable->klass->name, "ConstructorBuilder") == 0) {
10982                 MonoReflectionCtorBuilder *cb = (MonoReflectionCtorBuilder*)obj;
10983
10984                 result = cb->mhandle;
10985                 if (!result) {
10986                         MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder*)cb->type;
10987
10988                         mono_domain_try_type_resolve (mono_domain_get (), NULL, (MonoObject*)tb);
10989                         result = cb->mhandle;
10990                 }
10991                 if (context)
10992                         result = mono_class_inflate_generic_method (result, context);
10993                 *handle_class = mono_defaults.methodhandle_class;
10994         } else if (strcmp (obj->vtable->klass->name, "MonoField") == 0) {
10995                 MonoClassField *field = ((MonoReflectionField*)obj)->field;
10996
10997                 ensure_complete_type (field->parent);
10998                 if (context) {
10999                         MonoType *inflated = mono_class_inflate_generic_type (&field->parent->byval_arg, context);
11000                         MonoClass *class = mono_class_from_mono_type (inflated);
11001                         MonoClassField *inflated_field;
11002                         gpointer iter = NULL;
11003                         mono_metadata_free_type (inflated);
11004                         while ((inflated_field = mono_class_get_fields (class, &iter))) {
11005                                 if (!strcmp (field->name, inflated_field->name))
11006                                         break;
11007                         }
11008                         g_assert (inflated_field && !strcmp (field->name, inflated_field->name));
11009                         result = inflated_field;
11010                 } else {
11011                         result = field;
11012                 }
11013                 *handle_class = mono_defaults.fieldhandle_class;
11014                 g_assert (result);
11015         } else if (strcmp (obj->vtable->klass->name, "FieldBuilder") == 0) {
11016                 MonoReflectionFieldBuilder *fb = (MonoReflectionFieldBuilder*)obj;
11017                 result = fb->handle;
11018
11019                 if (!result) {
11020                         MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder*)fb->typeb;
11021
11022                         mono_domain_try_type_resolve (mono_domain_get (), NULL, (MonoObject*)tb);
11023                         result = fb->handle;
11024                 }
11025
11026                 if (fb->handle && fb->handle->parent->generic_container) {
11027                         MonoClass *klass = fb->handle->parent;
11028                         MonoType *type = mono_class_inflate_generic_type (&klass->byval_arg, context);
11029                         MonoClass *inflated = mono_class_from_mono_type (type);
11030
11031                         result = mono_class_get_field_from_name (inflated, mono_field_get_name (fb->handle));
11032                         g_assert (result);
11033                         mono_metadata_free_type (type);
11034                 }
11035                 *handle_class = mono_defaults.fieldhandle_class;
11036         } else if (strcmp (obj->vtable->klass->name, "TypeBuilder") == 0) {
11037                 MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder*)obj;
11038                 MonoType *type = mono_reflection_type_get_handle ((MonoReflectionType*)tb); 
11039                 MonoClass *klass;
11040
11041                 klass = type->data.klass;
11042                 if (klass->wastypebuilder) {
11043                         /* Already created */
11044                         result = klass;
11045                 }
11046                 else {
11047                         mono_domain_try_type_resolve (mono_domain_get (), NULL, (MonoObject*)tb);
11048                         result = type->data.klass;
11049                         g_assert (result);
11050                 }
11051                 *handle_class = mono_defaults.typehandle_class;
11052         } else if (strcmp (obj->vtable->klass->name, "SignatureHelper") == 0) {
11053                 MonoReflectionSigHelper *helper = (MonoReflectionSigHelper*)obj;
11054                 MonoMethodSignature *sig;
11055                 int nargs, i;
11056
11057                 if (helper->arguments)
11058                         nargs = mono_array_length (helper->arguments);
11059                 else
11060                         nargs = 0;
11061
11062                 sig = mono_metadata_signature_alloc (image, nargs);
11063                 sig->explicit_this = helper->call_conv & 64 ? 1 : 0;
11064                 sig->hasthis = helper->call_conv & 32 ? 1 : 0;
11065
11066                 if (helper->call_conv == 0) /* unmanaged */
11067                         sig->call_convention = helper->unmanaged_call_conv - 1;
11068                 else
11069                         if (helper->call_conv & 0x02)
11070                                 sig->call_convention = MONO_CALL_VARARG;
11071                 else
11072                         sig->call_convention = MONO_CALL_DEFAULT;
11073
11074                 sig->param_count = nargs;
11075                 /* TODO: Copy type ? */
11076                 sig->ret = helper->return_type->type;
11077                 for (i = 0; i < nargs; ++i)
11078                         sig->params [i] = mono_type_array_get_and_resolve (helper->arguments, i);
11079
11080                 result = sig;
11081                 *handle_class = NULL;
11082         } else if (strcmp (obj->vtable->klass->name, "DynamicMethod") == 0) {
11083                 MonoReflectionDynamicMethod *method = (MonoReflectionDynamicMethod*)obj;
11084                 /* Already created by the managed code */
11085                 g_assert (method->mhandle);
11086                 result = method->mhandle;
11087                 *handle_class = mono_defaults.methodhandle_class;
11088         } else if (strcmp (obj->vtable->klass->name, "GenericTypeParameterBuilder") == 0) {
11089                 MonoType *type = mono_reflection_type_get_handle ((MonoReflectionType*)obj);
11090                 type = mono_class_inflate_generic_type (type, context);
11091                 result = mono_class_from_mono_type (type);
11092                 *handle_class = mono_defaults.typehandle_class;
11093                 g_assert (result);
11094                 mono_metadata_free_type (type);
11095         } else if (strcmp (obj->vtable->klass->name, "MonoGenericClass") == 0) {
11096                 MonoType *type = mono_reflection_type_get_handle ((MonoReflectionType*)obj);
11097                 type = mono_class_inflate_generic_type (type, context);
11098                 result = mono_class_from_mono_type (type);
11099                 *handle_class = mono_defaults.typehandle_class;
11100                 g_assert (result);
11101                 mono_metadata_free_type (type);
11102         } else if (strcmp (obj->vtable->klass->name, "FieldOnTypeBuilderInst") == 0) {
11103                 MonoReflectionFieldOnTypeBuilderInst *f = (MonoReflectionFieldOnTypeBuilderInst*)obj;
11104                 MonoClass *inflated;
11105                 MonoType *type;
11106
11107                 type = mono_class_inflate_generic_type (mono_reflection_type_get_handle ((MonoReflectionType*)f->inst), context);
11108                 inflated = mono_class_from_mono_type (type);
11109
11110                 g_assert (f->fb->handle);
11111                 result = mono_class_get_field_from_name (inflated, mono_field_get_name (f->fb->handle));
11112                 g_assert (result);
11113                 mono_metadata_free_type (type);
11114                 *handle_class = mono_defaults.fieldhandle_class;
11115         } else if (strcmp (obj->vtable->klass->name, "ConstructorOnTypeBuilderInst") == 0) {
11116                 MonoReflectionCtorOnTypeBuilderInst *c = (MonoReflectionCtorOnTypeBuilderInst*)obj;
11117                 MonoType *type = mono_class_inflate_generic_type (mono_reflection_type_get_handle ((MonoReflectionType*)c->inst), context);
11118                 MonoClass *inflated_klass = mono_class_from_mono_type (type);
11119                 g_assert (c->cb->mhandle);
11120                 result = inflate_mono_method (inflated_klass, c->cb->mhandle, (MonoObject*)c->cb);
11121                 *handle_class = mono_defaults.methodhandle_class;
11122                 mono_metadata_free_type (type);
11123         } else if (strcmp (obj->vtable->klass->name, "MethodOnTypeBuilderInst") == 0) {
11124                 MonoReflectionMethodOnTypeBuilderInst *m = (MonoReflectionMethodOnTypeBuilderInst*)obj;
11125                 if (m->method_args) {
11126                         result = mono_reflection_method_on_tb_inst_get_handle (m);
11127                 } else {
11128                         MonoType *type = mono_class_inflate_generic_type (mono_reflection_type_get_handle ((MonoReflectionType*)m->inst), context);
11129                         MonoClass *inflated_klass = mono_class_from_mono_type (type);
11130                         g_assert (m->mb->mhandle);
11131                         result = inflate_mono_method (inflated_klass, m->mb->mhandle, (MonoObject*)m->mb);
11132                         mono_metadata_free_type (type);
11133                 }
11134                 *handle_class = mono_defaults.methodhandle_class;
11135         } else if (is_sre_array (mono_object_get_class(obj)) ||
11136                                 is_sre_byref (mono_object_get_class(obj)) ||
11137                                 is_sre_pointer (mono_object_get_class(obj))) {
11138                 MonoReflectionType *ref_type = (MonoReflectionType *)obj;
11139                 MonoType *type = mono_reflection_type_get_handle (ref_type);
11140                 result = mono_class_from_mono_type (type);
11141                 *handle_class = mono_defaults.typehandle_class;
11142         } else {
11143                 g_print ("%s\n", obj->vtable->klass->name);
11144                 g_assert_not_reached ();
11145         }
11146         return result;
11147 }
11148
11149 #else /* DISABLE_REFLECTION_EMIT */
11150
11151 MonoArray*
11152 mono_reflection_get_custom_attrs_blob (MonoReflectionAssembly *assembly, MonoObject *ctor, MonoArray *ctorArgs, MonoArray *properties, MonoArray *propValues, MonoArray *fields, MonoArray* fieldValues) 
11153 {
11154         g_assert_not_reached ();
11155         return NULL;
11156 }
11157
11158 void
11159 mono_reflection_setup_internal_class (MonoReflectionTypeBuilder *tb)
11160 {
11161         g_assert_not_reached ();
11162 }
11163
11164 void
11165 mono_reflection_setup_generic_class (MonoReflectionTypeBuilder *tb)
11166 {
11167         g_assert_not_reached ();
11168 }
11169
11170 void
11171 mono_reflection_create_generic_class (MonoReflectionTypeBuilder *tb)
11172 {
11173         g_assert_not_reached ();
11174 }
11175
11176 void
11177 mono_reflection_create_internal_class (MonoReflectionTypeBuilder *tb)
11178 {
11179         g_assert_not_reached ();
11180 }
11181
11182 void
11183 mono_image_basic_init (MonoReflectionAssemblyBuilder *assemblyb)
11184 {
11185         g_error ("This mono runtime was configured with --enable-minimal=reflection_emit, so System.Reflection.Emit is not supported.");
11186 }
11187
11188 void
11189 mono_image_module_basic_init (MonoReflectionModuleBuilder *moduleb)
11190 {
11191         g_assert_not_reached ();
11192 }
11193
11194 void
11195 mono_image_set_wrappers_type (MonoReflectionModuleBuilder *moduleb, MonoReflectionType *type)
11196 {
11197         g_assert_not_reached ();
11198 }
11199
11200 MonoReflectionModule *
11201 mono_image_load_module_dynamic (MonoReflectionAssemblyBuilder *ab, MonoString *fileName)
11202 {
11203         g_assert_not_reached ();
11204         return NULL;
11205 }
11206
11207 guint32
11208 mono_image_insert_string (MonoReflectionModuleBuilder *module, MonoString *str)
11209 {
11210         g_assert_not_reached ();
11211         return 0;
11212 }
11213
11214 guint32
11215 mono_image_create_method_token (MonoDynamicImage *assembly, MonoObject *obj, MonoArray *opt_param_types)
11216 {
11217         g_assert_not_reached ();
11218         return 0;
11219 }
11220
11221 guint32
11222 mono_image_create_token (MonoDynamicImage *assembly, MonoObject *obj, 
11223                                                  gboolean create_methodspec, gboolean register_token)
11224 {
11225         g_assert_not_reached ();
11226         return 0;
11227 }
11228
11229 void
11230 mono_image_register_token (MonoDynamicImage *assembly, guint32 token, MonoObject *obj)
11231 {
11232 }
11233
11234 void
11235 mono_reflection_generic_class_initialize (MonoReflectionGenericClass *type, MonoArray *methods, 
11236                                           MonoArray *ctors, MonoArray *fields, MonoArray *properties,
11237                                           MonoArray *events)
11238 {
11239         g_assert_not_reached ();
11240 }
11241
11242 void
11243 mono_reflection_get_dynamic_overrides (MonoClass *klass, MonoMethod ***overrides, int *num_overrides)
11244 {
11245         *overrides = NULL;
11246         *num_overrides = 0;
11247 }
11248
11249 MonoReflectionEvent *
11250 mono_reflection_event_builder_get_event_info (MonoReflectionTypeBuilder *tb, MonoReflectionEventBuilder *eb)
11251 {
11252         g_assert_not_reached ();
11253         return NULL;
11254 }
11255
11256 MonoReflectionType*
11257 mono_reflection_create_runtime_class (MonoReflectionTypeBuilder *tb)
11258 {
11259         g_assert_not_reached ();
11260         return NULL;
11261 }
11262
11263 void
11264 mono_reflection_initialize_generic_parameter (MonoReflectionGenericParam *gparam)
11265 {
11266         g_assert_not_reached ();
11267 }
11268
11269 MonoArray *
11270 mono_reflection_sighelper_get_signature_local (MonoReflectionSigHelper *sig)
11271 {
11272         g_assert_not_reached ();
11273         return NULL;
11274 }
11275
11276 MonoArray *
11277 mono_reflection_sighelper_get_signature_field (MonoReflectionSigHelper *sig)
11278 {
11279         g_assert_not_reached ();
11280         return NULL;
11281 }
11282
11283 void 
11284 mono_reflection_create_dynamic_method (MonoReflectionDynamicMethod *mb)
11285 {
11286 }
11287
11288 gpointer
11289 mono_reflection_lookup_dynamic_token (MonoImage *image, guint32 token, gboolean valid_token, MonoClass **handle_class, MonoGenericContext *context)
11290 {
11291         return NULL;
11292 }
11293
11294 MonoType*
11295 mono_reflection_type_get_handle (MonoReflectionType* ref)
11296 {
11297         if (!ref)
11298                 return NULL;
11299         return ref->type;
11300 }
11301
11302 #endif /* DISABLE_REFLECTION_EMIT */
11303
11304 /* SECURITY_ACTION_* are defined in mono/metadata/tabledefs.h */
11305 const static guint32 declsec_flags_map[] = {
11306         0x00000000,                                     /* empty */
11307         MONO_DECLSEC_FLAG_REQUEST,                      /* SECURITY_ACTION_REQUEST                      (x01) */
11308         MONO_DECLSEC_FLAG_DEMAND,                       /* SECURITY_ACTION_DEMAND                       (x02) */
11309         MONO_DECLSEC_FLAG_ASSERT,                       /* SECURITY_ACTION_ASSERT                       (x03) */
11310         MONO_DECLSEC_FLAG_DENY,                         /* SECURITY_ACTION_DENY                         (x04) */
11311         MONO_DECLSEC_FLAG_PERMITONLY,                   /* SECURITY_ACTION_PERMITONLY                   (x05) */
11312         MONO_DECLSEC_FLAG_LINKDEMAND,                   /* SECURITY_ACTION_LINKDEMAND                   (x06) */
11313         MONO_DECLSEC_FLAG_INHERITANCEDEMAND,            /* SECURITY_ACTION_INHERITANCEDEMAND            (x07) */
11314         MONO_DECLSEC_FLAG_REQUEST_MINIMUM,              /* SECURITY_ACTION_REQUEST_MINIMUM              (x08) */
11315         MONO_DECLSEC_FLAG_REQUEST_OPTIONAL,             /* SECURITY_ACTION_REQUEST_OPTIONAL             (x09) */
11316         MONO_DECLSEC_FLAG_REQUEST_REFUSE,               /* SECURITY_ACTION_REQUEST_REFUSE               (x0A) */
11317         MONO_DECLSEC_FLAG_PREJIT_GRANT,                 /* SECURITY_ACTION_PREJIT_GRANT                 (x0B) */
11318         MONO_DECLSEC_FLAG_PREJIT_DENY,                  /* SECURITY_ACTION_PREJIT_DENY                  (x0C) */
11319         MONO_DECLSEC_FLAG_NONCAS_DEMAND,                /* SECURITY_ACTION_NONCAS_DEMAND                (x0D) */
11320         MONO_DECLSEC_FLAG_NONCAS_LINKDEMAND,            /* SECURITY_ACTION_NONCAS_LINKDEMAND            (x0E) */
11321         MONO_DECLSEC_FLAG_NONCAS_INHERITANCEDEMAND,     /* SECURITY_ACTION_NONCAS_INHERITANCEDEMAND     (x0F) */
11322         MONO_DECLSEC_FLAG_LINKDEMAND_CHOICE,            /* SECURITY_ACTION_LINKDEMAND_CHOICE            (x10) */
11323         MONO_DECLSEC_FLAG_INHERITANCEDEMAND_CHOICE,     /* SECURITY_ACTION_INHERITANCEDEMAND_CHOICE     (x11) */
11324         MONO_DECLSEC_FLAG_DEMAND_CHOICE,                /* SECURITY_ACTION_DEMAND_CHOICE                (x12) */
11325 };
11326
11327 /*
11328  * Returns flags that includes all available security action associated to the handle.
11329  * @token: metadata token (either for a class or a method)
11330  * @image: image where resides the metadata.
11331  */
11332 static guint32
11333 mono_declsec_get_flags (MonoImage *image, guint32 token)
11334 {
11335         int index = mono_metadata_declsec_from_index (image, token);
11336         MonoTableInfo *t = &image->tables [MONO_TABLE_DECLSECURITY];
11337         guint32 result = 0;
11338         guint32 action;
11339         int i;
11340
11341         /* HasSecurity can be present for other, not specially encoded, attributes,
11342            e.g. SuppressUnmanagedCodeSecurityAttribute */
11343         if (index < 0)
11344                 return 0;
11345
11346         for (i = index; i < t->rows; i++) {
11347                 guint32 cols [MONO_DECL_SECURITY_SIZE];
11348
11349                 mono_metadata_decode_row (t, i, cols, MONO_DECL_SECURITY_SIZE);
11350                 if (cols [MONO_DECL_SECURITY_PARENT] != token)
11351                         break;
11352
11353                 action = cols [MONO_DECL_SECURITY_ACTION];
11354                 if ((action >= MONO_DECLSEC_ACTION_MIN) && (action <= MONO_DECLSEC_ACTION_MAX)) {
11355                         result |= declsec_flags_map [action];
11356                 } else {
11357                         g_assert_not_reached ();
11358                 }
11359         }
11360         return result;
11361 }
11362
11363 /*
11364  * Get the security actions (in the form of flags) associated with the specified method.
11365  *
11366  * @method: The method for which we want the declarative security flags.
11367  * Return the declarative security flags for the method (only).
11368  *
11369  * Note: To keep MonoMethod size down we do not cache the declarative security flags
11370  *       (except for the stack modifiers which are kept in the MonoJitInfo structure)
11371  */
11372 guint32
11373 mono_declsec_flags_from_method (MonoMethod *method)
11374 {
11375         if (method->flags & METHOD_ATTRIBUTE_HAS_SECURITY) {
11376                 /* FIXME: No cache (for the moment) */
11377                 guint32 idx = mono_method_get_index (method);
11378                 idx <<= MONO_HAS_DECL_SECURITY_BITS;
11379                 idx |= MONO_HAS_DECL_SECURITY_METHODDEF;
11380                 return mono_declsec_get_flags (method->klass->image, idx);
11381         }
11382         return 0;
11383 }
11384
11385 /*
11386  * Get the security actions (in the form of flags) associated with the specified class.
11387  *
11388  * @klass: The class for which we want the declarative security flags.
11389  * Return the declarative security flags for the class.
11390  *
11391  * Note: We cache the flags inside the MonoClass structure as this will get 
11392  *       called very often (at least for each method).
11393  */
11394 guint32
11395 mono_declsec_flags_from_class (MonoClass *klass)
11396 {
11397         if (klass->flags & TYPE_ATTRIBUTE_HAS_SECURITY) {
11398                 if (!klass->ext || !klass->ext->declsec_flags) {
11399                         guint32 idx;
11400
11401                         idx = mono_metadata_token_index (klass->type_token);
11402                         idx <<= MONO_HAS_DECL_SECURITY_BITS;
11403                         idx |= MONO_HAS_DECL_SECURITY_TYPEDEF;
11404                         mono_loader_lock ();
11405                         mono_class_alloc_ext (klass);
11406                         mono_loader_unlock ();
11407                         /* we cache the flags on classes */
11408                         klass->ext->declsec_flags = mono_declsec_get_flags (klass->image, idx);
11409                 }
11410                 return klass->ext->declsec_flags;
11411         }
11412         return 0;
11413 }
11414
11415 /*
11416  * Get the security actions (in the form of flags) associated with the specified assembly.
11417  *
11418  * @assembly: The assembly for which we want the declarative security flags.
11419  * Return the declarative security flags for the assembly.
11420  */
11421 guint32
11422 mono_declsec_flags_from_assembly (MonoAssembly *assembly)
11423 {
11424         guint32 idx = 1; /* there is only one assembly */
11425         idx <<= MONO_HAS_DECL_SECURITY_BITS;
11426         idx |= MONO_HAS_DECL_SECURITY_ASSEMBLY;
11427         return mono_declsec_get_flags (assembly->image, idx);
11428 }
11429
11430
11431 /*
11432  * Fill actions for the specific index (which may either be an encoded class token or
11433  * an encoded method token) from the metadata image.
11434  * Returns TRUE if some actions requiring code generation are present, FALSE otherwise.
11435  */
11436 static MonoBoolean
11437 fill_actions_from_index (MonoImage *image, guint32 token, MonoDeclSecurityActions* actions,
11438         guint32 id_std, guint32 id_noncas, guint32 id_choice)
11439 {
11440         MonoBoolean result = FALSE;
11441         MonoTableInfo *t;
11442         guint32 cols [MONO_DECL_SECURITY_SIZE];
11443         int index = mono_metadata_declsec_from_index (image, token);
11444         int i;
11445
11446         t  = &image->tables [MONO_TABLE_DECLSECURITY];
11447         for (i = index; i < t->rows; i++) {
11448                 mono_metadata_decode_row (t, i, cols, MONO_DECL_SECURITY_SIZE);
11449
11450                 if (cols [MONO_DECL_SECURITY_PARENT] != token)
11451                         return result;
11452
11453                 /* if present only replace (class) permissions with method permissions */
11454                 /* if empty accept either class or method permissions */
11455                 if (cols [MONO_DECL_SECURITY_ACTION] == id_std) {
11456                         if (!actions->demand.blob) {
11457                                 const char *blob = mono_metadata_blob_heap (image, cols [MONO_DECL_SECURITY_PERMISSIONSET]);
11458                                 actions->demand.index = cols [MONO_DECL_SECURITY_PERMISSIONSET];
11459                                 actions->demand.blob = (char*) (blob + 2);
11460                                 actions->demand.size = mono_metadata_decode_blob_size (blob, &blob);
11461                                 result = TRUE;
11462                         }
11463                 } else if (cols [MONO_DECL_SECURITY_ACTION] == id_noncas) {
11464                         if (!actions->noncasdemand.blob) {
11465                                 const char *blob = mono_metadata_blob_heap (image, cols [MONO_DECL_SECURITY_PERMISSIONSET]);
11466                                 actions->noncasdemand.index = cols [MONO_DECL_SECURITY_PERMISSIONSET];
11467                                 actions->noncasdemand.blob = (char*) (blob + 2);
11468                                 actions->noncasdemand.size = mono_metadata_decode_blob_size (blob, &blob);
11469                                 result = TRUE;
11470                         }
11471                 } else if (cols [MONO_DECL_SECURITY_ACTION] == id_choice) {
11472                         if (!actions->demandchoice.blob) {
11473                                 const char *blob = mono_metadata_blob_heap (image, cols [MONO_DECL_SECURITY_PERMISSIONSET]);
11474                                 actions->demandchoice.index = cols [MONO_DECL_SECURITY_PERMISSIONSET];
11475                                 actions->demandchoice.blob = (char*) (blob + 2);
11476                                 actions->demandchoice.size = mono_metadata_decode_blob_size (blob, &blob);
11477                                 result = TRUE;
11478                         }
11479                 }
11480         }
11481
11482         return result;
11483 }
11484
11485 static MonoBoolean
11486 mono_declsec_get_class_demands_params (MonoClass *klass, MonoDeclSecurityActions* demands, 
11487         guint32 id_std, guint32 id_noncas, guint32 id_choice)
11488 {
11489         guint32 idx = mono_metadata_token_index (klass->type_token);
11490         idx <<= MONO_HAS_DECL_SECURITY_BITS;
11491         idx |= MONO_HAS_DECL_SECURITY_TYPEDEF;
11492         return fill_actions_from_index (klass->image, idx, demands, id_std, id_noncas, id_choice);
11493 }
11494
11495 static MonoBoolean
11496 mono_declsec_get_method_demands_params (MonoMethod *method, MonoDeclSecurityActions* demands, 
11497         guint32 id_std, guint32 id_noncas, guint32 id_choice)
11498 {
11499         guint32 idx = mono_method_get_index (method);
11500         idx <<= MONO_HAS_DECL_SECURITY_BITS;
11501         idx |= MONO_HAS_DECL_SECURITY_METHODDEF;
11502         return fill_actions_from_index (method->klass->image, idx, demands, id_std, id_noncas, id_choice);
11503 }
11504
11505 /*
11506  * Collect all actions (that requires to generate code in mini) assigned for
11507  * the specified method.
11508  * Note: Don't use the content of actions if the function return FALSE.
11509  */
11510 MonoBoolean
11511 mono_declsec_get_demands (MonoMethod *method, MonoDeclSecurityActions* demands)
11512 {
11513         guint32 mask = MONO_DECLSEC_FLAG_DEMAND | MONO_DECLSEC_FLAG_NONCAS_DEMAND | 
11514                 MONO_DECLSEC_FLAG_DEMAND_CHOICE;
11515         MonoBoolean result = FALSE;
11516         guint32 flags;
11517
11518         /* quick exit if no declarative security is present in the metadata */
11519         if (!method->klass->image->tables [MONO_TABLE_DECLSECURITY].rows)
11520                 return FALSE;
11521
11522         /* we want the original as the wrapper is "free" of the security informations */
11523         if (method->wrapper_type == MONO_WRAPPER_MANAGED_TO_NATIVE || method->wrapper_type == MONO_WRAPPER_MANAGED_TO_MANAGED) {
11524                 method = mono_marshal_method_from_wrapper (method);
11525                 if (!method)
11526                         return FALSE;
11527         }
11528
11529         /* First we look for method-level attributes */
11530         if (method->flags & METHOD_ATTRIBUTE_HAS_SECURITY) {
11531                 mono_class_init (method->klass);
11532                 memset (demands, 0, sizeof (MonoDeclSecurityActions));
11533
11534                 result = mono_declsec_get_method_demands_params (method, demands, 
11535                         SECURITY_ACTION_DEMAND, SECURITY_ACTION_NONCASDEMAND, SECURITY_ACTION_DEMANDCHOICE);
11536         }
11537
11538         /* Here we use (or create) the class declarative cache to look for demands */
11539         flags = mono_declsec_flags_from_class (method->klass);
11540         if (flags & mask) {
11541                 if (!result) {
11542                         mono_class_init (method->klass);
11543                         memset (demands, 0, sizeof (MonoDeclSecurityActions));
11544                 }
11545                 result |= mono_declsec_get_class_demands_params (method->klass, demands, 
11546                         SECURITY_ACTION_DEMAND, SECURITY_ACTION_NONCASDEMAND, SECURITY_ACTION_DEMANDCHOICE);
11547         }
11548
11549         /* The boolean return value is used as a shortcut in case nothing needs to
11550            be generated (e.g. LinkDemand[Choice] and InheritanceDemand[Choice]) */
11551         return result;
11552 }
11553
11554
11555 /*
11556  * Collect all Link actions: LinkDemand, NonCasLinkDemand and LinkDemandChoice (2.0).
11557  *
11558  * Note: Don't use the content of actions if the function return FALSE.
11559  */
11560 MonoBoolean
11561 mono_declsec_get_linkdemands (MonoMethod *method, MonoDeclSecurityActions* klass, MonoDeclSecurityActions *cmethod)
11562 {
11563         MonoBoolean result = FALSE;
11564         guint32 flags;
11565
11566         /* quick exit if no declarative security is present in the metadata */
11567         if (!method->klass->image->tables [MONO_TABLE_DECLSECURITY].rows)
11568                 return FALSE;
11569
11570         /* we want the original as the wrapper is "free" of the security informations */
11571         if (method->wrapper_type == MONO_WRAPPER_MANAGED_TO_NATIVE || method->wrapper_type == MONO_WRAPPER_MANAGED_TO_MANAGED) {
11572                 method = mono_marshal_method_from_wrapper (method);
11573                 if (!method)
11574                         return FALSE;
11575         }
11576
11577         /* results are independant - zeroize both */
11578         memset (cmethod, 0, sizeof (MonoDeclSecurityActions));
11579         memset (klass, 0, sizeof (MonoDeclSecurityActions));
11580
11581         /* First we look for method-level attributes */
11582         if (method->flags & METHOD_ATTRIBUTE_HAS_SECURITY) {
11583                 mono_class_init (method->klass);
11584
11585                 result = mono_declsec_get_method_demands_params (method, cmethod, 
11586                         SECURITY_ACTION_LINKDEMAND, SECURITY_ACTION_NONCASLINKDEMAND, SECURITY_ACTION_LINKDEMANDCHOICE);
11587         }
11588
11589         /* Here we use (or create) the class declarative cache to look for demands */
11590         flags = mono_declsec_flags_from_class (method->klass);
11591         if (flags & (MONO_DECLSEC_FLAG_LINKDEMAND | MONO_DECLSEC_FLAG_NONCAS_LINKDEMAND | MONO_DECLSEC_FLAG_LINKDEMAND_CHOICE)) {
11592                 mono_class_init (method->klass);
11593
11594                 result |= mono_declsec_get_class_demands_params (method->klass, klass, 
11595                         SECURITY_ACTION_LINKDEMAND, SECURITY_ACTION_NONCASLINKDEMAND, SECURITY_ACTION_LINKDEMANDCHOICE);
11596         }
11597
11598         return result;
11599 }
11600
11601 /*
11602  * Collect all Inherit actions: InheritanceDemand, NonCasInheritanceDemand and InheritanceDemandChoice (2.0).
11603  *
11604  * @klass       The inherited class - this is the class that provides the security check (attributes)
11605  * @demans      
11606  * return TRUE if inheritance demands (any kind) are present, FALSE otherwise.
11607  * 
11608  * Note: Don't use the content of actions if the function return FALSE.
11609  */
11610 MonoBoolean
11611 mono_declsec_get_inheritdemands_class (MonoClass *klass, MonoDeclSecurityActions* demands)
11612 {
11613         MonoBoolean result = FALSE;
11614         guint32 flags;
11615
11616         /* quick exit if no declarative security is present in the metadata */
11617         if (!klass->image->tables [MONO_TABLE_DECLSECURITY].rows)
11618                 return FALSE;
11619
11620         /* Here we use (or create) the class declarative cache to look for demands */
11621         flags = mono_declsec_flags_from_class (klass);
11622         if (flags & (MONO_DECLSEC_FLAG_INHERITANCEDEMAND | MONO_DECLSEC_FLAG_NONCAS_INHERITANCEDEMAND | MONO_DECLSEC_FLAG_INHERITANCEDEMAND_CHOICE)) {
11623                 mono_class_init (klass);
11624                 memset (demands, 0, sizeof (MonoDeclSecurityActions));
11625
11626                 result |= mono_declsec_get_class_demands_params (klass, demands, 
11627                         SECURITY_ACTION_INHERITDEMAND, SECURITY_ACTION_NONCASINHERITANCE, SECURITY_ACTION_INHERITDEMANDCHOICE);
11628         }
11629
11630         return result;
11631 }
11632
11633 /*
11634  * Collect all Inherit actions: InheritanceDemand, NonCasInheritanceDemand and InheritanceDemandChoice (2.0).
11635  *
11636  * Note: Don't use the content of actions if the function return FALSE.
11637  */
11638 MonoBoolean
11639 mono_declsec_get_inheritdemands_method (MonoMethod *method, MonoDeclSecurityActions* demands)
11640 {
11641         /* quick exit if no declarative security is present in the metadata */
11642         if (!method->klass->image->tables [MONO_TABLE_DECLSECURITY].rows)
11643                 return FALSE;
11644
11645         /* we want the original as the wrapper is "free" of the security informations */
11646         if (method->wrapper_type == MONO_WRAPPER_MANAGED_TO_NATIVE || method->wrapper_type == MONO_WRAPPER_MANAGED_TO_MANAGED) {
11647                 method = mono_marshal_method_from_wrapper (method);
11648                 if (!method)
11649                         return FALSE;
11650         }
11651
11652         if (method->flags & METHOD_ATTRIBUTE_HAS_SECURITY) {
11653                 mono_class_init (method->klass);
11654                 memset (demands, 0, sizeof (MonoDeclSecurityActions));
11655
11656                 return mono_declsec_get_method_demands_params (method, demands, 
11657                         SECURITY_ACTION_INHERITDEMAND, SECURITY_ACTION_NONCASINHERITANCE, SECURITY_ACTION_INHERITDEMANDCHOICE);
11658         }
11659         return FALSE;
11660 }
11661
11662
11663 static MonoBoolean
11664 get_declsec_action (MonoImage *image, guint32 token, guint32 action, MonoDeclSecurityEntry *entry)
11665 {
11666         guint32 cols [MONO_DECL_SECURITY_SIZE];
11667         MonoTableInfo *t;
11668         int i;
11669
11670         int index = mono_metadata_declsec_from_index (image, token);
11671         if (index == -1)
11672                 return FALSE;
11673
11674         t =  &image->tables [MONO_TABLE_DECLSECURITY];
11675         for (i = index; i < t->rows; i++) {
11676                 mono_metadata_decode_row (t, i, cols, MONO_DECL_SECURITY_SIZE);
11677
11678                 /* shortcut - index are ordered */
11679                 if (token != cols [MONO_DECL_SECURITY_PARENT])
11680                         return FALSE;
11681
11682                 if (cols [MONO_DECL_SECURITY_ACTION] == action) {
11683                         const char *metadata = mono_metadata_blob_heap (image, cols [MONO_DECL_SECURITY_PERMISSIONSET]);
11684                         entry->blob = (char*) (metadata + 2);
11685                         entry->size = mono_metadata_decode_blob_size (metadata, &metadata);
11686                         return TRUE;
11687                 }
11688         }
11689
11690         return FALSE;
11691 }
11692
11693 MonoBoolean
11694 mono_declsec_get_method_action (MonoMethod *method, guint32 action, MonoDeclSecurityEntry *entry)
11695 {
11696         if (method->flags & METHOD_ATTRIBUTE_HAS_SECURITY) {
11697                 guint32 idx = mono_method_get_index (method);
11698                 idx <<= MONO_HAS_DECL_SECURITY_BITS;
11699                 idx |= MONO_HAS_DECL_SECURITY_METHODDEF;
11700                 return get_declsec_action (method->klass->image, idx, action, entry);
11701         }
11702         return FALSE;
11703 }
11704
11705 MonoBoolean
11706 mono_declsec_get_class_action (MonoClass *klass, guint32 action, MonoDeclSecurityEntry *entry)
11707 {
11708         /* use cache */
11709         guint32 flags = mono_declsec_flags_from_class (klass);
11710         if (declsec_flags_map [action] & flags) {
11711                 guint32 idx = mono_metadata_token_index (klass->type_token);
11712                 idx <<= MONO_HAS_DECL_SECURITY_BITS;
11713                 idx |= MONO_HAS_DECL_SECURITY_TYPEDEF;
11714                 return get_declsec_action (klass->image, idx, action, entry);
11715         }
11716         return FALSE;
11717 }
11718
11719 MonoBoolean
11720 mono_declsec_get_assembly_action (MonoAssembly *assembly, guint32 action, MonoDeclSecurityEntry *entry)
11721 {
11722         guint32 idx = 1; /* there is only one assembly */
11723         idx <<= MONO_HAS_DECL_SECURITY_BITS;
11724         idx |= MONO_HAS_DECL_SECURITY_ASSEMBLY;
11725
11726         return get_declsec_action (assembly->image, idx, action, entry);
11727 }
11728
11729 gboolean
11730 mono_reflection_call_is_assignable_to (MonoClass *klass, MonoClass *oklass)
11731 {
11732         MonoObject *res, *exc;
11733         void *params [1];
11734         static MonoClass *System_Reflection_Emit_TypeBuilder = NULL;
11735         static MonoMethod *method = NULL;
11736
11737         if (!System_Reflection_Emit_TypeBuilder) {
11738                 System_Reflection_Emit_TypeBuilder = mono_class_from_name (mono_defaults.corlib, "System.Reflection.Emit", "TypeBuilder");
11739                 g_assert (System_Reflection_Emit_TypeBuilder);
11740         }
11741         if (method == NULL) {
11742                 method = mono_class_get_method_from_name (System_Reflection_Emit_TypeBuilder, "IsAssignableTo", 1);
11743                 g_assert (method);
11744         }
11745
11746         /* 
11747          * The result of mono_type_get_object () might be a System.MonoType but we
11748          * need a TypeBuilder so use klass->reflection_info.
11749          */
11750         g_assert (klass->reflection_info);
11751         g_assert (!strcmp (((MonoObject*)(klass->reflection_info))->vtable->klass->name, "TypeBuilder"));
11752
11753         params [0] = mono_type_get_object (mono_domain_get (), &oklass->byval_arg);
11754
11755         res = mono_runtime_invoke (method, (MonoObject*)(klass->reflection_info), params, &exc);
11756         if (exc)
11757                 return FALSE;
11758         else
11759                 return *(MonoBoolean*)mono_object_unbox (res);
11760 }