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