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