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