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