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