New tests, updates
[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 = mono_get_runtime_info ()->runtime_version;
4556
4557 #if HAVE_BOEHM_GC
4558         image = GC_MALLOC (sizeof (MonoDynamicImage));
4559 #else
4560         image = g_new0 (MonoDynamicImage, 1);
4561 #endif
4562         
4563         mono_profiler_module_event (&image->image, MONO_PROFILE_START_LOAD);
4564         
4565         /*g_print ("created image %p\n", image);*/
4566         /* keep in sync with image.c */
4567         image->image.name = assembly_name;
4568         image->image.assembly_name = image->image.name; /* they may be different */
4569         image->image.module_name = module_name;
4570         image->image.version = g_strdup (version);
4571         image->image.md_version_major = 1;
4572         image->image.md_version_minor = 1;
4573         image->image.dynamic = TRUE;
4574
4575         image->image.references = g_new0 (MonoAssembly*, 1);
4576         image->image.references [0] = NULL;
4577
4578         mono_image_init (&image->image);
4579
4580         image->token_fixups = mono_g_hash_table_new_type (NULL, NULL, MONO_HASH_KEY_GC);
4581         image->method_to_table_idx = g_hash_table_new (NULL, NULL);
4582         image->field_to_table_idx = g_hash_table_new (NULL, NULL);
4583         image->method_aux_hash = g_hash_table_new (NULL, NULL);
4584         image->handleref = g_hash_table_new (NULL, NULL);
4585         image->tokens = mono_g_hash_table_new_type (NULL, NULL, MONO_HASH_VALUE_GC);
4586         image->generic_def_objects = mono_g_hash_table_new_type (NULL, NULL, MONO_HASH_VALUE_GC);
4587         image->methodspec = mono_g_hash_table_new_type (NULL, NULL, MONO_HASH_KEY_GC);
4588         image->typespec = g_hash_table_new ((GHashFunc)mono_metadata_type_hash, (GCompareFunc)mono_metadata_type_equal);
4589         image->typeref = g_hash_table_new ((GHashFunc)mono_metadata_type_hash, (GCompareFunc)mono_metadata_type_equal);
4590         image->blob_cache = g_hash_table_new ((GHashFunc)mono_blob_entry_hash, (GCompareFunc)mono_blob_entry_equal);
4591         image->gen_params = g_ptr_array_new ();
4592
4593         /*g_print ("string heap create for image %p (%s)\n", image, module_name);*/
4594         string_heap_init (&image->sheap);
4595         mono_image_add_stream_data (&image->us, "", 1);
4596         add_to_blob_cached (image, (char*) "", 1, NULL, 0);
4597         /* import tables... */
4598         mono_image_add_stream_data (&image->code, (char*)entrycode, sizeof (entrycode));
4599         image->iat_offset = mono_image_add_stream_zero (&image->code, 8); /* two IAT entries */
4600         image->idt_offset = mono_image_add_stream_zero (&image->code, 2 * sizeof (MonoIDT)); /* two IDT entries */
4601         image->imp_names_offset = mono_image_add_stream_zero (&image->code, 2); /* flags for name entry */
4602         mono_image_add_stream_data (&image->code, "_CorExeMain", 12);
4603         mono_image_add_stream_data (&image->code, "mscoree.dll", 12);
4604         image->ilt_offset = mono_image_add_stream_zero (&image->code, 8); /* two ILT entries */
4605         stream_data_align (&image->code);
4606
4607         image->cli_header_offset = mono_image_add_stream_zero (&image->code, sizeof (MonoCLIHeader));
4608
4609         for (i=0; i < MONO_TABLE_NUM; ++i) {
4610                 image->tables [i].next_idx = 1;
4611                 image->tables [i].columns = table_sizes [i];
4612         }
4613
4614         image->image.assembly = (MonoAssembly*)assembly;
4615         image->run = assembly->run;
4616         image->save = assembly->save;
4617         image->pe_kind = 0x1; /* ILOnly */
4618         image->machine = 0x14c; /* I386 */
4619         
4620         mono_profiler_module_loaded (&image->image, MONO_PROFILE_OK);
4621
4622         return image;
4623 }
4624
4625 static void
4626 free_blob_cache_entry (gpointer key, gpointer val, gpointer user_data)
4627 {
4628         g_free (key);
4629 }
4630
4631 void
4632 mono_dynamic_image_free (MonoDynamicImage *image)
4633 {
4634         MonoDynamicImage *di = image;
4635         GList *list;
4636         int i;
4637
4638         if (di->methodspec)
4639                 mono_g_hash_table_destroy (di->methodspec);
4640         if (di->typespec)
4641                 g_hash_table_destroy (di->typespec);
4642         if (di->typeref)
4643                 g_hash_table_destroy (di->typeref);
4644         if (di->handleref)
4645                 g_hash_table_destroy (di->handleref);
4646         if (di->tokens)
4647                 mono_g_hash_table_destroy (di->tokens);
4648         if (di->generic_def_objects)
4649                 mono_g_hash_table_destroy (di->generic_def_objects);
4650         if (di->blob_cache) {
4651                 g_hash_table_foreach (di->blob_cache, free_blob_cache_entry, NULL);
4652                 g_hash_table_destroy (di->blob_cache);
4653         }
4654         for (list = di->array_methods; list; list = list->next) {
4655                 ArrayMethod *am = (ArrayMethod *)list->data;
4656                 g_free (am->sig);
4657                 g_free (am->name);
4658                 g_free (am);
4659         }
4660         g_list_free (di->array_methods);
4661         if (di->gen_params) {
4662                 for (i = 0; i < di->gen_params->len; i++) {
4663                         GenericParamTableEntry *entry = g_ptr_array_index (di->gen_params, i);
4664                         if (entry->gparam->type.type) {
4665                                 MonoGenericParam *param = entry->gparam->type.type->data.generic_param;
4666                                 g_free ((char*)param->name);
4667                                 g_free (param);
4668                                 g_free (entry->gparam->type.type);
4669                         }
4670                         g_free (entry);
4671                 }
4672                 g_ptr_array_free (di->gen_params, TRUE);
4673         }
4674         if (di->token_fixups)
4675                 mono_g_hash_table_destroy (di->token_fixups);
4676         if (di->method_to_table_idx)
4677                 g_hash_table_destroy (di->method_to_table_idx);
4678         if (di->field_to_table_idx)
4679                 g_hash_table_destroy (di->field_to_table_idx);
4680         if (di->method_aux_hash)
4681                 g_hash_table_destroy (di->method_aux_hash);
4682         g_free (di->strong_name);
4683         g_free (di->win32_res);
4684         if (di->public_key)
4685                 g_free (di->public_key);
4686
4687         /*g_print ("string heap destroy for image %p\n", di);*/
4688         mono_dynamic_stream_reset (&di->sheap);
4689         mono_dynamic_stream_reset (&di->code);
4690         mono_dynamic_stream_reset (&di->resources);
4691         mono_dynamic_stream_reset (&di->us);
4692         mono_dynamic_stream_reset (&di->blob);
4693         mono_dynamic_stream_reset (&di->tstream);
4694         mono_dynamic_stream_reset (&di->guid);
4695         for (i = 0; i < MONO_TABLE_NUM; ++i) {
4696                 g_free (di->tables [i].values);
4697         }
4698 }       
4699
4700 /*
4701  * mono_image_basic_init:
4702  * @assembly: an assembly builder object
4703  *
4704  * Create the MonoImage that represents the assembly builder and setup some
4705  * of the helper hash table and the basic metadata streams.
4706  */
4707 void
4708 mono_image_basic_init (MonoReflectionAssemblyBuilder *assemblyb)
4709 {
4710         MonoDynamicAssembly *assembly;
4711         MonoDynamicImage *image;
4712         MonoDomain *domain = mono_object_domain (assemblyb);
4713         
4714         MONO_ARCH_SAVE_REGS;
4715
4716         if (assemblyb->dynamic_assembly)
4717                 return;
4718
4719 #if HAVE_BOEHM_GC
4720         assembly = assemblyb->dynamic_assembly = GC_MALLOC (sizeof (MonoDynamicAssembly));
4721 #else
4722         assembly = assemblyb->dynamic_assembly = g_new0 (MonoDynamicAssembly, 1);
4723 #endif
4724
4725         mono_profiler_assembly_event (&assembly->assembly, MONO_PROFILE_START_LOAD);
4726         
4727         assembly->assembly.ref_count = 1;
4728         assembly->assembly.dynamic = TRUE;
4729         assembly->assembly.corlib_internal = assemblyb->corlib_internal;
4730         assemblyb->assembly.assembly = (MonoAssembly*)assembly;
4731         assembly->assembly.basedir = mono_string_to_utf8 (assemblyb->dir);
4732         if (assemblyb->culture)
4733                 assembly->assembly.aname.culture = mono_string_to_utf8 (assemblyb->culture);
4734         else
4735                 assembly->assembly.aname.culture = g_strdup ("");
4736
4737         if (assemblyb->version) {
4738                         char *vstr = mono_string_to_utf8 (assemblyb->version);
4739                         char **version = g_strsplit (vstr, ".", 4);
4740                         char **parts = version;
4741                         assembly->assembly.aname.major = atoi (*parts++);
4742                         assembly->assembly.aname.minor = atoi (*parts++);
4743                         assembly->assembly.aname.build = *parts != NULL ? atoi (*parts++) : 0;
4744                         assembly->assembly.aname.revision = *parts != NULL ? atoi (*parts) : 0;
4745
4746                         g_strfreev (version);
4747                         g_free (vstr);
4748         } else {
4749                         assembly->assembly.aname.major = 0;
4750                         assembly->assembly.aname.minor = 0;
4751                         assembly->assembly.aname.build = 0;
4752                         assembly->assembly.aname.revision = 0;
4753         }
4754
4755         assembly->run = assemblyb->access != 2;
4756         assembly->save = assemblyb->access != 1;
4757
4758         image = create_dynamic_mono_image (assembly, mono_string_to_utf8 (assemblyb->name), g_strdup ("RefEmit_YouForgotToDefineAModule"));
4759         image->initial_image = TRUE;
4760         assembly->assembly.aname.name = image->image.name;
4761         assembly->assembly.image = &image->image;
4762
4763         mono_domain_assemblies_lock (domain);
4764         domain->domain_assemblies = g_slist_prepend (domain->domain_assemblies, assembly);
4765         mono_domain_assemblies_unlock (domain);
4766
4767         register_assembly (mono_object_domain (assemblyb), &assemblyb->assembly, &assembly->assembly);
4768         
4769         mono_profiler_assembly_loaded (&assembly->assembly, MONO_PROFILE_OK);
4770         
4771         mono_assembly_invoke_load_hook ((MonoAssembly*)assembly);
4772 }
4773
4774 static int
4775 calc_section_size (MonoDynamicImage *assembly)
4776 {
4777         int nsections = 0;
4778
4779         /* alignment constraints */
4780         mono_image_add_stream_zero (&assembly->code, 4 - (assembly->code.index % 4));
4781         g_assert ((assembly->code.index % 4) == 0);
4782         assembly->meta_size += 3;
4783         assembly->meta_size &= ~3;
4784         mono_image_add_stream_zero (&assembly->resources, 4 - (assembly->resources.index % 4));
4785         g_assert ((assembly->resources.index % 4) == 0);
4786
4787         assembly->sections [MONO_SECTION_TEXT].size = assembly->meta_size + assembly->code.index + assembly->resources.index + assembly->strong_name_size;
4788         assembly->sections [MONO_SECTION_TEXT].attrs = SECT_FLAGS_HAS_CODE | SECT_FLAGS_MEM_EXECUTE | SECT_FLAGS_MEM_READ;
4789         nsections++;
4790
4791         if (assembly->win32_res) {
4792                 guint32 res_size = (assembly->win32_res_size + 3) & ~3;
4793
4794                 assembly->sections [MONO_SECTION_RSRC].size = res_size;
4795                 assembly->sections [MONO_SECTION_RSRC].attrs = SECT_FLAGS_HAS_INITIALIZED_DATA | SECT_FLAGS_MEM_READ;
4796                 nsections++;
4797         }
4798
4799         assembly->sections [MONO_SECTION_RELOC].size = 12;
4800         assembly->sections [MONO_SECTION_RELOC].attrs = SECT_FLAGS_MEM_READ | SECT_FLAGS_MEM_DISCARDABLE | SECT_FLAGS_HAS_INITIALIZED_DATA;
4801         nsections++;
4802
4803         return nsections;
4804 }
4805
4806 typedef struct {
4807         guint32 id;
4808         guint32 offset;
4809         GSList *children;
4810         MonoReflectionWin32Resource *win32_res; /* Only for leaf nodes */
4811 } ResTreeNode;
4812
4813 static int
4814 resource_tree_compare_by_id (gconstpointer a, gconstpointer b)
4815 {
4816         ResTreeNode *t1 = (ResTreeNode*)a;
4817         ResTreeNode *t2 = (ResTreeNode*)b;
4818
4819         return t1->id - t2->id;
4820 }
4821
4822 /*
4823  * resource_tree_create:
4824  *
4825  *  Organize the resources into a resource tree.
4826  */
4827 static ResTreeNode *
4828 resource_tree_create (MonoArray *win32_resources)
4829 {
4830         ResTreeNode *tree, *res_node, *type_node, *lang_node;
4831         GSList *l;
4832         int i;
4833
4834         tree = g_new0 (ResTreeNode, 1);
4835         
4836         for (i = 0; i < mono_array_length (win32_resources); ++i) {
4837                 MonoReflectionWin32Resource *win32_res =
4838                         (MonoReflectionWin32Resource*)mono_array_addr (win32_resources, MonoReflectionWin32Resource, i);
4839
4840                 /* Create node */
4841
4842                 /* FIXME: BUG: this stores managed references in unmanaged memory */
4843                 lang_node = g_new0 (ResTreeNode, 1);
4844                 lang_node->id = win32_res->lang_id;
4845                 lang_node->win32_res = win32_res;
4846
4847                 /* Create type node if neccesary */
4848                 type_node = NULL;
4849                 for (l = tree->children; l; l = l->next)
4850                         if (((ResTreeNode*)(l->data))->id == win32_res->res_type) {
4851                                 type_node = (ResTreeNode*)l->data;
4852                                 break;
4853                         }
4854
4855                 if (!type_node) {
4856                         type_node = g_new0 (ResTreeNode, 1);
4857                         type_node->id = win32_res->res_type;
4858
4859                         /* 
4860                          * The resource types have to be sorted otherwise
4861                          * Windows Explorer can't display the version information.
4862                          */
4863                         tree->children = g_slist_insert_sorted (tree->children, 
4864                                 type_node, resource_tree_compare_by_id);
4865                 }
4866
4867                 /* Create res node if neccesary */
4868                 res_node = NULL;
4869                 for (l = type_node->children; l; l = l->next)
4870                         if (((ResTreeNode*)(l->data))->id == win32_res->res_id) {
4871                                 res_node = (ResTreeNode*)l->data;
4872                                 break;
4873                         }
4874
4875                 if (!res_node) {
4876                         res_node = g_new0 (ResTreeNode, 1);
4877                         res_node->id = win32_res->res_id;
4878                         type_node->children = g_slist_append (type_node->children, res_node);
4879                 }
4880
4881                 res_node->children = g_slist_append (res_node->children, lang_node);
4882         }
4883
4884         return tree;
4885 }
4886
4887 /*
4888  * resource_tree_encode:
4889  * 
4890  *   Encode the resource tree into the format used in the PE file.
4891  */
4892 static void
4893 resource_tree_encode (ResTreeNode *node, char *begin, char *p, char **endbuf)
4894 {
4895         char *entries;
4896         MonoPEResourceDir dir;
4897         MonoPEResourceDirEntry dir_entry;
4898         MonoPEResourceDataEntry data_entry;
4899         GSList *l;
4900
4901         /*
4902          * For the format of the resource directory, see the article
4903          * "An In-Depth Look into the Win32 Portable Executable File Format" by
4904          * Matt Pietrek
4905          */
4906
4907         memset (&dir, 0, sizeof (dir));
4908         memset (&dir_entry, 0, sizeof (dir_entry));
4909         memset (&data_entry, 0, sizeof (data_entry));
4910
4911         g_assert (sizeof (dir) == 16);
4912         g_assert (sizeof (dir_entry) == 8);
4913         g_assert (sizeof (data_entry) == 16);
4914
4915         node->offset = p - begin;
4916
4917         /* IMAGE_RESOURCE_DIRECTORY */
4918         dir.res_id_entries = GUINT32_TO_LE (g_slist_length (node->children));
4919
4920         memcpy (p, &dir, sizeof (dir));
4921         p += sizeof (dir);
4922
4923         /* Reserve space for entries */
4924         entries = p;
4925         p += sizeof (dir_entry) * dir.res_id_entries;
4926
4927         /* Write children */
4928         for (l = node->children; l; l = l->next) {
4929                 ResTreeNode *child = (ResTreeNode*)l->data;
4930
4931                 if (child->win32_res) {
4932
4933                         child->offset = p - begin;
4934
4935                         /* IMAGE_RESOURCE_DATA_ENTRY */
4936                         data_entry.rde_data_offset = GUINT32_TO_LE (p - begin + sizeof (data_entry));
4937                         data_entry.rde_size = mono_array_length (child->win32_res->res_data);
4938
4939                         memcpy (p, &data_entry, sizeof (data_entry));
4940                         p += sizeof (data_entry);
4941
4942                         memcpy (p, mono_array_addr (child->win32_res->res_data, char, 0), data_entry.rde_size);
4943                         p += data_entry.rde_size;
4944                 } else {
4945                         resource_tree_encode (child, begin, p, &p);
4946                 }
4947         }
4948
4949         /* IMAGE_RESOURCE_ENTRY */
4950         for (l = node->children; l; l = l->next) {
4951                 ResTreeNode *child = (ResTreeNode*)l->data;
4952                 dir_entry.name_offset = GUINT32_TO_LE (child->id);
4953
4954                 dir_entry.is_dir = child->win32_res ? 0 : 1;
4955                 dir_entry.dir_offset = GUINT32_TO_LE (child->offset);
4956
4957                 memcpy (entries, &dir_entry, sizeof (dir_entry));
4958                 entries += sizeof (dir_entry);
4959         }
4960
4961         *endbuf = p;
4962 }
4963
4964 static void
4965 resource_tree_free (ResTreeNode * node)
4966 {
4967         GSList * list;
4968         for (list = node->children; list; list = list->next)
4969                 resource_tree_free ((ResTreeNode*)list->data);
4970         g_slist_free(node->children);
4971         g_free (node);
4972 }
4973
4974 static void
4975 assembly_add_win32_resources (MonoDynamicImage *assembly, MonoReflectionAssemblyBuilder *assemblyb)
4976 {
4977         char *buf;
4978         char *p;
4979         guint32 size, i;
4980         MonoReflectionWin32Resource *win32_res;
4981         ResTreeNode *tree;
4982
4983         if (!assemblyb->win32_resources)
4984                 return;
4985
4986         /*
4987          * Resources are stored in a three level tree inside the PE file.
4988          * - level one contains a node for each type of resource
4989          * - level two contains a node for each resource
4990          * - level three contains a node for each instance of a resource for a
4991          *   specific language.
4992          */
4993
4994         tree = resource_tree_create (assemblyb->win32_resources);
4995
4996         /* Estimate the size of the encoded tree */
4997         size = 0;
4998         for (i = 0; i < mono_array_length (assemblyb->win32_resources); ++i) {
4999                 win32_res = (MonoReflectionWin32Resource*)mono_array_addr (assemblyb->win32_resources, MonoReflectionWin32Resource, i);
5000                 size += mono_array_length (win32_res->res_data);
5001         }
5002         /* Directory structure */
5003         size += mono_array_length (assemblyb->win32_resources) * 256;
5004         p = buf = g_malloc (size);
5005
5006         resource_tree_encode (tree, p, p, &p);
5007
5008         g_assert (p - buf <= size);
5009
5010         assembly->win32_res = g_malloc (p - buf);
5011         assembly->win32_res_size = p - buf;
5012         memcpy (assembly->win32_res, buf, p - buf);
5013
5014         g_free (buf);
5015         resource_tree_free (tree);
5016 }
5017
5018 static void
5019 fixup_resource_directory (char *res_section, char *p, guint32 rva)
5020 {
5021         MonoPEResourceDir *dir = (MonoPEResourceDir*)p;
5022         int i;
5023
5024         p += sizeof (MonoPEResourceDir);
5025         for (i = 0; i < dir->res_named_entries + dir->res_id_entries; ++i) {
5026                 MonoPEResourceDirEntry *dir_entry = (MonoPEResourceDirEntry*)p;
5027                 char *child = res_section + (GUINT32_FROM_LE (dir_entry->dir_offset));
5028                 if (dir_entry->is_dir) {
5029                         fixup_resource_directory (res_section, child, rva);
5030                 } else {
5031                         MonoPEResourceDataEntry *data_entry = (MonoPEResourceDataEntry*)child;
5032                         data_entry->rde_data_offset = GUINT32_TO_LE (GUINT32_FROM_LE (data_entry->rde_data_offset) + rva);
5033                 }
5034
5035                 p += sizeof (MonoPEResourceDirEntry);
5036         }
5037 }
5038
5039 static void
5040 checked_write_file (HANDLE f, gconstpointer buffer, guint32 numbytes)
5041 {
5042         guint32 dummy;
5043         if (!WriteFile (f, buffer, numbytes, &dummy, NULL))
5044                 g_error ("WriteFile returned %d\n", GetLastError ());
5045 }
5046
5047 /*
5048  * mono_image_create_pefile:
5049  * @mb: a module builder object
5050  * 
5051  * This function creates the PE-COFF header, the image sections, the CLI header  * etc. all the data is written in
5052  * assembly->pefile where it can be easily retrieved later in chunks.
5053  */
5054 void
5055 mono_image_create_pefile (MonoReflectionModuleBuilder *mb, HANDLE file) {
5056         MonoMSDOSHeader *msdos;
5057         MonoDotNetHeader *header;
5058         MonoSectionTable *section;
5059         MonoCLIHeader *cli_header;
5060         guint32 size, image_size, virtual_base, text_offset;
5061         guint32 header_start, section_start, file_offset, virtual_offset;
5062         MonoDynamicImage *assembly;
5063         MonoReflectionAssemblyBuilder *assemblyb;
5064         MonoDynamicStream pefile_stream = {0};
5065         MonoDynamicStream *pefile = &pefile_stream;
5066         int i, nsections;
5067         guint32 *rva, value;
5068         guchar *p;
5069         static const unsigned char msheader[] = {
5070                 0x4d, 0x5a, 0x90, 0x00, 0x03, 0x00, 0x00, 0x00,  0x04, 0x00, 0x00, 0x00, 0xff, 0xff, 0x00, 0x00,
5071                 0xb8, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,  0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
5072                 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
5073                 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,  0x00, 0x00, 0x00, 0x00, 0x80, 0x00, 0x00, 0x00,
5074                 0x0e, 0x1f, 0xba, 0x0e, 0x00, 0xb4, 0x09, 0xcd,  0x21, 0xb8, 0x01, 0x4c, 0xcd, 0x21, 0x54, 0x68,
5075                 0x69, 0x73, 0x20, 0x70, 0x72, 0x6f, 0x67, 0x72,  0x61, 0x6d, 0x20, 0x63, 0x61, 0x6e, 0x6e, 0x6f,
5076                 0x74, 0x20, 0x62, 0x65, 0x20, 0x72, 0x75, 0x6e,  0x20, 0x69, 0x6e, 0x20, 0x44, 0x4f, 0x53, 0x20,
5077                 0x6d, 0x6f, 0x64, 0x65, 0x2e, 0x0d, 0x0d, 0x0a,  0x24, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
5078         };
5079
5080         assemblyb = mb->assemblyb;
5081
5082         mono_image_basic_init (assemblyb);
5083         assembly = mb->dynamic_image;
5084
5085         assembly->pe_kind = assemblyb->pe_kind;
5086         assembly->machine = assemblyb->machine;
5087         ((MonoDynamicImage*)assemblyb->dynamic_assembly->assembly.image)->pe_kind = assemblyb->pe_kind;
5088         ((MonoDynamicImage*)assemblyb->dynamic_assembly->assembly.image)->machine = assemblyb->machine;
5089         
5090         mono_image_build_metadata (mb);
5091
5092         if (mb->is_main && assemblyb->resources) {
5093                 int len = mono_array_length (assemblyb->resources);
5094                 for (i = 0; i < len; ++i)
5095                         assembly_add_resource (mb, assembly, (MonoReflectionResource*)mono_array_addr (assemblyb->resources, MonoReflectionResource, i));
5096         }
5097
5098         if (mb->resources) {
5099                 int len = mono_array_length (mb->resources);
5100                 for (i = 0; i < len; ++i)
5101                         assembly_add_resource (mb, assembly, (MonoReflectionResource*)mono_array_addr (mb->resources, MonoReflectionResource, i));
5102         }
5103
5104         build_compressed_metadata (assembly);
5105
5106         if (mb->is_main)
5107                 assembly_add_win32_resources (assembly, assemblyb);
5108
5109         nsections = calc_section_size (assembly);
5110         
5111         /* The DOS header and stub */
5112         g_assert (sizeof (MonoMSDOSHeader) == sizeof (msheader));
5113         mono_image_add_stream_data (pefile, (char*)msheader, sizeof (msheader));
5114
5115         /* the dotnet header */
5116         header_start = mono_image_add_stream_zero (pefile, sizeof (MonoDotNetHeader));
5117
5118         /* the section tables */
5119         section_start = mono_image_add_stream_zero (pefile, sizeof (MonoSectionTable) * nsections);
5120
5121         file_offset = section_start + sizeof (MonoSectionTable) * nsections;
5122         virtual_offset = VIRT_ALIGN;
5123         image_size = 0;
5124
5125         for (i = 0; i < MONO_SECTION_MAX; ++i) {
5126                 if (!assembly->sections [i].size)
5127                         continue;
5128                 /* align offsets */
5129                 file_offset += FILE_ALIGN - 1;
5130                 file_offset &= ~(FILE_ALIGN - 1);
5131                 virtual_offset += VIRT_ALIGN - 1;
5132                 virtual_offset &= ~(VIRT_ALIGN - 1);
5133
5134                 assembly->sections [i].offset = file_offset;
5135                 assembly->sections [i].rva = virtual_offset;
5136
5137                 file_offset += assembly->sections [i].size;
5138                 virtual_offset += assembly->sections [i].size;
5139                 image_size += (assembly->sections [i].size + VIRT_ALIGN - 1) & ~(VIRT_ALIGN - 1);
5140         }
5141
5142         file_offset += FILE_ALIGN - 1;
5143         file_offset &= ~(FILE_ALIGN - 1);
5144
5145         image_size += section_start + sizeof (MonoSectionTable) * nsections;
5146
5147         /* back-patch info */
5148         msdos = (MonoMSDOSHeader*)pefile->data;
5149         msdos->pe_offset = GUINT32_FROM_LE (sizeof (MonoMSDOSHeader));
5150
5151         header = (MonoDotNetHeader*)(pefile->data + header_start);
5152         header->pesig [0] = 'P';
5153         header->pesig [1] = 'E';
5154         
5155         header->coff.coff_machine = GUINT16_FROM_LE (assemblyb->machine);
5156         header->coff.coff_sections = GUINT16_FROM_LE (nsections);
5157         header->coff.coff_time = GUINT32_FROM_LE (time (NULL));
5158         header->coff.coff_opt_header_size = GUINT16_FROM_LE (sizeof (MonoDotNetHeader) - sizeof (MonoCOFFHeader) - 4);
5159         if (assemblyb->pekind == 1) {
5160                 /* it's a dll */
5161                 header->coff.coff_attributes = GUINT16_FROM_LE (0x210e);
5162         } else {
5163                 /* it's an exe */
5164                 header->coff.coff_attributes = GUINT16_FROM_LE (0x010e);
5165         }
5166
5167         virtual_base = 0x400000; /* FIXME: 0x10000000 if a DLL */
5168
5169         header->pe.pe_magic = GUINT16_FROM_LE (0x10B);
5170         header->pe.pe_major = 6;
5171         header->pe.pe_minor = 0;
5172         size = assembly->sections [MONO_SECTION_TEXT].size;
5173         size += FILE_ALIGN - 1;
5174         size &= ~(FILE_ALIGN - 1);
5175         header->pe.pe_code_size = GUINT32_FROM_LE(size);
5176         size = assembly->sections [MONO_SECTION_RSRC].size;
5177         size += FILE_ALIGN - 1;
5178         size &= ~(FILE_ALIGN - 1);
5179         header->pe.pe_data_size = GUINT32_FROM_LE(size);
5180         g_assert (START_TEXT_RVA == assembly->sections [MONO_SECTION_TEXT].rva);
5181         header->pe.pe_rva_code_base = GUINT32_FROM_LE (assembly->sections [MONO_SECTION_TEXT].rva);
5182         header->pe.pe_rva_data_base = GUINT32_FROM_LE (assembly->sections [MONO_SECTION_RSRC].rva);
5183         /* pe_rva_entry_point always at the beginning of the text section */
5184         header->pe.pe_rva_entry_point = GUINT32_FROM_LE (assembly->sections [MONO_SECTION_TEXT].rva);
5185
5186         header->nt.pe_image_base = GUINT32_FROM_LE (virtual_base);
5187         header->nt.pe_section_align = GUINT32_FROM_LE (VIRT_ALIGN);
5188         header->nt.pe_file_alignment = GUINT32_FROM_LE (FILE_ALIGN);
5189         header->nt.pe_os_major = GUINT16_FROM_LE (4);
5190         header->nt.pe_os_minor = GUINT16_FROM_LE (0);
5191         header->nt.pe_subsys_major = GUINT16_FROM_LE (4);
5192         size = section_start;
5193         size += FILE_ALIGN - 1;
5194         size &= ~(FILE_ALIGN - 1);
5195         header->nt.pe_header_size = GUINT32_FROM_LE (size);
5196         size = image_size;
5197         size += VIRT_ALIGN - 1;
5198         size &= ~(VIRT_ALIGN - 1);
5199         header->nt.pe_image_size = GUINT32_FROM_LE (size);
5200
5201         /*
5202         // Translate the PEFileKind value to the value expected by the Windows loader
5203         */
5204         {
5205                 short kind;
5206
5207                 /*
5208                 // PEFileKinds.Dll == 1
5209                 // PEFileKinds.ConsoleApplication == 2
5210                 // PEFileKinds.WindowApplication == 3
5211                 //
5212                 // need to get:
5213                 //     IMAGE_SUBSYSTEM_WINDOWS_GUI 2 // Image runs in the Windows GUI subsystem.
5214                 //     IMAGE_SUBSYSTEM_WINDOWS_CUI 3 // Image runs in the Windows character subsystem.
5215                 */
5216                 if (assemblyb->pekind == 3)
5217                         kind = 2;
5218                 else
5219                         kind = 3;
5220                 
5221                 header->nt.pe_subsys_required = GUINT16_FROM_LE (kind);
5222         }    
5223         header->nt.pe_stack_reserve = GUINT32_FROM_LE (0x00100000);
5224         header->nt.pe_stack_commit = GUINT32_FROM_LE (0x00001000);
5225         header->nt.pe_heap_reserve = GUINT32_FROM_LE (0x00100000);
5226         header->nt.pe_heap_commit = GUINT32_FROM_LE (0x00001000);
5227         header->nt.pe_loader_flags = GUINT32_FROM_LE (0);
5228         header->nt.pe_data_dir_count = GUINT32_FROM_LE (16);
5229
5230         /* fill data directory entries */
5231
5232         header->datadir.pe_resource_table.size = GUINT32_FROM_LE (assembly->sections [MONO_SECTION_RSRC].size);
5233         header->datadir.pe_resource_table.rva = GUINT32_FROM_LE (assembly->sections [MONO_SECTION_RSRC].rva);
5234
5235         header->datadir.pe_reloc_table.size = GUINT32_FROM_LE (assembly->sections [MONO_SECTION_RELOC].size);
5236         header->datadir.pe_reloc_table.rva = GUINT32_FROM_LE (assembly->sections [MONO_SECTION_RELOC].rva);
5237
5238         header->datadir.pe_cli_header.size = GUINT32_FROM_LE (72);
5239         header->datadir.pe_cli_header.rva = GUINT32_FROM_LE (assembly->text_rva + assembly->cli_header_offset);
5240         header->datadir.pe_iat.size = GUINT32_FROM_LE (8);
5241         header->datadir.pe_iat.rva = GUINT32_FROM_LE (assembly->text_rva + assembly->iat_offset);
5242         /* patch entrypoint name */
5243         if (assemblyb->pekind == 1)
5244                 memcpy (assembly->code.data + assembly->imp_names_offset + 2, "_CorDllMain", 12);
5245         else
5246                 memcpy (assembly->code.data + assembly->imp_names_offset + 2, "_CorExeMain", 12);
5247         /* patch imported function RVA name */
5248         rva = (guint32*)(assembly->code.data + assembly->iat_offset);
5249         *rva = GUINT32_FROM_LE (assembly->text_rva + assembly->imp_names_offset);
5250
5251         /* the import table */
5252         header->datadir.pe_import_table.size = GUINT32_FROM_LE (79); /* FIXME: magic number? */
5253         header->datadir.pe_import_table.rva = GUINT32_FROM_LE (assembly->text_rva + assembly->idt_offset);
5254         /* patch imported dll RVA name and other entries in the dir */
5255         rva = (guint32*)(assembly->code.data + assembly->idt_offset + G_STRUCT_OFFSET (MonoIDT, name_rva));
5256         *rva = GUINT32_FROM_LE (assembly->text_rva + assembly->imp_names_offset + 14); /* 14 is hint+strlen+1 of func name */
5257         rva = (guint32*)(assembly->code.data + assembly->idt_offset + G_STRUCT_OFFSET (MonoIDT, import_address_table_rva));
5258         *rva = GUINT32_FROM_LE (assembly->text_rva + assembly->iat_offset);
5259         rva = (guint32*)(assembly->code.data + assembly->idt_offset + G_STRUCT_OFFSET (MonoIDT, import_lookup_table));
5260         *rva = GUINT32_FROM_LE (assembly->text_rva + assembly->ilt_offset);
5261
5262         p = (guchar*)(assembly->code.data + assembly->ilt_offset);
5263         value = (assembly->text_rva + assembly->imp_names_offset);
5264         *p++ = (value) & 0xff;
5265         *p++ = (value >> 8) & (0xff);
5266         *p++ = (value >> 16) & (0xff);
5267         *p++ = (value >> 24) & (0xff);
5268
5269         /* the CLI header info */
5270         cli_header = (MonoCLIHeader*)(assembly->code.data + assembly->cli_header_offset);
5271         cli_header->ch_size = GUINT32_FROM_LE (72);
5272         cli_header->ch_runtime_major = GUINT16_FROM_LE (2);
5273         if (mono_get_runtime_info ()->framework_version [0] > '1')
5274                 cli_header->ch_runtime_minor = GUINT16_FROM_LE (5);
5275         else 
5276                 cli_header->ch_runtime_minor = GUINT16_FROM_LE (0);
5277         cli_header->ch_flags = GUINT32_FROM_LE (assemblyb->pe_kind);
5278         if (assemblyb->entry_point) {
5279                 guint32 table_idx = 0;
5280                 if (!strcmp (assemblyb->entry_point->object.vtable->klass->name, "MethodBuilder")) {
5281                         MonoReflectionMethodBuilder *methodb = (MonoReflectionMethodBuilder*)assemblyb->entry_point;
5282                         table_idx = methodb->table_idx;
5283                 } else {
5284                         table_idx = GPOINTER_TO_UINT (g_hash_table_lookup (assembly->method_to_table_idx, assemblyb->entry_point->method));
5285                 }
5286                 cli_header->ch_entry_point = GUINT32_FROM_LE (table_idx | MONO_TOKEN_METHOD_DEF);
5287         } else {
5288                 cli_header->ch_entry_point = GUINT32_FROM_LE (0);
5289         }
5290         /* The embedded managed resources */
5291         text_offset = assembly->text_rva + assembly->code.index;
5292         cli_header->ch_resources.rva = GUINT32_FROM_LE (text_offset);
5293         cli_header->ch_resources.size = GUINT32_FROM_LE (assembly->resources.index);
5294         text_offset += assembly->resources.index;
5295         cli_header->ch_metadata.rva = GUINT32_FROM_LE (text_offset);
5296         cli_header->ch_metadata.size = GUINT32_FROM_LE (assembly->meta_size);
5297         text_offset += assembly->meta_size;
5298         if (assembly->strong_name_size) {
5299                 cli_header->ch_strong_name.rva = GUINT32_FROM_LE (text_offset);
5300                 cli_header->ch_strong_name.size = GUINT32_FROM_LE (assembly->strong_name_size);
5301                 text_offset += assembly->strong_name_size;
5302         }
5303
5304         /* write the section tables and section content */
5305         section = (MonoSectionTable*)(pefile->data + section_start);
5306         for (i = 0; i < MONO_SECTION_MAX; ++i) {
5307                 static const char section_names [][7] = {
5308                         ".text", ".rsrc", ".reloc"
5309                 };
5310                 if (!assembly->sections [i].size)
5311                         continue;
5312                 strcpy (section->st_name, section_names [i]);
5313                 /*g_print ("output section %s (%d), size: %d\n", section->st_name, i, assembly->sections [i].size);*/
5314                 section->st_virtual_address = GUINT32_FROM_LE (assembly->sections [i].rva);
5315                 section->st_virtual_size = GUINT32_FROM_LE (assembly->sections [i].size);
5316                 section->st_raw_data_size = GUINT32_FROM_LE (GUINT32_TO_LE (section->st_virtual_size) + (FILE_ALIGN - 1));
5317                 section->st_raw_data_size &= GUINT32_FROM_LE (~(FILE_ALIGN - 1));
5318                 section->st_raw_data_ptr = GUINT32_FROM_LE (assembly->sections [i].offset);
5319                 section->st_flags = GUINT32_FROM_LE (assembly->sections [i].attrs);
5320                 section ++;
5321         }
5322         
5323         checked_write_file (file, pefile->data, pefile->index);
5324         
5325         mono_dynamic_stream_reset (pefile);
5326         
5327         for (i = 0; i < MONO_SECTION_MAX; ++i) {
5328                 if (!assembly->sections [i].size)
5329                         continue;
5330                 
5331                 if (SetFilePointer (file, assembly->sections [i].offset, NULL, FILE_BEGIN) == INVALID_SET_FILE_POINTER)
5332                         g_error ("SetFilePointer returned %d\n", GetLastError ());
5333                 
5334                 switch (i) {
5335                 case MONO_SECTION_TEXT:
5336                         /* patch entry point */
5337                         p = (guchar*)(assembly->code.data + 2);
5338                         value = (virtual_base + assembly->text_rva + assembly->iat_offset);
5339                         *p++ = (value) & 0xff;
5340                         *p++ = (value >> 8) & 0xff;
5341                         *p++ = (value >> 16) & 0xff;
5342                         *p++ = (value >> 24) & 0xff;
5343                 
5344                         checked_write_file (file, assembly->code.data, assembly->code.index);
5345                         checked_write_file (file, assembly->resources.data, assembly->resources.index);
5346                         checked_write_file (file, assembly->image.raw_metadata, assembly->meta_size);
5347                         checked_write_file (file, assembly->strong_name, assembly->strong_name_size);
5348                                 
5349
5350                         g_free (assembly->image.raw_metadata);
5351                         break;
5352                 case MONO_SECTION_RELOC: {
5353                         struct {
5354                                 guint32 page_rva;
5355                                 guint32 block_size;
5356                                 guint16 type_and_offset;
5357                                 guint16 term;
5358                         } reloc;
5359                         
5360                         g_assert (sizeof (reloc) == 12);
5361                         
5362                         reloc.page_rva = GUINT32_FROM_LE (assembly->text_rva);
5363                         reloc.block_size = GUINT32_FROM_LE (12);
5364                         
5365                         /* 
5366                          * the entrypoint is always at the start of the text section 
5367                          * 3 is IMAGE_REL_BASED_HIGHLOW
5368                          * 2 is patch_size_rva - text_rva
5369                          */
5370                         reloc.type_and_offset = GUINT16_FROM_LE ((3 << 12) + (2));
5371                         reloc.term = 0;
5372                         
5373                         checked_write_file (file, &reloc, sizeof (reloc));
5374                         
5375                         break;
5376                 }
5377                 case MONO_SECTION_RSRC:
5378                         if (assembly->win32_res) {
5379
5380                                 /* Fixup the offsets in the IMAGE_RESOURCE_DATA_ENTRY structures */
5381                                 fixup_resource_directory (assembly->win32_res, assembly->win32_res, assembly->sections [i].rva);
5382                                 checked_write_file (file, assembly->win32_res, assembly->win32_res_size);
5383                         }
5384                         break;
5385                 default:
5386                         g_assert_not_reached ();
5387                 }
5388         }
5389         
5390         /* check that the file is properly padded */
5391         if (SetFilePointer (file, file_offset, NULL, FILE_BEGIN) == INVALID_SET_FILE_POINTER)
5392                 g_error ("SetFilePointer returned %d\n", GetLastError ());
5393         if (! SetEndOfFile (file))
5394                 g_error ("SetEndOfFile returned %d\n", GetLastError ());
5395         
5396         mono_dynamic_stream_reset (&assembly->code);
5397         mono_dynamic_stream_reset (&assembly->us);
5398         mono_dynamic_stream_reset (&assembly->blob);
5399         mono_dynamic_stream_reset (&assembly->guid);
5400         mono_dynamic_stream_reset (&assembly->sheap);
5401
5402         g_hash_table_foreach (assembly->blob_cache, (GHFunc)g_free, NULL);
5403         g_hash_table_destroy (assembly->blob_cache);
5404         assembly->blob_cache = NULL;
5405 }
5406
5407 MonoReflectionModule *
5408 mono_image_load_module_dynamic (MonoReflectionAssemblyBuilder *ab, MonoString *fileName)
5409 {
5410         char *name;
5411         MonoImage *image;
5412         MonoImageOpenStatus status;
5413         MonoDynamicAssembly *assembly;
5414         guint32 module_count;
5415         MonoImage **new_modules;
5416         gboolean *new_modules_loaded;
5417         
5418         name = mono_string_to_utf8 (fileName);
5419
5420         image = mono_image_open (name, &status);
5421         if (!image) {
5422                 MonoException *exc;
5423                 if (status == MONO_IMAGE_ERROR_ERRNO)
5424                         exc = mono_get_exception_file_not_found (fileName);
5425                 else
5426                         exc = mono_get_exception_bad_image_format (name);
5427                 g_free (name);
5428                 mono_raise_exception (exc);
5429         }
5430
5431         g_free (name);
5432
5433         assembly = ab->dynamic_assembly;
5434         image->assembly = (MonoAssembly*)assembly;
5435
5436         module_count = image->assembly->image->module_count;
5437         new_modules = g_new0 (MonoImage *, module_count + 1);
5438         new_modules_loaded = g_new0 (gboolean, module_count + 1);
5439
5440         if (image->assembly->image->modules)
5441                 memcpy (new_modules, image->assembly->image->modules, module_count * sizeof (MonoImage *));
5442         if (image->assembly->image->modules_loaded)
5443                 memcpy (new_modules_loaded, image->assembly->image->modules_loaded, module_count * sizeof (gboolean));
5444         new_modules [module_count] = image;
5445         new_modules_loaded [module_count] = TRUE;
5446         mono_image_addref (image);
5447
5448         g_free (image->assembly->image->modules);
5449         image->assembly->image->modules = new_modules;
5450         image->assembly->image->modules_loaded = new_modules_loaded;
5451         image->assembly->image->module_count ++;
5452
5453         mono_assembly_load_references (image, &status);
5454         if (status) {
5455                 mono_image_close (image);
5456                 mono_raise_exception (mono_get_exception_file_not_found (fileName));
5457         }
5458
5459         return mono_module_get_object (mono_domain_get (), image);
5460 }
5461
5462 /*
5463  * We need to return always the same object for MethodInfo, FieldInfo etc..
5464  * but we need to consider the reflected type.
5465  * type uses a different hash, since it uses custom hash/equal functions.
5466  */
5467
5468 typedef struct {
5469         gpointer item;
5470         MonoClass *refclass;
5471 } ReflectedEntry;
5472
5473 static gboolean
5474 reflected_equal (gconstpointer a, gconstpointer b) {
5475         const ReflectedEntry *ea = a;
5476         const ReflectedEntry *eb = b;
5477
5478         return (ea->item == eb->item) && (ea->refclass == eb->refclass);
5479 }
5480
5481 static guint
5482 reflected_hash (gconstpointer a) {
5483         const ReflectedEntry *ea = a;
5484         return mono_aligned_addr_hash (ea->item);
5485 }
5486
5487 #define CHECK_OBJECT(t,p,k)     \
5488         do {    \
5489                 t _obj; \
5490                 ReflectedEntry e;       \
5491                 e.item = (p);   \
5492                 e.refclass = (k);       \
5493                 mono_domain_lock (domain);      \
5494                 if (!domain->refobject_hash)    \
5495                         domain->refobject_hash = mono_g_hash_table_new_type (reflected_hash, reflected_equal, MONO_HASH_VALUE_GC);      \
5496                 if ((_obj = mono_g_hash_table_lookup (domain->refobject_hash, &e))) {   \
5497                         mono_domain_unlock (domain);    \
5498                         return _obj;    \
5499                 }       \
5500         mono_domain_unlock (domain); \
5501         } while (0)
5502
5503 #ifndef HAVE_NULL_GC
5504 #define ALLOC_REFENTRY mono_gc_alloc_fixed (sizeof (ReflectedEntry), NULL)
5505 #else
5506 #define ALLOC_REFENTRY mono_mempool_alloc (domain->mp, sizeof (ReflectedEntry))
5507 #endif
5508
5509 #define CACHE_OBJECT(t,p,o,k)   \
5510         do {    \
5511                 t _obj; \
5512         ReflectedEntry pe; \
5513         pe.item = (p); \
5514         pe.refclass = (k); \
5515         mono_domain_lock (domain); \
5516                 if (!domain->refobject_hash)    \
5517                         domain->refobject_hash = mono_g_hash_table_new_type (reflected_hash, reflected_equal, MONO_HASH_VALUE_GC);      \
5518         _obj = mono_g_hash_table_lookup (domain->refobject_hash, &pe); \
5519         if (!_obj) { \
5520                     ReflectedEntry *e = ALLOC_REFENTRY;         \
5521                     e->item = (p);      \
5522                     e->refclass = (k);  \
5523                     mono_g_hash_table_insert (domain->refobject_hash, e,o);     \
5524             _obj = o; \
5525         } \
5526                 mono_domain_unlock (domain);    \
5527         return _obj; \
5528         } while (0)
5529
5530 static gpointer
5531 register_assembly (MonoDomain *domain, MonoReflectionAssembly *res, MonoAssembly *assembly)
5532 {
5533         CACHE_OBJECT (MonoReflectionAssembly *, assembly, res, NULL);
5534 }
5535
5536 static gpointer
5537 register_module (MonoDomain *domain, MonoReflectionModuleBuilder *res, MonoDynamicImage *module)
5538 {
5539         CACHE_OBJECT (MonoReflectionModuleBuilder *, module, res, NULL);
5540 }
5541
5542 void
5543 mono_image_module_basic_init (MonoReflectionModuleBuilder *moduleb)
5544 {
5545         MonoDynamicImage *image = moduleb->dynamic_image;
5546         MonoReflectionAssemblyBuilder *ab = moduleb->assemblyb;
5547         if (!image) {
5548                 int module_count;
5549                 MonoImage **new_modules;
5550                 MonoImage *ass;
5551                 /*
5552                  * FIXME: we already created an image in mono_image_basic_init (), but
5553                  * we don't know which module it belongs to, since that is only 
5554                  * determined at assembly save time.
5555                  */
5556                 /*image = (MonoDynamicImage*)ab->dynamic_assembly->assembly.image; */
5557                 image = create_dynamic_mono_image (ab->dynamic_assembly, mono_string_to_utf8 (ab->name), mono_string_to_utf8 (moduleb->module.fqname));
5558
5559                 moduleb->module.image = &image->image;
5560                 moduleb->dynamic_image = image;
5561                 register_module (mono_object_domain (moduleb), moduleb, image);
5562
5563                 /* register the module with the assembly */
5564                 ass = ab->dynamic_assembly->assembly.image;
5565                 module_count = ass->module_count;
5566                 new_modules = g_new0 (MonoImage *, module_count + 1);
5567
5568                 if (ass->modules)
5569                         memcpy (new_modules, ass->modules, module_count * sizeof (MonoImage *));
5570                 new_modules [module_count] = &image->image;
5571                 mono_image_addref (&image->image);
5572
5573                 g_free (ass->modules);
5574                 ass->modules = new_modules;
5575                 ass->module_count ++;
5576         }
5577 }
5578
5579 /*
5580  * mono_assembly_get_object:
5581  * @domain: an app domain
5582  * @assembly: an assembly
5583  *
5584  * Return an System.Reflection.Assembly object representing the MonoAssembly @assembly.
5585  */
5586 MonoReflectionAssembly*
5587 mono_assembly_get_object (MonoDomain *domain, MonoAssembly *assembly)
5588 {
5589         static MonoClass *System_Reflection_Assembly;
5590         MonoReflectionAssembly *res;
5591         
5592         CHECK_OBJECT (MonoReflectionAssembly *, assembly, NULL);
5593         if (!System_Reflection_Assembly)
5594                 System_Reflection_Assembly = mono_class_from_name (
5595                         mono_defaults.corlib, "System.Reflection", "Assembly");
5596         res = (MonoReflectionAssembly *)mono_object_new (domain, System_Reflection_Assembly);
5597         res->assembly = assembly;
5598
5599         CACHE_OBJECT (MonoReflectionAssembly *, assembly, res, NULL);
5600 }
5601
5602
5603
5604 MonoReflectionModule*   
5605 mono_module_get_object   (MonoDomain *domain, MonoImage *image)
5606 {
5607         static MonoClass *System_Reflection_Module;
5608         MonoReflectionModule *res;
5609         char* basename;
5610         
5611         CHECK_OBJECT (MonoReflectionModule *, image, NULL);
5612         if (!System_Reflection_Module)
5613                 System_Reflection_Module = mono_class_from_name (
5614                         mono_defaults.corlib, "System.Reflection", "Module");
5615         res = (MonoReflectionModule *)mono_object_new (domain, System_Reflection_Module);
5616
5617         res->image = image;
5618         MONO_OBJECT_SETREF (res, assembly, (MonoReflectionAssembly *) mono_assembly_get_object(domain, image->assembly));
5619
5620         MONO_OBJECT_SETREF (res, fqname, mono_string_new (domain, image->name));
5621         basename = g_path_get_basename (image->name);
5622         MONO_OBJECT_SETREF (res, name, mono_string_new (domain, basename));
5623         MONO_OBJECT_SETREF (res, scopename, mono_string_new (domain, image->module_name));
5624         
5625         g_free (basename);
5626
5627         if (image->assembly->image == image) {
5628                 res->token = mono_metadata_make_token (MONO_TABLE_MODULE, 1);
5629         } else {
5630                 int i;
5631                 res->token = 0;
5632                 if (image->assembly->image->modules) {
5633                         for (i = 0; i < image->assembly->image->module_count; i++) {
5634                                 if (image->assembly->image->modules [i] == image)
5635                                         res->token = mono_metadata_make_token (MONO_TABLE_MODULEREF, i + 1);
5636                         }
5637                         g_assert (res->token);
5638                 }
5639         }
5640
5641         CACHE_OBJECT (MonoReflectionModule *, image, res, NULL);
5642 }
5643
5644 MonoReflectionModule*   
5645 mono_module_file_get_object (MonoDomain *domain, MonoImage *image, int table_index)
5646 {
5647         static MonoClass *System_Reflection_Module;
5648         MonoReflectionModule *res;
5649         MonoTableInfo *table;
5650         guint32 cols [MONO_FILE_SIZE];
5651         const char *name;
5652         guint32 i, name_idx;
5653         const char *val;
5654         
5655         if (!System_Reflection_Module)
5656                 System_Reflection_Module = mono_class_from_name (
5657                         mono_defaults.corlib, "System.Reflection", "Module");
5658         res = (MonoReflectionModule *)mono_object_new (domain, System_Reflection_Module);
5659
5660         table = &image->tables [MONO_TABLE_FILE];
5661         g_assert (table_index < table->rows);
5662         mono_metadata_decode_row (table, table_index, cols, MONO_FILE_SIZE);
5663
5664         res->image = NULL;
5665         MONO_OBJECT_SETREF (res, assembly, (MonoReflectionAssembly *) mono_assembly_get_object(domain, image->assembly));
5666         name = mono_metadata_string_heap (image, cols [MONO_FILE_NAME]);
5667
5668         /* Check whenever the row has a corresponding row in the moduleref table */
5669         table = &image->tables [MONO_TABLE_MODULEREF];
5670         for (i = 0; i < table->rows; ++i) {
5671                 name_idx = mono_metadata_decode_row_col (table, i, MONO_MODULEREF_NAME);
5672                 val = mono_metadata_string_heap (image, name_idx);
5673                 if (strcmp (val, name) == 0)
5674                         res->image = image->modules [i];
5675         }
5676
5677         MONO_OBJECT_SETREF (res, fqname, mono_string_new (domain, name));
5678         MONO_OBJECT_SETREF (res, name, mono_string_new (domain, name));
5679         MONO_OBJECT_SETREF (res, scopename, mono_string_new (domain, name));
5680         res->is_resource = cols [MONO_FILE_FLAGS] && FILE_CONTAINS_NO_METADATA;
5681         res->token = mono_metadata_make_token (MONO_TABLE_FILE, table_index + 1);
5682
5683         return res;
5684 }
5685
5686 static gboolean
5687 mymono_metadata_type_equal (MonoType *t1, MonoType *t2)
5688 {
5689         if ((t1->type != t2->type) ||
5690             (t1->byref != t2->byref))
5691                 return FALSE;
5692
5693         switch (t1->type) {
5694         case MONO_TYPE_VOID:
5695         case MONO_TYPE_BOOLEAN:
5696         case MONO_TYPE_CHAR:
5697         case MONO_TYPE_I1:
5698         case MONO_TYPE_U1:
5699         case MONO_TYPE_I2:
5700         case MONO_TYPE_U2:
5701         case MONO_TYPE_I4:
5702         case MONO_TYPE_U4:
5703         case MONO_TYPE_I8:
5704         case MONO_TYPE_U8:
5705         case MONO_TYPE_R4:
5706         case MONO_TYPE_R8:
5707         case MONO_TYPE_STRING:
5708         case MONO_TYPE_I:
5709         case MONO_TYPE_U:
5710         case MONO_TYPE_OBJECT:
5711         case MONO_TYPE_TYPEDBYREF:
5712                 return TRUE;
5713         case MONO_TYPE_VALUETYPE:
5714         case MONO_TYPE_CLASS:
5715         case MONO_TYPE_SZARRAY:
5716                 return t1->data.klass == t2->data.klass;
5717         case MONO_TYPE_PTR:
5718                 return mymono_metadata_type_equal (t1->data.type, t2->data.type);
5719         case MONO_TYPE_ARRAY:
5720                 if (t1->data.array->rank != t2->data.array->rank)
5721                         return FALSE;
5722                 return t1->data.array->eklass == t2->data.array->eklass;
5723         case MONO_TYPE_GENERICINST: {
5724                 int i;
5725                 MonoGenericInst *i1 = t1->data.generic_class->context.class_inst;
5726                 MonoGenericInst *i2 = t2->data.generic_class->context.class_inst;
5727                 if (i1->type_argc != i2->type_argc)
5728                         return FALSE;
5729                 if (!mono_metadata_type_equal (&t1->data.generic_class->container_class->byval_arg,
5730                                                &t2->data.generic_class->container_class->byval_arg))
5731                         return FALSE;
5732                 /* FIXME: we should probably just compare the instance pointers directly.  */
5733                 for (i = 0; i < i1->type_argc; ++i) {
5734                         if (!mono_metadata_type_equal (i1->type_argv [i], i2->type_argv [i]))
5735                                 return FALSE;
5736                 }
5737                 return TRUE;
5738         }
5739         case MONO_TYPE_VAR:
5740         case MONO_TYPE_MVAR:
5741                 return t1->data.generic_param == t2->data.generic_param;
5742         default:
5743                 g_error ("implement type compare for %0x!", t1->type);
5744                 return FALSE;
5745         }
5746
5747         return FALSE;
5748 }
5749
5750 static guint
5751 mymono_metadata_type_hash (MonoType *t1)
5752 {
5753         guint hash;
5754
5755         hash = t1->type;
5756
5757         hash |= t1->byref << 6; /* do not collide with t1->type values */
5758         switch (t1->type) {
5759         case MONO_TYPE_VALUETYPE:
5760         case MONO_TYPE_CLASS:
5761         case MONO_TYPE_SZARRAY:
5762                 /* check if the distribution is good enough */
5763                 return ((hash << 5) - hash) ^ g_str_hash (t1->data.klass->name);
5764         case MONO_TYPE_PTR:
5765                 return ((hash << 5) - hash) ^ mymono_metadata_type_hash (t1->data.type);
5766         case MONO_TYPE_GENERICINST: {
5767                 int i;
5768                 MonoGenericInst *inst = t1->data.generic_class->context.class_inst;
5769                 hash += g_str_hash (t1->data.generic_class->container_class->name);
5770                 hash *= 13;
5771                 for (i = 0; i < inst->type_argc; ++i) {
5772                         hash += mymono_metadata_type_hash (inst->type_argv [i]);
5773                         hash *= 13;
5774                 }
5775                 return hash;
5776         }
5777         }
5778         return hash;
5779 }
5780
5781 static MonoReflectionGenericClass*
5782 mono_generic_class_get_object (MonoDomain *domain, MonoType *geninst)
5783 {
5784         static MonoClass *System_Reflection_MonoGenericClass;
5785         MonoReflectionGenericClass *res;
5786         MonoClass *klass, *gklass;
5787
5788         if (!System_Reflection_MonoGenericClass) {
5789                 System_Reflection_MonoGenericClass = mono_class_from_name (
5790                         mono_defaults.corlib, "System.Reflection", "MonoGenericClass");
5791                 g_assert (System_Reflection_MonoGenericClass);
5792         }
5793
5794         klass = mono_class_from_mono_type (geninst);
5795         gklass = klass->generic_class->container_class;
5796
5797         mono_class_init (klass);
5798
5799 #ifdef HAVE_SGEN_GC
5800         /* FIXME: allow unpinned later */
5801         res = (MonoReflectionGenericClass *) mono_gc_alloc_pinned_obj (mono_class_vtable (domain, System_Reflection_MonoGenericClass), mono_class_instance_size (System_Reflection_MonoGenericClass));
5802 #else
5803         res = (MonoReflectionGenericClass *) mono_object_new (domain, System_Reflection_MonoGenericClass);
5804 #endif
5805
5806         res->type.type = geninst;
5807         g_assert (gklass->reflection_info);
5808         g_assert (!strcmp (((MonoObject*)gklass->reflection_info)->vtable->klass->name, "TypeBuilder"));
5809         MONO_OBJECT_SETREF (res, generic_type, gklass->reflection_info);
5810
5811         return res;
5812 }
5813
5814 static gboolean
5815 verify_safe_for_managed_space (MonoType *type)
5816 {
5817         switch (type->type) {
5818 #ifdef DEBUG_HARDER
5819         case MONO_TYPE_ARRAY:
5820                 return verify_safe_for_managed_space (&type->data.array->eklass->byval_arg);
5821         case MONO_TYPE_PTR:
5822                 return verify_safe_for_managed_space (type->data.type);
5823         case MONO_TYPE_SZARRAY:
5824                 return verify_safe_for_managed_space (&type->data.klass->byval_arg);
5825         case MONO_TYPE_GENERICINST: {
5826                 MonoGenericInst *inst = type->data.generic_class->inst;
5827                 int i;
5828                 if (!inst->is_open)
5829                         break;
5830                 for (i = 0; i < inst->type_argc; ++i)
5831                         if (!verify_safe_for_managed_space (inst->type_argv [i]))
5832                                 return FALSE;
5833                 break;
5834         }
5835 #endif
5836         case MONO_TYPE_VAR:
5837         case MONO_TYPE_MVAR:
5838                 return TRUE;
5839         }
5840         return TRUE;
5841 }
5842
5843 /*
5844  * mono_type_get_object:
5845  * @domain: an app domain
5846  * @type: a type
5847  *
5848  * Return an System.MonoType object representing the type @type.
5849  */
5850 MonoReflectionType*
5851 mono_type_get_object (MonoDomain *domain, MonoType *type)
5852 {
5853         MonoReflectionType *res;
5854         MonoClass *klass = mono_class_from_mono_type (type);
5855
5856         /*we must avoid using @type as it might have come
5857          * from a mono_metadata_type_dup and the caller
5858          * expects that is can be freed.
5859          * Using the right type from 
5860          */
5861         type = klass->byval_arg.byref == type->byref ? &klass->byval_arg : &klass->this_arg;
5862
5863         /*
5864          * If the vtable of the given class was already created, we can use
5865          * the MonoType from there and avoid all locking and hash table lookups.
5866          * 
5867          * We cannot do this for TypeBuilders as mono_reflection_create_runtime_class expects
5868          * that the resulting object is diferent.   
5869          */
5870         if (type == &klass->byval_arg && !klass->image->dynamic) {
5871                 MonoVTable *vtable = mono_class_try_get_vtable (domain, klass);
5872                 if (vtable && vtable->type)
5873                         return vtable->type;
5874         }
5875
5876         mono_domain_lock (domain);
5877         if (!domain->type_hash)
5878                 domain->type_hash = mono_g_hash_table_new_type ((GHashFunc)mymono_metadata_type_hash, 
5879                                 (GCompareFunc)mymono_metadata_type_equal, MONO_HASH_VALUE_GC);
5880         if ((res = mono_g_hash_table_lookup (domain->type_hash, type))) {
5881                 mono_domain_unlock (domain);
5882                 return res;
5883         }
5884         /* Create a MonoGenericClass object for instantiations of not finished TypeBuilders */
5885         if ((type->type == MONO_TYPE_GENERICINST) && type->data.generic_class->is_dynamic && !type->data.generic_class->container_class->wastypebuilder) {
5886                 res = (MonoReflectionType *)mono_generic_class_get_object (domain, type);
5887                 mono_g_hash_table_insert (domain->type_hash, type, res);
5888                 mono_domain_unlock (domain);
5889                 return res;
5890         }
5891
5892         if (!verify_safe_for_managed_space (type)) {
5893                 mono_domain_unlock (domain);
5894                 mono_raise_exception (mono_get_exception_invalid_operation ("This type cannot be propagated to managed space"));
5895         }
5896
5897         if (klass->reflection_info && !klass->wastypebuilder) {
5898                 /* g_assert_not_reached (); */
5899                 /* should this be considered an error condition? */
5900                 if (!type->byref) {
5901                         mono_domain_unlock (domain);
5902                         return klass->reflection_info;
5903                 }
5904         }
5905         // FIXME: Get rid of this, do it in the icalls for Type
5906         mono_class_init (klass);
5907 #ifdef HAVE_SGEN_GC
5908         res = (MonoReflectionType *)mono_gc_alloc_pinned_obj (mono_class_vtable (domain, mono_defaults.monotype_class), mono_class_instance_size (mono_defaults.monotype_class));
5909 #else
5910         res = (MonoReflectionType *)mono_object_new (domain, mono_defaults.monotype_class);
5911 #endif
5912         res->type = type;
5913         mono_g_hash_table_insert (domain->type_hash, type, res);
5914         mono_domain_unlock (domain);
5915         return res;
5916 }
5917
5918 /*
5919  * mono_method_get_object:
5920  * @domain: an app domain
5921  * @method: a method
5922  * @refclass: the reflected type (can be NULL)
5923  *
5924  * Return an System.Reflection.MonoMethod object representing the method @method.
5925  */
5926 MonoReflectionMethod*
5927 mono_method_get_object (MonoDomain *domain, MonoMethod *method, MonoClass *refclass)
5928 {
5929         /*
5930          * We use the same C representation for methods and constructors, but the type 
5931          * name in C# is different.
5932          */
5933         static MonoClass *System_Reflection_MonoMethod = NULL;
5934         static MonoClass *System_Reflection_MonoCMethod = NULL;
5935         static MonoClass *System_Reflection_MonoGenericMethod = NULL;
5936         static MonoClass *System_Reflection_MonoGenericCMethod = NULL;
5937         MonoClass *klass;
5938         MonoReflectionMethod *ret;
5939
5940         if (method->is_inflated) {
5941                 MonoReflectionGenericMethod *gret;
5942
5943                 refclass = method->klass;
5944                 CHECK_OBJECT (MonoReflectionMethod *, method, refclass);
5945                 if ((*method->name == '.') && (!strcmp (method->name, ".ctor") || !strcmp (method->name, ".cctor"))) {
5946                         if (!System_Reflection_MonoGenericCMethod)
5947                                 System_Reflection_MonoGenericCMethod = mono_class_from_name (mono_defaults.corlib, "System.Reflection", "MonoGenericCMethod");
5948                         klass = System_Reflection_MonoGenericCMethod;
5949                 } else {
5950                         if (!System_Reflection_MonoGenericMethod)
5951                                 System_Reflection_MonoGenericMethod = mono_class_from_name (mono_defaults.corlib, "System.Reflection", "MonoGenericMethod");
5952                         klass = System_Reflection_MonoGenericMethod;
5953                 }
5954                 gret = (MonoReflectionGenericMethod*)mono_object_new (domain, klass);
5955                 gret->method.method = method;
5956                 MONO_OBJECT_SETREF (gret, method.name, mono_string_new (domain, method->name));
5957                 MONO_OBJECT_SETREF (gret, method.reftype, mono_type_get_object (domain, &refclass->byval_arg));
5958                 CACHE_OBJECT (MonoReflectionMethod *, method, (MonoReflectionMethod*)gret, refclass);
5959         }
5960
5961         if (!refclass)
5962                 refclass = method->klass;
5963
5964         CHECK_OBJECT (MonoReflectionMethod *, method, refclass);
5965         if (*method->name == '.' && (strcmp (method->name, ".ctor") == 0 || strcmp (method->name, ".cctor") == 0)) {
5966                 if (!System_Reflection_MonoCMethod)
5967                         System_Reflection_MonoCMethod = mono_class_from_name (mono_defaults.corlib, "System.Reflection", "MonoCMethod");
5968                 klass = System_Reflection_MonoCMethod;
5969         }
5970         else {
5971                 if (!System_Reflection_MonoMethod)
5972                         System_Reflection_MonoMethod = mono_class_from_name (mono_defaults.corlib, "System.Reflection", "MonoMethod");
5973                 klass = System_Reflection_MonoMethod;
5974         }
5975         ret = (MonoReflectionMethod*)mono_object_new (domain, klass);
5976         ret->method = method;
5977         MONO_OBJECT_SETREF (ret, reftype, mono_type_get_object (domain, &refclass->byval_arg));
5978         CACHE_OBJECT (MonoReflectionMethod *, method, ret, refclass);
5979 }
5980
5981 /*
5982  * mono_field_get_object:
5983  * @domain: an app domain
5984  * @klass: a type
5985  * @field: a field
5986  *
5987  * Return an System.Reflection.MonoField object representing the field @field
5988  * in class @klass.
5989  */
5990 MonoReflectionField*
5991 mono_field_get_object (MonoDomain *domain, MonoClass *klass, MonoClassField *field)
5992 {
5993         MonoReflectionField *res;
5994         static MonoClass *monofield_klass;
5995
5996         CHECK_OBJECT (MonoReflectionField *, field, klass);
5997         if (!monofield_klass)
5998                 monofield_klass = mono_class_from_name (mono_defaults.corlib, "System.Reflection", "MonoField");
5999         res = (MonoReflectionField *)mono_object_new (domain, monofield_klass);
6000         res->klass = klass;
6001         res->field = field;
6002         MONO_OBJECT_SETREF (res, name, mono_string_new (domain, field->name));
6003         if (field->generic_info)
6004                 res->attrs = field->generic_info->generic_type->attrs;
6005         else
6006                 res->attrs = field->type->attrs;
6007         MONO_OBJECT_SETREF (res, type, mono_type_get_object (domain, field->type));
6008         CACHE_OBJECT (MonoReflectionField *, field, res, klass);
6009 }
6010
6011 /*
6012  * mono_property_get_object:
6013  * @domain: an app domain
6014  * @klass: a type
6015  * @property: a property
6016  *
6017  * Return an System.Reflection.MonoProperty object representing the property @property
6018  * in class @klass.
6019  */
6020 MonoReflectionProperty*
6021 mono_property_get_object (MonoDomain *domain, MonoClass *klass, MonoProperty *property)
6022 {
6023         MonoReflectionProperty *res;
6024         static MonoClass *monoproperty_klass;
6025
6026         CHECK_OBJECT (MonoReflectionProperty *, property, klass);
6027         if (!monoproperty_klass)
6028                 monoproperty_klass = mono_class_from_name (mono_defaults.corlib, "System.Reflection", "MonoProperty");
6029         res = (MonoReflectionProperty *)mono_object_new (domain, monoproperty_klass);
6030         res->klass = klass;
6031         res->property = property;
6032         CACHE_OBJECT (MonoReflectionProperty *, property, res, klass);
6033 }
6034
6035 /*
6036  * mono_event_get_object:
6037  * @domain: an app domain
6038  * @klass: a type
6039  * @event: a event
6040  *
6041  * Return an System.Reflection.MonoEvent object representing the event @event
6042  * in class @klass.
6043  */
6044 MonoReflectionEvent*
6045 mono_event_get_object (MonoDomain *domain, MonoClass *klass, MonoEvent *event)
6046 {
6047         MonoReflectionEvent *res;
6048         static MonoClass *monoevent_klass;
6049
6050         CHECK_OBJECT (MonoReflectionEvent *, event, klass);
6051         if (!monoevent_klass)
6052                 monoevent_klass = mono_class_from_name (mono_defaults.corlib, "System.Reflection", "MonoEvent");
6053         res = (MonoReflectionEvent *)mono_object_new (domain, monoevent_klass);
6054         res->klass = klass;
6055         res->event = event;
6056         CACHE_OBJECT (MonoReflectionEvent *, event, res, klass);
6057 }
6058
6059 /**
6060  * mono_get_reflection_missing_object:
6061  * @domain: Domain where the object lives
6062  *
6063  * Returns the System.Reflection.Missing.Value singleton object
6064  * (of type System.Reflection.Missing).
6065  *
6066  * Used as the value for ParameterInfo.DefaultValue when Optional
6067  * is present
6068  */
6069 static MonoObject *
6070 mono_get_reflection_missing_object (MonoDomain *domain)
6071 {
6072         MonoObject *obj;
6073         static MonoClassField *missing_value_field = NULL;
6074         
6075         if (!missing_value_field) {
6076                 MonoClass *missing_klass;
6077                 missing_klass = mono_class_from_name (mono_defaults.corlib, "System.Reflection", "Missing");
6078                 mono_class_init (missing_klass);
6079                 missing_value_field = mono_class_get_field_from_name (missing_klass, "Value");
6080                 g_assert (missing_value_field);
6081         }
6082         obj = mono_field_get_value_object (domain, missing_value_field, NULL); 
6083         g_assert (obj);
6084         return obj;
6085 }
6086
6087 static MonoObject*
6088 get_dbnull (MonoDomain *domain, MonoObject **dbnull)
6089 {
6090         if (!*dbnull)
6091                 *dbnull = mono_get_dbnull_object (domain);
6092         return *dbnull;
6093 }
6094
6095 static MonoObject*
6096 get_reflection_missing (MonoDomain *domain, MonoObject **reflection_missing)
6097 {
6098         if (!*reflection_missing)
6099                 *reflection_missing = mono_get_reflection_missing_object (domain);
6100         return *reflection_missing;
6101 }
6102
6103 /*
6104  * mono_param_get_objects:
6105  * @domain: an app domain
6106  * @method: a method
6107  *
6108  * Return an System.Reflection.ParameterInfo array object representing the parameters
6109  * in the method @method.
6110  */
6111 MonoArray*
6112 mono_param_get_objects (MonoDomain *domain, MonoMethod *method)
6113 {
6114         static MonoClass *System_Reflection_ParameterInfo;
6115         static MonoClass *System_Reflection_ParameterInfo_array;
6116         MonoArray *res = NULL;
6117         MonoReflectionMethod *member = NULL;
6118         MonoReflectionParameter *param = NULL;
6119         char **names, **blobs = NULL;
6120         guint32 *types = NULL;
6121         MonoType *type = NULL;
6122         MonoObject *dbnull = NULL;
6123         MonoObject *missing = NULL;
6124         MonoMarshalSpec **mspecs;
6125         MonoMethodSignature *sig;
6126         MonoVTable *pinfo_vtable;
6127         int i;
6128
6129         if (!System_Reflection_ParameterInfo_array) {
6130                 MonoClass *klass;
6131
6132                 klass = mono_class_from_name (mono_defaults.corlib, "System.Reflection", "ParameterInfo");
6133                 mono_memory_barrier ();
6134                 System_Reflection_ParameterInfo = klass; 
6135         
6136                 klass = mono_array_class_get (klass, 1);
6137                 mono_memory_barrier ();
6138                 System_Reflection_ParameterInfo_array = klass;
6139         }
6140         
6141         if (!mono_method_signature (method)->param_count)
6142                 return mono_array_new_specific (mono_class_vtable (domain, System_Reflection_ParameterInfo_array), 0);
6143
6144         /* Note: the cache is based on the address of the signature into the method
6145          * since we already cache MethodInfos with the method as keys.
6146          */
6147         CHECK_OBJECT (MonoArray*, &(method->signature), NULL);
6148
6149         sig = mono_method_signature (method);
6150         member = mono_method_get_object (domain, method, NULL);
6151         names = g_new (char *, sig->param_count);
6152         mono_method_get_param_names (method, (const char **) names);
6153
6154         mspecs = g_new (MonoMarshalSpec*, sig->param_count + 1);
6155         mono_method_get_marshal_info (method, mspecs);
6156
6157         res = mono_array_new_specific (mono_class_vtable (domain, System_Reflection_ParameterInfo_array), sig->param_count);
6158         pinfo_vtable = mono_class_vtable (domain, System_Reflection_ParameterInfo);
6159         for (i = 0; i < sig->param_count; ++i) {
6160                 param = (MonoReflectionParameter *)mono_object_new_specific (pinfo_vtable);
6161                 MONO_OBJECT_SETREF (param, ClassImpl, mono_type_get_object (domain, sig->params [i]));
6162                 MONO_OBJECT_SETREF (param, MemberImpl, (MonoObject*)member);
6163                 MONO_OBJECT_SETREF (param, NameImpl, mono_string_new (domain, names [i]));
6164                 param->PositionImpl = i;
6165                 param->AttrsImpl = sig->params [i]->attrs;
6166
6167                 if (!(param->AttrsImpl & PARAM_ATTRIBUTE_HAS_DEFAULT)) {
6168                         if (param->AttrsImpl & PARAM_ATTRIBUTE_OPTIONAL)
6169                                 MONO_OBJECT_SETREF (param, DefaultValueImpl, get_reflection_missing (domain, &missing));
6170                         else
6171                                 MONO_OBJECT_SETREF (param, DefaultValueImpl, get_dbnull (domain, &dbnull));
6172                 } else {
6173
6174                         if (!blobs) {
6175                                 blobs = g_new0 (char *, sig->param_count);
6176                                 types = g_new0 (guint32, sig->param_count);
6177                                 get_default_param_value_blobs (method, blobs, types); 
6178                         }
6179
6180                         /* Build MonoType for the type from the Constant Table */
6181                         if (!type)
6182                                 type = g_new0 (MonoType, 1);
6183                         type->type = types [i];
6184                         type->data.klass = NULL;
6185                         if (types [i] == MONO_TYPE_CLASS)
6186                                 type->data.klass = mono_defaults.object_class;
6187                         else if ((sig->params [i]->type == MONO_TYPE_VALUETYPE) && sig->params [i]->data.klass->enumtype) {
6188                                 /* For enums, types [i] contains the base type */
6189
6190                                         type->type = MONO_TYPE_VALUETYPE;
6191                                         type->data.klass = mono_class_from_mono_type (sig->params [i]);
6192                         } else
6193                                 type->data.klass = mono_class_from_mono_type (type);
6194
6195                         MONO_OBJECT_SETREF (param, DefaultValueImpl, mono_get_object_from_blob (domain, type, blobs [i]));
6196
6197                         /* Type in the Constant table is MONO_TYPE_CLASS for nulls */
6198                         if (types [i] != MONO_TYPE_CLASS && !param->DefaultValueImpl) {
6199                                 if (param->AttrsImpl & PARAM_ATTRIBUTE_OPTIONAL)
6200                                         MONO_OBJECT_SETREF (param, DefaultValueImpl, get_reflection_missing (domain, &missing));
6201                                 else
6202                                         MONO_OBJECT_SETREF (param, DefaultValueImpl, get_dbnull (domain, &dbnull));
6203                         }
6204                         
6205                 }
6206
6207                 if (mspecs [i + 1])
6208                         MONO_OBJECT_SETREF (param, MarshalAsImpl, (MonoObject*)mono_reflection_marshal_from_marshal_spec (domain, method->klass, mspecs [i + 1]));
6209                 
6210                 mono_array_setref (res, i, param);
6211         }
6212         g_free (names);
6213         g_free (blobs);
6214         g_free (types);
6215         g_free (type);
6216
6217         for (i = mono_method_signature (method)->param_count; i >= 0; i--)
6218                 if (mspecs [i])
6219                         mono_metadata_free_marshal_spec (mspecs [i]);
6220         g_free (mspecs);
6221         
6222         CACHE_OBJECT (MonoArray *, &(method->signature), res, NULL);
6223 }
6224
6225 /*
6226  * mono_method_body_get_object:
6227  * @domain: an app domain
6228  * @method: a method
6229  *
6230  * Return an System.Reflection.MethodBody object representing the method @method.
6231  */
6232 MonoReflectionMethodBody*
6233 mono_method_body_get_object (MonoDomain *domain, MonoMethod *method)
6234 {
6235         static MonoClass *System_Reflection_MethodBody = NULL;
6236         static MonoClass *System_Reflection_LocalVariableInfo = NULL;
6237         static MonoClass *System_Reflection_ExceptionHandlingClause = NULL;
6238         MonoReflectionMethodBody *ret;
6239         MonoMethodNormal *mn;
6240         MonoMethodHeader *header;
6241         guint32 method_rva, local_var_sig_token;
6242     char *ptr;
6243         unsigned char format, flags;
6244         int i;
6245
6246         if (!System_Reflection_MethodBody)
6247                 System_Reflection_MethodBody = mono_class_from_name (mono_defaults.corlib, "System.Reflection", "MethodBody");
6248         if (!System_Reflection_LocalVariableInfo)
6249                 System_Reflection_LocalVariableInfo = mono_class_from_name (mono_defaults.corlib, "System.Reflection", "LocalVariableInfo");
6250         if (!System_Reflection_ExceptionHandlingClause)
6251                 System_Reflection_ExceptionHandlingClause = mono_class_from_name (mono_defaults.corlib, "System.Reflection", "ExceptionHandlingClause");
6252
6253         CHECK_OBJECT (MonoReflectionMethodBody *, method, NULL);
6254
6255         if ((method->flags & METHOD_ATTRIBUTE_PINVOKE_IMPL) ||
6256                 (method->flags & METHOD_ATTRIBUTE_ABSTRACT) ||
6257             (method->iflags & METHOD_IMPL_ATTRIBUTE_INTERNAL_CALL) ||
6258             (method->iflags & METHOD_IMPL_ATTRIBUTE_RUNTIME))
6259                 return NULL;
6260         mn = (MonoMethodNormal *)method;
6261         header = mono_method_get_header (method);
6262         
6263         /* Obtain local vars signature token */
6264         method_rva = mono_metadata_decode_row_col (&method->klass->image->tables [MONO_TABLE_METHOD], mono_metadata_token_index (method->token) - 1, MONO_METHOD_RVA);
6265         ptr = mono_image_rva_map (method->klass->image, method_rva);
6266         flags = *(const unsigned char *) ptr;
6267         format = flags & METHOD_HEADER_FORMAT_MASK;
6268         switch (format){
6269         case METHOD_HEADER_TINY_FORMAT:
6270         case METHOD_HEADER_TINY_FORMAT1:
6271                 local_var_sig_token = 0;
6272                 break;
6273         case METHOD_HEADER_FAT_FORMAT:
6274                 ptr += 2;
6275                 ptr += 2;
6276                 ptr += 4;
6277                 local_var_sig_token = read32 (ptr);
6278                 break;
6279         default:
6280                 g_assert_not_reached ();
6281         }
6282
6283         ret = (MonoReflectionMethodBody*)mono_object_new (domain, System_Reflection_MethodBody);
6284
6285         ret->init_locals = header->init_locals;
6286         ret->max_stack = header->max_stack;
6287         ret->local_var_sig_token = local_var_sig_token;
6288         MONO_OBJECT_SETREF (ret, il, mono_array_new (domain, mono_defaults.byte_class, header->code_size));
6289         memcpy (mono_array_addr (ret->il, guint8, 0), header->code, header->code_size);
6290
6291         /* Locals */
6292         MONO_OBJECT_SETREF (ret, locals, mono_array_new (domain, System_Reflection_LocalVariableInfo, header->num_locals));
6293         for (i = 0; i < header->num_locals; ++i) {
6294                 MonoReflectionLocalVariableInfo *info = (MonoReflectionLocalVariableInfo*)mono_object_new (domain, System_Reflection_LocalVariableInfo);
6295                 MONO_OBJECT_SETREF (info, local_type, mono_type_get_object (domain, header->locals [i]));
6296                 info->is_pinned = header->locals [i]->pinned;
6297                 info->local_index = i;
6298                 mono_array_setref (ret->locals, i, info);
6299         }
6300
6301         /* Exceptions */
6302         MONO_OBJECT_SETREF (ret, clauses, mono_array_new (domain, System_Reflection_ExceptionHandlingClause, header->num_clauses));
6303         for (i = 0; i < header->num_clauses; ++i) {
6304                 MonoReflectionExceptionHandlingClause *info = (MonoReflectionExceptionHandlingClause*)mono_object_new (domain, System_Reflection_ExceptionHandlingClause);
6305                 MonoExceptionClause *clause = &header->clauses [i];
6306
6307                 info->flags = clause->flags;
6308                 info->try_offset = clause->try_offset;
6309                 info->try_length = clause->try_len;
6310                 info->handler_offset = clause->handler_offset;
6311                 info->handler_length = clause->handler_len;
6312                 if (clause->flags == MONO_EXCEPTION_CLAUSE_FILTER)
6313                         info->filter_offset = clause->data.filter_offset;
6314                 else if (clause->data.catch_class)
6315                         MONO_OBJECT_SETREF (info, catch_type, mono_type_get_object (mono_domain_get (), &clause->data.catch_class->byval_arg));
6316
6317                 mono_array_setref (ret->clauses, i, info);
6318         }
6319
6320         CACHE_OBJECT (MonoReflectionMethodBody *, method, ret, NULL);
6321         return ret;
6322 }
6323
6324 /**
6325  * mono_get_dbnull_object:
6326  * @domain: Domain where the object lives
6327  *
6328  * Returns the System.DBNull.Value singleton object
6329  *
6330  * Used as the value for ParameterInfo.DefaultValue 
6331  */
6332 MonoObject *
6333 mono_get_dbnull_object (MonoDomain *domain)
6334 {
6335         MonoObject *obj;
6336         static MonoClassField *dbnull_value_field = NULL;
6337         
6338         if (!dbnull_value_field) {
6339                 MonoClass *dbnull_klass;
6340                 dbnull_klass = mono_class_from_name (mono_defaults.corlib, "System", "DBNull");
6341                 mono_class_init (dbnull_klass);
6342                 dbnull_value_field = mono_class_get_field_from_name (dbnull_klass, "Value");
6343                 g_assert (dbnull_value_field);
6344         }
6345         obj = mono_field_get_value_object (domain, dbnull_value_field, NULL); 
6346         g_assert (obj);
6347         return obj;
6348 }
6349
6350 static void
6351 get_default_param_value_blobs (MonoMethod *method, char **blobs, guint32 *types)
6352 {
6353         guint32 param_index, i, lastp, crow = 0;
6354         guint32 param_cols [MONO_PARAM_SIZE], const_cols [MONO_CONSTANT_SIZE];
6355         gint32 idx;
6356
6357         MonoClass *klass = method->klass;
6358         MonoImage *image = klass->image;
6359         MonoMethodSignature *methodsig = mono_method_signature (method);
6360
6361         MonoTableInfo *constt;
6362         MonoTableInfo *methodt;
6363         MonoTableInfo *paramt;
6364
6365         if (!methodsig->param_count)
6366                 return;
6367
6368         mono_class_init (klass);
6369
6370         if (klass->image->dynamic) {
6371                 MonoReflectionMethodAux *aux;
6372                 if (method->is_inflated)
6373                         method = ((MonoMethodInflated*)method)->declaring;
6374                 aux = g_hash_table_lookup (((MonoDynamicImage*)method->klass->image)->method_aux_hash, method);
6375                 if (aux && aux->param_defaults) {
6376                         memcpy (blobs, &(aux->param_defaults [1]), methodsig->param_count * sizeof (char*));
6377                         memcpy (types, &(aux->param_default_types [1]), methodsig->param_count * sizeof (guint32));
6378                 }
6379                 return;
6380         }
6381
6382         methodt = &klass->image->tables [MONO_TABLE_METHOD];
6383         paramt = &klass->image->tables [MONO_TABLE_PARAM];
6384         constt = &image->tables [MONO_TABLE_CONSTANT];
6385
6386         idx = mono_method_get_index (method) - 1;
6387         g_assert (idx != -1);
6388
6389         param_index = mono_metadata_decode_row_col (methodt, idx, MONO_METHOD_PARAMLIST);
6390         if (idx + 1 < methodt->rows)
6391                 lastp = mono_metadata_decode_row_col (methodt, idx + 1, MONO_METHOD_PARAMLIST);
6392         else
6393                 lastp = paramt->rows + 1;
6394
6395         for (i = param_index; i < lastp; ++i) {
6396                 guint32 paramseq;
6397
6398                 mono_metadata_decode_row (paramt, i - 1, param_cols, MONO_PARAM_SIZE);
6399                 paramseq = param_cols [MONO_PARAM_SEQUENCE];
6400
6401                 if (!param_cols [MONO_PARAM_FLAGS] & PARAM_ATTRIBUTE_HAS_DEFAULT) 
6402                         continue;
6403
6404                 crow = mono_metadata_get_constant_index (image, MONO_TOKEN_PARAM_DEF | i, crow + 1);
6405                 if (!crow) {
6406                         continue;
6407                 }
6408         
6409                 mono_metadata_decode_row (constt, crow - 1, const_cols, MONO_CONSTANT_SIZE);
6410                 blobs [paramseq - 1] = (gpointer) mono_metadata_blob_heap (image, const_cols [MONO_CONSTANT_VALUE]);
6411                 types [paramseq - 1] = const_cols [MONO_CONSTANT_TYPE];
6412         }
6413
6414         return;
6415 }
6416
6417 static MonoObject *
6418 mono_get_object_from_blob (MonoDomain *domain, MonoType *type, const char *blob)
6419 {
6420         void *retval;
6421         MonoClass *klass;
6422         MonoObject *object;
6423         MonoType *basetype = type;
6424
6425         if (!blob)
6426                 return NULL;
6427         
6428         klass = mono_class_from_mono_type (type);
6429         if (klass->valuetype) {
6430                 object = mono_object_new (domain, klass);
6431                 retval = ((gchar *) object + sizeof (MonoObject));
6432                 if (klass->enumtype)
6433                         basetype = klass->enum_basetype;
6434         } else {
6435                 retval = &object;
6436         }
6437                         
6438         if (!mono_get_constant_value_from_blob (domain, basetype->type,  blob, retval))
6439                 return object;
6440         else
6441                 return NULL;
6442 }
6443
6444 static int
6445 assembly_name_to_aname (MonoAssemblyName *assembly, char *p) {
6446         int found_sep;
6447         char *s;
6448
6449         memset (assembly, 0, sizeof (MonoAssemblyName));
6450         assembly->name = p;
6451         assembly->culture = "";
6452         memset (assembly->public_key_token, 0, MONO_PUBLIC_KEY_TOKEN_LENGTH);
6453
6454         while (*p && (isalnum (*p) || *p == '.' || *p == '-' || *p == '_' || *p == '$' || *p == '@'))
6455                 p++;
6456         found_sep = 0;
6457         while (g_ascii_isspace (*p) || *p == ',') {
6458                 *p++ = 0;
6459                 found_sep = 1;
6460                 continue;
6461         }
6462         /* failed */
6463         if (!found_sep)
6464                 return 1;
6465         while (*p) {
6466                 if (*p == 'V' && g_ascii_strncasecmp (p, "Version=", 8) == 0) {
6467                         p += 8;
6468                         assembly->major = strtoul (p, &s, 10);
6469                         if (s == p || *s != '.')
6470                                 return 1;
6471                         p = ++s;
6472                         assembly->minor = strtoul (p, &s, 10);
6473                         if (s == p || *s != '.')
6474                                 return 1;
6475                         p = ++s;
6476                         assembly->build = strtoul (p, &s, 10);
6477                         if (s == p || *s != '.')
6478                                 return 1;
6479                         p = ++s;
6480                         assembly->revision = strtoul (p, &s, 10);
6481                         if (s == p)
6482                                 return 1;
6483                         p = s;
6484                 } else if (*p == 'C' && g_ascii_strncasecmp (p, "Culture=", 8) == 0) {
6485                         p += 8;
6486                         if (g_ascii_strncasecmp (p, "neutral", 7) == 0) {
6487                                 assembly->culture = "";
6488                                 p += 7;
6489                         } else {
6490                                 assembly->culture = p;
6491                                 while (*p && *p != ',') {
6492                                         p++;
6493                                 }
6494                         }
6495                 } else if (*p == 'P' && g_ascii_strncasecmp (p, "PublicKeyToken=", 15) == 0) {
6496                         p += 15;
6497                         if (strncmp (p, "null", 4) == 0) {
6498                                 p += 4;
6499                         } else {
6500                                 int len;
6501                                 gchar *start = p;
6502                                 while (*p && *p != ',') {
6503                                         p++;
6504                                 }
6505                                 len = (p - start + 1);
6506                                 if (len > MONO_PUBLIC_KEY_TOKEN_LENGTH)
6507                                         len = MONO_PUBLIC_KEY_TOKEN_LENGTH;
6508                                 g_strlcpy ((char*)assembly->public_key_token, start, len);
6509                         }
6510                 } else {
6511                         while (*p && *p != ',')
6512                                 p++;
6513                 }
6514                 found_sep = 0;
6515                 while (g_ascii_isspace (*p) || *p == ',') {
6516                         *p++ = 0;
6517                         found_sep = 1;
6518                         continue;
6519                 }
6520                 /* failed */
6521                 if (!found_sep)
6522                         return 1;
6523         }
6524
6525         return 0;
6526 }
6527
6528 /*
6529  * mono_reflection_parse_type:
6530  * @name: type name
6531  *
6532  * Parse a type name as accepted by the GetType () method and output the info
6533  * extracted in the info structure.
6534  * the name param will be mangled, so, make a copy before passing it to this function.
6535  * The fields in info will be valid until the memory pointed to by name is valid.
6536  *
6537  * See also mono_type_get_name () below.
6538  *
6539  * Returns: 0 on parse error.
6540  */
6541 static int
6542 _mono_reflection_parse_type (char *name, char **endptr, gboolean is_recursed,
6543                              MonoTypeNameParse *info)
6544 {
6545         char *start, *p, *w, *temp, *last_point, *startn;
6546         int in_modifiers = 0;
6547         int isbyref = 0, rank, arity = 0, i;
6548
6549         start = p = w = name;
6550
6551         //FIXME could we just zero the whole struct? memset (&info, 0, sizeof (MonoTypeNameParse))
6552         memset (&info->assembly, 0, sizeof (MonoAssemblyName));
6553         info->name = info->name_space = NULL;
6554         info->nested = NULL;
6555         info->modifiers = NULL;
6556         info->type_arguments = NULL;
6557
6558         /* last_point separates the namespace from the name */
6559         last_point = NULL;
6560
6561         while (*p) {
6562                 switch (*p) {
6563                 case '+':
6564                         *p = 0; /* NULL terminate the name */
6565                         startn = p + 1;
6566                         info->nested = g_list_append (info->nested, startn);
6567                         /* we have parsed the nesting namespace + name */
6568                         if (info->name)
6569                                 break;
6570                         if (last_point) {
6571                                 info->name_space = start;
6572                                 *last_point = 0;
6573                                 info->name = last_point + 1;
6574                         } else {
6575                                 info->name_space = (char *)"";
6576                                 info->name = start;
6577                         }
6578                         break;
6579                 case '.':
6580                         last_point = p;
6581                         break;
6582                 case '\\':
6583                         ++p;
6584                         break;
6585                 case '&':
6586                 case '*':
6587                 case '[':
6588                 case ',':
6589                 case ']':
6590                         in_modifiers = 1;
6591                         break;
6592                 case '`':
6593                         ++p;
6594                         i = strtol (p, &temp, 10);
6595                         arity += i;
6596                         if (p == temp)
6597                                 return 0;
6598                         p = temp-1;
6599                         break;
6600                 default:
6601                         break;
6602                 }
6603                 if (in_modifiers)
6604                         break;
6605                 // *w++ = *p++;
6606                 p++;
6607         }
6608         
6609         if (!info->name) {
6610                 if (last_point) {
6611                         info->name_space = start;
6612                         *last_point = 0;
6613                         info->name = last_point + 1;
6614                 } else {
6615                         info->name_space = (char *)"";
6616                         info->name = start;
6617                 }
6618         }
6619         while (*p) {
6620                 switch (*p) {
6621                 case '&':
6622                         if (isbyref) /* only one level allowed by the spec */
6623                                 return 0;
6624                         isbyref = 1;
6625                         info->modifiers = g_list_append (info->modifiers, GUINT_TO_POINTER (0));
6626                         *p++ = 0;
6627                         break;
6628                 case '*':
6629                         info->modifiers = g_list_append (info->modifiers, GUINT_TO_POINTER (-1));
6630                         *p++ = 0;
6631                         break;
6632                 case '[':
6633                         if (arity != 0) {
6634                                 *p++ = 0;
6635                                 info->type_arguments = g_ptr_array_new ();
6636                                 for (i = 0; i < arity; i++) {
6637                                         MonoTypeNameParse *subinfo = g_new0 (MonoTypeNameParse, 1);
6638                                         gboolean fqname = FALSE;
6639
6640                                         g_ptr_array_add (info->type_arguments, subinfo);
6641
6642                                         if (*p == '[') {
6643                                                 p++;
6644                                                 fqname = TRUE;
6645                                         }
6646
6647                                         if (!_mono_reflection_parse_type (p, &p, TRUE, subinfo))
6648                                                 return 0;
6649
6650                                         if (fqname) {
6651                                                 char *aname;
6652
6653                                                 if (*p != ',')
6654                                                         return 0;
6655                                                 *p++ = 0;
6656
6657                                                 aname = p;
6658                                                 while (*p && (*p != ']'))
6659                                                         p++;
6660
6661                                                 if (*p != ']')
6662                                                         return 0;
6663
6664                                                 *p++ = 0;
6665                                                 while (*aname) {
6666                                                         if (g_ascii_isspace (*aname)) {
6667                                                                 ++aname;
6668                                                                 continue;
6669                                                         }
6670                                                         break;
6671                                                 }
6672                                                 if (!*aname ||
6673                                                     !assembly_name_to_aname (&subinfo->assembly, aname))
6674                                                         return 0;
6675                                         }
6676
6677                                         if (i + 1 < arity) {
6678                                                 if (*p != ',')
6679                                                         return 0;
6680                                         } else {
6681                                                 if (*p != ']')
6682                                                         return 0;
6683                                         }
6684                                         *p++ = 0;
6685                                 }
6686
6687                                 arity = 0;
6688                                 break;
6689                         }
6690                         rank = 1;
6691                         *p++ = 0;
6692                         while (*p) {
6693                                 if (*p == ']')
6694                                         break;
6695                                 if (*p == ',')
6696                                         rank++;
6697                                 else if (*p == '*') /* '*' means unknown lower bound */
6698                                         info->modifiers = g_list_append (info->modifiers, GUINT_TO_POINTER (-2));
6699                                 else
6700                                         return 0;
6701                                 ++p;
6702                         }
6703                         if (*p++ != ']')
6704                                 return 0;
6705                         info->modifiers = g_list_append (info->modifiers, GUINT_TO_POINTER (rank));
6706                         break;
6707                 case ']':
6708                         if (is_recursed)
6709                                 goto end;
6710                         return 0;
6711                 case ',':
6712                         if (is_recursed)
6713                                 goto end;
6714                         *p++ = 0;
6715                         while (*p) {
6716                                 if (g_ascii_isspace (*p)) {
6717                                         ++p;
6718                                         continue;
6719                                 }
6720                                 break;
6721                         }
6722                         if (!*p)
6723                                 return 0; /* missing assembly name */
6724                         if (!assembly_name_to_aname (&info->assembly, p))
6725                                 return 0;
6726                         break;
6727                 default:
6728                         return 0;
6729                 }
6730                 if (info->assembly.name)
6731                         break;
6732         }
6733         // *w = 0; /* terminate class name */
6734  end:
6735         if (!info->name || !*info->name)
6736                 return 0;
6737         if (endptr)
6738                 *endptr = p;
6739         /* add other consistency checks */
6740         return 1;
6741 }
6742
6743 int
6744 mono_reflection_parse_type (char *name, MonoTypeNameParse *info)
6745 {
6746         return _mono_reflection_parse_type (name, NULL, FALSE, info);
6747 }
6748
6749 static MonoType*
6750 _mono_reflection_get_type_from_info (MonoTypeNameParse *info, MonoImage *image, gboolean ignorecase)
6751 {
6752         gboolean type_resolve = FALSE;
6753         MonoType *type;
6754         MonoImage *rootimage = image;
6755
6756         if (info->assembly.name) {
6757                 MonoAssembly *assembly = mono_assembly_loaded (&info->assembly);
6758                 if (!assembly) {
6759                         /* then we must load the assembly ourselve - see #60439 */
6760                         assembly = mono_assembly_load (&info->assembly, NULL, NULL);
6761                         if (!assembly)
6762                                 return NULL;
6763                 }
6764                 image = assembly->image;
6765         } else if (!image) {
6766                 image = mono_defaults.corlib;
6767         }
6768
6769         type = mono_reflection_get_type_with_rootimage (rootimage, image, info, ignorecase, &type_resolve);
6770         if (type == NULL && !info->assembly.name && image != mono_defaults.corlib) {
6771                 image = mono_defaults.corlib;
6772                 type = mono_reflection_get_type_with_rootimage (rootimage, image, info, ignorecase, &type_resolve);
6773         }
6774
6775         return type;
6776 }
6777
6778 static MonoType*
6779 mono_reflection_get_type_internal (MonoImage *rootimage, MonoImage* image, MonoTypeNameParse *info, gboolean ignorecase)
6780 {
6781         MonoClass *klass;
6782         GList *mod;
6783         int modval;
6784         gboolean bounded = FALSE;
6785         
6786         if (!image)
6787                 image = mono_defaults.corlib;
6788
6789         if (ignorecase)
6790                 klass = mono_class_from_name_case (image, info->name_space, info->name);
6791         else
6792                 klass = mono_class_from_name (image, info->name_space, info->name);
6793         if (!klass)
6794                 return NULL;
6795         for (mod = info->nested; mod; mod = mod->next) {
6796                 GList *nested;
6797
6798                 mono_class_init (klass);
6799                 nested = klass->nested_classes;
6800                 klass = NULL;
6801                 while (nested) {
6802                         klass = nested->data;
6803                         if (ignorecase) {
6804                                 if (g_strcasecmp (klass->name, mod->data) == 0)
6805                                         break;
6806                         } else {
6807                                 if (strcmp (klass->name, mod->data) == 0)
6808                                         break;
6809                         }
6810                         klass = NULL;
6811                         nested = nested->next;
6812                 }
6813                 if (!klass)
6814                         break;
6815         }
6816         if (!klass)
6817                 return NULL;
6818         mono_class_init (klass);
6819
6820         if (info->type_arguments) {
6821                 MonoType **type_args = g_new0 (MonoType *, info->type_arguments->len);
6822                 MonoReflectionType *the_type;
6823                 MonoType *instance;
6824                 int i;
6825
6826                 for (i = 0; i < info->type_arguments->len; i++) {
6827                         MonoTypeNameParse *subinfo = g_ptr_array_index (info->type_arguments, i);
6828
6829                         type_args [i] = _mono_reflection_get_type_from_info (subinfo, rootimage, ignorecase);
6830                         if (!type_args [i]) {
6831                                 g_free (type_args);
6832                                 return NULL;
6833                         }
6834                 }
6835
6836                 the_type = mono_type_get_object (mono_domain_get (), &klass->byval_arg);
6837
6838                 instance = mono_reflection_bind_generic_parameters (
6839                         the_type, info->type_arguments->len, type_args);
6840
6841                 g_free (type_args);
6842                 if (!instance)
6843                         return NULL;
6844
6845                 klass = mono_class_from_mono_type (instance);
6846         }
6847
6848         for (mod = info->modifiers; mod; mod = mod->next) {
6849                 modval = GPOINTER_TO_UINT (mod->data);
6850                 if (!modval) { /* byref: must be last modifier */
6851                         return &klass->this_arg;
6852                 } else if (modval == -1) {
6853                         klass = mono_ptr_class_get (&klass->byval_arg);
6854                 } else if (modval == -2) {
6855                         bounded = TRUE;
6856                 } else { /* array rank */
6857                         klass = mono_bounded_array_class_get (klass, modval, bounded);
6858                 }
6859                 mono_class_init (klass);
6860         }
6861
6862         return &klass->byval_arg;
6863 }
6864
6865 /*
6866  * mono_reflection_get_type:
6867  * @image: a metadata context
6868  * @info: type description structure
6869  * @ignorecase: flag for case-insensitive string compares
6870  * @type_resolve: whenever type resolve was already tried
6871  *
6872  * Build a MonoType from the type description in @info.
6873  * 
6874  */
6875
6876 MonoType*
6877 mono_reflection_get_type (MonoImage* image, MonoTypeNameParse *info, gboolean ignorecase, gboolean *type_resolve) {
6878         return mono_reflection_get_type_with_rootimage(image, image, info, ignorecase, type_resolve);
6879 }
6880
6881 static MonoType*
6882 mono_reflection_get_type_internal_dynamic (MonoImage *rootimage, MonoAssembly *assembly, MonoTypeNameParse *info, gboolean ignorecase)
6883 {
6884         MonoReflectionAssemblyBuilder *abuilder = (MonoReflectionAssemblyBuilder*)mono_assembly_get_object (mono_domain_get (), assembly);
6885         MonoType *type;
6886         int i;
6887
6888         g_assert (assembly->dynamic);
6889
6890         /* Enumerate all modules */
6891
6892         type = NULL;
6893         if (abuilder->modules) {
6894                 for (i = 0; i < mono_array_length (abuilder->modules); ++i) {
6895                         MonoReflectionModuleBuilder *mb = mono_array_get (abuilder->modules, MonoReflectionModuleBuilder*, i);
6896                         type = mono_reflection_get_type_internal (rootimage, &mb->dynamic_image->image, info, ignorecase);
6897                         if (type)
6898                                 break;
6899                 }
6900         }
6901
6902         if (!type && abuilder->loaded_modules) {
6903                 for (i = 0; i < mono_array_length (abuilder->loaded_modules); ++i) {
6904                         MonoReflectionModule *mod = mono_array_get (abuilder->loaded_modules, MonoReflectionModule*, i);
6905                         type = mono_reflection_get_type_internal (rootimage, mod->image, info, ignorecase);
6906                         if (type)
6907                                 break;
6908                 }
6909         }
6910
6911         return type;
6912 }
6913         
6914 MonoType*
6915 mono_reflection_get_type_with_rootimage (MonoImage *rootimage, MonoImage* image, MonoTypeNameParse *info, gboolean ignorecase, gboolean *type_resolve)
6916 {
6917         MonoType *type;
6918         MonoReflectionAssembly *assembly;
6919         GString *fullName;
6920         GList *mod;
6921
6922         if (image && image->dynamic)
6923                 type = mono_reflection_get_type_internal_dynamic (rootimage, image->assembly, info, ignorecase);
6924         else
6925                 type = mono_reflection_get_type_internal (rootimage, image, info, ignorecase);
6926         if (type)
6927                 return type;
6928         if (!mono_domain_has_type_resolve (mono_domain_get ()))
6929                 return NULL;
6930
6931         if (type_resolve) {
6932                 if (*type_resolve) 
6933                         return NULL;
6934                 else
6935                         *type_resolve = TRUE;
6936         }
6937         
6938         /* Reconstruct the type name */
6939         fullName = g_string_new ("");
6940         if (info->name_space && (info->name_space [0] != '\0'))
6941                 g_string_printf (fullName, "%s.%s", info->name_space, info->name);
6942         else
6943                 g_string_printf (fullName, info->name);
6944         for (mod = info->nested; mod; mod = mod->next)
6945                 g_string_append_printf (fullName, "+%s", (char*)mod->data);
6946
6947         assembly = mono_domain_try_type_resolve ( mono_domain_get (), fullName->str, NULL);
6948         if (assembly) {
6949                 if (assembly->assembly->dynamic)
6950                         type = mono_reflection_get_type_internal_dynamic (rootimage, assembly->assembly, info, ignorecase);
6951                 else
6952                         type = mono_reflection_get_type_internal (rootimage, assembly->assembly->image, 
6953                                                                                                           info, ignorecase);
6954         }
6955         g_string_free (fullName, TRUE);
6956         return type;
6957 }
6958
6959 void
6960 mono_reflection_free_type_info (MonoTypeNameParse *info)
6961 {
6962         g_list_free (info->modifiers);
6963         g_list_free (info->nested);
6964
6965         if (info->type_arguments) {
6966                 int i;
6967
6968                 for (i = 0; i < info->type_arguments->len; i++) {
6969                         MonoTypeNameParse *subinfo = g_ptr_array_index (info->type_arguments, i);
6970
6971                         mono_reflection_free_type_info (subinfo);
6972                         /*We free the subinfo since it is allocated by _mono_reflection_parse_type*/
6973                         g_free (subinfo);
6974                 }
6975
6976                 g_ptr_array_free (info->type_arguments, TRUE);
6977         }
6978 }
6979
6980 /*
6981  * mono_reflection_type_from_name:
6982  * @name: type name.
6983  * @image: a metadata context (can be NULL).
6984  *
6985  * Retrieves a MonoType from its @name. If the name is not fully qualified,
6986  * it defaults to get the type from @image or, if @image is NULL or loading
6987  * from it fails, uses corlib.
6988  * 
6989  */
6990 MonoType*
6991 mono_reflection_type_from_name (char *name, MonoImage *image)
6992 {
6993         MonoType *type = NULL;
6994         MonoTypeNameParse info;
6995         char *tmp;
6996
6997         /* Make a copy since parse_type modifies its argument */
6998         tmp = g_strdup (name);
6999         
7000         /*g_print ("requested type %s\n", str);*/
7001         if (mono_reflection_parse_type (tmp, &info)) {
7002                 type = _mono_reflection_get_type_from_info (&info, image, FALSE);
7003         }
7004
7005         g_free (tmp);
7006         mono_reflection_free_type_info (&info);
7007         return type;
7008 }
7009
7010 /*
7011  * mono_reflection_get_token:
7012  *
7013  *   Return the metadata token of OBJ which should be an object
7014  * representing a metadata element.
7015  */
7016 guint32
7017 mono_reflection_get_token (MonoObject *obj)
7018 {
7019         MonoClass *klass;
7020         guint32 token = 0;
7021
7022         klass = obj->vtable->klass;
7023
7024         if (strcmp (klass->name, "MethodBuilder") == 0) {
7025                 MonoReflectionMethodBuilder *mb = (MonoReflectionMethodBuilder *)obj;
7026
7027                 token = mb->table_idx | MONO_TOKEN_METHOD_DEF;
7028         } else if (strcmp (klass->name, "ConstructorBuilder") == 0) {
7029                 MonoReflectionCtorBuilder *mb = (MonoReflectionCtorBuilder *)obj;
7030
7031                 token = mb->table_idx | MONO_TOKEN_METHOD_DEF;
7032         } else if (strcmp (klass->name, "FieldBuilder") == 0) {
7033                 MonoReflectionFieldBuilder *fb = (MonoReflectionFieldBuilder *)obj;
7034
7035                 /* Call mono_image_create_token so the object gets added to the tokens hash table */
7036                 token = mono_image_create_token (((MonoReflectionTypeBuilder*)fb->typeb)->module->dynamic_image, obj, FALSE, TRUE);
7037         } else if (strcmp (klass->name, "TypeBuilder") == 0) {
7038                 MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder *)obj;
7039                 token = tb->table_idx | MONO_TOKEN_TYPE_DEF;
7040         } else if (strcmp (klass->name, "MonoType") == 0) {
7041                 MonoReflectionType *tb = (MonoReflectionType *)obj;
7042                 token = mono_class_from_mono_type (tb->type)->type_token;
7043         } else if (strcmp (klass->name, "MonoCMethod") == 0 ||
7044                    strcmp (klass->name, "MonoMethod") == 0 ||
7045                    strcmp (klass->name, "MonoGenericMethod") == 0 ||
7046                    strcmp (klass->name, "MonoGenericCMethod") == 0) {
7047                 MonoReflectionMethod *m = (MonoReflectionMethod *)obj;
7048                 if (m->method->is_inflated) {
7049                         MonoMethodInflated *inflated = (MonoMethodInflated *) m->method;
7050                         return inflated->declaring->token;
7051                 } else {
7052                         token = m->method->token;
7053                 }
7054         } else if (strcmp (klass->name, "MonoField") == 0) {
7055                 MonoReflectionField *f = (MonoReflectionField*)obj;
7056
7057                 if (f->field->generic_info && f->field->generic_info->reflection_info)
7058                         return mono_reflection_get_token (f->field->generic_info->reflection_info);
7059
7060                 token = mono_class_get_field_token (f->field);
7061         } else if (strcmp (klass->name, "MonoProperty") == 0) {
7062                 MonoReflectionProperty *p = (MonoReflectionProperty*)obj;
7063
7064                 token = mono_class_get_property_token (p->property);
7065         } else if (strcmp (klass->name, "MonoEvent") == 0) {
7066                 MonoReflectionEvent *p = (MonoReflectionEvent*)obj;
7067
7068                 token = mono_class_get_event_token (p->event);
7069         } else if (strcmp (klass->name, "ParameterInfo") == 0) {
7070                 MonoReflectionParameter *p = (MonoReflectionParameter*)obj;
7071
7072                 token = mono_method_get_param_token (((MonoReflectionMethod*)p->MemberImpl)->method, p->PositionImpl);
7073         } else if (strcmp (klass->name, "Module") == 0) {
7074                 MonoReflectionModule *m = (MonoReflectionModule*)obj;
7075
7076                 token = m->token;
7077         } else if (strcmp (klass->name, "Assembly") == 0) {
7078                 token = mono_metadata_make_token (MONO_TABLE_ASSEMBLY, 1);
7079         } else {
7080                 gchar *msg = g_strdup_printf ("MetadataToken is not supported for type '%s.%s'", klass->name_space, klass->name);
7081                 MonoException *ex = mono_get_exception_not_implemented (msg);
7082                 g_free (msg);
7083                 mono_raise_exception (ex);
7084         }
7085
7086         return token;
7087 }
7088
7089 static void*
7090 load_cattr_value (MonoImage *image, MonoType *t, const char *p, const char **end)
7091 {
7092         int slen, type = t->type;
7093         MonoClass *tklass = t->data.klass;
7094
7095 handle_enum:
7096         switch (type) {
7097         case MONO_TYPE_U1:
7098         case MONO_TYPE_I1:
7099         case MONO_TYPE_BOOLEAN: {
7100                 MonoBoolean *bval = g_malloc (sizeof (MonoBoolean));
7101                 *bval = *p;
7102                 *end = p + 1;
7103                 return bval;
7104         }
7105         case MONO_TYPE_CHAR:
7106         case MONO_TYPE_U2:
7107         case MONO_TYPE_I2: {
7108                 guint16 *val = g_malloc (sizeof (guint16));
7109                 *val = read16 (p);
7110                 *end = p + 2;
7111                 return val;
7112         }
7113 #if SIZEOF_VOID_P == 4
7114         case MONO_TYPE_U:
7115         case MONO_TYPE_I:
7116 #endif
7117         case MONO_TYPE_R4:
7118         case MONO_TYPE_U4:
7119         case MONO_TYPE_I4: {
7120                 guint32 *val = g_malloc (sizeof (guint32));
7121                 *val = read32 (p);
7122                 *end = p + 4;
7123                 return val;
7124         }
7125 #if SIZEOF_VOID_P == 8
7126         case MONO_TYPE_U: /* error out instead? this should probably not happen */
7127         case MONO_TYPE_I:
7128 #endif
7129         case MONO_TYPE_U8:
7130         case MONO_TYPE_I8: {
7131                 guint64 *val = g_malloc (sizeof (guint64));
7132                 *val = read64 (p);
7133                 *end = p + 8;
7134                 return val;
7135         }
7136         case MONO_TYPE_R8: {
7137                 double *val = g_malloc (sizeof (double));
7138                 readr8 (p, val);
7139                 *end = p + 8;
7140                 return val;
7141         }
7142         case MONO_TYPE_VALUETYPE:
7143                 if (t->data.klass->enumtype) {
7144                         type = t->data.klass->enum_basetype->type;
7145                         goto handle_enum;
7146                 } else {
7147                         g_error ("generic valutype %s not handled in custom attr value decoding", t->data.klass->name);
7148                 }
7149                 break;
7150         case MONO_TYPE_STRING:
7151                 if (*p == (char)0xFF) {
7152                         *end = p + 1;
7153                         return NULL;
7154                 }
7155                 slen = mono_metadata_decode_value (p, &p);
7156                 *end = p + slen;
7157                 return mono_string_new_len (mono_domain_get (), p, slen);
7158         case MONO_TYPE_CLASS: {
7159                 char *n;
7160                 MonoType *t;
7161                 if (*p == (char)0xFF) {
7162                         *end = p + 1;
7163                         return NULL;
7164                 }
7165 handle_type:
7166                 slen = mono_metadata_decode_value (p, &p);
7167                 n = g_memdup (p, slen + 1);
7168                 n [slen] = 0;
7169                 t = mono_reflection_type_from_name (n, image);
7170                 if (!t)
7171                         g_warning ("Cannot load type '%s'", n);
7172                 g_free (n);
7173                 *end = p + slen;
7174                 if (t)
7175                         return mono_type_get_object (mono_domain_get (), t);
7176                 else
7177                         return NULL;
7178         }
7179         case MONO_TYPE_OBJECT: {
7180                 char subt = *p++;
7181                 MonoObject *obj;
7182                 MonoClass *subc = NULL;
7183                 void *val;
7184
7185                 if (subt == 0x50) {
7186                         goto handle_type;
7187                 } else if (subt == 0x0E) {
7188                         type = MONO_TYPE_STRING;
7189                         goto handle_enum;
7190                 } else if (subt == 0x1D) {
7191                         MonoType simple_type = {{0}};
7192                         int etype = *p;
7193                         p ++;
7194
7195                         if (etype == 0x51)
7196                                 /* See Partition II, Appendix B3 */
7197                                 etype = MONO_TYPE_OBJECT;
7198                         type = MONO_TYPE_SZARRAY;
7199                         simple_type.type = etype;
7200                         tklass = mono_class_from_mono_type (&simple_type);
7201                         goto handle_enum;
7202                 } else if (subt == 0x55) {
7203                         char *n;
7204                         MonoType *t;
7205                         slen = mono_metadata_decode_value (p, &p);
7206                         n = g_memdup (p, slen + 1);
7207                         n [slen] = 0;
7208                         t = mono_reflection_type_from_name (n, image);
7209                         if (!t)
7210                                 g_error ("Cannot load type '%s'", n);
7211                         g_free (n);
7212                         p += slen;
7213                         subc = mono_class_from_mono_type (t);
7214                 } else if (subt >= MONO_TYPE_BOOLEAN && subt <= MONO_TYPE_R8) {
7215                         MonoType simple_type = {{0}};
7216                         simple_type.type = subt;
7217                         subc = mono_class_from_mono_type (&simple_type);
7218                 } else {
7219                         g_error ("Unknown type 0x%02x for object type encoding in custom attr", subt);
7220                 }
7221                 val = load_cattr_value (image, &subc->byval_arg, p, end);
7222                 obj = mono_object_new (mono_domain_get (), subc);
7223                 memcpy ((char*)obj + sizeof (MonoObject), val, mono_class_value_size (subc, NULL));
7224                 g_free (val);
7225                 return obj;
7226         }
7227         case MONO_TYPE_SZARRAY: {
7228                 MonoArray *arr;
7229                 guint32 i, alen, basetype;
7230                 alen = read32 (p);
7231                 p += 4;
7232                 if (alen == 0xffffffff) {
7233                         *end = p;
7234                         return NULL;
7235                 }
7236                 arr = mono_array_new (mono_domain_get(), tklass, alen);
7237                 basetype = tklass->byval_arg.type;
7238                 if (basetype == MONO_TYPE_VALUETYPE && tklass->enumtype)
7239                         basetype = tklass->enum_basetype->type;
7240                 switch (basetype)
7241                 {
7242                         case MONO_TYPE_U1:
7243                         case MONO_TYPE_I1:
7244                         case MONO_TYPE_BOOLEAN:
7245                                 for (i = 0; i < alen; i++) {
7246                                         MonoBoolean val = *p++;
7247                                         mono_array_set (arr, MonoBoolean, i, val);
7248                                 }
7249                                 break;
7250                         case MONO_TYPE_CHAR:
7251                         case MONO_TYPE_U2:
7252                         case MONO_TYPE_I2:
7253                                 for (i = 0; i < alen; i++) {
7254                                         guint16 val = read16 (p);
7255                                         mono_array_set (arr, guint16, i, val);
7256                                         p += 2;
7257                                 }
7258                                 break;
7259                         case MONO_TYPE_R4:
7260                         case MONO_TYPE_U4:
7261                         case MONO_TYPE_I4:
7262                                 for (i = 0; i < alen; i++) {
7263                                         guint32 val = read32 (p);
7264                                         mono_array_set (arr, guint32, i, val);
7265                                         p += 4;
7266                                 }
7267                                 break;
7268                         case MONO_TYPE_R8:
7269                                 for (i = 0; i < alen; i++) {
7270                                         double val;
7271                                         readr8 (p, &val);
7272                                         mono_array_set (arr, double, i, val);
7273                                         p += 8;
7274                                 }
7275                                 break;
7276                         case MONO_TYPE_U8:
7277                         case MONO_TYPE_I8:
7278                                 for (i = 0; i < alen; i++) {
7279                                         guint64 val = read64 (p);
7280                                         mono_array_set (arr, guint64, i, val);
7281                                         p += 8;
7282                                 }
7283                                 break;
7284                         case MONO_TYPE_CLASS:
7285                         case MONO_TYPE_OBJECT:
7286                         case MONO_TYPE_STRING:
7287                                 for (i = 0; i < alen; i++) {
7288                                         MonoObject *item = load_cattr_value (image, &tklass->byval_arg, p, &p);
7289                                         mono_array_setref (arr, i, item);
7290                                 }
7291                                 break;
7292                         default:
7293                                 g_error ("Type 0x%02x not handled in custom attr array decoding", basetype);
7294                 }
7295                 *end=p;
7296                 return arr;
7297         }
7298         default:
7299                 g_error ("Type 0x%02x not handled in custom attr value decoding", type);
7300         }
7301         return NULL;
7302 }
7303
7304 static MonoObject*
7305 create_cattr_typed_arg (MonoType *t, MonoObject *val)
7306 {
7307         static MonoClass *klass;
7308         static MonoMethod *ctor;
7309         MonoObject *retval;
7310         void *params [2], *unboxed;
7311
7312         if (!klass)
7313                 klass = mono_class_from_name (mono_defaults.corlib, "System.Reflection", "CustomAttributeTypedArgument");
7314         if (!ctor)
7315                 ctor = mono_class_get_method_from_name (klass, ".ctor", 2);
7316         
7317         params [0] = mono_type_get_object (mono_domain_get (), t);
7318         params [1] = val;
7319         retval = mono_object_new (mono_domain_get (), klass);
7320         unboxed = mono_object_unbox (retval);
7321         mono_runtime_invoke (ctor, unboxed, params, NULL);
7322
7323         return retval;
7324 }
7325
7326 static MonoObject*
7327 create_cattr_named_arg (void *minfo, MonoObject *typedarg)
7328 {
7329         static MonoClass *klass;
7330         static MonoMethod *ctor;
7331         MonoObject *retval;
7332         void *unboxed, *params [2];
7333
7334         if (!klass)
7335                 klass = mono_class_from_name (mono_defaults.corlib, "System.Reflection", "CustomAttributeNamedArgument");
7336         if (!ctor)
7337                 ctor = mono_class_get_method_from_name (klass, ".ctor", 2);
7338
7339         params [0] = minfo;
7340         params [1] = typedarg;
7341         retval = mono_object_new (mono_domain_get (), klass);
7342         unboxed = mono_object_unbox (retval);
7343         mono_runtime_invoke (ctor, unboxed, params, NULL);
7344
7345         return retval;
7346 }
7347
7348 static gboolean
7349 type_is_reference (MonoType *type)
7350 {
7351         switch (type->type) {
7352         case MONO_TYPE_BOOLEAN:
7353         case MONO_TYPE_CHAR:
7354         case MONO_TYPE_U:
7355         case MONO_TYPE_I:
7356         case MONO_TYPE_U1:
7357         case MONO_TYPE_I1:
7358         case MONO_TYPE_U2:
7359         case MONO_TYPE_I2:
7360         case MONO_TYPE_U4:
7361         case MONO_TYPE_I4:
7362         case MONO_TYPE_U8:
7363         case MONO_TYPE_I8:
7364         case MONO_TYPE_R8:
7365         case MONO_TYPE_R4:
7366         case MONO_TYPE_VALUETYPE:
7367                 return FALSE;
7368         default:
7369                 return TRUE;
7370         }
7371 }
7372
7373 static void
7374 free_param_data (MonoMethodSignature *sig, void **params) {
7375         int i;
7376         for (i = 0; i < sig->param_count; ++i) {
7377                 if (!type_is_reference (sig->params [i]))
7378                         g_free (params [i]);
7379         }
7380 }
7381
7382 /*
7383  * Find the field index in the metadata FieldDef table.
7384  */
7385 static guint32
7386 find_field_index (MonoClass *klass, MonoClassField *field) {
7387         int i;
7388
7389         for (i = 0; i < klass->field.count; ++i) {
7390                 if (field == &klass->fields [i])
7391                         return klass->field.first + 1 + i;
7392         }
7393         return 0;
7394 }
7395
7396 /*
7397  * Find the property index in the metadata Property table.
7398  */
7399 static guint32
7400 find_property_index (MonoClass *klass, MonoProperty *property) {
7401         int i;
7402
7403         for (i = 0; i < klass->property.count; ++i) {
7404                 if (property == &klass->properties [i])
7405                         return klass->property.first + 1 + i;
7406         }
7407         return 0;
7408 }
7409
7410 /*
7411  * Find the event index in the metadata Event table.
7412  */
7413 static guint32
7414 find_event_index (MonoClass *klass, MonoEvent *event) {
7415         int i;
7416
7417         for (i = 0; i < klass->event.count; ++i) {
7418                 if (event == &klass->events [i])
7419                         return klass->event.first + 1 + i;
7420         }
7421         return 0;
7422 }
7423
7424 static MonoObject*
7425 create_custom_attr (MonoImage *image, MonoMethod *method, const guchar *data, guint32 len)
7426 {
7427         const char *p = (const char*)data;
7428         const char *named;
7429         guint32 i, j, num_named;
7430         MonoObject *attr;
7431         void **params;
7432
7433         mono_class_init (method->klass);
7434
7435         if (len == 0) {
7436                 attr = mono_object_new (mono_domain_get (), method->klass);
7437                 mono_runtime_invoke (method, attr, NULL, NULL);
7438                 return attr;
7439         }
7440
7441         if (len < 2 || read16 (p) != 0x0001) /* Prolog */
7442                 return NULL;
7443
7444         /*g_print ("got attr %s\n", method->klass->name);*/
7445
7446         /* Allocate using alloca so it gets GC tracking */
7447         params = alloca (mono_method_signature (method)->param_count * sizeof (void*)); 
7448
7449         /* skip prolog */
7450         p += 2;
7451         for (i = 0; i < mono_method_signature (method)->param_count; ++i) {
7452                 params [i] = load_cattr_value (image, mono_method_signature (method)->params [i], p, &p);
7453         }
7454
7455         named = p;
7456         attr = mono_object_new (mono_domain_get (), method->klass);
7457         mono_runtime_invoke (method, attr, params, NULL);
7458         free_param_data (method->signature, params);
7459         num_named = read16 (named);
7460         named += 2;
7461         for (j = 0; j < num_named; j++) {
7462                 gint name_len;
7463                 char *name, named_type, data_type;
7464                 named_type = *named++;
7465                 data_type = *named++; /* type of data */
7466                 if (data_type == MONO_TYPE_SZARRAY)
7467                         data_type = *named++;
7468                 if (data_type == MONO_TYPE_ENUM) {
7469                         gint type_len;
7470                         char *type_name;
7471                         type_len = mono_metadata_decode_blob_size (named, &named);
7472                         type_name = g_malloc (type_len + 1);
7473                         memcpy (type_name, named, type_len);
7474                         type_name [type_len] = 0;
7475                         named += type_len;
7476                         /* FIXME: lookup the type and check type consistency */
7477                         g_free (type_name);
7478                 }
7479                 name_len = mono_metadata_decode_blob_size (named, &named);
7480                 name = g_malloc (name_len + 1);
7481                 memcpy (name, named, name_len);
7482                 name [name_len] = 0;
7483                 named += name_len;
7484                 if (named_type == 0x53) {
7485                         MonoClassField *field = mono_class_get_field_from_name (mono_object_class (attr), name);
7486                         void *val = load_cattr_value (image, field->type, named, &named);
7487                         mono_field_set_value (attr, field, val);
7488                         if (!type_is_reference (field->type))
7489                                 g_free (val);
7490                 } else if (named_type == 0x54) {
7491                         MonoProperty *prop;
7492                         void *pparams [1];
7493                         MonoType *prop_type;
7494
7495                         prop = mono_class_get_property_from_name (mono_object_class (attr), name);
7496                         /* can we have more that 1 arg in a custom attr named property? */
7497                         prop_type = prop->get? mono_method_signature (prop->get)->ret :
7498                              mono_method_signature (prop->set)->params [mono_method_signature (prop->set)->param_count - 1];
7499                         pparams [0] = load_cattr_value (image, prop_type, named, &named);
7500                         mono_property_set_value (prop, attr, pparams, NULL);
7501                         if (!type_is_reference (prop_type))
7502                                 g_free (pparams [0]);
7503                 }
7504                 g_free (name);
7505         }
7506
7507         return attr;
7508 }
7509
7510 static MonoObject*
7511 create_custom_attr_data (MonoImage *image, MonoMethod *method, const guchar *data, guint32 len)
7512 {
7513         MonoArray *typedargs, *namedargs;
7514         MonoClass *attrklass;
7515         static MonoMethod *ctor;
7516         MonoDomain *domain;
7517         MonoObject *attr;
7518         const char *p = (const char*)data;
7519         const char *named;
7520         guint32 i, j, num_named;
7521         void *params [3];
7522
7523         mono_class_init (method->klass);
7524
7525         if (!ctor)
7526                 ctor = mono_class_get_method_from_name (mono_defaults.customattribute_data_class, ".ctor", 3);
7527
7528         domain = mono_domain_get ();
7529         if (len == 0) {
7530                 /* This is for Attributes with no parameters */
7531                 attr = mono_object_new (domain, mono_defaults.customattribute_data_class);
7532                 params [0] = mono_method_get_object (domain, method, NULL);
7533                 params [1] = params [2] = NULL;
7534                 mono_runtime_invoke (method, attr, params, NULL);
7535                 return attr;
7536         }
7537
7538         if (len < 2 || read16 (p) != 0x0001) /* Prolog */
7539                 return NULL;
7540
7541         typedargs = mono_array_new (domain, mono_get_object_class (), mono_method_signature (method)->param_count);
7542         
7543         /* skip prolog */
7544         p += 2;
7545         for (i = 0; i < mono_method_signature (method)->param_count; ++i) {
7546                 MonoObject *obj, *typedarg;
7547                 void *val;
7548
7549                 val = load_cattr_value (image, mono_method_signature (method)->params [i], p, &p);
7550                 obj = type_is_reference (mono_method_signature (method)->params [i]) ? 
7551                         val : mono_value_box (domain, mono_class_from_mono_type (mono_method_signature (method)->params [i]), val);
7552                 typedarg = create_cattr_typed_arg (mono_method_signature (method)->params [i], obj);
7553                 mono_array_setref (typedargs, i, typedarg);
7554
7555                 if (!type_is_reference (mono_method_signature (method)->params [i]))
7556                         g_free (val);
7557         }
7558
7559         named = p;
7560         num_named = read16 (named);
7561         namedargs = mono_array_new (domain, mono_get_object_class (), num_named);
7562         named += 2;
7563         attrklass = method->klass;
7564         for (j = 0; j < num_named; j++) {
7565                 gint name_len;
7566                 char *name, named_type, data_type;
7567                 named_type = *named++;
7568                 data_type = *named++; /* type of data */
7569                 if (data_type == MONO_TYPE_SZARRAY)
7570                         data_type = *named++;
7571                 if (data_type == MONO_TYPE_ENUM) {
7572                         gint type_len;
7573                         char *type_name;
7574                         type_len = mono_metadata_decode_blob_size (named, &named);
7575                         type_name = g_malloc (type_len + 1);
7576                         memcpy (type_name, named, type_len);
7577                         type_name [type_len] = 0;
7578                         named += type_len;
7579                         /* FIXME: lookup the type and check type consistency */
7580                         g_free (type_name);
7581                 }
7582                 name_len = mono_metadata_decode_blob_size (named, &named);
7583                 name = g_malloc (name_len + 1);
7584                 memcpy (name, named, name_len);
7585                 name [name_len] = 0;
7586                 named += name_len;
7587                 if (named_type == 0x53) {
7588                         MonoObject *obj, *typedarg, *namedarg;
7589                         MonoClassField *field = mono_class_get_field_from_name (attrklass, name);
7590                         void *minfo, *val = load_cattr_value (image, field->type, named, &named);
7591                         
7592                         minfo = mono_field_get_object (domain, NULL, field);
7593                         obj = type_is_reference (field->type) ? val : mono_value_box (domain, mono_class_from_mono_type (field->type), val);
7594                         typedarg = create_cattr_typed_arg (field->type, obj);
7595                         namedarg = create_cattr_named_arg (minfo, typedarg);
7596                         mono_array_setref (namedargs, j, namedarg);
7597                         if (!type_is_reference (field->type))
7598                                 g_free (val);
7599                 } else if (named_type == 0x54) {
7600                         MonoObject *obj, *typedarg, *namedarg;
7601                         MonoType *prop_type;
7602                         void *val, *minfo;
7603                         MonoProperty *prop = mono_class_get_property_from_name (attrklass, name);
7604
7605                         prop_type = prop->get? mono_method_signature (prop->get)->ret :
7606                              mono_method_signature (prop->set)->params [mono_method_signature (prop->set)->param_count - 1];
7607                         minfo =  mono_property_get_object (domain, NULL, prop);
7608                         val = load_cattr_value (image, prop_type, named, &named);
7609                         obj = type_is_reference (prop_type) ? val : mono_value_box (domain, mono_class_from_mono_type (prop_type), val);
7610                         typedarg = create_cattr_typed_arg (prop_type, obj);
7611                         namedarg = create_cattr_named_arg (minfo, typedarg);
7612                         mono_array_setref (namedargs, j, namedarg);
7613                         if (!type_is_reference (prop_type))
7614                                 g_free (val);
7615                 }
7616                 g_free (name);
7617         }
7618         attr = mono_object_new (domain, mono_defaults.customattribute_data_class);
7619         params [0] = mono_method_get_object (domain, method, NULL);
7620         params [1] = typedargs;
7621         params [2] = namedargs;
7622         mono_runtime_invoke (ctor, attr, params, NULL);
7623         return attr;
7624 }
7625
7626 MonoArray*
7627 mono_custom_attrs_construct (MonoCustomAttrInfo *cinfo)
7628 {
7629         MonoArray *result;
7630         MonoObject *attr;
7631         int i;
7632
7633         result = mono_array_new (mono_domain_get (), mono_defaults.attribute_class, cinfo->num_attrs);
7634         for (i = 0; i < cinfo->num_attrs; ++i) {
7635                 if (!cinfo->attrs [i].ctor)
7636                         /* The cattr type is not finished yet */
7637                         /* We should include the type name but cinfo doesn't contain it */
7638                         mono_raise_exception (mono_get_exception_type_load (NULL, NULL));
7639                 attr = create_custom_attr (cinfo->image, cinfo->attrs [i].ctor, cinfo->attrs [i].data, cinfo->attrs [i].data_size);
7640                 mono_array_setref (result, i, attr);
7641         }
7642         return result;
7643 }
7644
7645 static MonoArray*
7646 mono_custom_attrs_construct_by_type (MonoCustomAttrInfo *cinfo, MonoClass *attr_klass)
7647 {
7648         MonoArray *result;
7649         MonoObject *attr;
7650         int i, n;
7651
7652         n = 0;
7653         for (i = 0; i < cinfo->num_attrs; ++i) {
7654                 if (mono_class_is_assignable_from (attr_klass, cinfo->attrs [i].ctor->klass))
7655                         n ++;
7656         }
7657
7658         result = mono_array_new (mono_domain_get (), mono_defaults.attribute_class, n);
7659         n = 0;
7660         for (i = 0; i < cinfo->num_attrs; ++i) {
7661                 if (mono_class_is_assignable_from (attr_klass, cinfo->attrs [i].ctor->klass)) {
7662                         attr = create_custom_attr (cinfo->image, cinfo->attrs [i].ctor, cinfo->attrs [i].data, cinfo->attrs [i].data_size);
7663                         mono_array_setref (result, n, attr);
7664                         n ++;
7665                 }
7666         }
7667         return result;
7668 }
7669
7670 static MonoArray*
7671 mono_custom_attrs_data_construct (MonoCustomAttrInfo *cinfo)
7672 {
7673         MonoArray *result;
7674         MonoObject *attr;
7675         int i;
7676         
7677         result = mono_array_new (mono_domain_get (), mono_defaults.customattribute_data_class, cinfo->num_attrs);
7678         for (i = 0; i < cinfo->num_attrs; ++i) {
7679                 attr = create_custom_attr_data (cinfo->image, cinfo->attrs [i].ctor, cinfo->attrs [i].data, cinfo->attrs [i].data_size);
7680                 mono_array_setref (result, i, attr);
7681         }
7682         return result;
7683 }
7684
7685 /**
7686  * mono_custom_attrs_from_index:
7687  *
7688  * Returns: NULL if no attributes are found or if a loading error occurs.
7689  */
7690 MonoCustomAttrInfo*
7691 mono_custom_attrs_from_index (MonoImage *image, guint32 idx)
7692 {
7693         guint32 mtoken, i, len;
7694         guint32 cols [MONO_CUSTOM_ATTR_SIZE];
7695         MonoTableInfo *ca;
7696         MonoCustomAttrInfo *ainfo;
7697         GList *tmp, *list = NULL;
7698         const char *data;
7699
7700         ca = &image->tables [MONO_TABLE_CUSTOMATTRIBUTE];
7701
7702         i = mono_metadata_custom_attrs_from_index (image, idx);
7703         if (!i)
7704                 return NULL;
7705         i --;
7706         while (i < ca->rows) {
7707                 if (mono_metadata_decode_row_col (ca, i, MONO_CUSTOM_ATTR_PARENT) != idx)
7708                         break;
7709                 list = g_list_prepend (list, GUINT_TO_POINTER (i));
7710                 ++i;
7711         }
7712         len = g_list_length (list);
7713         if (!len)
7714                 return NULL;
7715         ainfo = g_malloc0 (sizeof (MonoCustomAttrInfo) + sizeof (MonoCustomAttrEntry) * (len - MONO_ZERO_LEN_ARRAY));
7716         ainfo->num_attrs = len;
7717         ainfo->image = image;
7718         for (i = 0, tmp = list; i < len; ++i, tmp = tmp->next) {
7719                 mono_metadata_decode_row (ca, GPOINTER_TO_UINT (tmp->data), cols, MONO_CUSTOM_ATTR_SIZE);
7720                 mtoken = cols [MONO_CUSTOM_ATTR_TYPE] >> MONO_CUSTOM_ATTR_TYPE_BITS;
7721                 switch (cols [MONO_CUSTOM_ATTR_TYPE] & MONO_CUSTOM_ATTR_TYPE_MASK) {
7722                 case MONO_CUSTOM_ATTR_TYPE_METHODDEF:
7723                         mtoken |= MONO_TOKEN_METHOD_DEF;
7724                         break;
7725                 case MONO_CUSTOM_ATTR_TYPE_MEMBERREF:
7726                         mtoken |= MONO_TOKEN_MEMBER_REF;
7727                         break;
7728                 default:
7729                         g_error ("Unknown table for custom attr type %08x", cols [MONO_CUSTOM_ATTR_TYPE]);
7730                         break;
7731                 }
7732                 ainfo->attrs [i].ctor = mono_get_method (image, mtoken, NULL);
7733                 if (!ainfo->attrs [i].ctor) {
7734                         g_warning ("Can't find custom attr constructor image: %s mtoken: 0x%08x", image->name, mtoken);
7735                         g_list_free (list);
7736                         g_free (ainfo);
7737                         return NULL;
7738                 }
7739                 data = mono_metadata_blob_heap (image, cols [MONO_CUSTOM_ATTR_VALUE]);
7740                 ainfo->attrs [i].data_size = mono_metadata_decode_value (data, &data);
7741                 ainfo->attrs [i].data = (guchar*)data;
7742         }
7743         g_list_free (list);
7744
7745         return ainfo;
7746 }
7747
7748 MonoCustomAttrInfo*
7749 mono_custom_attrs_from_method (MonoMethod *method)
7750 {
7751         guint32 idx;
7752
7753         /*
7754          * An instantiated method has the same cattrs as the generic method definition.
7755          *
7756          * LAMESPEC: The .NET SRE throws an exception for instantiations of generic method builders
7757          *           Note that this stanza is not necessary for non-SRE types, but it's a micro-optimization
7758          */
7759         if (method->is_inflated)
7760                 method = ((MonoMethodInflated *) method)->declaring;
7761         
7762         if (method->dynamic || method->klass->image->dynamic)
7763                 return lookup_custom_attr (method->klass->image, method);
7764
7765         idx = mono_method_get_index (method);
7766         idx <<= MONO_CUSTOM_ATTR_BITS;
7767         idx |= MONO_CUSTOM_ATTR_METHODDEF;
7768         return mono_custom_attrs_from_index (method->klass->image, idx);
7769 }
7770
7771 MonoCustomAttrInfo*
7772 mono_custom_attrs_from_class (MonoClass *klass)
7773 {
7774         guint32 idx;
7775
7776         if (klass->generic_class)
7777                 klass = klass->generic_class->container_class;
7778
7779         if (klass->image->dynamic)
7780                 return lookup_custom_attr (klass->image, klass);
7781
7782         if (klass->byval_arg.type == MONO_TYPE_VAR || klass->byval_arg.type == MONO_TYPE_MVAR) {
7783                 idx = mono_metadata_token_index (klass->sizes.generic_param_token);
7784                 idx <<= MONO_CUSTOM_ATTR_BITS;
7785                 idx |= MONO_CUSTOM_ATTR_GENERICPAR;
7786         } else {
7787                 idx = mono_metadata_token_index (klass->type_token);
7788                 idx <<= MONO_CUSTOM_ATTR_BITS;
7789                 idx |= MONO_CUSTOM_ATTR_TYPEDEF;
7790         }
7791         return mono_custom_attrs_from_index (klass->image, idx);
7792 }
7793
7794 MonoCustomAttrInfo*
7795 mono_custom_attrs_from_assembly (MonoAssembly *assembly)
7796 {
7797         guint32 idx;
7798         
7799         if (assembly->image->dynamic)
7800                 return lookup_custom_attr (assembly->image, assembly);
7801         idx = 1; /* there is only one assembly */
7802         idx <<= MONO_CUSTOM_ATTR_BITS;
7803         idx |= MONO_CUSTOM_ATTR_ASSEMBLY;
7804         return mono_custom_attrs_from_index (assembly->image, idx);
7805 }
7806
7807 static MonoCustomAttrInfo*
7808 mono_custom_attrs_from_module (MonoImage *image)
7809 {
7810         guint32 idx;
7811         
7812         if (image->dynamic)
7813                 return lookup_custom_attr (image, image);
7814         idx = 1; /* there is only one module */
7815         idx <<= MONO_CUSTOM_ATTR_BITS;
7816         idx |= MONO_CUSTOM_ATTR_MODULE;
7817         return mono_custom_attrs_from_index (image, idx);
7818 }
7819
7820 MonoCustomAttrInfo*
7821 mono_custom_attrs_from_property (MonoClass *klass, MonoProperty *property)
7822 {
7823         guint32 idx;
7824         
7825         if (klass->image->dynamic) {
7826                 property = mono_metadata_get_corresponding_property_from_generic_type_definition (property);
7827                 return lookup_custom_attr (klass->image, property);
7828         }
7829         idx = find_property_index (klass, property);
7830         idx <<= MONO_CUSTOM_ATTR_BITS;
7831         idx |= MONO_CUSTOM_ATTR_PROPERTY;
7832         return mono_custom_attrs_from_index (klass->image, idx);
7833 }
7834
7835 MonoCustomAttrInfo*
7836 mono_custom_attrs_from_event (MonoClass *klass, MonoEvent *event)
7837 {
7838         guint32 idx;
7839         
7840         if (klass->image->dynamic) {
7841                 event = mono_metadata_get_corresponding_event_from_generic_type_definition (event);
7842                 return lookup_custom_attr (klass->image, event);
7843         }
7844         idx = find_event_index (klass, event);
7845         idx <<= MONO_CUSTOM_ATTR_BITS;
7846         idx |= MONO_CUSTOM_ATTR_EVENT;
7847         return mono_custom_attrs_from_index (klass->image, idx);
7848 }
7849
7850 MonoCustomAttrInfo*
7851 mono_custom_attrs_from_field (MonoClass *klass, MonoClassField *field)
7852 {
7853         guint32 idx;
7854         if (klass->image->dynamic) {
7855                 field = mono_metadata_get_corresponding_field_from_generic_type_definition (field);
7856                 return lookup_custom_attr (klass->image, field);
7857         }
7858         idx = find_field_index (klass, field);
7859         idx <<= MONO_CUSTOM_ATTR_BITS;
7860         idx |= MONO_CUSTOM_ATTR_FIELDDEF;
7861         return mono_custom_attrs_from_index (klass->image, idx);
7862 }
7863
7864 MonoCustomAttrInfo*
7865 mono_custom_attrs_from_param (MonoMethod *method, guint32 param)
7866 {
7867         MonoTableInfo *ca;
7868         guint32 i, idx, method_index;
7869         guint32 param_list, param_last, param_pos, found;
7870         MonoImage *image;
7871         MonoReflectionMethodAux *aux;
7872
7873         /*
7874          * An instantiated method has the same cattrs as the generic method definition.
7875          *
7876          * LAMESPEC: The .NET SRE throws an exception for instantiations of generic method builders
7877          *           Note that this stanza is not necessary for non-SRE types, but it's a micro-optimization
7878          */
7879         if (method->is_inflated)
7880                 method = ((MonoMethodInflated *) method)->declaring;
7881
7882         if (method->klass->image->dynamic) {
7883                 MonoCustomAttrInfo *res, *ainfo;
7884                 int size;
7885
7886                 aux = g_hash_table_lookup (((MonoDynamicImage*)method->klass->image)->method_aux_hash, method);
7887                 if (!aux || !aux->param_cattr)
7888                         return NULL;
7889
7890                 /* Need to copy since it will be freed later */
7891                 ainfo = aux->param_cattr [param];
7892                 size = sizeof (MonoCustomAttrInfo) + sizeof (MonoCustomAttrEntry) * (ainfo->num_attrs - MONO_ZERO_LEN_ARRAY);
7893                 res = g_malloc0 (size);
7894                 memcpy (res, ainfo, size);
7895                 return res;
7896         }
7897
7898         image = method->klass->image;
7899         method_index = mono_method_get_index (method);
7900         ca = &image->tables [MONO_TABLE_METHOD];
7901
7902         param_list = mono_metadata_decode_row_col (ca, method_index - 1, MONO_METHOD_PARAMLIST);
7903         if (method_index == ca->rows) {
7904                 ca = &image->tables [MONO_TABLE_PARAM];
7905                 param_last = ca->rows + 1;
7906         } else {
7907                 param_last = mono_metadata_decode_row_col (ca, method_index, MONO_METHOD_PARAMLIST);
7908                 ca = &image->tables [MONO_TABLE_PARAM];
7909         }
7910         found = FALSE;
7911         for (i = param_list; i < param_last; ++i) {
7912                 param_pos = mono_metadata_decode_row_col (ca, i - 1, MONO_PARAM_SEQUENCE);
7913                 if (param_pos == param) {
7914                         found = TRUE;
7915                         break;
7916                 }
7917         }
7918         if (!found)
7919                 return NULL;
7920         idx = i;
7921         idx <<= MONO_CUSTOM_ATTR_BITS;
7922         idx |= MONO_CUSTOM_ATTR_PARAMDEF;
7923         return mono_custom_attrs_from_index (image, idx);
7924 }
7925
7926 gboolean
7927 mono_custom_attrs_has_attr (MonoCustomAttrInfo *ainfo, MonoClass *attr_klass)
7928 {
7929         int i;
7930         MonoClass *klass;
7931         for (i = 0; i < ainfo->num_attrs; ++i) {
7932                 klass = ainfo->attrs [i].ctor->klass;
7933                 if (mono_class_has_parent (klass, attr_klass))
7934                         return TRUE;
7935         }
7936         return FALSE;
7937 }
7938
7939 MonoObject*
7940 mono_custom_attrs_get_attr (MonoCustomAttrInfo *ainfo, MonoClass *attr_klass)
7941 {
7942         int i, attr_index;
7943         MonoClass *klass;
7944         MonoArray *attrs;
7945
7946         attr_index = -1;
7947         for (i = 0; i < ainfo->num_attrs; ++i) {
7948                 klass = ainfo->attrs [i].ctor->klass;
7949                 if (mono_class_has_parent (klass, attr_klass)) {
7950                         attr_index = i;
7951                         break;
7952                 }
7953         }
7954         if (attr_index == -1)
7955                 return NULL;
7956
7957         attrs = mono_custom_attrs_construct (ainfo);
7958         if (attrs)
7959                 return mono_array_get (attrs, MonoObject*, attr_index);
7960         else
7961                 return NULL;
7962 }
7963
7964 /*
7965  * mono_reflection_get_custom_attrs_info:
7966  * @obj: a reflection object handle
7967  *
7968  * Return the custom attribute info for attributes defined for the
7969  * reflection handle @obj. The objects.
7970  */
7971 MonoCustomAttrInfo*
7972 mono_reflection_get_custom_attrs_info (MonoObject *obj)
7973 {
7974         MonoClass *klass;
7975         MonoCustomAttrInfo *cinfo = NULL;
7976         
7977         klass = obj->vtable->klass;
7978         if (klass == mono_defaults.monotype_class) {
7979                 MonoReflectionType *rtype = (MonoReflectionType*)obj;
7980                 klass = mono_class_from_mono_type (rtype->type);
7981                 cinfo = mono_custom_attrs_from_class (klass);
7982         } else if (strcmp ("Assembly", klass->name) == 0) {
7983                 MonoReflectionAssembly *rassembly = (MonoReflectionAssembly*)obj;
7984                 cinfo = mono_custom_attrs_from_assembly (rassembly->assembly);
7985         } else if (strcmp ("Module", klass->name) == 0) {
7986                 MonoReflectionModule *module = (MonoReflectionModule*)obj;
7987                 cinfo = mono_custom_attrs_from_module (module->image);
7988         } else if (strcmp ("MonoProperty", klass->name) == 0) {
7989                 MonoReflectionProperty *rprop = (MonoReflectionProperty*)obj;
7990                 cinfo = mono_custom_attrs_from_property (rprop->property->parent, rprop->property);
7991         } else if (strcmp ("MonoEvent", klass->name) == 0) {
7992                 MonoReflectionEvent *revent = (MonoReflectionEvent*)obj;
7993                 cinfo = mono_custom_attrs_from_event (revent->event->parent, revent->event);
7994         } else if (strcmp ("MonoField", klass->name) == 0) {
7995                 MonoReflectionField *rfield = (MonoReflectionField*)obj;
7996                 cinfo = mono_custom_attrs_from_field (rfield->field->parent, rfield->field);
7997         } else if ((strcmp ("MonoMethod", klass->name) == 0) || (strcmp ("MonoCMethod", klass->name) == 0)) {
7998                 MonoReflectionMethod *rmethod = (MonoReflectionMethod*)obj;
7999                 cinfo = mono_custom_attrs_from_method (rmethod->method);
8000         } else if ((strcmp ("MonoGenericMethod", klass->name) == 0) || (strcmp ("MonoGenericCMethod", klass->name) == 0)) {
8001                 MonoReflectionMethod *rmethod = (MonoReflectionMethod*)obj;
8002                 cinfo = mono_custom_attrs_from_method (rmethod->method);
8003         } else if (strcmp ("ParameterInfo", klass->name) == 0) {
8004                 MonoReflectionParameter *param = (MonoReflectionParameter*)obj;
8005                 MonoReflectionMethod *rmethod = (MonoReflectionMethod*)param->MemberImpl;
8006                 cinfo = mono_custom_attrs_from_param (rmethod->method, param->PositionImpl + 1);
8007         } else if (strcmp ("AssemblyBuilder", klass->name) == 0) {
8008                 MonoReflectionAssemblyBuilder *assemblyb = (MonoReflectionAssemblyBuilder*)obj;
8009                 cinfo = mono_custom_attrs_from_builders (NULL, assemblyb->assembly.assembly->image, assemblyb->cattrs);
8010         } else if (strcmp ("TypeBuilder", klass->name) == 0) {
8011                 MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder*)obj;
8012                 cinfo = mono_custom_attrs_from_builders (NULL, &tb->module->dynamic_image->image, tb->cattrs);
8013         } else if (strcmp ("ModuleBuilder", klass->name) == 0) {
8014                 MonoReflectionModuleBuilder *mb = (MonoReflectionModuleBuilder*)obj;
8015                 cinfo = mono_custom_attrs_from_builders (NULL, &mb->dynamic_image->image, mb->cattrs);
8016         } else if (strcmp ("ConstructorBuilder", klass->name) == 0) {
8017                 MonoReflectionCtorBuilder *cb = (MonoReflectionCtorBuilder*)obj;
8018                 cinfo = mono_custom_attrs_from_builders (NULL, cb->mhandle->klass->image, cb->cattrs);
8019         } else if (strcmp ("MethodBuilder", klass->name) == 0) {
8020                 MonoReflectionMethodBuilder *mb = (MonoReflectionMethodBuilder*)obj;
8021                 cinfo = mono_custom_attrs_from_builders (NULL, mb->mhandle->klass->image, mb->cattrs);
8022         } else if (strcmp ("FieldBuilder", klass->name) == 0) {
8023                 MonoReflectionFieldBuilder *fb = (MonoReflectionFieldBuilder*)obj;
8024                 cinfo = mono_custom_attrs_from_builders (NULL, &((MonoReflectionTypeBuilder*)fb->typeb)->module->dynamic_image->image, fb->cattrs);
8025         } else if (strcmp ("MonoGenericClass", klass->name) == 0) {
8026                 MonoReflectionGenericClass *gclass = (MonoReflectionGenericClass*)obj;
8027                 cinfo = mono_reflection_get_custom_attrs_info ((MonoObject*)gclass->generic_type);
8028         } else { /* handle other types here... */
8029                 g_error ("get custom attrs not yet supported for %s", klass->name);
8030         }
8031
8032         return cinfo;
8033 }
8034
8035 /*
8036  * mono_reflection_get_custom_attrs_by_type:
8037  * @obj: a reflection object handle
8038  *
8039  * Return an array with all the custom attributes defined of the
8040  * reflection handle @obj. If @attr_klass is non-NULL, only custom attributes 
8041  * of that type are returned. The objects are fully build. Return NULL if a loading error
8042  * occurs.
8043  */
8044 MonoArray*
8045 mono_reflection_get_custom_attrs_by_type (MonoObject *obj, MonoClass *attr_klass)
8046 {
8047         MonoArray *result;
8048         MonoCustomAttrInfo *cinfo;
8049
8050         cinfo = mono_reflection_get_custom_attrs_info (obj);
8051         if (cinfo) {
8052                 if (attr_klass)
8053                         result = mono_custom_attrs_construct_by_type (cinfo, attr_klass);
8054                 else
8055                         result = mono_custom_attrs_construct (cinfo);
8056                 if (!cinfo->cached)
8057                         mono_custom_attrs_free (cinfo);
8058         } else {
8059                 if (mono_loader_get_last_error ())
8060                         return NULL;
8061                 result = mono_array_new (mono_domain_get (), mono_defaults.attribute_class, 0);
8062         }
8063
8064         return result;
8065 }
8066
8067 /*
8068  * mono_reflection_get_custom_attrs:
8069  * @obj: a reflection object handle
8070  *
8071  * Return an array with all the custom attributes defined of the
8072  * reflection handle @obj. The objects are fully build. Return NULL if a loading error
8073  * occurs.
8074  */
8075 MonoArray*
8076 mono_reflection_get_custom_attrs (MonoObject *obj)
8077 {
8078         return mono_reflection_get_custom_attrs_by_type (obj, NULL);
8079 }
8080
8081 /*
8082  * mono_reflection_get_custom_attrs_data:
8083  * @obj: a reflection obj handle
8084  *
8085  * Returns an array of System.Reflection.CustomAttributeData,
8086  * which include information about attributes reflected on
8087  * types loaded using the Reflection Only methods
8088  */
8089 MonoArray*
8090 mono_reflection_get_custom_attrs_data (MonoObject *obj)
8091 {
8092         MonoArray *result;
8093         MonoCustomAttrInfo *cinfo;
8094
8095         cinfo = mono_reflection_get_custom_attrs_info (obj);
8096         if (cinfo) {
8097                 result = mono_custom_attrs_data_construct (cinfo);
8098                 if (!cinfo->cached)
8099                         mono_custom_attrs_free (cinfo);
8100         } else
8101                 result = mono_array_new (mono_domain_get (), mono_defaults.customattribute_data_class, 0);
8102
8103         return result;
8104 }
8105
8106 static MonoReflectionType*
8107 mono_reflection_type_get_underlying_system_type (MonoReflectionType* t)
8108 {
8109         MonoMethod *method_get_underlying_system_type;
8110
8111         method_get_underlying_system_type = mono_object_get_virtual_method ((MonoObject *) t,
8112                                                                             mono_class_get_method_from_name (mono_object_class (t),
8113                                                                                                              "get_UnderlyingSystemType",
8114                                                                                                              0));
8115         return (MonoReflectionType *) mono_runtime_invoke (method_get_underlying_system_type, t, NULL, NULL);
8116 }
8117
8118 static MonoType*
8119 mono_reflection_type_get_handle (MonoReflectionType* t)
8120 {
8121         if (t->type)
8122             return t->type;
8123
8124         t = mono_reflection_type_get_underlying_system_type (t);
8125         if (t)
8126             return t->type;
8127
8128         return NULL;
8129 }
8130
8131 /**
8132  * LOCKING: Assumes the loader lock is held.
8133  */
8134 static MonoMethodSignature*
8135 parameters_to_signature (MonoMemPool *mp, MonoArray *parameters) {
8136         MonoMethodSignature *sig;
8137         int count, i;
8138
8139         count = parameters? mono_array_length (parameters): 0;
8140
8141         sig = mp_g_malloc0 (mp, sizeof (MonoMethodSignature) + sizeof (MonoType*) * count);
8142         sig->param_count = count;
8143         sig->sentinelpos = -1; /* FIXME */
8144         for (i = 0; i < count; ++i) {
8145                 MonoReflectionType *pt = mono_array_get (parameters, MonoReflectionType*, i);
8146                 sig->params [i] = mono_reflection_type_get_handle (pt);
8147         }
8148         return sig;
8149 }
8150
8151 /**
8152  * LOCKING: Assumes the loader lock is held.
8153  */
8154 static MonoMethodSignature*
8155 ctor_builder_to_signature (MonoMemPool *mp, MonoReflectionCtorBuilder *ctor) {
8156         MonoMethodSignature *sig;
8157
8158         sig = parameters_to_signature (mp, ctor->parameters);
8159         sig->hasthis = ctor->attrs & METHOD_ATTRIBUTE_STATIC? 0: 1;
8160         sig->ret = &mono_defaults.void_class->byval_arg;
8161         return sig;
8162 }
8163
8164 /**
8165  * LOCKING: Assumes the loader lock is held.
8166  */
8167 static MonoMethodSignature*
8168 method_builder_to_signature (MonoMemPool *mp, MonoReflectionMethodBuilder *method) {
8169         MonoMethodSignature *sig;
8170
8171         sig = parameters_to_signature (mp, method->parameters);
8172         sig->hasthis = method->attrs & METHOD_ATTRIBUTE_STATIC? 0: 1;
8173         sig->ret = method->rtype? method->rtype->type: &mono_defaults.void_class->byval_arg;
8174         sig->generic_param_count = method->generic_params ? mono_array_length (method->generic_params) : 0;
8175         return sig;
8176 }
8177
8178 static MonoMethodSignature*
8179 dynamic_method_to_signature (MonoReflectionDynamicMethod *method) {
8180         MonoMethodSignature *sig;
8181
8182         sig = parameters_to_signature (NULL, method->parameters);
8183         sig->hasthis = method->attrs & METHOD_ATTRIBUTE_STATIC? 0: 1;
8184         sig->ret = method->rtype? method->rtype->type: &mono_defaults.void_class->byval_arg;
8185         sig->generic_param_count = 0;
8186         return sig;
8187 }
8188
8189 static void
8190 get_prop_name_and_type (MonoObject *prop, char **name, MonoType **type)
8191 {
8192         MonoClass *klass = mono_object_class (prop);
8193         if (strcmp (klass->name, "PropertyBuilder") == 0) {
8194                 MonoReflectionPropertyBuilder *pb = (MonoReflectionPropertyBuilder *)prop;
8195                 *name = mono_string_to_utf8 (pb->name);
8196                 *type = pb->type->type;
8197         } else {
8198                 MonoReflectionProperty *p = (MonoReflectionProperty *)prop;
8199                 *name = g_strdup (p->property->name);
8200                 if (p->property->get)
8201                         *type = mono_method_signature (p->property->get)->ret;
8202                 else
8203                         *type = mono_method_signature (p->property->set)->params [mono_method_signature (p->property->set)->param_count - 1];
8204         }
8205 }
8206
8207 static void
8208 get_field_name_and_type (MonoObject *field, char **name, MonoType **type)
8209 {
8210         MonoClass *klass = mono_object_class (field);
8211         if (strcmp (klass->name, "FieldBuilder") == 0) {
8212                 MonoReflectionFieldBuilder *fb = (MonoReflectionFieldBuilder *)field;
8213                 *name = mono_string_to_utf8 (fb->name);
8214                 *type = fb->type->type;
8215         } else {
8216                 MonoReflectionField *f = (MonoReflectionField *)field;
8217                 *name = g_strdup (f->field->name);
8218                 *type = f->field->type;
8219         }
8220 }
8221
8222 /*
8223  * Encode a value in a custom attribute stream of bytes.
8224  * The value to encode is either supplied as an object in argument val
8225  * (valuetypes are boxed), or as a pointer to the data in the
8226  * argument argval.
8227  * @type represents the type of the value
8228  * @buffer is the start of the buffer
8229  * @p the current position in the buffer
8230  * @buflen contains the size of the buffer and is used to return the new buffer size
8231  * if this needs to be realloced.
8232  * @retbuffer and @retp return the start and the position of the buffer
8233  */
8234 static void
8235 encode_cattr_value (MonoAssembly *assembly, char *buffer, char *p, char **retbuffer, char **retp, guint32 *buflen, MonoType *type, MonoObject *arg, char *argval)
8236 {
8237         MonoTypeEnum simple_type;
8238         
8239         if ((p-buffer) + 10 >= *buflen) {
8240                 char *newbuf;
8241                 *buflen *= 2;
8242                 newbuf = g_realloc (buffer, *buflen);
8243                 p = newbuf + (p-buffer);
8244                 buffer = newbuf;
8245         }
8246         if (!argval)
8247                 argval = ((char*)arg + sizeof (MonoObject));
8248         simple_type = type->type;
8249 handle_enum:
8250         switch (simple_type) {
8251         case MONO_TYPE_BOOLEAN:
8252         case MONO_TYPE_U1:
8253         case MONO_TYPE_I1:
8254                 *p++ = *argval;
8255                 break;
8256         case MONO_TYPE_CHAR:
8257         case MONO_TYPE_U2:
8258         case MONO_TYPE_I2:
8259                 swap_with_size (p, argval, 2, 1);
8260                 p += 2;
8261                 break;
8262         case MONO_TYPE_U4:
8263         case MONO_TYPE_I4:
8264         case MONO_TYPE_R4:
8265                 swap_with_size (p, argval, 4, 1);
8266                 p += 4;
8267                 break;
8268         case MONO_TYPE_R8:
8269 #if defined(ARM_FPU_FPA) && G_BYTE_ORDER == G_LITTLE_ENDIAN
8270                 p [0] = argval [4];
8271                 p [1] = argval [5];
8272                 p [2] = argval [6];
8273                 p [3] = argval [7];
8274                 p [4] = argval [0];
8275                 p [5] = argval [1];
8276                 p [6] = argval [2];
8277                 p [7] = argval [3];
8278 #else
8279                 swap_with_size (p, argval, 8, 1);
8280 #endif
8281                 p += 8;
8282                 break;
8283         case MONO_TYPE_U8:
8284         case MONO_TYPE_I8:
8285                 swap_with_size (p, argval, 8, 1);
8286                 p += 8;
8287                 break;
8288         case MONO_TYPE_VALUETYPE:
8289                 if (type->data.klass->enumtype) {
8290                         simple_type = type->data.klass->enum_basetype->type;
8291                         goto handle_enum;
8292                 } else {
8293                         g_warning ("generic valutype %s not handled in custom attr value decoding", type->data.klass->name);
8294                 }
8295                 break;
8296         case MONO_TYPE_STRING: {
8297                 char *str;
8298                 guint32 slen;
8299                 if (!arg) {
8300                         *p++ = 0xFF;
8301                         break;
8302                 }
8303                 str = mono_string_to_utf8 ((MonoString*)arg);
8304                 slen = strlen (str);
8305                 if ((p-buffer) + 10 + slen >= *buflen) {
8306                         char *newbuf;
8307                         *buflen *= 2;
8308                         *buflen += slen;
8309                         newbuf = g_realloc (buffer, *buflen);
8310                         p = newbuf + (p-buffer);
8311                         buffer = newbuf;
8312                 }
8313                 mono_metadata_encode_value (slen, p, &p);
8314                 memcpy (p, str, slen);
8315                 p += slen;
8316                 g_free (str);
8317                 break;
8318         }
8319         case MONO_TYPE_CLASS: {
8320                 char *str;
8321                 guint32 slen;
8322                 MonoClass *k;
8323                 if (!arg) {
8324                         *p++ = 0xFF;
8325                         break;
8326                 }
8327                 k = mono_object_class (arg);
8328                 if (!mono_object_isinst (arg, mono_defaults.monotype_class) &&
8329                         (strcmp (k->name, "TypeBuilder") || strcmp (k->name_space, "System.Reflection.Emit"))) {
8330                         MonoReflectionType* rt = mono_reflection_type_get_underlying_system_type ((MonoReflectionType*) arg);
8331                         MonoClass *rtc;
8332                         
8333                         if (rt && (rtc = mono_object_class (rt)) &&
8334                                    (mono_object_isinst ((MonoObject *) rt, mono_defaults.monotype_class) ||
8335                                     !strcmp (rtc->name, "TypeBuilder") || !strcmp (rtc->name_space, "System.Reflection.Emit"))) {
8336                                 arg = (MonoObject *) rt;
8337                                 k = rtc;
8338                         } else
8339                                 g_error ("Only System.Type allowed, not %s.%s", k->name_space, k->name);
8340                 }
8341 handle_type:
8342                 str = type_get_qualified_name (((MonoReflectionType*)arg)->type, NULL);
8343                 slen = strlen (str);
8344                 if ((p-buffer) + 10 + slen >= *buflen) {
8345                         char *newbuf;
8346                         *buflen *= 2;
8347                         *buflen += slen;
8348                         newbuf = g_realloc (buffer, *buflen);
8349                         p = newbuf + (p-buffer);
8350                         buffer = newbuf;
8351                 }
8352                 mono_metadata_encode_value (slen, p, &p);
8353                 memcpy (p, str, slen);
8354                 p += slen;
8355                 g_free (str);
8356                 break;
8357         }
8358         case MONO_TYPE_SZARRAY: {
8359                 int len, i;
8360                 MonoClass *eclass, *arg_eclass;
8361
8362                 if (!arg) {
8363                         *p++ = 0xff; *p++ = 0xff; *p++ = 0xff; *p++ = 0xff;
8364                         break;
8365                 }
8366                 len = mono_array_length ((MonoArray*)arg);
8367                 *p++ = len & 0xff;
8368                 *p++ = (len >> 8) & 0xff;
8369                 *p++ = (len >> 16) & 0xff;
8370                 *p++ = (len >> 24) & 0xff;
8371                 *retp = p;
8372                 *retbuffer = buffer;
8373                 eclass = type->data.klass;
8374                 arg_eclass = mono_object_class (arg)->element_class;
8375
8376                 if (!eclass) {
8377                         /* Happens when we are called from the MONO_TYPE_OBJECT case below */
8378                         eclass = mono_defaults.object_class;
8379                 }
8380                 if (eclass == mono_defaults.object_class && arg_eclass->valuetype) {
8381                         char *elptr = mono_array_addr ((MonoArray*)arg, char, 0);
8382                         int elsize = mono_class_array_element_size (arg_eclass);
8383                         for (i = 0; i < len; ++i) {
8384                                 encode_cattr_value (assembly, buffer, p, &buffer, &p, buflen, &arg_eclass->byval_arg, NULL, elptr);
8385                                 elptr += elsize;
8386                         }
8387                 } else if (eclass->valuetype && arg_eclass->valuetype) {
8388                         char *elptr = mono_array_addr ((MonoArray*)arg, char, 0);
8389                         int elsize = mono_class_array_element_size (eclass);
8390                         for (i = 0; i < len; ++i) {
8391                                 encode_cattr_value (assembly, buffer, p, &buffer, &p, buflen, &eclass->byval_arg, NULL, elptr);
8392                                 elptr += elsize;
8393                         }
8394                 } else {
8395                         for (i = 0; i < len; ++i) {
8396                                 encode_cattr_value (assembly, buffer, p, &buffer, &p, buflen, &eclass->byval_arg, mono_array_get ((MonoArray*)arg, MonoObject*, i), NULL);
8397                         }
8398                 }
8399                 break;
8400         }
8401         case MONO_TYPE_OBJECT: {
8402                 MonoClass *klass;
8403                 char *str;
8404                 guint32 slen;
8405
8406                 /*
8407                  * The parameter type is 'object' but the type of the actual
8408                  * argument is not. So we have to add type information to the blob
8409                  * too. This is completely undocumented in the spec.
8410                  */
8411
8412                 if (arg == NULL) {
8413                         *p++ = MONO_TYPE_STRING;        // It's same hack as MS uses
8414                         *p++ = 0xFF;
8415                         break;
8416                 }
8417                 
8418                 klass = mono_object_class (arg);
8419
8420                 if (mono_object_isinst (arg, mono_defaults.systemtype_class)) {
8421                         *p++ = 0x50;
8422                         goto handle_type;
8423                 } else if (klass->enumtype) {
8424                         *p++ = 0x55;
8425                 } else if (klass == mono_defaults.string_class) {
8426                         simple_type = MONO_TYPE_STRING;
8427                         *p++ = 0x0E;
8428                         goto handle_enum;
8429                 } else if (klass->rank == 1) {
8430                         *p++ = 0x1D;
8431                         if (klass->element_class->byval_arg.type == MONO_TYPE_OBJECT)
8432                                 /* See Partition II, Appendix B3 */
8433                                 *p++ = 0x51;
8434                         else
8435                                 *p++ = klass->element_class->byval_arg.type;
8436                         encode_cattr_value (assembly, buffer, p, &buffer, &p, buflen, &klass->byval_arg, arg, NULL);
8437                         break;
8438                 } else if (klass->byval_arg.type >= MONO_TYPE_BOOLEAN && klass->byval_arg.type <= MONO_TYPE_R8) {
8439                         *p++ = simple_type = klass->byval_arg.type;
8440                         goto handle_enum;
8441                 } else {
8442                         g_error ("unhandled type in custom attr");
8443                 }
8444                 str = type_get_qualified_name (mono_class_get_type(klass), NULL);
8445                 slen = strlen (str);
8446                 if ((p-buffer) + 10 + slen >= *buflen) {
8447                         char *newbuf;
8448                         *buflen *= 2;
8449                         *buflen += slen;
8450                         newbuf = g_realloc (buffer, *buflen);
8451                         p = newbuf + (p-buffer);
8452                         buffer = newbuf;
8453                 }
8454                 mono_metadata_encode_value (slen, p, &p);
8455                 memcpy (p, str, slen);
8456                 p += slen;
8457                 g_free (str);
8458                 simple_type = klass->enum_basetype->type;
8459                 goto handle_enum;
8460         }
8461         default:
8462                 g_error ("type 0x%02x not yet supported in custom attr encoder", simple_type);
8463         }
8464         *retp = p;
8465         *retbuffer = buffer;
8466 }
8467
8468 static void
8469 encode_field_or_prop_type (MonoType *type, char *p, char **retp)
8470 {
8471         if (type->type == MONO_TYPE_VALUETYPE && type->data.klass->enumtype) {
8472                 char *str = type_get_qualified_name (type, NULL);
8473                 int slen = strlen (str);
8474
8475                 *p++ = 0x55;
8476                 /*
8477                  * This seems to be optional...
8478                  * *p++ = 0x80;
8479                  */
8480                 mono_metadata_encode_value (slen, p, &p);
8481                 memcpy (p, str, slen);
8482                 p += slen;
8483                 g_free (str);
8484         } else if (type->type == MONO_TYPE_OBJECT) {
8485                 *p++ = 0x51;
8486         } else if (type->type == MONO_TYPE_CLASS) {
8487                 /* it should be a type: encode_cattr_value () has the check */
8488                 *p++ = 0x50;
8489         } else {
8490                 mono_metadata_encode_value (type->type, p, &p);
8491                 if (type->type == MONO_TYPE_SZARRAY)
8492                         /* See the examples in Partition VI, Annex B */
8493                         encode_field_or_prop_type (&type->data.klass->byval_arg, p, &p);
8494         }
8495
8496         *retp = p;
8497 }
8498
8499 static void
8500 encode_named_val (MonoReflectionAssembly *assembly, char *buffer, char *p, char **retbuffer, char **retp, guint32 *buflen, MonoType *type, char *name, MonoObject *value)
8501 {
8502         int len;
8503         /* Preallocate a large enough buffer */
8504         if (type->type == MONO_TYPE_VALUETYPE && type->data.klass->enumtype) {
8505                 char *str = type_get_qualified_name (type, NULL);
8506                 len = strlen (str);
8507                 g_free (str);
8508         } else if (type->type == MONO_TYPE_SZARRAY && type->data.klass->enumtype) {
8509                 char *str = type_get_qualified_name (&type->data.klass->byval_arg, NULL);
8510                 len = strlen (str);
8511                 g_free (str);
8512         } else {
8513                 len = 0;
8514         }
8515         len += strlen (name);
8516
8517         if ((p-buffer) + 20 + len >= *buflen) {
8518                 char *newbuf;
8519                 *buflen *= 2;
8520                 *buflen += len;
8521                 newbuf = g_realloc (buffer, *buflen);
8522                 p = newbuf + (p-buffer);
8523                 buffer = newbuf;
8524         }
8525
8526         encode_field_or_prop_type (type, p, &p);
8527
8528         len = strlen (name);
8529         mono_metadata_encode_value (len, p, &p);
8530         memcpy (p, name, len);
8531         p += len;
8532         encode_cattr_value (assembly->assembly, buffer, p, &buffer, &p, buflen, type, value, NULL);
8533         *retp = p;
8534         *retbuffer = buffer;
8535 }
8536
8537 /*
8538  * mono_reflection_get_custom_attrs_blob:
8539  * @ctor: custom attribute constructor
8540  * @ctorArgs: arguments o the constructor
8541  * @properties:
8542  * @propValues:
8543  * @fields:
8544  * @fieldValues:
8545  * 
8546  * Creates the blob of data that needs to be saved in the metadata and that represents
8547  * the custom attributed described by @ctor, @ctorArgs etc.
8548  * Returns: a Byte array representing the blob of data.
8549  */
8550 MonoArray*
8551 mono_reflection_get_custom_attrs_blob (MonoReflectionAssembly *assembly, MonoObject *ctor, MonoArray *ctorArgs, MonoArray *properties, MonoArray *propValues, MonoArray *fields, MonoArray* fieldValues) 
8552 {
8553         MonoArray *result;
8554         MonoMethodSignature *sig;
8555         MonoObject *arg;
8556         char *buffer, *p;
8557         guint32 buflen, i;
8558
8559         MONO_ARCH_SAVE_REGS;
8560
8561         if (strcmp (ctor->vtable->klass->name, "MonoCMethod")) {
8562                 /* sig is freed later so allocate it in the heap */
8563                 sig = ctor_builder_to_signature (NULL, (MonoReflectionCtorBuilder*)ctor);
8564         } else {
8565                 sig = mono_method_signature (((MonoReflectionMethod*)ctor)->method);
8566         }
8567
8568         g_assert (mono_array_length (ctorArgs) == sig->param_count);
8569         buflen = 256;
8570         p = buffer = g_malloc (buflen);
8571         /* write the prolog */
8572         *p++ = 1;
8573         *p++ = 0;
8574         for (i = 0; i < sig->param_count; ++i) {
8575                 arg = mono_array_get (ctorArgs, MonoObject*, i);
8576                 encode_cattr_value (assembly->assembly, buffer, p, &buffer, &p, &buflen, sig->params [i], arg, NULL);
8577         }
8578         i = 0;
8579         if (properties)
8580                 i += mono_array_length (properties);
8581         if (fields)
8582                 i += mono_array_length (fields);
8583         *p++ = i & 0xff;
8584         *p++ = (i >> 8) & 0xff;
8585         if (properties) {
8586                 MonoObject *prop;
8587                 for (i = 0; i < mono_array_length (properties); ++i) {
8588                         MonoType *ptype;
8589                         char *pname;
8590
8591                         prop = mono_array_get (properties, gpointer, i);
8592                         get_prop_name_and_type (prop, &pname, &ptype);
8593                         *p++ = 0x54; /* PROPERTY signature */
8594                         encode_named_val (assembly, buffer, p, &buffer, &p, &buflen, ptype, pname, (MonoObject*)mono_array_get (propValues, gpointer, i));
8595                         g_free (pname);
8596                 }
8597         }
8598
8599         if (fields) {
8600                 MonoObject *field;
8601                 for (i = 0; i < mono_array_length (fields); ++i) {
8602                         MonoType *ftype;
8603                         char *fname;
8604
8605                         field = mono_array_get (fields, gpointer, i);
8606                         get_field_name_and_type (field, &fname, &ftype);
8607                         *p++ = 0x53; /* FIELD signature */
8608                         encode_named_val (assembly, buffer, p, &buffer, &p, &buflen, ftype, fname, (MonoObject*)mono_array_get (fieldValues, gpointer, i));
8609                         g_free (fname);
8610                 }
8611         }
8612
8613         g_assert (p - buffer <= buflen);
8614         buflen = p - buffer;
8615         result = mono_array_new (mono_domain_get (), mono_defaults.byte_class, buflen);
8616         p = mono_array_addr (result, char, 0);
8617         memcpy (p, buffer, buflen);
8618         g_free (buffer);
8619         if (strcmp (ctor->vtable->klass->name, "MonoCMethod"))
8620                 g_free (sig);
8621         return result;
8622 }
8623
8624 #if HAVE_SGEN_GC
8625 static void* reflection_info_desc = NULL;
8626 #define MOVING_GC_REGISTER(addr) do {   \
8627                 if (!reflection_info_desc) {    \
8628                         gsize bmap = 1;         \
8629                         reflection_info_desc = mono_gc_make_descr_from_bitmap (&bmap, 1);       \
8630                 }       \
8631                 mono_gc_register_root ((addr), sizeof (gpointer), reflection_info_desc);        \
8632         } while (0)
8633 #else
8634 #define MOVING_GC_REGISTER(addr)
8635 #endif
8636
8637 /*
8638  * mono_reflection_setup_internal_class:
8639  * @tb: a TypeBuilder object
8640  *
8641  * Creates a MonoClass that represents the TypeBuilder.
8642  * This is a trick that lets us simplify a lot of reflection code
8643  * (and will allow us to support Build and Run assemblies easier).
8644  */
8645 void
8646 mono_reflection_setup_internal_class (MonoReflectionTypeBuilder *tb)
8647 {
8648         MonoClass *klass, *parent;
8649
8650         MONO_ARCH_SAVE_REGS;
8651
8652         mono_loader_lock ();
8653
8654         if (tb->parent) {
8655                 /* check so we can compile corlib correctly */
8656                 if (strcmp (mono_object_class (tb->parent)->name, "TypeBuilder") == 0) {
8657                         /* mono_class_setup_mono_type () guaranteess type->data.klass is valid */
8658                         parent = tb->parent->type->data.klass;
8659                 } else {
8660                         parent = my_mono_class_from_mono_type (tb->parent->type);
8661                 }
8662         } else {
8663                 parent = NULL;
8664         }
8665         
8666         /* the type has already being created: it means we just have to change the parent */
8667         if (tb->type.type) {
8668                 klass = mono_class_from_mono_type (tb->type.type);
8669                 klass->parent = NULL;
8670                 /* fool mono_class_setup_parent */
8671                 klass->supertypes = NULL;
8672                 mono_class_setup_parent (klass, parent);
8673                 mono_class_setup_mono_type (klass);
8674                 mono_loader_unlock ();
8675                 return;
8676         }
8677
8678         klass = mono_mempool_alloc0 (tb->module->dynamic_image->image.mempool, sizeof (MonoClass));
8679
8680         klass->image = &tb->module->dynamic_image->image;
8681
8682         klass->inited = 1; /* we lie to the runtime */
8683         klass->name = mono_string_to_utf8_mp (klass->image->mempool, tb->name);
8684         klass->name_space = mono_string_to_utf8_mp (klass->image->mempool, tb->nspace);
8685         klass->type_token = MONO_TOKEN_TYPE_DEF | tb->table_idx;
8686         klass->flags = tb->attrs;
8687         
8688         mono_profiler_class_event (klass, MONO_PROFILE_START_LOAD);
8689
8690         klass->element_class = klass;
8691
8692         MOVING_GC_REGISTER (&klass->reflection_info);
8693         klass->reflection_info = tb;
8694
8695         /* Put into cache so mono_class_get () will find it */
8696         mono_image_add_to_name_cache (klass->image, klass->name_space, klass->name, tb->table_idx);
8697
8698         mono_g_hash_table_insert (tb->module->dynamic_image->tokens,
8699                 GUINT_TO_POINTER (MONO_TOKEN_TYPE_DEF | tb->table_idx), tb);
8700
8701         if (parent != NULL) {
8702                 mono_class_setup_parent (klass, parent);
8703         } else if (strcmp (klass->name, "Object") == 0 && strcmp (klass->name_space, "System") == 0) {
8704                 const char *old_n = klass->name;
8705                 /* trick to get relative numbering right when compiling corlib */
8706                 klass->name = "BuildingObject";
8707                 mono_class_setup_parent (klass, mono_defaults.object_class);
8708                 klass->name = old_n;
8709         }
8710
8711         if ((!strcmp (klass->name, "ValueType") && !strcmp (klass->name_space, "System")) ||
8712                         (!strcmp (klass->name, "Object") && !strcmp (klass->name_space, "System")) ||
8713                         (!strcmp (klass->name, "Enum") && !strcmp (klass->name_space, "System"))) {
8714                 klass->instance_size = sizeof (MonoObject);
8715                 klass->size_inited = 1;
8716                 mono_class_setup_vtable_general (klass, NULL, 0);
8717         }
8718
8719         mono_class_setup_mono_type (klass);
8720
8721         mono_class_setup_supertypes (klass);
8722
8723         /*
8724          * FIXME: handle interfaces.
8725          */
8726
8727         tb->type.type = &klass->byval_arg;
8728
8729         if (tb->nesting_type) {
8730                 g_assert (tb->nesting_type->type);
8731                 klass->nested_in = mono_class_from_mono_type (tb->nesting_type->type);
8732         }
8733
8734         /*g_print ("setup %s as %s (%p)\n", klass->name, ((MonoObject*)tb)->vtable->klass->name, tb);*/
8735
8736         mono_profiler_class_loaded (klass, MONO_PROFILE_OK);
8737         
8738         mono_loader_unlock ();
8739 }
8740
8741 /*
8742  * mono_reflection_setup_generic_class:
8743  * @tb: a TypeBuilder object
8744  *
8745  * Setup the generic class before adding the first generic parameter.
8746  */
8747 void
8748 mono_reflection_setup_generic_class (MonoReflectionTypeBuilder *tb)
8749 {
8750         MonoClass *klass;
8751
8752         MONO_ARCH_SAVE_REGS;
8753
8754         klass = my_mono_class_from_mono_type (tb->type.type);
8755         if (tb->generic_container)
8756                 return;
8757
8758         tb->generic_container = mono_mempool_alloc0 (klass->image->mempool, sizeof (MonoGenericContainer));
8759         tb->generic_container->owner.klass = klass;
8760 }
8761
8762 /*
8763  * mono_reflection_create_generic_class:
8764  * @tb: a TypeBuilder object
8765  *
8766  * Creates the generic class after all generic parameters have been added.
8767  */
8768 void
8769 mono_reflection_create_generic_class (MonoReflectionTypeBuilder *tb)
8770 {
8771         MonoClass *klass;
8772         int count, i;
8773
8774         MONO_ARCH_SAVE_REGS;
8775
8776         klass = my_mono_class_from_mono_type (tb->type.type);
8777
8778         count = tb->generic_params ? mono_array_length (tb->generic_params) : 0;
8779
8780         if (klass->generic_container || (count == 0))
8781                 return;
8782
8783         g_assert (tb->generic_container && (tb->generic_container->owner.klass == klass));
8784
8785         klass->generic_container = mono_mempool_alloc0 (klass->image->mempool, sizeof (MonoGenericContainer));
8786
8787         klass->generic_container->owner.klass = klass;
8788         klass->generic_container->type_argc = count;
8789         klass->generic_container->type_params = mono_mempool_alloc0 (klass->image->mempool, sizeof (MonoGenericParam) * count);
8790
8791         for (i = 0; i < count; i++) {
8792                 MonoReflectionGenericParam *gparam = mono_array_get (tb->generic_params, gpointer, i);
8793                 klass->generic_container->type_params [i] = *gparam->type.type->data.generic_param;
8794                 /*Make sure we are a diferent type instance */
8795                 klass->generic_container->type_params [i].owner = klass->generic_container;
8796                 klass->generic_container->type_params [i].pklass = NULL;
8797
8798                 g_assert (klass->generic_container->type_params [i].owner);
8799         }
8800
8801         klass->generic_container->context.class_inst = mono_get_shared_generic_inst (klass->generic_container);
8802 }
8803
8804 /*
8805  * mono_reflection_create_internal_class:
8806  * @tb: a TypeBuilder object
8807  *
8808  * Actually create the MonoClass that is associated with the TypeBuilder.
8809  */
8810 void
8811 mono_reflection_create_internal_class (MonoReflectionTypeBuilder *tb)
8812 {
8813         MonoClass *klass;
8814
8815         MONO_ARCH_SAVE_REGS;
8816
8817         klass = my_mono_class_from_mono_type (tb->type.type);
8818
8819         mono_loader_lock ();
8820         if (klass->enumtype && klass->enum_basetype == NULL) {
8821                 MonoReflectionFieldBuilder *fb;
8822                 MonoClass *ec;
8823
8824                 g_assert (tb->fields != NULL);
8825                 g_assert (mono_array_length (tb->fields) >= 1);
8826
8827                 fb = mono_array_get (tb->fields, MonoReflectionFieldBuilder*, 0);
8828
8829                 if (!mono_type_is_valid_enum_basetype (fb->type->type)) {
8830                         mono_loader_unlock ();
8831                         return;
8832                 }
8833
8834                 klass->enum_basetype = fb->type->type;
8835                 klass->element_class = my_mono_class_from_mono_type (klass->enum_basetype);
8836                 if (!klass->element_class)
8837                         klass->element_class = mono_class_from_mono_type (klass->enum_basetype);
8838
8839                 /*
8840                  * get the element_class from the current corlib.
8841                  */
8842                 ec = default_class_from_mono_type (klass->enum_basetype);
8843                 klass->instance_size = ec->instance_size;
8844                 klass->size_inited = 1;
8845                 /* 
8846                  * this is almost safe to do with enums and it's needed to be able
8847                  * to create objects of the enum type (for use in SetConstant).
8848                  */
8849                 /* FIXME: Does this mean enums can't have method overrides ? */
8850                 mono_class_setup_vtable_general (klass, NULL, 0);
8851         }
8852         mono_loader_unlock ();
8853 }
8854
8855 static MonoMarshalSpec*
8856 mono_marshal_spec_from_builder (MonoMemPool *mp, MonoAssembly *assembly,
8857                                                                 MonoReflectionMarshal *minfo)
8858 {
8859         MonoMarshalSpec *res;
8860
8861         res = mp_g_new0 (mp, MonoMarshalSpec, 1);
8862         res->native = minfo->type;
8863
8864         switch (minfo->type) {
8865         case MONO_NATIVE_LPARRAY:
8866                 res->data.array_data.elem_type = minfo->eltype;
8867                 if (minfo->has_size) {
8868                         res->data.array_data.param_num = minfo->param_num;
8869                         res->data.array_data.num_elem = minfo->count;
8870                         res->data.array_data.elem_mult = minfo->param_num == -1 ? 0 : 1;
8871                 }
8872                 else {
8873                         res->data.array_data.param_num = -1;
8874                         res->data.array_data.num_elem = -1;
8875                         res->data.array_data.elem_mult = -1;
8876                 }
8877                 break;
8878
8879         case MONO_NATIVE_BYVALTSTR:
8880         case MONO_NATIVE_BYVALARRAY:
8881                 res->data.array_data.num_elem = minfo->count;
8882                 break;
8883
8884         case MONO_NATIVE_CUSTOM:
8885                 if (minfo->marshaltyperef)
8886                         res->data.custom_data.custom_name =
8887                                 type_get_fully_qualified_name (minfo->marshaltyperef->type);
8888                 if (minfo->mcookie)
8889                         res->data.custom_data.cookie = mono_string_to_utf8 (minfo->mcookie);
8890                 break;
8891
8892         default:
8893                 break;
8894         }
8895
8896         return res;
8897 }
8898
8899 MonoReflectionMarshal*
8900 mono_reflection_marshal_from_marshal_spec (MonoDomain *domain, MonoClass *klass,
8901                                                                                    MonoMarshalSpec *spec)
8902 {
8903         static MonoClass *System_Reflection_Emit_UnmanagedMarshalClass;
8904         MonoReflectionMarshal *minfo;
8905         MonoType *mtype;
8906
8907         if (!System_Reflection_Emit_UnmanagedMarshalClass) {
8908                 System_Reflection_Emit_UnmanagedMarshalClass = mono_class_from_name (
8909                    mono_defaults.corlib, "System.Reflection.Emit", "UnmanagedMarshal");
8910                 g_assert (System_Reflection_Emit_UnmanagedMarshalClass);
8911         }
8912
8913         minfo = (MonoReflectionMarshal*)mono_object_new (domain, System_Reflection_Emit_UnmanagedMarshalClass);
8914         minfo->type = spec->native;
8915
8916         switch (minfo->type) {
8917         case MONO_NATIVE_LPARRAY:
8918                 minfo->eltype = spec->data.array_data.elem_type;
8919                 minfo->count = spec->data.array_data.num_elem;
8920                 minfo->param_num = spec->data.array_data.param_num;
8921                 break;
8922
8923         case MONO_NATIVE_BYVALTSTR:
8924         case MONO_NATIVE_BYVALARRAY:
8925                 minfo->count = spec->data.array_data.num_elem;
8926                 break;
8927
8928         case MONO_NATIVE_CUSTOM:
8929                 if (spec->data.custom_data.custom_name) {
8930                         mtype = mono_reflection_type_from_name (spec->data.custom_data.custom_name, klass->image);
8931                         if (mtype)
8932                                 MONO_OBJECT_SETREF (minfo, marshaltyperef, mono_type_get_object (domain, mtype));
8933
8934                         MONO_OBJECT_SETREF (minfo, marshaltype, mono_string_new (domain, spec->data.custom_data.custom_name));
8935                 }
8936                 if (spec->data.custom_data.cookie)
8937                         MONO_OBJECT_SETREF (minfo, mcookie, mono_string_new (domain, spec->data.custom_data.cookie));
8938                 break;
8939
8940         default:
8941                 break;
8942         }
8943
8944         return minfo;
8945 }
8946
8947 static MonoMethod*
8948 reflection_methodbuilder_to_mono_method (MonoClass *klass,
8949                                          ReflectionMethodBuilder *rmb,
8950                                          MonoMethodSignature *sig)
8951 {
8952         MonoMethod *m;
8953         MonoMethodNormal *pm;
8954         MonoMarshalSpec **specs;
8955         MonoReflectionMethodAux *method_aux;
8956         MonoMemPool *mp;
8957         gboolean dynamic;
8958         int i;
8959
8960         /*
8961          * Methods created using a MethodBuilder should have their memory allocated
8962          * inside the image mempool, while dynamic methods should have their memory
8963          * malloc'd.
8964          */
8965         dynamic = rmb->refs != NULL;
8966         mp = dynamic ? NULL : klass->image->mempool;
8967
8968         if (!dynamic)
8969                 g_assert (!klass->generic_class);
8970
8971         mono_loader_lock ();
8972
8973         if ((rmb->attrs & METHOD_ATTRIBUTE_PINVOKE_IMPL) ||
8974                         (rmb->iattrs & METHOD_IMPL_ATTRIBUTE_INTERNAL_CALL))
8975                 m = (MonoMethod *)mp_g_new0 (mp, MonoMethodPInvoke, 1);
8976         else if (rmb->refs)
8977                 m = (MonoMethod *)mp_g_new0 (mp, MonoMethodWrapper, 1);
8978         else
8979                 m = (MonoMethod *)mp_g_new0 (mp, MonoMethodNormal, 1);
8980
8981         pm = (MonoMethodNormal*)m;
8982
8983         m->dynamic = dynamic;
8984         m->slot = -1;
8985         m->flags = rmb->attrs;
8986         m->iflags = rmb->iattrs;
8987         m->name = mp_string_to_utf8 (mp, rmb->name);
8988         m->klass = klass;
8989         m->signature = sig;
8990         m->skip_visibility = rmb->skip_visibility;
8991         if (rmb->table_idx)
8992                 m->token = MONO_TOKEN_METHOD_DEF | (*rmb->table_idx);
8993
8994         if (m->iflags & METHOD_IMPL_ATTRIBUTE_INTERNAL_CALL) {
8995                 if (klass == mono_defaults.string_class && !strcmp (m->name, ".ctor"))
8996                         m->string_ctor = 1;
8997
8998                 m->signature->pinvoke = 1;
8999         } else if (m->flags & METHOD_ATTRIBUTE_PINVOKE_IMPL) {
9000                 m->signature->pinvoke = 1;
9001
9002                 method_aux = mp_g_new0 (mp, MonoReflectionMethodAux, 1);
9003
9004                 method_aux->dllentry = rmb->dllentry ? mono_string_to_utf8_mp (mp, rmb->dllentry) : mono_mempool_strdup (mp, m->name);
9005                 method_aux->dll = mono_string_to_utf8_mp (mp, rmb->dll);
9006                 
9007                 ((MonoMethodPInvoke*)m)->piflags = (rmb->native_cc << 8) | (rmb->charset ? (rmb->charset - 1) * 2 : 0) | rmb->extra_flags;
9008
9009                 if (klass->image->dynamic)
9010                         g_hash_table_insert (((MonoDynamicImage*)klass->image)->method_aux_hash, m, method_aux);
9011
9012                 mono_loader_unlock ();
9013
9014                 return m;
9015         } else if (!(m->flags & METHOD_ATTRIBUTE_ABSTRACT) &&
9016                            !(m->iflags & METHOD_IMPL_ATTRIBUTE_RUNTIME)) {
9017                 MonoMethodHeader *header;
9018                 guint32 code_size;
9019                 gint32 max_stack, i;
9020                 gint32 num_locals = 0;
9021                 gint32 num_clauses = 0;
9022                 guint8 *code;
9023
9024                 if (rmb->ilgen) {
9025                         code = mono_array_addr (rmb->ilgen->code, guint8, 0);
9026                         code_size = rmb->ilgen->code_len;
9027                         max_stack = rmb->ilgen->max_stack;
9028                         num_locals = rmb->ilgen->locals ? mono_array_length (rmb->ilgen->locals) : 0;
9029                         if (rmb->ilgen->ex_handlers)
9030                                 num_clauses = method_count_clauses (rmb->ilgen);
9031                 } else {
9032                         if (rmb->code) {
9033                                 code = mono_array_addr (rmb->code, guint8, 0);
9034                                 code_size = mono_array_length (rmb->code);
9035                                 /* we probably need to run a verifier on the code... */
9036                                 max_stack = 8; 
9037                         }
9038                         else {
9039                                 code = NULL;
9040                                 code_size = 0;
9041                                 max_stack = 8;
9042                         }
9043                 }
9044
9045                 header = mp_g_malloc0 (mp, sizeof (MonoMethodHeader) + 
9046                         (num_locals - MONO_ZERO_LEN_ARRAY) * sizeof (MonoType*));
9047                 header->code_size = code_size;
9048                 header->code = mp_g_malloc (mp, code_size);
9049                 memcpy ((char*)header->code, code, code_size);
9050                 header->max_stack = max_stack;
9051                 header->init_locals = rmb->init_locals;
9052                 header->num_locals = num_locals;
9053
9054                 for (i = 0; i < num_locals; ++i) {
9055                         MonoReflectionLocalBuilder *lb = 
9056                                 mono_array_get (rmb->ilgen->locals, MonoReflectionLocalBuilder*, i);
9057
9058                         header->locals [i] = mp_g_new0 (mp, MonoType, 1);
9059                         memcpy (header->locals [i], lb->type->type, sizeof (MonoType));
9060                 }
9061
9062                 header->num_clauses = num_clauses;
9063                 if (num_clauses) {
9064                         header->clauses = method_encode_clauses (mp, (MonoDynamicImage*)klass->image,
9065                                  rmb->ilgen, num_clauses);
9066                 }
9067
9068                 pm->header = header;
9069         }
9070
9071         if (rmb->generic_params) {
9072                 int count = mono_array_length (rmb->generic_params);
9073                 MonoGenericContainer *container;
9074
9075                 container = rmb->generic_container;
9076                 if (container) {
9077                         m->is_generic = TRUE;
9078                         mono_method_set_generic_container (m, container);
9079                 }
9080                 container->type_argc = count;
9081                 container->type_params = mp_g_new0 (mp, MonoGenericParam, count);
9082                 container->owner.method = m;
9083
9084                 for (i = 0; i < count; i++) {
9085                         MonoReflectionGenericParam *gp =
9086                                 mono_array_get (rmb->generic_params, MonoReflectionGenericParam*, i);
9087
9088                         container->type_params [i] = *gp->type.type->data.generic_param;
9089                 }
9090
9091                 if (klass->generic_container) {
9092                         container->parent = klass->generic_container;
9093                         container->context.class_inst = klass->generic_container->context.class_inst;
9094                 }
9095                 container->context.method_inst = mono_get_shared_generic_inst (container);
9096         }
9097
9098         if (rmb->refs) {
9099                 MonoMethodWrapper *mw = (MonoMethodWrapper*)m;
9100                 int i;
9101                 void **data;
9102
9103                 m->wrapper_type = MONO_WRAPPER_DYNAMIC_METHOD;
9104
9105                 mw->method_data = data = mp_g_new (mp, gpointer, rmb->nrefs + 1);
9106                 data [0] = GUINT_TO_POINTER (rmb->nrefs);
9107                 for (i = 0; i < rmb->nrefs; ++i)
9108                         data [i + 1] = rmb->refs [i];
9109         }
9110
9111         method_aux = NULL;
9112
9113         /* Parameter info */
9114         if (rmb->pinfo) {
9115                 if (!method_aux)
9116                         method_aux = mp_g_new0 (mp, MonoReflectionMethodAux, 1);
9117                 method_aux->param_names = mp_g_new0 (mp, char *, mono_method_signature (m)->param_count + 1);
9118                 for (i = 0; i <= m->signature->param_count; ++i) {
9119                         MonoReflectionParamBuilder *pb;
9120                         if ((pb = mono_array_get (rmb->pinfo, MonoReflectionParamBuilder*, i))) {
9121                                 if ((i > 0) && (pb->attrs)) {
9122                                         /* Make a copy since it might point to a shared type structure */
9123                                         m->signature->params [i - 1] = mono_metadata_type_dup (mp, m->signature->params [i - 1]);
9124                                         m->signature->params [i - 1]->attrs = pb->attrs;
9125                                 }
9126
9127                                 if (pb->attrs & PARAM_ATTRIBUTE_HAS_DEFAULT) {
9128                                         MonoDynamicImage *assembly;
9129                                         guint32 idx, def_type, len;
9130                                         char *p;
9131                                         const char *p2;
9132
9133                                         if (!method_aux->param_defaults) {
9134                                                 method_aux->param_defaults = mp_g_new0 (mp, guint8*, m->signature->param_count + 1);
9135                                                 method_aux->param_default_types = mp_g_new0 (mp, guint32, m->signature->param_count + 1);
9136                                         }
9137                                         assembly = (MonoDynamicImage*)klass->image;
9138                                         idx = encode_constant (assembly, pb->def_value, &def_type);
9139                                         /* Copy the data from the blob since it might get realloc-ed */
9140                                         p = assembly->blob.data + idx;
9141                                         len = mono_metadata_decode_blob_size (p, &p2);
9142                                         len += p2 - p;
9143                                         method_aux->param_defaults [i] = mp_g_malloc (mp, len);
9144                                         method_aux->param_default_types [i] = def_type;
9145                                         memcpy ((gpointer)method_aux->param_defaults [i], p, len);
9146                                 }
9147
9148                                 if (pb->name)
9149                                         method_aux->param_names [i] = mp_string_to_utf8 (mp, pb->name);
9150                                 if (pb->cattrs) {
9151                                         if (!method_aux->param_cattr)
9152                                                 method_aux->param_cattr = mp_g_new0 (mp, MonoCustomAttrInfo*, m->signature->param_count + 1);
9153                                         method_aux->param_cattr [i] = mono_custom_attrs_from_builders (mp, klass->image, pb->cattrs);
9154                                 }
9155                         }
9156                 }
9157         }
9158
9159         /* Parameter marshalling */
9160         specs = NULL;
9161         if (rmb->pinfo)         
9162                 for (i = 0; i < mono_array_length (rmb->pinfo); ++i) {
9163                         MonoReflectionParamBuilder *pb;
9164                         if ((pb = mono_array_get (rmb->pinfo, MonoReflectionParamBuilder*, i))) {
9165                                 if (pb->marshal_info) {
9166                                         if (specs == NULL)
9167                                                 specs = mp_g_new0 (mp, MonoMarshalSpec*, sig->param_count + 1);
9168                                         specs [pb->position] = 
9169                                                 mono_marshal_spec_from_builder (mp, klass->image->assembly, pb->marshal_info);
9170                                 }
9171                         }
9172                 }
9173         if (specs != NULL) {
9174                 if (!method_aux)
9175                         method_aux = mp_g_new0 (mp, MonoReflectionMethodAux, 1);
9176                 method_aux->param_marshall = specs;
9177         }
9178
9179         if (klass->image->dynamic && method_aux)
9180                 g_hash_table_insert (((MonoDynamicImage*)klass->image)->method_aux_hash, m, method_aux);
9181
9182         mono_loader_unlock ();
9183
9184         return m;
9185 }       
9186
9187 static MonoMethod*
9188 ctorbuilder_to_mono_method (MonoClass *klass, MonoReflectionCtorBuilder* mb)
9189 {
9190         ReflectionMethodBuilder rmb;
9191         MonoMethodSignature *sig;
9192
9193         mono_loader_lock ();
9194         sig = ctor_builder_to_signature (klass->image->mempool, mb);
9195         mono_loader_unlock ();
9196
9197         reflection_methodbuilder_from_ctor_builder (&rmb, mb);
9198
9199         mb->mhandle = reflection_methodbuilder_to_mono_method (klass, &rmb, sig);
9200         mono_save_custom_attrs (klass->image, mb->mhandle, mb->cattrs);
9201
9202         /* If we are in a generic class, we might be called multiple times from inflate_method */
9203         if (!((MonoDynamicImage*)(MonoDynamicImage*)klass->image)->save && !klass->generic_container) {
9204                 /* ilgen is no longer needed */
9205                 mb->ilgen = NULL;
9206         }
9207
9208         return mb->mhandle;
9209 }
9210
9211 static MonoMethod*
9212 methodbuilder_to_mono_method (MonoClass *klass, MonoReflectionMethodBuilder* mb)
9213 {
9214         ReflectionMethodBuilder rmb;
9215         MonoMethodSignature *sig;
9216
9217         mono_loader_lock ();
9218         sig = method_builder_to_signature (klass->image->mempool, mb);
9219         mono_loader_unlock ();
9220
9221         reflection_methodbuilder_from_method_builder (&rmb, mb);
9222
9223         mb->mhandle = reflection_methodbuilder_to_mono_method (klass, &rmb, sig);
9224         mono_save_custom_attrs (klass->image, mb->mhandle, mb->cattrs);
9225
9226         /* If we are in a generic class, we might be called multiple times from inflate_method */
9227         if (!((MonoDynamicImage*)(MonoDynamicImage*)klass->image)->save && !klass->generic_container) {
9228                 /* ilgen is no longer needed */
9229                 mb->ilgen = NULL;
9230         }
9231         return mb->mhandle;
9232 }
9233
9234 static MonoClassField*
9235 fieldbuilder_to_mono_class_field (MonoClass *klass, MonoReflectionFieldBuilder* fb)
9236 {
9237         MonoClassField *field;
9238         const char *p, *p2;
9239         guint32 len, idx;
9240
9241         field = g_new0 (MonoClassField, 1);
9242
9243         field->name = mono_string_to_utf8 (fb->name);
9244         if (fb->attrs) {
9245                 field->type = mono_metadata_type_dup (NULL, fb->type->type);
9246                 field->type->attrs = fb->attrs;
9247         } else {
9248                 field->type = fb->type->type;
9249         }
9250         if ((fb->attrs & FIELD_ATTRIBUTE_HAS_FIELD_RVA) && fb->rva_data)
9251                 field->data = mono_array_addr (fb->rva_data, char, 0); /* FIXME: GC pin array */
9252         if (fb->offset != -1)
9253                 field->offset = fb->offset;
9254         field->parent = klass;
9255         mono_save_custom_attrs (klass->image, field, fb->cattrs);
9256
9257         if (fb->def_value) {
9258                 MonoDynamicImage *assembly = (MonoDynamicImage*)klass->image;
9259                 field->type->attrs |= FIELD_ATTRIBUTE_HAS_DEFAULT;
9260                 idx = encode_constant (assembly, fb->def_value, &field->def_type);
9261                 /* Copy the data from the blob since it might get realloc-ed */
9262                 p = assembly->blob.data + idx;
9263                 len = mono_metadata_decode_blob_size (p, &p2);
9264                 len += p2 - p;
9265                 field->data = g_malloc (len);
9266                 memcpy ((gpointer)field->data, p, len);
9267         }
9268
9269         return field;
9270 }
9271
9272 MonoType*
9273 mono_reflection_bind_generic_parameters (MonoReflectionType *type, int type_argc, MonoType **types)
9274 {
9275         MonoClass *klass;
9276         MonoReflectionTypeBuilder *tb = NULL;
9277         gboolean is_dynamic = FALSE;
9278         MonoDomain *domain;
9279         MonoClass *geninst;
9280
9281         mono_loader_lock ();
9282
9283         domain = mono_object_domain (type);
9284
9285         if (!strcmp (((MonoObject *) type)->vtable->klass->name, "TypeBuilder")) {
9286                 tb = (MonoReflectionTypeBuilder *) type;
9287
9288                 is_dynamic = TRUE;
9289         } else if (!strcmp (((MonoObject *) type)->vtable->klass->name, "MonoGenericClass")) {
9290                 MonoReflectionGenericClass *rgi = (MonoReflectionGenericClass *) type;
9291
9292                 tb = rgi->generic_type;
9293                 is_dynamic = TRUE;
9294         }
9295
9296         /* FIXME: fix the CreateGenericParameters protocol to avoid the two stage setup of TypeBuilders */
9297         if (tb && tb->generic_container)
9298                 mono_reflection_create_generic_class (tb);
9299
9300         klass = mono_class_from_mono_type (type->type);
9301         if (!klass->generic_container) {
9302                 mono_loader_unlock ();
9303                 return NULL;
9304         }
9305
9306         if (klass->wastypebuilder) {
9307                 tb = (MonoReflectionTypeBuilder *) klass->reflection_info;
9308
9309                 is_dynamic = TRUE;
9310         }
9311
9312         mono_loader_unlock ();
9313
9314         geninst = mono_class_bind_generic_parameters (klass, type_argc, types, is_dynamic);
9315
9316         return &geninst->byval_arg;
9317 }
9318
9319 MonoClass*
9320 mono_class_bind_generic_parameters (MonoClass *klass, int type_argc, MonoType **types, gboolean is_dynamic)
9321 {
9322         MonoGenericClass *gclass;
9323         MonoGenericInst *inst;
9324
9325         g_assert (klass->generic_container);
9326
9327         inst = mono_metadata_get_generic_inst (type_argc, types);
9328         gclass = mono_metadata_lookup_generic_class (klass, inst, is_dynamic);
9329
9330         return mono_generic_class_get_class (gclass);
9331 }
9332
9333 MonoReflectionMethod*
9334 mono_reflection_bind_generic_method_parameters (MonoReflectionMethod *rmethod, MonoArray *types)
9335 {
9336         MonoClass *klass;
9337         MonoMethod *method, *inflated;
9338         MonoMethodInflated *imethod;
9339         MonoReflectionMethodBuilder *mb = NULL;
9340         MonoGenericContext tmp_context;
9341         MonoGenericInst *ginst;
9342         MonoType **type_argv;
9343         int count, i;
9344
9345         MONO_ARCH_SAVE_REGS;
9346         if (!strcmp (rmethod->object.vtable->klass->name, "MethodBuilder")) {
9347                 MonoReflectionTypeBuilder *tb;
9348                 MonoClass *klass;
9349
9350                 mb = (MonoReflectionMethodBuilder *) rmethod;
9351                 tb = (MonoReflectionTypeBuilder *) mb->type;
9352                 klass = mono_class_from_mono_type (tb->type.type);
9353
9354                 method = methodbuilder_to_mono_method (klass, mb);
9355         } else {
9356                 method = rmethod->method;
9357         }
9358
9359         klass = method->klass;
9360
9361         if (method->is_inflated)
9362                 method = ((MonoMethodInflated *) method)->declaring;
9363
9364         count = mono_method_signature (method)->generic_param_count;
9365         if (count != mono_array_length (types))
9366                 return NULL;
9367
9368         type_argv = g_new0 (MonoType *, count);
9369         for (i = 0; i < count; i++) {
9370                 MonoReflectionType *garg = mono_array_get (types, gpointer, i);
9371                 type_argv [i] = garg->type;
9372         }
9373         ginst = mono_metadata_get_generic_inst (count, type_argv);
9374         g_free (type_argv);
9375
9376         tmp_context.class_inst = klass->generic_class ? klass->generic_class->context.class_inst : NULL;
9377         tmp_context.method_inst = ginst;
9378
9379         inflated = mono_class_inflate_generic_method (method, &tmp_context);
9380         imethod = (MonoMethodInflated *) inflated;
9381
9382         if (method->klass->image->dynamic) {
9383                 MonoDynamicImage *image = (MonoDynamicImage*)method->klass->image;
9384                 /*
9385                  * This table maps metadata structures representing inflated methods/fields
9386                  * to the reflection objects representing their generic definitions.
9387                  */
9388                 mono_loader_lock ();
9389                 mono_g_hash_table_insert (image->generic_def_objects, imethod, rmethod);
9390                 mono_loader_unlock ();
9391         }
9392         
9393         return mono_method_get_object (mono_object_domain (rmethod), inflated, NULL);
9394 }
9395
9396 static MonoMethod *
9397 inflate_mono_method (MonoClass *klass, MonoMethod *method, MonoObject *obj)
9398 {
9399         MonoMethodInflated *imethod;
9400         MonoGenericContext *context;
9401         int i;
9402
9403         g_assert (klass->generic_class);
9404         context = mono_class_get_context (klass);
9405
9406         if (klass->method.count) {
9407                 /* Find the already created inflated method */
9408                 for (i = 0; i < klass->method.count; ++i) {
9409                         g_assert (klass->methods [i]->is_inflated);
9410                         if (((MonoMethodInflated*)klass->methods [i])->declaring == method)
9411                                 break;
9412                 }
9413                 g_assert (i < klass->method.count);
9414                 imethod = (MonoMethodInflated*)klass->methods [i];
9415         } else {
9416                 imethod = (MonoMethodInflated *) mono_class_inflate_generic_method_full (method, klass, context);
9417         }
9418
9419         if (method->is_generic && method->klass->image->dynamic) {
9420                 MonoDynamicImage *image = (MonoDynamicImage*)method->klass->image;
9421
9422                 mono_loader_lock ();
9423                 mono_g_hash_table_insert (image->generic_def_objects, imethod, obj);
9424                 mono_loader_unlock ();
9425         }
9426         return (MonoMethod *) imethod;
9427 }
9428
9429 static MonoMethod *
9430 inflate_method (MonoReflectionGenericClass *type, MonoObject *obj)
9431 {
9432         MonoMethod *method;
9433         MonoClass *gklass;
9434
9435         gklass = mono_class_from_mono_type (type->generic_type->type.type);
9436
9437         if (!strcmp (obj->vtable->klass->name, "MethodBuilder"))
9438                 if (((MonoReflectionMethodBuilder*)obj)->mhandle)
9439                         method = ((MonoReflectionMethodBuilder*)obj)->mhandle;
9440                 else
9441                         method = methodbuilder_to_mono_method (gklass, (MonoReflectionMethodBuilder *) obj);
9442         else if (!strcmp (obj->vtable->klass->name, "ConstructorBuilder"))
9443                 method = ctorbuilder_to_mono_method (gklass, (MonoReflectionCtorBuilder *) obj);
9444         else if (!strcmp (obj->vtable->klass->name, "MonoMethod") || !strcmp (obj->vtable->klass->name, "MonoCMethod"))
9445                 method = ((MonoReflectionMethod *) obj)->method;
9446         else {
9447                 method = NULL; /* prevent compiler warning */
9448                 g_assert_not_reached ();
9449         }
9450
9451         return inflate_mono_method (mono_class_from_mono_type (type->type.type), method, obj);
9452 }
9453
9454 /*TODO avoid saving custom attrs for generic classes as it's enough to have them on the generic type definition.*/
9455 void
9456 mono_reflection_generic_class_initialize (MonoReflectionGenericClass *type, MonoArray *methods, 
9457                                           MonoArray *ctors, MonoArray *fields, MonoArray *properties,
9458                                           MonoArray *events)
9459 {
9460         MonoGenericClass *gclass;
9461         MonoDynamicGenericClass *dgclass;
9462         MonoClass *klass, *gklass;
9463         int i;
9464
9465         MONO_ARCH_SAVE_REGS;
9466
9467         klass = mono_class_from_mono_type (type->type.type);
9468         g_assert (type->type.type->type == MONO_TYPE_GENERICINST);
9469         gclass = type->type.type->data.generic_class;
9470
9471         g_assert (gclass->is_dynamic);
9472         dgclass = (MonoDynamicGenericClass *) gclass;
9473
9474         if (dgclass->initialized)
9475                 return;
9476
9477         gklass = gclass->container_class;
9478         mono_class_init (gklass);
9479
9480         dgclass->count_methods = methods ? mono_array_length (methods) : 0;
9481         dgclass->count_ctors = ctors ? mono_array_length (ctors) : 0;
9482         dgclass->count_fields = fields ? mono_array_length (fields) : 0;
9483         dgclass->count_properties = properties ? mono_array_length (properties) : 0;
9484         dgclass->count_events = events ? mono_array_length (events) : 0;
9485
9486         dgclass->methods = g_new0 (MonoMethod *, dgclass->count_methods);
9487         dgclass->ctors = g_new0 (MonoMethod *, dgclass->count_ctors);
9488         dgclass->fields = g_new0 (MonoClassField, dgclass->count_fields);
9489         dgclass->properties = g_new0 (MonoProperty, dgclass->count_properties);
9490         dgclass->events = g_new0 (MonoEvent, dgclass->count_events);
9491
9492         for (i = 0; i < dgclass->count_methods; i++) {
9493                 MonoObject *obj = mono_array_get (methods, gpointer, i);
9494
9495                 dgclass->methods [i] = inflate_method (type, obj);
9496         }
9497
9498         for (i = 0; i < dgclass->count_ctors; i++) {
9499                 MonoObject *obj = mono_array_get (ctors, gpointer, i);
9500
9501                 dgclass->ctors [i] = inflate_method (type, obj);
9502         }
9503
9504         for (i = 0; i < dgclass->count_fields; i++) {
9505                 MonoObject *obj = mono_array_get (fields, gpointer, i);
9506                 MonoClassField *field, *inflated_field = NULL;
9507                 MonoInflatedField *ifield;
9508
9509                 if (!strcmp (obj->vtable->klass->name, "FieldBuilder"))
9510                         inflated_field = field = fieldbuilder_to_mono_class_field (klass, (MonoReflectionFieldBuilder *) obj);
9511                 else if (!strcmp (obj->vtable->klass->name, "MonoField"))
9512                         field = ((MonoReflectionField *) obj)->field;
9513                 else {
9514                         field = NULL; /* prevent compiler warning */
9515                         g_assert_not_reached ();
9516                 }
9517
9518                 ifield = g_new0 (MonoInflatedField, 1);
9519                 ifield->generic_type = field->type;
9520                 MOVING_GC_REGISTER (&ifield->reflection_info);
9521                 ifield->reflection_info = obj;
9522
9523                 dgclass->fields [i] = *field;
9524                 dgclass->fields [i].parent = klass;
9525                 dgclass->fields [i].generic_info = ifield;
9526                 dgclass->fields [i].type = mono_class_inflate_generic_type (
9527                         field->type, mono_generic_class_get_context ((MonoGenericClass *) dgclass));
9528
9529                 if (inflated_field) {
9530                         g_free ((char*)inflated_field->data);
9531                         g_free (inflated_field);
9532                 } else {
9533                         dgclass->fields [i].name = g_strdup (dgclass->fields [i].name);
9534                 }
9535         }
9536
9537         for (i = 0; i < dgclass->count_properties; i++) {
9538                 MonoObject *obj = mono_array_get (properties, gpointer, i);
9539                 MonoProperty *property = &dgclass->properties [i];
9540
9541                 if (!strcmp (obj->vtable->klass->name, "PropertyBuilder")) {
9542                         MonoReflectionPropertyBuilder *pb = (MonoReflectionPropertyBuilder *) obj;
9543
9544                         property->parent = klass;
9545                         property->attrs = pb->attrs;
9546                         property->name = mono_string_to_utf8 (pb->name);
9547                         if (pb->get_method)
9548                                 property->get = inflate_method (type, (MonoObject *) pb->get_method);
9549                         if (pb->set_method)
9550                                 property->set = inflate_method (type, (MonoObject *) pb->set_method);
9551                 } else if (!strcmp (obj->vtable->klass->name, "MonoProperty")) {
9552                         *property = *((MonoReflectionProperty *) obj)->property;
9553                         property->name = g_strdup (property->name);
9554
9555                         if (property->get)
9556                                 property->get = inflate_mono_method (klass, property->get, NULL);
9557                         if (property->set)
9558                                 property->set = inflate_mono_method (klass, property->set, NULL);
9559                 } else
9560                         g_assert_not_reached ();
9561         }
9562
9563         for (i = 0; i < dgclass->count_events; i++) {
9564                 MonoObject *obj = mono_array_get (events, gpointer, i);
9565                 MonoEvent *event = &dgclass->events [i];
9566
9567                 if (!strcmp (obj->vtable->klass->name, "EventBuilder")) {
9568                         MonoReflectionEventBuilder *eb = (MonoReflectionEventBuilder *) obj;
9569
9570                         event->parent = klass;
9571                         event->attrs = eb->attrs;
9572                         event->name = mono_string_to_utf8 (eb->name);
9573                         if (eb->add_method)
9574                                 event->add = inflate_method (type, (MonoObject *) eb->add_method);
9575                         if (eb->remove_method)
9576                                 event->remove = inflate_method (type, (MonoObject *) eb->remove_method);
9577                 } else if (!strcmp (obj->vtable->klass->name, "MonoEvent")) {
9578                         *event = *((MonoReflectionEvent *) obj)->event;
9579                         event->name = g_strdup (event->name);
9580
9581                         if (event->add)
9582                                 event->add = inflate_mono_method (klass, event->add, NULL);
9583                         if (event->remove)
9584                                 event->remove = inflate_mono_method (klass, event->remove, NULL);
9585                 } else
9586                         g_assert_not_reached ();
9587         }
9588
9589         dgclass->initialized = TRUE;
9590 }
9591
9592 static void
9593 ensure_runtime_vtable (MonoClass *klass)
9594 {
9595         MonoReflectionTypeBuilder *tb = klass->reflection_info;
9596         int i, num, j;
9597
9598         if (!tb || klass->wastypebuilder)
9599                 return;
9600         if (klass->parent)
9601                 ensure_runtime_vtable (klass->parent);
9602
9603         num = tb->ctors? mono_array_length (tb->ctors): 0;
9604         num += tb->num_methods;
9605         klass->method.count = num;
9606         klass->methods = mono_mempool_alloc (klass->image->mempool, sizeof (MonoMethod*) * num);
9607         num = tb->ctors? mono_array_length (tb->ctors): 0;
9608         for (i = 0; i < num; ++i)
9609                 klass->methods [i] = ctorbuilder_to_mono_method (klass, mono_array_get (tb->ctors, MonoReflectionCtorBuilder*, i));
9610         num = tb->num_methods;
9611         j = i;
9612         for (i = 0; i < num; ++i)
9613                 klass->methods [j++] = methodbuilder_to_mono_method (klass, mono_array_get (tb->methods, MonoReflectionMethodBuilder*, i));
9614
9615         if (tb->interfaces) {
9616                 klass->interface_count = mono_array_length (tb->interfaces);
9617                 klass->interfaces = mono_mempool_alloc (klass->image->mempool, sizeof (MonoClass*) * klass->interface_count);
9618                 for (i = 0; i < klass->interface_count; ++i) {
9619                         MonoReflectionType *iface = mono_array_get (tb->interfaces, gpointer, i);
9620                         klass->interfaces [i] = mono_class_from_mono_type (iface->type);
9621                 }
9622         }
9623
9624         if (klass->flags & TYPE_ATTRIBUTE_INTERFACE) {
9625                 for (i = 0; i < klass->method.count; ++i)
9626                         klass->methods [i]->slot = i;
9627                 
9628                 mono_class_setup_interface_offsets (klass);
9629         }
9630
9631         /*
9632          * The generic vtable is needed even if image->run is not set since some
9633          * runtime code like ves_icall_Type_GetMethodsByName depends on 
9634          * method->slot being defined.
9635          */
9636
9637         /* 
9638          * tb->methods could not be freed since it is used for determining 
9639          * overrides during dynamic vtable construction.
9640          */
9641 }
9642
9643 void
9644 mono_reflection_get_dynamic_overrides (MonoClass *klass, MonoMethod ***overrides, int *num_overrides)
9645 {
9646         MonoReflectionTypeBuilder *tb;
9647         int i, onum;
9648
9649         *overrides = NULL;
9650         *num_overrides = 0;
9651
9652         g_assert (klass->image->dynamic);
9653
9654         if (!klass->reflection_info)
9655                 return;
9656
9657         g_assert (strcmp (((MonoObject*)klass->reflection_info)->vtable->klass->name, "TypeBuilder") == 0);
9658
9659         tb = (MonoReflectionTypeBuilder*)klass->reflection_info;
9660
9661         onum = 0;
9662         if (tb->methods) {
9663                 for (i = 0; i < tb->num_methods; ++i) {
9664                         MonoReflectionMethodBuilder *mb = 
9665                                 mono_array_get (tb->methods, MonoReflectionMethodBuilder*, i);
9666                         if (mb->override_method)
9667                                 onum ++;
9668                 }
9669         }
9670
9671         if (onum) {
9672                 *overrides = g_new0 (MonoMethod*, onum * 2);
9673
9674                 onum = 0;
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                                 (*overrides) [onum * 2] = 
9680                                         mb->override_method->method;
9681                                 (*overrides) [onum * 2 + 1] =
9682                                         mb->mhandle;
9683
9684                                 /* FIXME: What if 'override_method' is a MethodBuilder ? */
9685                                 g_assert (mb->override_method->method);
9686                                 g_assert (mb->mhandle);
9687
9688                                 onum ++;
9689                         }
9690                 }
9691         }
9692
9693         *num_overrides = onum;
9694 }
9695
9696 static void
9697 typebuilder_setup_fields (MonoClass *klass)
9698 {
9699         MonoReflectionTypeBuilder *tb = klass->reflection_info;
9700         MonoReflectionFieldBuilder *fb;
9701         MonoClassField *field;
9702         MonoMemPool *mp = klass->image->mempool;
9703         const char *p, *p2;
9704         int i;
9705         guint32 len, idx;
9706
9707         klass->field.count = tb->num_fields;
9708         klass->field.first = 0;
9709
9710         if (!klass->field.count)
9711                 return;
9712         
9713         klass->fields = mp_g_new0 (mp, MonoClassField, klass->field.count);
9714
9715         for (i = 0; i < klass->field.count; ++i) {
9716                 fb = mono_array_get (tb->fields, gpointer, i);
9717                 field = &klass->fields [i];
9718                 field->name = mp_string_to_utf8 (mp, fb->name);
9719                 if (fb->attrs) {
9720                         field->type = mono_metadata_type_dup (mp, fb->type->type);
9721                         field->type->attrs = fb->attrs;
9722                 } else {
9723                         field->type = fb->type->type;
9724                 }
9725                 if ((fb->attrs & FIELD_ATTRIBUTE_HAS_FIELD_RVA) && fb->rva_data)
9726                         field->data = mono_array_addr (fb->rva_data, char, 0);
9727                 if (fb->offset != -1)
9728                         field->offset = fb->offset;
9729                 field->parent = klass;
9730                 fb->handle = field;
9731                 mono_save_custom_attrs (klass->image, field, fb->cattrs);
9732
9733                 if (fb->def_value) {
9734                         MonoDynamicImage *assembly = (MonoDynamicImage*)klass->image;
9735                         field->type->attrs |= FIELD_ATTRIBUTE_HAS_DEFAULT;
9736                         idx = encode_constant (assembly, fb->def_value, &field->def_type);
9737                         /* Copy the data from the blob since it might get realloc-ed */
9738                         p = assembly->blob.data + idx;
9739                         len = mono_metadata_decode_blob_size (p, &p2);
9740                         len += p2 - p;
9741                         field->data = mono_mempool_alloc (mp, len);
9742                         memcpy ((gpointer)field->data, p, len);
9743                 }
9744         }
9745         mono_class_layout_fields (klass);
9746 }
9747
9748 static void
9749 typebuilder_setup_properties (MonoClass *klass)
9750 {
9751         MonoReflectionTypeBuilder *tb = klass->reflection_info;
9752         MonoReflectionPropertyBuilder *pb;
9753         MonoMemPool *mp = klass->image->mempool;
9754         int i;
9755
9756         klass->property.count = tb->properties ? mono_array_length (tb->properties) : 0;
9757         klass->property.first = 0;
9758
9759         klass->properties = mp_g_new0 (mp, MonoProperty, klass->property.count);
9760         for (i = 0; i < klass->property.count; ++i) {
9761                 pb = mono_array_get (tb->properties, MonoReflectionPropertyBuilder*, i);
9762                 klass->properties [i].parent = klass;
9763                 klass->properties [i].attrs = pb->attrs;
9764                 klass->properties [i].name = mp_string_to_utf8 (mp, pb->name);
9765                 if (pb->get_method)
9766                         klass->properties [i].get = pb->get_method->mhandle;
9767                 if (pb->set_method)
9768                         klass->properties [i].set = pb->set_method->mhandle;
9769
9770                 mono_save_custom_attrs (klass->image, &klass->properties [i], pb->cattrs);
9771         }
9772 }
9773
9774 MonoReflectionEvent *
9775 mono_reflection_event_builder_get_event_info (MonoReflectionTypeBuilder *tb, MonoReflectionEventBuilder *eb)
9776 {
9777         MonoEvent *event = g_new0 (MonoEvent, 1);
9778         MonoClass *klass;
9779         int j;
9780
9781         klass = my_mono_class_from_mono_type (tb->type.type);
9782
9783         event->parent = klass;
9784         event->attrs = eb->attrs;
9785         event->name = mono_string_to_utf8 (eb->name);
9786         if (eb->add_method)
9787                 event->add = eb->add_method->mhandle;
9788         if (eb->remove_method)
9789                 event->remove = eb->remove_method->mhandle;
9790         if (eb->raise_method)
9791                 event->raise = eb->raise_method->mhandle;
9792
9793         if (eb->other_methods) {
9794                 event->other = g_new0 (MonoMethod*, mono_array_length (eb->other_methods) + 1);
9795                 for (j = 0; j < mono_array_length (eb->other_methods); ++j) {
9796                         MonoReflectionMethodBuilder *mb = 
9797                                 mono_array_get (eb->other_methods,
9798                                                 MonoReflectionMethodBuilder*, j);
9799                         event->other [j] = mb->mhandle;
9800                 }
9801         }
9802
9803         return mono_event_get_object (mono_object_domain (tb), klass, event);
9804 }
9805
9806 static void
9807 typebuilder_setup_events (MonoClass *klass)
9808 {
9809         MonoReflectionTypeBuilder *tb = klass->reflection_info;
9810         MonoReflectionEventBuilder *eb;
9811         MonoMemPool *mp = klass->image->mempool;
9812         int i, j;
9813
9814         klass->event.count = tb->events ? mono_array_length (tb->events) : 0;
9815         klass->event.first = 0;
9816
9817         klass->events = mp_g_new0 (mp, MonoEvent, klass->event.count);
9818         for (i = 0; i < klass->event.count; ++i) {
9819                 eb = mono_array_get (tb->events, MonoReflectionEventBuilder*, i);
9820                 klass->events [i].parent = klass;
9821                 klass->events [i].attrs = eb->attrs;
9822                 klass->events [i].name = mp_string_to_utf8 (mp, eb->name);
9823                 if (eb->add_method)
9824                         klass->events [i].add = eb->add_method->mhandle;
9825                 if (eb->remove_method)
9826                         klass->events [i].remove = eb->remove_method->mhandle;
9827                 if (eb->raise_method)
9828                         klass->events [i].raise = eb->raise_method->mhandle;
9829
9830                 if (eb->other_methods) {
9831                         klass->events [i].other = mp_g_new0 (mp, MonoMethod*, mono_array_length (eb->other_methods) + 1);
9832                         for (j = 0; j < mono_array_length (eb->other_methods); ++j) {
9833                                 MonoReflectionMethodBuilder *mb = 
9834                                         mono_array_get (eb->other_methods,
9835                                                                         MonoReflectionMethodBuilder*, j);
9836                                 klass->events [i].other [j] = mb->mhandle;
9837                         }
9838                 }
9839                 mono_save_custom_attrs (klass->image, &klass->events [i], eb->cattrs);
9840         }
9841 }
9842
9843 static gboolean
9844 remove_instantiations_of (gpointer key,
9845                                                   gpointer value,
9846                                                   gpointer user_data)
9847 {
9848         MonoType *type = (MonoType*)key;
9849         MonoClass *klass = (MonoClass*)user_data;
9850
9851         if ((type->type == MONO_TYPE_GENERICINST) && (type->data.generic_class->container_class == klass))
9852                 return TRUE;
9853         else
9854                 return FALSE;
9855 }
9856
9857 MonoReflectionType*
9858 mono_reflection_create_runtime_class (MonoReflectionTypeBuilder *tb)
9859 {
9860         MonoClass *klass;
9861         MonoDomain* domain;
9862         MonoReflectionType* res;
9863         int i;
9864
9865         MONO_ARCH_SAVE_REGS;
9866
9867         domain = mono_object_domain (tb);
9868         klass = my_mono_class_from_mono_type (tb->type.type);
9869
9870         mono_save_custom_attrs (klass->image, klass, tb->cattrs);
9871         
9872         /* 
9873          * we need to lock the domain because the lock will be taken inside
9874          * So, we need to keep the locking order correct.
9875          */
9876         mono_domain_lock (domain);
9877         mono_loader_lock ();
9878         if (klass->wastypebuilder) {
9879                 mono_loader_unlock ();
9880                 mono_domain_unlock (domain);
9881                 return mono_type_get_object (mono_object_domain (tb), &klass->byval_arg);
9882         }
9883         /*
9884          * Fields to set in klass:
9885          * the various flags: delegate/unicode/contextbound etc.
9886          */
9887         klass->flags = tb->attrs;
9888         klass->has_cctor = 1;
9889         klass->has_finalize = 1;
9890
9891 #if 0
9892         if (!((MonoDynamicImage*)klass->image)->run) {
9893                 if (klass->generic_container) {
9894                         /* FIXME: The code below can't handle generic classes */
9895                         klass->wastypebuilder = TRUE;
9896                         mono_loader_unlock ();
9897                         mono_domain_unlock (domain);
9898                         return mono_type_get_object (mono_object_domain (tb), &klass->byval_arg);
9899                 }
9900         }
9901 #endif
9902
9903         /* enums are done right away */
9904         if (!klass->enumtype)
9905                 ensure_runtime_vtable (klass);
9906
9907         if (tb->subtypes) {
9908                 for (i = 0; i < mono_array_length (tb->subtypes); ++i) {
9909                         MonoReflectionTypeBuilder *subtb = mono_array_get (tb->subtypes, MonoReflectionTypeBuilder*, i);
9910                         klass->nested_classes = g_list_prepend (klass->nested_classes, my_mono_class_from_mono_type (subtb->type.type));
9911                 }
9912         }
9913
9914         /* fields and object layout */
9915         if (klass->parent) {
9916                 if (!klass->parent->size_inited)
9917                         mono_class_init (klass->parent);
9918                 klass->instance_size = klass->parent->instance_size;
9919                 klass->sizes.class_size = 0;
9920                 klass->min_align = klass->parent->min_align;
9921                 /* if the type has no fields we won't call the field_setup
9922                  * routine which sets up klass->has_references.
9923                  */
9924                 klass->has_references |= klass->parent->has_references;
9925         } else {
9926                 klass->instance_size = sizeof (MonoObject);
9927                 klass->min_align = 1;
9928         }
9929
9930         /* FIXME: handle packing_size and instance_size */
9931         typebuilder_setup_fields (klass);
9932
9933         typebuilder_setup_properties (klass);
9934
9935         typebuilder_setup_events (klass);
9936         
9937         klass->wastypebuilder = TRUE;
9938
9939         /* 
9940          * If we are a generic TypeBuilder, there might be instantiations in the type cache
9941          * which have type System.Reflection.MonoGenericClass, but after the type is created, 
9942          * we want to return normal System.MonoType objects, so clear these out from the cache.
9943          */
9944         if (domain->type_hash && klass->generic_container)
9945                 mono_g_hash_table_foreach_remove (domain->type_hash, remove_instantiations_of, klass);
9946
9947         mono_loader_unlock ();
9948         mono_domain_unlock (domain);
9949
9950         if (klass->enumtype && !mono_class_is_valid_enum (klass)) {
9951                 mono_class_set_failure (klass, MONO_EXCEPTION_TYPE_LOAD, NULL);
9952                 mono_raise_exception (mono_get_exception_type_load (tb->name, NULL));
9953         }
9954
9955         res = mono_type_get_object (mono_object_domain (tb), &klass->byval_arg);
9956         g_assert (res != (MonoReflectionType*)tb);
9957
9958         return res;
9959 }
9960
9961 void
9962 mono_reflection_initialize_generic_parameter (MonoReflectionGenericParam *gparam)
9963 {
9964         MonoGenericParam *param;
9965         MonoImage *image;
9966
9967         MONO_ARCH_SAVE_REGS;
9968
9969         param = g_new0 (MonoGenericParam, 1);
9970
9971         if (gparam->mbuilder) {
9972                 if (!gparam->mbuilder->generic_container) {
9973                         MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder *)gparam->mbuilder->type;
9974                         MonoClass *klass = my_mono_class_from_mono_type (tb->type.type);
9975                         gparam->mbuilder->generic_container = mono_mempool_alloc0 (klass->image->mempool, sizeof (MonoGenericContainer));
9976                         gparam->mbuilder->generic_container->is_method = TRUE;
9977                 }
9978                 param->owner = gparam->mbuilder->generic_container;
9979         } else if (gparam->tbuilder) {
9980                 g_assert (gparam->tbuilder->generic_container);
9981                 param->owner = gparam->tbuilder->generic_container;
9982         }
9983
9984         param->name = mono_string_to_utf8 (gparam->name);
9985         param->num = gparam->index;
9986
9987         image = &gparam->tbuilder->module->dynamic_image->image;
9988         mono_class_from_generic_parameter (param, image, gparam->mbuilder != NULL);
9989
9990         MOVING_GC_REGISTER (&param->pklass->reflection_info);
9991         param->pklass->reflection_info = gparam; /* FIXME: GC pin gparam */
9992
9993         gparam->type.type = g_new0 (MonoType, 1);
9994         gparam->type.type->type = gparam->mbuilder ? MONO_TYPE_MVAR : MONO_TYPE_VAR;
9995         gparam->type.type->attrs = TYPE_ATTRIBUTE_PUBLIC;
9996         gparam->type.type->data.generic_param = param;
9997 }
9998
9999 MonoArray *
10000 mono_reflection_sighelper_get_signature_local (MonoReflectionSigHelper *sig)
10001 {
10002         MonoDynamicImage *assembly = sig->module->dynamic_image;
10003         guint32 na = mono_array_length (sig->arguments);
10004         guint32 buflen, i;
10005         MonoArray *result;
10006         SigBuffer buf;
10007
10008         sigbuffer_init (&buf, 32);
10009
10010         sigbuffer_add_value (&buf, 0x07);
10011         sigbuffer_add_value (&buf, na);
10012         for (i = 0; i < na; ++i) {
10013                 MonoReflectionType *type = mono_array_get (sig->arguments, MonoReflectionType *, i);
10014                 encode_reflection_type (assembly, type, &buf);
10015         }
10016
10017         buflen = buf.p - buf.buf;
10018         result = mono_array_new (mono_domain_get (), mono_defaults.byte_class, buflen);
10019         memcpy (mono_array_addr (result, char, 0), buf.buf, buflen);
10020         sigbuffer_free (&buf);
10021
10022         return result;
10023 }
10024
10025 MonoArray *
10026 mono_reflection_sighelper_get_signature_field (MonoReflectionSigHelper *sig)
10027 {
10028         MonoDynamicImage *assembly = sig->module->dynamic_image;
10029         guint32 na = mono_array_length (sig->arguments);
10030         guint32 buflen, i;
10031         MonoArray *result;
10032         SigBuffer buf;
10033
10034         sigbuffer_init (&buf, 32);
10035
10036         sigbuffer_add_value (&buf, 0x06);
10037         for (i = 0; i < na; ++i) {
10038                 MonoReflectionType *type = mono_array_get (sig->arguments, MonoReflectionType *, i);
10039                 encode_reflection_type (assembly, type, &buf);
10040         }
10041
10042         buflen = buf.p - buf.buf;
10043         result = mono_array_new (mono_domain_get (), mono_defaults.byte_class, buflen);
10044         memcpy (mono_array_addr (result, char, 0), buf.buf, buflen);
10045         sigbuffer_free (&buf);
10046
10047         return result;
10048 }
10049
10050 void 
10051 mono_reflection_create_dynamic_method (MonoReflectionDynamicMethod *mb)
10052 {
10053         ReflectionMethodBuilder rmb;
10054         MonoMethodSignature *sig;
10055         MonoClass *klass;
10056         GSList *l;
10057         int i;
10058
10059         sig = dynamic_method_to_signature (mb);
10060
10061         reflection_methodbuilder_from_dynamic_method (&rmb, mb);
10062
10063         /*
10064          * Resolve references.
10065          */
10066         /* 
10067          * Every second entry in the refs array is reserved for storing handle_class,
10068          * which is needed by the ldtoken implementation in the JIT.
10069          */
10070         rmb.nrefs = mb->nrefs;
10071         rmb.refs = g_new0 (gpointer, mb->nrefs + 1);
10072         for (i = 0; i < mb->nrefs; i += 2) {
10073                 MonoClass *handle_class;
10074                 gpointer ref;
10075                 MonoObject *obj = mono_array_get (mb->refs, MonoObject*, i);
10076
10077                 if (strcmp (obj->vtable->klass->name, "DynamicMethod") == 0) {
10078                         MonoReflectionDynamicMethod *method = (MonoReflectionDynamicMethod*)obj;
10079                         /*
10080                          * The referenced DynamicMethod should already be created by the managed
10081                          * code, except in the case of circular references. In that case, we store
10082                          * method in the refs array, and fix it up later when the referenced 
10083                          * DynamicMethod is created.
10084                          */
10085                         if (method->mhandle) {
10086                                 ref = method->mhandle;
10087                         } else {
10088                                 /* FIXME: GC object stored in unmanaged memory */
10089                                 ref = method;
10090
10091                                 /* FIXME: GC object stored in unmanaged memory */
10092                                 method->referenced_by = g_slist_append (method->referenced_by, mb);
10093                         }
10094                         handle_class = mono_defaults.methodhandle_class;
10095                 } else {
10096                         ref = resolve_object (mb->module->image, obj, &handle_class, NULL);
10097                         if (!ref) {
10098                                 g_free (rmb.refs);
10099                                 mono_raise_exception (mono_get_exception_type_load (NULL, NULL));
10100                                 return;
10101                         }
10102                 }
10103
10104                 rmb.refs [i] = ref; /* FIXME: GC object stored in unmanaged memory (change also resolve_object() signature) */
10105                 rmb.refs [i + 1] = handle_class;
10106         }               
10107
10108         klass = mb->owner ? mono_class_from_mono_type (mb->owner->type) : mono_defaults.object_class;
10109
10110         mb->mhandle = reflection_methodbuilder_to_mono_method (klass, &rmb, sig);
10111
10112         /* Fix up refs entries pointing at us */
10113         for (l = mb->referenced_by; l; l = l->next) {
10114                 MonoReflectionDynamicMethod *method = (MonoReflectionDynamicMethod*)l->data;
10115                 MonoMethodWrapper *wrapper = (MonoMethodWrapper*)method->mhandle;
10116                 gpointer *data;
10117                 
10118                 g_assert (method->mhandle);
10119
10120                 data = (gpointer*)wrapper->method_data;
10121                 for (i = 0; i < GPOINTER_TO_UINT (data [0]); i += 2) {
10122                         if ((data [i + 1] == mb) && (data [i + 1 + 1] == mono_defaults.methodhandle_class))
10123                                 data [i + 1] = mb->mhandle;
10124                 }
10125         }
10126         g_slist_free (mb->referenced_by);
10127
10128         g_free (rmb.refs);
10129
10130         /* ilgen is no longer needed */
10131         mb->ilgen = NULL;
10132 }
10133
10134 void
10135 mono_reflection_destroy_dynamic_method (MonoReflectionDynamicMethod *mb)
10136 {
10137         g_assert (mb);
10138
10139         if (mb->mhandle)
10140                 mono_runtime_free_method (
10141                         mono_object_get_domain ((MonoObject*)mb), mb->mhandle);
10142 }
10143
10144 /**
10145  * 
10146  * mono_reflection_is_valid_dynamic_token:
10147  * 
10148  * Returns TRUE if token is valid.
10149  * 
10150  */
10151 gboolean
10152 mono_reflection_is_valid_dynamic_token (MonoDynamicImage *image, guint32 token)
10153 {
10154         return mono_g_hash_table_lookup (image->tokens, GUINT_TO_POINTER (token)) != NULL;
10155 }
10156
10157 /**
10158  * mono_reflection_lookup_dynamic_token:
10159  *
10160  * Finish the Builder object pointed to by TOKEN and return the corresponding
10161  * runtime structure. If HANDLE_CLASS is not NULL, it is set to the class required by 
10162  * mono_ldtoken. If valid_token is TRUE, assert if it is not found in the token->object
10163  * mapping table.
10164  */
10165 gpointer
10166 mono_reflection_lookup_dynamic_token (MonoImage *image, guint32 token, gboolean valid_token, MonoClass **handle_class, MonoGenericContext *context)
10167 {
10168         MonoDynamicImage *assembly = (MonoDynamicImage*)image;
10169         MonoObject *obj;
10170         MonoClass *klass;
10171
10172         obj = mono_g_hash_table_lookup (assembly->tokens, GUINT_TO_POINTER (token));
10173         if (!obj) {
10174                 if (valid_token)
10175                         g_assert_not_reached ();
10176                 else
10177                         return NULL;
10178         }
10179
10180         if (!handle_class)
10181                 handle_class = &klass;
10182         return resolve_object (image, obj, handle_class, context);
10183 }
10184
10185 static gpointer
10186 resolve_object (MonoImage *image, MonoObject *obj, MonoClass **handle_class, MonoGenericContext *context)
10187 {
10188         gpointer result = NULL;
10189
10190         if (strcmp (obj->vtable->klass->name, "String") == 0) {
10191                 result = mono_string_intern ((MonoString*)obj);
10192                 *handle_class = NULL;
10193                 g_assert (result);
10194         } else if (strcmp (obj->vtable->klass->name, "MonoType") == 0) {
10195                 MonoReflectionType *tb = (MonoReflectionType*)obj;
10196                 if (context) {
10197                         MonoType *inflated = mono_class_inflate_generic_type (tb->type, context);
10198                         result = mono_class_from_mono_type (inflated);
10199                         mono_metadata_free_type (inflated);
10200                 } else {
10201                         result = mono_class_from_mono_type (tb->type);
10202                 }
10203                 *handle_class = mono_defaults.typehandle_class;
10204                 g_assert (result);
10205         } else if (strcmp (obj->vtable->klass->name, "MonoMethod") == 0 ||
10206                    strcmp (obj->vtable->klass->name, "MonoCMethod") == 0 ||
10207                    strcmp (obj->vtable->klass->name, "MonoGenericCMethod") == 0 ||
10208                    strcmp (obj->vtable->klass->name, "MonoGenericMethod") == 0) {
10209                 result = ((MonoReflectionMethod*)obj)->method;
10210                 if (context)
10211                         result = mono_class_inflate_generic_method (result, context);
10212                 *handle_class = mono_defaults.methodhandle_class;
10213                 g_assert (result);
10214         } else if (strcmp (obj->vtable->klass->name, "MethodBuilder") == 0) {
10215                 MonoReflectionMethodBuilder *mb = (MonoReflectionMethodBuilder*)obj;
10216                 result = mb->mhandle;
10217                 if (!result) {
10218                         /* Type is not yet created */
10219                         MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder*)mb->type;
10220
10221                         mono_domain_try_type_resolve (mono_domain_get (), NULL, (MonoObject*)tb);
10222
10223                         /*
10224                          * Hopefully this has been filled in by calling CreateType() on the
10225                          * TypeBuilder.
10226                          */
10227                         /*
10228                          * TODO: This won't work if the application finishes another 
10229                          * TypeBuilder instance instead of this one.
10230                          */
10231                         result = mb->mhandle;
10232                 }
10233                 if (context)
10234                         result = mono_class_inflate_generic_method (result, context);
10235                 *handle_class = mono_defaults.methodhandle_class;
10236         } else if (strcmp (obj->vtable->klass->name, "ConstructorBuilder") == 0) {
10237                 MonoReflectionCtorBuilder *cb = (MonoReflectionCtorBuilder*)obj;
10238
10239                 result = cb->mhandle;
10240                 if (!result) {
10241                         MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder*)cb->type;
10242
10243                         mono_domain_try_type_resolve (mono_domain_get (), NULL, (MonoObject*)tb);
10244                         result = cb->mhandle;
10245                 }
10246                 if (context)
10247                         result = mono_class_inflate_generic_method (result, context);
10248                 *handle_class = mono_defaults.methodhandle_class;
10249         } else if (strcmp (obj->vtable->klass->name, "MonoField") == 0) {
10250                 result = ((MonoReflectionField*)obj)->field;
10251                 *handle_class = mono_defaults.fieldhandle_class;
10252                 g_assert (result);
10253         } else if (strcmp (obj->vtable->klass->name, "FieldBuilder") == 0) {
10254                 MonoReflectionFieldBuilder *fb = (MonoReflectionFieldBuilder*)obj;
10255                 result = fb->handle;
10256
10257                 if (!result) {
10258                         MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder*)fb->typeb;
10259
10260                         mono_domain_try_type_resolve (mono_domain_get (), NULL, (MonoObject*)tb);
10261                         result = fb->handle;
10262                 }
10263
10264                 if (fb->handle && fb->handle->parent->generic_container) {
10265                         MonoClass *klass = fb->handle->parent;
10266                         MonoType *type = mono_class_inflate_generic_type (&klass->byval_arg, context);
10267                         MonoClass *inflated = mono_class_from_mono_type (type);
10268
10269                         result = mono_class_get_field_from_name (inflated, fb->handle->name);
10270                         g_assert (result);
10271                         mono_metadata_free_type (type);
10272                 }
10273                 *handle_class = mono_defaults.fieldhandle_class;
10274         } else if (strcmp (obj->vtable->klass->name, "TypeBuilder") == 0) {
10275                 MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder*)obj;
10276                 MonoClass *klass;
10277
10278                 klass = tb->type.type->data.klass;
10279                 if (klass->wastypebuilder) {
10280                         /* Already created */
10281                         result = klass;
10282                 }
10283                 else {
10284                         mono_domain_try_type_resolve (mono_domain_get (), NULL, (MonoObject*)tb);
10285                         result = tb->type.type->data.klass;
10286                         g_assert (result);
10287                 }
10288                 *handle_class = mono_defaults.typehandle_class;
10289         } else if (strcmp (obj->vtable->klass->name, "SignatureHelper") == 0) {
10290                 MonoReflectionSigHelper *helper = (MonoReflectionSigHelper*)obj;
10291                 MonoMethodSignature *sig;
10292                 int nargs, i;
10293
10294                 if (helper->arguments)
10295                         nargs = mono_array_length (helper->arguments);
10296                 else
10297                         nargs = 0;
10298
10299                 sig = mono_metadata_signature_alloc (image, nargs);
10300                 sig->explicit_this = helper->call_conv & 64 ? 1 : 0;
10301                 sig->hasthis = helper->call_conv & 32 ? 1 : 0;
10302
10303                 if (helper->call_conv == 0) /* unmanaged */
10304                         sig->call_convention = helper->unmanaged_call_conv - 1;
10305                 else
10306                         if (helper->call_conv & 0x02)
10307                                 sig->call_convention = MONO_CALL_VARARG;
10308                 else
10309                         sig->call_convention = MONO_CALL_DEFAULT;
10310
10311                 sig->param_count = nargs;
10312                 /* TODO: Copy type ? */
10313                 sig->ret = helper->return_type->type;
10314                 for (i = 0; i < nargs; ++i) {
10315                         MonoReflectionType *rt = mono_array_get (helper->arguments, MonoReflectionType*, i);
10316                         sig->params [i] = rt->type;
10317                 }
10318
10319                 result = sig;
10320                 *handle_class = NULL;
10321         } else if (strcmp (obj->vtable->klass->name, "DynamicMethod") == 0) {
10322                 MonoReflectionDynamicMethod *method = (MonoReflectionDynamicMethod*)obj;
10323                 /* Already created by the managed code */
10324                 g_assert (method->mhandle);
10325                 result = method->mhandle;
10326                 *handle_class = mono_defaults.methodhandle_class;
10327         } else if (strcmp (obj->vtable->klass->name, "GenericTypeParameterBuilder") == 0) {
10328                 MonoReflectionType *tb = (MonoReflectionType*)obj;
10329                 MonoType *type = mono_class_inflate_generic_type (tb->type, context);
10330                 result = mono_class_from_mono_type (type);
10331                 *handle_class = mono_defaults.typehandle_class;
10332                 g_assert (result);
10333                 mono_metadata_free_type (type);
10334         } else if (strcmp (obj->vtable->klass->name, "MonoGenericClass") == 0) {
10335                 MonoReflectionGenericClass *ref = (MonoReflectionGenericClass*)obj;
10336                 MonoType *type = mono_class_inflate_generic_type (ref->type.type, context);
10337                 result = mono_class_from_mono_type (type);
10338                 *handle_class = mono_defaults.typehandle_class;
10339                 g_assert (result);
10340                 mono_metadata_free_type (type);
10341         } else if (strcmp (obj->vtable->klass->name, "FieldOnTypeBuilderInst") == 0) {
10342                 MonoReflectionFieldOnTypeBuilderInst *f = (MonoReflectionFieldOnTypeBuilderInst*)obj;
10343                 MonoClass *inflated;
10344                 MonoType *type;
10345
10346                 type = mono_class_inflate_generic_type (f->inst->type.type, context);
10347                 inflated = mono_class_from_mono_type (type);
10348
10349                 g_assert (f->fb->handle);
10350                 result = mono_class_get_field_from_name (inflated, f->fb->handle->name);
10351                 g_assert (result);
10352                 mono_metadata_free_type (type);
10353                 *handle_class = mono_defaults.fieldhandle_class;
10354         } else if (strcmp (obj->vtable->klass->name, "ConstructorOnTypeBuilderInst") == 0) {
10355                 MonoReflectionCtorOnTypeBuilderInst *c = (MonoReflectionCtorOnTypeBuilderInst*)obj;
10356                 MonoType *type = mono_class_inflate_generic_type (c->inst->type.type, context);
10357                 MonoClass *inflated_klass = mono_class_from_mono_type (type);
10358                 g_assert (c->cb->mhandle);
10359                 result = inflate_mono_method (inflated_klass, c->cb->mhandle, (MonoObject*)c->cb);
10360                 *handle_class = mono_defaults.methodhandle_class;
10361                 mono_metadata_free_type (type);
10362         } else if (strcmp (obj->vtable->klass->name, "MethodOnTypeBuilderInst") == 0) {
10363                 MonoReflectionMethodOnTypeBuilderInst *m = (MonoReflectionMethodOnTypeBuilderInst*)obj;
10364                 MonoType *type = mono_class_inflate_generic_type (m->inst->type.type, context);
10365                 MonoClass *inflated_klass = mono_class_from_mono_type (type);
10366                 g_assert (m->mb->mhandle);
10367                 result = inflate_mono_method (inflated_klass, m->mb->mhandle, (MonoObject*)m->mb);
10368                 *handle_class = mono_defaults.methodhandle_class;
10369                 mono_metadata_free_type (type);
10370         } else {
10371                 g_print (obj->vtable->klass->name);
10372                 g_assert_not_reached ();
10373         }
10374         return result;
10375 }
10376
10377
10378 /* SECURITY_ACTION_* are defined in mono/metadata/tabledefs.h */
10379 const static guint32 declsec_flags_map[] = {
10380         0x00000000,                                     /* empty */
10381         MONO_DECLSEC_FLAG_REQUEST,                      /* SECURITY_ACTION_REQUEST                      (x01) */
10382         MONO_DECLSEC_FLAG_DEMAND,                       /* SECURITY_ACTION_DEMAND                       (x02) */
10383         MONO_DECLSEC_FLAG_ASSERT,                       /* SECURITY_ACTION_ASSERT                       (x03) */
10384         MONO_DECLSEC_FLAG_DENY,                         /* SECURITY_ACTION_DENY                         (x04) */
10385         MONO_DECLSEC_FLAG_PERMITONLY,                   /* SECURITY_ACTION_PERMITONLY                   (x05) */
10386         MONO_DECLSEC_FLAG_LINKDEMAND,                   /* SECURITY_ACTION_LINKDEMAND                   (x06) */
10387         MONO_DECLSEC_FLAG_INHERITANCEDEMAND,            /* SECURITY_ACTION_INHERITANCEDEMAND            (x07) */
10388         MONO_DECLSEC_FLAG_REQUEST_MINIMUM,              /* SECURITY_ACTION_REQUEST_MINIMUM              (x08) */
10389         MONO_DECLSEC_FLAG_REQUEST_OPTIONAL,             /* SECURITY_ACTION_REQUEST_OPTIONAL             (x09) */
10390         MONO_DECLSEC_FLAG_REQUEST_REFUSE,               /* SECURITY_ACTION_REQUEST_REFUSE               (x0A) */
10391         MONO_DECLSEC_FLAG_PREJIT_GRANT,                 /* SECURITY_ACTION_PREJIT_GRANT                 (x0B) */
10392         MONO_DECLSEC_FLAG_PREJIT_DENY,                  /* SECURITY_ACTION_PREJIT_DENY                  (x0C) */
10393         MONO_DECLSEC_FLAG_NONCAS_DEMAND,                /* SECURITY_ACTION_NONCAS_DEMAND                (x0D) */
10394         MONO_DECLSEC_FLAG_NONCAS_LINKDEMAND,            /* SECURITY_ACTION_NONCAS_LINKDEMAND            (x0E) */
10395         MONO_DECLSEC_FLAG_NONCAS_INHERITANCEDEMAND,     /* SECURITY_ACTION_NONCAS_INHERITANCEDEMAND     (x0F) */
10396         MONO_DECLSEC_FLAG_LINKDEMAND_CHOICE,            /* SECURITY_ACTION_LINKDEMAND_CHOICE            (x10) */
10397         MONO_DECLSEC_FLAG_INHERITANCEDEMAND_CHOICE,     /* SECURITY_ACTION_INHERITANCEDEMAND_CHOICE     (x11) */
10398         MONO_DECLSEC_FLAG_DEMAND_CHOICE,                /* SECURITY_ACTION_DEMAND_CHOICE                (x12) */
10399 };
10400
10401 /*
10402  * Returns flags that includes all available security action associated to the handle.
10403  * @token: metadata token (either for a class or a method)
10404  * @image: image where resides the metadata.
10405  */
10406 static guint32
10407 mono_declsec_get_flags (MonoImage *image, guint32 token)
10408 {
10409         int index = mono_metadata_declsec_from_index (image, token);
10410         MonoTableInfo *t = &image->tables [MONO_TABLE_DECLSECURITY];
10411         guint32 result = 0;
10412         guint32 action;
10413         int i;
10414
10415         /* HasSecurity can be present for other, not specially encoded, attributes,
10416            e.g. SuppressUnmanagedCodeSecurityAttribute */
10417         if (index < 0)
10418                 return 0;
10419
10420         for (i = index; i < t->rows; i++) {
10421                 guint32 cols [MONO_DECL_SECURITY_SIZE];
10422
10423                 mono_metadata_decode_row (t, i, cols, MONO_DECL_SECURITY_SIZE);
10424                 if (cols [MONO_DECL_SECURITY_PARENT] != token)
10425                         break;
10426
10427                 action = cols [MONO_DECL_SECURITY_ACTION];
10428                 if ((action >= MONO_DECLSEC_ACTION_MIN) && (action <= MONO_DECLSEC_ACTION_MAX)) {
10429                         result |= declsec_flags_map [action];
10430                 } else {
10431                         g_assert_not_reached ();
10432                 }
10433         }
10434         return result;
10435 }
10436
10437 /*
10438  * Get the security actions (in the form of flags) associated with the specified method.
10439  *
10440  * @method: The method for which we want the declarative security flags.
10441  * Return the declarative security flags for the method (only).
10442  *
10443  * Note: To keep MonoMethod size down we do not cache the declarative security flags
10444  *       (except for the stack modifiers which are kept in the MonoJitInfo structure)
10445  */
10446 guint32
10447 mono_declsec_flags_from_method (MonoMethod *method)
10448 {
10449         if (method->flags & METHOD_ATTRIBUTE_HAS_SECURITY) {
10450                 /* FIXME: No cache (for the moment) */
10451                 guint32 idx = mono_method_get_index (method);
10452                 idx <<= MONO_HAS_DECL_SECURITY_BITS;
10453                 idx |= MONO_HAS_DECL_SECURITY_METHODDEF;
10454                 return mono_declsec_get_flags (method->klass->image, idx);
10455         }
10456         return 0;
10457 }
10458
10459 /*
10460  * Get the security actions (in the form of flags) associated with the specified class.
10461  *
10462  * @klass: The class for which we want the declarative security flags.
10463  * Return the declarative security flags for the class.
10464  *
10465  * Note: We cache the flags inside the MonoClass structure as this will get 
10466  *       called very often (at least for each method).
10467  */
10468 guint32
10469 mono_declsec_flags_from_class (MonoClass *klass)
10470 {
10471         if (klass->flags & TYPE_ATTRIBUTE_HAS_SECURITY) {
10472                 if (!klass->declsec_flags) {
10473                         guint32 idx = mono_metadata_token_index (klass->type_token);
10474                         idx <<= MONO_HAS_DECL_SECURITY_BITS;
10475                         idx |= MONO_HAS_DECL_SECURITY_TYPEDEF;
10476                         /* we cache the flags on classes */
10477                         klass->declsec_flags = mono_declsec_get_flags (klass->image, idx);
10478                 }
10479                 return klass->declsec_flags;
10480         }
10481         return 0;
10482 }
10483
10484 /*
10485  * Get the security actions (in the form of flags) associated with the specified assembly.
10486  *
10487  * @assembly: The assembly for which we want the declarative security flags.
10488  * Return the declarative security flags for the assembly.
10489  */
10490 guint32
10491 mono_declsec_flags_from_assembly (MonoAssembly *assembly)
10492 {
10493         guint32 idx = 1; /* there is only one assembly */
10494         idx <<= MONO_HAS_DECL_SECURITY_BITS;
10495         idx |= MONO_HAS_DECL_SECURITY_ASSEMBLY;
10496         return mono_declsec_get_flags (assembly->image, idx);
10497 }
10498
10499
10500 /*
10501  * Fill actions for the specific index (which may either be an encoded class token or
10502  * an encoded method token) from the metadata image.
10503  * Returns TRUE if some actions requiring code generation are present, FALSE otherwise.
10504  */
10505 static MonoBoolean
10506 fill_actions_from_index (MonoImage *image, guint32 token, MonoDeclSecurityActions* actions,
10507         guint32 id_std, guint32 id_noncas, guint32 id_choice)
10508 {
10509         MonoBoolean result = FALSE;
10510         MonoTableInfo *t;
10511         guint32 cols [MONO_DECL_SECURITY_SIZE];
10512         int index = mono_metadata_declsec_from_index (image, token);
10513         int i;
10514
10515         t  = &image->tables [MONO_TABLE_DECLSECURITY];
10516         for (i = index; i < t->rows; i++) {
10517                 mono_metadata_decode_row (t, i, cols, MONO_DECL_SECURITY_SIZE);
10518
10519                 if (cols [MONO_DECL_SECURITY_PARENT] != token)
10520                         return result;
10521
10522                 /* if present only replace (class) permissions with method permissions */
10523                 /* if empty accept either class or method permissions */
10524                 if (cols [MONO_DECL_SECURITY_ACTION] == id_std) {
10525                         if (!actions->demand.blob) {
10526                                 const char *blob = mono_metadata_blob_heap (image, cols [MONO_DECL_SECURITY_PERMISSIONSET]);
10527                                 actions->demand.index = cols [MONO_DECL_SECURITY_PERMISSIONSET];
10528                                 actions->demand.blob = (char*) (blob + 2);
10529                                 actions->demand.size = mono_metadata_decode_blob_size (blob, &blob);
10530                                 result = TRUE;
10531                         }
10532                 } else if (cols [MONO_DECL_SECURITY_ACTION] == id_noncas) {
10533                         if (!actions->noncasdemand.blob) {
10534                                 const char *blob = mono_metadata_blob_heap (image, cols [MONO_DECL_SECURITY_PERMISSIONSET]);
10535                                 actions->noncasdemand.index = cols [MONO_DECL_SECURITY_PERMISSIONSET];
10536                                 actions->noncasdemand.blob = (char*) (blob + 2);
10537                                 actions->noncasdemand.size = mono_metadata_decode_blob_size (blob, &blob);
10538                                 result = TRUE;
10539                         }
10540                 } else if (cols [MONO_DECL_SECURITY_ACTION] == id_choice) {
10541                         if (!actions->demandchoice.blob) {
10542                                 const char *blob = mono_metadata_blob_heap (image, cols [MONO_DECL_SECURITY_PERMISSIONSET]);
10543                                 actions->demandchoice.index = cols [MONO_DECL_SECURITY_PERMISSIONSET];
10544                                 actions->demandchoice.blob = (char*) (blob + 2);
10545                                 actions->demandchoice.size = mono_metadata_decode_blob_size (blob, &blob);
10546                                 result = TRUE;
10547                         }
10548                 }
10549         }
10550
10551         return result;
10552 }
10553
10554 static MonoBoolean
10555 mono_declsec_get_class_demands_params (MonoClass *klass, MonoDeclSecurityActions* demands, 
10556         guint32 id_std, guint32 id_noncas, guint32 id_choice)
10557 {
10558         guint32 idx = mono_metadata_token_index (klass->type_token);
10559         idx <<= MONO_HAS_DECL_SECURITY_BITS;
10560         idx |= MONO_HAS_DECL_SECURITY_TYPEDEF;
10561         return fill_actions_from_index (klass->image, idx, demands, id_std, id_noncas, id_choice);
10562 }
10563
10564 static MonoBoolean
10565 mono_declsec_get_method_demands_params (MonoMethod *method, MonoDeclSecurityActions* demands, 
10566         guint32 id_std, guint32 id_noncas, guint32 id_choice)
10567 {
10568         guint32 idx = mono_method_get_index (method);
10569         idx <<= MONO_HAS_DECL_SECURITY_BITS;
10570         idx |= MONO_HAS_DECL_SECURITY_METHODDEF;
10571         return fill_actions_from_index (method->klass->image, idx, demands, id_std, id_noncas, id_choice);
10572 }
10573
10574 /*
10575  * Collect all actions (that requires to generate code in mini) assigned for
10576  * the specified method.
10577  * Note: Don't use the content of actions if the function return FALSE.
10578  */
10579 MonoBoolean
10580 mono_declsec_get_demands (MonoMethod *method, MonoDeclSecurityActions* demands)
10581 {
10582         guint32 mask = MONO_DECLSEC_FLAG_DEMAND | MONO_DECLSEC_FLAG_NONCAS_DEMAND | 
10583                 MONO_DECLSEC_FLAG_DEMAND_CHOICE;
10584         MonoBoolean result = FALSE;
10585         guint32 flags;
10586
10587         /* quick exit if no declarative security is present in the metadata */
10588         if (!method->klass->image->tables [MONO_TABLE_DECLSECURITY].rows)
10589                 return FALSE;
10590
10591         /* we want the original as the wrapper is "free" of the security informations */
10592         if (method->wrapper_type == MONO_WRAPPER_MANAGED_TO_NATIVE || method->wrapper_type == MONO_WRAPPER_MANAGED_TO_MANAGED) {
10593                 method = mono_marshal_method_from_wrapper (method);
10594                 if (!method)
10595                         return FALSE;
10596         }
10597
10598         /* First we look for method-level attributes */
10599         if (method->flags & METHOD_ATTRIBUTE_HAS_SECURITY) {
10600                 mono_class_init (method->klass);
10601                 memset (demands, 0, sizeof (MonoDeclSecurityActions));
10602
10603                 result = mono_declsec_get_method_demands_params (method, demands, 
10604                         SECURITY_ACTION_DEMAND, SECURITY_ACTION_NONCASDEMAND, SECURITY_ACTION_DEMANDCHOICE);
10605         }
10606
10607         /* Here we use (or create) the class declarative cache to look for demands */
10608         flags = mono_declsec_flags_from_class (method->klass);
10609         if (flags & mask) {
10610                 if (!result) {
10611                         mono_class_init (method->klass);
10612                         memset (demands, 0, sizeof (MonoDeclSecurityActions));
10613                 }
10614                 result |= mono_declsec_get_class_demands_params (method->klass, demands, 
10615                         SECURITY_ACTION_DEMAND, SECURITY_ACTION_NONCASDEMAND, SECURITY_ACTION_DEMANDCHOICE);
10616         }
10617
10618         /* The boolean return value is used as a shortcut in case nothing needs to
10619            be generated (e.g. LinkDemand[Choice] and InheritanceDemand[Choice]) */
10620         return result;
10621 }
10622
10623
10624 /*
10625  * Collect all Link actions: LinkDemand, NonCasLinkDemand and LinkDemandChoice (2.0).
10626  *
10627  * Note: Don't use the content of actions if the function return FALSE.
10628  */
10629 MonoBoolean
10630 mono_declsec_get_linkdemands (MonoMethod *method, MonoDeclSecurityActions* klass, MonoDeclSecurityActions *cmethod)
10631 {
10632         MonoBoolean result = FALSE;
10633         guint32 flags;
10634
10635         /* quick exit if no declarative security is present in the metadata */
10636         if (!method->klass->image->tables [MONO_TABLE_DECLSECURITY].rows)
10637                 return FALSE;
10638
10639         /* we want the original as the wrapper is "free" of the security informations */
10640         if (method->wrapper_type == MONO_WRAPPER_MANAGED_TO_NATIVE || method->wrapper_type == MONO_WRAPPER_MANAGED_TO_MANAGED) {
10641                 method = mono_marshal_method_from_wrapper (method);
10642                 if (!method)
10643                         return FALSE;
10644         }
10645
10646         /* results are independant - zeroize both */
10647         memset (cmethod, 0, sizeof (MonoDeclSecurityActions));
10648         memset (klass, 0, sizeof (MonoDeclSecurityActions));
10649
10650         /* First we look for method-level attributes */
10651         if (method->flags & METHOD_ATTRIBUTE_HAS_SECURITY) {
10652                 mono_class_init (method->klass);
10653
10654                 result = mono_declsec_get_method_demands_params (method, cmethod, 
10655                         SECURITY_ACTION_LINKDEMAND, SECURITY_ACTION_NONCASLINKDEMAND, SECURITY_ACTION_LINKDEMANDCHOICE);
10656         }
10657
10658         /* Here we use (or create) the class declarative cache to look for demands */
10659         flags = mono_declsec_flags_from_class (method->klass);
10660         if (flags & (MONO_DECLSEC_FLAG_LINKDEMAND | MONO_DECLSEC_FLAG_NONCAS_LINKDEMAND | MONO_DECLSEC_FLAG_LINKDEMAND_CHOICE)) {
10661                 mono_class_init (method->klass);
10662
10663                 result |= mono_declsec_get_class_demands_params (method->klass, klass, 
10664                         SECURITY_ACTION_LINKDEMAND, SECURITY_ACTION_NONCASLINKDEMAND, SECURITY_ACTION_LINKDEMANDCHOICE);
10665         }
10666
10667         return result;
10668 }
10669
10670 /*
10671  * Collect all Inherit actions: InheritanceDemand, NonCasInheritanceDemand and InheritanceDemandChoice (2.0).
10672  *
10673  * @klass       The inherited class - this is the class that provides the security check (attributes)
10674  * @demans      
10675  * return TRUE if inheritance demands (any kind) are present, FALSE otherwise.
10676  * 
10677  * Note: Don't use the content of actions if the function return FALSE.
10678  */
10679 MonoBoolean
10680 mono_declsec_get_inheritdemands_class (MonoClass *klass, MonoDeclSecurityActions* demands)
10681 {
10682         MonoBoolean result = FALSE;
10683         guint32 flags;
10684
10685         /* quick exit if no declarative security is present in the metadata */
10686         if (!klass->image->tables [MONO_TABLE_DECLSECURITY].rows)
10687                 return FALSE;
10688
10689         /* Here we use (or create) the class declarative cache to look for demands */
10690         flags = mono_declsec_flags_from_class (klass);
10691         if (flags & (MONO_DECLSEC_FLAG_INHERITANCEDEMAND | MONO_DECLSEC_FLAG_NONCAS_INHERITANCEDEMAND | MONO_DECLSEC_FLAG_INHERITANCEDEMAND_CHOICE)) {
10692                 mono_class_init (klass);
10693                 memset (demands, 0, sizeof (MonoDeclSecurityActions));
10694
10695                 result |= mono_declsec_get_class_demands_params (klass, demands, 
10696                         SECURITY_ACTION_INHERITDEMAND, SECURITY_ACTION_NONCASINHERITANCE, SECURITY_ACTION_INHERITDEMANDCHOICE);
10697         }
10698
10699         return result;
10700 }
10701
10702 /*
10703  * Collect all Inherit actions: InheritanceDemand, NonCasInheritanceDemand and InheritanceDemandChoice (2.0).
10704  *
10705  * Note: Don't use the content of actions if the function return FALSE.
10706  */
10707 MonoBoolean
10708 mono_declsec_get_inheritdemands_method (MonoMethod *method, MonoDeclSecurityActions* demands)
10709 {
10710         /* quick exit if no declarative security is present in the metadata */
10711         if (!method->klass->image->tables [MONO_TABLE_DECLSECURITY].rows)
10712                 return FALSE;
10713
10714         /* we want the original as the wrapper is "free" of the security informations */
10715         if (method->wrapper_type == MONO_WRAPPER_MANAGED_TO_NATIVE || method->wrapper_type == MONO_WRAPPER_MANAGED_TO_MANAGED) {
10716                 method = mono_marshal_method_from_wrapper (method);
10717                 if (!method)
10718                         return FALSE;
10719         }
10720
10721         if (method->flags & METHOD_ATTRIBUTE_HAS_SECURITY) {
10722                 mono_class_init (method->klass);
10723                 memset (demands, 0, sizeof (MonoDeclSecurityActions));
10724
10725                 return mono_declsec_get_method_demands_params (method, demands, 
10726                         SECURITY_ACTION_INHERITDEMAND, SECURITY_ACTION_NONCASINHERITANCE, SECURITY_ACTION_INHERITDEMANDCHOICE);
10727         }
10728         return FALSE;
10729 }
10730
10731
10732 static MonoBoolean
10733 get_declsec_action (MonoImage *image, guint32 token, guint32 action, MonoDeclSecurityEntry *entry)
10734 {
10735         guint32 cols [MONO_DECL_SECURITY_SIZE];
10736         MonoTableInfo *t;
10737         int i;
10738
10739         int index = mono_metadata_declsec_from_index (image, token);
10740         if (index == -1)
10741                 return FALSE;
10742
10743         t =  &image->tables [MONO_TABLE_DECLSECURITY];
10744         for (i = index; i < t->rows; i++) {
10745                 mono_metadata_decode_row (t, i, cols, MONO_DECL_SECURITY_SIZE);
10746
10747                 /* shortcut - index are ordered */
10748                 if (token != cols [MONO_DECL_SECURITY_PARENT])
10749                         return FALSE;
10750
10751                 if (cols [MONO_DECL_SECURITY_ACTION] == action) {
10752                         const char *metadata = mono_metadata_blob_heap (image, cols [MONO_DECL_SECURITY_PERMISSIONSET]);
10753                         entry->blob = (char*) (metadata + 2);
10754                         entry->size = mono_metadata_decode_blob_size (metadata, &metadata);
10755                         return TRUE;
10756                 }
10757         }
10758
10759         return FALSE;
10760 }
10761
10762 MonoBoolean
10763 mono_declsec_get_method_action (MonoMethod *method, guint32 action, MonoDeclSecurityEntry *entry)
10764 {
10765         if (method->flags & METHOD_ATTRIBUTE_HAS_SECURITY) {
10766                 guint32 idx = mono_method_get_index (method);
10767                 idx <<= MONO_HAS_DECL_SECURITY_BITS;
10768                 idx |= MONO_HAS_DECL_SECURITY_METHODDEF;
10769                 return get_declsec_action (method->klass->image, idx, action, entry);
10770         }
10771         return FALSE;
10772 }
10773
10774 MonoBoolean
10775 mono_declsec_get_class_action (MonoClass *klass, guint32 action, MonoDeclSecurityEntry *entry)
10776 {
10777         /* use cache */
10778         guint32 flags = mono_declsec_flags_from_class (klass);
10779         if (declsec_flags_map [action] & flags) {
10780                 guint32 idx = mono_metadata_token_index (klass->type_token);
10781                 idx <<= MONO_HAS_DECL_SECURITY_BITS;
10782                 idx |= MONO_HAS_DECL_SECURITY_TYPEDEF;
10783                 return get_declsec_action (klass->image, idx, action, entry);
10784         }
10785         return FALSE;
10786 }
10787
10788 MonoBoolean
10789 mono_declsec_get_assembly_action (MonoAssembly *assembly, guint32 action, MonoDeclSecurityEntry *entry)
10790 {
10791         guint32 idx = 1; /* there is only one assembly */
10792         idx <<= MONO_HAS_DECL_SECURITY_BITS;
10793         idx |= MONO_HAS_DECL_SECURITY_ASSEMBLY;
10794
10795         return get_declsec_action (assembly->image, idx, action, entry);
10796 }
10797
10798 gboolean
10799 mono_reflection_call_is_assignable_to (MonoClass *klass, MonoClass *oklass)
10800 {
10801         MonoObject *res, *exc;
10802         void *params [1];
10803         static MonoClass *System_Reflection_Emit_TypeBuilder = NULL;
10804         static MonoMethod *method = NULL;
10805
10806         if (!System_Reflection_Emit_TypeBuilder) {
10807                 System_Reflection_Emit_TypeBuilder = mono_class_from_name (mono_defaults.corlib, "System.Reflection.Emit", "TypeBuilder");
10808                 g_assert (System_Reflection_Emit_TypeBuilder);
10809         }
10810         if (method == NULL) {
10811                 method = mono_class_get_method_from_name (System_Reflection_Emit_TypeBuilder, "IsAssignableTo", 1);
10812                 g_assert (method);
10813         }
10814
10815         /* 
10816          * The result of mono_type_get_object () might be a System.MonoType but we
10817          * need a TypeBuilder so use klass->reflection_info.
10818          */
10819         g_assert (klass->reflection_info);
10820         g_assert (!strcmp (((MonoObject*)(klass->reflection_info))->vtable->klass->name, "TypeBuilder"));
10821
10822         params [0] = mono_type_get_object (mono_domain_get (), &oklass->byval_arg);
10823
10824         res = mono_runtime_invoke (method, (MonoObject*)(klass->reflection_info), params, &exc);
10825         if (exc)
10826                 return FALSE;
10827         else
10828                 return *(MonoBoolean*)mono_object_unbox (res);
10829 }