cb51ca3a62be7465d103d3fc8bc803a62c5fe872
[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                         }
4862                         g_free (entry);
4863                 }
4864                 g_ptr_array_free (di->gen_params, TRUE);
4865         }
4866         if (di->token_fixups)
4867                 mono_g_hash_table_destroy (di->token_fixups);
4868         if (di->method_to_table_idx)
4869                 g_hash_table_destroy (di->method_to_table_idx);
4870         if (di->field_to_table_idx)
4871                 g_hash_table_destroy (di->field_to_table_idx);
4872         if (di->method_aux_hash)
4873                 g_hash_table_destroy (di->method_aux_hash);
4874         g_free (di->strong_name);
4875         g_free (di->win32_res);
4876         if (di->public_key)
4877                 g_free (di->public_key);
4878
4879         /*g_print ("string heap destroy for image %p\n", di);*/
4880         mono_dynamic_stream_reset (&di->sheap);
4881         mono_dynamic_stream_reset (&di->code);
4882         mono_dynamic_stream_reset (&di->resources);
4883         mono_dynamic_stream_reset (&di->us);
4884         mono_dynamic_stream_reset (&di->blob);
4885         mono_dynamic_stream_reset (&di->tstream);
4886         mono_dynamic_stream_reset (&di->guid);
4887         for (i = 0; i < MONO_TABLE_NUM; ++i) {
4888                 g_free (di->tables [i].values);
4889         }
4890 }       
4891
4892 #ifndef DISABLE_REFLECTION_EMIT
4893
4894 /*
4895  * mono_image_basic_init:
4896  * @assembly: an assembly builder object
4897  *
4898  * Create the MonoImage that represents the assembly builder and setup some
4899  * of the helper hash table and the basic metadata streams.
4900  */
4901 void
4902 mono_image_basic_init (MonoReflectionAssemblyBuilder *assemblyb)
4903 {
4904         MonoDynamicAssembly *assembly;
4905         MonoDynamicImage *image;
4906         MonoDomain *domain = mono_object_domain (assemblyb);
4907         
4908         MONO_ARCH_SAVE_REGS;
4909
4910         if (assemblyb->dynamic_assembly)
4911                 return;
4912
4913 #if HAVE_BOEHM_GC
4914         assembly = assemblyb->dynamic_assembly = GC_MALLOC (sizeof (MonoDynamicAssembly));
4915 #else
4916         assembly = assemblyb->dynamic_assembly = g_new0 (MonoDynamicAssembly, 1);
4917 #endif
4918
4919         mono_profiler_assembly_event (&assembly->assembly, MONO_PROFILE_START_LOAD);
4920         
4921         assembly->assembly.ref_count = 1;
4922         assembly->assembly.dynamic = TRUE;
4923         assembly->assembly.corlib_internal = assemblyb->corlib_internal;
4924         assemblyb->assembly.assembly = (MonoAssembly*)assembly;
4925         assembly->assembly.basedir = mono_string_to_utf8 (assemblyb->dir);
4926         if (assemblyb->culture)
4927                 assembly->assembly.aname.culture = mono_string_to_utf8 (assemblyb->culture);
4928         else
4929                 assembly->assembly.aname.culture = g_strdup ("");
4930
4931         if (assemblyb->version) {
4932                         char *vstr = mono_string_to_utf8 (assemblyb->version);
4933                         char **version = g_strsplit (vstr, ".", 4);
4934                         char **parts = version;
4935                         assembly->assembly.aname.major = atoi (*parts++);
4936                         assembly->assembly.aname.minor = atoi (*parts++);
4937                         assembly->assembly.aname.build = *parts != NULL ? atoi (*parts++) : 0;
4938                         assembly->assembly.aname.revision = *parts != NULL ? atoi (*parts) : 0;
4939
4940                         g_strfreev (version);
4941                         g_free (vstr);
4942         } else {
4943                         assembly->assembly.aname.major = 0;
4944                         assembly->assembly.aname.minor = 0;
4945                         assembly->assembly.aname.build = 0;
4946                         assembly->assembly.aname.revision = 0;
4947         }
4948
4949         assembly->run = assemblyb->access != 2;
4950         assembly->save = assemblyb->access != 1;
4951
4952         image = create_dynamic_mono_image (assembly, mono_string_to_utf8 (assemblyb->name), g_strdup ("RefEmit_YouForgotToDefineAModule"));
4953         image->initial_image = TRUE;
4954         assembly->assembly.aname.name = image->image.name;
4955         assembly->assembly.image = &image->image;
4956
4957         mono_domain_assemblies_lock (domain);
4958         domain->domain_assemblies = g_slist_prepend (domain->domain_assemblies, assembly);
4959         mono_domain_assemblies_unlock (domain);
4960
4961         register_assembly (mono_object_domain (assemblyb), &assemblyb->assembly, &assembly->assembly);
4962         
4963         mono_profiler_assembly_loaded (&assembly->assembly, MONO_PROFILE_OK);
4964         
4965         mono_assembly_invoke_load_hook ((MonoAssembly*)assembly);
4966 }
4967
4968 #endif /* DISABLE_REFLECTION_EMIT */
4969
4970 static int
4971 calc_section_size (MonoDynamicImage *assembly)
4972 {
4973         int nsections = 0;
4974
4975         /* alignment constraints */
4976         mono_image_add_stream_zero (&assembly->code, 4 - (assembly->code.index % 4));
4977         g_assert ((assembly->code.index % 4) == 0);
4978         assembly->meta_size += 3;
4979         assembly->meta_size &= ~3;
4980         mono_image_add_stream_zero (&assembly->resources, 4 - (assembly->resources.index % 4));
4981         g_assert ((assembly->resources.index % 4) == 0);
4982
4983         assembly->sections [MONO_SECTION_TEXT].size = assembly->meta_size + assembly->code.index + assembly->resources.index + assembly->strong_name_size;
4984         assembly->sections [MONO_SECTION_TEXT].attrs = SECT_FLAGS_HAS_CODE | SECT_FLAGS_MEM_EXECUTE | SECT_FLAGS_MEM_READ;
4985         nsections++;
4986
4987         if (assembly->win32_res) {
4988                 guint32 res_size = (assembly->win32_res_size + 3) & ~3;
4989
4990                 assembly->sections [MONO_SECTION_RSRC].size = res_size;
4991                 assembly->sections [MONO_SECTION_RSRC].attrs = SECT_FLAGS_HAS_INITIALIZED_DATA | SECT_FLAGS_MEM_READ;
4992                 nsections++;
4993         }
4994
4995         assembly->sections [MONO_SECTION_RELOC].size = 12;
4996         assembly->sections [MONO_SECTION_RELOC].attrs = SECT_FLAGS_MEM_READ | SECT_FLAGS_MEM_DISCARDABLE | SECT_FLAGS_HAS_INITIALIZED_DATA;
4997         nsections++;
4998
4999         return nsections;
5000 }
5001
5002 typedef struct {
5003         guint32 id;
5004         guint32 offset;
5005         GSList *children;
5006         MonoReflectionWin32Resource *win32_res; /* Only for leaf nodes */
5007 } ResTreeNode;
5008
5009 static int
5010 resource_tree_compare_by_id (gconstpointer a, gconstpointer b)
5011 {
5012         ResTreeNode *t1 = (ResTreeNode*)a;
5013         ResTreeNode *t2 = (ResTreeNode*)b;
5014
5015         return t1->id - t2->id;
5016 }
5017
5018 /*
5019  * resource_tree_create:
5020  *
5021  *  Organize the resources into a resource tree.
5022  */
5023 static ResTreeNode *
5024 resource_tree_create (MonoArray *win32_resources)
5025 {
5026         ResTreeNode *tree, *res_node, *type_node, *lang_node;
5027         GSList *l;
5028         int i;
5029
5030         tree = g_new0 (ResTreeNode, 1);
5031         
5032         for (i = 0; i < mono_array_length (win32_resources); ++i) {
5033                 MonoReflectionWin32Resource *win32_res =
5034                         (MonoReflectionWin32Resource*)mono_array_addr (win32_resources, MonoReflectionWin32Resource, i);
5035
5036                 /* Create node */
5037
5038                 /* FIXME: BUG: this stores managed references in unmanaged memory */
5039                 lang_node = g_new0 (ResTreeNode, 1);
5040                 lang_node->id = win32_res->lang_id;
5041                 lang_node->win32_res = win32_res;
5042
5043                 /* Create type node if neccesary */
5044                 type_node = NULL;
5045                 for (l = tree->children; l; l = l->next)
5046                         if (((ResTreeNode*)(l->data))->id == win32_res->res_type) {
5047                                 type_node = (ResTreeNode*)l->data;
5048                                 break;
5049                         }
5050
5051                 if (!type_node) {
5052                         type_node = g_new0 (ResTreeNode, 1);
5053                         type_node->id = win32_res->res_type;
5054
5055                         /* 
5056                          * The resource types have to be sorted otherwise
5057                          * Windows Explorer can't display the version information.
5058                          */
5059                         tree->children = g_slist_insert_sorted (tree->children, 
5060                                 type_node, resource_tree_compare_by_id);
5061                 }
5062
5063                 /* Create res node if neccesary */
5064                 res_node = NULL;
5065                 for (l = type_node->children; l; l = l->next)
5066                         if (((ResTreeNode*)(l->data))->id == win32_res->res_id) {
5067                                 res_node = (ResTreeNode*)l->data;
5068                                 break;
5069                         }
5070
5071                 if (!res_node) {
5072                         res_node = g_new0 (ResTreeNode, 1);
5073                         res_node->id = win32_res->res_id;
5074                         type_node->children = g_slist_append (type_node->children, res_node);
5075                 }
5076
5077                 res_node->children = g_slist_append (res_node->children, lang_node);
5078         }
5079
5080         return tree;
5081 }
5082
5083 /*
5084  * resource_tree_encode:
5085  * 
5086  *   Encode the resource tree into the format used in the PE file.
5087  */
5088 static void
5089 resource_tree_encode (ResTreeNode *node, char *begin, char *p, char **endbuf)
5090 {
5091         char *entries;
5092         MonoPEResourceDir dir;
5093         MonoPEResourceDirEntry dir_entry;
5094         MonoPEResourceDataEntry data_entry;
5095         GSList *l;
5096         guint32 res_id_entries;
5097
5098         /*
5099          * For the format of the resource directory, see the article
5100          * "An In-Depth Look into the Win32 Portable Executable File Format" by
5101          * Matt Pietrek
5102          */
5103
5104         memset (&dir, 0, sizeof (dir));
5105         memset (&dir_entry, 0, sizeof (dir_entry));
5106         memset (&data_entry, 0, sizeof (data_entry));
5107
5108         g_assert (sizeof (dir) == 16);
5109         g_assert (sizeof (dir_entry) == 8);
5110         g_assert (sizeof (data_entry) == 16);
5111
5112         node->offset = p - begin;
5113
5114         /* IMAGE_RESOURCE_DIRECTORY */
5115         res_id_entries = g_slist_length (node->children);
5116         dir.res_id_entries = GUINT16_TO_LE (res_id_entries);
5117
5118         memcpy (p, &dir, sizeof (dir));
5119         p += sizeof (dir);
5120
5121         /* Reserve space for entries */
5122         entries = p;
5123         p += sizeof (dir_entry) * res_id_entries;
5124
5125         /* Write children */
5126         for (l = node->children; l; l = l->next) {
5127                 ResTreeNode *child = (ResTreeNode*)l->data;
5128
5129                 if (child->win32_res) {
5130                         guint32 size;
5131
5132                         child->offset = p - begin;
5133
5134                         /* IMAGE_RESOURCE_DATA_ENTRY */
5135                         data_entry.rde_data_offset = GUINT32_TO_LE (p - begin + sizeof (data_entry));
5136                         size = mono_array_length (child->win32_res->res_data);
5137                         data_entry.rde_size = GUINT32_TO_LE (size);
5138
5139                         memcpy (p, &data_entry, sizeof (data_entry));
5140                         p += sizeof (data_entry);
5141
5142                         memcpy (p, mono_array_addr (child->win32_res->res_data, char, 0), size);
5143                         p += size;
5144                 } else {
5145                         resource_tree_encode (child, begin, p, &p);
5146                 }
5147         }
5148
5149         /* IMAGE_RESOURCE_ENTRY */
5150         for (l = node->children; l; l = l->next) {
5151                 ResTreeNode *child = (ResTreeNode*)l->data;
5152
5153                 MONO_PE_RES_DIR_ENTRY_SET_NAME (dir_entry, FALSE, child->id);
5154                 MONO_PE_RES_DIR_ENTRY_SET_DIR (dir_entry, !child->win32_res, child->offset);
5155
5156                 memcpy (entries, &dir_entry, sizeof (dir_entry));
5157                 entries += sizeof (dir_entry);
5158         }
5159
5160         *endbuf = p;
5161 }
5162
5163 static void
5164 resource_tree_free (ResTreeNode * node)
5165 {
5166         GSList * list;
5167         for (list = node->children; list; list = list->next)
5168                 resource_tree_free ((ResTreeNode*)list->data);
5169         g_slist_free(node->children);
5170         g_free (node);
5171 }
5172
5173 static void
5174 assembly_add_win32_resources (MonoDynamicImage *assembly, MonoReflectionAssemblyBuilder *assemblyb)
5175 {
5176         char *buf;
5177         char *p;
5178         guint32 size, i;
5179         MonoReflectionWin32Resource *win32_res;
5180         ResTreeNode *tree;
5181
5182         if (!assemblyb->win32_resources)
5183                 return;
5184
5185         /*
5186          * Resources are stored in a three level tree inside the PE file.
5187          * - level one contains a node for each type of resource
5188          * - level two contains a node for each resource
5189          * - level three contains a node for each instance of a resource for a
5190          *   specific language.
5191          */
5192
5193         tree = resource_tree_create (assemblyb->win32_resources);
5194
5195         /* Estimate the size of the encoded tree */
5196         size = 0;
5197         for (i = 0; i < mono_array_length (assemblyb->win32_resources); ++i) {
5198                 win32_res = (MonoReflectionWin32Resource*)mono_array_addr (assemblyb->win32_resources, MonoReflectionWin32Resource, i);
5199                 size += mono_array_length (win32_res->res_data);
5200         }
5201         /* Directory structure */
5202         size += mono_array_length (assemblyb->win32_resources) * 256;
5203         p = buf = g_malloc (size);
5204
5205         resource_tree_encode (tree, p, p, &p);
5206
5207         g_assert (p - buf <= size);
5208
5209         assembly->win32_res = g_malloc (p - buf);
5210         assembly->win32_res_size = p - buf;
5211         memcpy (assembly->win32_res, buf, p - buf);
5212
5213         g_free (buf);
5214         resource_tree_free (tree);
5215 }
5216
5217 static void
5218 fixup_resource_directory (char *res_section, char *p, guint32 rva)
5219 {
5220         MonoPEResourceDir *dir = (MonoPEResourceDir*)p;
5221         int i;
5222
5223         p += sizeof (MonoPEResourceDir);
5224         for (i = 0; i < GUINT16_FROM_LE (dir->res_named_entries) + GUINT16_FROM_LE (dir->res_id_entries); ++i) {
5225                 MonoPEResourceDirEntry *dir_entry = (MonoPEResourceDirEntry*)p;
5226                 char *child = res_section + MONO_PE_RES_DIR_ENTRY_DIR_OFFSET (*dir_entry);
5227                 if (MONO_PE_RES_DIR_ENTRY_IS_DIR (*dir_entry)) {
5228                         fixup_resource_directory (res_section, child, rva);
5229                 } else {
5230                         MonoPEResourceDataEntry *data_entry = (MonoPEResourceDataEntry*)child;
5231                         data_entry->rde_data_offset = GUINT32_TO_LE (GUINT32_FROM_LE (data_entry->rde_data_offset) + rva);
5232                 }
5233
5234                 p += sizeof (MonoPEResourceDirEntry);
5235         }
5236 }
5237
5238 static void
5239 checked_write_file (HANDLE f, gconstpointer buffer, guint32 numbytes)
5240 {
5241         guint32 dummy;
5242         if (!WriteFile (f, buffer, numbytes, &dummy, NULL))
5243                 g_error ("WriteFile returned %d\n", GetLastError ());
5244 }
5245
5246 #ifndef DISABLE_REFLECTION_EMIT_SAVE
5247
5248 /*
5249  * mono_image_create_pefile:
5250  * @mb: a module builder object
5251  * 
5252  * This function creates the PE-COFF header, the image sections, the CLI header  * etc. all the data is written in
5253  * assembly->pefile where it can be easily retrieved later in chunks.
5254  */
5255 void
5256 mono_image_create_pefile (MonoReflectionModuleBuilder *mb, HANDLE file)
5257 {
5258         MonoMSDOSHeader *msdos;
5259         MonoDotNetHeader *header;
5260         MonoSectionTable *section;
5261         MonoCLIHeader *cli_header;
5262         guint32 size, image_size, virtual_base, text_offset;
5263         guint32 header_start, section_start, file_offset, virtual_offset;
5264         MonoDynamicImage *assembly;
5265         MonoReflectionAssemblyBuilder *assemblyb;
5266         MonoDynamicStream pefile_stream = {0};
5267         MonoDynamicStream *pefile = &pefile_stream;
5268         int i, nsections;
5269         guint32 *rva, value;
5270         guchar *p;
5271         static const unsigned char msheader[] = {
5272                 0x4d, 0x5a, 0x90, 0x00, 0x03, 0x00, 0x00, 0x00,  0x04, 0x00, 0x00, 0x00, 0xff, 0xff, 0x00, 0x00,
5273                 0xb8, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,  0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
5274                 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
5275                 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,  0x00, 0x00, 0x00, 0x00, 0x80, 0x00, 0x00, 0x00,
5276                 0x0e, 0x1f, 0xba, 0x0e, 0x00, 0xb4, 0x09, 0xcd,  0x21, 0xb8, 0x01, 0x4c, 0xcd, 0x21, 0x54, 0x68,
5277                 0x69, 0x73, 0x20, 0x70, 0x72, 0x6f, 0x67, 0x72,  0x61, 0x6d, 0x20, 0x63, 0x61, 0x6e, 0x6e, 0x6f,
5278                 0x74, 0x20, 0x62, 0x65, 0x20, 0x72, 0x75, 0x6e,  0x20, 0x69, 0x6e, 0x20, 0x44, 0x4f, 0x53, 0x20,
5279                 0x6d, 0x6f, 0x64, 0x65, 0x2e, 0x0d, 0x0d, 0x0a,  0x24, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
5280         };
5281
5282         assemblyb = mb->assemblyb;
5283
5284         mono_image_basic_init (assemblyb);
5285         assembly = mb->dynamic_image;
5286
5287         assembly->pe_kind = assemblyb->pe_kind;
5288         assembly->machine = assemblyb->machine;
5289         ((MonoDynamicImage*)assemblyb->dynamic_assembly->assembly.image)->pe_kind = assemblyb->pe_kind;
5290         ((MonoDynamicImage*)assemblyb->dynamic_assembly->assembly.image)->machine = assemblyb->machine;
5291         
5292         mono_image_build_metadata (mb);
5293
5294         if (mb->is_main && assemblyb->resources) {
5295                 int len = mono_array_length (assemblyb->resources);
5296                 for (i = 0; i < len; ++i)
5297                         assembly_add_resource (mb, assembly, (MonoReflectionResource*)mono_array_addr (assemblyb->resources, MonoReflectionResource, i));
5298         }
5299
5300         if (mb->resources) {
5301                 int len = mono_array_length (mb->resources);
5302                 for (i = 0; i < len; ++i)
5303                         assembly_add_resource (mb, assembly, (MonoReflectionResource*)mono_array_addr (mb->resources, MonoReflectionResource, i));
5304         }
5305
5306         build_compressed_metadata (assembly);
5307
5308         if (mb->is_main)
5309                 assembly_add_win32_resources (assembly, assemblyb);
5310
5311         nsections = calc_section_size (assembly);
5312         
5313         /* The DOS header and stub */
5314         g_assert (sizeof (MonoMSDOSHeader) == sizeof (msheader));
5315         mono_image_add_stream_data (pefile, (char*)msheader, sizeof (msheader));
5316
5317         /* the dotnet header */
5318         header_start = mono_image_add_stream_zero (pefile, sizeof (MonoDotNetHeader));
5319
5320         /* the section tables */
5321         section_start = mono_image_add_stream_zero (pefile, sizeof (MonoSectionTable) * nsections);
5322
5323         file_offset = section_start + sizeof (MonoSectionTable) * nsections;
5324         virtual_offset = VIRT_ALIGN;
5325         image_size = 0;
5326
5327         for (i = 0; i < MONO_SECTION_MAX; ++i) {
5328                 if (!assembly->sections [i].size)
5329                         continue;
5330                 /* align offsets */
5331                 file_offset += FILE_ALIGN - 1;
5332                 file_offset &= ~(FILE_ALIGN - 1);
5333                 virtual_offset += VIRT_ALIGN - 1;
5334                 virtual_offset &= ~(VIRT_ALIGN - 1);
5335
5336                 assembly->sections [i].offset = file_offset;
5337                 assembly->sections [i].rva = virtual_offset;
5338
5339                 file_offset += assembly->sections [i].size;
5340                 virtual_offset += assembly->sections [i].size;
5341                 image_size += (assembly->sections [i].size + VIRT_ALIGN - 1) & ~(VIRT_ALIGN - 1);
5342         }
5343
5344         file_offset += FILE_ALIGN - 1;
5345         file_offset &= ~(FILE_ALIGN - 1);
5346
5347         image_size += section_start + sizeof (MonoSectionTable) * nsections;
5348
5349         /* back-patch info */
5350         msdos = (MonoMSDOSHeader*)pefile->data;
5351         msdos->pe_offset = GUINT32_FROM_LE (sizeof (MonoMSDOSHeader));
5352
5353         header = (MonoDotNetHeader*)(pefile->data + header_start);
5354         header->pesig [0] = 'P';
5355         header->pesig [1] = 'E';
5356         
5357         header->coff.coff_machine = GUINT16_FROM_LE (assemblyb->machine);
5358         header->coff.coff_sections = GUINT16_FROM_LE (nsections);
5359         header->coff.coff_time = GUINT32_FROM_LE (time (NULL));
5360         header->coff.coff_opt_header_size = GUINT16_FROM_LE (sizeof (MonoDotNetHeader) - sizeof (MonoCOFFHeader) - 4);
5361         if (assemblyb->pekind == 1) {
5362                 /* it's a dll */
5363                 header->coff.coff_attributes = GUINT16_FROM_LE (0x210e);
5364         } else {
5365                 /* it's an exe */
5366                 header->coff.coff_attributes = GUINT16_FROM_LE (0x010e);
5367         }
5368
5369         virtual_base = 0x400000; /* FIXME: 0x10000000 if a DLL */
5370
5371         header->pe.pe_magic = GUINT16_FROM_LE (0x10B);
5372         header->pe.pe_major = 6;
5373         header->pe.pe_minor = 0;
5374         size = assembly->sections [MONO_SECTION_TEXT].size;
5375         size += FILE_ALIGN - 1;
5376         size &= ~(FILE_ALIGN - 1);
5377         header->pe.pe_code_size = GUINT32_FROM_LE(size);
5378         size = assembly->sections [MONO_SECTION_RSRC].size;
5379         size += FILE_ALIGN - 1;
5380         size &= ~(FILE_ALIGN - 1);
5381         header->pe.pe_data_size = GUINT32_FROM_LE(size);
5382         g_assert (START_TEXT_RVA == assembly->sections [MONO_SECTION_TEXT].rva);
5383         header->pe.pe_rva_code_base = GUINT32_FROM_LE (assembly->sections [MONO_SECTION_TEXT].rva);
5384         header->pe.pe_rva_data_base = GUINT32_FROM_LE (assembly->sections [MONO_SECTION_RSRC].rva);
5385         /* pe_rva_entry_point always at the beginning of the text section */
5386         header->pe.pe_rva_entry_point = GUINT32_FROM_LE (assembly->sections [MONO_SECTION_TEXT].rva);
5387
5388         header->nt.pe_image_base = GUINT32_FROM_LE (virtual_base);
5389         header->nt.pe_section_align = GUINT32_FROM_LE (VIRT_ALIGN);
5390         header->nt.pe_file_alignment = GUINT32_FROM_LE (FILE_ALIGN);
5391         header->nt.pe_os_major = GUINT16_FROM_LE (4);
5392         header->nt.pe_os_minor = GUINT16_FROM_LE (0);
5393         header->nt.pe_subsys_major = GUINT16_FROM_LE (4);
5394         size = section_start;
5395         size += FILE_ALIGN - 1;
5396         size &= ~(FILE_ALIGN - 1);
5397         header->nt.pe_header_size = GUINT32_FROM_LE (size);
5398         size = image_size;
5399         size += VIRT_ALIGN - 1;
5400         size &= ~(VIRT_ALIGN - 1);
5401         header->nt.pe_image_size = GUINT32_FROM_LE (size);
5402
5403         /*
5404         // Translate the PEFileKind value to the value expected by the Windows loader
5405         */
5406         {
5407                 short kind;
5408
5409                 /*
5410                 // PEFileKinds.Dll == 1
5411                 // PEFileKinds.ConsoleApplication == 2
5412                 // PEFileKinds.WindowApplication == 3
5413                 //
5414                 // need to get:
5415                 //     IMAGE_SUBSYSTEM_WINDOWS_GUI 2 // Image runs in the Windows GUI subsystem.
5416                 //     IMAGE_SUBSYSTEM_WINDOWS_CUI 3 // Image runs in the Windows character subsystem.
5417                 */
5418                 if (assemblyb->pekind == 3)
5419                         kind = 2;
5420                 else
5421                         kind = 3;
5422                 
5423                 header->nt.pe_subsys_required = GUINT16_FROM_LE (kind);
5424         }    
5425         header->nt.pe_stack_reserve = GUINT32_FROM_LE (0x00100000);
5426         header->nt.pe_stack_commit = GUINT32_FROM_LE (0x00001000);
5427         header->nt.pe_heap_reserve = GUINT32_FROM_LE (0x00100000);
5428         header->nt.pe_heap_commit = GUINT32_FROM_LE (0x00001000);
5429         header->nt.pe_loader_flags = GUINT32_FROM_LE (0);
5430         header->nt.pe_data_dir_count = GUINT32_FROM_LE (16);
5431
5432         /* fill data directory entries */
5433
5434         header->datadir.pe_resource_table.size = GUINT32_FROM_LE (assembly->sections [MONO_SECTION_RSRC].size);
5435         header->datadir.pe_resource_table.rva = GUINT32_FROM_LE (assembly->sections [MONO_SECTION_RSRC].rva);
5436
5437         header->datadir.pe_reloc_table.size = GUINT32_FROM_LE (assembly->sections [MONO_SECTION_RELOC].size);
5438         header->datadir.pe_reloc_table.rva = GUINT32_FROM_LE (assembly->sections [MONO_SECTION_RELOC].rva);
5439
5440         header->datadir.pe_cli_header.size = GUINT32_FROM_LE (72);
5441         header->datadir.pe_cli_header.rva = GUINT32_FROM_LE (assembly->text_rva + assembly->cli_header_offset);
5442         header->datadir.pe_iat.size = GUINT32_FROM_LE (8);
5443         header->datadir.pe_iat.rva = GUINT32_FROM_LE (assembly->text_rva + assembly->iat_offset);
5444         /* patch entrypoint name */
5445         if (assemblyb->pekind == 1)
5446                 memcpy (assembly->code.data + assembly->imp_names_offset + 2, "_CorDllMain", 12);
5447         else
5448                 memcpy (assembly->code.data + assembly->imp_names_offset + 2, "_CorExeMain", 12);
5449         /* patch imported function RVA name */
5450         rva = (guint32*)(assembly->code.data + assembly->iat_offset);
5451         *rva = GUINT32_FROM_LE (assembly->text_rva + assembly->imp_names_offset);
5452
5453         /* the import table */
5454         header->datadir.pe_import_table.size = GUINT32_FROM_LE (79); /* FIXME: magic number? */
5455         header->datadir.pe_import_table.rva = GUINT32_FROM_LE (assembly->text_rva + assembly->idt_offset);
5456         /* patch imported dll RVA name and other entries in the dir */
5457         rva = (guint32*)(assembly->code.data + assembly->idt_offset + G_STRUCT_OFFSET (MonoIDT, name_rva));
5458         *rva = GUINT32_FROM_LE (assembly->text_rva + assembly->imp_names_offset + 14); /* 14 is hint+strlen+1 of func name */
5459         rva = (guint32*)(assembly->code.data + assembly->idt_offset + G_STRUCT_OFFSET (MonoIDT, import_address_table_rva));
5460         *rva = GUINT32_FROM_LE (assembly->text_rva + assembly->iat_offset);
5461         rva = (guint32*)(assembly->code.data + assembly->idt_offset + G_STRUCT_OFFSET (MonoIDT, import_lookup_table));
5462         *rva = GUINT32_FROM_LE (assembly->text_rva + assembly->ilt_offset);
5463
5464         p = (guchar*)(assembly->code.data + assembly->ilt_offset);
5465         value = (assembly->text_rva + assembly->imp_names_offset);
5466         *p++ = (value) & 0xff;
5467         *p++ = (value >> 8) & (0xff);
5468         *p++ = (value >> 16) & (0xff);
5469         *p++ = (value >> 24) & (0xff);
5470
5471         /* the CLI header info */
5472         cli_header = (MonoCLIHeader*)(assembly->code.data + assembly->cli_header_offset);
5473         cli_header->ch_size = GUINT32_FROM_LE (72);
5474         cli_header->ch_runtime_major = GUINT16_FROM_LE (2);
5475         if (mono_framework_version () > 1)
5476                 cli_header->ch_runtime_minor = GUINT16_FROM_LE (5);
5477         else 
5478                 cli_header->ch_runtime_minor = GUINT16_FROM_LE (0);
5479         cli_header->ch_flags = GUINT32_FROM_LE (assemblyb->pe_kind);
5480         if (assemblyb->entry_point) {
5481                 guint32 table_idx = 0;
5482                 if (!strcmp (assemblyb->entry_point->object.vtable->klass->name, "MethodBuilder")) {
5483                         MonoReflectionMethodBuilder *methodb = (MonoReflectionMethodBuilder*)assemblyb->entry_point;
5484                         table_idx = methodb->table_idx;
5485                 } else {
5486                         table_idx = GPOINTER_TO_UINT (g_hash_table_lookup (assembly->method_to_table_idx, assemblyb->entry_point->method));
5487                 }
5488                 cli_header->ch_entry_point = GUINT32_FROM_LE (table_idx | MONO_TOKEN_METHOD_DEF);
5489         } else {
5490                 cli_header->ch_entry_point = GUINT32_FROM_LE (0);
5491         }
5492         /* The embedded managed resources */
5493         text_offset = assembly->text_rva + assembly->code.index;
5494         cli_header->ch_resources.rva = GUINT32_FROM_LE (text_offset);
5495         cli_header->ch_resources.size = GUINT32_FROM_LE (assembly->resources.index);
5496         text_offset += assembly->resources.index;
5497         cli_header->ch_metadata.rva = GUINT32_FROM_LE (text_offset);
5498         cli_header->ch_metadata.size = GUINT32_FROM_LE (assembly->meta_size);
5499         text_offset += assembly->meta_size;
5500         if (assembly->strong_name_size) {
5501                 cli_header->ch_strong_name.rva = GUINT32_FROM_LE (text_offset);
5502                 cli_header->ch_strong_name.size = GUINT32_FROM_LE (assembly->strong_name_size);
5503                 text_offset += assembly->strong_name_size;
5504         }
5505
5506         /* write the section tables and section content */
5507         section = (MonoSectionTable*)(pefile->data + section_start);
5508         for (i = 0; i < MONO_SECTION_MAX; ++i) {
5509                 static const char section_names [][7] = {
5510                         ".text", ".rsrc", ".reloc"
5511                 };
5512                 if (!assembly->sections [i].size)
5513                         continue;
5514                 strcpy (section->st_name, section_names [i]);
5515                 /*g_print ("output section %s (%d), size: %d\n", section->st_name, i, assembly->sections [i].size);*/
5516                 section->st_virtual_address = GUINT32_FROM_LE (assembly->sections [i].rva);
5517                 section->st_virtual_size = GUINT32_FROM_LE (assembly->sections [i].size);
5518                 section->st_raw_data_size = GUINT32_FROM_LE (GUINT32_TO_LE (section->st_virtual_size) + (FILE_ALIGN - 1));
5519                 section->st_raw_data_size &= GUINT32_FROM_LE (~(FILE_ALIGN - 1));
5520                 section->st_raw_data_ptr = GUINT32_FROM_LE (assembly->sections [i].offset);
5521                 section->st_flags = GUINT32_FROM_LE (assembly->sections [i].attrs);
5522                 section ++;
5523         }
5524         
5525         checked_write_file (file, pefile->data, pefile->index);
5526         
5527         mono_dynamic_stream_reset (pefile);
5528         
5529         for (i = 0; i < MONO_SECTION_MAX; ++i) {
5530                 if (!assembly->sections [i].size)
5531                         continue;
5532                 
5533                 if (SetFilePointer (file, assembly->sections [i].offset, NULL, FILE_BEGIN) == INVALID_SET_FILE_POINTER)
5534                         g_error ("SetFilePointer returned %d\n", GetLastError ());
5535                 
5536                 switch (i) {
5537                 case MONO_SECTION_TEXT:
5538                         /* patch entry point */
5539                         p = (guchar*)(assembly->code.data + 2);
5540                         value = (virtual_base + assembly->text_rva + assembly->iat_offset);
5541                         *p++ = (value) & 0xff;
5542                         *p++ = (value >> 8) & 0xff;
5543                         *p++ = (value >> 16) & 0xff;
5544                         *p++ = (value >> 24) & 0xff;
5545                 
5546                         checked_write_file (file, assembly->code.data, assembly->code.index);
5547                         checked_write_file (file, assembly->resources.data, assembly->resources.index);
5548                         checked_write_file (file, assembly->image.raw_metadata, assembly->meta_size);
5549                         checked_write_file (file, assembly->strong_name, assembly->strong_name_size);
5550                                 
5551
5552                         g_free (assembly->image.raw_metadata);
5553                         break;
5554                 case MONO_SECTION_RELOC: {
5555                         struct {
5556                                 guint32 page_rva;
5557                                 guint32 block_size;
5558                                 guint16 type_and_offset;
5559                                 guint16 term;
5560                         } reloc;
5561                         
5562                         g_assert (sizeof (reloc) == 12);
5563                         
5564                         reloc.page_rva = GUINT32_FROM_LE (assembly->text_rva);
5565                         reloc.block_size = GUINT32_FROM_LE (12);
5566                         
5567                         /* 
5568                          * the entrypoint is always at the start of the text section 
5569                          * 3 is IMAGE_REL_BASED_HIGHLOW
5570                          * 2 is patch_size_rva - text_rva
5571                          */
5572                         reloc.type_and_offset = GUINT16_FROM_LE ((3 << 12) + (2));
5573                         reloc.term = 0;
5574                         
5575                         checked_write_file (file, &reloc, sizeof (reloc));
5576                         
5577                         break;
5578                 }
5579                 case MONO_SECTION_RSRC:
5580                         if (assembly->win32_res) {
5581
5582                                 /* Fixup the offsets in the IMAGE_RESOURCE_DATA_ENTRY structures */
5583                                 fixup_resource_directory (assembly->win32_res, assembly->win32_res, assembly->sections [i].rva);
5584                                 checked_write_file (file, assembly->win32_res, assembly->win32_res_size);
5585                         }
5586                         break;
5587                 default:
5588                         g_assert_not_reached ();
5589                 }
5590         }
5591         
5592         /* check that the file is properly padded */
5593         if (SetFilePointer (file, file_offset, NULL, FILE_BEGIN) == INVALID_SET_FILE_POINTER)
5594                 g_error ("SetFilePointer returned %d\n", GetLastError ());
5595         if (! SetEndOfFile (file))
5596                 g_error ("SetEndOfFile returned %d\n", GetLastError ());
5597         
5598         mono_dynamic_stream_reset (&assembly->code);
5599         mono_dynamic_stream_reset (&assembly->us);
5600         mono_dynamic_stream_reset (&assembly->blob);
5601         mono_dynamic_stream_reset (&assembly->guid);
5602         mono_dynamic_stream_reset (&assembly->sheap);
5603
5604         g_hash_table_foreach (assembly->blob_cache, (GHFunc)g_free, NULL);
5605         g_hash_table_destroy (assembly->blob_cache);
5606         assembly->blob_cache = NULL;
5607 }
5608
5609 #else /* DISABLE_REFLECTION_EMIT_SAVE */
5610
5611 void
5612 mono_image_create_pefile (MonoReflectionModuleBuilder *mb, HANDLE file)
5613 {
5614         g_assert_not_reached ();
5615 }
5616
5617 #endif /* DISABLE_REFLECTION_EMIT_SAVE */
5618
5619 #ifndef DISABLE_REFLECTION_EMIT
5620
5621 MonoReflectionModule *
5622 mono_image_load_module_dynamic (MonoReflectionAssemblyBuilder *ab, MonoString *fileName)
5623 {
5624         char *name;
5625         MonoImage *image;
5626         MonoImageOpenStatus status;
5627         MonoDynamicAssembly *assembly;
5628         guint32 module_count;
5629         MonoImage **new_modules;
5630         gboolean *new_modules_loaded;
5631         
5632         name = mono_string_to_utf8 (fileName);
5633
5634         image = mono_image_open (name, &status);
5635         if (!image) {
5636                 MonoException *exc;
5637                 if (status == MONO_IMAGE_ERROR_ERRNO)
5638                         exc = mono_get_exception_file_not_found (fileName);
5639                 else
5640                         exc = mono_get_exception_bad_image_format (name);
5641                 g_free (name);
5642                 mono_raise_exception (exc);
5643         }
5644
5645         g_free (name);
5646
5647         assembly = ab->dynamic_assembly;
5648         image->assembly = (MonoAssembly*)assembly;
5649
5650         module_count = image->assembly->image->module_count;
5651         new_modules = g_new0 (MonoImage *, module_count + 1);
5652         new_modules_loaded = g_new0 (gboolean, module_count + 1);
5653
5654         if (image->assembly->image->modules)
5655                 memcpy (new_modules, image->assembly->image->modules, module_count * sizeof (MonoImage *));
5656         if (image->assembly->image->modules_loaded)
5657                 memcpy (new_modules_loaded, image->assembly->image->modules_loaded, module_count * sizeof (gboolean));
5658         new_modules [module_count] = image;
5659         new_modules_loaded [module_count] = TRUE;
5660         mono_image_addref (image);
5661
5662         g_free (image->assembly->image->modules);
5663         image->assembly->image->modules = new_modules;
5664         image->assembly->image->modules_loaded = new_modules_loaded;
5665         image->assembly->image->module_count ++;
5666
5667         mono_assembly_load_references (image, &status);
5668         if (status) {
5669                 mono_image_close (image);
5670                 mono_raise_exception (mono_get_exception_file_not_found (fileName));
5671         }
5672
5673         return mono_module_get_object (mono_domain_get (), image);
5674 }
5675
5676 #endif /* DISABLE_REFLECTION_EMIT */
5677
5678 /*
5679  * We need to return always the same object for MethodInfo, FieldInfo etc..
5680  * but we need to consider the reflected type.
5681  * type uses a different hash, since it uses custom hash/equal functions.
5682  */
5683
5684 typedef struct {
5685         gpointer item;
5686         MonoClass *refclass;
5687 } ReflectedEntry;
5688
5689 static gboolean
5690 reflected_equal (gconstpointer a, gconstpointer b) {
5691         const ReflectedEntry *ea = a;
5692         const ReflectedEntry *eb = b;
5693
5694         return (ea->item == eb->item) && (ea->refclass == eb->refclass);
5695 }
5696
5697 static guint
5698 reflected_hash (gconstpointer a) {
5699         const ReflectedEntry *ea = a;
5700         return mono_aligned_addr_hash (ea->item);
5701 }
5702
5703 #define CHECK_OBJECT(t,p,k)     \
5704         do {    \
5705                 t _obj; \
5706                 ReflectedEntry e;       \
5707                 e.item = (p);   \
5708                 e.refclass = (k);       \
5709                 mono_domain_lock (domain);      \
5710                 if (!domain->refobject_hash)    \
5711                         domain->refobject_hash = mono_g_hash_table_new_type (reflected_hash, reflected_equal, MONO_HASH_VALUE_GC);      \
5712                 if ((_obj = mono_g_hash_table_lookup (domain->refobject_hash, &e))) {   \
5713                         mono_domain_unlock (domain);    \
5714                         return _obj;    \
5715                 }       \
5716         mono_domain_unlock (domain); \
5717         } while (0)
5718
5719 #ifdef HAVE_BOEHM_GC
5720 #define ALLOC_REFENTRY mono_gc_alloc_fixed (sizeof (ReflectedEntry), NULL)
5721 #else
5722 #define ALLOC_REFENTRY mono_mempool_alloc (domain->mp, sizeof (ReflectedEntry))
5723 #endif
5724
5725 #define CACHE_OBJECT(t,p,o,k)   \
5726         do {    \
5727                 t _obj; \
5728         ReflectedEntry pe; \
5729         pe.item = (p); \
5730         pe.refclass = (k); \
5731         mono_domain_lock (domain); \
5732                 if (!domain->refobject_hash)    \
5733                         domain->refobject_hash = mono_g_hash_table_new_type (reflected_hash, reflected_equal, MONO_HASH_VALUE_GC);      \
5734         _obj = mono_g_hash_table_lookup (domain->refobject_hash, &pe); \
5735         if (!_obj) { \
5736                     ReflectedEntry *e = ALLOC_REFENTRY;         \
5737                     e->item = (p);      \
5738                     e->refclass = (k);  \
5739                     mono_g_hash_table_insert (domain->refobject_hash, e,o);     \
5740             _obj = o; \
5741         } \
5742                 mono_domain_unlock (domain);    \
5743         return _obj; \
5744         } while (0)
5745
5746 static gpointer
5747 register_assembly (MonoDomain *domain, MonoReflectionAssembly *res, MonoAssembly *assembly)
5748 {
5749         CACHE_OBJECT (MonoReflectionAssembly *, assembly, res, NULL);
5750 }
5751
5752 static gpointer
5753 register_module (MonoDomain *domain, MonoReflectionModuleBuilder *res, MonoDynamicImage *module)
5754 {
5755         CACHE_OBJECT (MonoReflectionModuleBuilder *, module, res, NULL);
5756 }
5757
5758 #ifndef DISABLE_REFLECTION_EMIT
5759
5760 void
5761 mono_image_module_basic_init (MonoReflectionModuleBuilder *moduleb)
5762 {
5763         MonoDynamicImage *image = moduleb->dynamic_image;
5764         MonoReflectionAssemblyBuilder *ab = moduleb->assemblyb;
5765         if (!image) {
5766                 int module_count;
5767                 MonoImage **new_modules;
5768                 MonoImage *ass;
5769                 /*
5770                  * FIXME: we already created an image in mono_image_basic_init (), but
5771                  * we don't know which module it belongs to, since that is only 
5772                  * determined at assembly save time.
5773                  */
5774                 /*image = (MonoDynamicImage*)ab->dynamic_assembly->assembly.image; */
5775                 image = create_dynamic_mono_image (ab->dynamic_assembly, mono_string_to_utf8 (ab->name), mono_string_to_utf8 (moduleb->module.fqname));
5776
5777                 moduleb->module.image = &image->image;
5778                 moduleb->dynamic_image = image;
5779                 register_module (mono_object_domain (moduleb), moduleb, image);
5780
5781                 /* register the module with the assembly */
5782                 ass = ab->dynamic_assembly->assembly.image;
5783                 module_count = ass->module_count;
5784                 new_modules = g_new0 (MonoImage *, module_count + 1);
5785
5786                 if (ass->modules)
5787                         memcpy (new_modules, ass->modules, module_count * sizeof (MonoImage *));
5788                 new_modules [module_count] = &image->image;
5789                 mono_image_addref (&image->image);
5790
5791                 g_free (ass->modules);
5792                 ass->modules = new_modules;
5793                 ass->module_count ++;
5794         }
5795 }
5796
5797 #endif
5798
5799 /*
5800  * mono_assembly_get_object:
5801  * @domain: an app domain
5802  * @assembly: an assembly
5803  *
5804  * Return an System.Reflection.Assembly object representing the MonoAssembly @assembly.
5805  */
5806 MonoReflectionAssembly*
5807 mono_assembly_get_object (MonoDomain *domain, MonoAssembly *assembly)
5808 {
5809         static MonoClass *System_Reflection_Assembly;
5810         MonoReflectionAssembly *res;
5811         
5812         CHECK_OBJECT (MonoReflectionAssembly *, assembly, NULL);
5813         if (!System_Reflection_Assembly)
5814                 System_Reflection_Assembly = mono_class_from_name (
5815                         mono_defaults.corlib, "System.Reflection", "Assembly");
5816         res = (MonoReflectionAssembly *)mono_object_new (domain, System_Reflection_Assembly);
5817         res->assembly = assembly;
5818
5819         CACHE_OBJECT (MonoReflectionAssembly *, assembly, res, NULL);
5820 }
5821
5822
5823
5824 MonoReflectionModule*   
5825 mono_module_get_object   (MonoDomain *domain, MonoImage *image)
5826 {
5827         static MonoClass *System_Reflection_Module;
5828         MonoReflectionModule *res;
5829         char* basename;
5830         
5831         CHECK_OBJECT (MonoReflectionModule *, image, NULL);
5832         if (!System_Reflection_Module)
5833                 System_Reflection_Module = mono_class_from_name (
5834                         mono_defaults.corlib, "System.Reflection", "Module");
5835         res = (MonoReflectionModule *)mono_object_new (domain, System_Reflection_Module);
5836
5837         res->image = image;
5838         MONO_OBJECT_SETREF (res, assembly, (MonoReflectionAssembly *) mono_assembly_get_object(domain, image->assembly));
5839
5840         MONO_OBJECT_SETREF (res, fqname, mono_string_new (domain, image->name));
5841         basename = g_path_get_basename (image->name);
5842         MONO_OBJECT_SETREF (res, name, mono_string_new (domain, basename));
5843         MONO_OBJECT_SETREF (res, scopename, mono_string_new (domain, image->module_name));
5844         
5845         g_free (basename);
5846
5847         if (image->assembly->image == image) {
5848                 res->token = mono_metadata_make_token (MONO_TABLE_MODULE, 1);
5849         } else {
5850                 int i;
5851                 res->token = 0;
5852                 if (image->assembly->image->modules) {
5853                         for (i = 0; i < image->assembly->image->module_count; i++) {
5854                                 if (image->assembly->image->modules [i] == image)
5855                                         res->token = mono_metadata_make_token (MONO_TABLE_MODULEREF, i + 1);
5856                         }
5857                         g_assert (res->token);
5858                 }
5859         }
5860
5861         CACHE_OBJECT (MonoReflectionModule *, image, res, NULL);
5862 }
5863
5864 MonoReflectionModule*   
5865 mono_module_file_get_object (MonoDomain *domain, MonoImage *image, int table_index)
5866 {
5867         static MonoClass *System_Reflection_Module;
5868         MonoReflectionModule *res;
5869         MonoTableInfo *table;
5870         guint32 cols [MONO_FILE_SIZE];
5871         const char *name;
5872         guint32 i, name_idx;
5873         const char *val;
5874         
5875         if (!System_Reflection_Module)
5876                 System_Reflection_Module = mono_class_from_name (
5877                         mono_defaults.corlib, "System.Reflection", "Module");
5878         res = (MonoReflectionModule *)mono_object_new (domain, System_Reflection_Module);
5879
5880         table = &image->tables [MONO_TABLE_FILE];
5881         g_assert (table_index < table->rows);
5882         mono_metadata_decode_row (table, table_index, cols, MONO_FILE_SIZE);
5883
5884         res->image = NULL;
5885         MONO_OBJECT_SETREF (res, assembly, (MonoReflectionAssembly *) mono_assembly_get_object(domain, image->assembly));
5886         name = mono_metadata_string_heap (image, cols [MONO_FILE_NAME]);
5887
5888         /* Check whenever the row has a corresponding row in the moduleref table */
5889         table = &image->tables [MONO_TABLE_MODULEREF];
5890         for (i = 0; i < table->rows; ++i) {
5891                 name_idx = mono_metadata_decode_row_col (table, i, MONO_MODULEREF_NAME);
5892                 val = mono_metadata_string_heap (image, name_idx);
5893                 if (strcmp (val, name) == 0)
5894                         res->image = image->modules [i];
5895         }
5896
5897         MONO_OBJECT_SETREF (res, fqname, mono_string_new (domain, name));
5898         MONO_OBJECT_SETREF (res, name, mono_string_new (domain, name));
5899         MONO_OBJECT_SETREF (res, scopename, mono_string_new (domain, name));
5900         res->is_resource = cols [MONO_FILE_FLAGS] && FILE_CONTAINS_NO_METADATA;
5901         res->token = mono_metadata_make_token (MONO_TABLE_FILE, table_index + 1);
5902
5903         return res;
5904 }
5905
5906 static gboolean
5907 mymono_metadata_type_equal (MonoType *t1, MonoType *t2)
5908 {
5909         if ((t1->type != t2->type) ||
5910             (t1->byref != t2->byref))
5911                 return FALSE;
5912
5913         switch (t1->type) {
5914         case MONO_TYPE_VOID:
5915         case MONO_TYPE_BOOLEAN:
5916         case MONO_TYPE_CHAR:
5917         case MONO_TYPE_I1:
5918         case MONO_TYPE_U1:
5919         case MONO_TYPE_I2:
5920         case MONO_TYPE_U2:
5921         case MONO_TYPE_I4:
5922         case MONO_TYPE_U4:
5923         case MONO_TYPE_I8:
5924         case MONO_TYPE_U8:
5925         case MONO_TYPE_R4:
5926         case MONO_TYPE_R8:
5927         case MONO_TYPE_STRING:
5928         case MONO_TYPE_I:
5929         case MONO_TYPE_U:
5930         case MONO_TYPE_OBJECT:
5931         case MONO_TYPE_TYPEDBYREF:
5932                 return TRUE;
5933         case MONO_TYPE_VALUETYPE:
5934         case MONO_TYPE_CLASS:
5935         case MONO_TYPE_SZARRAY:
5936                 return t1->data.klass == t2->data.klass;
5937         case MONO_TYPE_PTR:
5938                 return mymono_metadata_type_equal (t1->data.type, t2->data.type);
5939         case MONO_TYPE_ARRAY:
5940                 if (t1->data.array->rank != t2->data.array->rank)
5941                         return FALSE;
5942                 return t1->data.array->eklass == t2->data.array->eklass;
5943         case MONO_TYPE_GENERICINST: {
5944                 int i;
5945                 MonoGenericInst *i1 = t1->data.generic_class->context.class_inst;
5946                 MonoGenericInst *i2 = t2->data.generic_class->context.class_inst;
5947                 if (i1->type_argc != i2->type_argc)
5948                         return FALSE;
5949                 if (!mono_metadata_type_equal (&t1->data.generic_class->container_class->byval_arg,
5950                                                &t2->data.generic_class->container_class->byval_arg))
5951                         return FALSE;
5952                 /* FIXME: we should probably just compare the instance pointers directly.  */
5953                 for (i = 0; i < i1->type_argc; ++i) {
5954                         if (!mono_metadata_type_equal (i1->type_argv [i], i2->type_argv [i]))
5955                                 return FALSE;
5956                 }
5957                 return TRUE;
5958         }
5959         case MONO_TYPE_VAR:
5960         case MONO_TYPE_MVAR:
5961                 return t1->data.generic_param == t2->data.generic_param;
5962         default:
5963                 g_error ("implement type compare for %0x!", t1->type);
5964                 return FALSE;
5965         }
5966
5967         return FALSE;
5968 }
5969
5970 static guint
5971 mymono_metadata_type_hash (MonoType *t1)
5972 {
5973         guint hash;
5974
5975         hash = t1->type;
5976
5977         hash |= t1->byref << 6; /* do not collide with t1->type values */
5978         switch (t1->type) {
5979         case MONO_TYPE_VALUETYPE:
5980         case MONO_TYPE_CLASS:
5981         case MONO_TYPE_SZARRAY:
5982                 /* check if the distribution is good enough */
5983                 return ((hash << 5) - hash) ^ g_str_hash (t1->data.klass->name);
5984         case MONO_TYPE_PTR:
5985                 return ((hash << 5) - hash) ^ mymono_metadata_type_hash (t1->data.type);
5986         case MONO_TYPE_GENERICINST: {
5987                 int i;
5988                 MonoGenericInst *inst = t1->data.generic_class->context.class_inst;
5989                 hash += g_str_hash (t1->data.generic_class->container_class->name);
5990                 hash *= 13;
5991                 for (i = 0; i < inst->type_argc; ++i) {
5992                         hash += mymono_metadata_type_hash (inst->type_argv [i]);
5993                         hash *= 13;
5994                 }
5995                 return hash;
5996         }
5997         }
5998         return hash;
5999 }
6000
6001 static MonoReflectionGenericClass*
6002 mono_generic_class_get_object (MonoDomain *domain, MonoType *geninst)
6003 {
6004         static MonoClass *System_Reflection_MonoGenericClass;
6005         MonoReflectionGenericClass *res;
6006         MonoClass *klass, *gklass;
6007
6008         if (!System_Reflection_MonoGenericClass) {
6009                 System_Reflection_MonoGenericClass = mono_class_from_name (
6010                         mono_defaults.corlib, "System.Reflection", "MonoGenericClass");
6011                 g_assert (System_Reflection_MonoGenericClass);
6012         }
6013
6014         klass = mono_class_from_mono_type (geninst);
6015         gklass = klass->generic_class->container_class;
6016
6017         mono_class_init (klass);
6018
6019 #ifdef HAVE_SGEN_GC
6020         res = (MonoReflectionGenericClass *) mono_gc_alloc_pinned_obj (mono_class_vtable (domain, System_Reflection_MonoGenericClass), mono_class_instance_size (System_Reflection_MonoGenericClass));
6021 #else
6022         res = (MonoReflectionGenericClass *) mono_object_new (domain, System_Reflection_MonoGenericClass);
6023 #endif
6024
6025         res->type.type = geninst;
6026         g_assert (gklass->reflection_info);
6027         g_assert (!strcmp (((MonoObject*)gklass->reflection_info)->vtable->klass->name, "TypeBuilder"));
6028         MONO_OBJECT_SETREF (res, generic_type, gklass->reflection_info);
6029
6030         return res;
6031 }
6032
6033 static gboolean
6034 verify_safe_for_managed_space (MonoType *type)
6035 {
6036         switch (type->type) {
6037 #ifdef DEBUG_HARDER
6038         case MONO_TYPE_ARRAY:
6039                 return verify_safe_for_managed_space (&type->data.array->eklass->byval_arg);
6040         case MONO_TYPE_PTR:
6041                 return verify_safe_for_managed_space (type->data.type);
6042         case MONO_TYPE_SZARRAY:
6043                 return verify_safe_for_managed_space (&type->data.klass->byval_arg);
6044         case MONO_TYPE_GENERICINST: {
6045                 MonoGenericInst *inst = type->data.generic_class->inst;
6046                 int i;
6047                 if (!inst->is_open)
6048                         break;
6049                 for (i = 0; i < inst->type_argc; ++i)
6050                         if (!verify_safe_for_managed_space (inst->type_argv [i]))
6051                                 return FALSE;
6052                 break;
6053         }
6054 #endif
6055         case MONO_TYPE_VAR:
6056         case MONO_TYPE_MVAR:
6057                 return TRUE;
6058         }
6059         return TRUE;
6060 }
6061
6062 /*
6063  * mono_type_get_object:
6064  * @domain: an app domain
6065  * @type: a type
6066  *
6067  * Return an System.MonoType object representing the type @type.
6068  */
6069 MonoReflectionType*
6070 mono_type_get_object (MonoDomain *domain, MonoType *type)
6071 {
6072         MonoReflectionType *res;
6073         MonoClass *klass = mono_class_from_mono_type (type);
6074
6075         /*we must avoid using @type as it might have come
6076          * from a mono_metadata_type_dup and the caller
6077          * expects that is can be freed.
6078          * Using the right type from 
6079          */
6080         type = klass->byval_arg.byref == type->byref ? &klass->byval_arg : &klass->this_arg;
6081
6082         /* void is very common */
6083         if (type->type == MONO_TYPE_VOID && domain->typeof_void)
6084                 return (MonoReflectionType*)domain->typeof_void;
6085
6086         /*
6087          * If the vtable of the given class was already created, we can use
6088          * the MonoType from there and avoid all locking and hash table lookups.
6089          * 
6090          * We cannot do this for TypeBuilders as mono_reflection_create_runtime_class expects
6091          * that the resulting object is diferent.   
6092          */
6093         if (type == &klass->byval_arg && !klass->image->dynamic) {
6094                 MonoVTable *vtable = mono_class_try_get_vtable (domain, klass);
6095                 if (vtable && vtable->type)
6096                         return vtable->type;
6097         }
6098
6099         mono_domain_lock (domain);
6100         if (!domain->type_hash)
6101                 domain->type_hash = mono_g_hash_table_new_type ((GHashFunc)mymono_metadata_type_hash, 
6102                                 (GCompareFunc)mymono_metadata_type_equal, MONO_HASH_VALUE_GC);
6103         if ((res = mono_g_hash_table_lookup (domain->type_hash, type))) {
6104                 mono_domain_unlock (domain);
6105                 return res;
6106         }
6107         /* Create a MonoGenericClass object for instantiations of not finished TypeBuilders */
6108         if ((type->type == MONO_TYPE_GENERICINST) && type->data.generic_class->is_dynamic && !type->data.generic_class->container_class->wastypebuilder) {
6109                 res = (MonoReflectionType *)mono_generic_class_get_object (domain, type);
6110                 mono_g_hash_table_insert (domain->type_hash, type, res);
6111                 mono_domain_unlock (domain);
6112                 return res;
6113         }
6114
6115         if (!verify_safe_for_managed_space (type)) {
6116                 mono_domain_unlock (domain);
6117                 mono_raise_exception (mono_get_exception_invalid_operation ("This type cannot be propagated to managed space"));
6118         }
6119
6120         if (klass->reflection_info && !klass->wastypebuilder) {
6121                 /* g_assert_not_reached (); */
6122                 /* should this be considered an error condition? */
6123                 if (!type->byref) {
6124                         mono_domain_unlock (domain);
6125                         return klass->reflection_info;
6126                 }
6127         }
6128         // FIXME: Get rid of this, do it in the icalls for Type
6129         mono_class_init (klass);
6130 #ifdef HAVE_SGEN_GC
6131         res = (MonoReflectionType *)mono_gc_alloc_pinned_obj (mono_class_vtable (domain, mono_defaults.monotype_class), mono_class_instance_size (mono_defaults.monotype_class));
6132 #else
6133         res = (MonoReflectionType *)mono_object_new (domain, mono_defaults.monotype_class);
6134 #endif
6135         res->type = type;
6136         mono_g_hash_table_insert (domain->type_hash, type, res);
6137
6138         if (type->type == MONO_TYPE_VOID)
6139                 MONO_OBJECT_SETREF (domain, typeof_void, res);
6140
6141         mono_domain_unlock (domain);
6142         return res;
6143 }
6144
6145 /*
6146  * mono_method_get_object:
6147  * @domain: an app domain
6148  * @method: a method
6149  * @refclass: the reflected type (can be NULL)
6150  *
6151  * Return an System.Reflection.MonoMethod object representing the method @method.
6152  */
6153 MonoReflectionMethod*
6154 mono_method_get_object (MonoDomain *domain, MonoMethod *method, MonoClass *refclass)
6155 {
6156         /*
6157          * We use the same C representation for methods and constructors, but the type 
6158          * name in C# is different.
6159          */
6160         static MonoClass *System_Reflection_MonoMethod = NULL;
6161         static MonoClass *System_Reflection_MonoCMethod = NULL;
6162         static MonoClass *System_Reflection_MonoGenericMethod = NULL;
6163         static MonoClass *System_Reflection_MonoGenericCMethod = NULL;
6164         MonoClass *klass;
6165         MonoReflectionMethod *ret;
6166
6167         /*
6168          * Don't let static RGCTX invoke wrappers get into
6169          * MonoReflectionMethods.
6170          */
6171         if (method->wrapper_type == MONO_WRAPPER_STATIC_RGCTX_INVOKE)
6172                 method = mono_marshal_method_from_wrapper (method);
6173
6174         if (method->is_inflated) {
6175                 MonoReflectionGenericMethod *gret;
6176
6177                 refclass = method->klass;
6178                 CHECK_OBJECT (MonoReflectionMethod *, method, refclass);
6179                 if ((*method->name == '.') && (!strcmp (method->name, ".ctor") || !strcmp (method->name, ".cctor"))) {
6180                         if (!System_Reflection_MonoGenericCMethod)
6181                                 System_Reflection_MonoGenericCMethod = mono_class_from_name (mono_defaults.corlib, "System.Reflection", "MonoGenericCMethod");
6182                         klass = System_Reflection_MonoGenericCMethod;
6183                 } else {
6184                         if (!System_Reflection_MonoGenericMethod)
6185                                 System_Reflection_MonoGenericMethod = mono_class_from_name (mono_defaults.corlib, "System.Reflection", "MonoGenericMethod");
6186                         klass = System_Reflection_MonoGenericMethod;
6187                 }
6188                 gret = (MonoReflectionGenericMethod*)mono_object_new (domain, klass);
6189                 gret->method.method = method;
6190                 MONO_OBJECT_SETREF (gret, method.name, mono_string_new (domain, method->name));
6191                 MONO_OBJECT_SETREF (gret, method.reftype, mono_type_get_object (domain, &refclass->byval_arg));
6192                 CACHE_OBJECT (MonoReflectionMethod *, method, (MonoReflectionMethod*)gret, refclass);
6193         }
6194
6195         if (!refclass)
6196                 refclass = method->klass;
6197
6198         CHECK_OBJECT (MonoReflectionMethod *, method, refclass);
6199         if (*method->name == '.' && (strcmp (method->name, ".ctor") == 0 || strcmp (method->name, ".cctor") == 0)) {
6200                 if (!System_Reflection_MonoCMethod)
6201                         System_Reflection_MonoCMethod = mono_class_from_name (mono_defaults.corlib, "System.Reflection", "MonoCMethod");
6202                 klass = System_Reflection_MonoCMethod;
6203         }
6204         else {
6205                 if (!System_Reflection_MonoMethod)
6206                         System_Reflection_MonoMethod = mono_class_from_name (mono_defaults.corlib, "System.Reflection", "MonoMethod");
6207                 klass = System_Reflection_MonoMethod;
6208         }
6209         ret = (MonoReflectionMethod*)mono_object_new (domain, klass);
6210         ret->method = method;
6211         MONO_OBJECT_SETREF (ret, reftype, mono_type_get_object (domain, &refclass->byval_arg));
6212         CACHE_OBJECT (MonoReflectionMethod *, method, ret, refclass);
6213 }
6214
6215 /*
6216  * mono_field_get_object:
6217  * @domain: an app domain
6218  * @klass: a type
6219  * @field: a field
6220  *
6221  * Return an System.Reflection.MonoField object representing the field @field
6222  * in class @klass.
6223  */
6224 MonoReflectionField*
6225 mono_field_get_object (MonoDomain *domain, MonoClass *klass, MonoClassField *field)
6226 {
6227         MonoReflectionField *res;
6228         static MonoClass *monofield_klass;
6229
6230         CHECK_OBJECT (MonoReflectionField *, field, klass);
6231         if (!monofield_klass)
6232                 monofield_klass = mono_class_from_name (mono_defaults.corlib, "System.Reflection", "MonoField");
6233         res = (MonoReflectionField *)mono_object_new (domain, monofield_klass);
6234         res->klass = klass;
6235         res->field = field;
6236         MONO_OBJECT_SETREF (res, name, mono_string_new (domain, mono_field_get_name (field)));
6237         if (is_field_on_inst (field))
6238                 res->attrs = get_field_on_inst_generic_type (field)->attrs;
6239         else
6240                 res->attrs = field->type->attrs;
6241         MONO_OBJECT_SETREF (res, type, mono_type_get_object (domain, field->type));
6242         CACHE_OBJECT (MonoReflectionField *, field, res, klass);
6243 }
6244
6245 /*
6246  * mono_property_get_object:
6247  * @domain: an app domain
6248  * @klass: a type
6249  * @property: a property
6250  *
6251  * Return an System.Reflection.MonoProperty object representing the property @property
6252  * in class @klass.
6253  */
6254 MonoReflectionProperty*
6255 mono_property_get_object (MonoDomain *domain, MonoClass *klass, MonoProperty *property)
6256 {
6257         MonoReflectionProperty *res;
6258         static MonoClass *monoproperty_klass;
6259
6260         CHECK_OBJECT (MonoReflectionProperty *, property, klass);
6261         if (!monoproperty_klass)
6262                 monoproperty_klass = mono_class_from_name (mono_defaults.corlib, "System.Reflection", "MonoProperty");
6263         res = (MonoReflectionProperty *)mono_object_new (domain, monoproperty_klass);
6264         res->klass = klass;
6265         res->property = property;
6266         CACHE_OBJECT (MonoReflectionProperty *, property, res, klass);
6267 }
6268
6269 /*
6270  * mono_event_get_object:
6271  * @domain: an app domain
6272  * @klass: a type
6273  * @event: a event
6274  *
6275  * Return an System.Reflection.MonoEvent object representing the event @event
6276  * in class @klass.
6277  */
6278 MonoReflectionEvent*
6279 mono_event_get_object (MonoDomain *domain, MonoClass *klass, MonoEvent *event)
6280 {
6281         MonoReflectionEvent *res;
6282         static MonoClass *monoevent_klass;
6283
6284         CHECK_OBJECT (MonoReflectionEvent *, event, klass);
6285         if (!monoevent_klass)
6286                 monoevent_klass = mono_class_from_name (mono_defaults.corlib, "System.Reflection", "MonoEvent");
6287         res = (MonoReflectionEvent *)mono_object_new (domain, monoevent_klass);
6288         res->klass = klass;
6289         res->event = event;
6290         CACHE_OBJECT (MonoReflectionEvent *, event, res, klass);
6291 }
6292
6293 /**
6294  * mono_get_reflection_missing_object:
6295  * @domain: Domain where the object lives
6296  *
6297  * Returns the System.Reflection.Missing.Value singleton object
6298  * (of type System.Reflection.Missing).
6299  *
6300  * Used as the value for ParameterInfo.DefaultValue when Optional
6301  * is present
6302  */
6303 static MonoObject *
6304 mono_get_reflection_missing_object (MonoDomain *domain)
6305 {
6306         MonoObject *obj;
6307         static MonoClassField *missing_value_field = NULL;
6308         
6309         if (!missing_value_field) {
6310                 MonoClass *missing_klass;
6311                 missing_klass = mono_class_from_name (mono_defaults.corlib, "System.Reflection", "Missing");
6312                 mono_class_init (missing_klass);
6313                 missing_value_field = mono_class_get_field_from_name (missing_klass, "Value");
6314                 g_assert (missing_value_field);
6315         }
6316         obj = mono_field_get_value_object (domain, missing_value_field, NULL); 
6317         g_assert (obj);
6318         return obj;
6319 }
6320
6321 static MonoObject*
6322 get_dbnull (MonoDomain *domain, MonoObject **dbnull)
6323 {
6324         if (!*dbnull)
6325                 *dbnull = mono_get_dbnull_object (domain);
6326         return *dbnull;
6327 }
6328
6329 static MonoObject*
6330 get_reflection_missing (MonoDomain *domain, MonoObject **reflection_missing)
6331 {
6332         if (!*reflection_missing)
6333                 *reflection_missing = mono_get_reflection_missing_object (domain);
6334         return *reflection_missing;
6335 }
6336
6337 /*
6338  * mono_param_get_objects:
6339  * @domain: an app domain
6340  * @method: a method
6341  *
6342  * Return an System.Reflection.ParameterInfo array object representing the parameters
6343  * in the method @method.
6344  */
6345 MonoArray*
6346 mono_param_get_objects (MonoDomain *domain, MonoMethod *method)
6347 {
6348         static MonoClass *System_Reflection_ParameterInfo;
6349         static MonoClass *System_Reflection_ParameterInfo_array;
6350         MonoArray *res = NULL;
6351         MonoReflectionMethod *member = NULL;
6352         MonoReflectionParameter *param = NULL;
6353         char **names, **blobs = NULL;
6354         guint32 *types = NULL;
6355         MonoType *type = NULL;
6356         MonoObject *dbnull = NULL;
6357         MonoObject *missing = NULL;
6358         MonoMarshalSpec **mspecs;
6359         MonoMethodSignature *sig;
6360         MonoVTable *pinfo_vtable;
6361         int i;
6362
6363         if (!System_Reflection_ParameterInfo_array) {
6364                 MonoClass *klass;
6365
6366                 klass = mono_class_from_name (mono_defaults.corlib, "System.Reflection", "ParameterInfo");
6367                 mono_memory_barrier ();
6368                 System_Reflection_ParameterInfo = klass; 
6369         
6370                 klass = mono_array_class_get (klass, 1);
6371                 mono_memory_barrier ();
6372                 System_Reflection_ParameterInfo_array = klass;
6373         }
6374         
6375         if (!mono_method_signature (method)->param_count)
6376                 return mono_array_new_specific (mono_class_vtable (domain, System_Reflection_ParameterInfo_array), 0);
6377
6378         /* Note: the cache is based on the address of the signature into the method
6379          * since we already cache MethodInfos with the method as keys.
6380          */
6381         CHECK_OBJECT (MonoArray*, &(method->signature), NULL);
6382
6383         sig = mono_method_signature (method);
6384         member = mono_method_get_object (domain, method, NULL);
6385         names = g_new (char *, sig->param_count);
6386         mono_method_get_param_names (method, (const char **) names);
6387
6388         mspecs = g_new (MonoMarshalSpec*, sig->param_count + 1);
6389         mono_method_get_marshal_info (method, mspecs);
6390
6391         res = mono_array_new_specific (mono_class_vtable (domain, System_Reflection_ParameterInfo_array), sig->param_count);
6392         pinfo_vtable = mono_class_vtable (domain, System_Reflection_ParameterInfo);
6393         for (i = 0; i < sig->param_count; ++i) {
6394                 param = (MonoReflectionParameter *)mono_object_new_specific (pinfo_vtable);
6395                 MONO_OBJECT_SETREF (param, ClassImpl, mono_type_get_object (domain, sig->params [i]));
6396                 MONO_OBJECT_SETREF (param, MemberImpl, (MonoObject*)member);
6397                 MONO_OBJECT_SETREF (param, NameImpl, mono_string_new (domain, names [i]));
6398                 param->PositionImpl = i;
6399                 param->AttrsImpl = sig->params [i]->attrs;
6400
6401                 if (!(param->AttrsImpl & PARAM_ATTRIBUTE_HAS_DEFAULT)) {
6402                         if (param->AttrsImpl & PARAM_ATTRIBUTE_OPTIONAL)
6403                                 MONO_OBJECT_SETREF (param, DefaultValueImpl, get_reflection_missing (domain, &missing));
6404                         else
6405                                 MONO_OBJECT_SETREF (param, DefaultValueImpl, get_dbnull (domain, &dbnull));
6406                 } else {
6407
6408                         if (!blobs) {
6409                                 blobs = g_new0 (char *, sig->param_count);
6410                                 types = g_new0 (guint32, sig->param_count);
6411                                 get_default_param_value_blobs (method, blobs, types); 
6412                         }
6413
6414                         /* Build MonoType for the type from the Constant Table */
6415                         if (!type)
6416                                 type = g_new0 (MonoType, 1);
6417                         type->type = types [i];
6418                         type->data.klass = NULL;
6419                         if (types [i] == MONO_TYPE_CLASS)
6420                                 type->data.klass = mono_defaults.object_class;
6421                         else if ((sig->params [i]->type == MONO_TYPE_VALUETYPE) && sig->params [i]->data.klass->enumtype) {
6422                                 /* For enums, types [i] contains the base type */
6423
6424                                         type->type = MONO_TYPE_VALUETYPE;
6425                                         type->data.klass = mono_class_from_mono_type (sig->params [i]);
6426                         } else
6427                                 type->data.klass = mono_class_from_mono_type (type);
6428
6429                         MONO_OBJECT_SETREF (param, DefaultValueImpl, mono_get_object_from_blob (domain, type, blobs [i]));
6430
6431                         /* Type in the Constant table is MONO_TYPE_CLASS for nulls */
6432                         if (types [i] != MONO_TYPE_CLASS && !param->DefaultValueImpl) {
6433                                 if (param->AttrsImpl & PARAM_ATTRIBUTE_OPTIONAL)
6434                                         MONO_OBJECT_SETREF (param, DefaultValueImpl, get_reflection_missing (domain, &missing));
6435                                 else
6436                                         MONO_OBJECT_SETREF (param, DefaultValueImpl, get_dbnull (domain, &dbnull));
6437                         }
6438                         
6439                 }
6440
6441                 if (mspecs [i + 1])
6442                         MONO_OBJECT_SETREF (param, MarshalAsImpl, (MonoObject*)mono_reflection_marshal_from_marshal_spec (domain, method->klass, mspecs [i + 1]));
6443                 
6444                 mono_array_setref (res, i, param);
6445         }
6446         g_free (names);
6447         g_free (blobs);
6448         g_free (types);
6449         g_free (type);
6450
6451         for (i = mono_method_signature (method)->param_count; i >= 0; i--)
6452                 if (mspecs [i])
6453                         mono_metadata_free_marshal_spec (mspecs [i]);
6454         g_free (mspecs);
6455         
6456         CACHE_OBJECT (MonoArray *, &(method->signature), res, NULL);
6457 }
6458
6459 /*
6460  * mono_method_body_get_object:
6461  * @domain: an app domain
6462  * @method: a method
6463  *
6464  * Return an System.Reflection.MethodBody object representing the method @method.
6465  */
6466 MonoReflectionMethodBody*
6467 mono_method_body_get_object (MonoDomain *domain, MonoMethod *method)
6468 {
6469         static MonoClass *System_Reflection_MethodBody = NULL;
6470         static MonoClass *System_Reflection_LocalVariableInfo = NULL;
6471         static MonoClass *System_Reflection_ExceptionHandlingClause = NULL;
6472         MonoReflectionMethodBody *ret;
6473         MonoMethodNormal *mn;
6474         MonoMethodHeader *header;
6475         guint32 method_rva, local_var_sig_token;
6476     char *ptr;
6477         unsigned char format, flags;
6478         int i;
6479
6480         if (!System_Reflection_MethodBody)
6481                 System_Reflection_MethodBody = mono_class_from_name (mono_defaults.corlib, "System.Reflection", "MethodBody");
6482         if (!System_Reflection_LocalVariableInfo)
6483                 System_Reflection_LocalVariableInfo = mono_class_from_name (mono_defaults.corlib, "System.Reflection", "LocalVariableInfo");
6484         if (!System_Reflection_ExceptionHandlingClause)
6485                 System_Reflection_ExceptionHandlingClause = mono_class_from_name (mono_defaults.corlib, "System.Reflection", "ExceptionHandlingClause");
6486
6487         CHECK_OBJECT (MonoReflectionMethodBody *, method, NULL);
6488
6489         if ((method->flags & METHOD_ATTRIBUTE_PINVOKE_IMPL) ||
6490                 (method->flags & METHOD_ATTRIBUTE_ABSTRACT) ||
6491             (method->iflags & METHOD_IMPL_ATTRIBUTE_INTERNAL_CALL) ||
6492             (method->iflags & METHOD_IMPL_ATTRIBUTE_RUNTIME))
6493                 return NULL;
6494         mn = (MonoMethodNormal *)method;
6495         header = mono_method_get_header (method);
6496         
6497         /* Obtain local vars signature token */
6498         method_rva = mono_metadata_decode_row_col (&method->klass->image->tables [MONO_TABLE_METHOD], mono_metadata_token_index (method->token) - 1, MONO_METHOD_RVA);
6499         ptr = mono_image_rva_map (method->klass->image, method_rva);
6500         flags = *(const unsigned char *) ptr;
6501         format = flags & METHOD_HEADER_FORMAT_MASK;
6502         switch (format){
6503         case METHOD_HEADER_TINY_FORMAT:
6504         case METHOD_HEADER_TINY_FORMAT1:
6505                 local_var_sig_token = 0;
6506                 break;
6507         case METHOD_HEADER_FAT_FORMAT:
6508                 ptr += 2;
6509                 ptr += 2;
6510                 ptr += 4;
6511                 local_var_sig_token = read32 (ptr);
6512                 break;
6513         default:
6514                 g_assert_not_reached ();
6515         }
6516
6517         ret = (MonoReflectionMethodBody*)mono_object_new (domain, System_Reflection_MethodBody);
6518
6519         ret->init_locals = header->init_locals;
6520         ret->max_stack = header->max_stack;
6521         ret->local_var_sig_token = local_var_sig_token;
6522         MONO_OBJECT_SETREF (ret, il, mono_array_new (domain, mono_defaults.byte_class, header->code_size));
6523         memcpy (mono_array_addr (ret->il, guint8, 0), header->code, header->code_size);
6524
6525         /* Locals */
6526         MONO_OBJECT_SETREF (ret, locals, mono_array_new (domain, System_Reflection_LocalVariableInfo, header->num_locals));
6527         for (i = 0; i < header->num_locals; ++i) {
6528                 MonoReflectionLocalVariableInfo *info = (MonoReflectionLocalVariableInfo*)mono_object_new (domain, System_Reflection_LocalVariableInfo);
6529                 MONO_OBJECT_SETREF (info, local_type, mono_type_get_object (domain, header->locals [i]));
6530                 info->is_pinned = header->locals [i]->pinned;
6531                 info->local_index = i;
6532                 mono_array_setref (ret->locals, i, info);
6533         }
6534
6535         /* Exceptions */
6536         MONO_OBJECT_SETREF (ret, clauses, mono_array_new (domain, System_Reflection_ExceptionHandlingClause, header->num_clauses));
6537         for (i = 0; i < header->num_clauses; ++i) {
6538                 MonoReflectionExceptionHandlingClause *info = (MonoReflectionExceptionHandlingClause*)mono_object_new (domain, System_Reflection_ExceptionHandlingClause);
6539                 MonoExceptionClause *clause = &header->clauses [i];
6540
6541                 info->flags = clause->flags;
6542                 info->try_offset = clause->try_offset;
6543                 info->try_length = clause->try_len;
6544                 info->handler_offset = clause->handler_offset;
6545                 info->handler_length = clause->handler_len;
6546                 if (clause->flags == MONO_EXCEPTION_CLAUSE_FILTER)
6547                         info->filter_offset = clause->data.filter_offset;
6548                 else if (clause->data.catch_class)
6549                         MONO_OBJECT_SETREF (info, catch_type, mono_type_get_object (mono_domain_get (), &clause->data.catch_class->byval_arg));
6550
6551                 mono_array_setref (ret->clauses, i, info);
6552         }
6553
6554         CACHE_OBJECT (MonoReflectionMethodBody *, method, ret, NULL);
6555         return ret;
6556 }
6557
6558 /**
6559  * mono_get_dbnull_object:
6560  * @domain: Domain where the object lives
6561  *
6562  * Returns the System.DBNull.Value singleton object
6563  *
6564  * Used as the value for ParameterInfo.DefaultValue 
6565  */
6566 MonoObject *
6567 mono_get_dbnull_object (MonoDomain *domain)
6568 {
6569         MonoObject *obj;
6570         static MonoClassField *dbnull_value_field = NULL;
6571         
6572         if (!dbnull_value_field) {
6573                 MonoClass *dbnull_klass;
6574                 dbnull_klass = mono_class_from_name (mono_defaults.corlib, "System", "DBNull");
6575                 mono_class_init (dbnull_klass);
6576                 dbnull_value_field = mono_class_get_field_from_name (dbnull_klass, "Value");
6577                 g_assert (dbnull_value_field);
6578         }
6579         obj = mono_field_get_value_object (domain, dbnull_value_field, NULL); 
6580         g_assert (obj);
6581         return obj;
6582 }
6583
6584 static void
6585 get_default_param_value_blobs (MonoMethod *method, char **blobs, guint32 *types)
6586 {
6587         guint32 param_index, i, lastp, crow = 0;
6588         guint32 param_cols [MONO_PARAM_SIZE], const_cols [MONO_CONSTANT_SIZE];
6589         gint32 idx;
6590
6591         MonoClass *klass = method->klass;
6592         MonoImage *image = klass->image;
6593         MonoMethodSignature *methodsig = mono_method_signature (method);
6594
6595         MonoTableInfo *constt;
6596         MonoTableInfo *methodt;
6597         MonoTableInfo *paramt;
6598
6599         if (!methodsig->param_count)
6600                 return;
6601
6602         mono_class_init (klass);
6603
6604         if (klass->image->dynamic) {
6605                 MonoReflectionMethodAux *aux;
6606                 if (method->is_inflated)
6607                         method = ((MonoMethodInflated*)method)->declaring;
6608                 aux = g_hash_table_lookup (((MonoDynamicImage*)method->klass->image)->method_aux_hash, method);
6609                 if (aux && aux->param_defaults) {
6610                         memcpy (blobs, &(aux->param_defaults [1]), methodsig->param_count * sizeof (char*));
6611                         memcpy (types, &(aux->param_default_types [1]), methodsig->param_count * sizeof (guint32));
6612                 }
6613                 return;
6614         }
6615
6616         methodt = &klass->image->tables [MONO_TABLE_METHOD];
6617         paramt = &klass->image->tables [MONO_TABLE_PARAM];
6618         constt = &image->tables [MONO_TABLE_CONSTANT];
6619
6620         idx = mono_method_get_index (method) - 1;
6621         g_assert (idx != -1);
6622
6623         param_index = mono_metadata_decode_row_col (methodt, idx, MONO_METHOD_PARAMLIST);
6624         if (idx + 1 < methodt->rows)
6625                 lastp = mono_metadata_decode_row_col (methodt, idx + 1, MONO_METHOD_PARAMLIST);
6626         else
6627                 lastp = paramt->rows + 1;
6628
6629         for (i = param_index; i < lastp; ++i) {
6630                 guint32 paramseq;
6631
6632                 mono_metadata_decode_row (paramt, i - 1, param_cols, MONO_PARAM_SIZE);
6633                 paramseq = param_cols [MONO_PARAM_SEQUENCE];
6634
6635                 if (!param_cols [MONO_PARAM_FLAGS] & PARAM_ATTRIBUTE_HAS_DEFAULT) 
6636                         continue;
6637
6638                 crow = mono_metadata_get_constant_index (image, MONO_TOKEN_PARAM_DEF | i, crow + 1);
6639                 if (!crow) {
6640                         continue;
6641                 }
6642         
6643                 mono_metadata_decode_row (constt, crow - 1, const_cols, MONO_CONSTANT_SIZE);
6644                 blobs [paramseq - 1] = (gpointer) mono_metadata_blob_heap (image, const_cols [MONO_CONSTANT_VALUE]);
6645                 types [paramseq - 1] = const_cols [MONO_CONSTANT_TYPE];
6646         }
6647
6648         return;
6649 }
6650
6651 static MonoObject *
6652 mono_get_object_from_blob (MonoDomain *domain, MonoType *type, const char *blob)
6653 {
6654         void *retval;
6655         MonoClass *klass;
6656         MonoObject *object;
6657         MonoType *basetype = type;
6658
6659         if (!blob)
6660                 return NULL;
6661         
6662         klass = mono_class_from_mono_type (type);
6663         if (klass->valuetype) {
6664                 object = mono_object_new (domain, klass);
6665                 retval = ((gchar *) object + sizeof (MonoObject));
6666                 if (klass->enumtype)
6667                         basetype = klass->enum_basetype;
6668         } else {
6669                 retval = &object;
6670         }
6671                         
6672         if (!mono_get_constant_value_from_blob (domain, basetype->type,  blob, retval))
6673                 return object;
6674         else
6675                 return NULL;
6676 }
6677
6678 static int
6679 assembly_name_to_aname (MonoAssemblyName *assembly, char *p) {
6680         int found_sep;
6681         char *s;
6682
6683         memset (assembly, 0, sizeof (MonoAssemblyName));
6684         assembly->name = p;
6685         assembly->culture = "";
6686         memset (assembly->public_key_token, 0, MONO_PUBLIC_KEY_TOKEN_LENGTH);
6687
6688         while (*p && (isalnum (*p) || *p == '.' || *p == '-' || *p == '_' || *p == '$' || *p == '@'))
6689                 p++;
6690         found_sep = 0;
6691         while (g_ascii_isspace (*p) || *p == ',') {
6692                 *p++ = 0;
6693                 found_sep = 1;
6694                 continue;
6695         }
6696         /* failed */
6697         if (!found_sep)
6698                 return 1;
6699         while (*p) {
6700                 if (*p == 'V' && g_ascii_strncasecmp (p, "Version=", 8) == 0) {
6701                         p += 8;
6702                         assembly->major = strtoul (p, &s, 10);
6703                         if (s == p || *s != '.')
6704                                 return 1;
6705                         p = ++s;
6706                         assembly->minor = strtoul (p, &s, 10);
6707                         if (s == p || *s != '.')
6708                                 return 1;
6709                         p = ++s;
6710                         assembly->build = strtoul (p, &s, 10);
6711                         if (s == p || *s != '.')
6712                                 return 1;
6713                         p = ++s;
6714                         assembly->revision = strtoul (p, &s, 10);
6715                         if (s == p)
6716                                 return 1;
6717                         p = s;
6718                 } else if (*p == 'C' && g_ascii_strncasecmp (p, "Culture=", 8) == 0) {
6719                         p += 8;
6720                         if (g_ascii_strncasecmp (p, "neutral", 7) == 0) {
6721                                 assembly->culture = "";
6722                                 p += 7;
6723                         } else {
6724                                 assembly->culture = p;
6725                                 while (*p && *p != ',') {
6726                                         p++;
6727                                 }
6728                         }
6729                 } else if (*p == 'P' && g_ascii_strncasecmp (p, "PublicKeyToken=", 15) == 0) {
6730                         p += 15;
6731                         if (strncmp (p, "null", 4) == 0) {
6732                                 p += 4;
6733                         } else {
6734                                 int len;
6735                                 gchar *start = p;
6736                                 while (*p && *p != ',') {
6737                                         p++;
6738                                 }
6739                                 len = (p - start + 1);
6740                                 if (len > MONO_PUBLIC_KEY_TOKEN_LENGTH)
6741                                         len = MONO_PUBLIC_KEY_TOKEN_LENGTH;
6742                                 g_strlcpy ((char*)assembly->public_key_token, start, len);
6743                         }
6744                 } else {
6745                         while (*p && *p != ',')
6746                                 p++;
6747                 }
6748                 found_sep = 0;
6749                 while (g_ascii_isspace (*p) || *p == ',') {
6750                         *p++ = 0;
6751                         found_sep = 1;
6752                         continue;
6753                 }
6754                 /* failed */
6755                 if (!found_sep)
6756                         return 1;
6757         }
6758
6759         return 0;
6760 }
6761
6762 /*
6763  * mono_reflection_parse_type:
6764  * @name: type name
6765  *
6766  * Parse a type name as accepted by the GetType () method and output the info
6767  * extracted in the info structure.
6768  * the name param will be mangled, so, make a copy before passing it to this function.
6769  * The fields in info will be valid until the memory pointed to by name is valid.
6770  *
6771  * See also mono_type_get_name () below.
6772  *
6773  * Returns: 0 on parse error.
6774  */
6775 static int
6776 _mono_reflection_parse_type (char *name, char **endptr, gboolean is_recursed,
6777                              MonoTypeNameParse *info)
6778 {
6779         char *start, *p, *w, *temp, *last_point, *startn;
6780         int in_modifiers = 0;
6781         int isbyref = 0, rank, arity = 0, i;
6782
6783         start = p = w = name;
6784
6785         //FIXME could we just zero the whole struct? memset (&info, 0, sizeof (MonoTypeNameParse))
6786         memset (&info->assembly, 0, sizeof (MonoAssemblyName));
6787         info->name = info->name_space = NULL;
6788         info->nested = NULL;
6789         info->modifiers = NULL;
6790         info->type_arguments = NULL;
6791
6792         /* last_point separates the namespace from the name */
6793         last_point = NULL;
6794         /* Skips spaces */
6795         while (*p == ' ') p++, start++, w++, name++;
6796
6797         while (*p) {
6798                 switch (*p) {
6799                 case '+':
6800                         *p = 0; /* NULL terminate the name */
6801                         startn = p + 1;
6802                         info->nested = g_list_append (info->nested, startn);
6803                         /* we have parsed the nesting namespace + name */
6804                         if (info->name)
6805                                 break;
6806                         if (last_point) {
6807                                 info->name_space = start;
6808                                 *last_point = 0;
6809                                 info->name = last_point + 1;
6810                         } else {
6811                                 info->name_space = (char *)"";
6812                                 info->name = start;
6813                         }
6814                         break;
6815                 case '.':
6816                         last_point = p;
6817                         break;
6818                 case '\\':
6819                         ++p;
6820                         break;
6821                 case '&':
6822                 case '*':
6823                 case '[':
6824                 case ',':
6825                 case ']':
6826                         in_modifiers = 1;
6827                         break;
6828                 case '`':
6829                         ++p;
6830                         i = strtol (p, &temp, 10);
6831                         arity += i;
6832                         if (p == temp)
6833                                 return 0;
6834                         p = temp-1;
6835                         break;
6836                 default:
6837                         break;
6838                 }
6839                 if (in_modifiers)
6840                         break;
6841                 // *w++ = *p++;
6842                 p++;
6843         }
6844         
6845         if (!info->name) {
6846                 if (last_point) {
6847                         info->name_space = start;
6848                         *last_point = 0;
6849                         info->name = last_point + 1;
6850                 } else {
6851                         info->name_space = (char *)"";
6852                         info->name = start;
6853                 }
6854         }
6855         while (*p) {
6856                 switch (*p) {
6857                 case '&':
6858                         if (isbyref) /* only one level allowed by the spec */
6859                                 return 0;
6860                         isbyref = 1;
6861                         info->modifiers = g_list_append (info->modifiers, GUINT_TO_POINTER (0));
6862                         *p++ = 0;
6863                         break;
6864                 case '*':
6865                         info->modifiers = g_list_append (info->modifiers, GUINT_TO_POINTER (-1));
6866                         *p++ = 0;
6867                         break;
6868                 case '[':
6869                         if (arity != 0) {
6870                                 *p++ = 0;
6871                                 info->type_arguments = g_ptr_array_new ();
6872                                 for (i = 0; i < arity; i++) {
6873                                         MonoTypeNameParse *subinfo = g_new0 (MonoTypeNameParse, 1);
6874                                         gboolean fqname = FALSE;
6875
6876                                         g_ptr_array_add (info->type_arguments, subinfo);
6877
6878                                         if (*p == '[') {
6879                                                 p++;
6880                                                 fqname = TRUE;
6881                                         }
6882
6883                                         if (!_mono_reflection_parse_type (p, &p, TRUE, subinfo))
6884                                                 return 0;
6885
6886                                         if (fqname) {
6887                                                 char *aname;
6888
6889                                                 if (*p != ',')
6890                                                         return 0;
6891                                                 *p++ = 0;
6892
6893                                                 aname = p;
6894                                                 while (*p && (*p != ']'))
6895                                                         p++;
6896
6897                                                 if (*p != ']')
6898                                                         return 0;
6899
6900                                                 *p++ = 0;
6901                                                 while (*aname) {
6902                                                         if (g_ascii_isspace (*aname)) {
6903                                                                 ++aname;
6904                                                                 continue;
6905                                                         }
6906                                                         break;
6907                                                 }
6908                                                 if (!*aname ||
6909                                                     !assembly_name_to_aname (&subinfo->assembly, aname))
6910                                                         return 0;
6911                                         }
6912
6913                                         if (i + 1 < arity) {
6914                                                 if (*p != ',')
6915                                                         return 0;
6916                                         } else {
6917                                                 if (*p != ']')
6918                                                         return 0;
6919                                         }
6920                                         *p++ = 0;
6921                                 }
6922
6923                                 arity = 0;
6924                                 break;
6925                         }
6926                         rank = 1;
6927                         *p++ = 0;
6928                         while (*p) {
6929                                 if (*p == ']')
6930                                         break;
6931                                 if (*p == ',')
6932                                         rank++;
6933                                 else if (*p == '*') /* '*' means unknown lower bound */
6934                                         info->modifiers = g_list_append (info->modifiers, GUINT_TO_POINTER (-2));
6935                                 else
6936                                         return 0;
6937                                 ++p;
6938                         }
6939                         if (*p++ != ']')
6940                                 return 0;
6941                         info->modifiers = g_list_append (info->modifiers, GUINT_TO_POINTER (rank));
6942                         break;
6943                 case ']':
6944                         if (is_recursed)
6945                                 goto end;
6946                         return 0;
6947                 case ',':
6948                         if (is_recursed)
6949                                 goto end;
6950                         *p++ = 0;
6951                         while (*p) {
6952                                 if (g_ascii_isspace (*p)) {
6953                                         ++p;
6954                                         continue;
6955                                 }
6956                                 break;
6957                         }
6958                         if (!*p)
6959                                 return 0; /* missing assembly name */
6960                         if (!assembly_name_to_aname (&info->assembly, p))
6961                                 return 0;
6962                         break;
6963                 default:
6964                         return 0;
6965                 }
6966                 if (info->assembly.name)
6967                         break;
6968         }
6969         // *w = 0; /* terminate class name */
6970  end:
6971         if (!info->name || !*info->name)
6972                 return 0;
6973         if (endptr)
6974                 *endptr = p;
6975         /* add other consistency checks */
6976         return 1;
6977 }
6978
6979 int
6980 mono_reflection_parse_type (char *name, MonoTypeNameParse *info)
6981 {
6982         return _mono_reflection_parse_type (name, NULL, FALSE, info);
6983 }
6984
6985 static MonoType*
6986 _mono_reflection_get_type_from_info (MonoTypeNameParse *info, MonoImage *image, gboolean ignorecase)
6987 {
6988         gboolean type_resolve = FALSE;
6989         MonoType *type;
6990         MonoImage *rootimage = image;
6991
6992         if (info->assembly.name) {
6993                 MonoAssembly *assembly = mono_assembly_loaded (&info->assembly);
6994                 if (!assembly && image && image->assembly && mono_assembly_names_equal (&info->assembly, &image->assembly->aname))
6995                         /* 
6996                          * This could happen in the AOT compiler case when the search hook is not
6997                          * installed.
6998                          */
6999                         assembly = image->assembly;
7000                 if (!assembly) {
7001                         /* then we must load the assembly ourselve - see #60439 */
7002                         assembly = mono_assembly_load (&info->assembly, NULL, NULL);
7003                         if (!assembly)
7004                                 return NULL;
7005                 }
7006                 image = assembly->image;
7007         } else if (!image) {
7008                 image = mono_defaults.corlib;
7009         }
7010
7011         type = mono_reflection_get_type_with_rootimage (rootimage, image, info, ignorecase, &type_resolve);
7012         if (type == NULL && !info->assembly.name && image != mono_defaults.corlib) {
7013                 image = mono_defaults.corlib;
7014                 type = mono_reflection_get_type_with_rootimage (rootimage, image, info, ignorecase, &type_resolve);
7015         }
7016
7017         return type;
7018 }
7019
7020 static MonoType*
7021 mono_reflection_get_type_internal (MonoImage *rootimage, MonoImage* image, MonoTypeNameParse *info, gboolean ignorecase)
7022 {
7023         MonoClass *klass;
7024         GList *mod;
7025         int modval;
7026         gboolean bounded = FALSE;
7027         
7028         if (!image)
7029                 image = mono_defaults.corlib;
7030
7031         if (ignorecase)
7032                 klass = mono_class_from_name_case (image, info->name_space, info->name);
7033         else
7034                 klass = mono_class_from_name (image, info->name_space, info->name);
7035         if (!klass)
7036                 return NULL;
7037         for (mod = info->nested; mod; mod = mod->next) {
7038                 gpointer iter = NULL;
7039                 MonoClass *parent;
7040
7041                 parent = klass;
7042                 mono_class_init (parent);
7043
7044                 while ((klass = mono_class_get_nested_types (parent, &iter))) {
7045                         if (ignorecase) {
7046                                 if (g_strcasecmp (klass->name, mod->data) == 0)
7047                                         break;
7048                         } else {
7049                                 if (strcmp (klass->name, mod->data) == 0)
7050                                         break;
7051                         }
7052                 }
7053                 if (!klass)
7054                         break;
7055         }
7056         if (!klass)
7057                 return NULL;
7058         mono_class_init (klass);
7059
7060         if (info->type_arguments) {
7061                 MonoType **type_args = g_new0 (MonoType *, info->type_arguments->len);
7062                 MonoReflectionType *the_type;
7063                 MonoType *instance;
7064                 int i;
7065
7066                 for (i = 0; i < info->type_arguments->len; i++) {
7067                         MonoTypeNameParse *subinfo = g_ptr_array_index (info->type_arguments, i);
7068
7069                         type_args [i] = _mono_reflection_get_type_from_info (subinfo, rootimage, ignorecase);
7070                         if (!type_args [i]) {
7071                                 g_free (type_args);
7072                                 return NULL;
7073                         }
7074                 }
7075
7076                 the_type = mono_type_get_object (mono_domain_get (), &klass->byval_arg);
7077
7078                 instance = mono_reflection_bind_generic_parameters (
7079                         the_type, info->type_arguments->len, type_args);
7080
7081                 g_free (type_args);
7082                 if (!instance)
7083                         return NULL;
7084
7085                 klass = mono_class_from_mono_type (instance);
7086         }
7087
7088         for (mod = info->modifiers; mod; mod = mod->next) {
7089                 modval = GPOINTER_TO_UINT (mod->data);
7090                 if (!modval) { /* byref: must be last modifier */
7091                         return &klass->this_arg;
7092                 } else if (modval == -1) {
7093                         klass = mono_ptr_class_get (&klass->byval_arg);
7094                 } else if (modval == -2) {
7095                         bounded = TRUE;
7096                 } else { /* array rank */
7097                         klass = mono_bounded_array_class_get (klass, modval, bounded);
7098                 }
7099                 mono_class_init (klass);
7100         }
7101
7102         return &klass->byval_arg;
7103 }
7104
7105 /*
7106  * mono_reflection_get_type:
7107  * @image: a metadata context
7108  * @info: type description structure
7109  * @ignorecase: flag for case-insensitive string compares
7110  * @type_resolve: whenever type resolve was already tried
7111  *
7112  * Build a MonoType from the type description in @info.
7113  * 
7114  */
7115
7116 MonoType*
7117 mono_reflection_get_type (MonoImage* image, MonoTypeNameParse *info, gboolean ignorecase, gboolean *type_resolve) {
7118         return mono_reflection_get_type_with_rootimage(image, image, info, ignorecase, type_resolve);
7119 }
7120
7121 static MonoType*
7122 mono_reflection_get_type_internal_dynamic (MonoImage *rootimage, MonoAssembly *assembly, MonoTypeNameParse *info, gboolean ignorecase)
7123 {
7124         MonoReflectionAssemblyBuilder *abuilder = (MonoReflectionAssemblyBuilder*)mono_assembly_get_object (mono_domain_get (), assembly);
7125         MonoType *type;
7126         int i;
7127
7128         g_assert (assembly->dynamic);
7129
7130         /* Enumerate all modules */
7131
7132         type = NULL;
7133         if (abuilder->modules) {
7134                 for (i = 0; i < mono_array_length (abuilder->modules); ++i) {
7135                         MonoReflectionModuleBuilder *mb = mono_array_get (abuilder->modules, MonoReflectionModuleBuilder*, i);
7136                         type = mono_reflection_get_type_internal (rootimage, &mb->dynamic_image->image, info, ignorecase);
7137                         if (type)
7138                                 break;
7139                 }
7140         }
7141
7142         if (!type && abuilder->loaded_modules) {
7143                 for (i = 0; i < mono_array_length (abuilder->loaded_modules); ++i) {
7144                         MonoReflectionModule *mod = mono_array_get (abuilder->loaded_modules, MonoReflectionModule*, i);
7145                         type = mono_reflection_get_type_internal (rootimage, mod->image, info, ignorecase);
7146                         if (type)
7147                                 break;
7148                 }
7149         }
7150
7151         return type;
7152 }
7153         
7154 MonoType*
7155 mono_reflection_get_type_with_rootimage (MonoImage *rootimage, MonoImage* image, MonoTypeNameParse *info, gboolean ignorecase, gboolean *type_resolve)
7156 {
7157         MonoType *type;
7158         MonoReflectionAssembly *assembly;
7159         GString *fullName;
7160         GList *mod;
7161
7162         if (image && image->dynamic)
7163                 type = mono_reflection_get_type_internal_dynamic (rootimage, image->assembly, info, ignorecase);
7164         else
7165                 type = mono_reflection_get_type_internal (rootimage, image, info, ignorecase);
7166         if (type)
7167                 return type;
7168         if (!mono_domain_has_type_resolve (mono_domain_get ()))
7169                 return NULL;
7170
7171         if (type_resolve) {
7172                 if (*type_resolve) 
7173                         return NULL;
7174                 else
7175                         *type_resolve = TRUE;
7176         }
7177         
7178         /* Reconstruct the type name */
7179         fullName = g_string_new ("");
7180         if (info->name_space && (info->name_space [0] != '\0'))
7181                 g_string_printf (fullName, "%s.%s", info->name_space, info->name);
7182         else
7183                 g_string_printf (fullName, info->name);
7184         for (mod = info->nested; mod; mod = mod->next)
7185                 g_string_append_printf (fullName, "+%s", (char*)mod->data);
7186
7187         assembly = mono_domain_try_type_resolve ( mono_domain_get (), fullName->str, NULL);
7188         if (assembly) {
7189                 if (assembly->assembly->dynamic)
7190                         type = mono_reflection_get_type_internal_dynamic (rootimage, assembly->assembly, info, ignorecase);
7191                 else
7192                         type = mono_reflection_get_type_internal (rootimage, assembly->assembly->image, 
7193                                                                                                           info, ignorecase);
7194         }
7195         g_string_free (fullName, TRUE);
7196         return type;
7197 }
7198
7199 void
7200 mono_reflection_free_type_info (MonoTypeNameParse *info)
7201 {
7202         g_list_free (info->modifiers);
7203         g_list_free (info->nested);
7204
7205         if (info->type_arguments) {
7206                 int i;
7207
7208                 for (i = 0; i < info->type_arguments->len; i++) {
7209                         MonoTypeNameParse *subinfo = g_ptr_array_index (info->type_arguments, i);
7210
7211                         mono_reflection_free_type_info (subinfo);
7212                         /*We free the subinfo since it is allocated by _mono_reflection_parse_type*/
7213                         g_free (subinfo);
7214                 }
7215
7216                 g_ptr_array_free (info->type_arguments, TRUE);
7217         }
7218 }
7219
7220 /*
7221  * mono_reflection_type_from_name:
7222  * @name: type name.
7223  * @image: a metadata context (can be NULL).
7224  *
7225  * Retrieves a MonoType from its @name. If the name is not fully qualified,
7226  * it defaults to get the type from @image or, if @image is NULL or loading
7227  * from it fails, uses corlib.
7228  * 
7229  */
7230 MonoType*
7231 mono_reflection_type_from_name (char *name, MonoImage *image)
7232 {
7233         MonoType *type = NULL;
7234         MonoTypeNameParse info;
7235         char *tmp;
7236
7237         /* Make a copy since parse_type modifies its argument */
7238         tmp = g_strdup (name);
7239         
7240         /*g_print ("requested type %s\n", str);*/
7241         if (mono_reflection_parse_type (tmp, &info)) {
7242                 type = _mono_reflection_get_type_from_info (&info, image, FALSE);
7243         }
7244
7245         g_free (tmp);
7246         mono_reflection_free_type_info (&info);
7247         return type;
7248 }
7249
7250 /*
7251  * mono_reflection_get_token:
7252  *
7253  *   Return the metadata token of OBJ which should be an object
7254  * representing a metadata element.
7255  */
7256 guint32
7257 mono_reflection_get_token (MonoObject *obj)
7258 {
7259         MonoClass *klass;
7260         guint32 token = 0;
7261
7262         klass = obj->vtable->klass;
7263
7264         if (strcmp (klass->name, "MethodBuilder") == 0) {
7265                 MonoReflectionMethodBuilder *mb = (MonoReflectionMethodBuilder *)obj;
7266
7267                 token = mb->table_idx | MONO_TOKEN_METHOD_DEF;
7268         } else if (strcmp (klass->name, "ConstructorBuilder") == 0) {
7269                 MonoReflectionCtorBuilder *mb = (MonoReflectionCtorBuilder *)obj;
7270
7271                 token = mb->table_idx | MONO_TOKEN_METHOD_DEF;
7272         } else if (strcmp (klass->name, "FieldBuilder") == 0) {
7273                 MonoReflectionFieldBuilder *fb = (MonoReflectionFieldBuilder *)obj;
7274
7275                 /* Call mono_image_create_token so the object gets added to the tokens hash table */
7276                 token = mono_image_create_token (((MonoReflectionTypeBuilder*)fb->typeb)->module->dynamic_image, obj, FALSE, TRUE);
7277         } else if (strcmp (klass->name, "TypeBuilder") == 0) {
7278                 MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder *)obj;
7279                 token = tb->table_idx | MONO_TOKEN_TYPE_DEF;
7280         } else if (strcmp (klass->name, "MonoType") == 0) {
7281                 MonoReflectionType *tb = (MonoReflectionType *)obj;
7282                 token = mono_class_from_mono_type (tb->type)->type_token;
7283         } else if (strcmp (klass->name, "MonoCMethod") == 0 ||
7284                    strcmp (klass->name, "MonoMethod") == 0 ||
7285                    strcmp (klass->name, "MonoGenericMethod") == 0 ||
7286                    strcmp (klass->name, "MonoGenericCMethod") == 0) {
7287                 MonoReflectionMethod *m = (MonoReflectionMethod *)obj;
7288                 if (m->method->is_inflated) {
7289                         MonoMethodInflated *inflated = (MonoMethodInflated *) m->method;
7290                         return inflated->declaring->token;
7291                 } else {
7292                         token = m->method->token;
7293                 }
7294         } else if (strcmp (klass->name, "MonoField") == 0) {
7295                 MonoReflectionField *f = (MonoReflectionField*)obj;
7296
7297                 if (is_field_on_inst (f->field)) {
7298                         MonoDynamicGenericClass *dgclass = (MonoDynamicGenericClass*)f->field->parent->generic_class;
7299                         int field_index = f->field - dgclass->fields;
7300                         MonoObject *obj;
7301
7302                         g_assert (field_index >= 0 && field_index < dgclass->count_fields);
7303                         obj = dgclass->field_objects [field_index];
7304                         return mono_reflection_get_token (obj);
7305                 }
7306                 token = mono_class_get_field_token (f->field);
7307         } else if (strcmp (klass->name, "MonoProperty") == 0) {
7308                 MonoReflectionProperty *p = (MonoReflectionProperty*)obj;
7309
7310                 token = mono_class_get_property_token (p->property);
7311         } else if (strcmp (klass->name, "MonoEvent") == 0) {
7312                 MonoReflectionEvent *p = (MonoReflectionEvent*)obj;
7313
7314                 token = mono_class_get_event_token (p->event);
7315         } else if (strcmp (klass->name, "ParameterInfo") == 0) {
7316                 MonoReflectionParameter *p = (MonoReflectionParameter*)obj;
7317
7318                 token = mono_method_get_param_token (((MonoReflectionMethod*)p->MemberImpl)->method, p->PositionImpl);
7319         } else if (strcmp (klass->name, "Module") == 0) {
7320                 MonoReflectionModule *m = (MonoReflectionModule*)obj;
7321
7322                 token = m->token;
7323         } else if (strcmp (klass->name, "Assembly") == 0) {
7324                 token = mono_metadata_make_token (MONO_TABLE_ASSEMBLY, 1);
7325         } else {
7326                 gchar *msg = g_strdup_printf ("MetadataToken is not supported for type '%s.%s'", klass->name_space, klass->name);
7327                 MonoException *ex = mono_get_exception_not_implemented (msg);
7328                 g_free (msg);
7329                 mono_raise_exception (ex);
7330         }
7331
7332         return token;
7333 }
7334
7335 static void*
7336 load_cattr_value (MonoImage *image, MonoType *t, const char *p, const char **end)
7337 {
7338         int slen, type = t->type;
7339         MonoClass *tklass = t->data.klass;
7340
7341 handle_enum:
7342         switch (type) {
7343         case MONO_TYPE_U1:
7344         case MONO_TYPE_I1:
7345         case MONO_TYPE_BOOLEAN: {
7346                 MonoBoolean *bval = g_malloc (sizeof (MonoBoolean));
7347                 *bval = *p;
7348                 *end = p + 1;
7349                 return bval;
7350         }
7351         case MONO_TYPE_CHAR:
7352         case MONO_TYPE_U2:
7353         case MONO_TYPE_I2: {
7354                 guint16 *val = g_malloc (sizeof (guint16));
7355                 *val = read16 (p);
7356                 *end = p + 2;
7357                 return val;
7358         }
7359 #if SIZEOF_VOID_P == 4
7360         case MONO_TYPE_U:
7361         case MONO_TYPE_I:
7362 #endif
7363         case MONO_TYPE_R4:
7364         case MONO_TYPE_U4:
7365         case MONO_TYPE_I4: {
7366                 guint32 *val = g_malloc (sizeof (guint32));
7367                 *val = read32 (p);
7368                 *end = p + 4;
7369                 return val;
7370         }
7371 #if SIZEOF_VOID_P == 8
7372         case MONO_TYPE_U: /* error out instead? this should probably not happen */
7373         case MONO_TYPE_I:
7374 #endif
7375         case MONO_TYPE_U8:
7376         case MONO_TYPE_I8: {
7377                 guint64 *val = g_malloc (sizeof (guint64));
7378                 *val = read64 (p);
7379                 *end = p + 8;
7380                 return val;
7381         }
7382         case MONO_TYPE_R8: {
7383                 double *val = g_malloc (sizeof (double));
7384                 readr8 (p, val);
7385                 *end = p + 8;
7386                 return val;
7387         }
7388         case MONO_TYPE_VALUETYPE:
7389                 if (t->data.klass->enumtype) {
7390                         type = t->data.klass->enum_basetype->type;
7391                         goto handle_enum;
7392                 } else {
7393                         g_error ("generic valutype %s not handled in custom attr value decoding", t->data.klass->name);
7394                 }
7395                 break;
7396         case MONO_TYPE_STRING:
7397                 if (*p == (char)0xFF) {
7398                         *end = p + 1;
7399                         return NULL;
7400                 }
7401                 slen = mono_metadata_decode_value (p, &p);
7402                 *end = p + slen;
7403                 return mono_string_new_len (mono_domain_get (), p, slen);
7404         case MONO_TYPE_CLASS: {
7405                 char *n;
7406                 MonoType *t;
7407                 if (*p == (char)0xFF) {
7408                         *end = p + 1;
7409                         return NULL;
7410                 }
7411 handle_type:
7412                 slen = mono_metadata_decode_value (p, &p);
7413                 n = g_memdup (p, slen + 1);
7414                 n [slen] = 0;
7415                 t = mono_reflection_type_from_name (n, image);
7416                 if (!t)
7417                         g_warning ("Cannot load type '%s'", n);
7418                 g_free (n);
7419                 *end = p + slen;
7420                 if (t)
7421                         return mono_type_get_object (mono_domain_get (), t);
7422                 else
7423                         return NULL;
7424         }
7425         case MONO_TYPE_OBJECT: {
7426                 char subt = *p++;
7427                 MonoObject *obj;
7428                 MonoClass *subc = NULL;
7429                 void *val;
7430
7431                 if (subt == 0x50) {
7432                         goto handle_type;
7433                 } else if (subt == 0x0E) {
7434                         type = MONO_TYPE_STRING;
7435                         goto handle_enum;
7436                 } else if (subt == 0x1D) {
7437                         MonoType simple_type = {{0}};
7438                         int etype = *p;
7439                         p ++;
7440
7441                         if (etype == 0x51)
7442                                 /* See Partition II, Appendix B3 */
7443                                 etype = MONO_TYPE_OBJECT;
7444                         type = MONO_TYPE_SZARRAY;
7445                         simple_type.type = etype;
7446                         tklass = mono_class_from_mono_type (&simple_type);
7447                         goto handle_enum;
7448                 } else if (subt == 0x55) {
7449                         char *n;
7450                         MonoType *t;
7451                         slen = mono_metadata_decode_value (p, &p);
7452                         n = g_memdup (p, slen + 1);
7453                         n [slen] = 0;
7454                         t = mono_reflection_type_from_name (n, image);
7455                         if (!t)
7456                                 g_error ("Cannot load type '%s'", n);
7457                         g_free (n);
7458                         p += slen;
7459                         subc = mono_class_from_mono_type (t);
7460                 } else if (subt >= MONO_TYPE_BOOLEAN && subt <= MONO_TYPE_R8) {
7461                         MonoType simple_type = {{0}};
7462                         simple_type.type = subt;
7463                         subc = mono_class_from_mono_type (&simple_type);
7464                 } else {
7465                         g_error ("Unknown type 0x%02x for object type encoding in custom attr", subt);
7466                 }
7467                 val = load_cattr_value (image, &subc->byval_arg, p, end);
7468                 obj = mono_object_new (mono_domain_get (), subc);
7469                 memcpy ((char*)obj + sizeof (MonoObject), val, mono_class_value_size (subc, NULL));
7470                 g_free (val);
7471                 return obj;
7472         }
7473         case MONO_TYPE_SZARRAY: {
7474                 MonoArray *arr;
7475                 guint32 i, alen, basetype;
7476                 alen = read32 (p);
7477                 p += 4;
7478                 if (alen == 0xffffffff) {
7479                         *end = p;
7480                         return NULL;
7481                 }
7482                 arr = mono_array_new (mono_domain_get(), tklass, alen);
7483                 basetype = tklass->byval_arg.type;
7484                 if (basetype == MONO_TYPE_VALUETYPE && tklass->enumtype)
7485                         basetype = tklass->enum_basetype->type;
7486                 switch (basetype)
7487                 {
7488                         case MONO_TYPE_U1:
7489                         case MONO_TYPE_I1:
7490                         case MONO_TYPE_BOOLEAN:
7491                                 for (i = 0; i < alen; i++) {
7492                                         MonoBoolean val = *p++;
7493                                         mono_array_set (arr, MonoBoolean, i, val);
7494                                 }
7495                                 break;
7496                         case MONO_TYPE_CHAR:
7497                         case MONO_TYPE_U2:
7498                         case MONO_TYPE_I2:
7499                                 for (i = 0; i < alen; i++) {
7500                                         guint16 val = read16 (p);
7501                                         mono_array_set (arr, guint16, i, val);
7502                                         p += 2;
7503                                 }
7504                                 break;
7505                         case MONO_TYPE_R4:
7506                         case MONO_TYPE_U4:
7507                         case MONO_TYPE_I4:
7508                                 for (i = 0; i < alen; i++) {
7509                                         guint32 val = read32 (p);
7510                                         mono_array_set (arr, guint32, i, val);
7511                                         p += 4;
7512                                 }
7513                                 break;
7514                         case MONO_TYPE_R8:
7515                                 for (i = 0; i < alen; i++) {
7516                                         double val;
7517                                         readr8 (p, &val);
7518                                         mono_array_set (arr, double, i, val);
7519                                         p += 8;
7520                                 }
7521                                 break;
7522                         case MONO_TYPE_U8:
7523                         case MONO_TYPE_I8:
7524                                 for (i = 0; i < alen; i++) {
7525                                         guint64 val = read64 (p);
7526                                         mono_array_set (arr, guint64, i, val);
7527                                         p += 8;
7528                                 }
7529                                 break;
7530                         case MONO_TYPE_CLASS:
7531                         case MONO_TYPE_OBJECT:
7532                         case MONO_TYPE_STRING:
7533                                 for (i = 0; i < alen; i++) {
7534                                         MonoObject *item = load_cattr_value (image, &tklass->byval_arg, p, &p);
7535                                         mono_array_setref (arr, i, item);
7536                                 }
7537                                 break;
7538                         default:
7539                                 g_error ("Type 0x%02x not handled in custom attr array decoding", basetype);
7540                 }
7541                 *end=p;
7542                 return arr;
7543         }
7544         default:
7545                 g_error ("Type 0x%02x not handled in custom attr value decoding", type);
7546         }
7547         return NULL;
7548 }
7549
7550 static MonoObject*
7551 create_cattr_typed_arg (MonoType *t, MonoObject *val)
7552 {
7553         static MonoClass *klass;
7554         static MonoMethod *ctor;
7555         MonoObject *retval;
7556         void *params [2], *unboxed;
7557
7558         if (!klass)
7559                 klass = mono_class_from_name (mono_defaults.corlib, "System.Reflection", "CustomAttributeTypedArgument");
7560         if (!ctor)
7561                 ctor = mono_class_get_method_from_name (klass, ".ctor", 2);
7562         
7563         params [0] = mono_type_get_object (mono_domain_get (), t);
7564         params [1] = val;
7565         retval = mono_object_new (mono_domain_get (), klass);
7566         unboxed = mono_object_unbox (retval);
7567         mono_runtime_invoke (ctor, unboxed, params, NULL);
7568
7569         return retval;
7570 }
7571
7572 static MonoObject*
7573 create_cattr_named_arg (void *minfo, MonoObject *typedarg)
7574 {
7575         static MonoClass *klass;
7576         static MonoMethod *ctor;
7577         MonoObject *retval;
7578         void *unboxed, *params [2];
7579
7580         if (!klass)
7581                 klass = mono_class_from_name (mono_defaults.corlib, "System.Reflection", "CustomAttributeNamedArgument");
7582         if (!ctor)
7583                 ctor = mono_class_get_method_from_name (klass, ".ctor", 2);
7584
7585         params [0] = minfo;
7586         params [1] = typedarg;
7587         retval = mono_object_new (mono_domain_get (), klass);
7588         unboxed = mono_object_unbox (retval);
7589         mono_runtime_invoke (ctor, unboxed, params, NULL);
7590
7591         return retval;
7592 }
7593
7594 static gboolean
7595 type_is_reference (MonoType *type)
7596 {
7597         switch (type->type) {
7598         case MONO_TYPE_BOOLEAN:
7599         case MONO_TYPE_CHAR:
7600         case MONO_TYPE_U:
7601         case MONO_TYPE_I:
7602         case MONO_TYPE_U1:
7603         case MONO_TYPE_I1:
7604         case MONO_TYPE_U2:
7605         case MONO_TYPE_I2:
7606         case MONO_TYPE_U4:
7607         case MONO_TYPE_I4:
7608         case MONO_TYPE_U8:
7609         case MONO_TYPE_I8:
7610         case MONO_TYPE_R8:
7611         case MONO_TYPE_R4:
7612         case MONO_TYPE_VALUETYPE:
7613                 return FALSE;
7614         default:
7615                 return TRUE;
7616         }
7617 }
7618
7619 static void
7620 free_param_data (MonoMethodSignature *sig, void **params) {
7621         int i;
7622         for (i = 0; i < sig->param_count; ++i) {
7623                 if (!type_is_reference (sig->params [i]))
7624                         g_free (params [i]);
7625         }
7626 }
7627
7628 /*
7629  * Find the field index in the metadata FieldDef table.
7630  */
7631 static guint32
7632 find_field_index (MonoClass *klass, MonoClassField *field) {
7633         int i;
7634
7635         for (i = 0; i < klass->field.count; ++i) {
7636                 if (field == &klass->fields [i])
7637                         return klass->field.first + 1 + i;
7638         }
7639         return 0;
7640 }
7641
7642 /*
7643  * Find the property index in the metadata Property table.
7644  */
7645 static guint32
7646 find_property_index (MonoClass *klass, MonoProperty *property) {
7647         int i;
7648
7649         for (i = 0; i < klass->property.count; ++i) {
7650                 if (property == &klass->properties [i])
7651                         return klass->property.first + 1 + i;
7652         }
7653         return 0;
7654 }
7655
7656 /*
7657  * Find the event index in the metadata Event table.
7658  */
7659 static guint32
7660 find_event_index (MonoClass *klass, MonoEvent *event) {
7661         int i;
7662
7663         for (i = 0; i < klass->event.count; ++i) {
7664                 if (event == &klass->events [i])
7665                         return klass->event.first + 1 + i;
7666         }
7667         return 0;
7668 }
7669
7670 static MonoObject*
7671 create_custom_attr (MonoImage *image, MonoMethod *method, const guchar *data, guint32 len)
7672 {
7673         const char *p = (const char*)data;
7674         const char *named;
7675         guint32 i, j, num_named;
7676         MonoObject *attr;
7677         void **params;
7678
7679         mono_class_init (method->klass);
7680
7681         if (len == 0) {
7682                 attr = mono_object_new (mono_domain_get (), method->klass);
7683                 mono_runtime_invoke (method, attr, NULL, NULL);
7684                 return attr;
7685         }
7686
7687         if (len < 2 || read16 (p) != 0x0001) /* Prolog */
7688                 return NULL;
7689
7690         /*g_print ("got attr %s\n", method->klass->name);*/
7691
7692         /* Allocate using alloca so it gets GC tracking */
7693         params = alloca (mono_method_signature (method)->param_count * sizeof (void*)); 
7694
7695         /* skip prolog */
7696         p += 2;
7697         for (i = 0; i < mono_method_signature (method)->param_count; ++i) {
7698                 params [i] = load_cattr_value (image, mono_method_signature (method)->params [i], p, &p);
7699         }
7700
7701         named = p;
7702         attr = mono_object_new (mono_domain_get (), method->klass);
7703         mono_runtime_invoke (method, attr, params, NULL);
7704         free_param_data (method->signature, params);
7705         num_named = read16 (named);
7706         named += 2;
7707         for (j = 0; j < num_named; j++) {
7708                 gint name_len;
7709                 char *name, named_type, data_type;
7710                 named_type = *named++;
7711                 data_type = *named++; /* type of data */
7712                 if (data_type == MONO_TYPE_SZARRAY)
7713                         data_type = *named++;
7714                 if (data_type == MONO_TYPE_ENUM) {
7715                         gint type_len;
7716                         char *type_name;
7717                         type_len = mono_metadata_decode_blob_size (named, &named);
7718                         type_name = g_malloc (type_len + 1);
7719                         memcpy (type_name, named, type_len);
7720                         type_name [type_len] = 0;
7721                         named += type_len;
7722                         /* FIXME: lookup the type and check type consistency */
7723                         g_free (type_name);
7724                 }
7725                 name_len = mono_metadata_decode_blob_size (named, &named);
7726                 name = g_malloc (name_len + 1);
7727                 memcpy (name, named, name_len);
7728                 name [name_len] = 0;
7729                 named += name_len;
7730                 if (named_type == 0x53) {
7731                         MonoClassField *field = mono_class_get_field_from_name (mono_object_class (attr), name);
7732                         void *val = load_cattr_value (image, field->type, named, &named);
7733                         mono_field_set_value (attr, field, val);
7734                         if (!type_is_reference (field->type))
7735                                 g_free (val);
7736                 } else if (named_type == 0x54) {
7737                         MonoProperty *prop;
7738                         void *pparams [1];
7739                         MonoType *prop_type;
7740
7741                         prop = mono_class_get_property_from_name (mono_object_class (attr), name);
7742                         /* can we have more that 1 arg in a custom attr named property? */
7743                         prop_type = prop->get? mono_method_signature (prop->get)->ret :
7744                              mono_method_signature (prop->set)->params [mono_method_signature (prop->set)->param_count - 1];
7745                         pparams [0] = load_cattr_value (image, prop_type, named, &named);
7746                         mono_property_set_value (prop, attr, pparams, NULL);
7747                         if (!type_is_reference (prop_type))
7748                                 g_free (pparams [0]);
7749                 }
7750                 g_free (name);
7751         }
7752
7753         return attr;
7754 }
7755
7756 static MonoObject*
7757 create_custom_attr_data (MonoImage *image, MonoMethod *method, const guchar *data, guint32 len)
7758 {
7759         MonoArray *typedargs, *namedargs;
7760         MonoClass *attrklass;
7761         static MonoMethod *ctor;
7762         MonoDomain *domain;
7763         MonoObject *attr;
7764         const char *p = (const char*)data;
7765         const char *named;
7766         guint32 i, j, num_named;
7767         void *params [3];
7768
7769         mono_class_init (method->klass);
7770
7771         if (!ctor)
7772                 ctor = mono_class_get_method_from_name (mono_defaults.customattribute_data_class, ".ctor", 3);
7773
7774         domain = mono_domain_get ();
7775         if (len == 0) {
7776                 /* This is for Attributes with no parameters */
7777                 attr = mono_object_new (domain, mono_defaults.customattribute_data_class);
7778                 params [0] = mono_method_get_object (domain, method, NULL);
7779                 params [1] = params [2] = NULL;
7780                 mono_runtime_invoke (method, attr, params, NULL);
7781                 return attr;
7782         }
7783
7784         if (len < 2 || read16 (p) != 0x0001) /* Prolog */
7785                 return NULL;
7786
7787         typedargs = mono_array_new (domain, mono_get_object_class (), mono_method_signature (method)->param_count);
7788         
7789         /* skip prolog */
7790         p += 2;
7791         for (i = 0; i < mono_method_signature (method)->param_count; ++i) {
7792                 MonoObject *obj, *typedarg;
7793                 void *val;
7794
7795                 val = load_cattr_value (image, mono_method_signature (method)->params [i], p, &p);
7796                 obj = type_is_reference (mono_method_signature (method)->params [i]) ? 
7797                         val : mono_value_box (domain, mono_class_from_mono_type (mono_method_signature (method)->params [i]), val);
7798                 typedarg = create_cattr_typed_arg (mono_method_signature (method)->params [i], obj);
7799                 mono_array_setref (typedargs, i, typedarg);
7800
7801                 if (!type_is_reference (mono_method_signature (method)->params [i]))
7802                         g_free (val);
7803         }
7804
7805         named = p;
7806         num_named = read16 (named);
7807         namedargs = mono_array_new (domain, mono_get_object_class (), num_named);
7808         named += 2;
7809         attrklass = method->klass;
7810         for (j = 0; j < num_named; j++) {
7811                 gint name_len;
7812                 char *name, named_type, data_type;
7813                 named_type = *named++;
7814                 data_type = *named++; /* type of data */
7815                 if (data_type == MONO_TYPE_SZARRAY)
7816                         data_type = *named++;
7817                 if (data_type == MONO_TYPE_ENUM) {
7818                         gint type_len;
7819                         char *type_name;
7820                         type_len = mono_metadata_decode_blob_size (named, &named);
7821                         type_name = g_malloc (type_len + 1);
7822                         memcpy (type_name, named, type_len);
7823                         type_name [type_len] = 0;
7824                         named += type_len;
7825                         /* FIXME: lookup the type and check type consistency */
7826                         g_free (type_name);
7827                 }
7828                 name_len = mono_metadata_decode_blob_size (named, &named);
7829                 name = g_malloc (name_len + 1);
7830                 memcpy (name, named, name_len);
7831                 name [name_len] = 0;
7832                 named += name_len;
7833                 if (named_type == 0x53) {
7834                         MonoObject *obj, *typedarg, *namedarg;
7835                         MonoClassField *field = mono_class_get_field_from_name (attrklass, name);
7836                         void *minfo, *val = load_cattr_value (image, field->type, named, &named);
7837                         
7838                         minfo = mono_field_get_object (domain, NULL, field);
7839                         obj = type_is_reference (field->type) ? val : mono_value_box (domain, mono_class_from_mono_type (field->type), val);
7840                         typedarg = create_cattr_typed_arg (field->type, obj);
7841                         namedarg = create_cattr_named_arg (minfo, typedarg);
7842                         mono_array_setref (namedargs, j, namedarg);
7843                         if (!type_is_reference (field->type))
7844                                 g_free (val);
7845                 } else if (named_type == 0x54) {
7846                         MonoObject *obj, *typedarg, *namedarg;
7847                         MonoType *prop_type;
7848                         void *val, *minfo;
7849                         MonoProperty *prop = mono_class_get_property_from_name (attrklass, name);
7850
7851                         prop_type = prop->get? mono_method_signature (prop->get)->ret :
7852                              mono_method_signature (prop->set)->params [mono_method_signature (prop->set)->param_count - 1];
7853                         minfo =  mono_property_get_object (domain, NULL, prop);
7854                         val = load_cattr_value (image, prop_type, named, &named);
7855                         obj = type_is_reference (prop_type) ? val : mono_value_box (domain, mono_class_from_mono_type (prop_type), val);
7856                         typedarg = create_cattr_typed_arg (prop_type, obj);
7857                         namedarg = create_cattr_named_arg (minfo, typedarg);
7858                         mono_array_setref (namedargs, j, namedarg);
7859                         if (!type_is_reference (prop_type))
7860                                 g_free (val);
7861                 }
7862                 g_free (name);
7863         }
7864         attr = mono_object_new (domain, mono_defaults.customattribute_data_class);
7865         params [0] = mono_method_get_object (domain, method, NULL);
7866         params [1] = typedargs;
7867         params [2] = namedargs;
7868         mono_runtime_invoke (ctor, attr, params, NULL);
7869         return attr;
7870 }
7871
7872 MonoArray*
7873 mono_custom_attrs_construct (MonoCustomAttrInfo *cinfo)
7874 {
7875         MonoArray *result;
7876         MonoObject *attr;
7877         int i;
7878
7879         result = mono_array_new (mono_domain_get (), mono_defaults.attribute_class, cinfo->num_attrs);
7880         for (i = 0; i < cinfo->num_attrs; ++i) {
7881                 if (!cinfo->attrs [i].ctor)
7882                         /* The cattr type is not finished yet */
7883                         /* We should include the type name but cinfo doesn't contain it */
7884                         mono_raise_exception (mono_get_exception_type_load (NULL, NULL));
7885                 attr = create_custom_attr (cinfo->image, cinfo->attrs [i].ctor, cinfo->attrs [i].data, cinfo->attrs [i].data_size);
7886                 mono_array_setref (result, i, attr);
7887         }
7888         return result;
7889 }
7890
7891 static MonoArray*
7892 mono_custom_attrs_construct_by_type (MonoCustomAttrInfo *cinfo, MonoClass *attr_klass)
7893 {
7894         MonoArray *result;
7895         MonoObject *attr;
7896         int i, n;
7897
7898         n = 0;
7899         for (i = 0; i < cinfo->num_attrs; ++i) {
7900                 if (mono_class_is_assignable_from (attr_klass, cinfo->attrs [i].ctor->klass))
7901                         n ++;
7902         }
7903
7904         result = mono_array_new (mono_domain_get (), mono_defaults.attribute_class, n);
7905         n = 0;
7906         for (i = 0; i < cinfo->num_attrs; ++i) {
7907                 if (mono_class_is_assignable_from (attr_klass, cinfo->attrs [i].ctor->klass)) {
7908                         attr = create_custom_attr (cinfo->image, cinfo->attrs [i].ctor, cinfo->attrs [i].data, cinfo->attrs [i].data_size);
7909                         mono_array_setref (result, n, attr);
7910                         n ++;
7911                 }
7912         }
7913         return result;
7914 }
7915
7916 static MonoArray*
7917 mono_custom_attrs_data_construct (MonoCustomAttrInfo *cinfo)
7918 {
7919         MonoArray *result;
7920         MonoObject *attr;
7921         int i;
7922         
7923         result = mono_array_new (mono_domain_get (), mono_defaults.customattribute_data_class, cinfo->num_attrs);
7924         for (i = 0; i < cinfo->num_attrs; ++i) {
7925                 attr = create_custom_attr_data (cinfo->image, cinfo->attrs [i].ctor, cinfo->attrs [i].data, cinfo->attrs [i].data_size);
7926                 mono_array_setref (result, i, attr);
7927         }
7928         return result;
7929 }
7930
7931 /**
7932  * mono_custom_attrs_from_index:
7933  *
7934  * Returns: NULL if no attributes are found or if a loading error occurs.
7935  */
7936 MonoCustomAttrInfo*
7937 mono_custom_attrs_from_index (MonoImage *image, guint32 idx)
7938 {
7939         guint32 mtoken, i, len;
7940         guint32 cols [MONO_CUSTOM_ATTR_SIZE];
7941         MonoTableInfo *ca;
7942         MonoCustomAttrInfo *ainfo;
7943         GList *tmp, *list = NULL;
7944         const char *data;
7945
7946         ca = &image->tables [MONO_TABLE_CUSTOMATTRIBUTE];
7947
7948         i = mono_metadata_custom_attrs_from_index (image, idx);
7949         if (!i)
7950                 return NULL;
7951         i --;
7952         while (i < ca->rows) {
7953                 if (mono_metadata_decode_row_col (ca, i, MONO_CUSTOM_ATTR_PARENT) != idx)
7954                         break;
7955                 list = g_list_prepend (list, GUINT_TO_POINTER (i));
7956                 ++i;
7957         }
7958         len = g_list_length (list);
7959         if (!len)
7960                 return NULL;
7961         ainfo = g_malloc0 (sizeof (MonoCustomAttrInfo) + sizeof (MonoCustomAttrEntry) * (len - MONO_ZERO_LEN_ARRAY));
7962         ainfo->num_attrs = len;
7963         ainfo->image = image;
7964         for (i = 0, tmp = list; i < len; ++i, tmp = tmp->next) {
7965                 mono_metadata_decode_row (ca, GPOINTER_TO_UINT (tmp->data), cols, MONO_CUSTOM_ATTR_SIZE);
7966                 mtoken = cols [MONO_CUSTOM_ATTR_TYPE] >> MONO_CUSTOM_ATTR_TYPE_BITS;
7967                 switch (cols [MONO_CUSTOM_ATTR_TYPE] & MONO_CUSTOM_ATTR_TYPE_MASK) {
7968                 case MONO_CUSTOM_ATTR_TYPE_METHODDEF:
7969                         mtoken |= MONO_TOKEN_METHOD_DEF;
7970                         break;
7971                 case MONO_CUSTOM_ATTR_TYPE_MEMBERREF:
7972                         mtoken |= MONO_TOKEN_MEMBER_REF;
7973                         break;
7974                 default:
7975                         g_error ("Unknown table for custom attr type %08x", cols [MONO_CUSTOM_ATTR_TYPE]);
7976                         break;
7977                 }
7978                 ainfo->attrs [i].ctor = mono_get_method (image, mtoken, NULL);
7979                 if (!ainfo->attrs [i].ctor) {
7980                         g_warning ("Can't find custom attr constructor image: %s mtoken: 0x%08x", image->name, mtoken);
7981                         g_list_free (list);
7982                         g_free (ainfo);
7983                         return NULL;
7984                 }
7985                 data = mono_metadata_blob_heap (image, cols [MONO_CUSTOM_ATTR_VALUE]);
7986                 ainfo->attrs [i].data_size = mono_metadata_decode_value (data, &data);
7987                 ainfo->attrs [i].data = (guchar*)data;
7988         }
7989         g_list_free (list);
7990
7991         return ainfo;
7992 }
7993
7994 MonoCustomAttrInfo*
7995 mono_custom_attrs_from_method (MonoMethod *method)
7996 {
7997         guint32 idx;
7998
7999         /*
8000          * An instantiated method has the same cattrs as the generic method definition.
8001          *
8002          * LAMESPEC: The .NET SRE throws an exception for instantiations of generic method builders
8003          *           Note that this stanza is not necessary for non-SRE types, but it's a micro-optimization
8004          */
8005         if (method->is_inflated)
8006                 method = ((MonoMethodInflated *) method)->declaring;
8007         
8008         if (method->dynamic || method->klass->image->dynamic)
8009                 return lookup_custom_attr (method->klass->image, method);
8010
8011         idx = mono_method_get_index (method);
8012         idx <<= MONO_CUSTOM_ATTR_BITS;
8013         idx |= MONO_CUSTOM_ATTR_METHODDEF;
8014         return mono_custom_attrs_from_index (method->klass->image, idx);
8015 }
8016
8017 MonoCustomAttrInfo*
8018 mono_custom_attrs_from_class (MonoClass *klass)
8019 {
8020         guint32 idx;
8021
8022         if (klass->generic_class)
8023                 klass = klass->generic_class->container_class;
8024
8025         if (klass->image->dynamic)
8026                 return lookup_custom_attr (klass->image, klass);
8027
8028         if (klass->byval_arg.type == MONO_TYPE_VAR || klass->byval_arg.type == MONO_TYPE_MVAR) {
8029                 idx = mono_metadata_token_index (klass->sizes.generic_param_token);
8030                 idx <<= MONO_CUSTOM_ATTR_BITS;
8031                 idx |= MONO_CUSTOM_ATTR_GENERICPAR;
8032         } else {
8033                 idx = mono_metadata_token_index (klass->type_token);
8034                 idx <<= MONO_CUSTOM_ATTR_BITS;
8035                 idx |= MONO_CUSTOM_ATTR_TYPEDEF;
8036         }
8037         return mono_custom_attrs_from_index (klass->image, idx);
8038 }
8039
8040 MonoCustomAttrInfo*
8041 mono_custom_attrs_from_assembly (MonoAssembly *assembly)
8042 {
8043         guint32 idx;
8044         
8045         if (assembly->image->dynamic)
8046                 return lookup_custom_attr (assembly->image, assembly);
8047         idx = 1; /* there is only one assembly */
8048         idx <<= MONO_CUSTOM_ATTR_BITS;
8049         idx |= MONO_CUSTOM_ATTR_ASSEMBLY;
8050         return mono_custom_attrs_from_index (assembly->image, idx);
8051 }
8052
8053 static MonoCustomAttrInfo*
8054 mono_custom_attrs_from_module (MonoImage *image)
8055 {
8056         guint32 idx;
8057         
8058         if (image->dynamic)
8059                 return lookup_custom_attr (image, image);
8060         idx = 1; /* there is only one module */
8061         idx <<= MONO_CUSTOM_ATTR_BITS;
8062         idx |= MONO_CUSTOM_ATTR_MODULE;
8063         return mono_custom_attrs_from_index (image, idx);
8064 }
8065
8066 MonoCustomAttrInfo*
8067 mono_custom_attrs_from_property (MonoClass *klass, MonoProperty *property)
8068 {
8069         guint32 idx;
8070         
8071         if (klass->image->dynamic) {
8072                 property = mono_metadata_get_corresponding_property_from_generic_type_definition (property);
8073                 return lookup_custom_attr (klass->image, property);
8074         }
8075         idx = find_property_index (klass, property);
8076         idx <<= MONO_CUSTOM_ATTR_BITS;
8077         idx |= MONO_CUSTOM_ATTR_PROPERTY;
8078         return mono_custom_attrs_from_index (klass->image, idx);
8079 }
8080
8081 MonoCustomAttrInfo*
8082 mono_custom_attrs_from_event (MonoClass *klass, MonoEvent *event)
8083 {
8084         guint32 idx;
8085         
8086         if (klass->image->dynamic) {
8087                 event = mono_metadata_get_corresponding_event_from_generic_type_definition (event);
8088                 return lookup_custom_attr (klass->image, event);
8089         }
8090         idx = find_event_index (klass, event);
8091         idx <<= MONO_CUSTOM_ATTR_BITS;
8092         idx |= MONO_CUSTOM_ATTR_EVENT;
8093         return mono_custom_attrs_from_index (klass->image, idx);
8094 }
8095
8096 MonoCustomAttrInfo*
8097 mono_custom_attrs_from_field (MonoClass *klass, MonoClassField *field)
8098 {
8099         guint32 idx;
8100         if (klass->image->dynamic) {
8101                 field = mono_metadata_get_corresponding_field_from_generic_type_definition (field);
8102                 return lookup_custom_attr (klass->image, field);
8103         }
8104         idx = find_field_index (klass, field);
8105         idx <<= MONO_CUSTOM_ATTR_BITS;
8106         idx |= MONO_CUSTOM_ATTR_FIELDDEF;
8107         return mono_custom_attrs_from_index (klass->image, idx);
8108 }
8109
8110 MonoCustomAttrInfo*
8111 mono_custom_attrs_from_param (MonoMethod *method, guint32 param)
8112 {
8113         MonoTableInfo *ca;
8114         guint32 i, idx, method_index;
8115         guint32 param_list, param_last, param_pos, found;
8116         MonoImage *image;
8117         MonoReflectionMethodAux *aux;
8118
8119         /*
8120          * An instantiated method has the same cattrs as the generic method definition.
8121          *
8122          * LAMESPEC: The .NET SRE throws an exception for instantiations of generic method builders
8123          *           Note that this stanza is not necessary for non-SRE types, but it's a micro-optimization
8124          */
8125         if (method->is_inflated)
8126                 method = ((MonoMethodInflated *) method)->declaring;
8127
8128         if (method->klass->image->dynamic) {
8129                 MonoCustomAttrInfo *res, *ainfo;
8130                 int size;
8131
8132                 aux = g_hash_table_lookup (((MonoDynamicImage*)method->klass->image)->method_aux_hash, method);
8133                 if (!aux || !aux->param_cattr)
8134                         return NULL;
8135
8136                 /* Need to copy since it will be freed later */
8137                 ainfo = aux->param_cattr [param];
8138                 size = sizeof (MonoCustomAttrInfo) + sizeof (MonoCustomAttrEntry) * (ainfo->num_attrs - MONO_ZERO_LEN_ARRAY);
8139                 res = g_malloc0 (size);
8140                 memcpy (res, ainfo, size);
8141                 return res;
8142         }
8143
8144         image = method->klass->image;
8145         method_index = mono_method_get_index (method);
8146         ca = &image->tables [MONO_TABLE_METHOD];
8147
8148         param_list = mono_metadata_decode_row_col (ca, method_index - 1, MONO_METHOD_PARAMLIST);
8149         if (method_index == ca->rows) {
8150                 ca = &image->tables [MONO_TABLE_PARAM];
8151                 param_last = ca->rows + 1;
8152         } else {
8153                 param_last = mono_metadata_decode_row_col (ca, method_index, MONO_METHOD_PARAMLIST);
8154                 ca = &image->tables [MONO_TABLE_PARAM];
8155         }
8156         found = FALSE;
8157         for (i = param_list; i < param_last; ++i) {
8158                 param_pos = mono_metadata_decode_row_col (ca, i - 1, MONO_PARAM_SEQUENCE);
8159                 if (param_pos == param) {
8160                         found = TRUE;
8161                         break;
8162                 }
8163         }
8164         if (!found)
8165                 return NULL;
8166         idx = i;
8167         idx <<= MONO_CUSTOM_ATTR_BITS;
8168         idx |= MONO_CUSTOM_ATTR_PARAMDEF;
8169         return mono_custom_attrs_from_index (image, idx);
8170 }
8171
8172 gboolean
8173 mono_custom_attrs_has_attr (MonoCustomAttrInfo *ainfo, MonoClass *attr_klass)
8174 {
8175         int i;
8176         MonoClass *klass;
8177         for (i = 0; i < ainfo->num_attrs; ++i) {
8178                 klass = ainfo->attrs [i].ctor->klass;
8179                 if (mono_class_has_parent (klass, attr_klass))
8180                         return TRUE;
8181         }
8182         return FALSE;
8183 }
8184
8185 MonoObject*
8186 mono_custom_attrs_get_attr (MonoCustomAttrInfo *ainfo, MonoClass *attr_klass)
8187 {
8188         int i, attr_index;
8189         MonoClass *klass;
8190         MonoArray *attrs;
8191
8192         attr_index = -1;
8193         for (i = 0; i < ainfo->num_attrs; ++i) {
8194                 klass = ainfo->attrs [i].ctor->klass;
8195                 if (mono_class_has_parent (klass, attr_klass)) {
8196                         attr_index = i;
8197                         break;
8198                 }
8199         }
8200         if (attr_index == -1)
8201                 return NULL;
8202
8203         attrs = mono_custom_attrs_construct (ainfo);
8204         if (attrs)
8205                 return mono_array_get (attrs, MonoObject*, attr_index);
8206         else
8207                 return NULL;
8208 }
8209
8210 /*
8211  * mono_reflection_get_custom_attrs_info:
8212  * @obj: a reflection object handle
8213  *
8214  * Return the custom attribute info for attributes defined for the
8215  * reflection handle @obj. The objects.
8216  */
8217 MonoCustomAttrInfo*
8218 mono_reflection_get_custom_attrs_info (MonoObject *obj)
8219 {
8220         MonoClass *klass;
8221         MonoCustomAttrInfo *cinfo = NULL;
8222         
8223         klass = obj->vtable->klass;
8224         if (klass == mono_defaults.monotype_class) {
8225                 MonoReflectionType *rtype = (MonoReflectionType*)obj;
8226                 klass = mono_class_from_mono_type (rtype->type);
8227                 cinfo = mono_custom_attrs_from_class (klass);
8228         } else if (strcmp ("Assembly", klass->name) == 0) {
8229                 MonoReflectionAssembly *rassembly = (MonoReflectionAssembly*)obj;
8230                 cinfo = mono_custom_attrs_from_assembly (rassembly->assembly);
8231         } else if (strcmp ("Module", klass->name) == 0) {
8232                 MonoReflectionModule *module = (MonoReflectionModule*)obj;
8233                 cinfo = mono_custom_attrs_from_module (module->image);
8234         } else if (strcmp ("MonoProperty", klass->name) == 0) {
8235                 MonoReflectionProperty *rprop = (MonoReflectionProperty*)obj;
8236                 cinfo = mono_custom_attrs_from_property (rprop->property->parent, rprop->property);
8237         } else if (strcmp ("MonoEvent", klass->name) == 0) {
8238                 MonoReflectionEvent *revent = (MonoReflectionEvent*)obj;
8239                 cinfo = mono_custom_attrs_from_event (revent->event->parent, revent->event);
8240         } else if (strcmp ("MonoField", klass->name) == 0) {
8241                 MonoReflectionField *rfield = (MonoReflectionField*)obj;
8242                 cinfo = mono_custom_attrs_from_field (rfield->field->parent, rfield->field);
8243         } else if ((strcmp ("MonoMethod", klass->name) == 0) || (strcmp ("MonoCMethod", klass->name) == 0)) {
8244                 MonoReflectionMethod *rmethod = (MonoReflectionMethod*)obj;
8245                 cinfo = mono_custom_attrs_from_method (rmethod->method);
8246         } else if ((strcmp ("MonoGenericMethod", klass->name) == 0) || (strcmp ("MonoGenericCMethod", klass->name) == 0)) {
8247                 MonoReflectionMethod *rmethod = (MonoReflectionMethod*)obj;
8248                 cinfo = mono_custom_attrs_from_method (rmethod->method);
8249         } else if (strcmp ("ParameterInfo", klass->name) == 0) {
8250                 MonoReflectionParameter *param = (MonoReflectionParameter*)obj;
8251                 MonoReflectionMethod *rmethod = (MonoReflectionMethod*)param->MemberImpl;
8252                 cinfo = mono_custom_attrs_from_param (rmethod->method, param->PositionImpl + 1);
8253         } else if (strcmp ("AssemblyBuilder", klass->name) == 0) {
8254                 MonoReflectionAssemblyBuilder *assemblyb = (MonoReflectionAssemblyBuilder*)obj;
8255                 cinfo = mono_custom_attrs_from_builders (NULL, assemblyb->assembly.assembly->image, assemblyb->cattrs);
8256         } else if (strcmp ("TypeBuilder", klass->name) == 0) {
8257                 MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder*)obj;
8258                 cinfo = mono_custom_attrs_from_builders (NULL, &tb->module->dynamic_image->image, tb->cattrs);
8259         } else if (strcmp ("ModuleBuilder", klass->name) == 0) {
8260                 MonoReflectionModuleBuilder *mb = (MonoReflectionModuleBuilder*)obj;
8261                 cinfo = mono_custom_attrs_from_builders (NULL, &mb->dynamic_image->image, mb->cattrs);
8262         } else if (strcmp ("ConstructorBuilder", klass->name) == 0) {
8263                 MonoReflectionCtorBuilder *cb = (MonoReflectionCtorBuilder*)obj;
8264                 cinfo = mono_custom_attrs_from_builders (NULL, cb->mhandle->klass->image, cb->cattrs);
8265         } else if (strcmp ("MethodBuilder", klass->name) == 0) {
8266                 MonoReflectionMethodBuilder *mb = (MonoReflectionMethodBuilder*)obj;
8267                 cinfo = mono_custom_attrs_from_builders (NULL, mb->mhandle->klass->image, mb->cattrs);
8268         } else if (strcmp ("FieldBuilder", klass->name) == 0) {
8269                 MonoReflectionFieldBuilder *fb = (MonoReflectionFieldBuilder*)obj;
8270                 cinfo = mono_custom_attrs_from_builders (NULL, &((MonoReflectionTypeBuilder*)fb->typeb)->module->dynamic_image->image, fb->cattrs);
8271         } else if (strcmp ("MonoGenericClass", klass->name) == 0) {
8272                 MonoReflectionGenericClass *gclass = (MonoReflectionGenericClass*)obj;
8273                 cinfo = mono_reflection_get_custom_attrs_info ((MonoObject*)gclass->generic_type);
8274         } else { /* handle other types here... */
8275                 g_error ("get custom attrs not yet supported for %s", klass->name);
8276         }
8277
8278         return cinfo;
8279 }
8280
8281 /*
8282  * mono_reflection_get_custom_attrs_by_type:
8283  * @obj: a reflection object handle
8284  *
8285  * Return an array with all the custom attributes defined of the
8286  * reflection handle @obj. If @attr_klass is non-NULL, only custom attributes 
8287  * of that type are returned. The objects are fully build. Return NULL if a loading error
8288  * occurs.
8289  */
8290 MonoArray*
8291 mono_reflection_get_custom_attrs_by_type (MonoObject *obj, MonoClass *attr_klass)
8292 {
8293         MonoArray *result;
8294         MonoCustomAttrInfo *cinfo;
8295
8296         cinfo = mono_reflection_get_custom_attrs_info (obj);
8297         if (cinfo) {
8298                 if (attr_klass)
8299                         result = mono_custom_attrs_construct_by_type (cinfo, attr_klass);
8300                 else
8301                         result = mono_custom_attrs_construct (cinfo);
8302                 if (!cinfo->cached)
8303                         mono_custom_attrs_free (cinfo);
8304         } else {
8305                 if (mono_loader_get_last_error ())
8306                         return NULL;
8307                 result = mono_array_new (mono_domain_get (), mono_defaults.attribute_class, 0);
8308         }
8309
8310         return result;
8311 }
8312
8313 /*
8314  * mono_reflection_get_custom_attrs:
8315  * @obj: a reflection object handle
8316  *
8317  * Return an array with all the custom attributes defined of the
8318  * reflection handle @obj. The objects are fully build. Return NULL if a loading error
8319  * occurs.
8320  */
8321 MonoArray*
8322 mono_reflection_get_custom_attrs (MonoObject *obj)
8323 {
8324         return mono_reflection_get_custom_attrs_by_type (obj, NULL);
8325 }
8326
8327 /*
8328  * mono_reflection_get_custom_attrs_data:
8329  * @obj: a reflection obj handle
8330  *
8331  * Returns an array of System.Reflection.CustomAttributeData,
8332  * which include information about attributes reflected on
8333  * types loaded using the Reflection Only methods
8334  */
8335 MonoArray*
8336 mono_reflection_get_custom_attrs_data (MonoObject *obj)
8337 {
8338         MonoArray *result;
8339         MonoCustomAttrInfo *cinfo;
8340
8341         cinfo = mono_reflection_get_custom_attrs_info (obj);
8342         if (cinfo) {
8343                 result = mono_custom_attrs_data_construct (cinfo);
8344                 if (!cinfo->cached)
8345                         mono_custom_attrs_free (cinfo);
8346         } else
8347                 result = mono_array_new (mono_domain_get (), mono_defaults.customattribute_data_class, 0);
8348
8349         return result;
8350 }
8351
8352 static MonoReflectionType*
8353 mono_reflection_type_get_underlying_system_type (MonoReflectionType* t)
8354 {
8355         MonoMethod *method_get_underlying_system_type;
8356
8357         method_get_underlying_system_type = mono_object_get_virtual_method ((MonoObject *) t,
8358                                                                             mono_class_get_method_from_name (mono_object_class (t),
8359                                                                                                              "get_UnderlyingSystemType",
8360                                                                                                              0));
8361         return (MonoReflectionType *) mono_runtime_invoke (method_get_underlying_system_type, t, NULL, NULL);
8362 }
8363
8364 static MonoType*
8365 mono_reflection_type_get_handle (MonoReflectionType* t)
8366 {
8367         if (t->type)
8368             return t->type;
8369
8370         t = mono_reflection_type_get_underlying_system_type (t);
8371         if (t)
8372             return t->type;
8373
8374         return NULL;
8375 }
8376
8377 /**
8378  * LOCKING: Assumes the loader lock is held.
8379  */
8380 static MonoMethodSignature*
8381 parameters_to_signature (MonoMemPool *mp, MonoArray *parameters) {
8382         MonoMethodSignature *sig;
8383         int count, i;
8384
8385         count = parameters? mono_array_length (parameters): 0;
8386
8387         sig = mp_g_malloc0 (mp, sizeof (MonoMethodSignature) + sizeof (MonoType*) * count);
8388         sig->param_count = count;
8389         sig->sentinelpos = -1; /* FIXME */
8390         for (i = 0; i < count; ++i) {
8391                 MonoReflectionType *pt = mono_array_get (parameters, MonoReflectionType*, i);
8392                 sig->params [i] = mono_reflection_type_get_handle (pt);
8393         }
8394         return sig;
8395 }
8396
8397 /**
8398  * LOCKING: Assumes the loader lock is held.
8399  */
8400 static MonoMethodSignature*
8401 ctor_builder_to_signature (MonoMemPool *mp, MonoReflectionCtorBuilder *ctor) {
8402         MonoMethodSignature *sig;
8403
8404         sig = parameters_to_signature (mp, ctor->parameters);
8405         sig->hasthis = ctor->attrs & METHOD_ATTRIBUTE_STATIC? 0: 1;
8406         sig->ret = &mono_defaults.void_class->byval_arg;
8407         return sig;
8408 }
8409
8410 /**
8411  * LOCKING: Assumes the loader lock is held.
8412  */
8413 static MonoMethodSignature*
8414 method_builder_to_signature (MonoMemPool *mp, MonoReflectionMethodBuilder *method) {
8415         MonoMethodSignature *sig;
8416
8417         sig = parameters_to_signature (mp, method->parameters);
8418         sig->hasthis = method->attrs & METHOD_ATTRIBUTE_STATIC? 0: 1;
8419         sig->ret = method->rtype? method->rtype->type: &mono_defaults.void_class->byval_arg;
8420         sig->generic_param_count = method->generic_params ? mono_array_length (method->generic_params) : 0;
8421         return sig;
8422 }
8423
8424 static MonoMethodSignature*
8425 dynamic_method_to_signature (MonoReflectionDynamicMethod *method) {
8426         MonoMethodSignature *sig;
8427
8428         sig = parameters_to_signature (NULL, method->parameters);
8429         sig->hasthis = method->attrs & METHOD_ATTRIBUTE_STATIC? 0: 1;
8430         sig->ret = method->rtype? method->rtype->type: &mono_defaults.void_class->byval_arg;
8431         sig->generic_param_count = 0;
8432         return sig;
8433 }
8434
8435 static void
8436 get_prop_name_and_type (MonoObject *prop, char **name, MonoType **type)
8437 {
8438         MonoClass *klass = mono_object_class (prop);
8439         if (strcmp (klass->name, "PropertyBuilder") == 0) {
8440                 MonoReflectionPropertyBuilder *pb = (MonoReflectionPropertyBuilder *)prop;
8441                 *name = mono_string_to_utf8 (pb->name);
8442                 *type = pb->type->type;
8443         } else {
8444                 MonoReflectionProperty *p = (MonoReflectionProperty *)prop;
8445                 *name = g_strdup (p->property->name);
8446                 if (p->property->get)
8447                         *type = mono_method_signature (p->property->get)->ret;
8448                 else
8449                         *type = mono_method_signature (p->property->set)->params [mono_method_signature (p->property->set)->param_count - 1];
8450         }
8451 }
8452
8453 static void
8454 get_field_name_and_type (MonoObject *field, char **name, MonoType **type)
8455 {
8456         MonoClass *klass = mono_object_class (field);
8457         if (strcmp (klass->name, "FieldBuilder") == 0) {
8458                 MonoReflectionFieldBuilder *fb = (MonoReflectionFieldBuilder *)field;
8459                 *name = mono_string_to_utf8 (fb->name);
8460                 *type = fb->type->type;
8461         } else {
8462                 MonoReflectionField *f = (MonoReflectionField *)field;
8463                 *name = g_strdup (mono_field_get_name (f->field));
8464                 *type = f->field->type;
8465         }
8466 }
8467
8468 /*
8469  * Encode a value in a custom attribute stream of bytes.
8470  * The value to encode is either supplied as an object in argument val
8471  * (valuetypes are boxed), or as a pointer to the data in the
8472  * argument argval.
8473  * @type represents the type of the value
8474  * @buffer is the start of the buffer
8475  * @p the current position in the buffer
8476  * @buflen contains the size of the buffer and is used to return the new buffer size
8477  * if this needs to be realloced.
8478  * @retbuffer and @retp return the start and the position of the buffer
8479  */
8480 static void
8481 encode_cattr_value (MonoAssembly *assembly, char *buffer, char *p, char **retbuffer, char **retp, guint32 *buflen, MonoType *type, MonoObject *arg, char *argval)
8482 {
8483         MonoTypeEnum simple_type;
8484         
8485         if ((p-buffer) + 10 >= *buflen) {
8486                 char *newbuf;
8487                 *buflen *= 2;
8488                 newbuf = g_realloc (buffer, *buflen);
8489                 p = newbuf + (p-buffer);
8490                 buffer = newbuf;
8491         }
8492         if (!argval)
8493                 argval = ((char*)arg + sizeof (MonoObject));
8494         simple_type = type->type;
8495 handle_enum:
8496         switch (simple_type) {
8497         case MONO_TYPE_BOOLEAN:
8498         case MONO_TYPE_U1:
8499         case MONO_TYPE_I1:
8500                 *p++ = *argval;
8501                 break;
8502         case MONO_TYPE_CHAR:
8503         case MONO_TYPE_U2:
8504         case MONO_TYPE_I2:
8505                 swap_with_size (p, argval, 2, 1);
8506                 p += 2;
8507                 break;
8508         case MONO_TYPE_U4:
8509         case MONO_TYPE_I4:
8510         case MONO_TYPE_R4:
8511                 swap_with_size (p, argval, 4, 1);
8512                 p += 4;
8513                 break;
8514         case MONO_TYPE_R8:
8515 #if defined(ARM_FPU_FPA) && G_BYTE_ORDER == G_LITTLE_ENDIAN
8516                 p [0] = argval [4];
8517                 p [1] = argval [5];
8518                 p [2] = argval [6];
8519                 p [3] = argval [7];
8520                 p [4] = argval [0];
8521                 p [5] = argval [1];
8522                 p [6] = argval [2];
8523                 p [7] = argval [3];
8524 #else
8525                 swap_with_size (p, argval, 8, 1);
8526 #endif
8527                 p += 8;
8528                 break;
8529         case MONO_TYPE_U8:
8530         case MONO_TYPE_I8:
8531                 swap_with_size (p, argval, 8, 1);
8532                 p += 8;
8533                 break;
8534         case MONO_TYPE_VALUETYPE:
8535                 if (type->data.klass->enumtype) {
8536                         simple_type = type->data.klass->enum_basetype->type;
8537                         goto handle_enum;
8538                 } else {
8539                         g_warning ("generic valutype %s not handled in custom attr value decoding", type->data.klass->name);
8540                 }
8541                 break;
8542         case MONO_TYPE_STRING: {
8543                 char *str;
8544                 guint32 slen;
8545                 if (!arg) {
8546                         *p++ = 0xFF;
8547                         break;
8548                 }
8549                 str = mono_string_to_utf8 ((MonoString*)arg);
8550                 slen = strlen (str);
8551                 if ((p-buffer) + 10 + slen >= *buflen) {
8552                         char *newbuf;
8553                         *buflen *= 2;
8554                         *buflen += slen;
8555                         newbuf = g_realloc (buffer, *buflen);
8556                         p = newbuf + (p-buffer);
8557                         buffer = newbuf;
8558                 }
8559                 mono_metadata_encode_value (slen, p, &p);
8560                 memcpy (p, str, slen);
8561                 p += slen;
8562                 g_free (str);
8563                 break;
8564         }
8565         case MONO_TYPE_CLASS: {
8566                 char *str;
8567                 guint32 slen;
8568                 MonoClass *k;
8569                 if (!arg) {
8570                         *p++ = 0xFF;
8571                         break;
8572                 }
8573                 k = mono_object_class (arg);
8574                 if (!mono_object_isinst (arg, mono_defaults.monotype_class) &&
8575                         (strcmp (k->name, "TypeBuilder") || strcmp (k->name_space, "System.Reflection.Emit"))) {
8576                         MonoReflectionType* rt = mono_reflection_type_get_underlying_system_type ((MonoReflectionType*) arg);
8577                         MonoClass *rtc;
8578                         
8579                         if (rt && (rtc = mono_object_class (rt)) &&
8580                                    (mono_object_isinst ((MonoObject *) rt, mono_defaults.monotype_class) ||
8581                                     !strcmp (rtc->name, "TypeBuilder") || !strcmp (rtc->name_space, "System.Reflection.Emit"))) {
8582                                 arg = (MonoObject *) rt;
8583                                 k = rtc;
8584                         } else
8585                                 g_error ("Only System.Type allowed, not %s.%s", k->name_space, k->name);
8586                 }
8587 handle_type:
8588                 str = type_get_qualified_name (((MonoReflectionType*)arg)->type, NULL);
8589                 slen = strlen (str);
8590                 if ((p-buffer) + 10 + slen >= *buflen) {
8591                         char *newbuf;
8592                         *buflen *= 2;
8593                         *buflen += slen;
8594                         newbuf = g_realloc (buffer, *buflen);
8595                         p = newbuf + (p-buffer);
8596                         buffer = newbuf;
8597                 }
8598                 mono_metadata_encode_value (slen, p, &p);
8599                 memcpy (p, str, slen);
8600                 p += slen;
8601                 g_free (str);
8602                 break;
8603         }
8604         case MONO_TYPE_SZARRAY: {
8605                 int len, i;
8606                 MonoClass *eclass, *arg_eclass;
8607
8608                 if (!arg) {
8609                         *p++ = 0xff; *p++ = 0xff; *p++ = 0xff; *p++ = 0xff;
8610                         break;
8611                 }
8612                 len = mono_array_length ((MonoArray*)arg);
8613                 *p++ = len & 0xff;
8614                 *p++ = (len >> 8) & 0xff;
8615                 *p++ = (len >> 16) & 0xff;
8616                 *p++ = (len >> 24) & 0xff;
8617                 *retp = p;
8618                 *retbuffer = buffer;
8619                 eclass = type->data.klass;
8620                 arg_eclass = mono_object_class (arg)->element_class;
8621
8622                 if (!eclass) {
8623                         /* Happens when we are called from the MONO_TYPE_OBJECT case below */
8624                         eclass = mono_defaults.object_class;
8625                 }
8626                 if (eclass == mono_defaults.object_class && arg_eclass->valuetype) {
8627                         char *elptr = mono_array_addr ((MonoArray*)arg, char, 0);
8628                         int elsize = mono_class_array_element_size (arg_eclass);
8629                         for (i = 0; i < len; ++i) {
8630                                 encode_cattr_value (assembly, buffer, p, &buffer, &p, buflen, &arg_eclass->byval_arg, NULL, elptr);
8631                                 elptr += elsize;
8632                         }
8633                 } else if (eclass->valuetype && arg_eclass->valuetype) {
8634                         char *elptr = mono_array_addr ((MonoArray*)arg, char, 0);
8635                         int elsize = mono_class_array_element_size (eclass);
8636                         for (i = 0; i < len; ++i) {
8637                                 encode_cattr_value (assembly, buffer, p, &buffer, &p, buflen, &eclass->byval_arg, NULL, elptr);
8638                                 elptr += elsize;
8639                         }
8640                 } else {
8641                         for (i = 0; i < len; ++i) {
8642                                 encode_cattr_value (assembly, buffer, p, &buffer, &p, buflen, &eclass->byval_arg, mono_array_get ((MonoArray*)arg, MonoObject*, i), NULL);
8643                         }
8644                 }
8645                 break;
8646         }
8647         case MONO_TYPE_OBJECT: {
8648                 MonoClass *klass;
8649                 char *str;
8650                 guint32 slen;
8651
8652                 /*
8653                  * The parameter type is 'object' but the type of the actual
8654                  * argument is not. So we have to add type information to the blob
8655                  * too. This is completely undocumented in the spec.
8656                  */
8657
8658                 if (arg == NULL) {
8659                         *p++ = MONO_TYPE_STRING;        // It's same hack as MS uses
8660                         *p++ = 0xFF;
8661                         break;
8662                 }
8663                 
8664                 klass = mono_object_class (arg);
8665
8666                 if (mono_object_isinst (arg, mono_defaults.systemtype_class)) {
8667                         *p++ = 0x50;
8668                         goto handle_type;
8669                 } else if (klass->enumtype) {
8670                         *p++ = 0x55;
8671                 } else if (klass == mono_defaults.string_class) {
8672                         simple_type = MONO_TYPE_STRING;
8673                         *p++ = 0x0E;
8674                         goto handle_enum;
8675                 } else if (klass->rank == 1) {
8676                         *p++ = 0x1D;
8677                         if (klass->element_class->byval_arg.type == MONO_TYPE_OBJECT)
8678                                 /* See Partition II, Appendix B3 */
8679                                 *p++ = 0x51;
8680                         else
8681                                 *p++ = klass->element_class->byval_arg.type;
8682                         encode_cattr_value (assembly, buffer, p, &buffer, &p, buflen, &klass->byval_arg, arg, NULL);
8683                         break;
8684                 } else if (klass->byval_arg.type >= MONO_TYPE_BOOLEAN && klass->byval_arg.type <= MONO_TYPE_R8) {
8685                         *p++ = simple_type = klass->byval_arg.type;
8686                         goto handle_enum;
8687                 } else {
8688                         g_error ("unhandled type in custom attr");
8689                 }
8690                 str = type_get_qualified_name (mono_class_get_type(klass), NULL);
8691                 slen = strlen (str);
8692                 if ((p-buffer) + 10 + slen >= *buflen) {
8693                         char *newbuf;
8694                         *buflen *= 2;
8695                         *buflen += slen;
8696                         newbuf = g_realloc (buffer, *buflen);
8697                         p = newbuf + (p-buffer);
8698                         buffer = newbuf;
8699                 }
8700                 mono_metadata_encode_value (slen, p, &p);
8701                 memcpy (p, str, slen);
8702                 p += slen;
8703                 g_free (str);
8704                 simple_type = klass->enum_basetype->type;
8705                 goto handle_enum;
8706         }
8707         default:
8708                 g_error ("type 0x%02x not yet supported in custom attr encoder", simple_type);
8709         }
8710         *retp = p;
8711         *retbuffer = buffer;
8712 }
8713
8714 static void
8715 encode_field_or_prop_type (MonoType *type, char *p, char **retp)
8716 {
8717         if (type->type == MONO_TYPE_VALUETYPE && type->data.klass->enumtype) {
8718                 char *str = type_get_qualified_name (type, NULL);
8719                 int slen = strlen (str);
8720
8721                 *p++ = 0x55;
8722                 /*
8723                  * This seems to be optional...
8724                  * *p++ = 0x80;
8725                  */
8726                 mono_metadata_encode_value (slen, p, &p);
8727                 memcpy (p, str, slen);
8728                 p += slen;
8729                 g_free (str);
8730         } else if (type->type == MONO_TYPE_OBJECT) {
8731                 *p++ = 0x51;
8732         } else if (type->type == MONO_TYPE_CLASS) {
8733                 /* it should be a type: encode_cattr_value () has the check */
8734                 *p++ = 0x50;
8735         } else {
8736                 mono_metadata_encode_value (type->type, p, &p);
8737                 if (type->type == MONO_TYPE_SZARRAY)
8738                         /* See the examples in Partition VI, Annex B */
8739                         encode_field_or_prop_type (&type->data.klass->byval_arg, p, &p);
8740         }
8741
8742         *retp = p;
8743 }
8744
8745 static void
8746 encode_named_val (MonoReflectionAssembly *assembly, char *buffer, char *p, char **retbuffer, char **retp, guint32 *buflen, MonoType *type, char *name, MonoObject *value)
8747 {
8748         int len;
8749         /* Preallocate a large enough buffer */
8750         if (type->type == MONO_TYPE_VALUETYPE && type->data.klass->enumtype) {
8751                 char *str = type_get_qualified_name (type, NULL);
8752                 len = strlen (str);
8753                 g_free (str);
8754         } else if (type->type == MONO_TYPE_SZARRAY && type->data.klass->enumtype) {
8755                 char *str = type_get_qualified_name (&type->data.klass->byval_arg, NULL);
8756                 len = strlen (str);
8757                 g_free (str);
8758         } else {
8759                 len = 0;
8760         }
8761         len += strlen (name);
8762
8763         if ((p-buffer) + 20 + len >= *buflen) {
8764                 char *newbuf;
8765                 *buflen *= 2;
8766                 *buflen += len;
8767                 newbuf = g_realloc (buffer, *buflen);
8768                 p = newbuf + (p-buffer);
8769                 buffer = newbuf;
8770         }
8771
8772         encode_field_or_prop_type (type, p, &p);
8773
8774         len = strlen (name);
8775         mono_metadata_encode_value (len, p, &p);
8776         memcpy (p, name, len);
8777         p += len;
8778         encode_cattr_value (assembly->assembly, buffer, p, &buffer, &p, buflen, type, value, NULL);
8779         *retp = p;
8780         *retbuffer = buffer;
8781 }
8782
8783 #ifndef DISABLE_REFLECTION_EMIT
8784
8785 /*
8786  * mono_reflection_get_custom_attrs_blob:
8787  * @ctor: custom attribute constructor
8788  * @ctorArgs: arguments o the constructor
8789  * @properties:
8790  * @propValues:
8791  * @fields:
8792  * @fieldValues:
8793  * 
8794  * Creates the blob of data that needs to be saved in the metadata and that represents
8795  * the custom attributed described by @ctor, @ctorArgs etc.
8796  * Returns: a Byte array representing the blob of data.
8797  */
8798 MonoArray*
8799 mono_reflection_get_custom_attrs_blob (MonoReflectionAssembly *assembly, MonoObject *ctor, MonoArray *ctorArgs, MonoArray *properties, MonoArray *propValues, MonoArray *fields, MonoArray* fieldValues) 
8800 {
8801         MonoArray *result;
8802         MonoMethodSignature *sig;
8803         MonoObject *arg;
8804         char *buffer, *p;
8805         guint32 buflen, i;
8806
8807         MONO_ARCH_SAVE_REGS;
8808
8809         if (strcmp (ctor->vtable->klass->name, "MonoCMethod")) {
8810                 /* sig is freed later so allocate it in the heap */
8811                 sig = ctor_builder_to_signature (NULL, (MonoReflectionCtorBuilder*)ctor);
8812         } else {
8813                 sig = mono_method_signature (((MonoReflectionMethod*)ctor)->method);
8814         }
8815
8816         g_assert (mono_array_length (ctorArgs) == sig->param_count);
8817         buflen = 256;
8818         p = buffer = g_malloc (buflen);
8819         /* write the prolog */
8820         *p++ = 1;
8821         *p++ = 0;
8822         for (i = 0; i < sig->param_count; ++i) {
8823                 arg = mono_array_get (ctorArgs, MonoObject*, i);
8824                 encode_cattr_value (assembly->assembly, buffer, p, &buffer, &p, &buflen, sig->params [i], arg, NULL);
8825         }
8826         i = 0;
8827         if (properties)
8828                 i += mono_array_length (properties);
8829         if (fields)
8830                 i += mono_array_length (fields);
8831         *p++ = i & 0xff;
8832         *p++ = (i >> 8) & 0xff;
8833         if (properties) {
8834                 MonoObject *prop;
8835                 for (i = 0; i < mono_array_length (properties); ++i) {
8836                         MonoType *ptype;
8837                         char *pname;
8838
8839                         prop = mono_array_get (properties, gpointer, i);
8840                         get_prop_name_and_type (prop, &pname, &ptype);
8841                         *p++ = 0x54; /* PROPERTY signature */
8842                         encode_named_val (assembly, buffer, p, &buffer, &p, &buflen, ptype, pname, (MonoObject*)mono_array_get (propValues, gpointer, i));
8843                         g_free (pname);
8844                 }
8845         }
8846
8847         if (fields) {
8848                 MonoObject *field;
8849                 for (i = 0; i < mono_array_length (fields); ++i) {
8850                         MonoType *ftype;
8851                         char *fname;
8852
8853                         field = mono_array_get (fields, gpointer, i);
8854                         get_field_name_and_type (field, &fname, &ftype);
8855                         *p++ = 0x53; /* FIELD signature */
8856                         encode_named_val (assembly, buffer, p, &buffer, &p, &buflen, ftype, fname, (MonoObject*)mono_array_get (fieldValues, gpointer, i));
8857                         g_free (fname);
8858                 }
8859         }
8860
8861         g_assert (p - buffer <= buflen);
8862         buflen = p - buffer;
8863         result = mono_array_new (mono_domain_get (), mono_defaults.byte_class, buflen);
8864         p = mono_array_addr (result, char, 0);
8865         memcpy (p, buffer, buflen);
8866         g_free (buffer);
8867         if (strcmp (ctor->vtable->klass->name, "MonoCMethod"))
8868                 g_free (sig);
8869         return result;
8870 }
8871
8872 /*
8873  * mono_reflection_setup_internal_class:
8874  * @tb: a TypeBuilder object
8875  *
8876  * Creates a MonoClass that represents the TypeBuilder.
8877  * This is a trick that lets us simplify a lot of reflection code
8878  * (and will allow us to support Build and Run assemblies easier).
8879  */
8880 void
8881 mono_reflection_setup_internal_class (MonoReflectionTypeBuilder *tb)
8882 {
8883         MonoClass *klass, *parent;
8884
8885         MONO_ARCH_SAVE_REGS;
8886
8887         mono_loader_lock ();
8888
8889         if (tb->parent) {
8890                 /* check so we can compile corlib correctly */
8891                 if (strcmp (mono_object_class (tb->parent)->name, "TypeBuilder") == 0) {
8892                         /* mono_class_setup_mono_type () guaranteess type->data.klass is valid */
8893                         parent = tb->parent->type->data.klass;
8894                 } else {
8895                         parent = my_mono_class_from_mono_type (tb->parent->type);
8896                 }
8897         } else {
8898                 parent = NULL;
8899         }
8900         
8901         /* the type has already being created: it means we just have to change the parent */
8902         if (tb->type.type) {
8903                 klass = mono_class_from_mono_type (tb->type.type);
8904                 klass->parent = NULL;
8905                 /* fool mono_class_setup_parent */
8906                 klass->supertypes = NULL;
8907                 mono_class_setup_parent (klass, parent);
8908                 mono_class_setup_mono_type (klass);
8909                 mono_loader_unlock ();
8910                 return;
8911         }
8912
8913         klass = mono_image_alloc0 (&tb->module->dynamic_image->image, sizeof (MonoClass));
8914
8915         klass->image = &tb->module->dynamic_image->image;
8916
8917         klass->inited = 1; /* we lie to the runtime */
8918         klass->name = mono_string_to_utf8_mp (klass->image->mempool, tb->name);
8919         klass->name_space = mono_string_to_utf8_mp (klass->image->mempool, tb->nspace);
8920         klass->type_token = MONO_TOKEN_TYPE_DEF | tb->table_idx;
8921         klass->flags = tb->attrs;
8922         
8923         mono_profiler_class_event (klass, MONO_PROFILE_START_LOAD);
8924
8925         klass->element_class = klass;
8926
8927         MOVING_GC_REGISTER (&klass->reflection_info);
8928         klass->reflection_info = tb;
8929
8930         /* Put into cache so mono_class_get () will find it */
8931         mono_image_add_to_name_cache (klass->image, klass->name_space, klass->name, tb->table_idx);
8932
8933         mono_g_hash_table_insert (tb->module->dynamic_image->tokens,
8934                 GUINT_TO_POINTER (MONO_TOKEN_TYPE_DEF | tb->table_idx), tb);
8935
8936         if (parent != NULL) {
8937                 mono_class_setup_parent (klass, parent);
8938         } else if (strcmp (klass->name, "Object") == 0 && strcmp (klass->name_space, "System") == 0) {
8939                 const char *old_n = klass->name;
8940                 /* trick to get relative numbering right when compiling corlib */
8941                 klass->name = "BuildingObject";
8942                 mono_class_setup_parent (klass, mono_defaults.object_class);
8943                 klass->name = old_n;
8944         }
8945
8946         if ((!strcmp (klass->name, "ValueType") && !strcmp (klass->name_space, "System")) ||
8947                         (!strcmp (klass->name, "Object") && !strcmp (klass->name_space, "System")) ||
8948                         (!strcmp (klass->name, "Enum") && !strcmp (klass->name_space, "System"))) {
8949                 klass->instance_size = sizeof (MonoObject);
8950                 klass->size_inited = 1;
8951                 mono_class_setup_vtable_general (klass, NULL, 0);
8952         }
8953
8954         mono_class_setup_mono_type (klass);
8955
8956         mono_class_setup_supertypes (klass);
8957
8958         /*
8959          * FIXME: handle interfaces.
8960          */
8961
8962         tb->type.type = &klass->byval_arg;
8963
8964         if (tb->nesting_type) {
8965                 g_assert (tb->nesting_type->type);
8966                 klass->nested_in = mono_class_from_mono_type (tb->nesting_type->type);
8967         }
8968
8969         /*g_print ("setup %s as %s (%p)\n", klass->name, ((MonoObject*)tb)->vtable->klass->name, tb);*/
8970
8971         mono_profiler_class_loaded (klass, MONO_PROFILE_OK);
8972         
8973         mono_loader_unlock ();
8974 }
8975
8976 /*
8977  * mono_reflection_setup_generic_class:
8978  * @tb: a TypeBuilder object
8979  *
8980  * Setup the generic class before adding the first generic parameter.
8981  */
8982 void
8983 mono_reflection_setup_generic_class (MonoReflectionTypeBuilder *tb)
8984 {
8985 }
8986
8987 /*
8988  * mono_reflection_create_generic_class:
8989  * @tb: a TypeBuilder object
8990  *
8991  * Creates the generic class after all generic parameters have been added.
8992  */
8993 void
8994 mono_reflection_create_generic_class (MonoReflectionTypeBuilder *tb)
8995 {
8996         MonoClass *klass;
8997         int count, i;
8998
8999         MONO_ARCH_SAVE_REGS;
9000
9001         klass = my_mono_class_from_mono_type (tb->type.type);
9002
9003         count = tb->generic_params ? mono_array_length (tb->generic_params) : 0;
9004
9005         if (klass->generic_container || (count == 0))
9006                 return;
9007
9008         g_assert (tb->generic_container && (tb->generic_container->owner.klass == klass));
9009
9010         klass->generic_container = mono_image_alloc0 (klass->image, sizeof (MonoGenericContainer));
9011
9012         klass->generic_container->owner.klass = klass;
9013         klass->generic_container->type_argc = count;
9014         klass->generic_container->type_params = mono_image_alloc0 (klass->image, sizeof (MonoGenericParam) * count);
9015
9016         for (i = 0; i < count; i++) {
9017                 MonoReflectionGenericParam *gparam = mono_array_get (tb->generic_params, gpointer, i);
9018                 klass->generic_container->type_params [i] = *gparam->type.type->data.generic_param;
9019                 /*Make sure we are a diferent type instance */
9020                 klass->generic_container->type_params [i].owner = klass->generic_container;
9021                 klass->generic_container->type_params [i].pklass = NULL;
9022
9023                 g_assert (klass->generic_container->type_params [i].owner);
9024         }
9025
9026         klass->generic_container->context.class_inst = mono_get_shared_generic_inst (klass->generic_container);
9027 }
9028
9029 /*
9030  * mono_reflection_create_internal_class:
9031  * @tb: a TypeBuilder object
9032  *
9033  * Actually create the MonoClass that is associated with the TypeBuilder.
9034  */
9035 void
9036 mono_reflection_create_internal_class (MonoReflectionTypeBuilder *tb)
9037 {
9038         MonoClass *klass;
9039
9040         MONO_ARCH_SAVE_REGS;
9041
9042         klass = my_mono_class_from_mono_type (tb->type.type);
9043
9044         mono_loader_lock ();
9045         if (klass->enumtype && klass->enum_basetype == NULL) {
9046                 MonoReflectionFieldBuilder *fb;
9047                 MonoClass *ec;
9048
9049                 g_assert (tb->fields != NULL);
9050                 g_assert (mono_array_length (tb->fields) >= 1);
9051
9052                 fb = mono_array_get (tb->fields, MonoReflectionFieldBuilder*, 0);
9053
9054                 if (!mono_type_is_valid_enum_basetype (fb->type->type)) {
9055                         mono_loader_unlock ();
9056                         return;
9057                 }
9058
9059                 klass->enum_basetype = fb->type->type;
9060                 klass->element_class = my_mono_class_from_mono_type (klass->enum_basetype);
9061                 if (!klass->element_class)
9062                         klass->element_class = mono_class_from_mono_type (klass->enum_basetype);
9063
9064                 /*
9065                  * get the element_class from the current corlib.
9066                  */
9067                 ec = default_class_from_mono_type (klass->enum_basetype);
9068                 klass->instance_size = ec->instance_size;
9069                 klass->size_inited = 1;
9070                 /* 
9071                  * this is almost safe to do with enums and it's needed to be able
9072                  * to create objects of the enum type (for use in SetConstant).
9073                  */
9074                 /* FIXME: Does this mean enums can't have method overrides ? */
9075                 mono_class_setup_vtable_general (klass, NULL, 0);
9076         }
9077         mono_loader_unlock ();
9078 }
9079
9080 #endif /* DISABLE_REFLECTION_EMIT */
9081
9082 static MonoMarshalSpec*
9083 mono_marshal_spec_from_builder (MonoMemPool *mp, MonoAssembly *assembly,
9084                                                                 MonoReflectionMarshal *minfo)
9085 {
9086         MonoMarshalSpec *res;
9087
9088         res = mp_g_new0 (mp, MonoMarshalSpec, 1);
9089         res->native = minfo->type;
9090
9091         switch (minfo->type) {
9092         case MONO_NATIVE_LPARRAY:
9093                 res->data.array_data.elem_type = minfo->eltype;
9094                 if (minfo->has_size) {
9095                         res->data.array_data.param_num = minfo->param_num;
9096                         res->data.array_data.num_elem = minfo->count;
9097                         res->data.array_data.elem_mult = minfo->param_num == -1 ? 0 : 1;
9098                 }
9099                 else {
9100                         res->data.array_data.param_num = -1;
9101                         res->data.array_data.num_elem = -1;
9102                         res->data.array_data.elem_mult = -1;
9103                 }
9104                 break;
9105
9106         case MONO_NATIVE_BYVALTSTR:
9107         case MONO_NATIVE_BYVALARRAY:
9108                 res->data.array_data.num_elem = minfo->count;
9109                 break;
9110
9111         case MONO_NATIVE_CUSTOM:
9112                 if (minfo->marshaltyperef)
9113                         res->data.custom_data.custom_name =
9114                                 type_get_fully_qualified_name (minfo->marshaltyperef->type);
9115                 if (minfo->mcookie)
9116                         res->data.custom_data.cookie = mono_string_to_utf8 (minfo->mcookie);
9117                 break;
9118
9119         default:
9120                 break;
9121         }
9122
9123         return res;
9124 }
9125
9126 MonoReflectionMarshal*
9127 mono_reflection_marshal_from_marshal_spec (MonoDomain *domain, MonoClass *klass,
9128                                                                                    MonoMarshalSpec *spec)
9129 {
9130         static MonoClass *System_Reflection_Emit_UnmanagedMarshalClass;
9131         MonoReflectionMarshal *minfo;
9132         MonoType *mtype;
9133
9134         if (!System_Reflection_Emit_UnmanagedMarshalClass) {
9135                 System_Reflection_Emit_UnmanagedMarshalClass = mono_class_from_name (
9136                    mono_defaults.corlib, "System.Reflection.Emit", "UnmanagedMarshal");
9137                 g_assert (System_Reflection_Emit_UnmanagedMarshalClass);
9138         }
9139
9140         minfo = (MonoReflectionMarshal*)mono_object_new (domain, System_Reflection_Emit_UnmanagedMarshalClass);
9141         minfo->type = spec->native;
9142
9143         switch (minfo->type) {
9144         case MONO_NATIVE_LPARRAY:
9145                 minfo->eltype = spec->data.array_data.elem_type;
9146                 minfo->count = spec->data.array_data.num_elem;
9147                 minfo->param_num = spec->data.array_data.param_num;
9148                 break;
9149
9150         case MONO_NATIVE_BYVALTSTR:
9151         case MONO_NATIVE_BYVALARRAY:
9152                 minfo->count = spec->data.array_data.num_elem;
9153                 break;
9154
9155         case MONO_NATIVE_CUSTOM:
9156                 if (spec->data.custom_data.custom_name) {
9157                         mtype = mono_reflection_type_from_name (spec->data.custom_data.custom_name, klass->image);
9158                         if (mtype)
9159                                 MONO_OBJECT_SETREF (minfo, marshaltyperef, mono_type_get_object (domain, mtype));
9160
9161                         MONO_OBJECT_SETREF (minfo, marshaltype, mono_string_new (domain, spec->data.custom_data.custom_name));
9162                 }
9163                 if (spec->data.custom_data.cookie)
9164                         MONO_OBJECT_SETREF (minfo, mcookie, mono_string_new (domain, spec->data.custom_data.cookie));
9165                 break;
9166
9167         default:
9168                 break;
9169         }
9170
9171         return minfo;
9172 }
9173
9174 static MonoMethod*
9175 reflection_methodbuilder_to_mono_method (MonoClass *klass,
9176                                          ReflectionMethodBuilder *rmb,
9177                                          MonoMethodSignature *sig)
9178 {
9179         MonoMethod *m;
9180         MonoMethodNormal *pm;
9181         MonoMarshalSpec **specs;
9182         MonoReflectionMethodAux *method_aux;
9183         MonoMemPool *mp;
9184         gboolean dynamic;
9185         int i;
9186
9187         /*
9188          * Methods created using a MethodBuilder should have their memory allocated
9189          * inside the image mempool, while dynamic methods should have their memory
9190          * malloc'd.
9191          */
9192         dynamic = rmb->refs != NULL;
9193         mp = dynamic ? NULL : klass->image->mempool;
9194
9195         if (!dynamic)
9196                 g_assert (!klass->generic_class);
9197
9198         mono_loader_lock ();
9199
9200         if ((rmb->attrs & METHOD_ATTRIBUTE_PINVOKE_IMPL) ||
9201                         (rmb->iattrs & METHOD_IMPL_ATTRIBUTE_INTERNAL_CALL))
9202                 m = (MonoMethod *)mp_g_new0 (mp, MonoMethodPInvoke, 1);
9203         else if (rmb->refs)
9204                 m = (MonoMethod *)mp_g_new0 (mp, MonoMethodWrapper, 1);
9205         else
9206                 m = (MonoMethod *)mp_g_new0 (mp, MonoMethodNormal, 1);
9207
9208         pm = (MonoMethodNormal*)m;
9209
9210         m->dynamic = dynamic;
9211         m->slot = -1;
9212         m->flags = rmb->attrs;
9213         m->iflags = rmb->iattrs;
9214         m->name = mp_string_to_utf8 (mp, rmb->name);
9215         m->klass = klass;
9216         m->signature = sig;
9217         m->skip_visibility = rmb->skip_visibility;
9218         if (rmb->table_idx)
9219                 m->token = MONO_TOKEN_METHOD_DEF | (*rmb->table_idx);
9220
9221         if (m->iflags & METHOD_IMPL_ATTRIBUTE_INTERNAL_CALL) {
9222                 if (klass == mono_defaults.string_class && !strcmp (m->name, ".ctor"))
9223                         m->string_ctor = 1;
9224
9225                 m->signature->pinvoke = 1;
9226         } else if (m->flags & METHOD_ATTRIBUTE_PINVOKE_IMPL) {
9227                 m->signature->pinvoke = 1;
9228
9229                 method_aux = mp_g_new0 (mp, MonoReflectionMethodAux, 1);
9230
9231                 method_aux->dllentry = rmb->dllentry ? mono_string_to_utf8_mp (mp, rmb->dllentry) : mono_mempool_strdup (mp, m->name);
9232                 method_aux->dll = mono_string_to_utf8_mp (mp, rmb->dll);
9233                 
9234                 ((MonoMethodPInvoke*)m)->piflags = (rmb->native_cc << 8) | (rmb->charset ? (rmb->charset - 1) * 2 : 0) | rmb->extra_flags;
9235
9236                 if (klass->image->dynamic)
9237                         g_hash_table_insert (((MonoDynamicImage*)klass->image)->method_aux_hash, m, method_aux);
9238
9239                 mono_loader_unlock ();
9240
9241                 return m;
9242         } else if (!(m->flags & METHOD_ATTRIBUTE_ABSTRACT) &&
9243                            !(m->iflags & METHOD_IMPL_ATTRIBUTE_RUNTIME)) {
9244                 MonoMethodHeader *header;
9245                 guint32 code_size;
9246                 gint32 max_stack, i;
9247                 gint32 num_locals = 0;
9248                 gint32 num_clauses = 0;
9249                 guint8 *code;
9250
9251                 if (rmb->ilgen) {
9252                         code = mono_array_addr (rmb->ilgen->code, guint8, 0);
9253                         code_size = rmb->ilgen->code_len;
9254                         max_stack = rmb->ilgen->max_stack;
9255                         num_locals = rmb->ilgen->locals ? mono_array_length (rmb->ilgen->locals) : 0;
9256                         if (rmb->ilgen->ex_handlers)
9257                                 num_clauses = method_count_clauses (rmb->ilgen);
9258                 } else {
9259                         if (rmb->code) {
9260                                 code = mono_array_addr (rmb->code, guint8, 0);
9261                                 code_size = mono_array_length (rmb->code);
9262                                 /* we probably need to run a verifier on the code... */
9263                                 max_stack = 8; 
9264                         }
9265                         else {
9266                                 code = NULL;
9267                                 code_size = 0;
9268                                 max_stack = 8;
9269                         }
9270                 }
9271
9272                 header = mp_g_malloc0 (mp, sizeof (MonoMethodHeader) + 
9273                         (num_locals - MONO_ZERO_LEN_ARRAY) * sizeof (MonoType*));
9274                 header->code_size = code_size;
9275                 header->code = mp_g_malloc (mp, code_size);
9276                 memcpy ((char*)header->code, code, code_size);
9277                 header->max_stack = max_stack;
9278                 header->init_locals = rmb->init_locals;
9279                 header->num_locals = num_locals;
9280
9281                 for (i = 0; i < num_locals; ++i) {
9282                         MonoReflectionLocalBuilder *lb = 
9283                                 mono_array_get (rmb->ilgen->locals, MonoReflectionLocalBuilder*, i);
9284
9285                         header->locals [i] = mp_g_new0 (mp, MonoType, 1);
9286                         memcpy (header->locals [i], lb->type->type, sizeof (MonoType));
9287                 }
9288
9289                 header->num_clauses = num_clauses;
9290                 if (num_clauses) {
9291                         header->clauses = method_encode_clauses (mp, (MonoDynamicImage*)klass->image,
9292                                  rmb->ilgen, num_clauses);
9293                 }
9294
9295                 pm->header = header;
9296         }
9297
9298         if (rmb->generic_params) {
9299                 int count = mono_array_length (rmb->generic_params);
9300                 MonoGenericContainer *container;
9301
9302                 container = rmb->generic_container;
9303                 if (container) {
9304                         m->is_generic = TRUE;
9305                         mono_method_set_generic_container (m, container);
9306                 }
9307                 container->type_argc = count;
9308                 container->type_params = mp_g_new0 (mp, MonoGenericParam, count);
9309                 container->owner.method = m;
9310
9311                 for (i = 0; i < count; i++) {
9312                         MonoReflectionGenericParam *gp =
9313                                 mono_array_get (rmb->generic_params, MonoReflectionGenericParam*, i);
9314
9315                         container->type_params [i] = *gp->type.type->data.generic_param;
9316                 }
9317
9318                 if (klass->generic_container) {
9319                         container->parent = klass->generic_container;
9320                         container->context.class_inst = klass->generic_container->context.class_inst;
9321                 }
9322                 container->context.method_inst = mono_get_shared_generic_inst (container);
9323         }
9324
9325         if (rmb->refs) {
9326                 MonoMethodWrapper *mw = (MonoMethodWrapper*)m;
9327                 int i;
9328                 void **data;
9329
9330                 m->wrapper_type = MONO_WRAPPER_DYNAMIC_METHOD;
9331
9332                 mw->method_data = data = mp_g_new (mp, gpointer, rmb->nrefs + 1);
9333                 data [0] = GUINT_TO_POINTER (rmb->nrefs);
9334                 for (i = 0; i < rmb->nrefs; ++i)
9335                         data [i + 1] = rmb->refs [i];
9336         }
9337
9338         method_aux = NULL;
9339
9340         /* Parameter info */
9341         if (rmb->pinfo) {
9342                 if (!method_aux)
9343                         method_aux = mp_g_new0 (mp, MonoReflectionMethodAux, 1);
9344                 method_aux->param_names = mp_g_new0 (mp, char *, mono_method_signature (m)->param_count + 1);
9345                 for (i = 0; i <= m->signature->param_count; ++i) {
9346                         MonoReflectionParamBuilder *pb;
9347                         if ((pb = mono_array_get (rmb->pinfo, MonoReflectionParamBuilder*, i))) {
9348                                 if ((i > 0) && (pb->attrs)) {
9349                                         /* Make a copy since it might point to a shared type structure */
9350                                         m->signature->params [i - 1] = mono_metadata_type_dup (mp, m->signature->params [i - 1]);
9351                                         m->signature->params [i - 1]->attrs = pb->attrs;
9352                                 }
9353
9354                                 if (pb->attrs & PARAM_ATTRIBUTE_HAS_DEFAULT) {
9355                                         MonoDynamicImage *assembly;
9356                                         guint32 idx, def_type, len;
9357                                         char *p;
9358                                         const char *p2;
9359
9360                                         if (!method_aux->param_defaults) {
9361                                                 method_aux->param_defaults = mp_g_new0 (mp, guint8*, m->signature->param_count + 1);
9362                                                 method_aux->param_default_types = mp_g_new0 (mp, guint32, m->signature->param_count + 1);
9363                                         }
9364                                         assembly = (MonoDynamicImage*)klass->image;
9365                                         idx = encode_constant (assembly, pb->def_value, &def_type);
9366                                         /* Copy the data from the blob since it might get realloc-ed */
9367                                         p = assembly->blob.data + idx;
9368                                         len = mono_metadata_decode_blob_size (p, &p2);
9369                                         len += p2 - p;
9370                                         method_aux->param_defaults [i] = mp_g_malloc (mp, len);
9371                                         method_aux->param_default_types [i] = def_type;
9372                                         memcpy ((gpointer)method_aux->param_defaults [i], p, len);
9373                                 }
9374
9375                                 if (pb->name)
9376                                         method_aux->param_names [i] = mp_string_to_utf8 (mp, pb->name);
9377                                 if (pb->cattrs) {
9378                                         if (!method_aux->param_cattr)
9379                                                 method_aux->param_cattr = mp_g_new0 (mp, MonoCustomAttrInfo*, m->signature->param_count + 1);
9380                                         method_aux->param_cattr [i] = mono_custom_attrs_from_builders (mp, klass->image, pb->cattrs);
9381                                 }
9382                         }
9383                 }
9384         }
9385
9386         /* Parameter marshalling */
9387         specs = NULL;
9388         if (rmb->pinfo)         
9389                 for (i = 0; i < mono_array_length (rmb->pinfo); ++i) {
9390                         MonoReflectionParamBuilder *pb;
9391                         if ((pb = mono_array_get (rmb->pinfo, MonoReflectionParamBuilder*, i))) {
9392                                 if (pb->marshal_info) {
9393                                         if (specs == NULL)
9394                                                 specs = mp_g_new0 (mp, MonoMarshalSpec*, sig->param_count + 1);
9395                                         specs [pb->position] = 
9396                                                 mono_marshal_spec_from_builder (mp, klass->image->assembly, pb->marshal_info);
9397                                 }
9398                         }
9399                 }
9400         if (specs != NULL) {
9401                 if (!method_aux)
9402                         method_aux = mp_g_new0 (mp, MonoReflectionMethodAux, 1);
9403                 method_aux->param_marshall = specs;
9404         }
9405
9406         if (klass->image->dynamic && method_aux)
9407                 g_hash_table_insert (((MonoDynamicImage*)klass->image)->method_aux_hash, m, method_aux);
9408
9409         mono_loader_unlock ();
9410
9411         return m;
9412 }       
9413
9414 static MonoMethod*
9415 ctorbuilder_to_mono_method (MonoClass *klass, MonoReflectionCtorBuilder* mb)
9416 {
9417         ReflectionMethodBuilder rmb;
9418         MonoMethodSignature *sig;
9419
9420         mono_loader_lock ();
9421         sig = ctor_builder_to_signature (klass->image->mempool, mb);
9422         mono_loader_unlock ();
9423
9424         reflection_methodbuilder_from_ctor_builder (&rmb, mb);
9425
9426         mb->mhandle = reflection_methodbuilder_to_mono_method (klass, &rmb, sig);
9427         mono_save_custom_attrs (klass->image, mb->mhandle, mb->cattrs);
9428
9429         /* If we are in a generic class, we might be called multiple times from inflate_method */
9430         if (!((MonoDynamicImage*)(MonoDynamicImage*)klass->image)->save && !klass->generic_container) {
9431                 /* ilgen is no longer needed */
9432                 mb->ilgen = NULL;
9433         }
9434
9435         return mb->mhandle;
9436 }
9437
9438 static MonoMethod*
9439 methodbuilder_to_mono_method (MonoClass *klass, MonoReflectionMethodBuilder* mb)
9440 {
9441         ReflectionMethodBuilder rmb;
9442         MonoMethodSignature *sig;
9443
9444         mono_loader_lock ();
9445         sig = method_builder_to_signature (klass->image->mempool, mb);
9446         mono_loader_unlock ();
9447
9448         reflection_methodbuilder_from_method_builder (&rmb, mb);
9449
9450         mb->mhandle = reflection_methodbuilder_to_mono_method (klass, &rmb, sig);
9451         mono_save_custom_attrs (klass->image, mb->mhandle, mb->cattrs);
9452
9453         /* If we are in a generic class, we might be called multiple times from inflate_method */
9454         if (!((MonoDynamicImage*)(MonoDynamicImage*)klass->image)->save && !klass->generic_container) {
9455                 /* ilgen is no longer needed */
9456                 mb->ilgen = NULL;
9457         }
9458         return mb->mhandle;
9459 }
9460
9461 static MonoClassField*
9462 fieldbuilder_to_mono_class_field (MonoClass *klass, MonoReflectionFieldBuilder* fb)
9463 {
9464         MonoClassField *field;
9465         MonoType *custom;
9466
9467         field = g_new0 (MonoClassField, 1);
9468
9469         field->name = mono_string_to_utf8 (fb->name);
9470         if (fb->attrs || fb->modreq || fb->modopt) {
9471                 field->type = mono_metadata_type_dup (NULL, fb->type->type);
9472                 field->type->attrs = fb->attrs;
9473
9474                 g_assert (klass->image->dynamic);
9475                 custom = add_custom_modifiers ((MonoDynamicImage*)klass->image, field->type, fb->modreq, fb->modopt);
9476                 g_free (field->type);
9477                 field->type = custom;
9478         } else {
9479                 field->type = fb->type->type;
9480         }
9481         if (fb->offset != -1)
9482                 field->offset = fb->offset;
9483         field->parent = klass;
9484         mono_save_custom_attrs (klass->image, field, fb->cattrs);
9485
9486         // FIXME: Can't store fb->def_value/RVA, is it needed for field_on_insts ?
9487
9488         return field;
9489 }
9490
9491 MonoType*
9492 mono_reflection_bind_generic_parameters (MonoReflectionType *type, int type_argc, MonoType **types)
9493 {
9494         MonoClass *klass;
9495         MonoReflectionTypeBuilder *tb = NULL;
9496         gboolean is_dynamic = FALSE;
9497         MonoDomain *domain;
9498         MonoClass *geninst;
9499
9500         mono_loader_lock ();
9501
9502         domain = mono_object_domain (type);
9503
9504         if (!strcmp (((MonoObject *) type)->vtable->klass->name, "TypeBuilder")) {
9505                 tb = (MonoReflectionTypeBuilder *) type;
9506
9507                 is_dynamic = TRUE;
9508         } else if (!strcmp (((MonoObject *) type)->vtable->klass->name, "MonoGenericClass")) {
9509                 MonoReflectionGenericClass *rgi = (MonoReflectionGenericClass *) type;
9510
9511                 tb = rgi->generic_type;
9512                 is_dynamic = TRUE;
9513         }
9514
9515         /* FIXME: fix the CreateGenericParameters protocol to avoid the two stage setup of TypeBuilders */
9516         if (tb && tb->generic_container)
9517                 mono_reflection_create_generic_class (tb);
9518
9519         klass = mono_class_from_mono_type (type->type);
9520         if (!klass->generic_container) {
9521                 mono_loader_unlock ();
9522                 return NULL;
9523         }
9524
9525         if (klass->wastypebuilder) {
9526                 tb = (MonoReflectionTypeBuilder *) klass->reflection_info;
9527
9528                 is_dynamic = TRUE;
9529         }
9530
9531         mono_loader_unlock ();
9532
9533         geninst = mono_class_bind_generic_parameters (klass, type_argc, types, is_dynamic);
9534
9535         return &geninst->byval_arg;
9536 }
9537
9538 MonoClass*
9539 mono_class_bind_generic_parameters (MonoClass *klass, int type_argc, MonoType **types, gboolean is_dynamic)
9540 {
9541         MonoGenericClass *gclass;
9542         MonoGenericInst *inst;
9543
9544         g_assert (klass->generic_container);
9545
9546         inst = mono_metadata_get_generic_inst (type_argc, types);
9547         gclass = mono_metadata_lookup_generic_class (klass, inst, is_dynamic);
9548
9549         return mono_generic_class_get_class (gclass);
9550 }
9551
9552 MonoReflectionMethod*
9553 mono_reflection_bind_generic_method_parameters (MonoReflectionMethod *rmethod, MonoArray *types)
9554 {
9555         MonoClass *klass;
9556         MonoMethod *method, *inflated;
9557         MonoMethodInflated *imethod;
9558         MonoReflectionMethodBuilder *mb = NULL;
9559         MonoGenericContext tmp_context;
9560         MonoGenericInst *ginst;
9561         MonoType **type_argv;
9562         int count, i;
9563
9564         MONO_ARCH_SAVE_REGS;
9565
9566         if (!strcmp (rmethod->object.vtable->klass->name, "MethodBuilder")) {
9567 #ifndef DISABLE_REFLECTION_EMIT
9568                 MonoReflectionTypeBuilder *tb;
9569                 MonoClass *klass;
9570
9571                 mb = (MonoReflectionMethodBuilder *) rmethod;
9572                 tb = (MonoReflectionTypeBuilder *) mb->type;
9573                 klass = mono_class_from_mono_type (tb->type.type);
9574
9575                 method = methodbuilder_to_mono_method (klass, mb);
9576 #else
9577                 g_assert_not_reached ();
9578                 method = NULL;
9579 #endif
9580         } else {
9581                 method = rmethod->method;
9582         }
9583
9584         klass = method->klass;
9585
9586         if (method->is_inflated)
9587                 method = ((MonoMethodInflated *) method)->declaring;
9588
9589         count = mono_method_signature (method)->generic_param_count;
9590         if (count != mono_array_length (types))
9591                 return NULL;
9592
9593         type_argv = g_new0 (MonoType *, count);
9594         for (i = 0; i < count; i++) {
9595                 MonoReflectionType *garg = mono_array_get (types, gpointer, i);
9596                 type_argv [i] = garg->type;
9597         }
9598         ginst = mono_metadata_get_generic_inst (count, type_argv);
9599         g_free (type_argv);
9600
9601         tmp_context.class_inst = klass->generic_class ? klass->generic_class->context.class_inst : NULL;
9602         tmp_context.method_inst = ginst;
9603
9604         inflated = mono_class_inflate_generic_method (method, &tmp_context);
9605         imethod = (MonoMethodInflated *) inflated;
9606
9607         if (method->klass->image->dynamic) {
9608                 MonoDynamicImage *image = (MonoDynamicImage*)method->klass->image;
9609                 /*
9610                  * This table maps metadata structures representing inflated methods/fields
9611                  * to the reflection objects representing their generic definitions.
9612                  */
9613                 mono_loader_lock ();
9614                 mono_g_hash_table_insert (image->generic_def_objects, imethod, rmethod);
9615                 mono_loader_unlock ();
9616         }
9617         
9618         return mono_method_get_object (mono_object_domain (rmethod), inflated, NULL);
9619 }
9620
9621 #ifndef DISABLE_REFLECTION_EMIT
9622
9623 static MonoMethod *
9624 inflate_mono_method (MonoClass *klass, MonoMethod *method, MonoObject *obj)
9625 {
9626         MonoMethodInflated *imethod;
9627         MonoGenericContext *context;
9628         int i;
9629
9630         /*
9631          * With generic code sharing the klass might not be inflated.
9632          * This can happen because classes inflated with their own
9633          * type arguments are "normalized" to the uninflated class.
9634          */
9635         if (!klass->generic_class)
9636                 return method;
9637
9638         context = mono_class_get_context (klass);
9639
9640         if (klass->method.count) {
9641                 /* Find the already created inflated method */
9642                 for (i = 0; i < klass->method.count; ++i) {
9643                         g_assert (klass->methods [i]->is_inflated);
9644                         if (((MonoMethodInflated*)klass->methods [i])->declaring == method)
9645                                 break;
9646                 }
9647                 g_assert (i < klass->method.count);
9648                 imethod = (MonoMethodInflated*)klass->methods [i];
9649         } else {
9650                 imethod = (MonoMethodInflated *) mono_class_inflate_generic_method_full (method, klass, context);
9651         }
9652
9653         if (method->is_generic && method->klass->image->dynamic) {
9654                 MonoDynamicImage *image = (MonoDynamicImage*)method->klass->image;
9655
9656                 mono_loader_lock ();
9657                 mono_g_hash_table_insert (image->generic_def_objects, imethod, obj);
9658                 mono_loader_unlock ();
9659         }
9660         return (MonoMethod *) imethod;
9661 }
9662
9663 static MonoMethod *
9664 inflate_method (MonoReflectionGenericClass *type, MonoObject *obj)
9665 {
9666         MonoMethod *method;
9667         MonoClass *gklass;
9668
9669         gklass = mono_class_from_mono_type (type->generic_type->type.type);
9670
9671         if (!strcmp (obj->vtable->klass->name, "MethodBuilder"))
9672                 if (((MonoReflectionMethodBuilder*)obj)->mhandle)
9673                         method = ((MonoReflectionMethodBuilder*)obj)->mhandle;
9674                 else
9675                         method = methodbuilder_to_mono_method (gklass, (MonoReflectionMethodBuilder *) obj);
9676         else if (!strcmp (obj->vtable->klass->name, "ConstructorBuilder"))
9677                 method = ctorbuilder_to_mono_method (gklass, (MonoReflectionCtorBuilder *) obj);
9678         else if (!strcmp (obj->vtable->klass->name, "MonoMethod") || !strcmp (obj->vtable->klass->name, "MonoCMethod"))
9679                 method = ((MonoReflectionMethod *) obj)->method;
9680         else {
9681                 method = NULL; /* prevent compiler warning */
9682                 g_assert_not_reached ();
9683         }
9684
9685         return inflate_mono_method (mono_class_from_mono_type (type->type.type), method, obj);
9686 }
9687
9688 /*TODO avoid saving custom attrs for generic classes as it's enough to have them on the generic type definition.*/
9689 void
9690 mono_reflection_generic_class_initialize (MonoReflectionGenericClass *type, MonoArray *methods, 
9691                                           MonoArray *ctors, MonoArray *fields, MonoArray *properties,
9692                                           MonoArray *events)
9693 {
9694         MonoGenericClass *gclass;
9695         MonoDynamicGenericClass *dgclass;
9696         MonoClass *klass, *gklass;
9697         int i;
9698
9699         MONO_ARCH_SAVE_REGS;
9700
9701         klass = mono_class_from_mono_type (type->type.type);
9702         g_assert (type->type.type->type == MONO_TYPE_GENERICINST);
9703         gclass = type->type.type->data.generic_class;
9704
9705         g_assert (gclass->is_dynamic);
9706         dgclass = (MonoDynamicGenericClass *) gclass;
9707
9708         if (dgclass->initialized)
9709                 return;
9710
9711         gklass = gclass->container_class;
9712         mono_class_init (gklass);
9713
9714         dgclass->count_methods = methods ? mono_array_length (methods) : 0;
9715         dgclass->count_ctors = ctors ? mono_array_length (ctors) : 0;
9716         dgclass->count_fields = fields ? mono_array_length (fields) : 0;
9717         dgclass->count_properties = properties ? mono_array_length (properties) : 0;
9718         dgclass->count_events = events ? mono_array_length (events) : 0;
9719
9720         dgclass->methods = g_new0 (MonoMethod *, dgclass->count_methods);
9721         dgclass->ctors = g_new0 (MonoMethod *, dgclass->count_ctors);
9722         dgclass->fields = g_new0 (MonoClassField, dgclass->count_fields);
9723         dgclass->properties = g_new0 (MonoProperty, dgclass->count_properties);
9724         dgclass->events = g_new0 (MonoEvent, dgclass->count_events);
9725         dgclass->field_objects = g_new0 (MonoObject*, dgclass->count_fields);
9726         dgclass->field_generic_types = g_new0 (MonoType*, dgclass->count_fields);
9727
9728         for (i = 0; i < dgclass->count_methods; i++) {
9729                 MonoObject *obj = mono_array_get (methods, gpointer, i);
9730
9731                 dgclass->methods [i] = inflate_method (type, obj);
9732         }
9733
9734         for (i = 0; i < dgclass->count_ctors; i++) {
9735                 MonoObject *obj = mono_array_get (ctors, gpointer, i);
9736
9737                 dgclass->ctors [i] = inflate_method (type, obj);
9738         }
9739
9740         for (i = 0; i < dgclass->count_fields; i++) {
9741                 MonoObject *obj = mono_array_get (fields, gpointer, i);
9742                 MonoClassField *field, *inflated_field = NULL;
9743
9744                 if (!strcmp (obj->vtable->klass->name, "FieldBuilder"))
9745                         inflated_field = field = fieldbuilder_to_mono_class_field (klass, (MonoReflectionFieldBuilder *) obj);
9746                 else if (!strcmp (obj->vtable->klass->name, "MonoField"))
9747                         field = ((MonoReflectionField *) obj)->field;
9748                 else {
9749                         field = NULL; /* prevent compiler warning */
9750                         g_assert_not_reached ();
9751                 }
9752
9753                 dgclass->fields [i] = *field;
9754                 dgclass->fields [i].parent = klass;
9755                 dgclass->fields [i].type = mono_class_inflate_generic_type (
9756                         field->type, mono_generic_class_get_context ((MonoGenericClass *) dgclass));
9757                 dgclass->field_generic_types [i] = field->type;
9758                 MOVING_GC_REGISTER (&dgclass->field_objects [i]);
9759                 dgclass->field_objects [i] = obj;
9760
9761                 if (inflated_field) {
9762                         g_free (inflated_field);
9763                 } else {
9764                         dgclass->fields [i].name = g_strdup (dgclass->fields [i].name);
9765                 }
9766         }
9767
9768         for (i = 0; i < dgclass->count_properties; i++) {
9769                 MonoObject *obj = mono_array_get (properties, gpointer, i);
9770                 MonoProperty *property = &dgclass->properties [i];
9771
9772                 if (!strcmp (obj->vtable->klass->name, "PropertyBuilder")) {
9773                         MonoReflectionPropertyBuilder *pb = (MonoReflectionPropertyBuilder *) obj;
9774
9775                         property->parent = klass;
9776                         property->attrs = pb->attrs;
9777                         property->name = mono_string_to_utf8 (pb->name);
9778                         if (pb->get_method)
9779                                 property->get = inflate_method (type, (MonoObject *) pb->get_method);
9780                         if (pb->set_method)
9781                                 property->set = inflate_method (type, (MonoObject *) pb->set_method);
9782                 } else if (!strcmp (obj->vtable->klass->name, "MonoProperty")) {
9783                         *property = *((MonoReflectionProperty *) obj)->property;
9784                         property->name = g_strdup (property->name);
9785
9786                         if (property->get)
9787                                 property->get = inflate_mono_method (klass, property->get, NULL);
9788                         if (property->set)
9789                                 property->set = inflate_mono_method (klass, property->set, NULL);
9790                 } else
9791                         g_assert_not_reached ();
9792         }
9793
9794         for (i = 0; i < dgclass->count_events; i++) {
9795                 MonoObject *obj = mono_array_get (events, gpointer, i);
9796                 MonoEvent *event = &dgclass->events [i];
9797
9798                 if (!strcmp (obj->vtable->klass->name, "EventBuilder")) {
9799                         MonoReflectionEventBuilder *eb = (MonoReflectionEventBuilder *) obj;
9800
9801                         event->parent = klass;
9802                         event->attrs = eb->attrs;
9803                         event->name = mono_string_to_utf8 (eb->name);
9804                         if (eb->add_method)
9805                                 event->add = inflate_method (type, (MonoObject *) eb->add_method);
9806                         if (eb->remove_method)
9807                                 event->remove = inflate_method (type, (MonoObject *) eb->remove_method);
9808                 } else if (!strcmp (obj->vtable->klass->name, "MonoEvent")) {
9809                         *event = *((MonoReflectionEvent *) obj)->event;
9810                         event->name = g_strdup (event->name);
9811
9812                         if (event->add)
9813                                 event->add = inflate_mono_method (klass, event->add, NULL);
9814                         if (event->remove)
9815                                 event->remove = inflate_mono_method (klass, event->remove, NULL);
9816                 } else
9817                         g_assert_not_reached ();
9818         }
9819
9820         dgclass->initialized = TRUE;
9821 }
9822
9823 static void
9824 ensure_generic_class_runtime_vtable (MonoClass *klass)
9825 {
9826         MonoClass *gklass = klass->generic_class->container_class;
9827         int i;
9828
9829         if (klass->wastypebuilder)
9830                 return;
9831
9832         ensure_runtime_vtable (gklass);
9833
9834         klass->method.count = gklass->method.count;
9835         klass->methods = mono_image_alloc (klass->image, sizeof (MonoMethod*) * (klass->method.count + 1));
9836
9837         for (i = 0; i < klass->method.count; i++) {
9838                 klass->methods [i] = mono_class_inflate_generic_method_full (
9839                         gklass->methods [i], klass, mono_class_get_context (klass));
9840         }
9841
9842         klass->interface_count = gklass->interface_count;
9843         klass->interfaces = mono_image_alloc (klass->image, sizeof (MonoClass*) * klass->interface_count);
9844         for (i = 0; i < klass->interface_count; ++i) {
9845                 MonoType *iface_type = mono_class_inflate_generic_type (&gklass->interfaces [i]->byval_arg, mono_class_get_context (klass));
9846                 klass->interfaces [i] = mono_class_from_mono_type (iface_type);
9847                 mono_metadata_free_type (iface_type);
9848
9849                 ensure_runtime_vtable (klass->interfaces [i]);
9850         }
9851         /*We can only finish with this klass once it's parent has as well*/
9852         if (gklass->wastypebuilder)
9853                 klass->wastypebuilder = TRUE;
9854         return;
9855 }
9856
9857 static void
9858 ensure_runtime_vtable (MonoClass *klass)
9859 {
9860         MonoReflectionTypeBuilder *tb = klass->reflection_info;
9861         int i, num, j;
9862
9863         if (!klass->image->dynamic || (!tb && !klass->generic_class) || klass->wastypebuilder)
9864                 return;
9865         if (klass->parent)
9866                 ensure_runtime_vtable (klass->parent);
9867
9868         if (tb) {
9869                 num = tb->ctors? mono_array_length (tb->ctors): 0;
9870                 num += tb->num_methods;
9871                 klass->method.count = num;
9872                 klass->methods = mono_image_alloc (klass->image, sizeof (MonoMethod*) * num);
9873                 num = tb->ctors? mono_array_length (tb->ctors): 0;
9874                 for (i = 0; i < num; ++i)
9875                         klass->methods [i] = ctorbuilder_to_mono_method (klass, mono_array_get (tb->ctors, MonoReflectionCtorBuilder*, i));
9876                 num = tb->num_methods;
9877                 j = i;
9878                 for (i = 0; i < num; ++i)
9879                         klass->methods [j++] = methodbuilder_to_mono_method (klass, mono_array_get (tb->methods, MonoReflectionMethodBuilder*, i));
9880         
9881                 if (tb->interfaces) {
9882                         klass->interface_count = mono_array_length (tb->interfaces);
9883                         klass->interfaces = mono_image_alloc (klass->image, sizeof (MonoClass*) * klass->interface_count);
9884                         for (i = 0; i < klass->interface_count; ++i) {
9885                                 MonoReflectionType *iface = mono_array_get (tb->interfaces, gpointer, i);
9886                                 klass->interfaces [i] = mono_class_from_mono_type (iface->type);
9887                                 ensure_runtime_vtable (klass->interfaces [i]);
9888                         }
9889                 }
9890         } else if (klass->generic_class){
9891                 ensure_generic_class_runtime_vtable (klass);
9892         }
9893
9894         if (klass->flags & TYPE_ATTRIBUTE_INTERFACE) {
9895                 for (i = 0; i < klass->method.count; ++i)
9896                         klass->methods [i]->slot = i;
9897                 
9898                 mono_class_setup_interface_offsets (klass);
9899                 mono_class_setup_interface_id (klass);
9900         }
9901
9902         /*
9903          * The generic vtable is needed even if image->run is not set since some
9904          * runtime code like ves_icall_Type_GetMethodsByName depends on 
9905          * method->slot being defined.
9906          */
9907
9908         /* 
9909          * tb->methods could not be freed since it is used for determining 
9910          * overrides during dynamic vtable construction.
9911          */
9912 }
9913
9914 void
9915 mono_reflection_get_dynamic_overrides (MonoClass *klass, MonoMethod ***overrides, int *num_overrides)
9916 {
9917         MonoReflectionTypeBuilder *tb;
9918         int i, onum;
9919
9920         *overrides = NULL;
9921         *num_overrides = 0;
9922
9923         g_assert (klass->image->dynamic);
9924
9925         if (!klass->reflection_info)
9926                 return;
9927
9928         g_assert (strcmp (((MonoObject*)klass->reflection_info)->vtable->klass->name, "TypeBuilder") == 0);
9929
9930         tb = (MonoReflectionTypeBuilder*)klass->reflection_info;
9931
9932         onum = 0;
9933         if (tb->methods) {
9934                 for (i = 0; i < tb->num_methods; ++i) {
9935                         MonoReflectionMethodBuilder *mb = 
9936                                 mono_array_get (tb->methods, MonoReflectionMethodBuilder*, i);
9937                         if (mb->override_method)
9938                                 onum ++;
9939                 }
9940         }
9941
9942         if (onum) {
9943                 *overrides = g_new0 (MonoMethod*, onum * 2);
9944
9945                 onum = 0;
9946                 for (i = 0; i < tb->num_methods; ++i) {
9947                         MonoReflectionMethodBuilder *mb = 
9948                                 mono_array_get (tb->methods, MonoReflectionMethodBuilder*, i);
9949                         if (mb->override_method) {
9950                                 (*overrides) [onum * 2] = 
9951                                         mb->override_method->method;
9952                                 (*overrides) [onum * 2 + 1] =
9953                                         mb->mhandle;
9954
9955                                 /* FIXME: What if 'override_method' is a MethodBuilder ? */
9956                                 g_assert (mb->override_method->method);
9957                                 g_assert (mb->mhandle);
9958
9959                                 onum ++;
9960                         }
9961                 }
9962         }
9963
9964         *num_overrides = onum;
9965 }
9966
9967 static void
9968 typebuilder_setup_fields (MonoClass *klass)
9969 {
9970         MonoReflectionTypeBuilder *tb = klass->reflection_info;
9971         MonoReflectionFieldBuilder *fb;
9972         MonoClassField *field;
9973         MonoMemPool *mp = klass->image->mempool;
9974         const char *p, *p2;
9975         int i;
9976         guint32 len, idx, real_size = 0;
9977
9978         klass->field.count = tb->num_fields;
9979         klass->field.first = 0;
9980
9981         if (tb->class_size) {
9982                 g_assert ((tb->packing_size & 0xfffffff0) == 0);
9983                 klass->packing_size = tb->packing_size;
9984                 real_size = klass->instance_size + tb->class_size;
9985         }
9986
9987         if (!klass->field.count) {
9988                 klass->instance_size = MAX (klass->instance_size, real_size);
9989                 return;
9990         }
9991         
9992         klass->fields = mp_g_new0 (mp, MonoClassField, klass->field.count);
9993         klass->field_def_values = mp_g_new0 (mp, MonoFieldDefaultValue, klass->field.count);
9994
9995         for (i = 0; i < klass->field.count; ++i) {
9996                 fb = mono_array_get (tb->fields, gpointer, i);
9997                 field = &klass->fields [i];
9998                 field->name = mp_string_to_utf8 (mp, fb->name);
9999                 if (fb->attrs) {
10000                         field->type = mono_metadata_type_dup (mp, fb->type->type);
10001                         field->type->attrs = fb->attrs;
10002                 } else {
10003                         field->type = fb->type->type;
10004                 }
10005                 if ((fb->attrs & FIELD_ATTRIBUTE_HAS_FIELD_RVA) && fb->rva_data)
10006                         klass->field_def_values [i].data = mono_array_addr (fb->rva_data, char, 0);
10007                 if (fb->offset != -1)
10008                         field->offset = fb->offset;
10009                 field->parent = klass;
10010                 fb->handle = field;
10011                 mono_save_custom_attrs (klass->image, field, fb->cattrs);
10012
10013                 if (fb->def_value) {
10014                         MonoDynamicImage *assembly = (MonoDynamicImage*)klass->image;
10015                         field->type->attrs |= FIELD_ATTRIBUTE_HAS_DEFAULT;
10016                         idx = encode_constant (assembly, fb->def_value, &klass->field_def_values [i].def_type);
10017                         /* Copy the data from the blob since it might get realloc-ed */
10018                         p = assembly->blob.data + idx;
10019                         len = mono_metadata_decode_blob_size (p, &p2);
10020                         len += p2 - p;
10021                         klass->field_def_values [i].data = mono_mempool_alloc (mp, len);
10022                         memcpy ((gpointer)klass->field_def_values [i].data, p, len);
10023                 }
10024         }
10025
10026         klass->instance_size = MAX (klass->instance_size, real_size);
10027         mono_class_layout_fields (klass);
10028 }
10029
10030 static void
10031 typebuilder_setup_properties (MonoClass *klass)
10032 {
10033         MonoReflectionTypeBuilder *tb = klass->reflection_info;
10034         MonoReflectionPropertyBuilder *pb;
10035         MonoMemPool *mp = klass->image->mempool;
10036         int i;
10037
10038         klass->property.count = tb->properties ? mono_array_length (tb->properties) : 0;
10039         klass->property.first = 0;
10040
10041         klass->properties = mp_g_new0 (mp, MonoProperty, klass->property.count);
10042         for (i = 0; i < klass->property.count; ++i) {
10043                 pb = mono_array_get (tb->properties, MonoReflectionPropertyBuilder*, i);
10044                 klass->properties [i].parent = klass;
10045                 klass->properties [i].attrs = pb->attrs;
10046                 klass->properties [i].name = mp_string_to_utf8 (mp, pb->name);
10047                 if (pb->get_method)
10048                         klass->properties [i].get = pb->get_method->mhandle;
10049                 if (pb->set_method)
10050                         klass->properties [i].set = pb->set_method->mhandle;
10051
10052                 mono_save_custom_attrs (klass->image, &klass->properties [i], pb->cattrs);
10053         }
10054 }
10055
10056 MonoReflectionEvent *
10057 mono_reflection_event_builder_get_event_info (MonoReflectionTypeBuilder *tb, MonoReflectionEventBuilder *eb)
10058 {
10059         MonoEvent *event = g_new0 (MonoEvent, 1);
10060         MonoClass *klass;
10061         int j;
10062
10063         klass = my_mono_class_from_mono_type (tb->type.type);
10064
10065         event->parent = klass;
10066         event->attrs = eb->attrs;
10067         event->name = mono_string_to_utf8 (eb->name);
10068         if (eb->add_method)
10069                 event->add = eb->add_method->mhandle;
10070         if (eb->remove_method)
10071                 event->remove = eb->remove_method->mhandle;
10072         if (eb->raise_method)
10073                 event->raise = eb->raise_method->mhandle;
10074
10075         if (eb->other_methods) {
10076                 event->other = g_new0 (MonoMethod*, mono_array_length (eb->other_methods) + 1);
10077                 for (j = 0; j < mono_array_length (eb->other_methods); ++j) {
10078                         MonoReflectionMethodBuilder *mb = 
10079                                 mono_array_get (eb->other_methods,
10080                                                 MonoReflectionMethodBuilder*, j);
10081                         event->other [j] = mb->mhandle;
10082                 }
10083         }
10084
10085         return mono_event_get_object (mono_object_domain (tb), klass, event);
10086 }
10087
10088 static void
10089 typebuilder_setup_events (MonoClass *klass)
10090 {
10091         MonoReflectionTypeBuilder *tb = klass->reflection_info;
10092         MonoReflectionEventBuilder *eb;
10093         MonoMemPool *mp = klass->image->mempool;
10094         int i, j;
10095
10096         klass->event.count = tb->events ? mono_array_length (tb->events) : 0;
10097         klass->event.first = 0;
10098
10099         klass->events = mp_g_new0 (mp, MonoEvent, klass->event.count);
10100         for (i = 0; i < klass->event.count; ++i) {
10101                 eb = mono_array_get (tb->events, MonoReflectionEventBuilder*, i);
10102                 klass->events [i].parent = klass;
10103                 klass->events [i].attrs = eb->attrs;
10104                 klass->events [i].name = mp_string_to_utf8 (mp, eb->name);
10105                 if (eb->add_method)
10106                         klass->events [i].add = eb->add_method->mhandle;
10107                 if (eb->remove_method)
10108                         klass->events [i].remove = eb->remove_method->mhandle;
10109                 if (eb->raise_method)
10110                         klass->events [i].raise = eb->raise_method->mhandle;
10111
10112                 if (eb->other_methods) {
10113                         klass->events [i].other = mp_g_new0 (mp, MonoMethod*, mono_array_length (eb->other_methods) + 1);
10114                         for (j = 0; j < mono_array_length (eb->other_methods); ++j) {
10115                                 MonoReflectionMethodBuilder *mb = 
10116                                         mono_array_get (eb->other_methods,
10117                                                                         MonoReflectionMethodBuilder*, j);
10118                                 klass->events [i].other [j] = mb->mhandle;
10119                         }
10120                 }
10121                 mono_save_custom_attrs (klass->image, &klass->events [i], eb->cattrs);
10122         }
10123 }
10124
10125 static gboolean
10126 remove_instantiations_of (gpointer key,
10127                                                   gpointer value,
10128                                                   gpointer user_data)
10129 {
10130         MonoType *type = (MonoType*)key;
10131         MonoClass *klass = (MonoClass*)user_data;
10132
10133         if ((type->type == MONO_TYPE_GENERICINST) && (type->data.generic_class->container_class == klass))
10134                 return TRUE;
10135         else
10136                 return FALSE;
10137 }
10138
10139 MonoReflectionType*
10140 mono_reflection_create_runtime_class (MonoReflectionTypeBuilder *tb)
10141 {
10142         MonoClass *klass;
10143         MonoDomain* domain;
10144         MonoReflectionType* res;
10145         int i;
10146
10147         MONO_ARCH_SAVE_REGS;
10148
10149         domain = mono_object_domain (tb);
10150         klass = my_mono_class_from_mono_type (tb->type.type);
10151
10152         mono_save_custom_attrs (klass->image, klass, tb->cattrs);
10153         
10154         /* 
10155          * we need to lock the domain because the lock will be taken inside
10156          * So, we need to keep the locking order correct.
10157          */
10158         mono_domain_lock (domain);
10159         mono_loader_lock ();
10160         if (klass->wastypebuilder) {
10161                 mono_loader_unlock ();
10162                 mono_domain_unlock (domain);
10163                 return mono_type_get_object (mono_object_domain (tb), &klass->byval_arg);
10164         }
10165         /*
10166          * Fields to set in klass:
10167          * the various flags: delegate/unicode/contextbound etc.
10168          */
10169         klass->flags = tb->attrs;
10170         klass->has_cctor = 1;
10171         klass->has_finalize = 1;
10172
10173 #if 0
10174         if (!((MonoDynamicImage*)klass->image)->run) {
10175                 if (klass->generic_container) {
10176                         /* FIXME: The code below can't handle generic classes */
10177                         klass->wastypebuilder = TRUE;
10178                         mono_loader_unlock ();
10179                         mono_domain_unlock (domain);
10180                         return mono_type_get_object (mono_object_domain (tb), &klass->byval_arg);
10181                 }
10182         }
10183 #endif
10184
10185         /* enums are done right away */
10186         if (!klass->enumtype)
10187                 ensure_runtime_vtable (klass);
10188
10189         if (tb->subtypes) {
10190                 for (i = 0; i < mono_array_length (tb->subtypes); ++i) {
10191                         MonoReflectionTypeBuilder *subtb = mono_array_get (tb->subtypes, MonoReflectionTypeBuilder*, i);
10192                         klass->nested_classes = g_list_prepend_mempool (klass->image->mempool, klass->nested_classes, my_mono_class_from_mono_type (subtb->type.type));
10193                 }
10194         }
10195
10196         klass->nested_classes_inited = TRUE;
10197
10198         /* fields and object layout */
10199         if (klass->parent) {
10200                 if (!klass->parent->size_inited)
10201                         mono_class_init (klass->parent);
10202                 klass->instance_size = klass->parent->instance_size;
10203                 klass->sizes.class_size = 0;
10204                 klass->min_align = klass->parent->min_align;
10205                 /* if the type has no fields we won't call the field_setup
10206                  * routine which sets up klass->has_references.
10207                  */
10208                 klass->has_references |= klass->parent->has_references;
10209         } else {
10210                 klass->instance_size = sizeof (MonoObject);
10211                 klass->min_align = 1;
10212         }
10213
10214         /* FIXME: handle packing_size and instance_size */
10215         typebuilder_setup_fields (klass);
10216
10217         typebuilder_setup_properties (klass);
10218
10219         typebuilder_setup_events (klass);
10220         
10221         klass->wastypebuilder = TRUE;
10222
10223         /* 
10224          * If we are a generic TypeBuilder, there might be instantiations in the type cache
10225          * which have type System.Reflection.MonoGenericClass, but after the type is created, 
10226          * we want to return normal System.MonoType objects, so clear these out from the cache.
10227          */
10228         if (domain->type_hash && klass->generic_container)
10229                 mono_g_hash_table_foreach_remove (domain->type_hash, remove_instantiations_of, klass);
10230
10231         mono_loader_unlock ();
10232         mono_domain_unlock (domain);
10233
10234         if (klass->enumtype && !mono_class_is_valid_enum (klass)) {
10235                 mono_class_set_failure (klass, MONO_EXCEPTION_TYPE_LOAD, NULL);
10236                 mono_raise_exception (mono_get_exception_type_load (tb->name, NULL));
10237         }
10238
10239         res = mono_type_get_object (mono_object_domain (tb), &klass->byval_arg);
10240         g_assert (res != (MonoReflectionType*)tb);
10241
10242         return res;
10243 }
10244
10245 void
10246 mono_reflection_initialize_generic_parameter (MonoReflectionGenericParam *gparam)
10247 {
10248         MonoGenericParam *param;
10249         MonoImage *image;
10250
10251         MONO_ARCH_SAVE_REGS;
10252
10253         param = g_new0 (MonoGenericParam, 1);
10254
10255         if (gparam->mbuilder) {
10256                 if (!gparam->mbuilder->generic_container) {
10257                         MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder *)gparam->mbuilder->type;
10258                         MonoClass *klass = my_mono_class_from_mono_type (tb->type.type);
10259                         gparam->mbuilder->generic_container = mono_image_alloc0 (klass->image, sizeof (MonoGenericContainer));
10260                         gparam->mbuilder->generic_container->is_method = TRUE;
10261                 }
10262                 param->owner = gparam->mbuilder->generic_container;
10263         } else if (gparam->tbuilder) {
10264                 if (!gparam->tbuilder->generic_container) {
10265                         MonoClass *klass = my_mono_class_from_mono_type (gparam->tbuilder->type.type);
10266                         gparam->tbuilder->generic_container = mono_image_alloc0 (klass->image, sizeof (MonoGenericContainer));
10267                         gparam->tbuilder->generic_container->owner.klass = klass;
10268                 }
10269                 param->owner = gparam->tbuilder->generic_container;
10270         }
10271
10272         param->name = mono_string_to_utf8 (gparam->name);
10273         param->num = gparam->index;
10274
10275         image = &gparam->tbuilder->module->dynamic_image->image;
10276         mono_class_from_generic_parameter (param, image, gparam->mbuilder != NULL);
10277
10278         gparam->type.type = &param->pklass->byval_arg;
10279
10280         MOVING_GC_REGISTER (&param->pklass->reflection_info);
10281         param->pklass->reflection_info = gparam; /* FIXME: GC pin gparam */
10282 }
10283
10284 MonoArray *
10285 mono_reflection_sighelper_get_signature_local (MonoReflectionSigHelper *sig)
10286 {
10287         MonoDynamicImage *assembly = sig->module->dynamic_image;
10288         guint32 na = mono_array_length (sig->arguments);
10289         guint32 buflen, i;
10290         MonoArray *result;
10291         SigBuffer buf;
10292
10293         sigbuffer_init (&buf, 32);
10294
10295         sigbuffer_add_value (&buf, 0x07);
10296         sigbuffer_add_value (&buf, na);
10297         for (i = 0; i < na; ++i) {
10298                 MonoReflectionType *type = mono_array_get (sig->arguments, MonoReflectionType *, i);
10299                 encode_reflection_type (assembly, type, &buf);
10300         }
10301
10302         buflen = buf.p - buf.buf;
10303         result = mono_array_new (mono_domain_get (), mono_defaults.byte_class, buflen);
10304         memcpy (mono_array_addr (result, char, 0), buf.buf, buflen);
10305         sigbuffer_free (&buf);
10306
10307         return result;
10308 }
10309
10310 MonoArray *
10311 mono_reflection_sighelper_get_signature_field (MonoReflectionSigHelper *sig)
10312 {
10313         MonoDynamicImage *assembly = sig->module->dynamic_image;
10314         guint32 na = mono_array_length (sig->arguments);
10315         guint32 buflen, i;
10316         MonoArray *result;
10317         SigBuffer buf;
10318
10319         sigbuffer_init (&buf, 32);
10320
10321         sigbuffer_add_value (&buf, 0x06);
10322         for (i = 0; i < na; ++i) {
10323                 MonoReflectionType *type = mono_array_get (sig->arguments, MonoReflectionType *, i);
10324                 encode_reflection_type (assembly, type, &buf);
10325         }
10326
10327         buflen = buf.p - buf.buf;
10328         result = mono_array_new (mono_domain_get (), mono_defaults.byte_class, buflen);
10329         memcpy (mono_array_addr (result, char, 0), buf.buf, buflen);
10330         sigbuffer_free (&buf);
10331
10332         return result;
10333 }
10334
10335 void 
10336 mono_reflection_create_dynamic_method (MonoReflectionDynamicMethod *mb)
10337 {
10338         ReflectionMethodBuilder rmb;
10339         MonoMethodSignature *sig;
10340         MonoClass *klass;
10341         GSList *l;
10342         int i;
10343
10344         sig = dynamic_method_to_signature (mb);
10345
10346         reflection_methodbuilder_from_dynamic_method (&rmb, mb);
10347
10348         /*
10349          * Resolve references.
10350          */
10351         /* 
10352          * Every second entry in the refs array is reserved for storing handle_class,
10353          * which is needed by the ldtoken implementation in the JIT.
10354          */
10355         rmb.nrefs = mb->nrefs;
10356         rmb.refs = g_new0 (gpointer, mb->nrefs + 1);
10357         for (i = 0; i < mb->nrefs; i += 2) {
10358                 MonoClass *handle_class;
10359                 gpointer ref;
10360                 MonoObject *obj = mono_array_get (mb->refs, MonoObject*, i);
10361
10362                 if (strcmp (obj->vtable->klass->name, "DynamicMethod") == 0) {
10363                         MonoReflectionDynamicMethod *method = (MonoReflectionDynamicMethod*)obj;
10364                         /*
10365                          * The referenced DynamicMethod should already be created by the managed
10366                          * code, except in the case of circular references. In that case, we store
10367                          * method in the refs array, and fix it up later when the referenced 
10368                          * DynamicMethod is created.
10369                          */
10370                         if (method->mhandle) {
10371                                 ref = method->mhandle;
10372                         } else {
10373                                 /* FIXME: GC object stored in unmanaged memory */
10374                                 ref = method;
10375
10376                                 /* FIXME: GC object stored in unmanaged memory */
10377                                 method->referenced_by = g_slist_append (method->referenced_by, mb);
10378                         }
10379                         handle_class = mono_defaults.methodhandle_class;
10380                 } else {
10381                         ref = resolve_object (mb->module->image, obj, &handle_class, NULL);
10382                         if (!ref) {
10383                                 g_free (rmb.refs);
10384                                 mono_raise_exception (mono_get_exception_type_load (NULL, NULL));
10385                                 return;
10386                         }
10387                 }
10388
10389                 rmb.refs [i] = ref; /* FIXME: GC object stored in unmanaged memory (change also resolve_object() signature) */
10390                 rmb.refs [i + 1] = handle_class;
10391         }               
10392
10393         klass = mb->owner ? mono_class_from_mono_type (mb->owner->type) : mono_defaults.object_class;
10394
10395         mb->mhandle = reflection_methodbuilder_to_mono_method (klass, &rmb, sig);
10396
10397         /* Fix up refs entries pointing at us */
10398         for (l = mb->referenced_by; l; l = l->next) {
10399                 MonoReflectionDynamicMethod *method = (MonoReflectionDynamicMethod*)l->data;
10400                 MonoMethodWrapper *wrapper = (MonoMethodWrapper*)method->mhandle;
10401                 gpointer *data;
10402                 
10403                 g_assert (method->mhandle);
10404
10405                 data = (gpointer*)wrapper->method_data;
10406                 for (i = 0; i < GPOINTER_TO_UINT (data [0]); i += 2) {
10407                         if ((data [i + 1] == mb) && (data [i + 1 + 1] == mono_defaults.methodhandle_class))
10408                                 data [i + 1] = mb->mhandle;
10409                 }
10410         }
10411         g_slist_free (mb->referenced_by);
10412
10413         g_free (rmb.refs);
10414
10415         /* ilgen is no longer needed */
10416         mb->ilgen = NULL;
10417 }
10418
10419 #endif /* DISABLE_REFLECTION_EMIT */
10420
10421 void
10422 mono_reflection_destroy_dynamic_method (MonoReflectionDynamicMethod *mb)
10423 {
10424         g_assert (mb);
10425
10426         if (mb->mhandle)
10427                 mono_runtime_free_method (
10428                         mono_object_get_domain ((MonoObject*)mb), mb->mhandle);
10429 }
10430
10431 /**
10432  * 
10433  * mono_reflection_is_valid_dynamic_token:
10434  * 
10435  * Returns TRUE if token is valid.
10436  * 
10437  */
10438 gboolean
10439 mono_reflection_is_valid_dynamic_token (MonoDynamicImage *image, guint32 token)
10440 {
10441         return mono_g_hash_table_lookup (image->tokens, GUINT_TO_POINTER (token)) != NULL;
10442 }
10443
10444 #ifndef DISABLE_REFLECTION_EMIT
10445
10446 /**
10447  * mono_reflection_lookup_dynamic_token:
10448  *
10449  * Finish the Builder object pointed to by TOKEN and return the corresponding
10450  * runtime structure. If HANDLE_CLASS is not NULL, it is set to the class required by 
10451  * mono_ldtoken. If valid_token is TRUE, assert if it is not found in the token->object
10452  * mapping table.
10453  */
10454 gpointer
10455 mono_reflection_lookup_dynamic_token (MonoImage *image, guint32 token, gboolean valid_token, MonoClass **handle_class, MonoGenericContext *context)
10456 {
10457         MonoDynamicImage *assembly = (MonoDynamicImage*)image;
10458         MonoObject *obj;
10459         MonoClass *klass;
10460
10461         obj = mono_g_hash_table_lookup (assembly->tokens, GUINT_TO_POINTER (token));
10462         if (!obj) {
10463                 if (valid_token)
10464                         g_assert_not_reached ();
10465                 else
10466                         return NULL;
10467         }
10468
10469         if (!handle_class)
10470                 handle_class = &klass;
10471         return resolve_object (image, obj, handle_class, context);
10472 }
10473
10474 static gpointer
10475 resolve_object (MonoImage *image, MonoObject *obj, MonoClass **handle_class, MonoGenericContext *context)
10476 {
10477         gpointer result = NULL;
10478
10479         if (strcmp (obj->vtable->klass->name, "String") == 0) {
10480                 result = mono_string_intern ((MonoString*)obj);
10481                 *handle_class = NULL;
10482                 g_assert (result);
10483         } else if (strcmp (obj->vtable->klass->name, "MonoType") == 0) {
10484                 MonoReflectionType *tb = (MonoReflectionType*)obj;
10485                 if (context) {
10486                         MonoType *inflated = mono_class_inflate_generic_type (tb->type, context);
10487                         result = mono_class_from_mono_type (inflated);
10488                         mono_metadata_free_type (inflated);
10489                 } else {
10490                         result = mono_class_from_mono_type (tb->type);
10491                 }
10492                 *handle_class = mono_defaults.typehandle_class;
10493                 g_assert (result);
10494         } else if (strcmp (obj->vtable->klass->name, "MonoMethod") == 0 ||
10495                    strcmp (obj->vtable->klass->name, "MonoCMethod") == 0 ||
10496                    strcmp (obj->vtable->klass->name, "MonoGenericCMethod") == 0 ||
10497                    strcmp (obj->vtable->klass->name, "MonoGenericMethod") == 0) {
10498                 result = ((MonoReflectionMethod*)obj)->method;
10499                 if (context)
10500                         result = mono_class_inflate_generic_method (result, context);
10501                 *handle_class = mono_defaults.methodhandle_class;
10502                 g_assert (result);
10503         } else if (strcmp (obj->vtable->klass->name, "MethodBuilder") == 0) {
10504                 MonoReflectionMethodBuilder *mb = (MonoReflectionMethodBuilder*)obj;
10505                 result = mb->mhandle;
10506                 if (!result) {
10507                         /* Type is not yet created */
10508                         MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder*)mb->type;
10509
10510                         mono_domain_try_type_resolve (mono_domain_get (), NULL, (MonoObject*)tb);
10511
10512                         /*
10513                          * Hopefully this has been filled in by calling CreateType() on the
10514                          * TypeBuilder.
10515                          */
10516                         /*
10517                          * TODO: This won't work if the application finishes another 
10518                          * TypeBuilder instance instead of this one.
10519                          */
10520                         result = mb->mhandle;
10521                 }
10522                 if (context)
10523                         result = mono_class_inflate_generic_method (result, context);
10524                 *handle_class = mono_defaults.methodhandle_class;
10525         } else if (strcmp (obj->vtable->klass->name, "ConstructorBuilder") == 0) {
10526                 MonoReflectionCtorBuilder *cb = (MonoReflectionCtorBuilder*)obj;
10527
10528                 result = cb->mhandle;
10529                 if (!result) {
10530                         MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder*)cb->type;
10531
10532                         mono_domain_try_type_resolve (mono_domain_get (), NULL, (MonoObject*)tb);
10533                         result = cb->mhandle;
10534                 }
10535                 if (context)
10536                         result = mono_class_inflate_generic_method (result, context);
10537                 *handle_class = mono_defaults.methodhandle_class;
10538         } else if (strcmp (obj->vtable->klass->name, "MonoField") == 0) {
10539                 MonoClassField *field = ((MonoReflectionField*)obj)->field;
10540                 if (context) {
10541                         MonoType *inflated = mono_class_inflate_generic_type (&field->parent->byval_arg, context);
10542                         MonoClass *class = mono_class_from_mono_type (inflated);
10543                         MonoClassField *inflated_field;
10544                         gpointer iter = NULL;
10545                         mono_metadata_free_type (inflated);
10546                         while ((inflated_field = mono_class_get_fields (class, &iter))) {
10547                                 if (!strcmp (field->name, inflated_field->name))
10548                                         break;
10549                         }
10550                         g_assert (inflated_field && !strcmp (field->name, inflated_field->name));
10551                         result = inflated_field;
10552                 } else {
10553                         result = field;
10554                 }
10555                 *handle_class = mono_defaults.fieldhandle_class;
10556                 g_assert (result);
10557         } else if (strcmp (obj->vtable->klass->name, "FieldBuilder") == 0) {
10558                 MonoReflectionFieldBuilder *fb = (MonoReflectionFieldBuilder*)obj;
10559                 result = fb->handle;
10560
10561                 if (!result) {
10562                         MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder*)fb->typeb;
10563
10564                         mono_domain_try_type_resolve (mono_domain_get (), NULL, (MonoObject*)tb);
10565                         result = fb->handle;
10566                 }
10567
10568                 if (fb->handle && fb->handle->parent->generic_container) {
10569                         MonoClass *klass = fb->handle->parent;
10570                         MonoType *type = mono_class_inflate_generic_type (&klass->byval_arg, context);
10571                         MonoClass *inflated = mono_class_from_mono_type (type);
10572
10573                         result = mono_class_get_field_from_name (inflated, mono_field_get_name (fb->handle));
10574                         g_assert (result);
10575                         mono_metadata_free_type (type);
10576                 }
10577                 *handle_class = mono_defaults.fieldhandle_class;
10578         } else if (strcmp (obj->vtable->klass->name, "TypeBuilder") == 0) {
10579                 MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder*)obj;
10580                 MonoClass *klass;
10581
10582                 klass = tb->type.type->data.klass;
10583                 if (klass->wastypebuilder) {
10584                         /* Already created */
10585                         result = klass;
10586                 }
10587                 else {
10588                         mono_domain_try_type_resolve (mono_domain_get (), NULL, (MonoObject*)tb);
10589                         result = tb->type.type->data.klass;
10590                         g_assert (result);
10591                 }
10592                 *handle_class = mono_defaults.typehandle_class;
10593         } else if (strcmp (obj->vtable->klass->name, "SignatureHelper") == 0) {
10594                 MonoReflectionSigHelper *helper = (MonoReflectionSigHelper*)obj;
10595                 MonoMethodSignature *sig;
10596                 int nargs, i;
10597
10598                 if (helper->arguments)
10599                         nargs = mono_array_length (helper->arguments);
10600                 else
10601                         nargs = 0;
10602
10603                 sig = mono_metadata_signature_alloc (image, nargs);
10604                 sig->explicit_this = helper->call_conv & 64 ? 1 : 0;
10605                 sig->hasthis = helper->call_conv & 32 ? 1 : 0;
10606
10607                 if (helper->call_conv == 0) /* unmanaged */
10608                         sig->call_convention = helper->unmanaged_call_conv - 1;
10609                 else
10610                         if (helper->call_conv & 0x02)
10611                                 sig->call_convention = MONO_CALL_VARARG;
10612                 else
10613                         sig->call_convention = MONO_CALL_DEFAULT;
10614
10615                 sig->param_count = nargs;
10616                 /* TODO: Copy type ? */
10617                 sig->ret = helper->return_type->type;
10618                 for (i = 0; i < nargs; ++i) {
10619                         MonoReflectionType *rt = mono_array_get (helper->arguments, MonoReflectionType*, i);
10620                         sig->params [i] = rt->type;
10621                 }
10622
10623                 result = sig;
10624                 *handle_class = NULL;
10625         } else if (strcmp (obj->vtable->klass->name, "DynamicMethod") == 0) {
10626                 MonoReflectionDynamicMethod *method = (MonoReflectionDynamicMethod*)obj;
10627                 /* Already created by the managed code */
10628                 g_assert (method->mhandle);
10629                 result = method->mhandle;
10630                 *handle_class = mono_defaults.methodhandle_class;
10631         } else if (strcmp (obj->vtable->klass->name, "GenericTypeParameterBuilder") == 0) {
10632                 MonoReflectionType *tb = (MonoReflectionType*)obj;
10633                 MonoType *type = mono_class_inflate_generic_type (tb->type, context);
10634                 result = mono_class_from_mono_type (type);
10635                 *handle_class = mono_defaults.typehandle_class;
10636                 g_assert (result);
10637                 mono_metadata_free_type (type);
10638         } else if (strcmp (obj->vtable->klass->name, "MonoGenericClass") == 0) {
10639                 MonoReflectionGenericClass *ref = (MonoReflectionGenericClass*)obj;
10640                 MonoType *type = mono_class_inflate_generic_type (ref->type.type, context);
10641                 result = mono_class_from_mono_type (type);
10642                 *handle_class = mono_defaults.typehandle_class;
10643                 g_assert (result);
10644                 mono_metadata_free_type (type);
10645         } else if (strcmp (obj->vtable->klass->name, "FieldOnTypeBuilderInst") == 0) {
10646                 MonoReflectionFieldOnTypeBuilderInst *f = (MonoReflectionFieldOnTypeBuilderInst*)obj;
10647                 MonoClass *inflated;
10648                 MonoType *type;
10649
10650                 type = mono_class_inflate_generic_type (f->inst->type.type, context);
10651                 inflated = mono_class_from_mono_type (type);
10652
10653                 g_assert (f->fb->handle);
10654                 result = mono_class_get_field_from_name (inflated, mono_field_get_name (f->fb->handle));
10655                 g_assert (result);
10656                 mono_metadata_free_type (type);
10657                 *handle_class = mono_defaults.fieldhandle_class;
10658         } else if (strcmp (obj->vtable->klass->name, "ConstructorOnTypeBuilderInst") == 0) {
10659                 MonoReflectionCtorOnTypeBuilderInst *c = (MonoReflectionCtorOnTypeBuilderInst*)obj;
10660                 MonoType *type = mono_class_inflate_generic_type (c->inst->type.type, context);
10661                 MonoClass *inflated_klass = mono_class_from_mono_type (type);
10662                 g_assert (c->cb->mhandle);
10663                 result = inflate_mono_method (inflated_klass, c->cb->mhandle, (MonoObject*)c->cb);
10664                 *handle_class = mono_defaults.methodhandle_class;
10665                 mono_metadata_free_type (type);
10666         } else if (strcmp (obj->vtable->klass->name, "MethodOnTypeBuilderInst") == 0) {
10667                 MonoReflectionMethodOnTypeBuilderInst *m = (MonoReflectionMethodOnTypeBuilderInst*)obj;
10668                 MonoType *type = mono_class_inflate_generic_type (m->inst->type.type, context);
10669                 MonoClass *inflated_klass = mono_class_from_mono_type (type);
10670                 g_assert (m->mb->mhandle);
10671                 result = inflate_mono_method (inflated_klass, m->mb->mhandle, (MonoObject*)m->mb);
10672                 *handle_class = mono_defaults.methodhandle_class;
10673                 mono_metadata_free_type (type);
10674         } else {
10675                 g_print (obj->vtable->klass->name);
10676                 g_assert_not_reached ();
10677         }
10678         return result;
10679 }
10680
10681 #else /* DISABLE_REFLECTION_EMIT */
10682
10683 MonoArray*
10684 mono_reflection_get_custom_attrs_blob (MonoReflectionAssembly *assembly, MonoObject *ctor, MonoArray *ctorArgs, MonoArray *properties, MonoArray *propValues, MonoArray *fields, MonoArray* fieldValues) 
10685 {
10686         g_assert_not_reached ();
10687         return NULL;
10688 }
10689
10690 void
10691 mono_reflection_setup_internal_class (MonoReflectionTypeBuilder *tb)
10692 {
10693         g_assert_not_reached ();
10694 }
10695
10696 void
10697 mono_reflection_setup_generic_class (MonoReflectionTypeBuilder *tb)
10698 {
10699         g_assert_not_reached ();
10700 }
10701
10702 void
10703 mono_reflection_create_generic_class (MonoReflectionTypeBuilder *tb)
10704 {
10705         g_assert_not_reached ();
10706 }
10707
10708 void
10709 mono_reflection_create_internal_class (MonoReflectionTypeBuilder *tb)
10710 {
10711         g_assert_not_reached ();
10712 }
10713
10714 void
10715 mono_image_basic_init (MonoReflectionAssemblyBuilder *assemblyb)
10716 {
10717         g_error ("This mono runtime was configured with --enable-minimal=reflection_emit, so System.Reflection.Emit is not supported.");
10718 }
10719
10720 void
10721 mono_image_module_basic_init (MonoReflectionModuleBuilder *moduleb)
10722 {
10723         g_assert_not_reached ();
10724 }
10725
10726 MonoReflectionModule *
10727 mono_image_load_module_dynamic (MonoReflectionAssemblyBuilder *ab, MonoString *fileName)
10728 {
10729         g_assert_not_reached ();
10730         return NULL;
10731 }
10732
10733 guint32
10734 mono_image_insert_string (MonoReflectionModuleBuilder *module, MonoString *str)
10735 {
10736         g_assert_not_reached ();
10737         return 0;
10738 }
10739
10740 guint32
10741 mono_image_create_method_token (MonoDynamicImage *assembly, MonoObject *obj, MonoArray *opt_param_types)
10742 {
10743         g_assert_not_reached ();
10744         return 0;
10745 }
10746
10747 guint32
10748 mono_image_create_token (MonoDynamicImage *assembly, MonoObject *obj, 
10749                                                  gboolean create_methodspec, gboolean register_token)
10750 {
10751         g_assert_not_reached ();
10752         return 0;
10753 }
10754
10755 void
10756 mono_image_register_token (MonoDynamicImage *assembly, guint32 token, MonoObject *obj)
10757 {
10758 }
10759
10760 void
10761 mono_reflection_generic_class_initialize (MonoReflectionGenericClass *type, MonoArray *methods, 
10762                                           MonoArray *ctors, MonoArray *fields, MonoArray *properties,
10763                                           MonoArray *events)
10764 {
10765         g_assert_not_reached ();
10766 }
10767
10768 void
10769 mono_reflection_get_dynamic_overrides (MonoClass *klass, MonoMethod ***overrides, int *num_overrides)
10770 {
10771         *overrides = NULL;
10772         *num_overrides = 0;
10773 }
10774
10775 MonoReflectionEvent *
10776 mono_reflection_event_builder_get_event_info (MonoReflectionTypeBuilder *tb, MonoReflectionEventBuilder *eb)
10777 {
10778         g_assert_not_reached ();
10779         return NULL;
10780 }
10781
10782 MonoReflectionType*
10783 mono_reflection_create_runtime_class (MonoReflectionTypeBuilder *tb)
10784 {
10785         g_assert_not_reached ();
10786         return NULL;
10787 }
10788
10789 void
10790 mono_reflection_initialize_generic_parameter (MonoReflectionGenericParam *gparam)
10791 {
10792         g_assert_not_reached ();
10793 }
10794
10795 MonoArray *
10796 mono_reflection_sighelper_get_signature_local (MonoReflectionSigHelper *sig)
10797 {
10798         g_assert_not_reached ();
10799         return NULL;
10800 }
10801
10802 MonoArray *
10803 mono_reflection_sighelper_get_signature_field (MonoReflectionSigHelper *sig)
10804 {
10805         g_assert_not_reached ();
10806         return NULL;
10807 }
10808
10809 void 
10810 mono_reflection_create_dynamic_method (MonoReflectionDynamicMethod *mb)
10811 {
10812 }
10813
10814 gpointer
10815 mono_reflection_lookup_dynamic_token (MonoImage *image, guint32 token, gboolean valid_token, MonoClass **handle_class, MonoGenericContext *context)
10816 {
10817         return NULL;
10818 }
10819
10820 #endif /* DISABLE_REFLECTION_EMIT */
10821
10822 /* SECURITY_ACTION_* are defined in mono/metadata/tabledefs.h */
10823 const static guint32 declsec_flags_map[] = {
10824         0x00000000,                                     /* empty */
10825         MONO_DECLSEC_FLAG_REQUEST,                      /* SECURITY_ACTION_REQUEST                      (x01) */
10826         MONO_DECLSEC_FLAG_DEMAND,                       /* SECURITY_ACTION_DEMAND                       (x02) */
10827         MONO_DECLSEC_FLAG_ASSERT,                       /* SECURITY_ACTION_ASSERT                       (x03) */
10828         MONO_DECLSEC_FLAG_DENY,                         /* SECURITY_ACTION_DENY                         (x04) */
10829         MONO_DECLSEC_FLAG_PERMITONLY,                   /* SECURITY_ACTION_PERMITONLY                   (x05) */
10830         MONO_DECLSEC_FLAG_LINKDEMAND,                   /* SECURITY_ACTION_LINKDEMAND                   (x06) */
10831         MONO_DECLSEC_FLAG_INHERITANCEDEMAND,            /* SECURITY_ACTION_INHERITANCEDEMAND            (x07) */
10832         MONO_DECLSEC_FLAG_REQUEST_MINIMUM,              /* SECURITY_ACTION_REQUEST_MINIMUM              (x08) */
10833         MONO_DECLSEC_FLAG_REQUEST_OPTIONAL,             /* SECURITY_ACTION_REQUEST_OPTIONAL             (x09) */
10834         MONO_DECLSEC_FLAG_REQUEST_REFUSE,               /* SECURITY_ACTION_REQUEST_REFUSE               (x0A) */
10835         MONO_DECLSEC_FLAG_PREJIT_GRANT,                 /* SECURITY_ACTION_PREJIT_GRANT                 (x0B) */
10836         MONO_DECLSEC_FLAG_PREJIT_DENY,                  /* SECURITY_ACTION_PREJIT_DENY                  (x0C) */
10837         MONO_DECLSEC_FLAG_NONCAS_DEMAND,                /* SECURITY_ACTION_NONCAS_DEMAND                (x0D) */
10838         MONO_DECLSEC_FLAG_NONCAS_LINKDEMAND,            /* SECURITY_ACTION_NONCAS_LINKDEMAND            (x0E) */
10839         MONO_DECLSEC_FLAG_NONCAS_INHERITANCEDEMAND,     /* SECURITY_ACTION_NONCAS_INHERITANCEDEMAND     (x0F) */
10840         MONO_DECLSEC_FLAG_LINKDEMAND_CHOICE,            /* SECURITY_ACTION_LINKDEMAND_CHOICE            (x10) */
10841         MONO_DECLSEC_FLAG_INHERITANCEDEMAND_CHOICE,     /* SECURITY_ACTION_INHERITANCEDEMAND_CHOICE     (x11) */
10842         MONO_DECLSEC_FLAG_DEMAND_CHOICE,                /* SECURITY_ACTION_DEMAND_CHOICE                (x12) */
10843 };
10844
10845 /*
10846  * Returns flags that includes all available security action associated to the handle.
10847  * @token: metadata token (either for a class or a method)
10848  * @image: image where resides the metadata.
10849  */
10850 static guint32
10851 mono_declsec_get_flags (MonoImage *image, guint32 token)
10852 {
10853         int index = mono_metadata_declsec_from_index (image, token);
10854         MonoTableInfo *t = &image->tables [MONO_TABLE_DECLSECURITY];
10855         guint32 result = 0;
10856         guint32 action;
10857         int i;
10858
10859         /* HasSecurity can be present for other, not specially encoded, attributes,
10860            e.g. SuppressUnmanagedCodeSecurityAttribute */
10861         if (index < 0)
10862                 return 0;
10863
10864         for (i = index; i < t->rows; i++) {
10865                 guint32 cols [MONO_DECL_SECURITY_SIZE];
10866
10867                 mono_metadata_decode_row (t, i, cols, MONO_DECL_SECURITY_SIZE);
10868                 if (cols [MONO_DECL_SECURITY_PARENT] != token)
10869                         break;
10870
10871                 action = cols [MONO_DECL_SECURITY_ACTION];
10872                 if ((action >= MONO_DECLSEC_ACTION_MIN) && (action <= MONO_DECLSEC_ACTION_MAX)) {
10873                         result |= declsec_flags_map [action];
10874                 } else {
10875                         g_assert_not_reached ();
10876                 }
10877         }
10878         return result;
10879 }
10880
10881 /*
10882  * Get the security actions (in the form of flags) associated with the specified method.
10883  *
10884  * @method: The method for which we want the declarative security flags.
10885  * Return the declarative security flags for the method (only).
10886  *
10887  * Note: To keep MonoMethod size down we do not cache the declarative security flags
10888  *       (except for the stack modifiers which are kept in the MonoJitInfo structure)
10889  */
10890 guint32
10891 mono_declsec_flags_from_method (MonoMethod *method)
10892 {
10893         if (method->flags & METHOD_ATTRIBUTE_HAS_SECURITY) {
10894                 /* FIXME: No cache (for the moment) */
10895                 guint32 idx = mono_method_get_index (method);
10896                 idx <<= MONO_HAS_DECL_SECURITY_BITS;
10897                 idx |= MONO_HAS_DECL_SECURITY_METHODDEF;
10898                 return mono_declsec_get_flags (method->klass->image, idx);
10899         }
10900         return 0;
10901 }
10902
10903 /*
10904  * Get the security actions (in the form of flags) associated with the specified class.
10905  *
10906  * @klass: The class for which we want the declarative security flags.
10907  * Return the declarative security flags for the class.
10908  *
10909  * Note: We cache the flags inside the MonoClass structure as this will get 
10910  *       called very often (at least for each method).
10911  */
10912 guint32
10913 mono_declsec_flags_from_class (MonoClass *klass)
10914 {
10915         if (klass->flags & TYPE_ATTRIBUTE_HAS_SECURITY) {
10916                 if (!klass->declsec_flags) {
10917                         guint32 idx = mono_metadata_token_index (klass->type_token);
10918                         idx <<= MONO_HAS_DECL_SECURITY_BITS;
10919                         idx |= MONO_HAS_DECL_SECURITY_TYPEDEF;
10920                         /* we cache the flags on classes */
10921                         klass->declsec_flags = mono_declsec_get_flags (klass->image, idx);
10922                 }
10923                 return klass->declsec_flags;
10924         }
10925         return 0;
10926 }
10927
10928 /*
10929  * Get the security actions (in the form of flags) associated with the specified assembly.
10930  *
10931  * @assembly: The assembly for which we want the declarative security flags.
10932  * Return the declarative security flags for the assembly.
10933  */
10934 guint32
10935 mono_declsec_flags_from_assembly (MonoAssembly *assembly)
10936 {
10937         guint32 idx = 1; /* there is only one assembly */
10938         idx <<= MONO_HAS_DECL_SECURITY_BITS;
10939         idx |= MONO_HAS_DECL_SECURITY_ASSEMBLY;
10940         return mono_declsec_get_flags (assembly->image, idx);
10941 }
10942
10943
10944 /*
10945  * Fill actions for the specific index (which may either be an encoded class token or
10946  * an encoded method token) from the metadata image.
10947  * Returns TRUE if some actions requiring code generation are present, FALSE otherwise.
10948  */
10949 static MonoBoolean
10950 fill_actions_from_index (MonoImage *image, guint32 token, MonoDeclSecurityActions* actions,
10951         guint32 id_std, guint32 id_noncas, guint32 id_choice)
10952 {
10953         MonoBoolean result = FALSE;
10954         MonoTableInfo *t;
10955         guint32 cols [MONO_DECL_SECURITY_SIZE];
10956         int index = mono_metadata_declsec_from_index (image, token);
10957         int i;
10958
10959         t  = &image->tables [MONO_TABLE_DECLSECURITY];
10960         for (i = index; i < t->rows; i++) {
10961                 mono_metadata_decode_row (t, i, cols, MONO_DECL_SECURITY_SIZE);
10962
10963                 if (cols [MONO_DECL_SECURITY_PARENT] != token)
10964                         return result;
10965
10966                 /* if present only replace (class) permissions with method permissions */
10967                 /* if empty accept either class or method permissions */
10968                 if (cols [MONO_DECL_SECURITY_ACTION] == id_std) {
10969                         if (!actions->demand.blob) {
10970                                 const char *blob = mono_metadata_blob_heap (image, cols [MONO_DECL_SECURITY_PERMISSIONSET]);
10971                                 actions->demand.index = cols [MONO_DECL_SECURITY_PERMISSIONSET];
10972                                 actions->demand.blob = (char*) (blob + 2);
10973                                 actions->demand.size = mono_metadata_decode_blob_size (blob, &blob);
10974                                 result = TRUE;
10975                         }
10976                 } else if (cols [MONO_DECL_SECURITY_ACTION] == id_noncas) {
10977                         if (!actions->noncasdemand.blob) {
10978                                 const char *blob = mono_metadata_blob_heap (image, cols [MONO_DECL_SECURITY_PERMISSIONSET]);
10979                                 actions->noncasdemand.index = cols [MONO_DECL_SECURITY_PERMISSIONSET];
10980                                 actions->noncasdemand.blob = (char*) (blob + 2);
10981                                 actions->noncasdemand.size = mono_metadata_decode_blob_size (blob, &blob);
10982                                 result = TRUE;
10983                         }
10984                 } else if (cols [MONO_DECL_SECURITY_ACTION] == id_choice) {
10985                         if (!actions->demandchoice.blob) {
10986                                 const char *blob = mono_metadata_blob_heap (image, cols [MONO_DECL_SECURITY_PERMISSIONSET]);
10987                                 actions->demandchoice.index = cols [MONO_DECL_SECURITY_PERMISSIONSET];
10988                                 actions->demandchoice.blob = (char*) (blob + 2);
10989                                 actions->demandchoice.size = mono_metadata_decode_blob_size (blob, &blob);
10990                                 result = TRUE;
10991                         }
10992                 }
10993         }
10994
10995         return result;
10996 }
10997
10998 static MonoBoolean
10999 mono_declsec_get_class_demands_params (MonoClass *klass, MonoDeclSecurityActions* demands, 
11000         guint32 id_std, guint32 id_noncas, guint32 id_choice)
11001 {
11002         guint32 idx = mono_metadata_token_index (klass->type_token);
11003         idx <<= MONO_HAS_DECL_SECURITY_BITS;
11004         idx |= MONO_HAS_DECL_SECURITY_TYPEDEF;
11005         return fill_actions_from_index (klass->image, idx, demands, id_std, id_noncas, id_choice);
11006 }
11007
11008 static MonoBoolean
11009 mono_declsec_get_method_demands_params (MonoMethod *method, MonoDeclSecurityActions* demands, 
11010         guint32 id_std, guint32 id_noncas, guint32 id_choice)
11011 {
11012         guint32 idx = mono_method_get_index (method);
11013         idx <<= MONO_HAS_DECL_SECURITY_BITS;
11014         idx |= MONO_HAS_DECL_SECURITY_METHODDEF;
11015         return fill_actions_from_index (method->klass->image, idx, demands, id_std, id_noncas, id_choice);
11016 }
11017
11018 /*
11019  * Collect all actions (that requires to generate code in mini) assigned for
11020  * the specified method.
11021  * Note: Don't use the content of actions if the function return FALSE.
11022  */
11023 MonoBoolean
11024 mono_declsec_get_demands (MonoMethod *method, MonoDeclSecurityActions* demands)
11025 {
11026         guint32 mask = MONO_DECLSEC_FLAG_DEMAND | MONO_DECLSEC_FLAG_NONCAS_DEMAND | 
11027                 MONO_DECLSEC_FLAG_DEMAND_CHOICE;
11028         MonoBoolean result = FALSE;
11029         guint32 flags;
11030
11031         /* quick exit if no declarative security is present in the metadata */
11032         if (!method->klass->image->tables [MONO_TABLE_DECLSECURITY].rows)
11033                 return FALSE;
11034
11035         /* we want the original as the wrapper is "free" of the security informations */
11036         if (method->wrapper_type == MONO_WRAPPER_MANAGED_TO_NATIVE || method->wrapper_type == MONO_WRAPPER_MANAGED_TO_MANAGED) {
11037                 method = mono_marshal_method_from_wrapper (method);
11038                 if (!method)
11039                         return FALSE;
11040         }
11041
11042         /* First we look for method-level attributes */
11043         if (method->flags & METHOD_ATTRIBUTE_HAS_SECURITY) {
11044                 mono_class_init (method->klass);
11045                 memset (demands, 0, sizeof (MonoDeclSecurityActions));
11046
11047                 result = mono_declsec_get_method_demands_params (method, demands, 
11048                         SECURITY_ACTION_DEMAND, SECURITY_ACTION_NONCASDEMAND, SECURITY_ACTION_DEMANDCHOICE);
11049         }
11050
11051         /* Here we use (or create) the class declarative cache to look for demands */
11052         flags = mono_declsec_flags_from_class (method->klass);
11053         if (flags & mask) {
11054                 if (!result) {
11055                         mono_class_init (method->klass);
11056                         memset (demands, 0, sizeof (MonoDeclSecurityActions));
11057                 }
11058                 result |= mono_declsec_get_class_demands_params (method->klass, demands, 
11059                         SECURITY_ACTION_DEMAND, SECURITY_ACTION_NONCASDEMAND, SECURITY_ACTION_DEMANDCHOICE);
11060         }
11061
11062         /* The boolean return value is used as a shortcut in case nothing needs to
11063            be generated (e.g. LinkDemand[Choice] and InheritanceDemand[Choice]) */
11064         return result;
11065 }
11066
11067
11068 /*
11069  * Collect all Link actions: LinkDemand, NonCasLinkDemand and LinkDemandChoice (2.0).
11070  *
11071  * Note: Don't use the content of actions if the function return FALSE.
11072  */
11073 MonoBoolean
11074 mono_declsec_get_linkdemands (MonoMethod *method, MonoDeclSecurityActions* klass, MonoDeclSecurityActions *cmethod)
11075 {
11076         MonoBoolean result = FALSE;
11077         guint32 flags;
11078
11079         /* quick exit if no declarative security is present in the metadata */
11080         if (!method->klass->image->tables [MONO_TABLE_DECLSECURITY].rows)
11081                 return FALSE;
11082
11083         /* we want the original as the wrapper is "free" of the security informations */
11084         if (method->wrapper_type == MONO_WRAPPER_MANAGED_TO_NATIVE || method->wrapper_type == MONO_WRAPPER_MANAGED_TO_MANAGED) {
11085                 method = mono_marshal_method_from_wrapper (method);
11086                 if (!method)
11087                         return FALSE;
11088         }
11089
11090         /* results are independant - zeroize both */
11091         memset (cmethod, 0, sizeof (MonoDeclSecurityActions));
11092         memset (klass, 0, sizeof (MonoDeclSecurityActions));
11093
11094         /* First we look for method-level attributes */
11095         if (method->flags & METHOD_ATTRIBUTE_HAS_SECURITY) {
11096                 mono_class_init (method->klass);
11097
11098                 result = mono_declsec_get_method_demands_params (method, cmethod, 
11099                         SECURITY_ACTION_LINKDEMAND, SECURITY_ACTION_NONCASLINKDEMAND, SECURITY_ACTION_LINKDEMANDCHOICE);
11100         }
11101
11102         /* Here we use (or create) the class declarative cache to look for demands */
11103         flags = mono_declsec_flags_from_class (method->klass);
11104         if (flags & (MONO_DECLSEC_FLAG_LINKDEMAND | MONO_DECLSEC_FLAG_NONCAS_LINKDEMAND | MONO_DECLSEC_FLAG_LINKDEMAND_CHOICE)) {
11105                 mono_class_init (method->klass);
11106
11107                 result |= mono_declsec_get_class_demands_params (method->klass, klass, 
11108                         SECURITY_ACTION_LINKDEMAND, SECURITY_ACTION_NONCASLINKDEMAND, SECURITY_ACTION_LINKDEMANDCHOICE);
11109         }
11110
11111         return result;
11112 }
11113
11114 /*
11115  * Collect all Inherit actions: InheritanceDemand, NonCasInheritanceDemand and InheritanceDemandChoice (2.0).
11116  *
11117  * @klass       The inherited class - this is the class that provides the security check (attributes)
11118  * @demans      
11119  * return TRUE if inheritance demands (any kind) are present, FALSE otherwise.
11120  * 
11121  * Note: Don't use the content of actions if the function return FALSE.
11122  */
11123 MonoBoolean
11124 mono_declsec_get_inheritdemands_class (MonoClass *klass, MonoDeclSecurityActions* demands)
11125 {
11126         MonoBoolean result = FALSE;
11127         guint32 flags;
11128
11129         /* quick exit if no declarative security is present in the metadata */
11130         if (!klass->image->tables [MONO_TABLE_DECLSECURITY].rows)
11131                 return FALSE;
11132
11133         /* Here we use (or create) the class declarative cache to look for demands */
11134         flags = mono_declsec_flags_from_class (klass);
11135         if (flags & (MONO_DECLSEC_FLAG_INHERITANCEDEMAND | MONO_DECLSEC_FLAG_NONCAS_INHERITANCEDEMAND | MONO_DECLSEC_FLAG_INHERITANCEDEMAND_CHOICE)) {
11136                 mono_class_init (klass);
11137                 memset (demands, 0, sizeof (MonoDeclSecurityActions));
11138
11139                 result |= mono_declsec_get_class_demands_params (klass, demands, 
11140                         SECURITY_ACTION_INHERITDEMAND, SECURITY_ACTION_NONCASINHERITANCE, SECURITY_ACTION_INHERITDEMANDCHOICE);
11141         }
11142
11143         return result;
11144 }
11145
11146 /*
11147  * Collect all Inherit actions: InheritanceDemand, NonCasInheritanceDemand and InheritanceDemandChoice (2.0).
11148  *
11149  * Note: Don't use the content of actions if the function return FALSE.
11150  */
11151 MonoBoolean
11152 mono_declsec_get_inheritdemands_method (MonoMethod *method, MonoDeclSecurityActions* demands)
11153 {
11154         /* quick exit if no declarative security is present in the metadata */
11155         if (!method->klass->image->tables [MONO_TABLE_DECLSECURITY].rows)
11156                 return FALSE;
11157
11158         /* we want the original as the wrapper is "free" of the security informations */
11159         if (method->wrapper_type == MONO_WRAPPER_MANAGED_TO_NATIVE || method->wrapper_type == MONO_WRAPPER_MANAGED_TO_MANAGED) {
11160                 method = mono_marshal_method_from_wrapper (method);
11161                 if (!method)
11162                         return FALSE;
11163         }
11164
11165         if (method->flags & METHOD_ATTRIBUTE_HAS_SECURITY) {
11166                 mono_class_init (method->klass);
11167                 memset (demands, 0, sizeof (MonoDeclSecurityActions));
11168
11169                 return mono_declsec_get_method_demands_params (method, demands, 
11170                         SECURITY_ACTION_INHERITDEMAND, SECURITY_ACTION_NONCASINHERITANCE, SECURITY_ACTION_INHERITDEMANDCHOICE);
11171         }
11172         return FALSE;
11173 }
11174
11175
11176 static MonoBoolean
11177 get_declsec_action (MonoImage *image, guint32 token, guint32 action, MonoDeclSecurityEntry *entry)
11178 {
11179         guint32 cols [MONO_DECL_SECURITY_SIZE];
11180         MonoTableInfo *t;
11181         int i;
11182
11183         int index = mono_metadata_declsec_from_index (image, token);
11184         if (index == -1)
11185                 return FALSE;
11186
11187         t =  &image->tables [MONO_TABLE_DECLSECURITY];
11188         for (i = index; i < t->rows; i++) {
11189                 mono_metadata_decode_row (t, i, cols, MONO_DECL_SECURITY_SIZE);
11190
11191                 /* shortcut - index are ordered */
11192                 if (token != cols [MONO_DECL_SECURITY_PARENT])
11193                         return FALSE;
11194
11195                 if (cols [MONO_DECL_SECURITY_ACTION] == action) {
11196                         const char *metadata = mono_metadata_blob_heap (image, cols [MONO_DECL_SECURITY_PERMISSIONSET]);
11197                         entry->blob = (char*) (metadata + 2);
11198                         entry->size = mono_metadata_decode_blob_size (metadata, &metadata);
11199                         return TRUE;
11200                 }
11201         }
11202
11203         return FALSE;
11204 }
11205
11206 MonoBoolean
11207 mono_declsec_get_method_action (MonoMethod *method, guint32 action, MonoDeclSecurityEntry *entry)
11208 {
11209         if (method->flags & METHOD_ATTRIBUTE_HAS_SECURITY) {
11210                 guint32 idx = mono_method_get_index (method);
11211                 idx <<= MONO_HAS_DECL_SECURITY_BITS;
11212                 idx |= MONO_HAS_DECL_SECURITY_METHODDEF;
11213                 return get_declsec_action (method->klass->image, idx, action, entry);
11214         }
11215         return FALSE;
11216 }
11217
11218 MonoBoolean
11219 mono_declsec_get_class_action (MonoClass *klass, guint32 action, MonoDeclSecurityEntry *entry)
11220 {
11221         /* use cache */
11222         guint32 flags = mono_declsec_flags_from_class (klass);
11223         if (declsec_flags_map [action] & flags) {
11224                 guint32 idx = mono_metadata_token_index (klass->type_token);
11225                 idx <<= MONO_HAS_DECL_SECURITY_BITS;
11226                 idx |= MONO_HAS_DECL_SECURITY_TYPEDEF;
11227                 return get_declsec_action (klass->image, idx, action, entry);
11228         }
11229         return FALSE;
11230 }
11231
11232 MonoBoolean
11233 mono_declsec_get_assembly_action (MonoAssembly *assembly, guint32 action, MonoDeclSecurityEntry *entry)
11234 {
11235         guint32 idx = 1; /* there is only one assembly */
11236         idx <<= MONO_HAS_DECL_SECURITY_BITS;
11237         idx |= MONO_HAS_DECL_SECURITY_ASSEMBLY;
11238
11239         return get_declsec_action (assembly->image, idx, action, entry);
11240 }
11241
11242 gboolean
11243 mono_reflection_call_is_assignable_to (MonoClass *klass, MonoClass *oklass)
11244 {
11245         MonoObject *res, *exc;
11246         void *params [1];
11247         static MonoClass *System_Reflection_Emit_TypeBuilder = NULL;
11248         static MonoMethod *method = NULL;
11249
11250         if (!System_Reflection_Emit_TypeBuilder) {
11251                 System_Reflection_Emit_TypeBuilder = mono_class_from_name (mono_defaults.corlib, "System.Reflection.Emit", "TypeBuilder");
11252                 g_assert (System_Reflection_Emit_TypeBuilder);
11253         }
11254         if (method == NULL) {
11255                 method = mono_class_get_method_from_name (System_Reflection_Emit_TypeBuilder, "IsAssignableTo", 1);
11256                 g_assert (method);
11257         }
11258
11259         /* 
11260          * The result of mono_type_get_object () might be a System.MonoType but we
11261          * need a TypeBuilder so use klass->reflection_info.
11262          */
11263         g_assert (klass->reflection_info);
11264         g_assert (!strcmp (((MonoObject*)(klass->reflection_info))->vtable->klass->name, "TypeBuilder"));
11265
11266         params [0] = mono_type_get_object (mono_domain_get (), &oklass->byval_arg);
11267
11268         res = mono_runtime_invoke (method, (MonoObject*)(klass->reflection_info), params, &exc);
11269         if (exc)
11270                 return FALSE;
11271         else
11272                 return *(MonoBoolean*)mono_object_unbox (res);
11273 }