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