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