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