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