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