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