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