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