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