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