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