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