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