2007-10-27 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         if (tb->generic_container)
2555                 mono_reflection_create_generic_class (tb);
2556
2557         sigbuffer_add_value (&buf, MONO_TYPE_GENERICINST);
2558         g_assert (klass->generic_container);
2559         sigbuffer_add_value (&buf, klass->byval_arg.type);
2560         sigbuffer_add_value (&buf, mono_image_typedef_or_ref_full (assembly, &klass->byval_arg, FALSE));
2561
2562         count = mono_array_length (tb->generic_params);
2563         sigbuffer_add_value (&buf, count);
2564         for (i = 0; i < count; i++) {
2565                 MonoReflectionGenericParam *gparam;
2566
2567                 gparam = mono_array_get (tb->generic_params, MonoReflectionGenericParam *, i);
2568
2569                 encode_type (assembly, gparam->type.type, &buf);
2570         }
2571
2572         table = &assembly->tables [MONO_TABLE_TYPESPEC];
2573
2574         if (assembly->save) {
2575                 token = sigbuffer_add_to_blob_cached (assembly, &buf);
2576                 alloc_table (table, table->rows + 1);
2577                 values = table->values + table->next_idx * MONO_TYPESPEC_SIZE;
2578                 values [MONO_TYPESPEC_SIGNATURE] = token;
2579         }
2580         sigbuffer_free (&buf);
2581
2582         token = MONO_TYPEDEFORREF_TYPESPEC | (table->next_idx << MONO_TYPEDEFORREF_BITS);
2583         g_hash_table_insert (assembly->typespec, tb->type.type, GUINT_TO_POINTER(token));
2584         table->next_idx ++;
2585         return token;
2586 }
2587
2588 static guint32
2589 mono_image_get_generic_field_token (MonoDynamicImage *assembly, MonoReflectionFieldBuilder *fb)
2590 {
2591         MonoDynamicTable *table;
2592         MonoClass *klass;
2593         guint32 *values;
2594         guint32 token, pclass, parent, sig;
2595         gchar *name;
2596
2597         token = GPOINTER_TO_UINT (g_hash_table_lookup (assembly->handleref, fb));
2598         if (token)
2599                 return token;
2600
2601         klass = mono_class_from_mono_type (fb->typeb->type);
2602         name = mono_string_to_utf8 (fb->name);
2603
2604         sig = fieldref_encode_signature (assembly, fb->type->type);
2605
2606         parent = create_generic_typespec (assembly, (MonoReflectionTypeBuilder *) fb->typeb);
2607         g_assert ((parent & MONO_TYPEDEFORREF_MASK) == MONO_TYPEDEFORREF_TYPESPEC);
2608         
2609         pclass = MONO_MEMBERREF_PARENT_TYPESPEC;
2610         parent >>= MONO_TYPEDEFORREF_BITS;
2611
2612         table = &assembly->tables [MONO_TABLE_MEMBERREF];
2613
2614         if (assembly->save) {
2615                 alloc_table (table, table->rows + 1);
2616                 values = table->values + table->next_idx * MONO_MEMBERREF_SIZE;
2617                 values [MONO_MEMBERREF_CLASS] = pclass | (parent << MONO_MEMBERREF_PARENT_BITS);
2618                 values [MONO_MEMBERREF_NAME] = string_heap_insert (&assembly->sheap, name);
2619                 values [MONO_MEMBERREF_SIGNATURE] = sig;
2620         }
2621
2622         token = MONO_TOKEN_MEMBER_REF | table->next_idx;
2623         table->next_idx ++;
2624         g_hash_table_insert (assembly->handleref, fb, GUINT_TO_POINTER(token));
2625         return token;
2626 }
2627
2628 static guint32
2629 mono_reflection_encode_sighelper (MonoDynamicImage *assembly, MonoReflectionSigHelper *helper)
2630 {
2631         SigBuffer buf;
2632         guint32 nargs;
2633         guint32 size;
2634         guint32 i, idx;
2635
2636         if (!assembly->save)
2637                 return 0;
2638
2639         /* FIXME: */
2640         g_assert (helper->type == 2);
2641
2642         if (helper->arguments)
2643                 nargs = mono_array_length (helper->arguments);
2644         else
2645                 nargs = 0;
2646
2647         size = 10 + (nargs * 10);
2648         
2649         sigbuffer_init (&buf, 32);
2650
2651         /* Encode calling convention */
2652         /* Change Any to Standard */
2653         if ((helper->call_conv & 0x03) == 0x03)
2654                 helper->call_conv = 0x01;
2655         /* explicit_this implies has_this */
2656         if (helper->call_conv & 0x40)
2657                 helper->call_conv &= 0x20;
2658
2659         if (helper->call_conv == 0) { /* Unmanaged */
2660                 idx = helper->unmanaged_call_conv - 1;
2661         } else {
2662                 /* Managed */
2663                 idx = helper->call_conv & 0x60; /* has_this + explicit_this */
2664                 if (helper->call_conv & 0x02) /* varargs */
2665                         idx += 0x05;
2666         }
2667
2668         sigbuffer_add_byte (&buf, idx);
2669         sigbuffer_add_value (&buf, nargs);
2670         encode_reflection_type (assembly, helper->return_type, &buf);
2671         for (i = 0; i < nargs; ++i) {
2672                 MonoReflectionType *pt = mono_array_get (helper->arguments, MonoReflectionType*, i);
2673                 encode_reflection_type (assembly, pt, &buf);
2674         }
2675         idx = sigbuffer_add_to_blob_cached (assembly, &buf);
2676         sigbuffer_free (&buf);
2677
2678         return idx;
2679 }
2680         
2681 static guint32 
2682 mono_image_get_sighelper_token (MonoDynamicImage *assembly, MonoReflectionSigHelper *helper)
2683 {
2684         guint32 idx;
2685         MonoDynamicTable *table;
2686         guint32 *values;
2687
2688         table = &assembly->tables [MONO_TABLE_STANDALONESIG];
2689         idx = table->next_idx ++;
2690         table->rows ++;
2691         alloc_table (table, table->rows);
2692         values = table->values + idx * MONO_STAND_ALONE_SIGNATURE_SIZE;
2693
2694         values [MONO_STAND_ALONE_SIGNATURE] =
2695                 mono_reflection_encode_sighelper (assembly, helper);
2696
2697         return idx;
2698 }
2699
2700 static int
2701 reflection_cc_to_file (int call_conv) {
2702         switch (call_conv & 0x3) {
2703         case 0:
2704         case 1: return MONO_CALL_DEFAULT;
2705         case 2: return MONO_CALL_VARARG;
2706         default:
2707                 g_assert_not_reached ();
2708         }
2709         return 0;
2710 }
2711
2712 typedef struct {
2713         MonoType *parent;
2714         MonoMethodSignature *sig;
2715         char *name;
2716         guint32 token;
2717 } ArrayMethod;
2718
2719 static guint32
2720 mono_image_get_array_token (MonoDynamicImage *assembly, MonoReflectionArrayMethod *m)
2721 {
2722         guint32 nparams, i;
2723         GList *tmp;
2724         char *name;
2725         MonoMethodSignature *sig;
2726         ArrayMethod *am;
2727         
2728         name = mono_string_to_utf8 (m->name);
2729         nparams = mono_array_length (m->parameters);
2730         sig = g_malloc0 (sizeof (MonoMethodSignature) + sizeof (MonoType*) * nparams);
2731         sig->hasthis = 1;
2732         sig->sentinelpos = -1;
2733         sig->call_convention = reflection_cc_to_file (m->call_conv);
2734         sig->param_count = nparams;
2735         sig->ret = m->ret? m->ret->type: &mono_defaults.void_class->byval_arg;
2736         for (i = 0; i < nparams; ++i) {
2737                 MonoReflectionType *t = mono_array_get (m->parameters, gpointer, i);
2738                 sig->params [i] = t->type;
2739         }
2740
2741         for (tmp = assembly->array_methods; tmp; tmp = tmp->next) {
2742                 am = tmp->data;
2743                 if (strcmp (name, am->name) == 0 && 
2744                                 mono_metadata_type_equal (am->parent, m->parent->type) &&
2745                                 mono_metadata_signature_equal (am->sig, sig)) {
2746                         g_free (name);
2747                         g_free (sig);
2748                         m->table_idx = am->token & 0xffffff;
2749                         return am->token;
2750                 }
2751         }
2752         am = g_new0 (ArrayMethod, 1);
2753         am->name = name;
2754         am->sig = sig;
2755         am->parent = m->parent->type;
2756         am->token = mono_image_get_memberref_token (assembly, am->parent, name,
2757                 method_encode_signature (assembly, sig));
2758         assembly->array_methods = g_list_prepend (assembly->array_methods, am);
2759         m->table_idx = am->token & 0xffffff;
2760         return am->token;
2761 }
2762
2763 /*
2764  * Insert into the metadata tables all the info about the TypeBuilder tb.
2765  * Data in the tables is inserted in a predefined order, since some tables need to be sorted.
2766  */
2767 static void
2768 mono_image_get_type_info (MonoDomain *domain, MonoReflectionTypeBuilder *tb, MonoDynamicImage *assembly)
2769 {
2770         MonoDynamicTable *table;
2771         guint *values;
2772         int i, is_object = 0, is_system = 0;
2773         char *n;
2774
2775         table = &assembly->tables [MONO_TABLE_TYPEDEF];
2776         values = table->values + tb->table_idx * MONO_TYPEDEF_SIZE;
2777         values [MONO_TYPEDEF_FLAGS] = tb->attrs;
2778         n = mono_string_to_utf8 (tb->name);
2779         if (strcmp (n, "Object") == 0)
2780                 is_object++;
2781         values [MONO_TYPEDEF_NAME] = string_heap_insert (&assembly->sheap, n);
2782         g_free (n);
2783         n = mono_string_to_utf8 (tb->nspace);
2784         if (strcmp (n, "System") == 0)
2785                 is_system++;
2786         values [MONO_TYPEDEF_NAMESPACE] = string_heap_insert (&assembly->sheap, n);
2787         g_free (n);
2788         if (tb->parent && !(is_system && is_object) && 
2789                         !(tb->attrs & TYPE_ATTRIBUTE_INTERFACE)) { /* interfaces don't have a parent */
2790                 values [MONO_TYPEDEF_EXTENDS] = mono_image_typedef_or_ref (assembly, tb->parent->type);
2791         } else {
2792                 values [MONO_TYPEDEF_EXTENDS] = 0;
2793         }
2794         values [MONO_TYPEDEF_FIELD_LIST] = assembly->tables [MONO_TABLE_FIELD].next_idx;
2795         values [MONO_TYPEDEF_METHOD_LIST] = assembly->tables [MONO_TABLE_METHOD].next_idx;
2796
2797         /*
2798          * if we have explicitlayout or sequentiallayouts, output data in the
2799          * ClassLayout table.
2800          */
2801         if (((tb->attrs & TYPE_ATTRIBUTE_LAYOUT_MASK) != TYPE_ATTRIBUTE_AUTO_LAYOUT) &&
2802                         ((tb->class_size > 0) || (tb->packing_size > 0))) {
2803                 table = &assembly->tables [MONO_TABLE_CLASSLAYOUT];
2804                 table->rows++;
2805                 alloc_table (table, table->rows);
2806                 values = table->values + table->rows * MONO_CLASS_LAYOUT_SIZE;
2807                 values [MONO_CLASS_LAYOUT_PARENT] = tb->table_idx;
2808                 values [MONO_CLASS_LAYOUT_CLASS_SIZE] = tb->class_size;
2809                 values [MONO_CLASS_LAYOUT_PACKING_SIZE] = tb->packing_size;
2810         }
2811
2812         /* handle interfaces */
2813         if (tb->interfaces) {
2814                 table = &assembly->tables [MONO_TABLE_INTERFACEIMPL];
2815                 i = table->rows;
2816                 table->rows += mono_array_length (tb->interfaces);
2817                 alloc_table (table, table->rows);
2818                 values = table->values + (i + 1) * MONO_INTERFACEIMPL_SIZE;
2819                 for (i = 0; i < mono_array_length (tb->interfaces); ++i) {
2820                         MonoReflectionType* iface = (MonoReflectionType*) mono_array_get (tb->interfaces, gpointer, i);
2821                         values [MONO_INTERFACEIMPL_CLASS] = tb->table_idx;
2822                         values [MONO_INTERFACEIMPL_INTERFACE] = mono_image_typedef_or_ref (assembly, iface->type);
2823                         values += MONO_INTERFACEIMPL_SIZE;
2824                 }
2825         }
2826
2827         /* handle fields */
2828         if (tb->fields) {
2829                 table = &assembly->tables [MONO_TABLE_FIELD];
2830                 table->rows += tb->num_fields;
2831                 alloc_table (table, table->rows);
2832                 for (i = 0; i < tb->num_fields; ++i)
2833                         mono_image_get_field_info (
2834                                 mono_array_get (tb->fields, MonoReflectionFieldBuilder*, i), assembly);
2835         }
2836
2837         /* handle constructors */
2838         if (tb->ctors) {
2839                 table = &assembly->tables [MONO_TABLE_METHOD];
2840                 table->rows += mono_array_length (tb->ctors);
2841                 alloc_table (table, table->rows);
2842                 for (i = 0; i < mono_array_length (tb->ctors); ++i)
2843                         mono_image_get_ctor_info (domain,
2844                                 mono_array_get (tb->ctors, MonoReflectionCtorBuilder*, i), assembly);
2845         }
2846
2847         /* handle methods */
2848         if (tb->methods) {
2849                 table = &assembly->tables [MONO_TABLE_METHOD];
2850                 table->rows += tb->num_methods;
2851                 alloc_table (table, table->rows);
2852                 for (i = 0; i < tb->num_methods; ++i)
2853                         mono_image_get_method_info (
2854                                 mono_array_get (tb->methods, MonoReflectionMethodBuilder*, i), assembly);
2855         }
2856
2857         /* Do the same with properties etc.. */
2858         if (tb->events && mono_array_length (tb->events)) {
2859                 table = &assembly->tables [MONO_TABLE_EVENT];
2860                 table->rows += mono_array_length (tb->events);
2861                 alloc_table (table, table->rows);
2862                 table = &assembly->tables [MONO_TABLE_EVENTMAP];
2863                 table->rows ++;
2864                 alloc_table (table, table->rows);
2865                 values = table->values + table->rows * MONO_EVENT_MAP_SIZE;
2866                 values [MONO_EVENT_MAP_PARENT] = tb->table_idx;
2867                 values [MONO_EVENT_MAP_EVENTLIST] = assembly->tables [MONO_TABLE_EVENT].next_idx;
2868                 for (i = 0; i < mono_array_length (tb->events); ++i)
2869                         mono_image_get_event_info (
2870                                 mono_array_get (tb->events, MonoReflectionEventBuilder*, i), assembly);
2871         }
2872         if (tb->properties && mono_array_length (tb->properties)) {
2873                 table = &assembly->tables [MONO_TABLE_PROPERTY];
2874                 table->rows += mono_array_length (tb->properties);
2875                 alloc_table (table, table->rows);
2876                 table = &assembly->tables [MONO_TABLE_PROPERTYMAP];
2877                 table->rows ++;
2878                 alloc_table (table, table->rows);
2879                 values = table->values + table->rows * MONO_PROPERTY_MAP_SIZE;
2880                 values [MONO_PROPERTY_MAP_PARENT] = tb->table_idx;
2881                 values [MONO_PROPERTY_MAP_PROPERTY_LIST] = assembly->tables [MONO_TABLE_PROPERTY].next_idx;
2882                 for (i = 0; i < mono_array_length (tb->properties); ++i)
2883                         mono_image_get_property_info (
2884                                 mono_array_get (tb->properties, MonoReflectionPropertyBuilder*, i), assembly);
2885         }
2886
2887         /* handle generic parameters */
2888         if (tb->generic_params) {
2889                 table = &assembly->tables [MONO_TABLE_GENERICPARAM];
2890                 table->rows += mono_array_length (tb->generic_params);
2891                 alloc_table (table, table->rows);
2892                 for (i = 0; i < mono_array_length (tb->generic_params); ++i) {
2893                         guint32 owner = MONO_TYPEORMETHOD_TYPE | (tb->table_idx << MONO_TYPEORMETHOD_BITS);
2894
2895                         mono_image_get_generic_param_info (
2896                                 mono_array_get (tb->generic_params, MonoReflectionGenericParam*, i), owner, assembly);
2897                 }
2898         }
2899
2900         mono_image_add_decl_security (assembly, 
2901                 mono_metadata_make_token (MONO_TABLE_TYPEDEF, tb->table_idx), tb->permissions);
2902
2903         if (tb->subtypes) {
2904                 MonoDynamicTable *ntable;
2905                 
2906                 ntable = &assembly->tables [MONO_TABLE_NESTEDCLASS];
2907                 ntable->rows += mono_array_length (tb->subtypes);
2908                 alloc_table (ntable, ntable->rows);
2909                 values = ntable->values + ntable->next_idx * MONO_NESTED_CLASS_SIZE;
2910
2911                 for (i = 0; i < mono_array_length (tb->subtypes); ++i) {
2912                         MonoReflectionTypeBuilder *subtype = mono_array_get (tb->subtypes, MonoReflectionTypeBuilder*, i);
2913
2914                         values [MONO_NESTED_CLASS_NESTED] = subtype->table_idx;
2915                         values [MONO_NESTED_CLASS_ENCLOSING] = tb->table_idx;
2916                         /*g_print ("nesting %s (%d) in %s (%d) (rows %d/%d)\n",
2917                                 mono_string_to_utf8 (subtype->name), subtype->table_idx,
2918                                 mono_string_to_utf8 (tb->name), tb->table_idx,
2919                                 ntable->next_idx, ntable->rows);*/
2920                         values += MONO_NESTED_CLASS_SIZE;
2921                         ntable->next_idx++;
2922                 }
2923         }
2924 }
2925
2926 static void
2927 collect_types (GPtrArray *types, MonoReflectionTypeBuilder *type)
2928 {
2929         int i;
2930
2931         g_ptr_array_add (types, type); /* FIXME: GC object added to unmanaged memory */
2932
2933         if (!type->subtypes)
2934                 return;
2935
2936         for (i = 0; i < mono_array_length (type->subtypes); ++i) {
2937                 MonoReflectionTypeBuilder *subtype = mono_array_get (type->subtypes, MonoReflectionTypeBuilder*, i);
2938                 collect_types (types, subtype);
2939         }
2940 }
2941
2942 static gint
2943 compare_types_by_table_idx (MonoReflectionTypeBuilder **type1, MonoReflectionTypeBuilder **type2)
2944 {
2945         if ((*type1)->table_idx < (*type2)->table_idx)
2946                 return -1;
2947         else
2948                 if ((*type1)->table_idx > (*type2)->table_idx)
2949                         return 1;
2950         else
2951                 return 0;
2952 }
2953
2954 static void
2955 params_add_cattrs (MonoDynamicImage *assembly, MonoArray *pinfo) {
2956         int i;
2957
2958         if (!pinfo)
2959                 return;
2960         for (i = 0; i < mono_array_length (pinfo); ++i) {
2961                 MonoReflectionParamBuilder *pb;
2962                 pb = mono_array_get (pinfo, MonoReflectionParamBuilder *, i);
2963                 if (!pb)
2964                         continue;
2965                 mono_image_add_cattrs (assembly, pb->table_idx, MONO_CUSTOM_ATTR_PARAMDEF, pb->cattrs);
2966         }
2967 }
2968
2969 static void
2970 type_add_cattrs (MonoDynamicImage *assembly, MonoReflectionTypeBuilder *tb) {
2971         int i;
2972         
2973         mono_image_add_cattrs (assembly, tb->table_idx, MONO_CUSTOM_ATTR_TYPEDEF, tb->cattrs);
2974         if (tb->fields) {
2975                 for (i = 0; i < tb->num_fields; ++i) {
2976                         MonoReflectionFieldBuilder* fb;
2977                         fb = mono_array_get (tb->fields, MonoReflectionFieldBuilder*, i);
2978                         mono_image_add_cattrs (assembly, fb->table_idx, MONO_CUSTOM_ATTR_FIELDDEF, fb->cattrs);
2979                 }
2980         }
2981         if (tb->events) {
2982                 for (i = 0; i < mono_array_length (tb->events); ++i) {
2983                         MonoReflectionEventBuilder* eb;
2984                         eb = mono_array_get (tb->events, MonoReflectionEventBuilder*, i);
2985                         mono_image_add_cattrs (assembly, eb->table_idx, MONO_CUSTOM_ATTR_EVENT, eb->cattrs);
2986                 }
2987         }
2988         if (tb->properties) {
2989                 for (i = 0; i < mono_array_length (tb->properties); ++i) {
2990                         MonoReflectionPropertyBuilder* pb;
2991                         pb = mono_array_get (tb->properties, MonoReflectionPropertyBuilder*, i);
2992                         mono_image_add_cattrs (assembly, pb->table_idx, MONO_CUSTOM_ATTR_PROPERTY, pb->cattrs);
2993                 }
2994         }
2995         if (tb->ctors) {
2996                 for (i = 0; i < mono_array_length (tb->ctors); ++i) {
2997                         MonoReflectionCtorBuilder* cb;
2998                         cb = mono_array_get (tb->ctors, MonoReflectionCtorBuilder*, i);
2999                         mono_image_add_cattrs (assembly, cb->table_idx, MONO_CUSTOM_ATTR_METHODDEF, cb->cattrs);
3000                         params_add_cattrs (assembly, cb->pinfo);
3001                 }
3002         }
3003
3004         if (tb->methods) {
3005                 for (i = 0; i < tb->num_methods; ++i) {
3006                         MonoReflectionMethodBuilder* mb;
3007                         mb = mono_array_get (tb->methods, MonoReflectionMethodBuilder*, i);
3008                         mono_image_add_cattrs (assembly, mb->table_idx, MONO_CUSTOM_ATTR_METHODDEF, mb->cattrs);
3009                         params_add_cattrs (assembly, mb->pinfo);
3010                 }
3011         }
3012
3013         if (tb->subtypes) {
3014                 for (i = 0; i < mono_array_length (tb->subtypes); ++i)
3015                         type_add_cattrs (assembly, mono_array_get (tb->subtypes, MonoReflectionTypeBuilder*, i));
3016         }
3017 }
3018
3019 static void
3020 module_add_cattrs (MonoDynamicImage *assembly, MonoReflectionModuleBuilder *moduleb)
3021 {
3022         int i;
3023         
3024         mono_image_add_cattrs (assembly, moduleb->table_idx, MONO_CUSTOM_ATTR_MODULE, moduleb->cattrs);
3025
3026         if (moduleb->global_methods) {
3027                 for (i = 0; i < mono_array_length (moduleb->global_methods); ++i) {
3028                         MonoReflectionMethodBuilder* mb = mono_array_get (moduleb->global_methods, MonoReflectionMethodBuilder*, i);
3029                         mono_image_add_cattrs (assembly, mb->table_idx, MONO_CUSTOM_ATTR_METHODDEF, mb->cattrs);
3030                         params_add_cattrs (assembly, mb->pinfo);
3031                 }
3032         }
3033
3034         if (moduleb->global_fields) {
3035                 for (i = 0; i < mono_array_length (moduleb->global_fields); ++i) {
3036                         MonoReflectionFieldBuilder *fb = mono_array_get (moduleb->global_fields, MonoReflectionFieldBuilder*, i);
3037                         mono_image_add_cattrs (assembly, fb->table_idx, MONO_CUSTOM_ATTR_FIELDDEF, fb->cattrs);
3038                 }
3039         }
3040         
3041         if (moduleb->types) {
3042                 for (i = 0; i < moduleb->num_types; ++i)
3043                         type_add_cattrs (assembly, mono_array_get (moduleb->types, MonoReflectionTypeBuilder*, i));
3044         }
3045 }
3046
3047 static void
3048 mono_image_fill_file_table (MonoDomain *domain, MonoReflectionModule *module, MonoDynamicImage *assembly)
3049 {
3050         MonoDynamicTable *table;
3051         guint32 *values;
3052         char blob_size [6];
3053         guchar hash [20];
3054         char *b = blob_size;
3055         char *dir, *path;
3056
3057         table = &assembly->tables [MONO_TABLE_FILE];
3058         table->rows++;
3059         alloc_table (table, table->rows);
3060         values = table->values + table->next_idx * MONO_FILE_SIZE;
3061         values [MONO_FILE_FLAGS] = FILE_CONTAINS_METADATA;
3062         values [MONO_FILE_NAME] = string_heap_insert (&assembly->sheap, module->image->module_name);
3063         if (module->image->dynamic) {
3064                 /* This depends on the fact that the main module is emitted last */
3065                 dir = mono_string_to_utf8 (((MonoReflectionModuleBuilder*)module)->assemblyb->dir);
3066                 path = g_strdup_printf ("%s%c%s", dir, G_DIR_SEPARATOR, module->image->module_name);
3067         } else {
3068                 dir = NULL;
3069                 path = g_strdup (module->image->name);
3070         }
3071         mono_sha1_get_digest_from_file (path, hash);
3072         g_free (dir);
3073         g_free (path);
3074         mono_metadata_encode_value (20, b, &b);
3075         values [MONO_FILE_HASH_VALUE] = mono_image_add_stream_data (&assembly->blob, blob_size, b-blob_size);
3076         mono_image_add_stream_data (&assembly->blob, (char*)hash, 20);
3077         table->next_idx ++;
3078 }
3079
3080 static void
3081 mono_image_fill_module_table (MonoDomain *domain, MonoReflectionModuleBuilder *mb, MonoDynamicImage *assembly)
3082 {
3083         MonoDynamicTable *table;
3084         int i;
3085
3086         table = &assembly->tables [MONO_TABLE_MODULE];
3087         mb->table_idx = table->next_idx ++;
3088         table->values [mb->table_idx * MONO_MODULE_SIZE + MONO_MODULE_NAME] = string_heap_insert_mstring (&assembly->sheap, mb->module.name);
3089         i = mono_image_add_stream_data (&assembly->guid, mono_array_addr (mb->guid, char, 0), 16);
3090         i /= 16;
3091         ++i;
3092         table->values [mb->table_idx * MONO_MODULE_SIZE + MONO_MODULE_GENERATION] = 0;
3093         table->values [mb->table_idx * MONO_MODULE_SIZE + MONO_MODULE_MVID] = i;
3094         table->values [mb->table_idx * MONO_MODULE_SIZE + MONO_MODULE_ENC] = 0;
3095         table->values [mb->table_idx * MONO_MODULE_SIZE + MONO_MODULE_ENCBASE] = 0;
3096 }
3097
3098 static guint32
3099 mono_image_fill_export_table_from_class (MonoDomain *domain, MonoClass *klass,
3100         guint32 module_index, guint32 parent_index, MonoDynamicImage *assembly)
3101 {
3102         MonoDynamicTable *table;
3103         guint32 *values;
3104         guint32 visib, res;
3105
3106         visib = klass->flags & TYPE_ATTRIBUTE_VISIBILITY_MASK;
3107         if (! ((visib & TYPE_ATTRIBUTE_PUBLIC) || (visib & TYPE_ATTRIBUTE_NESTED_PUBLIC)))
3108                 return 0;
3109
3110         table = &assembly->tables [MONO_TABLE_EXPORTEDTYPE];
3111         table->rows++;
3112         alloc_table (table, table->rows);
3113         values = table->values + table->next_idx * MONO_EXP_TYPE_SIZE;
3114
3115         values [MONO_EXP_TYPE_FLAGS] = klass->flags;
3116         values [MONO_EXP_TYPE_TYPEDEF] = klass->type_token;
3117         if (klass->nested_in)
3118                 values [MONO_EXP_TYPE_IMPLEMENTATION] = (parent_index << MONO_IMPLEMENTATION_BITS) + MONO_IMPLEMENTATION_EXP_TYPE;
3119         else
3120                 values [MONO_EXP_TYPE_IMPLEMENTATION] = (module_index << MONO_IMPLEMENTATION_BITS) + MONO_IMPLEMENTATION_FILE;
3121         values [MONO_EXP_TYPE_NAME] = string_heap_insert (&assembly->sheap, klass->name);
3122         values [MONO_EXP_TYPE_NAMESPACE] = string_heap_insert (&assembly->sheap, klass->name_space);
3123
3124         res = table->next_idx;
3125
3126         table->next_idx ++;
3127
3128         /* Emit nested types */
3129         if (klass->nested_classes) {
3130                 GList *tmp;
3131
3132                 for (tmp = klass->nested_classes; tmp; tmp = tmp->next)
3133                         mono_image_fill_export_table_from_class (domain, tmp->data, module_index, table->next_idx - 1, assembly);
3134         }
3135
3136         return res;
3137 }
3138
3139 static void
3140 mono_image_fill_export_table (MonoDomain *domain, MonoReflectionTypeBuilder *tb,
3141         guint32 module_index, guint32 parent_index, MonoDynamicImage *assembly)
3142 {
3143         MonoClass *klass;
3144         guint32 idx, i;
3145
3146         klass = mono_class_from_mono_type (tb->type.type);
3147
3148         klass->type_token = mono_metadata_make_token (MONO_TABLE_TYPEDEF, tb->table_idx);
3149
3150         idx = mono_image_fill_export_table_from_class (domain, klass, module_index, 
3151                                                                                                    parent_index, assembly);
3152
3153         /* 
3154          * Emit nested types
3155          * We need to do this ourselves since klass->nested_classes is not set up.
3156          */
3157         if (tb->subtypes) {
3158                 for (i = 0; i < mono_array_length (tb->subtypes); ++i)
3159                         mono_image_fill_export_table (domain, mono_array_get (tb->subtypes, MonoReflectionTypeBuilder*, i), module_index, idx, assembly);
3160         }
3161 }
3162
3163 static void
3164 mono_image_fill_export_table_from_module (MonoDomain *domain, MonoReflectionModule *module,
3165         guint32 module_index, MonoDynamicImage *assembly)
3166 {
3167         MonoImage *image = module->image;
3168         MonoTableInfo  *t;
3169         guint32 i;
3170
3171         t = &image->tables [MONO_TABLE_TYPEDEF];
3172
3173         for (i = 0; i < t->rows; ++i) {
3174                 MonoClass *klass = mono_class_get (image, mono_metadata_make_token (MONO_TABLE_TYPEDEF, i + 1));
3175
3176                 if (klass->flags & TYPE_ATTRIBUTE_PUBLIC)
3177                         mono_image_fill_export_table_from_class (domain, klass, module_index, 0, assembly);
3178         }
3179 }
3180
3181 static void
3182 mono_image_fill_export_table_from_type_forwarders (MonoReflectionAssemblyBuilder *assemblyb, MonoDynamicImage *assembly)
3183 {
3184         MonoDynamicTable *table;
3185         MonoClass *klass;
3186         guint32 *values;
3187         guint32 scope, idx;
3188         int i;
3189
3190         table = &assembly->tables [MONO_TABLE_EXPORTEDTYPE];
3191
3192         if (assemblyb->type_forwarders) {
3193                 for (i = 0; i < mono_array_length (assemblyb->type_forwarders); ++i) {
3194                         MonoReflectionType *t = mono_array_get (assemblyb->type_forwarders, MonoReflectionType*, i);
3195                         if (!t)
3196                                 continue;
3197
3198                         g_assert (t->type);
3199
3200                         klass = mono_class_from_mono_type (t->type);
3201
3202                         scope = resolution_scope_from_image (assembly, klass->image);
3203                         g_assert ((scope & MONO_RESOLTION_SCOPE_MASK) == MONO_RESOLTION_SCOPE_ASSEMBLYREF);
3204                         idx = scope >> MONO_RESOLTION_SCOPE_BITS;
3205
3206                         table->rows++;
3207                         alloc_table (table, table->rows);
3208                         values = table->values + table->next_idx * MONO_EXP_TYPE_SIZE;
3209
3210                         values [MONO_EXP_TYPE_FLAGS] = TYPE_ATTRIBUTE_FORWARDER;
3211                         values [MONO_EXP_TYPE_TYPEDEF] = 0;
3212                         values [MONO_EXP_TYPE_IMPLEMENTATION] = (idx << MONO_IMPLEMENTATION_BITS) + MONO_IMPLEMENTATION_ASSEMBLYREF;
3213                         values [MONO_EXP_TYPE_NAME] = string_heap_insert (&assembly->sheap, klass->name);
3214                         values [MONO_EXP_TYPE_NAMESPACE] = string_heap_insert (&assembly->sheap, klass->name_space);
3215                 }
3216         }
3217 }
3218
3219 #define align_pointer(base,p)\
3220         do {\
3221                 guint32 __diff = (unsigned char*)(p)-(unsigned char*)(base);\
3222                 if (__diff & 3)\
3223                         (p) += 4 - (__diff & 3);\
3224         } while (0)
3225
3226 static int
3227 compare_constants (const void *a, const void *b)
3228 {
3229         const guint32 *a_values = a;
3230         const guint32 *b_values = b;
3231         return a_values [MONO_CONSTANT_PARENT] - b_values [MONO_CONSTANT_PARENT];
3232 }
3233
3234 static int
3235 compare_semantics (const void *a, const void *b)
3236 {
3237         const guint32 *a_values = a;
3238         const guint32 *b_values = b;
3239         int assoc = a_values [MONO_METHOD_SEMA_ASSOCIATION] - b_values [MONO_METHOD_SEMA_ASSOCIATION];
3240         if (assoc)
3241                 return assoc;
3242         return a_values [MONO_METHOD_SEMA_SEMANTICS] - b_values [MONO_METHOD_SEMA_SEMANTICS];
3243 }
3244
3245 static int
3246 compare_custom_attrs (const void *a, const void *b)
3247 {
3248         const guint32 *a_values = a;
3249         const guint32 *b_values = b;
3250
3251         return a_values [MONO_CUSTOM_ATTR_PARENT] - b_values [MONO_CUSTOM_ATTR_PARENT];
3252 }
3253
3254 static int
3255 compare_field_marshal (const void *a, const void *b)
3256 {
3257         const guint32 *a_values = a;
3258         const guint32 *b_values = b;
3259
3260         return a_values [MONO_FIELD_MARSHAL_PARENT] - b_values [MONO_FIELD_MARSHAL_PARENT];
3261 }
3262
3263 static int
3264 compare_nested (const void *a, const void *b)
3265 {
3266         const guint32 *a_values = a;
3267         const guint32 *b_values = b;
3268
3269         return a_values [MONO_NESTED_CLASS_NESTED] - b_values [MONO_NESTED_CLASS_NESTED];
3270 }
3271
3272 static int
3273 compare_genericparam (const void *a, const void *b)
3274 {
3275         const GenericParamTableEntry **a_entry = (const GenericParamTableEntry **) a;
3276         const GenericParamTableEntry **b_entry = (const GenericParamTableEntry **) b;
3277
3278         if ((*b_entry)->owner == (*a_entry)->owner)
3279                 return 
3280                         (*a_entry)->gparam->type.type->data.generic_param->num - 
3281                         (*b_entry)->gparam->type.type->data.generic_param->num;
3282         else
3283                 return (*a_entry)->owner - (*b_entry)->owner;
3284 }
3285
3286 static int
3287 compare_declsecurity_attrs (const void *a, const void *b)
3288 {
3289         const guint32 *a_values = a;
3290         const guint32 *b_values = b;
3291
3292         return a_values [MONO_DECL_SECURITY_PARENT] - b_values [MONO_DECL_SECURITY_PARENT];
3293 }
3294
3295 static void
3296 pad_heap (MonoDynamicStream *sh)
3297 {
3298         if (sh->index & 3) {
3299                 int sz = 4 - (sh->index & 3);
3300                 memset (sh->data + sh->index, 0, sz);
3301                 sh->index += sz;
3302         }
3303 }
3304
3305 struct StreamDesc {
3306         const char *name;
3307         MonoDynamicStream *stream;
3308 };
3309
3310 /*
3311  * build_compressed_metadata() fills in the blob of data that represents the 
3312  * raw metadata as it will be saved in the PE file. The five streams are output 
3313  * and the metadata tables are comnpressed from the guint32 array representation, 
3314  * to the compressed on-disk format.
3315  */
3316 static void
3317 build_compressed_metadata (MonoDynamicImage *assembly)
3318 {
3319         MonoDynamicTable *table;
3320         int i;
3321         guint64 valid_mask = 0;
3322         guint64 sorted_mask;
3323         guint32 heapt_size = 0;
3324         guint32 meta_size = 256; /* allow for header and other stuff */
3325         guint32 table_offset;
3326         guint32 ntables = 0;
3327         guint64 *int64val;
3328         guint32 *int32val;
3329         guint16 *int16val;
3330         MonoImage *meta;
3331         unsigned char *p;
3332         struct StreamDesc stream_desc [5];
3333
3334         qsort (assembly->gen_params->pdata, assembly->gen_params->len, sizeof (gpointer), compare_genericparam);
3335         for (i = 0; i < assembly->gen_params->len; i++){
3336                 GenericParamTableEntry *entry = g_ptr_array_index (assembly->gen_params, i);
3337                 write_generic_param_entry (assembly, entry);
3338         }
3339
3340         stream_desc [0].name  = "#~";
3341         stream_desc [0].stream = &assembly->tstream;
3342         stream_desc [1].name  = "#Strings";
3343         stream_desc [1].stream = &assembly->sheap;
3344         stream_desc [2].name  = "#US";
3345         stream_desc [2].stream = &assembly->us;
3346         stream_desc [3].name  = "#Blob";
3347         stream_desc [3].stream = &assembly->blob;
3348         stream_desc [4].name  = "#GUID";
3349         stream_desc [4].stream = &assembly->guid;
3350         
3351         /* tables that are sorted */
3352         sorted_mask = ((guint64)1 << MONO_TABLE_CONSTANT) | ((guint64)1 << MONO_TABLE_FIELDMARSHAL)
3353                 | ((guint64)1 << MONO_TABLE_METHODSEMANTICS) | ((guint64)1 << MONO_TABLE_CLASSLAYOUT)
3354                 | ((guint64)1 << MONO_TABLE_FIELDLAYOUT) | ((guint64)1 << MONO_TABLE_FIELDRVA)
3355                 | ((guint64)1 << MONO_TABLE_IMPLMAP) | ((guint64)1 << MONO_TABLE_NESTEDCLASS)
3356                 | ((guint64)1 << MONO_TABLE_METHODIMPL) | ((guint64)1 << MONO_TABLE_CUSTOMATTRIBUTE)
3357                 | ((guint64)1 << MONO_TABLE_DECLSECURITY) | ((guint64)1 << MONO_TABLE_GENERICPARAM);
3358         
3359         /* Compute table sizes */
3360         /* the MonoImage has already been created in mono_image_basic_init() */
3361         meta = &assembly->image;
3362
3363         /* sizes should be multiple of 4 */
3364         pad_heap (&assembly->blob);
3365         pad_heap (&assembly->guid);
3366         pad_heap (&assembly->sheap);
3367         pad_heap (&assembly->us);
3368
3369         /* Setup the info used by compute_sizes () */
3370         meta->idx_blob_wide = assembly->blob.index >= 65536 ? 1 : 0;
3371         meta->idx_guid_wide = assembly->guid.index >= 65536 ? 1 : 0;
3372         meta->idx_string_wide = assembly->sheap.index >= 65536 ? 1 : 0;
3373
3374         meta_size += assembly->blob.index;
3375         meta_size += assembly->guid.index;
3376         meta_size += assembly->sheap.index;
3377         meta_size += assembly->us.index;
3378
3379         for (i=0; i < MONO_TABLE_NUM; ++i)
3380                 meta->tables [i].rows = assembly->tables [i].rows;
3381         
3382         for (i = 0; i < MONO_TABLE_NUM; i++){
3383                 if (meta->tables [i].rows == 0)
3384                         continue;
3385                 valid_mask |= (guint64)1 << i;
3386                 ntables ++;
3387                 meta->tables [i].row_size = mono_metadata_compute_size (
3388                         meta, i, &meta->tables [i].size_bitfield);
3389                 heapt_size += meta->tables [i].row_size * meta->tables [i].rows;
3390         }
3391         heapt_size += 24; /* #~ header size */
3392         heapt_size += ntables * 4;
3393         /* make multiple of 4 */
3394         heapt_size += 3;
3395         heapt_size &= ~3;
3396         meta_size += heapt_size;
3397         meta->raw_metadata = g_malloc0 (meta_size);
3398         p = (unsigned char*)meta->raw_metadata;
3399         /* the metadata signature */
3400         *p++ = 'B'; *p++ = 'S'; *p++ = 'J'; *p++ = 'B';
3401         /* version numbers and 4 bytes reserved */
3402         int16val = (guint16*)p;
3403         *int16val++ = GUINT16_TO_LE (meta->md_version_major);
3404         *int16val = GUINT16_TO_LE (meta->md_version_minor);
3405         p += 8;
3406         /* version string */
3407         int32val = (guint32*)p;
3408         *int32val = GUINT32_TO_LE ((strlen (meta->version) + 3) & (~3)); /* needs to be multiple of 4 */
3409         p += 4;
3410         memcpy (p, meta->version, strlen (meta->version));
3411         p += GUINT32_FROM_LE (*int32val);
3412         align_pointer (meta->raw_metadata, p);
3413         int16val = (guint16*)p;
3414         *int16val++ = GUINT16_TO_LE (0); /* flags must be 0 */
3415         *int16val = GUINT16_TO_LE (5); /* number of streams */
3416         p += 4;
3417
3418         /*
3419          * write the stream info.
3420          */
3421         table_offset = (p - (unsigned char*)meta->raw_metadata) + 5 * 8 + 40; /* room needed for stream headers */
3422         table_offset += 3; table_offset &= ~3;
3423
3424         assembly->tstream.index = heapt_size;
3425         for (i = 0; i < 5; ++i) {
3426                 int32val = (guint32*)p;
3427                 stream_desc [i].stream->offset = table_offset;
3428                 *int32val++ = GUINT32_TO_LE (table_offset);
3429                 *int32val = GUINT32_TO_LE (stream_desc [i].stream->index);
3430                 table_offset += GUINT32_FROM_LE (*int32val);
3431                 table_offset += 3; table_offset &= ~3;
3432                 p += 8;
3433                 strcpy ((char*)p, stream_desc [i].name);
3434                 p += strlen (stream_desc [i].name) + 1;
3435                 align_pointer (meta->raw_metadata, p);
3436         }
3437         /* 
3438          * now copy the data, the table stream header and contents goes first.
3439          */
3440         g_assert ((p - (unsigned char*)meta->raw_metadata) < assembly->tstream.offset);
3441         p = (guchar*)meta->raw_metadata + assembly->tstream.offset;
3442         int32val = (guint32*)p;
3443         *int32val = GUINT32_TO_LE (0); /* reserved */
3444         p += 4;
3445
3446         if ((assembly->tables [MONO_TABLE_GENERICPARAM].rows > 0) ||
3447             (assembly->tables [MONO_TABLE_METHODSPEC].rows > 0) ||
3448             (assembly->tables [MONO_TABLE_GENERICPARAMCONSTRAINT].rows > 0)) {
3449                 *p++ = 2; /* version */
3450                 *p++ = 0;
3451         } else {
3452                 *p++ = 1; /* version */
3453                 *p++ = 0;
3454         }
3455
3456         if (meta->idx_string_wide)
3457                 *p |= 0x01;
3458         if (meta->idx_guid_wide)
3459                 *p |= 0x02;
3460         if (meta->idx_blob_wide)
3461                 *p |= 0x04;
3462         ++p;
3463         *p++ = 1; /* reserved */
3464         int64val = (guint64*)p;
3465         *int64val++ = GUINT64_TO_LE (valid_mask);
3466         *int64val++ = GUINT64_TO_LE (valid_mask & sorted_mask); /* bitvector of sorted tables  */
3467         p += 16;
3468         int32val = (guint32*)p;
3469         for (i = 0; i < MONO_TABLE_NUM; i++){
3470                 if (meta->tables [i].rows == 0)
3471                         continue;
3472                 *int32val++ = GUINT32_TO_LE (meta->tables [i].rows);
3473         }
3474         p = (unsigned char*)int32val;
3475
3476         /* sort the tables that still need sorting */
3477         table = &assembly->tables [MONO_TABLE_CONSTANT];
3478         if (table->rows)
3479                 qsort (table->values + MONO_CONSTANT_SIZE, table->rows, sizeof (guint32) * MONO_CONSTANT_SIZE, compare_constants);
3480         table = &assembly->tables [MONO_TABLE_METHODSEMANTICS];
3481         if (table->rows)
3482                 qsort (table->values + MONO_METHOD_SEMA_SIZE, table->rows, sizeof (guint32) * MONO_METHOD_SEMA_SIZE, compare_semantics);
3483         table = &assembly->tables [MONO_TABLE_CUSTOMATTRIBUTE];
3484         if (table->rows)
3485                 qsort (table->values + MONO_CUSTOM_ATTR_SIZE, table->rows, sizeof (guint32) * MONO_CUSTOM_ATTR_SIZE, compare_custom_attrs);
3486         table = &assembly->tables [MONO_TABLE_FIELDMARSHAL];
3487         if (table->rows)
3488                 qsort (table->values + MONO_FIELD_MARSHAL_SIZE, table->rows, sizeof (guint32) * MONO_FIELD_MARSHAL_SIZE, compare_field_marshal);
3489         table = &assembly->tables [MONO_TABLE_NESTEDCLASS];
3490         if (table->rows)
3491                 qsort (table->values + MONO_NESTED_CLASS_SIZE, table->rows, sizeof (guint32) * MONO_NESTED_CLASS_SIZE, compare_nested);
3492         /* Section 21.11 DeclSecurity in Partition II doesn't specify this to be sorted by MS implementation requires it */
3493         table = &assembly->tables [MONO_TABLE_DECLSECURITY];
3494         if (table->rows)
3495                 qsort (table->values + MONO_DECL_SECURITY_SIZE, table->rows, sizeof (guint32) * MONO_DECL_SECURITY_SIZE, compare_declsecurity_attrs);
3496
3497         /* compress the tables */
3498         for (i = 0; i < MONO_TABLE_NUM; i++){
3499                 int row, col;
3500                 guint32 *values;
3501                 guint32 bitfield = meta->tables [i].size_bitfield;
3502                 if (!meta->tables [i].rows)
3503                         continue;
3504                 if (assembly->tables [i].columns != mono_metadata_table_count (bitfield))
3505                         g_error ("col count mismatch in %d: %d %d", i, assembly->tables [i].columns, mono_metadata_table_count (bitfield));
3506                 meta->tables [i].base = (char*)p;
3507                 for (row = 1; row <= meta->tables [i].rows; ++row) {
3508                         values = assembly->tables [i].values + row * assembly->tables [i].columns;
3509                         for (col = 0; col < assembly->tables [i].columns; ++col) {
3510                                 switch (mono_metadata_table_size (bitfield, col)) {
3511                                 case 1:
3512                                         *p++ = values [col];
3513                                         break;
3514                                 case 2:
3515                                         *p++ = values [col] & 0xff;
3516                                         *p++ = (values [col] >> 8) & 0xff;
3517                                         break;
3518                                 case 4:
3519                                         *p++ = values [col] & 0xff;
3520                                         *p++ = (values [col] >> 8) & 0xff;
3521                                         *p++ = (values [col] >> 16) & 0xff;
3522                                         *p++ = (values [col] >> 24) & 0xff;
3523                                         break;
3524                                 default:
3525                                         g_assert_not_reached ();
3526                                 }
3527                         }
3528                 }
3529                 g_assert ((p - (const unsigned char*)meta->tables [i].base) == (meta->tables [i].rows * meta->tables [i].row_size));
3530         }
3531         
3532         g_assert (assembly->guid.offset + assembly->guid.index < meta_size);
3533         memcpy (meta->raw_metadata + assembly->sheap.offset, assembly->sheap.data, assembly->sheap.index);
3534         memcpy (meta->raw_metadata + assembly->us.offset, assembly->us.data, assembly->us.index);
3535         memcpy (meta->raw_metadata + assembly->blob.offset, assembly->blob.data, assembly->blob.index);
3536         memcpy (meta->raw_metadata + assembly->guid.offset, assembly->guid.data, assembly->guid.index);
3537
3538         assembly->meta_size = assembly->guid.offset + assembly->guid.index;
3539 }
3540
3541 /*
3542  * Some tables in metadata need to be sorted according to some criteria, but
3543  * when methods and fields are first created with reflection, they may be assigned a token
3544  * that doesn't correspond to the final token they will get assigned after the sorting.
3545  * ILGenerator.cs keeps a fixup table that maps the position of tokens in the IL code stream
3546  * with the reflection objects that represent them. Once all the tables are set up, the 
3547  * reflection objects will contains the correct table index. fixup_method() will fixup the
3548  * tokens for the method with ILGenerator @ilgen.
3549  */
3550 static void
3551 fixup_method (MonoReflectionILGen *ilgen, gpointer value, MonoDynamicImage *assembly) {
3552         guint32 code_idx = GPOINTER_TO_UINT (value);
3553         MonoReflectionILTokenInfo *iltoken;
3554         MonoReflectionFieldBuilder *field;
3555         MonoReflectionCtorBuilder *ctor;
3556         MonoReflectionMethodBuilder *method;
3557         MonoReflectionTypeBuilder *tb;
3558         MonoReflectionArrayMethod *am;
3559         guint32 i, idx = 0;
3560         unsigned char *target;
3561
3562         for (i = 0; i < ilgen->num_token_fixups; ++i) {
3563                 iltoken = (MonoReflectionILTokenInfo *)mono_array_addr_with_size (ilgen->token_fixups, sizeof (MonoReflectionILTokenInfo), i);
3564                 target = (guchar*)assembly->code.data + code_idx + iltoken->code_pos;
3565                 switch (target [3]) {
3566                 case MONO_TABLE_FIELD:
3567                         if (!strcmp (iltoken->member->vtable->klass->name, "FieldBuilder")) {
3568                                 field = (MonoReflectionFieldBuilder *)iltoken->member;
3569                                 idx = field->table_idx;
3570                         } else if (!strcmp (iltoken->member->vtable->klass->name, "MonoField")) {
3571                                 MonoClassField *f = ((MonoReflectionField*)iltoken->member)->field;
3572                                 idx = GPOINTER_TO_UINT (g_hash_table_lookup (assembly->field_to_table_idx, f));
3573                         } else {
3574                                 g_assert_not_reached ();
3575                         }
3576                         break;
3577                 case MONO_TABLE_METHOD:
3578                         if (!strcmp (iltoken->member->vtable->klass->name, "MethodBuilder")) {
3579                                 method = (MonoReflectionMethodBuilder *)iltoken->member;
3580                                 idx = method->table_idx;
3581                         } else if (!strcmp (iltoken->member->vtable->klass->name, "ConstructorBuilder")) {
3582                                 ctor = (MonoReflectionCtorBuilder *)iltoken->member;
3583                                 idx = ctor->table_idx;
3584                         } else if (!strcmp (iltoken->member->vtable->klass->name, "MonoMethod") || 
3585                                            !strcmp (iltoken->member->vtable->klass->name, "MonoCMethod")) {
3586                                 MonoMethod *m = ((MonoReflectionMethod*)iltoken->member)->method;
3587                                 idx = GPOINTER_TO_UINT (g_hash_table_lookup (assembly->method_to_table_idx, m));
3588                         } else {
3589                                 g_assert_not_reached ();
3590                         }
3591                         break;
3592                 case MONO_TABLE_TYPEDEF:
3593                         if (strcmp (iltoken->member->vtable->klass->name, "TypeBuilder"))
3594                                 g_assert_not_reached ();
3595                         tb = (MonoReflectionTypeBuilder *)iltoken->member;
3596                         idx = tb->table_idx;
3597                         break;
3598                 case MONO_TABLE_MEMBERREF:
3599                         if (!strcmp (iltoken->member->vtable->klass->name, "MonoArrayMethod")) {
3600                                 am = (MonoReflectionArrayMethod*)iltoken->member;
3601                                 idx = am->table_idx;
3602                         } else if (!strcmp (iltoken->member->vtable->klass->name, "MonoMethod") ||
3603                                    !strcmp (iltoken->member->vtable->klass->name, "MonoCMethod") ||
3604                                    !strcmp (iltoken->member->vtable->klass->name, "MonoGenericMethod") ||
3605                                    !strcmp (iltoken->member->vtable->klass->name, "MonoGenericCMethod")) {
3606                                 MonoMethod *m = ((MonoReflectionMethod*)iltoken->member)->method;
3607                                 g_assert (m->klass->generic_class || m->klass->generic_container);
3608                                 continue;
3609                         } else if (!strcmp (iltoken->member->vtable->klass->name, "FieldBuilder")) {
3610                                 continue;
3611                         } else if (!strcmp (iltoken->member->vtable->klass->name, "MonoField")) {
3612                                 MonoClassField *f = ((MonoReflectionField*)iltoken->member)->field;
3613                                 g_assert (f->generic_info);
3614                                 continue;
3615                         } else if (!strcmp (iltoken->member->vtable->klass->name, "MethodBuilder")) {
3616                                 continue;
3617                         } else {
3618                                 g_assert_not_reached ();
3619                         }
3620                         break;
3621                 case MONO_TABLE_METHODSPEC:
3622                         if (!strcmp (iltoken->member->vtable->klass->name, "MonoGenericMethod")) {
3623                                 MonoMethod *m = ((MonoReflectionMethod*)iltoken->member)->method;
3624                                 g_assert (mono_method_signature (m)->generic_param_count);
3625                                 continue;
3626                         } else {
3627                                 g_assert_not_reached ();
3628                         }
3629                         break;
3630                 default:
3631                         g_error ("got unexpected table 0x%02x in fixup", target [3]);
3632                 }
3633                 target [0] = idx & 0xff;
3634                 target [1] = (idx >> 8) & 0xff;
3635                 target [2] = (idx >> 16) & 0xff;
3636         }
3637 }
3638
3639 /*
3640  * fixup_cattrs:
3641  *
3642  *   The CUSTOM_ATTRIBUTE table might contain METHODDEF tokens whose final
3643  * value is not known when the table is emitted.
3644  */
3645 static void
3646 fixup_cattrs (MonoDynamicImage *assembly)
3647 {
3648         MonoDynamicTable *table;
3649         guint32 *values;
3650         guint32 type, i, idx, token;
3651         MonoObject *ctor;
3652
3653         table = &assembly->tables [MONO_TABLE_CUSTOMATTRIBUTE];
3654
3655         for (i = 0; i < table->rows; ++i) {
3656                 values = table->values + ((i + 1) * MONO_CUSTOM_ATTR_SIZE);
3657
3658                 type = values [MONO_CUSTOM_ATTR_TYPE];
3659                 if ((type & MONO_CUSTOM_ATTR_TYPE_MASK) == MONO_CUSTOM_ATTR_TYPE_METHODDEF) {
3660                         idx = type >> MONO_CUSTOM_ATTR_TYPE_BITS;
3661                         token = mono_metadata_make_token (MONO_TABLE_METHOD, idx);
3662                         ctor = mono_g_hash_table_lookup (assembly->tokens, GUINT_TO_POINTER (token));
3663                         g_assert (ctor);
3664
3665                         if (!strcmp (ctor->vtable->klass->name, "MonoCMethod")) {
3666                                 MonoMethod *m = ((MonoReflectionMethod*)ctor)->method;
3667                                 idx = GPOINTER_TO_UINT (g_hash_table_lookup (assembly->method_to_table_idx, m));
3668                                 values [MONO_CUSTOM_ATTR_TYPE] = (idx << MONO_CUSTOM_ATTR_TYPE_BITS) | MONO_CUSTOM_ATTR_TYPE_METHODDEF;
3669                         }
3670                 }
3671         }
3672 }
3673
3674 static void
3675 assembly_add_resource_manifest (MonoReflectionModuleBuilder *mb, MonoDynamicImage *assembly, MonoReflectionResource *rsrc, guint32 implementation)
3676 {
3677         MonoDynamicTable *table;
3678         guint32 *values;
3679
3680         table = &assembly->tables [MONO_TABLE_MANIFESTRESOURCE];
3681         table->rows++;
3682         alloc_table (table, table->rows);
3683         values = table->values + table->next_idx * MONO_MANIFEST_SIZE;
3684         values [MONO_MANIFEST_OFFSET] = rsrc->offset;
3685         values [MONO_MANIFEST_FLAGS] = rsrc->attrs;
3686         values [MONO_MANIFEST_NAME] = string_heap_insert_mstring (&assembly->sheap, rsrc->name);
3687         values [MONO_MANIFEST_IMPLEMENTATION] = implementation;
3688         table->next_idx++;
3689 }
3690
3691 static void
3692 assembly_add_resource (MonoReflectionModuleBuilder *mb, MonoDynamicImage *assembly, MonoReflectionResource *rsrc)
3693 {
3694         MonoDynamicTable *table;
3695         guint32 *values;
3696         char blob_size [6];
3697         guchar hash [20];
3698         char *b = blob_size;
3699         char *name, *sname;
3700         guint32 idx, offset;
3701
3702         if (rsrc->filename) {
3703                 name = mono_string_to_utf8 (rsrc->filename);
3704                 sname = g_path_get_basename (name);
3705         
3706                 table = &assembly->tables [MONO_TABLE_FILE];
3707                 table->rows++;
3708                 alloc_table (table, table->rows);
3709                 values = table->values + table->next_idx * MONO_FILE_SIZE;
3710                 values [MONO_FILE_FLAGS] = FILE_CONTAINS_NO_METADATA;
3711                 values [MONO_FILE_NAME] = string_heap_insert (&assembly->sheap, sname);
3712                 g_free (sname);
3713
3714                 mono_sha1_get_digest_from_file (name, hash);
3715                 mono_metadata_encode_value (20, b, &b);
3716                 values [MONO_FILE_HASH_VALUE] = mono_image_add_stream_data (&assembly->blob, blob_size, b-blob_size);
3717                 mono_image_add_stream_data (&assembly->blob, (char*)hash, 20);
3718                 g_free (name);
3719                 idx = table->next_idx++;
3720                 rsrc->offset = 0;
3721                 idx = MONO_IMPLEMENTATION_FILE | (idx << MONO_IMPLEMENTATION_BITS);
3722         } else {
3723                 char sizebuf [4];
3724                 char *data;
3725                 guint len;
3726                 if (rsrc->data) {
3727                         data = mono_array_addr (rsrc->data, char, 0);
3728                         len = mono_array_length (rsrc->data);
3729                 } else {
3730                         data = NULL;
3731                         len = 0;
3732                 }
3733                 offset = len;
3734                 sizebuf [0] = offset; sizebuf [1] = offset >> 8;
3735                 sizebuf [2] = offset >> 16; sizebuf [3] = offset >> 24;
3736                 rsrc->offset = mono_image_add_stream_data (&assembly->resources, sizebuf, 4);
3737                 mono_image_add_stream_data (&assembly->resources, data, len);
3738
3739                 if (!mb->is_main)
3740                         /* 
3741                          * The entry should be emitted into the MANIFESTRESOURCE table of 
3742                          * the main module, but that needs to reference the FILE table
3743                          * which isn't emitted yet.
3744                          */
3745                         return;
3746                 else
3747                         idx = 0;
3748         }
3749
3750         assembly_add_resource_manifest (mb, assembly, rsrc, idx);
3751 }
3752
3753 static void
3754 set_version_from_string (MonoString *version, guint32 *values)
3755 {
3756         gchar *ver, *p, *str;
3757         guint32 i;
3758         
3759         values [MONO_ASSEMBLY_MAJOR_VERSION] = 0;
3760         values [MONO_ASSEMBLY_MINOR_VERSION] = 0;
3761         values [MONO_ASSEMBLY_REV_NUMBER] = 0;
3762         values [MONO_ASSEMBLY_BUILD_NUMBER] = 0;
3763         if (!version)
3764                 return;
3765         ver = str = mono_string_to_utf8 (version);
3766         for (i = 0; i < 4; ++i) {
3767                 values [MONO_ASSEMBLY_MAJOR_VERSION + i] = strtol (ver, &p, 10);
3768                 switch (*p) {
3769                 case '.':
3770                         p++;
3771                         break;
3772                 case '*':
3773                         /* handle Revision and Build */
3774                         p++;
3775                         break;
3776                 }
3777                 ver = p;
3778         }
3779         g_free (str);
3780 }
3781
3782 static guint32
3783 load_public_key (MonoArray *pkey, MonoDynamicImage *assembly) {
3784         gsize len;
3785         guint32 token = 0;
3786         char blob_size [6];
3787         char *b = blob_size;
3788
3789         if (!pkey)
3790                 return token;
3791
3792         len = mono_array_length (pkey);
3793         mono_metadata_encode_value (len, b, &b);
3794         token = mono_image_add_stream_data (&assembly->blob, blob_size, b - blob_size);
3795         mono_image_add_stream_data (&assembly->blob, mono_array_addr (pkey, char, 0), len);
3796
3797         assembly->public_key = g_malloc (len);
3798         memcpy (assembly->public_key, mono_array_addr (pkey, char, 0), len);
3799         assembly->public_key_len = len;
3800
3801         /* Special case: check for ECMA key (16 bytes) */
3802         if ((len == MONO_ECMA_KEY_LENGTH) && mono_is_ecma_key (mono_array_addr (pkey, char, 0), len)) {
3803                 /* In this case we must reserve 128 bytes (1024 bits) for the signature */
3804                 assembly->strong_name_size = MONO_DEFAULT_PUBLIC_KEY_LENGTH;
3805         } else if (len >= MONO_PUBLIC_KEY_HEADER_LENGTH + MONO_MINIMUM_PUBLIC_KEY_LENGTH) {
3806                 /* minimum key size (in 2.0) is 384 bits */
3807                 assembly->strong_name_size = len - MONO_PUBLIC_KEY_HEADER_LENGTH;
3808         } else {
3809                 /* FIXME - verifier */
3810                 g_warning ("Invalid public key length: %d bits (total: %d)", (int)MONO_PUBLIC_KEY_BIT_SIZE (len), (int)len);
3811                 assembly->strong_name_size = MONO_DEFAULT_PUBLIC_KEY_LENGTH; /* to be safe */
3812         }
3813         assembly->strong_name = g_malloc0 (assembly->strong_name_size);
3814
3815         return token;
3816 }
3817
3818 static void
3819 mono_image_emit_manifest (MonoReflectionModuleBuilder *moduleb)
3820 {
3821         MonoDynamicTable *table;
3822         MonoDynamicImage *assembly;
3823         MonoReflectionAssemblyBuilder *assemblyb;
3824         MonoDomain *domain;
3825         guint32 *values;
3826         int i;
3827         guint32 module_index;
3828
3829         assemblyb = moduleb->assemblyb;
3830         assembly = moduleb->dynamic_image;
3831         domain = mono_object_domain (assemblyb);
3832
3833         /* Emit ASSEMBLY table */
3834         table = &assembly->tables [MONO_TABLE_ASSEMBLY];
3835         alloc_table (table, 1);
3836         values = table->values + MONO_ASSEMBLY_SIZE;
3837         values [MONO_ASSEMBLY_HASH_ALG] = assemblyb->algid? assemblyb->algid: ASSEMBLY_HASH_SHA1;
3838         values [MONO_ASSEMBLY_NAME] = string_heap_insert_mstring (&assembly->sheap, assemblyb->name);
3839         if (assemblyb->culture) {
3840                 values [MONO_ASSEMBLY_CULTURE] = string_heap_insert_mstring (&assembly->sheap, assemblyb->culture);
3841         } else {
3842                 values [MONO_ASSEMBLY_CULTURE] = string_heap_insert (&assembly->sheap, "");
3843         }
3844         values [MONO_ASSEMBLY_PUBLIC_KEY] = load_public_key (assemblyb->public_key, assembly);
3845         values [MONO_ASSEMBLY_FLAGS] = assemblyb->flags;
3846         set_version_from_string (assemblyb->version, values);
3847
3848         /* Emit FILE + EXPORTED_TYPE table */
3849         module_index = 0;
3850         for (i = 0; i < mono_array_length (assemblyb->modules); ++i) {
3851                 int j;
3852                 MonoReflectionModuleBuilder *file_module = 
3853                         mono_array_get (assemblyb->modules, MonoReflectionModuleBuilder*, i);
3854                 if (file_module != moduleb) {
3855                         mono_image_fill_file_table (domain, (MonoReflectionModule*)file_module, assembly);
3856                         module_index ++;
3857                         if (file_module->types) {
3858                                 for (j = 0; j < file_module->num_types; ++j) {
3859                                         MonoReflectionTypeBuilder *tb = mono_array_get (file_module->types, MonoReflectionTypeBuilder*, j);
3860                                         mono_image_fill_export_table (domain, tb, module_index, 0, assembly);
3861                                 }
3862                         }
3863                 }
3864         }
3865         if (assemblyb->loaded_modules) {
3866                 for (i = 0; i < mono_array_length (assemblyb->loaded_modules); ++i) {
3867                         MonoReflectionModule *file_module = 
3868                                 mono_array_get (assemblyb->loaded_modules, MonoReflectionModule*, i);
3869                         mono_image_fill_file_table (domain, file_module, assembly);
3870                         module_index ++;
3871                         mono_image_fill_export_table_from_module (domain, file_module, module_index, assembly);
3872                 }
3873         }
3874         if (assemblyb->type_forwarders)
3875                 mono_image_fill_export_table_from_type_forwarders (assemblyb, assembly);
3876
3877         /* Emit MANIFESTRESOURCE table */
3878         module_index = 0;
3879         for (i = 0; i < mono_array_length (assemblyb->modules); ++i) {
3880                 int j;
3881                 MonoReflectionModuleBuilder *file_module = 
3882                         mono_array_get (assemblyb->modules, MonoReflectionModuleBuilder*, i);
3883                 /* The table for the main module is emitted later */
3884                 if (file_module != moduleb) {
3885                         module_index ++;
3886                         if (file_module->resources) {
3887                                 int len = mono_array_length (file_module->resources);
3888                                 for (j = 0; j < len; ++j) {
3889                                         MonoReflectionResource* res = (MonoReflectionResource*)mono_array_addr (file_module->resources, MonoReflectionResource, j);
3890                                         assembly_add_resource_manifest (file_module, assembly, res, MONO_IMPLEMENTATION_FILE | (module_index << MONO_IMPLEMENTATION_BITS));
3891                                 }
3892                         }
3893                 }
3894         }               
3895 }
3896
3897 /*
3898  * mono_image_build_metadata() will fill the info in all the needed metadata tables
3899  * for the modulebuilder @moduleb.
3900  * At the end of the process, method and field tokens are fixed up and the 
3901  * on-disk compressed metadata representation is created.
3902  */
3903 void
3904 mono_image_build_metadata (MonoReflectionModuleBuilder *moduleb)
3905 {
3906         MonoDynamicTable *table;
3907         MonoDynamicImage *assembly;
3908         MonoReflectionAssemblyBuilder *assemblyb;
3909         MonoDomain *domain;
3910         GPtrArray *types;
3911         guint32 *values;
3912         int i, j;
3913
3914         assemblyb = moduleb->assemblyb;
3915         assembly = moduleb->dynamic_image;
3916         domain = mono_object_domain (assemblyb);
3917
3918         if (assembly->text_rva)
3919                 return;
3920
3921         assembly->text_rva = START_TEXT_RVA;
3922
3923         if (moduleb->is_main) {
3924                 mono_image_emit_manifest (moduleb);
3925         }
3926
3927         table = &assembly->tables [MONO_TABLE_TYPEDEF];
3928         table->rows = 1; /* .<Module> */
3929         table->next_idx++;
3930         alloc_table (table, table->rows);
3931         /*
3932          * Set the first entry.
3933          */
3934         values = table->values + table->columns;
3935         values [MONO_TYPEDEF_FLAGS] = 0;
3936         values [MONO_TYPEDEF_NAME] = string_heap_insert (&assembly->sheap, "<Module>") ;
3937         values [MONO_TYPEDEF_NAMESPACE] = string_heap_insert (&assembly->sheap, "") ;
3938         values [MONO_TYPEDEF_EXTENDS] = 0;
3939         values [MONO_TYPEDEF_FIELD_LIST] = 1;
3940         values [MONO_TYPEDEF_METHOD_LIST] = 1;
3941
3942         /* 
3943          * handle global methods 
3944          * FIXME: test what to do when global methods are defined in multiple modules.
3945          */
3946         if (moduleb->global_methods) {
3947                 table = &assembly->tables [MONO_TABLE_METHOD];
3948                 table->rows += mono_array_length (moduleb->global_methods);
3949                 alloc_table (table, table->rows);
3950                 for (i = 0; i < mono_array_length (moduleb->global_methods); ++i)
3951                         mono_image_get_method_info (
3952                                 mono_array_get (moduleb->global_methods, MonoReflectionMethodBuilder*, i), assembly);
3953         }
3954         if (moduleb->global_fields) {
3955                 table = &assembly->tables [MONO_TABLE_FIELD];
3956                 table->rows += mono_array_length (moduleb->global_fields);
3957                 alloc_table (table, table->rows);
3958                 for (i = 0; i < mono_array_length (moduleb->global_fields); ++i)
3959                         mono_image_get_field_info (
3960                                 mono_array_get (moduleb->global_fields, MonoReflectionFieldBuilder*, i), assembly);
3961         }
3962
3963         table = &assembly->tables [MONO_TABLE_MODULE];
3964         alloc_table (table, 1);
3965         mono_image_fill_module_table (domain, moduleb, assembly);
3966
3967         /* Collect all types into a list sorted by their table_idx */
3968         types = g_ptr_array_new ();
3969
3970         if (moduleb->types)
3971                 for (i = 0; i < moduleb->num_types; ++i) {
3972                         MonoReflectionTypeBuilder *type = mono_array_get (moduleb->types, MonoReflectionTypeBuilder*, i);
3973                         collect_types (types, type);
3974                 }
3975
3976         g_ptr_array_sort (types, (GCompareFunc)compare_types_by_table_idx);
3977         table = &assembly->tables [MONO_TABLE_TYPEDEF];
3978         table->rows += types->len;
3979         alloc_table (table, table->rows);
3980
3981         /*
3982          * Emit type names + namespaces at one place inside the string heap,
3983          * so load_class_names () needs to touch fewer pages.
3984          */
3985         for (i = 0; i < types->len; ++i) {
3986                 MonoReflectionTypeBuilder *tb = g_ptr_array_index (types, i);
3987                 string_heap_insert_mstring (&assembly->sheap, tb->nspace);
3988         }
3989         for (i = 0; i < types->len; ++i) {
3990                 MonoReflectionTypeBuilder *tb = g_ptr_array_index (types, i);
3991                 string_heap_insert_mstring (&assembly->sheap, tb->name);
3992         }
3993
3994         for (i = 0; i < types->len; ++i) {
3995                 MonoReflectionTypeBuilder *type = g_ptr_array_index (types, i);
3996                 mono_image_get_type_info (domain, type, assembly);
3997         }
3998
3999         /* 
4000          * table->rows is already set above and in mono_image_fill_module_table.
4001          */
4002         /* add all the custom attributes at the end, once all the indexes are stable */
4003         mono_image_add_cattrs (assembly, 1, MONO_CUSTOM_ATTR_ASSEMBLY, assemblyb->cattrs);
4004
4005         /* CAS assembly permissions */
4006         if (assemblyb->permissions_minimum)
4007                 mono_image_add_decl_security (assembly, mono_metadata_make_token (MONO_TABLE_ASSEMBLY, 1), assemblyb->permissions_minimum);
4008         if (assemblyb->permissions_optional)
4009                 mono_image_add_decl_security (assembly, mono_metadata_make_token (MONO_TABLE_ASSEMBLY, 1), assemblyb->permissions_optional);
4010         if (assemblyb->permissions_refused)
4011                 mono_image_add_decl_security (assembly, mono_metadata_make_token (MONO_TABLE_ASSEMBLY, 1), assemblyb->permissions_refused);
4012
4013         module_add_cattrs (assembly, moduleb);
4014
4015         /* fixup tokens */
4016         mono_g_hash_table_foreach (assembly->token_fixups, (GHFunc)fixup_method, assembly);
4017
4018         /* Create the MethodImpl table.  We do this after emitting all methods so we already know
4019          * the final tokens and don't need another fixup pass. */
4020
4021         if (moduleb->global_methods) {
4022                 for (i = 0; i < mono_array_length (moduleb->global_methods); ++i) {
4023                         MonoReflectionMethodBuilder *mb = mono_array_get (
4024                                 moduleb->global_methods, MonoReflectionMethodBuilder*, i);
4025                         mono_image_add_methodimpl (assembly, mb);
4026                 }
4027         }
4028
4029         for (i = 0; i < types->len; ++i) {
4030                 MonoReflectionTypeBuilder *type = g_ptr_array_index (types, i);
4031                 if (type->methods) {
4032                         for (j = 0; j < type->num_methods; ++j) {
4033                                 MonoReflectionMethodBuilder *mb = mono_array_get (
4034                                         type->methods, MonoReflectionMethodBuilder*, j);
4035
4036                                 mono_image_add_methodimpl (assembly, mb);
4037                         }
4038                 }
4039         }
4040
4041         g_ptr_array_free (types, TRUE);
4042
4043         fixup_cattrs (assembly);
4044 }
4045
4046 /*
4047  * mono_image_insert_string:
4048  * @module: module builder object
4049  * @str: a string
4050  *
4051  * Insert @str into the user string stream of @module.
4052  */
4053 guint32
4054 mono_image_insert_string (MonoReflectionModuleBuilder *module, MonoString *str)
4055 {
4056         MonoDynamicImage *assembly;
4057         guint32 idx;
4058         char buf [16];
4059         char *b = buf;
4060         
4061         MONO_ARCH_SAVE_REGS;
4062
4063         if (!module->dynamic_image)
4064                 mono_image_module_basic_init (module);
4065
4066         assembly = module->dynamic_image;
4067         
4068         if (assembly->save) {
4069                 mono_metadata_encode_value (1 | (str->length * 2), b, &b);
4070                 idx = mono_image_add_stream_data (&assembly->us, buf, b-buf);
4071 #if G_BYTE_ORDER != G_LITTLE_ENDIAN
4072         {
4073                 char *swapped = g_malloc (2 * mono_string_length (str));
4074                 const char *p = (const char*)mono_string_chars (str);
4075
4076                 swap_with_size (swapped, p, 2, mono_string_length (str));
4077                 mono_image_add_stream_data (&assembly->us, swapped, str->length * 2);
4078                 g_free (swapped);
4079         }
4080 #else
4081                 mono_image_add_stream_data (&assembly->us, (const char*)mono_string_chars (str), str->length * 2);
4082 #endif
4083                 mono_image_add_stream_data (&assembly->us, "", 1);
4084         } else {
4085                 idx = assembly->us.index ++;
4086         }
4087
4088         mono_g_hash_table_insert (assembly->tokens, GUINT_TO_POINTER (MONO_TOKEN_STRING | idx), str);
4089
4090         return MONO_TOKEN_STRING | idx;
4091 }
4092
4093 guint32
4094 mono_image_create_method_token (MonoDynamicImage *assembly, MonoObject *obj, MonoArray *opt_param_types)
4095 {
4096         MonoClass *klass;
4097         guint32 token = 0;
4098
4099         klass = obj->vtable->klass;
4100         if (strcmp (klass->name, "MonoMethod") == 0) {
4101                 MonoMethod *method = ((MonoReflectionMethod *)obj)->method;
4102                 MonoMethodSignature *sig, *old;
4103                 guint32 sig_token, parent;
4104                 int nargs, i;
4105
4106                 g_assert (opt_param_types && (mono_method_signature (method)->sentinelpos >= 0));
4107
4108                 nargs = mono_array_length (opt_param_types);
4109                 old = mono_method_signature (method);
4110                 sig = mono_metadata_signature_alloc ( &assembly->image, old->param_count + nargs);
4111
4112                 sig->hasthis = old->hasthis;
4113                 sig->explicit_this = old->explicit_this;
4114                 sig->call_convention = old->call_convention;
4115                 sig->generic_param_count = old->generic_param_count;
4116                 sig->param_count = old->param_count + nargs;
4117                 sig->sentinelpos = old->param_count;
4118                 sig->ret = old->ret;
4119
4120                 for (i = 0; i < old->param_count; i++)
4121                         sig->params [i] = old->params [i];
4122
4123                 for (i = 0; i < nargs; i++) {
4124                         MonoReflectionType *rt = mono_array_get (opt_param_types, MonoReflectionType *, i);
4125                         sig->params [old->param_count + i] = rt->type;
4126                 }
4127
4128                 parent = mono_image_typedef_or_ref (assembly, &method->klass->byval_arg);
4129                 g_assert ((parent & MONO_TYPEDEFORREF_MASK) == MONO_MEMBERREF_PARENT_TYPEREF);
4130                 parent >>= MONO_TYPEDEFORREF_BITS;
4131
4132                 parent <<= MONO_MEMBERREF_PARENT_BITS;
4133                 parent |= MONO_MEMBERREF_PARENT_TYPEREF;
4134
4135                 sig_token = method_encode_signature (assembly, sig);
4136                 token = mono_image_get_varargs_method_token (assembly, parent, method->name, sig_token);
4137         } else if (strcmp (klass->name, "MethodBuilder") == 0) {
4138                 MonoReflectionMethodBuilder *mb = (MonoReflectionMethodBuilder *)obj;
4139                 ReflectionMethodBuilder rmb;
4140                 guint32 parent, sig;
4141         
4142                 reflection_methodbuilder_from_method_builder (&rmb, mb);
4143                 rmb.opt_types = opt_param_types;
4144
4145                 sig = method_builder_encode_signature (assembly, &rmb);
4146
4147                 parent = mono_image_create_token (assembly, obj, TRUE);
4148                 g_assert (mono_metadata_token_table (parent) == MONO_TABLE_METHOD);
4149
4150                 parent = mono_metadata_token_index (parent) << MONO_MEMBERREF_PARENT_BITS;
4151                 parent |= MONO_MEMBERREF_PARENT_METHODDEF;
4152
4153                 token = mono_image_get_varargs_method_token (
4154                         assembly, parent, mono_string_to_utf8 (rmb.name), sig);
4155         } else {
4156                 g_error ("requested method token for %s\n", klass->name);
4157         }
4158
4159         return token;
4160 }
4161
4162 /*
4163  * mono_image_create_token:
4164  * @assembly: a dynamic assembly
4165  * @obj:
4166  *
4167  * Get a token to insert in the IL code stream for the given MemberInfo.
4168  * @obj can be one of:
4169  *      ConstructorBuilder
4170  *      MethodBuilder
4171  *      FieldBuilder
4172  *      MonoCMethod
4173  *      MonoMethod
4174  *      MonoField
4175  *      MonoType
4176  *      TypeBuilder
4177  */
4178 guint32
4179 mono_image_create_token (MonoDynamicImage *assembly, MonoObject *obj, gboolean create_methodspec)
4180 {
4181         MonoClass *klass;
4182         guint32 token = 0;
4183
4184         klass = obj->vtable->klass;
4185         if (strcmp (klass->name, "MethodBuilder") == 0) {
4186                 MonoReflectionMethodBuilder *mb = (MonoReflectionMethodBuilder *)obj;
4187
4188                 if (((MonoReflectionTypeBuilder*)mb->type)->module->dynamic_image == assembly)
4189                         token = mb->table_idx | MONO_TOKEN_METHOD_DEF;
4190                 else
4191                         token = mono_image_get_methodbuilder_token (assembly, mb);
4192                 /*g_print ("got token 0x%08x for %s\n", token, mono_string_to_utf8 (mb->name));*/
4193         } else if (strcmp (klass->name, "ConstructorBuilder") == 0) {
4194                 MonoReflectionCtorBuilder *mb = (MonoReflectionCtorBuilder *)obj;
4195
4196                 if (((MonoReflectionTypeBuilder*)mb->type)->module->dynamic_image == assembly)
4197                         token = mb->table_idx | MONO_TOKEN_METHOD_DEF;
4198                 else
4199                         token = mono_image_get_ctorbuilder_token (assembly, mb);
4200                 /*g_print ("got token 0x%08x for %s\n", token, mono_string_to_utf8 (mb->name));*/
4201         } else if (strcmp (klass->name, "FieldBuilder") == 0) {
4202                 MonoReflectionFieldBuilder *fb = (MonoReflectionFieldBuilder *)obj;
4203                 MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder *)fb->typeb;
4204                 if (tb->generic_params) {
4205                         token = mono_image_get_generic_field_token (assembly, fb);
4206                 } else {
4207                         token = fb->table_idx | MONO_TOKEN_FIELD_DEF;
4208                 }
4209         } else if (strcmp (klass->name, "TypeBuilder") == 0) {
4210                 MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder *)obj;
4211                 token = tb->table_idx | MONO_TOKEN_TYPE_DEF;
4212         } else if (strcmp (klass->name, "MonoType") == 0) {
4213                 MonoReflectionType *tb = (MonoReflectionType *)obj;
4214                 MonoClass *mc = mono_class_from_mono_type (tb->type);
4215                 token = mono_metadata_token_from_dor (
4216                         mono_image_typedef_or_ref_full (assembly, tb->type, mc->generic_container == NULL));
4217         } else if (strcmp (klass->name, "GenericTypeParameterBuilder") == 0) {
4218                 MonoReflectionType *tb = (MonoReflectionType *)obj;
4219                 token = mono_metadata_token_from_dor (
4220                         mono_image_typedef_or_ref (assembly, tb->type));
4221         } else if (strcmp (klass->name, "MonoGenericClass") == 0) {
4222                 MonoReflectionType *tb = (MonoReflectionType *)obj;
4223                 token = mono_metadata_token_from_dor (
4224                         mono_image_typedef_or_ref (assembly, tb->type));
4225         } else if (strcmp (klass->name, "MonoCMethod") == 0 ||
4226                    strcmp (klass->name, "MonoMethod") == 0 ||
4227                    strcmp (klass->name, "MonoGenericMethod") == 0 ||
4228                    strcmp (klass->name, "MonoGenericCMethod") == 0) {
4229                 MonoReflectionMethod *m = (MonoReflectionMethod *)obj;
4230                 if (m->method->is_inflated) {
4231                         if (create_methodspec)
4232                                 token = mono_image_get_methodspec_token (assembly, m->method);
4233                         else
4234                                 token = mono_image_get_inflated_method_token (assembly, m->method);
4235                 } else if ((m->method->klass->image == &assembly->image) &&
4236                          !m->method->klass->generic_class) {
4237                         static guint32 method_table_idx = 0xffffff;
4238                         if (m->method->klass->wastypebuilder) {
4239                                 /* we use the same token as the one that was assigned
4240                                  * to the Methodbuilder.
4241                                  * FIXME: do the equivalent for Fields.
4242                                  */
4243                                 token = m->method->token;
4244                         } else {
4245                                 /*
4246                                  * Each token should have a unique index, but the indexes are
4247                                  * assigned by managed code, so we don't know about them. An
4248                                  * easy solution is to count backwards...
4249                                  */
4250                                 method_table_idx --;
4251                                 token = MONO_TOKEN_METHOD_DEF | method_table_idx;
4252                         }
4253                 } else {
4254                         token = mono_image_get_methodref_token (assembly, m->method);
4255                 }
4256                 /*g_print ("got token 0x%08x for %s\n", token, m->method->name);*/
4257         } else if (strcmp (klass->name, "MonoField") == 0) {
4258                 MonoReflectionField *f = (MonoReflectionField *)obj;
4259                 if ((f->field->parent->image == &assembly->image) && !f->field->generic_info) {
4260                         static guint32 field_table_idx = 0xffffff;
4261                         field_table_idx --;
4262                         token = MONO_TOKEN_FIELD_DEF | field_table_idx;
4263                 } else {
4264                         token = mono_image_get_fieldref_token (assembly, f);
4265                 }
4266                 /*g_print ("got token 0x%08x for %s\n", token, f->field->name);*/
4267         } else if (strcmp (klass->name, "MonoArrayMethod") == 0) {
4268                 MonoReflectionArrayMethod *m = (MonoReflectionArrayMethod *)obj;
4269                 token = mono_image_get_array_token (assembly, m);
4270         } else if (strcmp (klass->name, "SignatureHelper") == 0) {
4271                 MonoReflectionSigHelper *s = (MonoReflectionSigHelper*)obj;
4272                 token = MONO_TOKEN_SIGNATURE | mono_image_get_sighelper_token (assembly, s);
4273         } else if (strcmp (klass->name, "EnumBuilder") == 0) {
4274                 MonoReflectionType *tb = (MonoReflectionType *)obj;
4275                 token = mono_metadata_token_from_dor (
4276                         mono_image_typedef_or_ref (assembly, tb->type));
4277         } else {
4278                 g_error ("requested token for %s\n", klass->name);
4279         }
4280
4281         mono_g_hash_table_insert (assembly->tokens, GUINT_TO_POINTER (token), obj);
4282
4283         return token;
4284 }
4285
4286 typedef struct {
4287         guint32 import_lookup_table;
4288         guint32 timestamp;
4289         guint32 forwarder;
4290         guint32 name_rva;
4291         guint32 import_address_table_rva;
4292 } MonoIDT;
4293
4294 typedef struct {
4295         guint32 name_rva;
4296         guint32 flags;
4297 } MonoILT;
4298
4299 static gpointer register_assembly (MonoDomain *domain, MonoReflectionAssembly *res, MonoAssembly *assembly);
4300
4301 static MonoDynamicImage*
4302 create_dynamic_mono_image (MonoDynamicAssembly *assembly, char *assembly_name, char *module_name)
4303 {
4304         static const guchar entrycode [16] = {0xff, 0x25, 0};
4305         MonoDynamicImage *image;
4306         int i;
4307
4308         const char *version = mono_get_runtime_info ()->runtime_version;
4309
4310 #if HAVE_BOEHM_GC
4311         image = GC_MALLOC (sizeof (MonoDynamicImage));
4312 #else
4313         image = g_new0 (MonoDynamicImage, 1);
4314 #endif
4315
4316         /*g_print ("created image %p\n", image);*/
4317         /* keep in sync with image.c */
4318         image->image.name = assembly_name;
4319         image->image.assembly_name = image->image.name; /* they may be different */
4320         image->image.module_name = module_name;
4321         image->image.version = g_strdup (version);
4322         image->image.md_version_major = 1;
4323         image->image.md_version_minor = 1;
4324         image->image.dynamic = TRUE;
4325
4326         image->image.references = g_new0 (MonoAssembly*, 1);
4327         image->image.references [0] = NULL;
4328
4329         mono_image_init (&image->image);
4330
4331         image->token_fixups = mono_g_hash_table_new_type (NULL, NULL, MONO_HASH_KEY_GC);
4332         image->method_to_table_idx = g_hash_table_new (NULL, NULL);
4333         image->field_to_table_idx = g_hash_table_new (NULL, NULL);
4334         image->method_aux_hash = g_hash_table_new (NULL, NULL);
4335         image->handleref = g_hash_table_new (NULL, NULL);
4336         image->tokens = mono_g_hash_table_new_type (NULL, NULL, MONO_HASH_VALUE_GC);
4337         image->typespec = g_hash_table_new ((GHashFunc)mono_metadata_type_hash, (GCompareFunc)mono_metadata_type_equal);
4338         image->typeref = g_hash_table_new ((GHashFunc)mono_metadata_type_hash, (GCompareFunc)mono_metadata_type_equal);
4339         image->blob_cache = g_hash_table_new ((GHashFunc)mono_blob_entry_hash, (GCompareFunc)mono_blob_entry_equal);
4340         image->gen_params = g_ptr_array_new ();
4341
4342         /*g_print ("string heap create for image %p (%s)\n", image, module_name);*/
4343         string_heap_init (&image->sheap);
4344         mono_image_add_stream_data (&image->us, "", 1);
4345         add_to_blob_cached (image, (char*) "", 1, NULL, 0);
4346         /* import tables... */
4347         mono_image_add_stream_data (&image->code, (char*)entrycode, sizeof (entrycode));
4348         image->iat_offset = mono_image_add_stream_zero (&image->code, 8); /* two IAT entries */
4349         image->idt_offset = mono_image_add_stream_zero (&image->code, 2 * sizeof (MonoIDT)); /* two IDT entries */
4350         image->imp_names_offset = mono_image_add_stream_zero (&image->code, 2); /* flags for name entry */
4351         mono_image_add_stream_data (&image->code, "_CorExeMain", 12);
4352         mono_image_add_stream_data (&image->code, "mscoree.dll", 12);
4353         image->ilt_offset = mono_image_add_stream_zero (&image->code, 8); /* two ILT entries */
4354         stream_data_align (&image->code);
4355
4356         image->cli_header_offset = mono_image_add_stream_zero (&image->code, sizeof (MonoCLIHeader));
4357
4358         for (i=0; i < MONO_TABLE_NUM; ++i) {
4359                 image->tables [i].next_idx = 1;
4360                 image->tables [i].columns = table_sizes [i];
4361         }
4362
4363         image->image.assembly = (MonoAssembly*)assembly;
4364         image->run = assembly->run;
4365         image->save = assembly->save;
4366         image->pe_kind = 0x1; /* ILOnly */
4367         image->machine = 0x14c; /* I386 */
4368
4369         return image;
4370 }
4371
4372 /*
4373  * mono_image_basic_init:
4374  * @assembly: an assembly builder object
4375  *
4376  * Create the MonoImage that represents the assembly builder and setup some
4377  * of the helper hash table and the basic metadata streams.
4378  */
4379 void
4380 mono_image_basic_init (MonoReflectionAssemblyBuilder *assemblyb)
4381 {
4382         MonoDynamicAssembly *assembly;
4383         MonoDynamicImage *image;
4384         MonoDomain *domain = mono_object_domain (assemblyb);
4385         
4386         MONO_ARCH_SAVE_REGS;
4387
4388         if (assemblyb->dynamic_assembly)
4389                 return;
4390
4391 #if HAVE_BOEHM_GC
4392         assembly = assemblyb->dynamic_assembly = GC_MALLOC (sizeof (MonoDynamicAssembly));
4393 #else
4394         assembly = assemblyb->dynamic_assembly = g_new0 (MonoDynamicAssembly, 1);
4395 #endif
4396
4397         assembly->assembly.ref_count = 1;
4398         assembly->assembly.dynamic = TRUE;
4399         assembly->assembly.corlib_internal = assemblyb->corlib_internal;
4400         assemblyb->assembly.assembly = (MonoAssembly*)assembly;
4401         assembly->assembly.basedir = mono_string_to_utf8 (assemblyb->dir);
4402         if (assemblyb->culture)
4403                 assembly->assembly.aname.culture = mono_string_to_utf8 (assemblyb->culture);
4404         else
4405                 assembly->assembly.aname.culture = g_strdup ("");
4406
4407         if (assemblyb->version) {
4408                         char *vstr = mono_string_to_utf8 (assemblyb->version);
4409                         char **version = g_strsplit (vstr, ".", 4);
4410                         char **parts = version;
4411                         assembly->assembly.aname.major = atoi (*parts++);
4412                         assembly->assembly.aname.minor = atoi (*parts++);
4413                         assembly->assembly.aname.build = *parts != NULL ? atoi (*parts++) : 0;
4414                         assembly->assembly.aname.revision = *parts != NULL ? atoi (*parts) : 0;
4415
4416                         g_strfreev (version);
4417                         g_free (vstr);
4418         } else {
4419                         assembly->assembly.aname.major = 0;
4420                         assembly->assembly.aname.minor = 0;
4421                         assembly->assembly.aname.build = 0;
4422                         assembly->assembly.aname.revision = 0;
4423         }
4424
4425         assembly->run = assemblyb->access != 2;
4426         assembly->save = assemblyb->access != 1;
4427
4428         image = create_dynamic_mono_image (assembly, mono_string_to_utf8 (assemblyb->name), g_strdup ("RefEmit_YouForgotToDefineAModule"));
4429         image->initial_image = TRUE;
4430         assembly->assembly.aname.name = image->image.name;
4431         assembly->assembly.image = &image->image;
4432
4433         mono_domain_assemblies_lock (domain);
4434         domain->domain_assemblies = g_slist_prepend (domain->domain_assemblies, assembly);
4435         mono_domain_assemblies_unlock (domain);
4436
4437         register_assembly (mono_object_domain (assemblyb), &assemblyb->assembly, &assembly->assembly);
4438         mono_assembly_invoke_load_hook ((MonoAssembly*)assembly);
4439 }
4440
4441 static int
4442 calc_section_size (MonoDynamicImage *assembly)
4443 {
4444         int nsections = 0;
4445
4446         /* alignment constraints */
4447         assembly->code.index += 3;
4448         assembly->code.index &= ~3;
4449         assembly->meta_size += 3;
4450         assembly->meta_size &= ~3;
4451         assembly->resources.index += 3;
4452         assembly->resources.index &= ~3;
4453
4454         assembly->sections [MONO_SECTION_TEXT].size = assembly->meta_size + assembly->code.index + assembly->resources.index + assembly->strong_name_size;
4455         assembly->sections [MONO_SECTION_TEXT].attrs = SECT_FLAGS_HAS_CODE | SECT_FLAGS_MEM_EXECUTE | SECT_FLAGS_MEM_READ;
4456         nsections++;
4457
4458         if (assembly->win32_res) {
4459                 guint32 res_size = (assembly->win32_res_size + 3) & ~3;
4460
4461                 assembly->sections [MONO_SECTION_RSRC].size = res_size;
4462                 assembly->sections [MONO_SECTION_RSRC].attrs = SECT_FLAGS_HAS_INITIALIZED_DATA | SECT_FLAGS_MEM_READ;
4463                 nsections++;
4464         }
4465
4466         assembly->sections [MONO_SECTION_RELOC].size = 12;
4467         assembly->sections [MONO_SECTION_RELOC].attrs = SECT_FLAGS_MEM_READ | SECT_FLAGS_MEM_DISCARDABLE | SECT_FLAGS_HAS_INITIALIZED_DATA;
4468         nsections++;
4469
4470         return nsections;
4471 }
4472
4473 typedef struct {
4474         guint32 id;
4475         guint32 offset;
4476         GSList *children;
4477         MonoReflectionWin32Resource *win32_res; /* Only for leaf nodes */
4478 } ResTreeNode;
4479
4480 static int
4481 resource_tree_compare_by_id (gconstpointer a, gconstpointer b)
4482 {
4483         ResTreeNode *t1 = (ResTreeNode*)a;
4484         ResTreeNode *t2 = (ResTreeNode*)b;
4485
4486         return t1->id - t2->id;
4487 }
4488
4489 /*
4490  * resource_tree_create:
4491  *
4492  *  Organize the resources into a resource tree.
4493  */
4494 static ResTreeNode *
4495 resource_tree_create (MonoArray *win32_resources)
4496 {
4497         ResTreeNode *tree, *res_node, *type_node, *lang_node;
4498         GSList *l;
4499         int i;
4500
4501         tree = g_new0 (ResTreeNode, 1);
4502         
4503         for (i = 0; i < mono_array_length (win32_resources); ++i) {
4504                 MonoReflectionWin32Resource *win32_res =
4505                         (MonoReflectionWin32Resource*)mono_array_addr (win32_resources, MonoReflectionWin32Resource, i);
4506
4507                 /* Create node */
4508
4509                 /* FIXME: BUG: this stores managed references in unmanaged memory */
4510                 lang_node = g_new0 (ResTreeNode, 1);
4511                 lang_node->id = win32_res->lang_id;
4512                 lang_node->win32_res = win32_res;
4513
4514                 /* Create type node if neccesary */
4515                 type_node = NULL;
4516                 for (l = tree->children; l; l = l->next)
4517                         if (((ResTreeNode*)(l->data))->id == win32_res->res_type) {
4518                                 type_node = (ResTreeNode*)l->data;
4519                                 break;
4520                         }
4521
4522                 if (!type_node) {
4523                         type_node = g_new0 (ResTreeNode, 1);
4524                         type_node->id = win32_res->res_type;
4525
4526                         /* 
4527                          * The resource types have to be sorted otherwise
4528                          * Windows Explorer can't display the version information.
4529                          */
4530                         tree->children = g_slist_insert_sorted (tree->children, 
4531                                 type_node, resource_tree_compare_by_id);
4532                 }
4533
4534                 /* Create res node if neccesary */
4535                 res_node = NULL;
4536                 for (l = type_node->children; l; l = l->next)
4537                         if (((ResTreeNode*)(l->data))->id == win32_res->res_id) {
4538                                 res_node = (ResTreeNode*)l->data;
4539                                 break;
4540                         }
4541
4542                 if (!res_node) {
4543                         res_node = g_new0 (ResTreeNode, 1);
4544                         res_node->id = win32_res->res_id;
4545                         type_node->children = g_slist_append (type_node->children, res_node);
4546                 }
4547
4548                 res_node->children = g_slist_append (res_node->children, lang_node);
4549         }
4550
4551         return tree;
4552 }
4553
4554 /*
4555  * resource_tree_encode:
4556  * 
4557  *   Encode the resource tree into the format used in the PE file.
4558  */
4559 static void
4560 resource_tree_encode (ResTreeNode *node, char *begin, char *p, char **endbuf)
4561 {
4562         char *entries;
4563         MonoPEResourceDir dir;
4564         MonoPEResourceDirEntry dir_entry;
4565         MonoPEResourceDataEntry data_entry;
4566         GSList *l;
4567
4568         /*
4569          * For the format of the resource directory, see the article
4570          * "An In-Depth Look into the Win32 Portable Executable File Format" by
4571          * Matt Pietrek
4572          */
4573
4574         memset (&dir, 0, sizeof (dir));
4575         memset (&dir_entry, 0, sizeof (dir_entry));
4576         memset (&data_entry, 0, sizeof (data_entry));
4577
4578         g_assert (sizeof (dir) == 16);
4579         g_assert (sizeof (dir_entry) == 8);
4580         g_assert (sizeof (data_entry) == 16);
4581
4582         node->offset = p - begin;
4583
4584         /* IMAGE_RESOURCE_DIRECTORY */
4585         dir.res_id_entries = GUINT32_TO_LE (g_slist_length (node->children));
4586
4587         memcpy (p, &dir, sizeof (dir));
4588         p += sizeof (dir);
4589
4590         /* Reserve space for entries */
4591         entries = p;
4592         p += sizeof (dir_entry) * dir.res_id_entries;
4593
4594         /* Write children */
4595         for (l = node->children; l; l = l->next) {
4596                 ResTreeNode *child = (ResTreeNode*)l->data;
4597
4598                 if (child->win32_res) {
4599
4600                         child->offset = p - begin;
4601
4602                         /* IMAGE_RESOURCE_DATA_ENTRY */
4603                         data_entry.rde_data_offset = GUINT32_TO_LE (p - begin + sizeof (data_entry));
4604                         data_entry.rde_size = mono_array_length (child->win32_res->res_data);
4605
4606                         memcpy (p, &data_entry, sizeof (data_entry));
4607                         p += sizeof (data_entry);
4608
4609                         memcpy (p, mono_array_addr (child->win32_res->res_data, char, 0), data_entry.rde_size);
4610                         p += data_entry.rde_size;
4611                 } else {
4612                         resource_tree_encode (child, begin, p, &p);
4613                 }
4614         }
4615
4616         /* IMAGE_RESOURCE_ENTRY */
4617         for (l = node->children; l; l = l->next) {
4618                 ResTreeNode *child = (ResTreeNode*)l->data;
4619                 dir_entry.name_offset = GUINT32_TO_LE (child->id);
4620
4621                 dir_entry.is_dir = child->win32_res ? 0 : 1;
4622                 dir_entry.dir_offset = GUINT32_TO_LE (child->offset);
4623
4624                 memcpy (entries, &dir_entry, sizeof (dir_entry));
4625                 entries += sizeof (dir_entry);
4626         }
4627
4628         *endbuf = p;
4629 }
4630
4631 static void
4632 assembly_add_win32_resources (MonoDynamicImage *assembly, MonoReflectionAssemblyBuilder *assemblyb)
4633 {
4634         char *buf;
4635         char *p;
4636         guint32 size, i;
4637         MonoReflectionWin32Resource *win32_res;
4638         ResTreeNode *tree;
4639
4640         if (!assemblyb->win32_resources)
4641                 return;
4642
4643         /*
4644          * Resources are stored in a three level tree inside the PE file.
4645          * - level one contains a node for each type of resource
4646          * - level two contains a node for each resource
4647          * - level three contains a node for each instance of a resource for a
4648          *   specific language.
4649          */
4650
4651         tree = resource_tree_create (assemblyb->win32_resources);
4652
4653         /* Estimate the size of the encoded tree */
4654         size = 0;
4655         for (i = 0; i < mono_array_length (assemblyb->win32_resources); ++i) {
4656                 win32_res = (MonoReflectionWin32Resource*)mono_array_addr (assemblyb->win32_resources, MonoReflectionWin32Resource, i);
4657                 size += mono_array_length (win32_res->res_data);
4658         }
4659         /* Directory structure */
4660         size += mono_array_length (assemblyb->win32_resources) * 256;
4661         p = buf = g_malloc (size);
4662
4663         resource_tree_encode (tree, p, p, &p);
4664
4665         g_assert (p - buf <= size);
4666
4667         assembly->win32_res = g_malloc (p - buf);
4668         assembly->win32_res_size = p - buf;
4669         memcpy (assembly->win32_res, buf, p - buf);
4670
4671         g_free (buf);
4672 }
4673
4674 static void
4675 fixup_resource_directory (char *res_section, char *p, guint32 rva)
4676 {
4677         MonoPEResourceDir *dir = (MonoPEResourceDir*)p;
4678         int i;
4679
4680         p += sizeof (MonoPEResourceDir);
4681         for (i = 0; i < dir->res_named_entries + dir->res_id_entries; ++i) {
4682                 MonoPEResourceDirEntry *dir_entry = (MonoPEResourceDirEntry*)p;
4683                 char *child = res_section + (GUINT32_FROM_LE (dir_entry->dir_offset));
4684                 if (dir_entry->is_dir) {
4685                         fixup_resource_directory (res_section, child, rva);
4686                 } else {
4687                         MonoPEResourceDataEntry *data_entry = (MonoPEResourceDataEntry*)child;
4688                         data_entry->rde_data_offset = GUINT32_TO_LE (GUINT32_FROM_LE (data_entry->rde_data_offset) + rva);
4689                 }
4690
4691                 p += sizeof (MonoPEResourceDirEntry);
4692         }
4693 }
4694
4695 static void
4696 checked_write_file (HANDLE f, gconstpointer buffer, guint32 numbytes)
4697 {
4698         guint32 dummy;
4699         if (!WriteFile (f, buffer, numbytes, &dummy, NULL))
4700                 g_error ("WriteFile returned %d\n", GetLastError ());
4701 }
4702
4703 /*
4704  * mono_image_create_pefile:
4705  * @mb: a module builder object
4706  * 
4707  * This function creates the PE-COFF header, the image sections, the CLI header  * etc. all the data is written in
4708  * assembly->pefile where it can be easily retrieved later in chunks.
4709  */
4710 void
4711 mono_image_create_pefile (MonoReflectionModuleBuilder *mb, HANDLE file) {
4712         MonoMSDOSHeader *msdos;
4713         MonoDotNetHeader *header;
4714         MonoSectionTable *section;
4715         MonoCLIHeader *cli_header;
4716         guint32 size, image_size, virtual_base, text_offset;
4717         guint32 header_start, section_start, file_offset, virtual_offset;
4718         MonoDynamicImage *assembly;
4719         MonoReflectionAssemblyBuilder *assemblyb;
4720         MonoDynamicStream pefile_stream = {0};
4721         MonoDynamicStream *pefile = &pefile_stream;
4722         int i, nsections;
4723         guint32 *rva, value;
4724         guchar *p;
4725         static const unsigned char msheader[] = {
4726                 0x4d, 0x5a, 0x90, 0x00, 0x03, 0x00, 0x00, 0x00,  0x04, 0x00, 0x00, 0x00, 0xff, 0xff, 0x00, 0x00,
4727                 0xb8, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,  0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
4728                 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
4729                 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,  0x00, 0x00, 0x00, 0x00, 0x80, 0x00, 0x00, 0x00,
4730                 0x0e, 0x1f, 0xba, 0x0e, 0x00, 0xb4, 0x09, 0xcd,  0x21, 0xb8, 0x01, 0x4c, 0xcd, 0x21, 0x54, 0x68,
4731                 0x69, 0x73, 0x20, 0x70, 0x72, 0x6f, 0x67, 0x72,  0x61, 0x6d, 0x20, 0x63, 0x61, 0x6e, 0x6e, 0x6f,
4732                 0x74, 0x20, 0x62, 0x65, 0x20, 0x72, 0x75, 0x6e,  0x20, 0x69, 0x6e, 0x20, 0x44, 0x4f, 0x53, 0x20,
4733                 0x6d, 0x6f, 0x64, 0x65, 0x2e, 0x0d, 0x0d, 0x0a,  0x24, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
4734         };
4735
4736         assemblyb = mb->assemblyb;
4737
4738         mono_image_basic_init (assemblyb);
4739         assembly = mb->dynamic_image;
4740
4741         assembly->pe_kind = assemblyb->pe_kind;
4742         assembly->machine = assemblyb->machine;
4743         ((MonoDynamicImage*)assemblyb->dynamic_assembly->assembly.image)->pe_kind = assemblyb->pe_kind;
4744         ((MonoDynamicImage*)assemblyb->dynamic_assembly->assembly.image)->machine = assemblyb->machine;
4745         
4746         mono_image_build_metadata (mb);
4747
4748         if (mb->is_main && assemblyb->resources) {
4749                 int len = mono_array_length (assemblyb->resources);
4750                 for (i = 0; i < len; ++i)
4751                         assembly_add_resource (mb, assembly, (MonoReflectionResource*)mono_array_addr (assemblyb->resources, MonoReflectionResource, i));
4752         }
4753
4754         if (mb->resources) {
4755                 int len = mono_array_length (mb->resources);
4756                 for (i = 0; i < len; ++i)
4757                         assembly_add_resource (mb, assembly, (MonoReflectionResource*)mono_array_addr (mb->resources, MonoReflectionResource, i));
4758         }
4759
4760         build_compressed_metadata (assembly);
4761
4762         if (mb->is_main)
4763                 assembly_add_win32_resources (assembly, assemblyb);
4764
4765         nsections = calc_section_size (assembly);
4766         
4767         /* The DOS header and stub */
4768         g_assert (sizeof (MonoMSDOSHeader) == sizeof (msheader));
4769         mono_image_add_stream_data (pefile, (char*)msheader, sizeof (msheader));
4770
4771         /* the dotnet header */
4772         header_start = mono_image_add_stream_zero (pefile, sizeof (MonoDotNetHeader));
4773
4774         /* the section tables */
4775         section_start = mono_image_add_stream_zero (pefile, sizeof (MonoSectionTable) * nsections);
4776
4777         file_offset = section_start + sizeof (MonoSectionTable) * nsections;
4778         virtual_offset = VIRT_ALIGN;
4779         image_size = 0;
4780
4781         for (i = 0; i < MONO_SECTION_MAX; ++i) {
4782                 if (!assembly->sections [i].size)
4783                         continue;
4784                 /* align offsets */
4785                 file_offset += FILE_ALIGN - 1;
4786                 file_offset &= ~(FILE_ALIGN - 1);
4787                 virtual_offset += VIRT_ALIGN - 1;
4788                 virtual_offset &= ~(VIRT_ALIGN - 1);
4789
4790                 assembly->sections [i].offset = file_offset;
4791                 assembly->sections [i].rva = virtual_offset;
4792
4793                 file_offset += assembly->sections [i].size;
4794                 virtual_offset += assembly->sections [i].size;
4795                 image_size += (assembly->sections [i].size + VIRT_ALIGN - 1) & ~(VIRT_ALIGN - 1);
4796         }
4797
4798         file_offset += FILE_ALIGN - 1;
4799         file_offset &= ~(FILE_ALIGN - 1);
4800
4801         image_size += section_start + sizeof (MonoSectionTable) * nsections;
4802
4803         /* back-patch info */
4804         msdos = (MonoMSDOSHeader*)pefile->data;
4805         msdos->pe_offset = GUINT32_FROM_LE (sizeof (MonoMSDOSHeader));
4806
4807         header = (MonoDotNetHeader*)(pefile->data + header_start);
4808         header->pesig [0] = 'P';
4809         header->pesig [1] = 'E';
4810         
4811         header->coff.coff_machine = GUINT16_FROM_LE (assemblyb->machine);
4812         header->coff.coff_sections = GUINT16_FROM_LE (nsections);
4813         header->coff.coff_time = GUINT32_FROM_LE (time (NULL));
4814         header->coff.coff_opt_header_size = GUINT16_FROM_LE (sizeof (MonoDotNetHeader) - sizeof (MonoCOFFHeader) - 4);
4815         if (assemblyb->pekind == 1) {
4816                 /* it's a dll */
4817                 header->coff.coff_attributes = GUINT16_FROM_LE (0x210e);
4818         } else {
4819                 /* it's an exe */
4820                 header->coff.coff_attributes = GUINT16_FROM_LE (0x010e);
4821         }
4822
4823         virtual_base = 0x400000; /* FIXME: 0x10000000 if a DLL */
4824
4825         header->pe.pe_magic = GUINT16_FROM_LE (0x10B);
4826         header->pe.pe_major = 6;
4827         header->pe.pe_minor = 0;
4828         size = assembly->sections [MONO_SECTION_TEXT].size;
4829         size += FILE_ALIGN - 1;
4830         size &= ~(FILE_ALIGN - 1);
4831         header->pe.pe_code_size = GUINT32_FROM_LE(size);
4832         size = assembly->sections [MONO_SECTION_RSRC].size;
4833         size += FILE_ALIGN - 1;
4834         size &= ~(FILE_ALIGN - 1);
4835         header->pe.pe_data_size = GUINT32_FROM_LE(size);
4836         g_assert (START_TEXT_RVA == assembly->sections [MONO_SECTION_TEXT].rva);
4837         header->pe.pe_rva_code_base = GUINT32_FROM_LE (assembly->sections [MONO_SECTION_TEXT].rva);
4838         header->pe.pe_rva_data_base = GUINT32_FROM_LE (assembly->sections [MONO_SECTION_RSRC].rva);
4839         /* pe_rva_entry_point always at the beginning of the text section */
4840         header->pe.pe_rva_entry_point = GUINT32_FROM_LE (assembly->sections [MONO_SECTION_TEXT].rva);
4841
4842         header->nt.pe_image_base = GUINT32_FROM_LE (virtual_base);
4843         header->nt.pe_section_align = GUINT32_FROM_LE (VIRT_ALIGN);
4844         header->nt.pe_file_alignment = GUINT32_FROM_LE (FILE_ALIGN);
4845         header->nt.pe_os_major = GUINT16_FROM_LE (4);
4846         header->nt.pe_os_minor = GUINT16_FROM_LE (0);
4847         header->nt.pe_subsys_major = GUINT16_FROM_LE (4);
4848         size = section_start;
4849         size += FILE_ALIGN - 1;
4850         size &= ~(FILE_ALIGN - 1);
4851         header->nt.pe_header_size = GUINT32_FROM_LE (size);
4852         size = image_size;
4853         size += VIRT_ALIGN - 1;
4854         size &= ~(VIRT_ALIGN - 1);
4855         header->nt.pe_image_size = GUINT32_FROM_LE (size);
4856
4857         /*
4858         // Translate the PEFileKind value to the value expected by the Windows loader
4859         */
4860         {
4861                 short kind;
4862
4863                 /*
4864                 // PEFileKinds.Dll == 1
4865                 // PEFileKinds.ConsoleApplication == 2
4866                 // PEFileKinds.WindowApplication == 3
4867                 //
4868                 // need to get:
4869                 //     IMAGE_SUBSYSTEM_WINDOWS_GUI 2 // Image runs in the Windows GUI subsystem.
4870                 //     IMAGE_SUBSYSTEM_WINDOWS_CUI 3 // Image runs in the Windows character subsystem.
4871                 */
4872                 if (assemblyb->pekind == 3)
4873                         kind = 2;
4874                 else
4875                         kind = 3;
4876                 
4877                 header->nt.pe_subsys_required = GUINT16_FROM_LE (kind);
4878         }    
4879         header->nt.pe_stack_reserve = GUINT32_FROM_LE (0x00100000);
4880         header->nt.pe_stack_commit = GUINT32_FROM_LE (0x00001000);
4881         header->nt.pe_heap_reserve = GUINT32_FROM_LE (0x00100000);
4882         header->nt.pe_heap_commit = GUINT32_FROM_LE (0x00001000);
4883         header->nt.pe_loader_flags = GUINT32_FROM_LE (0);
4884         header->nt.pe_data_dir_count = GUINT32_FROM_LE (16);
4885
4886         /* fill data directory entries */
4887
4888         header->datadir.pe_resource_table.size = GUINT32_FROM_LE (assembly->sections [MONO_SECTION_RSRC].size);
4889         header->datadir.pe_resource_table.rva = GUINT32_FROM_LE (assembly->sections [MONO_SECTION_RSRC].rva);
4890
4891         header->datadir.pe_reloc_table.size = GUINT32_FROM_LE (assembly->sections [MONO_SECTION_RELOC].size);
4892         header->datadir.pe_reloc_table.rva = GUINT32_FROM_LE (assembly->sections [MONO_SECTION_RELOC].rva);
4893
4894         header->datadir.pe_cli_header.size = GUINT32_FROM_LE (72);
4895         header->datadir.pe_cli_header.rva = GUINT32_FROM_LE (assembly->text_rva + assembly->cli_header_offset);
4896         header->datadir.pe_iat.size = GUINT32_FROM_LE (8);
4897         header->datadir.pe_iat.rva = GUINT32_FROM_LE (assembly->text_rva + assembly->iat_offset);
4898         /* patch entrypoint name */
4899         if (assemblyb->pekind == 1)
4900                 memcpy (assembly->code.data + assembly->imp_names_offset + 2, "_CorDllMain", 12);
4901         else
4902                 memcpy (assembly->code.data + assembly->imp_names_offset + 2, "_CorExeMain", 12);
4903         /* patch imported function RVA name */
4904         rva = (guint32*)(assembly->code.data + assembly->iat_offset);
4905         *rva = GUINT32_FROM_LE (assembly->text_rva + assembly->imp_names_offset);
4906
4907         /* the import table */
4908         header->datadir.pe_import_table.size = GUINT32_FROM_LE (79); /* FIXME: magic number? */
4909         header->datadir.pe_import_table.rva = GUINT32_FROM_LE (assembly->text_rva + assembly->idt_offset);
4910         /* patch imported dll RVA name and other entries in the dir */
4911         rva = (guint32*)(assembly->code.data + assembly->idt_offset + G_STRUCT_OFFSET (MonoIDT, name_rva));
4912         *rva = GUINT32_FROM_LE (assembly->text_rva + assembly->imp_names_offset + 14); /* 14 is hint+strlen+1 of func name */
4913         rva = (guint32*)(assembly->code.data + assembly->idt_offset + G_STRUCT_OFFSET (MonoIDT, import_address_table_rva));
4914         *rva = GUINT32_FROM_LE (assembly->text_rva + assembly->iat_offset);
4915         rva = (guint32*)(assembly->code.data + assembly->idt_offset + G_STRUCT_OFFSET (MonoIDT, import_lookup_table));
4916         *rva = GUINT32_FROM_LE (assembly->text_rva + assembly->ilt_offset);
4917
4918         p = (guchar*)(assembly->code.data + assembly->ilt_offset);
4919         value = (assembly->text_rva + assembly->imp_names_offset);
4920         *p++ = (value) & 0xff;
4921         *p++ = (value >> 8) & (0xff);
4922         *p++ = (value >> 16) & (0xff);
4923         *p++ = (value >> 24) & (0xff);
4924
4925         /* the CLI header info */
4926         cli_header = (MonoCLIHeader*)(assembly->code.data + assembly->cli_header_offset);
4927         cli_header->ch_size = GUINT32_FROM_LE (72);
4928         cli_header->ch_runtime_major = GUINT16_FROM_LE (2);
4929         cli_header->ch_flags = GUINT32_FROM_LE (assemblyb->pe_kind);
4930         if (assemblyb->entry_point) {
4931                 guint32 table_idx = 0;
4932                 if (!strcmp (assemblyb->entry_point->object.vtable->klass->name, "MethodBuilder")) {
4933                         MonoReflectionMethodBuilder *methodb = (MonoReflectionMethodBuilder*)assemblyb->entry_point;
4934                         table_idx = methodb->table_idx;
4935                 } else {
4936                         table_idx = GPOINTER_TO_UINT (g_hash_table_lookup (assembly->method_to_table_idx, assemblyb->entry_point->method));
4937                 }
4938                 cli_header->ch_entry_point = GUINT32_FROM_LE (table_idx | MONO_TOKEN_METHOD_DEF);
4939         } else {
4940                 cli_header->ch_entry_point = GUINT32_FROM_LE (0);
4941         }
4942         /* The embedded managed resources */
4943         text_offset = assembly->text_rva + assembly->code.index;
4944         cli_header->ch_resources.rva = GUINT32_FROM_LE (text_offset);
4945         cli_header->ch_resources.size = GUINT32_FROM_LE (assembly->resources.index);
4946         text_offset += assembly->resources.index;
4947         cli_header->ch_metadata.rva = GUINT32_FROM_LE (text_offset);
4948         cli_header->ch_metadata.size = GUINT32_FROM_LE (assembly->meta_size);
4949         text_offset += assembly->meta_size;
4950         if (assembly->strong_name_size) {
4951                 cli_header->ch_strong_name.rva = GUINT32_FROM_LE (text_offset);
4952                 cli_header->ch_strong_name.size = GUINT32_FROM_LE (assembly->strong_name_size);
4953                 text_offset += assembly->strong_name_size;
4954         }
4955
4956         /* write the section tables and section content */
4957         section = (MonoSectionTable*)(pefile->data + section_start);
4958         for (i = 0; i < MONO_SECTION_MAX; ++i) {
4959                 static const char section_names [][7] = {
4960                         ".text", ".rsrc", ".reloc"
4961                 };
4962                 if (!assembly->sections [i].size)
4963                         continue;
4964                 strcpy (section->st_name, section_names [i]);
4965                 /*g_print ("output section %s (%d), size: %d\n", section->st_name, i, assembly->sections [i].size);*/
4966                 section->st_virtual_address = GUINT32_FROM_LE (assembly->sections [i].rva);
4967                 section->st_virtual_size = GUINT32_FROM_LE (assembly->sections [i].size);
4968                 section->st_raw_data_size = GUINT32_FROM_LE (GUINT32_TO_LE (section->st_virtual_size) + (FILE_ALIGN - 1));
4969                 section->st_raw_data_size &= GUINT32_FROM_LE (~(FILE_ALIGN - 1));
4970                 section->st_raw_data_ptr = GUINT32_FROM_LE (assembly->sections [i].offset);
4971                 section->st_flags = GUINT32_FROM_LE (assembly->sections [i].attrs);
4972                 section ++;
4973         }
4974         
4975         checked_write_file (file, pefile->data, pefile->index);
4976         
4977         mono_dynamic_stream_reset (pefile);
4978         
4979         for (i = 0; i < MONO_SECTION_MAX; ++i) {
4980                 if (!assembly->sections [i].size)
4981                         continue;
4982                 
4983                 if (SetFilePointer (file, assembly->sections [i].offset, NULL, FILE_BEGIN) == INVALID_SET_FILE_POINTER)
4984                         g_error ("SetFilePointer returned %d\n", GetLastError ());
4985                 
4986                 switch (i) {
4987                 case MONO_SECTION_TEXT:
4988                         /* patch entry point */
4989                         p = (guchar*)(assembly->code.data + 2);
4990                         value = (virtual_base + assembly->text_rva + assembly->iat_offset);
4991                         *p++ = (value) & 0xff;
4992                         *p++ = (value >> 8) & 0xff;
4993                         *p++ = (value >> 16) & 0xff;
4994                         *p++ = (value >> 24) & 0xff;
4995                 
4996                         checked_write_file (file, assembly->code.data, assembly->code.index);
4997                         checked_write_file (file, assembly->resources.data, assembly->resources.index);
4998                         checked_write_file (file, assembly->image.raw_metadata, assembly->meta_size);
4999                         checked_write_file (file, assembly->strong_name, assembly->strong_name_size);
5000                                 
5001
5002                         g_free (assembly->image.raw_metadata);
5003                         break;
5004                 case MONO_SECTION_RELOC: {
5005                         struct {
5006                                 guint32 page_rva;
5007                                 guint32 block_size;
5008                                 guint16 type_and_offset;
5009                                 guint16 term;
5010                         } reloc;
5011                         
5012                         g_assert (sizeof (reloc) == 12);
5013                         
5014                         reloc.page_rva = GUINT32_FROM_LE (assembly->text_rva);
5015                         reloc.block_size = GUINT32_FROM_LE (12);
5016                         
5017                         /* 
5018                          * the entrypoint is always at the start of the text section 
5019                          * 3 is IMAGE_REL_BASED_HIGHLOW
5020                          * 2 is patch_size_rva - text_rva
5021                          */
5022                         reloc.type_and_offset = GUINT16_FROM_LE ((3 << 12) + (2));
5023                         reloc.term = 0;
5024                         
5025                         checked_write_file (file, &reloc, sizeof (reloc));
5026                         
5027                         break;
5028                 }
5029                 case MONO_SECTION_RSRC:
5030                         if (assembly->win32_res) {
5031
5032                                 /* Fixup the offsets in the IMAGE_RESOURCE_DATA_ENTRY structures */
5033                                 fixup_resource_directory (assembly->win32_res, assembly->win32_res, assembly->sections [i].rva);
5034                                 checked_write_file (file, assembly->win32_res, assembly->win32_res_size);
5035                         }
5036                         break;
5037                 default:
5038                         g_assert_not_reached ();
5039                 }
5040         }
5041         
5042         /* check that the file is properly padded */
5043         if (SetFilePointer (file, file_offset, NULL, FILE_BEGIN) == INVALID_SET_FILE_POINTER)
5044                 g_error ("SetFilePointer returned %d\n", GetLastError ());
5045         if (! SetEndOfFile (file))
5046                 g_error ("SetEndOfFile returned %d\n", GetLastError ());
5047         
5048         mono_dynamic_stream_reset (&assembly->code);
5049         mono_dynamic_stream_reset (&assembly->us);
5050         mono_dynamic_stream_reset (&assembly->blob);
5051         mono_dynamic_stream_reset (&assembly->guid);
5052         mono_dynamic_stream_reset (&assembly->sheap);
5053
5054         g_hash_table_foreach (assembly->blob_cache, (GHFunc)g_free, NULL);
5055         g_hash_table_destroy (assembly->blob_cache);
5056         assembly->blob_cache = NULL;
5057 }
5058
5059 MonoReflectionModule *
5060 mono_image_load_module_dynamic (MonoReflectionAssemblyBuilder *ab, MonoString *fileName)
5061 {
5062         char *name;
5063         MonoImage *image;
5064         MonoImageOpenStatus status;
5065         MonoDynamicAssembly *assembly;
5066         guint32 module_count;
5067         MonoImage **new_modules;
5068         gboolean *new_modules_loaded;
5069         
5070         name = mono_string_to_utf8 (fileName);
5071
5072         image = mono_image_open (name, &status);
5073         if (!image) {
5074                 MonoException *exc;
5075                 if (status == MONO_IMAGE_ERROR_ERRNO)
5076                         exc = mono_get_exception_file_not_found (fileName);
5077                 else
5078                         exc = mono_get_exception_bad_image_format (name);
5079                 g_free (name);
5080                 mono_raise_exception (exc);
5081         }
5082
5083         g_free (name);
5084
5085         assembly = ab->dynamic_assembly;
5086         image->assembly = (MonoAssembly*)assembly;
5087
5088         module_count = image->assembly->image->module_count;
5089         new_modules = g_new0 (MonoImage *, module_count + 1);
5090         new_modules_loaded = g_new0 (gboolean, module_count + 1);
5091
5092         if (image->assembly->image->modules)
5093                 memcpy (new_modules, image->assembly->image->modules, module_count * sizeof (MonoImage *));
5094         if (image->assembly->image->modules_loaded)
5095                 memcpy (new_modules_loaded, image->assembly->image->modules_loaded, module_count * sizeof (gboolean));
5096         new_modules [module_count] = image;
5097         new_modules_loaded [module_count] = TRUE;
5098         mono_image_addref (image);
5099
5100         g_free (image->assembly->image->modules);
5101         image->assembly->image->modules = new_modules;
5102         image->assembly->image->modules_loaded = new_modules_loaded;
5103         image->assembly->image->module_count ++;
5104
5105         mono_assembly_load_references (image, &status);
5106         if (status) {
5107                 mono_image_close (image);
5108                 mono_raise_exception (mono_get_exception_file_not_found (fileName));
5109         }
5110
5111         return mono_module_get_object (mono_domain_get (), image);
5112 }
5113
5114 /*
5115  * We need to return always the same object for MethodInfo, FieldInfo etc..
5116  * but we need to consider the reflected type.
5117  * type uses a different hash, since it uses custom hash/equal functions.
5118  */
5119
5120 typedef struct {
5121         gpointer item;
5122         MonoClass *refclass;
5123 } ReflectedEntry;
5124
5125 static gboolean
5126 reflected_equal (gconstpointer a, gconstpointer b) {
5127         const ReflectedEntry *ea = a;
5128         const ReflectedEntry *eb = b;
5129
5130         return (ea->item == eb->item) && (ea->refclass == eb->refclass);
5131 }
5132
5133 static guint
5134 reflected_hash (gconstpointer a) {
5135         const ReflectedEntry *ea = a;
5136         return mono_aligned_addr_hash (ea->item);
5137 }
5138
5139 #define CHECK_OBJECT(t,p,k)     \
5140         do {    \
5141                 t _obj; \
5142                 ReflectedEntry e;       \
5143                 e.item = (p);   \
5144                 e.refclass = (k);       \
5145                 mono_domain_lock (domain);      \
5146                 if (!domain->refobject_hash)    \
5147                         domain->refobject_hash = mono_g_hash_table_new_type (reflected_hash, reflected_equal, MONO_HASH_VALUE_GC);      \
5148                 if ((_obj = mono_g_hash_table_lookup (domain->refobject_hash, &e))) {   \
5149                         mono_domain_unlock (domain);    \
5150                         return _obj;    \
5151                 }       \
5152         mono_domain_unlock (domain); \
5153         } while (0)
5154
5155 #if HAVE_BOEHM_GC
5156 #define ALLOC_REFENTRY GC_MALLOC (sizeof (ReflectedEntry))
5157 #elif HAVE_SGEN_GC
5158 #define ALLOC_REFENTRY mono_gc_alloc_fixed (sizeof (ReflectedEntry), NULL)
5159 #else
5160 #define ALLOC_REFENTRY mono_mempool_alloc (domain->mp, sizeof (ReflectedEntry))
5161 #endif
5162
5163 #define CACHE_OBJECT(t,p,o,k)   \
5164         do {    \
5165                 t _obj; \
5166         ReflectedEntry pe; \
5167         pe.item = (p); \
5168         pe.refclass = (k); \
5169         mono_domain_lock (domain); \
5170                 if (!domain->refobject_hash)    \
5171                         domain->refobject_hash = mono_g_hash_table_new_type (reflected_hash, reflected_equal, MONO_HASH_VALUE_GC);      \
5172         _obj = mono_g_hash_table_lookup (domain->refobject_hash, &pe); \
5173         if (!_obj) { \
5174                     ReflectedEntry *e = ALLOC_REFENTRY;         \
5175                     e->item = (p);      \
5176                     e->refclass = (k);  \
5177                     mono_g_hash_table_insert (domain->refobject_hash, e,o);     \
5178             _obj = o; \
5179         } \
5180                 mono_domain_unlock (domain);    \
5181         return _obj; \
5182         } while (0)
5183
5184 static gpointer
5185 register_assembly (MonoDomain *domain, MonoReflectionAssembly *res, MonoAssembly *assembly)
5186 {
5187         CACHE_OBJECT (MonoReflectionAssembly *, assembly, res, NULL);
5188 }
5189
5190 static gpointer
5191 register_module (MonoDomain *domain, MonoReflectionModuleBuilder *res, MonoDynamicImage *module)
5192 {
5193         CACHE_OBJECT (MonoReflectionModuleBuilder *, module, res, NULL);
5194 }
5195
5196 void
5197 mono_image_module_basic_init (MonoReflectionModuleBuilder *moduleb)
5198 {
5199         MonoDynamicImage *image = moduleb->dynamic_image;
5200         MonoReflectionAssemblyBuilder *ab = moduleb->assemblyb;
5201         if (!image) {
5202                 int module_count;
5203                 MonoImage **new_modules;
5204                 MonoImage *ass;
5205                 /*
5206                  * FIXME: we already created an image in mono_image_basic_init (), but
5207                  * we don't know which module it belongs to, since that is only 
5208                  * determined at assembly save time.
5209                  */
5210                 /*image = (MonoDynamicImage*)ab->dynamic_assembly->assembly.image; */
5211                 image = create_dynamic_mono_image (ab->dynamic_assembly, mono_string_to_utf8 (ab->name), mono_string_to_utf8 (moduleb->module.fqname));
5212
5213                 moduleb->module.image = &image->image;
5214                 moduleb->dynamic_image = image;
5215                 register_module (mono_object_domain (moduleb), moduleb, image);
5216
5217                 /* register the module with the assembly */
5218                 ass = ab->dynamic_assembly->assembly.image;
5219                 module_count = ass->module_count;
5220                 new_modules = g_new0 (MonoImage *, module_count + 1);
5221
5222                 if (ass->modules)
5223                         memcpy (new_modules, ass->modules, module_count * sizeof (MonoImage *));
5224                 new_modules [module_count] = &image->image;
5225                 mono_image_addref (&image->image);
5226
5227                 g_free (ass->modules);
5228                 ass->modules = new_modules;
5229                 ass->module_count ++;
5230         }
5231 }
5232
5233 /*
5234  * mono_assembly_get_object:
5235  * @domain: an app domain
5236  * @assembly: an assembly
5237  *
5238  * Return an System.Reflection.Assembly object representing the MonoAssembly @assembly.
5239  */
5240 MonoReflectionAssembly*
5241 mono_assembly_get_object (MonoDomain *domain, MonoAssembly *assembly)
5242 {
5243         static MonoClass *System_Reflection_Assembly;
5244         MonoReflectionAssembly *res;
5245         
5246         CHECK_OBJECT (MonoReflectionAssembly *, assembly, NULL);
5247         if (!System_Reflection_Assembly)
5248                 System_Reflection_Assembly = mono_class_from_name (
5249                         mono_defaults.corlib, "System.Reflection", "Assembly");
5250         res = (MonoReflectionAssembly *)mono_object_new (domain, System_Reflection_Assembly);
5251         res->assembly = assembly;
5252
5253         CACHE_OBJECT (MonoReflectionAssembly *, assembly, res, NULL);
5254 }
5255
5256
5257
5258 MonoReflectionModule*   
5259 mono_module_get_object   (MonoDomain *domain, MonoImage *image)
5260 {
5261         static MonoClass *System_Reflection_Module;
5262         MonoReflectionModule *res;
5263         char* basename;
5264         
5265         CHECK_OBJECT (MonoReflectionModule *, image, NULL);
5266         if (!System_Reflection_Module)
5267                 System_Reflection_Module = mono_class_from_name (
5268                         mono_defaults.corlib, "System.Reflection", "Module");
5269         res = (MonoReflectionModule *)mono_object_new (domain, System_Reflection_Module);
5270
5271         res->image = image;
5272         MONO_OBJECT_SETREF (res, assembly, (MonoReflectionAssembly *) mono_assembly_get_object(domain, image->assembly));
5273
5274         MONO_OBJECT_SETREF (res, fqname, mono_string_new (domain, image->name));
5275         basename = g_path_get_basename (image->name);
5276         MONO_OBJECT_SETREF (res, name, mono_string_new (domain, basename));
5277         MONO_OBJECT_SETREF (res, scopename, mono_string_new (domain, image->module_name));
5278         
5279         g_free (basename);
5280
5281         if (image->assembly->image == image) {
5282                 res->token = mono_metadata_make_token (MONO_TABLE_MODULE, 1);
5283         } else {
5284                 int i;
5285                 res->token = 0;
5286                 if (image->assembly->image->modules) {
5287                         for (i = 0; i < image->assembly->image->module_count; i++) {
5288                                 if (image->assembly->image->modules [i] == image)
5289                                         res->token = mono_metadata_make_token (MONO_TABLE_MODULEREF, i + 1);
5290                         }
5291                         g_assert (res->token);
5292                 }
5293         }
5294
5295         CACHE_OBJECT (MonoReflectionModule *, image, res, NULL);
5296 }
5297
5298 MonoReflectionModule*   
5299 mono_module_file_get_object (MonoDomain *domain, MonoImage *image, int table_index)
5300 {
5301         static MonoClass *System_Reflection_Module;
5302         MonoReflectionModule *res;
5303         MonoTableInfo *table;
5304         guint32 cols [MONO_FILE_SIZE];
5305         const char *name;
5306         guint32 i, name_idx;
5307         const char *val;
5308         
5309         if (!System_Reflection_Module)
5310                 System_Reflection_Module = mono_class_from_name (
5311                         mono_defaults.corlib, "System.Reflection", "Module");
5312         res = (MonoReflectionModule *)mono_object_new (domain, System_Reflection_Module);
5313
5314         table = &image->tables [MONO_TABLE_FILE];
5315         g_assert (table_index < table->rows);
5316         mono_metadata_decode_row (table, table_index, cols, MONO_FILE_SIZE);
5317
5318         res->image = NULL;
5319         MONO_OBJECT_SETREF (res, assembly, (MonoReflectionAssembly *) mono_assembly_get_object(domain, image->assembly));
5320         name = mono_metadata_string_heap (image, cols [MONO_FILE_NAME]);
5321
5322         /* Check whenever the row has a corresponding row in the moduleref table */
5323         table = &image->tables [MONO_TABLE_MODULEREF];
5324         for (i = 0; i < table->rows; ++i) {
5325                 name_idx = mono_metadata_decode_row_col (table, i, MONO_MODULEREF_NAME);
5326                 val = mono_metadata_string_heap (image, name_idx);
5327                 if (strcmp (val, name) == 0)
5328                         res->image = image->modules [i];
5329         }
5330
5331         MONO_OBJECT_SETREF (res, fqname, mono_string_new (domain, name));
5332         MONO_OBJECT_SETREF (res, name, mono_string_new (domain, name));
5333         MONO_OBJECT_SETREF (res, scopename, mono_string_new (domain, name));
5334         res->is_resource = cols [MONO_FILE_FLAGS] && FILE_CONTAINS_NO_METADATA;
5335         res->token = mono_metadata_make_token (MONO_TABLE_FILE, table_index + 1);
5336
5337         return res;
5338 }
5339
5340 static gboolean
5341 mymono_metadata_type_equal (MonoType *t1, MonoType *t2)
5342 {
5343         if ((t1->type != t2->type) ||
5344             (t1->byref != t2->byref))
5345                 return FALSE;
5346
5347         switch (t1->type) {
5348         case MONO_TYPE_VOID:
5349         case MONO_TYPE_BOOLEAN:
5350         case MONO_TYPE_CHAR:
5351         case MONO_TYPE_I1:
5352         case MONO_TYPE_U1:
5353         case MONO_TYPE_I2:
5354         case MONO_TYPE_U2:
5355         case MONO_TYPE_I4:
5356         case MONO_TYPE_U4:
5357         case MONO_TYPE_I8:
5358         case MONO_TYPE_U8:
5359         case MONO_TYPE_R4:
5360         case MONO_TYPE_R8:
5361         case MONO_TYPE_STRING:
5362         case MONO_TYPE_I:
5363         case MONO_TYPE_U:
5364         case MONO_TYPE_OBJECT:
5365         case MONO_TYPE_TYPEDBYREF:
5366                 return TRUE;
5367         case MONO_TYPE_VALUETYPE:
5368         case MONO_TYPE_CLASS:
5369         case MONO_TYPE_SZARRAY:
5370                 return t1->data.klass == t2->data.klass;
5371         case MONO_TYPE_PTR:
5372                 return mymono_metadata_type_equal (t1->data.type, t2->data.type);
5373         case MONO_TYPE_ARRAY:
5374                 if (t1->data.array->rank != t2->data.array->rank)
5375                         return FALSE;
5376                 return t1->data.array->eklass == t2->data.array->eklass;
5377         case MONO_TYPE_GENERICINST: {
5378                 int i;
5379                 MonoGenericInst *i1 = t1->data.generic_class->context.class_inst;
5380                 MonoGenericInst *i2 = t2->data.generic_class->context.class_inst;
5381                 if (i1->type_argc != i2->type_argc)
5382                         return FALSE;
5383                 if (!mono_metadata_type_equal (&t1->data.generic_class->container_class->byval_arg,
5384                                                &t2->data.generic_class->container_class->byval_arg))
5385                         return FALSE;
5386                 /* FIXME: we should probably just compare the instance pointers directly.  */
5387                 for (i = 0; i < i1->type_argc; ++i) {
5388                         if (!mono_metadata_type_equal (i1->type_argv [i], i2->type_argv [i]))
5389                                 return FALSE;
5390                 }
5391                 return TRUE;
5392         }
5393         case MONO_TYPE_VAR:
5394         case MONO_TYPE_MVAR:
5395                 return t1->data.generic_param == t2->data.generic_param;
5396         default:
5397                 g_error ("implement type compare for %0x!", t1->type);
5398                 return FALSE;
5399         }
5400
5401         return FALSE;
5402 }
5403
5404 static guint
5405 mymono_metadata_type_hash (MonoType *t1)
5406 {
5407         guint hash;
5408
5409         hash = t1->type;
5410
5411         hash |= t1->byref << 6; /* do not collide with t1->type values */
5412         switch (t1->type) {
5413         case MONO_TYPE_VALUETYPE:
5414         case MONO_TYPE_CLASS:
5415         case MONO_TYPE_SZARRAY:
5416                 /* check if the distribution is good enough */
5417                 return ((hash << 5) - hash) ^ g_str_hash (t1->data.klass->name);
5418         case MONO_TYPE_PTR:
5419                 return ((hash << 5) - hash) ^ mymono_metadata_type_hash (t1->data.type);
5420         case MONO_TYPE_GENERICINST: {
5421                 int i;
5422                 MonoGenericInst *inst = t1->data.generic_class->context.class_inst;
5423                 hash += g_str_hash (t1->data.generic_class->container_class->name);
5424                 hash *= 13;
5425                 for (i = 0; i < inst->type_argc; ++i) {
5426                         hash += mymono_metadata_type_hash (inst->type_argv [i]);
5427                         hash *= 13;
5428                 }
5429                 return hash;
5430         }
5431         }
5432         return hash;
5433 }
5434
5435 static MonoReflectionGenericClass*
5436 mono_generic_class_get_object (MonoDomain *domain, MonoType *geninst)
5437 {
5438         static MonoClass *System_Reflection_MonoGenericClass;
5439         MonoReflectionGenericClass *res;
5440         MonoClass *klass, *gklass;
5441
5442         if (!System_Reflection_MonoGenericClass) {
5443                 System_Reflection_MonoGenericClass = mono_class_from_name (
5444                         mono_defaults.corlib, "System.Reflection", "MonoGenericClass");
5445                 g_assert (System_Reflection_MonoGenericClass);
5446         }
5447
5448         klass = mono_class_from_mono_type (geninst);
5449         gklass = klass->generic_class->container_class;
5450
5451         mono_class_init (klass);
5452
5453 #ifdef HAVE_SGEN_GC
5454         /* FIXME: allow unpinned later */
5455         res = (MonoReflectionGenericClass *) mono_gc_alloc_pinned_obj (mono_class_vtable (domain, System_Reflection_MonoGenericClass), mono_class_instance_size (System_Reflection_MonoGenericClass));
5456 #else
5457         res = (MonoReflectionGenericClass *) mono_object_new (domain, System_Reflection_MonoGenericClass);
5458 #endif
5459
5460         res->type.type = geninst;
5461         if (gklass->wastypebuilder && gklass->reflection_info)
5462                 MONO_OBJECT_SETREF (res, generic_type, gklass->reflection_info);
5463         else
5464                 MONO_OBJECT_SETREF (res, generic_type, mono_type_get_object (domain, &gklass->byval_arg));
5465
5466         return res;
5467 }
5468
5469 static gboolean
5470 verify_safe_for_managed_space (MonoType *type)
5471 {
5472         switch (type->type) {
5473 #ifdef DEBUG_HARDER
5474         case MONO_TYPE_ARRAY:
5475                 return verify_safe_for_managed_space (&type->data.array->eklass->byval_arg);
5476         case MONO_TYPE_PTR:
5477                 return verify_safe_for_managed_space (type->data.type);
5478         case MONO_TYPE_SZARRAY:
5479                 return verify_safe_for_managed_space (&type->data.klass->byval_arg);
5480         case MONO_TYPE_GENERICINST: {
5481                 MonoGenericInst *inst = type->data.generic_class->inst;
5482                 int i;
5483                 if (!inst->is_open)
5484                         break;
5485                 for (i = 0; i < inst->type_argc; ++i)
5486                         if (!verify_safe_for_managed_space (inst->type_argv [i]))
5487                                 return FALSE;
5488                 break;
5489         }
5490 #endif
5491         case MONO_TYPE_VAR:
5492         case MONO_TYPE_MVAR:
5493                 return TRUE;
5494         }
5495         return TRUE;
5496 }
5497
5498 /*
5499  * mono_type_get_object:
5500  * @domain: an app domain
5501  * @type: a type
5502  *
5503  * Return an System.MonoType object representing the type @type.
5504  */
5505 MonoReflectionType*
5506 mono_type_get_object (MonoDomain *domain, MonoType *type)
5507 {
5508         MonoReflectionType *res;
5509         MonoClass *klass = mono_class_from_mono_type (type);
5510
5511         mono_domain_lock (domain);
5512         if (!domain->type_hash)
5513                 domain->type_hash = mono_g_hash_table_new_type ((GHashFunc)mymono_metadata_type_hash, 
5514                                 (GCompareFunc)mymono_metadata_type_equal, MONO_HASH_VALUE_GC);
5515         if ((res = mono_g_hash_table_lookup (domain->type_hash, type))) {
5516                 mono_domain_unlock (domain);
5517                 return res;
5518         }
5519         if ((type->type == MONO_TYPE_GENERICINST) && type->data.generic_class->is_dynamic) {
5520                 res = (MonoReflectionType *)mono_generic_class_get_object (domain, type);
5521                 mono_g_hash_table_insert (domain->type_hash, type, res);
5522                 mono_domain_unlock (domain);
5523                 return res;
5524         }
5525
5526         if (!verify_safe_for_managed_space (type)) {
5527                 mono_domain_unlock (domain);
5528                 mono_raise_exception (mono_get_exception_invalid_operation ("This type cannot be propagated to managed space"));
5529         }
5530
5531         if (klass->reflection_info && !klass->wastypebuilder) {
5532                 /* g_assert_not_reached (); */
5533                 /* should this be considered an error condition? */
5534                 if (!type->byref) {
5535                         mono_domain_unlock (domain);
5536                         return klass->reflection_info;
5537                 }
5538         }
5539         mono_class_init (klass);
5540 #ifdef HAVE_SGEN_GC
5541         res = (MonoReflectionType *)mono_gc_alloc_pinned_obj (mono_class_vtable (domain, mono_defaults.monotype_class), mono_class_instance_size (mono_defaults.monotype_class));
5542 #else
5543         res = (MonoReflectionType *)mono_object_new (domain, mono_defaults.monotype_class);
5544 #endif
5545         res->type = type;
5546         mono_g_hash_table_insert (domain->type_hash, type, res);
5547         mono_domain_unlock (domain);
5548         return res;
5549 }
5550
5551 /*
5552  * mono_method_get_object:
5553  * @domain: an app domain
5554  * @method: a method
5555  * @refclass: the reflected type (can be NULL)
5556  *
5557  * Return an System.Reflection.MonoMethod object representing the method @method.
5558  */
5559 MonoReflectionMethod*
5560 mono_method_get_object (MonoDomain *domain, MonoMethod *method, MonoClass *refclass)
5561 {
5562         /*
5563          * We use the same C representation for methods and constructors, but the type 
5564          * name in C# is different.
5565          */
5566         static MonoClass *System_Reflection_MonoMethod = NULL;
5567         static MonoClass *System_Reflection_MonoCMethod = NULL;
5568         static MonoClass *System_Reflection_MonoGenericMethod = NULL;
5569         static MonoClass *System_Reflection_MonoGenericCMethod = NULL;
5570         MonoClass *klass;
5571         MonoReflectionMethod *ret;
5572
5573         if (method->is_inflated) {
5574                 MonoReflectionGenericMethod *gret;
5575
5576                 refclass = method->klass;
5577                 CHECK_OBJECT (MonoReflectionMethod *, method, refclass);
5578                 if ((*method->name == '.') && (!strcmp (method->name, ".ctor") || !strcmp (method->name, ".cctor"))) {
5579                         if (!System_Reflection_MonoGenericCMethod)
5580                                 System_Reflection_MonoGenericCMethod = mono_class_from_name (mono_defaults.corlib, "System.Reflection", "MonoGenericCMethod");
5581                         klass = System_Reflection_MonoGenericCMethod;
5582                 } else {
5583                         if (!System_Reflection_MonoGenericMethod)
5584                                 System_Reflection_MonoGenericMethod = mono_class_from_name (mono_defaults.corlib, "System.Reflection", "MonoGenericMethod");
5585                         klass = System_Reflection_MonoGenericMethod;
5586                 }
5587                 gret = (MonoReflectionGenericMethod*)mono_object_new (domain, klass);
5588                 gret->method.method = method;
5589                 MONO_OBJECT_SETREF (gret, method.name, mono_string_new (domain, method->name));
5590                 MONO_OBJECT_SETREF (gret, method.reftype, mono_type_get_object (domain, &refclass->byval_arg));
5591                 CACHE_OBJECT (MonoReflectionMethod *, method, (MonoReflectionMethod*)gret, refclass);
5592         }
5593
5594         if (!refclass)
5595                 refclass = method->klass;
5596
5597         CHECK_OBJECT (MonoReflectionMethod *, method, refclass);
5598         if (*method->name == '.' && (strcmp (method->name, ".ctor") == 0 || strcmp (method->name, ".cctor") == 0)) {
5599                 if (!System_Reflection_MonoCMethod)
5600                         System_Reflection_MonoCMethod = mono_class_from_name (mono_defaults.corlib, "System.Reflection", "MonoCMethod");
5601                 klass = System_Reflection_MonoCMethod;
5602         }
5603         else {
5604                 if (!System_Reflection_MonoMethod)
5605                         System_Reflection_MonoMethod = mono_class_from_name (mono_defaults.corlib, "System.Reflection", "MonoMethod");
5606                 klass = System_Reflection_MonoMethod;
5607         }
5608         ret = (MonoReflectionMethod*)mono_object_new (domain, klass);
5609         ret->method = method;
5610         MONO_OBJECT_SETREF (ret, reftype, mono_type_get_object (domain, &refclass->byval_arg));
5611         CACHE_OBJECT (MonoReflectionMethod *, method, ret, refclass);
5612 }
5613
5614 /*
5615  * mono_field_get_object:
5616  * @domain: an app domain
5617  * @klass: a type
5618  * @field: a field
5619  *
5620  * Return an System.Reflection.MonoField object representing the field @field
5621  * in class @klass.
5622  */
5623 MonoReflectionField*
5624 mono_field_get_object (MonoDomain *domain, MonoClass *klass, MonoClassField *field)
5625 {
5626         MonoReflectionField *res;
5627         static MonoClass *monofield_klass;
5628
5629         CHECK_OBJECT (MonoReflectionField *, field, klass);
5630         if (!monofield_klass)
5631                 monofield_klass = mono_class_from_name (mono_defaults.corlib, "System.Reflection", "MonoField");
5632         res = (MonoReflectionField *)mono_object_new (domain, monofield_klass);
5633         res->klass = klass;
5634         res->field = field;
5635         MONO_OBJECT_SETREF (res, name, mono_string_new (domain, field->name));
5636         if (field->generic_info)
5637                 res->attrs = field->generic_info->generic_type->attrs;
5638         else
5639                 res->attrs = field->type->attrs;
5640         MONO_OBJECT_SETREF (res, type, mono_type_get_object (domain, field->type));
5641         CACHE_OBJECT (MonoReflectionField *, field, res, klass);
5642 }
5643
5644 /*
5645  * mono_property_get_object:
5646  * @domain: an app domain
5647  * @klass: a type
5648  * @property: a property
5649  *
5650  * Return an System.Reflection.MonoProperty object representing the property @property
5651  * in class @klass.
5652  */
5653 MonoReflectionProperty*
5654 mono_property_get_object (MonoDomain *domain, MonoClass *klass, MonoProperty *property)
5655 {
5656         MonoReflectionProperty *res;
5657         static MonoClass *monoproperty_klass;
5658
5659         CHECK_OBJECT (MonoReflectionProperty *, property, klass);
5660         if (!monoproperty_klass)
5661                 monoproperty_klass = mono_class_from_name (mono_defaults.corlib, "System.Reflection", "MonoProperty");
5662         res = (MonoReflectionProperty *)mono_object_new (domain, monoproperty_klass);
5663         res->klass = klass;
5664         res->property = property;
5665         CACHE_OBJECT (MonoReflectionProperty *, property, res, klass);
5666 }
5667
5668 /*
5669  * mono_event_get_object:
5670  * @domain: an app domain
5671  * @klass: a type
5672  * @event: a event
5673  *
5674  * Return an System.Reflection.MonoEvent object representing the event @event
5675  * in class @klass.
5676  */
5677 MonoReflectionEvent*
5678 mono_event_get_object (MonoDomain *domain, MonoClass *klass, MonoEvent *event)
5679 {
5680         MonoReflectionEvent *res;
5681         static MonoClass *monoevent_klass;
5682
5683         CHECK_OBJECT (MonoReflectionEvent *, event, klass);
5684         if (!monoevent_klass)
5685                 monoevent_klass = mono_class_from_name (mono_defaults.corlib, "System.Reflection", "MonoEvent");
5686         res = (MonoReflectionEvent *)mono_object_new (domain, monoevent_klass);
5687         res->klass = klass;
5688         res->event = event;
5689         CACHE_OBJECT (MonoReflectionEvent *, event, res, klass);
5690 }
5691
5692 /*
5693  * mono_param_get_objects:
5694  * @domain: an app domain
5695  * @method: a method
5696  *
5697  * Return an System.Reflection.ParameterInfo array object representing the parameters
5698  * in the method @method.
5699  */
5700 MonoArray*
5701 mono_param_get_objects (MonoDomain *domain, MonoMethod *method)
5702 {
5703         static MonoClass *System_Reflection_ParameterInfo;
5704         MonoArray *res = NULL;
5705         MonoReflectionMethod *member = NULL;
5706         MonoReflectionParameter *param = NULL;
5707         char **names, **blobs = NULL;
5708         guint32 *types = NULL;
5709         MonoType *type = NULL;
5710         MonoObject *dbnull = mono_get_dbnull_object (domain);
5711         MonoMarshalSpec **mspecs;
5712         MonoMethodSignature *sig;
5713         int i;
5714
5715         if (!System_Reflection_ParameterInfo)
5716                 System_Reflection_ParameterInfo = mono_class_from_name (
5717                         mono_defaults.corlib, "System.Reflection", "ParameterInfo");
5718         
5719         if (!mono_method_signature (method)->param_count)
5720                 return mono_array_new (domain, System_Reflection_ParameterInfo, 0);
5721
5722         /* Note: the cache is based on the address of the signature into the method
5723          * since we already cache MethodInfos with the method as keys.
5724          */
5725         CHECK_OBJECT (MonoArray*, &(method->signature), NULL);
5726
5727         sig = mono_method_signature (method);
5728         member = mono_method_get_object (domain, method, NULL);
5729         names = g_new (char *, sig->param_count);
5730         mono_method_get_param_names (method, (const char **) names);
5731
5732         mspecs = g_new (MonoMarshalSpec*, sig->param_count + 1);
5733         mono_method_get_marshal_info (method, mspecs);
5734
5735         res = mono_array_new (domain, System_Reflection_ParameterInfo, sig->param_count);
5736         for (i = 0; i < sig->param_count; ++i) {
5737                 param = (MonoReflectionParameter *)mono_object_new (domain, System_Reflection_ParameterInfo);
5738                 MONO_OBJECT_SETREF (param, ClassImpl, mono_type_get_object (domain, sig->params [i]));
5739                 MONO_OBJECT_SETREF (param, MemberImpl, (MonoObject*)member);
5740                 MONO_OBJECT_SETREF (param, NameImpl, mono_string_new (domain, names [i]));
5741                 param->PositionImpl = i;
5742                 param->AttrsImpl = sig->params [i]->attrs;
5743
5744                 if (!(param->AttrsImpl & PARAM_ATTRIBUTE_HAS_DEFAULT)) {
5745                         MONO_OBJECT_SETREF (param, DefaultValueImpl, dbnull);
5746                 } else {
5747
5748                         if (!blobs) {
5749                                 blobs = g_new0 (char *, sig->param_count);
5750                                 types = g_new0 (guint32, sig->param_count);
5751                                 get_default_param_value_blobs (method, blobs, types); 
5752                         }
5753
5754                         /* Build MonoType for the type from the Constant Table */
5755                         if (!type)
5756                                 type = g_new0 (MonoType, 1);
5757                         type->type = types [i];
5758                         type->data.klass = NULL;
5759                         if (types [i] == MONO_TYPE_CLASS)
5760                                 type->data.klass = mono_defaults.object_class;
5761                         else if ((sig->params [i]->type == MONO_TYPE_VALUETYPE) && sig->params [i]->data.klass->enumtype) {
5762                                 /* For enums, types [i] contains the base type */
5763
5764                                         type->type = MONO_TYPE_VALUETYPE;
5765                                         type->data.klass = mono_class_from_mono_type (sig->params [i]);
5766                         } else
5767                                 type->data.klass = mono_class_from_mono_type (type);
5768
5769                         MONO_OBJECT_SETREF (param, DefaultValueImpl, mono_get_object_from_blob (domain, type, blobs [i]));
5770
5771                         /* Type in the Constant table is MONO_TYPE_CLASS for nulls */
5772                         if (types [i] != MONO_TYPE_CLASS && !param->DefaultValueImpl) 
5773                                 MONO_OBJECT_SETREF (param, DefaultValueImpl, dbnull);
5774                         
5775                 }
5776
5777                 if (mspecs [i + 1])
5778                         MONO_OBJECT_SETREF (param, MarshalAsImpl, (MonoObject*)mono_reflection_marshal_from_marshal_spec (domain, method->klass, mspecs [i + 1]));
5779                 
5780                 mono_array_setref (res, i, param);
5781         }
5782         g_free (names);
5783         g_free (blobs);
5784         g_free (types);
5785         g_free (type);
5786
5787         for (i = mono_method_signature (method)->param_count; i >= 0; i--)
5788                 if (mspecs [i])
5789                         mono_metadata_free_marshal_spec (mspecs [i]);
5790         g_free (mspecs);
5791         
5792         CACHE_OBJECT (MonoArray *, &(method->signature), res, NULL);
5793 }
5794
5795 /*
5796  * mono_method_body_get_object:
5797  * @domain: an app domain
5798  * @method: a method
5799  *
5800  * Return an System.Reflection.MethodBody object representing the method @method.
5801  */
5802 MonoReflectionMethodBody*
5803 mono_method_body_get_object (MonoDomain *domain, MonoMethod *method)
5804 {
5805         static MonoClass *System_Reflection_MethodBody = NULL;
5806         static MonoClass *System_Reflection_LocalVariableInfo = NULL;
5807         static MonoClass *System_Reflection_ExceptionHandlingClause = NULL;
5808         MonoReflectionMethodBody *ret;
5809         MonoMethodNormal *mn;
5810         MonoMethodHeader *header;
5811         guint32 method_rva, local_var_sig_token;
5812     char *ptr;
5813         unsigned char format, flags;
5814         int i;
5815
5816         if (!System_Reflection_MethodBody)
5817                 System_Reflection_MethodBody = mono_class_from_name (mono_defaults.corlib, "System.Reflection", "MethodBody");
5818         if (!System_Reflection_LocalVariableInfo)
5819                 System_Reflection_LocalVariableInfo = mono_class_from_name (mono_defaults.corlib, "System.Reflection", "LocalVariableInfo");
5820         if (!System_Reflection_ExceptionHandlingClause)
5821                 System_Reflection_ExceptionHandlingClause = mono_class_from_name (mono_defaults.corlib, "System.Reflection", "ExceptionHandlingClause");
5822
5823         CHECK_OBJECT (MonoReflectionMethodBody *, method, NULL);
5824
5825         if ((method->flags & METHOD_ATTRIBUTE_PINVOKE_IMPL) ||
5826                 (method->flags & METHOD_ATTRIBUTE_ABSTRACT) ||
5827             (method->iflags & METHOD_IMPL_ATTRIBUTE_INTERNAL_CALL) ||
5828             (method->iflags & METHOD_IMPL_ATTRIBUTE_RUNTIME))
5829                 return NULL;
5830         mn = (MonoMethodNormal *)method;
5831         header = mono_method_get_header (method);
5832         
5833         /* Obtain local vars signature token */
5834         method_rva = mono_metadata_decode_row_col (&method->klass->image->tables [MONO_TABLE_METHOD], mono_metadata_token_index (method->token) - 1, MONO_METHOD_RVA);
5835         ptr = mono_image_rva_map (method->klass->image, method_rva);
5836         flags = *(const unsigned char *) ptr;
5837         format = flags & METHOD_HEADER_FORMAT_MASK;
5838         switch (format){
5839         case METHOD_HEADER_TINY_FORMAT:
5840         case METHOD_HEADER_TINY_FORMAT1:
5841                 local_var_sig_token = 0;
5842                 break;
5843         case METHOD_HEADER_FAT_FORMAT:
5844                 ptr += 2;
5845                 ptr += 2;
5846                 ptr += 4;
5847                 local_var_sig_token = read32 (ptr);
5848                 break;
5849         default:
5850                 g_assert_not_reached ();
5851         }
5852
5853         ret = (MonoReflectionMethodBody*)mono_object_new (domain, System_Reflection_MethodBody);
5854
5855         ret->init_locals = header->init_locals;
5856         ret->max_stack = header->max_stack;
5857         ret->local_var_sig_token = local_var_sig_token;
5858         MONO_OBJECT_SETREF (ret, il, mono_array_new (domain, mono_defaults.byte_class, header->code_size));
5859         memcpy (mono_array_addr (ret->il, guint8, 0), header->code, header->code_size);
5860
5861         /* Locals */
5862         MONO_OBJECT_SETREF (ret, locals, mono_array_new (domain, System_Reflection_LocalVariableInfo, header->num_locals));
5863         for (i = 0; i < header->num_locals; ++i) {
5864                 MonoReflectionLocalVariableInfo *info = (MonoReflectionLocalVariableInfo*)mono_object_new (domain, System_Reflection_LocalVariableInfo);
5865                 MONO_OBJECT_SETREF (info, local_type, mono_type_get_object (domain, header->locals [i]));
5866                 info->is_pinned = header->locals [i]->pinned;
5867                 info->local_index = i;
5868                 mono_array_setref (ret->locals, i, info);
5869         }
5870
5871         /* Exceptions */
5872         MONO_OBJECT_SETREF (ret, clauses, mono_array_new (domain, System_Reflection_ExceptionHandlingClause, header->num_clauses));
5873         for (i = 0; i < header->num_clauses; ++i) {
5874                 MonoReflectionExceptionHandlingClause *info = (MonoReflectionExceptionHandlingClause*)mono_object_new (domain, System_Reflection_ExceptionHandlingClause);
5875                 MonoExceptionClause *clause = &header->clauses [i];
5876
5877                 info->flags = clause->flags;
5878                 info->try_offset = clause->try_offset;
5879                 info->try_length = clause->try_len;
5880                 info->handler_offset = clause->handler_offset;
5881                 info->handler_length = clause->handler_len;
5882                 if (clause->flags == MONO_EXCEPTION_CLAUSE_FILTER)
5883                         info->filter_offset = clause->data.filter_offset;
5884                 else if (clause->data.catch_class)
5885                         MONO_OBJECT_SETREF (info, catch_type, mono_type_get_object (mono_domain_get (), &clause->data.catch_class->byval_arg));
5886
5887                 mono_array_setref (ret->clauses, i, info);
5888         }
5889
5890         CACHE_OBJECT (MonoReflectionMethodBody *, method, ret, NULL);
5891         return ret;
5892 }
5893
5894 MonoObject *
5895 mono_get_dbnull_object (MonoDomain *domain)
5896 {
5897         MonoObject *obj;
5898         static MonoClassField *dbnull_value_field = NULL;
5899         
5900         if (!dbnull_value_field) {
5901                 MonoClass *dbnull_klass;
5902                 dbnull_klass = mono_class_from_name (mono_defaults.corlib, "System", "DBNull");
5903                 mono_class_init (dbnull_klass);
5904                 dbnull_value_field = mono_class_get_field_from_name (dbnull_klass, "Value");
5905                 g_assert (dbnull_value_field);
5906         }
5907         obj = mono_field_get_value_object (domain, dbnull_value_field, NULL); 
5908         g_assert (obj);
5909         return obj;
5910 }
5911
5912
5913 static void
5914 get_default_param_value_blobs (MonoMethod *method, char **blobs, guint32 *types)
5915 {
5916         guint32 param_index, i, lastp, crow = 0;
5917         guint32 param_cols [MONO_PARAM_SIZE], const_cols [MONO_CONSTANT_SIZE];
5918         gint32 idx;
5919
5920         MonoClass *klass = method->klass;
5921         MonoImage *image = klass->image;
5922         MonoMethodSignature *methodsig = mono_method_signature (method);
5923
5924         MonoTableInfo *constt;
5925         MonoTableInfo *methodt;
5926         MonoTableInfo *paramt;
5927
5928         if (!methodsig->param_count)
5929                 return;
5930
5931         mono_class_init (klass);
5932
5933         if (klass->image->dynamic) {
5934                 MonoReflectionMethodAux *aux;
5935                 if (method->is_inflated)
5936                         method = ((MonoMethodInflated*)method)->declaring;
5937                 aux = g_hash_table_lookup (((MonoDynamicImage*)method->klass->image)->method_aux_hash, method);
5938                 if (aux && aux->param_defaults) {
5939                         memcpy (blobs, &(aux->param_defaults [1]), methodsig->param_count * sizeof (char*));
5940                         memcpy (types, &(aux->param_default_types [1]), methodsig->param_count * sizeof (guint32));
5941                 }
5942                 return;
5943         }
5944
5945         methodt = &klass->image->tables [MONO_TABLE_METHOD];
5946         paramt = &klass->image->tables [MONO_TABLE_PARAM];
5947         constt = &image->tables [MONO_TABLE_CONSTANT];
5948
5949         idx = mono_method_get_index (method) - 1;
5950         g_assert (idx != -1);
5951
5952         param_index = mono_metadata_decode_row_col (methodt, idx, MONO_METHOD_PARAMLIST);
5953         if (idx + 1 < methodt->rows)
5954                 lastp = mono_metadata_decode_row_col (methodt, idx + 1, MONO_METHOD_PARAMLIST);
5955         else
5956                 lastp = paramt->rows + 1;
5957
5958         for (i = param_index; i < lastp; ++i) {
5959                 guint32 paramseq;
5960
5961                 mono_metadata_decode_row (paramt, i - 1, param_cols, MONO_PARAM_SIZE);
5962                 paramseq = param_cols [MONO_PARAM_SEQUENCE];
5963
5964                 if (!param_cols [MONO_PARAM_FLAGS] & PARAM_ATTRIBUTE_HAS_DEFAULT) 
5965                         continue;
5966
5967                 crow = mono_metadata_get_constant_index (image, MONO_TOKEN_PARAM_DEF | i, crow + 1);
5968                 if (!crow) {
5969                         continue;
5970                 }
5971         
5972                 mono_metadata_decode_row (constt, crow - 1, const_cols, MONO_CONSTANT_SIZE);
5973                 blobs [paramseq - 1] = (gpointer) mono_metadata_blob_heap (image, const_cols [MONO_CONSTANT_VALUE]);
5974                 types [paramseq - 1] = const_cols [MONO_CONSTANT_TYPE];
5975         }
5976
5977         return;
5978 }
5979
5980 static MonoObject *
5981 mono_get_object_from_blob (MonoDomain *domain, MonoType *type, const char *blob)
5982 {
5983         void *retval;
5984         MonoClass *klass;
5985         MonoObject *object;
5986         MonoType *basetype = type;
5987
5988         if (!blob)
5989                 return NULL;
5990         
5991         klass = mono_class_from_mono_type (type);
5992         if (klass->valuetype) {
5993                 object = mono_object_new (domain, klass);
5994                 retval = ((gchar *) object + sizeof (MonoObject));
5995                 if (klass->enumtype)
5996                         basetype = klass->enum_basetype;
5997         } else {
5998                 retval = &object;
5999         }
6000                         
6001         if (!mono_get_constant_value_from_blob (domain, basetype->type,  blob, retval))
6002                 return object;
6003         else
6004                 return NULL;
6005 }
6006
6007 static int
6008 assembly_name_to_aname (MonoAssemblyName *assembly, char *p) {
6009         int found_sep;
6010         char *s;
6011
6012         memset (assembly, 0, sizeof (MonoAssemblyName));
6013         assembly->name = p;
6014         assembly->culture = "";
6015         memset (assembly->public_key_token, 0, MONO_PUBLIC_KEY_TOKEN_LENGTH);
6016
6017         while (*p && (isalnum (*p) || *p == '.' || *p == '-' || *p == '_' || *p == '$' || *p == '@'))
6018                 p++;
6019         found_sep = 0;
6020         while (g_ascii_isspace (*p) || *p == ',') {
6021                 *p++ = 0;
6022                 found_sep = 1;
6023                 continue;
6024         }
6025         /* failed */
6026         if (!found_sep)
6027                 return 1;
6028         while (*p) {
6029                 if (*p == 'V' && g_ascii_strncasecmp (p, "Version=", 8) == 0) {
6030                         p += 8;
6031                         assembly->major = strtoul (p, &s, 10);
6032                         if (s == p || *s != '.')
6033                                 return 1;
6034                         p = ++s;
6035                         assembly->minor = strtoul (p, &s, 10);
6036                         if (s == p || *s != '.')
6037                                 return 1;
6038                         p = ++s;
6039                         assembly->build = strtoul (p, &s, 10);
6040                         if (s == p || *s != '.')
6041                                 return 1;
6042                         p = ++s;
6043                         assembly->revision = strtoul (p, &s, 10);
6044                         if (s == p)
6045                                 return 1;
6046                         p = s;
6047                 } else if (*p == 'C' && g_ascii_strncasecmp (p, "Culture=", 8) == 0) {
6048                         p += 8;
6049                         if (g_ascii_strncasecmp (p, "neutral", 7) == 0) {
6050                                 assembly->culture = "";
6051                                 p += 7;
6052                         } else {
6053                                 assembly->culture = p;
6054                                 while (*p && *p != ',') {
6055                                         p++;
6056                                 }
6057                         }
6058                 } else if (*p == 'P' && g_ascii_strncasecmp (p, "PublicKeyToken=", 15) == 0) {
6059                         p += 15;
6060                         if (strncmp (p, "null", 4) == 0) {
6061                                 p += 4;
6062                         } else {
6063                                 int len;
6064                                 gchar *start = p;
6065                                 while (*p && *p != ',') {
6066                                         p++;
6067                                 }
6068                                 len = (p - start + 1);
6069                                 if (len > MONO_PUBLIC_KEY_TOKEN_LENGTH)
6070                                         len = MONO_PUBLIC_KEY_TOKEN_LENGTH;
6071                                 g_strlcpy ((char*)assembly->public_key_token, start, len);
6072                         }
6073                 } else {
6074                         while (*p && *p != ',')
6075                                 p++;
6076                 }
6077                 found_sep = 0;
6078                 while (g_ascii_isspace (*p) || *p == ',') {
6079                         *p++ = 0;
6080                         found_sep = 1;
6081                         continue;
6082                 }
6083                 /* failed */
6084                 if (!found_sep)
6085                         return 1;
6086         }
6087
6088         return 0;
6089 }
6090
6091 /*
6092  * mono_reflection_parse_type:
6093  * @name: type name
6094  *
6095  * Parse a type name as accepted by the GetType () method and output the info
6096  * extracted in the info structure.
6097  * the name param will be mangled, so, make a copy before passing it to this function.
6098  * The fields in info will be valid until the memory pointed to by name is valid.
6099  *
6100  * See also mono_type_get_name () below.
6101  *
6102  * Returns: 0 on parse error.
6103  */
6104 static int
6105 _mono_reflection_parse_type (char *name, char **endptr, gboolean is_recursed,
6106                              MonoTypeNameParse *info)
6107 {
6108         char *start, *p, *w, *temp, *last_point, *startn;
6109         int in_modifiers = 0;
6110         int isbyref = 0, rank, arity = 0, i;
6111
6112         start = p = w = name;
6113
6114         //FIXME could we just zero the whole struct? memset (&info, 0, sizeof (MonoTypeNameParse))
6115         memset (&info->assembly, 0, sizeof (MonoAssemblyName));
6116         info->name = info->name_space = NULL;
6117         info->nested = NULL;
6118         info->modifiers = NULL;
6119         info->type_arguments = NULL;
6120
6121         /* last_point separates the namespace from the name */
6122         last_point = NULL;
6123
6124         while (*p) {
6125                 switch (*p) {
6126                 case '+':
6127                         *p = 0; /* NULL terminate the name */
6128                         startn = p + 1;
6129                         info->nested = g_list_append (info->nested, startn);
6130                         /* we have parsed the nesting namespace + name */
6131                         if (info->name)
6132                                 break;
6133                         if (last_point) {
6134                                 info->name_space = start;
6135                                 *last_point = 0;
6136                                 info->name = last_point + 1;
6137                         } else {
6138                                 info->name_space = (char *)"";
6139                                 info->name = start;
6140                         }
6141                         break;
6142                 case '.':
6143                         last_point = p;
6144                         break;
6145                 case '\\':
6146                         ++p;
6147                         break;
6148                 case '&':
6149                 case '*':
6150                 case '[':
6151                 case ',':
6152                 case ']':
6153                         in_modifiers = 1;
6154                         break;
6155                 case '`':
6156                         ++p;
6157                         i = strtol (p, &temp, 10);
6158                         arity += i;
6159                         if (p == temp)
6160                                 return 0;
6161                         p = temp-1;
6162                         break;
6163                 default:
6164                         break;
6165                 }
6166                 if (in_modifiers)
6167                         break;
6168                 // *w++ = *p++;
6169                 p++;
6170         }
6171         
6172         if (!info->name) {
6173                 if (last_point) {
6174                         info->name_space = start;
6175                         *last_point = 0;
6176                         info->name = last_point + 1;
6177                 } else {
6178                         info->name_space = (char *)"";
6179                         info->name = start;
6180                 }
6181         }
6182         while (*p) {
6183                 switch (*p) {
6184                 case '&':
6185                         if (isbyref) /* only one level allowed by the spec */
6186                                 return 0;
6187                         isbyref = 1;
6188                         info->modifiers = g_list_append (info->modifiers, GUINT_TO_POINTER (0));
6189                         *p++ = 0;
6190                         break;
6191                 case '*':
6192                         info->modifiers = g_list_append (info->modifiers, GUINT_TO_POINTER (-1));
6193                         *p++ = 0;
6194                         break;
6195                 case '[':
6196                         if (arity != 0) {
6197                                 *p++ = 0;
6198                                 info->type_arguments = g_ptr_array_new ();
6199                                 for (i = 0; i < arity; i++) {
6200                                         MonoTypeNameParse *subinfo = g_new0 (MonoTypeNameParse, 1);
6201                                         gboolean fqname = FALSE;
6202
6203                                         g_ptr_array_add (info->type_arguments, subinfo);
6204
6205                                         if (*p == '[') {
6206                                                 p++;
6207                                                 fqname = TRUE;
6208                                         }
6209
6210                                         if (!_mono_reflection_parse_type (p, &p, TRUE, subinfo))
6211                                                 return 0;
6212
6213                                         if (fqname) {
6214                                                 char *aname;
6215
6216                                                 if (*p != ',')
6217                                                         return 0;
6218                                                 *p++ = 0;
6219
6220                                                 aname = p;
6221                                                 while (*p && (*p != ']'))
6222                                                         p++;
6223
6224                                                 if (*p != ']')
6225                                                         return 0;
6226
6227                                                 *p++ = 0;
6228                                                 while (*aname) {
6229                                                         if (g_ascii_isspace (*aname)) {
6230                                                                 ++aname;
6231                                                                 continue;
6232                                                         }
6233                                                         break;
6234                                                 }
6235                                                 if (!*aname ||
6236                                                     !assembly_name_to_aname (&subinfo->assembly, aname))
6237                                                         return 0;
6238                                         }
6239
6240                                         if (i + 1 < arity) {
6241                                                 if (*p != ',')
6242                                                         return 0;
6243                                         } else {
6244                                                 if (*p != ']')
6245                                                         return 0;
6246                                         }
6247                                         *p++ = 0;
6248                                 }
6249
6250                                 arity = 0;
6251                                 break;
6252                         }
6253                         rank = 1;
6254                         *p++ = 0;
6255                         while (*p) {
6256                                 if (*p == ']')
6257                                         break;
6258                                 if (*p == ',')
6259                                         rank++;
6260                                 else if (*p != '*') /* '*' means unknown lower bound */
6261                                         return 0;
6262                                 ++p;
6263                         }
6264                         if (*p++ != ']')
6265                                 return 0;
6266                         info->modifiers = g_list_append (info->modifiers, GUINT_TO_POINTER (rank));
6267                         break;
6268                 case ']':
6269                         if (is_recursed)
6270                                 goto end;
6271                         return 0;
6272                 case ',':
6273                         if (is_recursed)
6274                                 goto end;
6275                         *p++ = 0;
6276                         while (*p) {
6277                                 if (g_ascii_isspace (*p)) {
6278                                         ++p;
6279                                         continue;
6280                                 }
6281                                 break;
6282                         }
6283                         if (!*p)
6284                                 return 0; /* missing assembly name */
6285                         if (!assembly_name_to_aname (&info->assembly, p))
6286                                 return 0;
6287                         break;
6288                 default:
6289                         return 0;
6290                 }
6291                 if (info->assembly.name)
6292                         break;
6293         }
6294         // *w = 0; /* terminate class name */
6295  end:
6296         if (!info->name || !*info->name)
6297                 return 0;
6298         if (endptr)
6299                 *endptr = p;
6300         /* add other consistency checks */
6301         return 1;
6302 }
6303
6304 int
6305 mono_reflection_parse_type (char *name, MonoTypeNameParse *info)
6306 {
6307         return _mono_reflection_parse_type (name, NULL, FALSE, info);
6308 }
6309
6310 static MonoType*
6311 _mono_reflection_get_type_from_info (MonoTypeNameParse *info, MonoImage *image, gboolean ignorecase)
6312 {
6313         gboolean type_resolve = FALSE;
6314         MonoType *type;
6315         MonoImage *rootimage = image;
6316
6317         if (info->assembly.name) {
6318                 MonoAssembly *assembly = mono_assembly_loaded (&info->assembly);
6319                 if (!assembly) {
6320                         /* then we must load the assembly ourselve - see #60439 */
6321                         assembly = mono_assembly_load (&info->assembly, NULL, NULL);
6322                         if (!assembly)
6323                                 return NULL;
6324                 }
6325                 image = assembly->image;
6326         } else if (!image) {
6327                 image = mono_defaults.corlib;
6328         }
6329
6330         type = mono_reflection_get_type_with_rootimage (rootimage, image, info, ignorecase, &type_resolve);
6331         if (type == NULL && !info->assembly.name && image != mono_defaults.corlib) {
6332                 image = mono_defaults.corlib;
6333                 type = mono_reflection_get_type_with_rootimage (rootimage, image, info, ignorecase, &type_resolve);
6334         }
6335
6336         return type;
6337 }
6338
6339 static MonoType*
6340 mono_reflection_get_type_internal (MonoImage *rootimage, MonoImage* image, MonoTypeNameParse *info, gboolean ignorecase)
6341 {
6342         MonoClass *klass;
6343         GList *mod;
6344         int modval;
6345         
6346         if (!image)
6347                 image = mono_defaults.corlib;
6348
6349         if (ignorecase)
6350                 klass = mono_class_from_name_case (image, info->name_space, info->name);
6351         else
6352                 klass = mono_class_from_name (image, info->name_space, info->name);
6353         if (!klass)
6354                 return NULL;
6355         for (mod = info->nested; mod; mod = mod->next) {
6356                 GList *nested;
6357
6358                 mono_class_init (klass);
6359                 nested = klass->nested_classes;
6360                 klass = NULL;
6361                 while (nested) {
6362                         klass = nested->data;
6363                         if (ignorecase) {
6364                                 if (g_strcasecmp (klass->name, mod->data) == 0)
6365                                         break;
6366                         } else {
6367                                 if (strcmp (klass->name, mod->data) == 0)
6368                                         break;
6369                         }
6370                         klass = NULL;
6371                         nested = nested->next;
6372                 }
6373                 if (!klass)
6374                         break;
6375         }
6376         if (!klass)
6377                 return NULL;
6378         mono_class_init (klass);
6379
6380         if (info->type_arguments) {
6381                 MonoType **type_args = g_new0 (MonoType *, info->type_arguments->len);
6382                 MonoReflectionType *the_type;
6383                 MonoType *instance;
6384                 int i;
6385
6386                 for (i = 0; i < info->type_arguments->len; i++) {
6387                         MonoTypeNameParse *subinfo = g_ptr_array_index (info->type_arguments, i);
6388
6389                         type_args [i] = _mono_reflection_get_type_from_info (subinfo, rootimage, ignorecase);
6390                         if (!type_args [i]) {
6391                                 g_free (type_args);
6392                                 return NULL;
6393                         }
6394                 }
6395
6396                 the_type = mono_type_get_object (mono_domain_get (), &klass->byval_arg);
6397
6398                 instance = mono_reflection_bind_generic_parameters (
6399                         the_type, info->type_arguments->len, type_args);
6400
6401                 g_free (type_args);
6402                 if (!instance)
6403                         return NULL;
6404
6405                 klass = mono_class_from_mono_type (instance);
6406         }
6407
6408         for (mod = info->modifiers; mod; mod = mod->next) {
6409                 modval = GPOINTER_TO_UINT (mod->data);
6410                 if (!modval) { /* byref: must be last modifier */
6411                         return &klass->this_arg;
6412                 } else if (modval == -1) {
6413                         klass = mono_ptr_class_get (&klass->byval_arg);
6414                 } else { /* array rank */
6415                         klass = mono_array_class_get (klass, modval);
6416                 }
6417                 mono_class_init (klass);
6418         }
6419
6420         return &klass->byval_arg;
6421 }
6422
6423 /*
6424  * mono_reflection_get_type:
6425  * @image: a metadata context
6426  * @info: type description structure
6427  * @ignorecase: flag for case-insensitive string compares
6428  * @type_resolve: whenever type resolve was already tried
6429  *
6430  * Build a MonoType from the type description in @info.
6431  * 
6432  */
6433
6434 MonoType*
6435 mono_reflection_get_type (MonoImage* image, MonoTypeNameParse *info, gboolean ignorecase, gboolean *type_resolve) {
6436         return mono_reflection_get_type_with_rootimage(image, image, info, ignorecase, type_resolve);
6437 }
6438
6439 static MonoType*
6440 mono_reflection_get_type_internal_dynamic (MonoImage *rootimage, MonoAssembly *assembly, MonoTypeNameParse *info, gboolean ignorecase)
6441 {
6442         MonoReflectionAssemblyBuilder *abuilder = (MonoReflectionAssemblyBuilder*)mono_assembly_get_object (mono_domain_get (), assembly);
6443         MonoType *type;
6444         int i;
6445
6446         g_assert (assembly->dynamic);
6447
6448         /* Enumerate all modules */
6449
6450         type = NULL;
6451         if (abuilder->modules) {
6452                 for (i = 0; i < mono_array_length (abuilder->modules); ++i) {
6453                         MonoReflectionModuleBuilder *mb = mono_array_get (abuilder->modules, MonoReflectionModuleBuilder*, i);
6454                         type = mono_reflection_get_type_internal (rootimage, &mb->dynamic_image->image, info, ignorecase);
6455                         if (type)
6456                                 break;
6457                 }
6458         }
6459
6460         if (!type && abuilder->loaded_modules) {
6461                 for (i = 0; i < mono_array_length (abuilder->loaded_modules); ++i) {
6462                         MonoReflectionModule *mod = mono_array_get (abuilder->loaded_modules, MonoReflectionModule*, i);
6463                         type = mono_reflection_get_type_internal (rootimage, mod->image, info, ignorecase);
6464                         if (type)
6465                                 break;
6466                 }
6467         }
6468
6469         return type;
6470 }
6471         
6472 MonoType*
6473 mono_reflection_get_type_with_rootimage (MonoImage *rootimage, MonoImage* image, MonoTypeNameParse *info, gboolean ignorecase, gboolean *type_resolve)
6474 {
6475         MonoType *type;
6476         MonoReflectionAssembly *assembly;
6477         GString *fullName;
6478         GList *mod;
6479
6480         if (image && image->dynamic)
6481                 type = mono_reflection_get_type_internal_dynamic (rootimage, image->assembly, info, ignorecase);
6482         else
6483                 type = mono_reflection_get_type_internal (rootimage, image, info, ignorecase);
6484         if (type)
6485                 return type;
6486         if (!mono_domain_has_type_resolve (mono_domain_get ()))
6487                 return NULL;
6488
6489         if (type_resolve) {
6490                 if (*type_resolve) 
6491                         return NULL;
6492                 else
6493                         *type_resolve = TRUE;
6494         }
6495         
6496         /* Reconstruct the type name */
6497         fullName = g_string_new ("");
6498         if (info->name_space && (info->name_space [0] != '\0'))
6499                 g_string_printf (fullName, "%s.%s", info->name_space, info->name);
6500         else
6501                 g_string_printf (fullName, info->name);
6502         for (mod = info->nested; mod; mod = mod->next)
6503                 g_string_append_printf (fullName, "+%s", (char*)mod->data);
6504
6505         assembly = mono_domain_try_type_resolve ( mono_domain_get (), fullName->str, NULL);
6506         if (assembly) {
6507                 if (assembly->assembly->dynamic)
6508                         type = mono_reflection_get_type_internal_dynamic (rootimage, assembly->assembly, info, ignorecase);
6509                 else
6510                         type = mono_reflection_get_type_internal (rootimage, assembly->assembly->image, 
6511                                                                                                           info, ignorecase);
6512         }
6513         g_string_free (fullName, TRUE);
6514         return type;
6515 }
6516
6517 void
6518 mono_reflection_free_type_info (MonoTypeNameParse *info)
6519 {
6520         g_list_free (info->modifiers);
6521         g_list_free (info->nested);
6522
6523         if (info->type_arguments) {
6524                 int i;
6525
6526                 for (i = 0; i < info->type_arguments->len; i++) {
6527                         MonoTypeNameParse *subinfo = g_ptr_array_index (info->type_arguments, i);
6528
6529                         mono_reflection_free_type_info (subinfo);
6530                         /*We free the subinfo since it is allocated by _mono_reflection_parse_type*/
6531                         g_free (subinfo);
6532                 }
6533
6534                 g_ptr_array_free (info->type_arguments, TRUE);
6535         }
6536 }
6537
6538 /*
6539  * mono_reflection_type_from_name:
6540  * @name: type name.
6541  * @image: a metadata context (can be NULL).
6542  *
6543  * Retrieves a MonoType from its @name. If the name is not fully qualified,
6544  * it defaults to get the type from @image or, if @image is NULL or loading
6545  * from it fails, uses corlib.
6546  * 
6547  */
6548 MonoType*
6549 mono_reflection_type_from_name (char *name, MonoImage *image)
6550 {
6551         MonoType *type = NULL;
6552         MonoTypeNameParse info;
6553         char *tmp;
6554
6555         /* Make a copy since parse_type modifies its argument */
6556         tmp = g_strdup (name);
6557         
6558         /*g_print ("requested type %s\n", str);*/
6559         if (mono_reflection_parse_type (tmp, &info)) {
6560                 type = _mono_reflection_get_type_from_info (&info, image, FALSE);
6561         }
6562
6563         g_free (tmp);
6564         mono_reflection_free_type_info (&info);
6565         return type;
6566 }
6567
6568 /*
6569  * mono_reflection_get_token:
6570  *
6571  *   Return the metadata token of OBJ which should be an object
6572  * representing a metadata element.
6573  */
6574 guint32
6575 mono_reflection_get_token (MonoObject *obj)
6576 {
6577         MonoClass *klass;
6578         guint32 token = 0;
6579
6580         klass = obj->vtable->klass;
6581
6582         if (strcmp (klass->name, "MethodBuilder") == 0) {
6583                 MonoReflectionMethodBuilder *mb = (MonoReflectionMethodBuilder *)obj;
6584
6585                 token = mb->table_idx | MONO_TOKEN_METHOD_DEF;
6586         } else if (strcmp (klass->name, "ConstructorBuilder") == 0) {
6587                 MonoReflectionCtorBuilder *mb = (MonoReflectionCtorBuilder *)obj;
6588
6589                 token = mb->table_idx | MONO_TOKEN_METHOD_DEF;
6590         } else if (strcmp (klass->name, "FieldBuilder") == 0) {
6591                 MonoReflectionFieldBuilder *fb = (MonoReflectionFieldBuilder *)obj;
6592                 token = fb->table_idx | MONO_TOKEN_FIELD_DEF;
6593         } else if (strcmp (klass->name, "TypeBuilder") == 0) {
6594                 MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder *)obj;
6595                 token = tb->table_idx | MONO_TOKEN_TYPE_DEF;
6596         } else if (strcmp (klass->name, "MonoType") == 0) {
6597                 MonoReflectionType *tb = (MonoReflectionType *)obj;
6598                 token = mono_class_from_mono_type (tb->type)->type_token;
6599         } else if (strcmp (klass->name, "MonoCMethod") == 0 ||
6600                    strcmp (klass->name, "MonoMethod") == 0 ||
6601                    strcmp (klass->name, "MonoGenericMethod") == 0 ||
6602                    strcmp (klass->name, "MonoGenericCMethod") == 0) {
6603                 MonoReflectionMethod *m = (MonoReflectionMethod *)obj;
6604                 if (m->method->is_inflated) {
6605                         MonoMethodInflated *inflated = (MonoMethodInflated *) m->method;
6606                         return inflated->declaring->token;
6607                 } else {
6608                         token = m->method->token;
6609                 }
6610         } else if (strcmp (klass->name, "MonoField") == 0) {
6611                 MonoReflectionField *f = (MonoReflectionField*)obj;
6612
6613                 if (f->field->generic_info && f->field->generic_info->reflection_info)
6614                         return mono_reflection_get_token (f->field->generic_info->reflection_info);
6615
6616                 token = mono_class_get_field_token (f->field);
6617         } else if (strcmp (klass->name, "MonoProperty") == 0) {
6618                 MonoReflectionProperty *p = (MonoReflectionProperty*)obj;
6619
6620                 token = mono_class_get_property_token (p->property);
6621         } else if (strcmp (klass->name, "MonoEvent") == 0) {
6622                 MonoReflectionEvent *p = (MonoReflectionEvent*)obj;
6623
6624                 token = mono_class_get_event_token (p->event);
6625         } else if (strcmp (klass->name, "ParameterInfo") == 0) {
6626                 MonoReflectionParameter *p = (MonoReflectionParameter*)obj;
6627
6628                 token = mono_method_get_param_token (((MonoReflectionMethod*)p->MemberImpl)->method, p->PositionImpl);
6629         } else if (strcmp (klass->name, "Module") == 0) {
6630                 MonoReflectionModule *m = (MonoReflectionModule*)obj;
6631
6632                 token = m->token;
6633         } else if (strcmp (klass->name, "Assembly") == 0) {
6634                 token = mono_metadata_make_token (MONO_TABLE_ASSEMBLY, 1);
6635         } else {
6636                 gchar *msg = g_strdup_printf ("MetadataToken is not supported for type '%s.%s'", klass->name_space, klass->name);
6637                 MonoException *ex = mono_get_exception_not_implemented (msg);
6638                 g_free (msg);
6639                 mono_raise_exception (ex);
6640         }
6641
6642         return token;
6643 }
6644
6645 static void*
6646 load_cattr_value (MonoImage *image, MonoType *t, const char *p, const char **end)
6647 {
6648         int slen, type = t->type;
6649         MonoClass *tklass = t->data.klass;
6650
6651 handle_enum:
6652         switch (type) {
6653         case MONO_TYPE_U1:
6654         case MONO_TYPE_I1:
6655         case MONO_TYPE_BOOLEAN: {
6656                 MonoBoolean *bval = g_malloc (sizeof (MonoBoolean));
6657                 *bval = *p;
6658                 *end = p + 1;
6659                 return bval;
6660         }
6661         case MONO_TYPE_CHAR:
6662         case MONO_TYPE_U2:
6663         case MONO_TYPE_I2: {
6664                 guint16 *val = g_malloc (sizeof (guint16));
6665                 *val = read16 (p);
6666                 *end = p + 2;
6667                 return val;
6668         }
6669 #if SIZEOF_VOID_P == 4
6670         case MONO_TYPE_U:
6671         case MONO_TYPE_I:
6672 #endif
6673         case MONO_TYPE_R4:
6674         case MONO_TYPE_U4:
6675         case MONO_TYPE_I4: {
6676                 guint32 *val = g_malloc (sizeof (guint32));
6677                 *val = read32 (p);
6678                 *end = p + 4;
6679                 return val;
6680         }
6681 #if SIZEOF_VOID_P == 8
6682         case MONO_TYPE_U: /* error out instead? this should probably not happen */
6683         case MONO_TYPE_I:
6684 #endif
6685         case MONO_TYPE_U8:
6686         case MONO_TYPE_I8: {
6687                 guint64 *val = g_malloc (sizeof (guint64));
6688                 *val = read64 (p);
6689                 *end = p + 8;
6690                 return val;
6691         }
6692         case MONO_TYPE_R8: {
6693                 double *val = g_malloc (sizeof (double));
6694                 readr8 (p, val);
6695                 *end = p + 8;
6696                 return val;
6697         }
6698         case MONO_TYPE_VALUETYPE:
6699                 if (t->data.klass->enumtype) {
6700                         type = t->data.klass->enum_basetype->type;
6701                         goto handle_enum;
6702                 } else {
6703                         g_error ("generic valutype %s not handled in custom attr value decoding", t->data.klass->name);
6704                 }
6705                 break;
6706         case MONO_TYPE_STRING:
6707                 if (*p == (char)0xFF) {
6708                         *end = p + 1;
6709                         return NULL;
6710                 }
6711                 slen = mono_metadata_decode_value (p, &p);
6712                 *end = p + slen;
6713                 return mono_string_new_len (mono_domain_get (), p, slen);
6714         case MONO_TYPE_CLASS: {
6715                 char *n;
6716                 MonoType *t;
6717                 if (*p == (char)0xFF) {
6718                         *end = p + 1;
6719                         return NULL;
6720                 }
6721 handle_type:
6722                 slen = mono_metadata_decode_value (p, &p);
6723                 n = g_memdup (p, slen + 1);
6724                 n [slen] = 0;
6725                 t = mono_reflection_type_from_name (n, image);
6726                 if (!t)
6727                         g_warning ("Cannot load type '%s'", n);
6728                 g_free (n);
6729                 *end = p + slen;
6730                 if (t)
6731                         return mono_type_get_object (mono_domain_get (), t);
6732                 else
6733                         return NULL;
6734         }
6735         case MONO_TYPE_OBJECT: {
6736                 char subt = *p++;
6737                 MonoObject *obj;
6738                 MonoClass *subc = NULL;
6739                 void *val;
6740
6741                 if (subt == 0x50) {
6742                         goto handle_type;
6743                 } else if (subt == 0x0E) {
6744                         type = MONO_TYPE_STRING;
6745                         goto handle_enum;
6746                 } else if (subt == 0x1D) {
6747                         MonoType simple_type = {{0}};
6748                         int etype = *p;
6749                         p ++;
6750
6751                         if (etype == 0x51)
6752                                 /* See Partition II, Appendix B3 */
6753                                 etype = MONO_TYPE_OBJECT;
6754                         type = MONO_TYPE_SZARRAY;
6755                         simple_type.type = etype;
6756                         tklass = mono_class_from_mono_type (&simple_type);
6757                         goto handle_enum;
6758                 } else if (subt == 0x55) {
6759                         char *n;
6760                         MonoType *t;
6761                         slen = mono_metadata_decode_value (p, &p);
6762                         n = g_memdup (p, slen + 1);
6763                         n [slen] = 0;
6764                         t = mono_reflection_type_from_name (n, image);
6765                         if (!t)
6766                                 g_error ("Cannot load type '%s'", n);
6767                         g_free (n);
6768                         p += slen;
6769                         subc = mono_class_from_mono_type (t);
6770                 } else if (subt >= MONO_TYPE_BOOLEAN && subt <= MONO_TYPE_R8) {
6771                         MonoType simple_type = {{0}};
6772                         simple_type.type = subt;
6773                         subc = mono_class_from_mono_type (&simple_type);
6774                 } else {
6775                         g_error ("Unknown type 0x%02x for object type encoding in custom attr", subt);
6776                 }
6777                 val = load_cattr_value (image, &subc->byval_arg, p, end);
6778                 obj = mono_object_new (mono_domain_get (), subc);
6779                 memcpy ((char*)obj + sizeof (MonoObject), val, mono_class_value_size (subc, NULL));
6780                 g_free (val);
6781                 return obj;
6782         }
6783         case MONO_TYPE_SZARRAY: {
6784                 MonoArray *arr;
6785                 guint32 i, alen, basetype;
6786                 alen = read32 (p);
6787                 p += 4;
6788                 if (alen == 0xffffffff) {
6789                         *end = p;
6790                         return NULL;
6791                 }
6792                 arr = mono_array_new (mono_domain_get(), tklass, alen);
6793                 basetype = tklass->byval_arg.type;
6794                 if (basetype == MONO_TYPE_VALUETYPE && tklass->enumtype)
6795                         basetype = tklass->enum_basetype->type;
6796                 switch (basetype)
6797                 {
6798                         case MONO_TYPE_U1:
6799                         case MONO_TYPE_I1:
6800                         case MONO_TYPE_BOOLEAN:
6801                                 for (i = 0; i < alen; i++) {
6802                                         MonoBoolean val = *p++;
6803                                         mono_array_set (arr, MonoBoolean, i, val);
6804                                 }
6805                                 break;
6806                         case MONO_TYPE_CHAR:
6807                         case MONO_TYPE_U2:
6808                         case MONO_TYPE_I2:
6809                                 for (i = 0; i < alen; i++) {
6810                                         guint16 val = read16 (p);
6811                                         mono_array_set (arr, guint16, i, val);
6812                                         p += 2;
6813                                 }
6814                                 break;
6815                         case MONO_TYPE_R4:
6816                         case MONO_TYPE_U4:
6817                         case MONO_TYPE_I4:
6818                                 for (i = 0; i < alen; i++) {
6819                                         guint32 val = read32 (p);
6820                                         mono_array_set (arr, guint32, i, val);
6821                                         p += 4;
6822                                 }
6823                                 break;
6824                         case MONO_TYPE_R8:
6825                                 for (i = 0; i < alen; i++) {
6826                                         double val;
6827                                         readr8 (p, &val);
6828                                         mono_array_set (arr, double, i, val);
6829                                         p += 8;
6830                                 }
6831                                 break;
6832                         case MONO_TYPE_U8:
6833                         case MONO_TYPE_I8:
6834                                 for (i = 0; i < alen; i++) {
6835                                         guint64 val = read64 (p);
6836                                         mono_array_set (arr, guint64, i, val);
6837                                         p += 8;
6838                                 }
6839                                 break;
6840                         case MONO_TYPE_CLASS:
6841                         case MONO_TYPE_OBJECT:
6842                         case MONO_TYPE_STRING:
6843                                 for (i = 0; i < alen; i++) {
6844                                         MonoObject *item = load_cattr_value (image, &tklass->byval_arg, p, &p);
6845                                         mono_array_setref (arr, i, item);
6846                                 }
6847                                 break;
6848                         default:
6849                                 g_error ("Type 0x%02x not handled in custom attr array decoding", basetype);
6850                 }
6851                 *end=p;
6852                 return arr;
6853         }
6854         default:
6855                 g_error ("Type 0x%02x not handled in custom attr value decoding", type);
6856         }
6857         return NULL;
6858 }
6859
6860 static MonoObject*
6861 create_cattr_typed_arg (MonoType *t, MonoObject *val)
6862 {
6863         static MonoClass *klass;
6864         static MonoMethod *ctor;
6865         MonoObject *retval;
6866         void *params [2], *unboxed;
6867
6868         if (!klass)
6869                 klass = mono_class_from_name (mono_defaults.corlib, "System.Reflection", "CustomAttributeTypedArgument");
6870         if (!ctor)
6871                 ctor = mono_class_get_method_from_name (klass, ".ctor", 2);
6872         
6873         params [0] = mono_type_get_object (mono_domain_get (), t);
6874         params [1] = val;
6875         retval = mono_object_new (mono_domain_get (), klass);
6876         unboxed = mono_object_unbox (retval);
6877         mono_runtime_invoke (ctor, unboxed, params, NULL);
6878
6879         return retval;
6880 }
6881
6882 static MonoObject*
6883 create_cattr_named_arg (void *minfo, MonoObject *typedarg)
6884 {
6885         static MonoClass *klass;
6886         static MonoMethod *ctor;
6887         MonoObject *retval;
6888         void *unboxed, *params [2];
6889
6890         if (!klass)
6891                 klass = mono_class_from_name (mono_defaults.corlib, "System.Reflection", "CustomAttributeNamedArgument");
6892         if (!ctor)
6893                 ctor = mono_class_get_method_from_name (klass, ".ctor", 2);
6894
6895         params [0] = minfo;
6896         params [1] = typedarg;
6897         retval = mono_object_new (mono_domain_get (), klass);
6898         unboxed = mono_object_unbox (retval);
6899         mono_runtime_invoke (ctor, unboxed, params, NULL);
6900
6901         return retval;
6902 }
6903
6904 static gboolean
6905 type_is_reference (MonoType *type)
6906 {
6907         switch (type->type) {
6908         case MONO_TYPE_BOOLEAN:
6909         case MONO_TYPE_CHAR:
6910         case MONO_TYPE_U:
6911         case MONO_TYPE_I:
6912         case MONO_TYPE_U1:
6913         case MONO_TYPE_I1:
6914         case MONO_TYPE_U2:
6915         case MONO_TYPE_I2:
6916         case MONO_TYPE_U4:
6917         case MONO_TYPE_I4:
6918         case MONO_TYPE_U8:
6919         case MONO_TYPE_I8:
6920         case MONO_TYPE_R8:
6921         case MONO_TYPE_R4:
6922         case MONO_TYPE_VALUETYPE:
6923                 return FALSE;
6924         default:
6925                 return TRUE;
6926         }
6927 }
6928
6929 static void
6930 free_param_data (MonoMethodSignature *sig, void **params) {
6931         int i;
6932         for (i = 0; i < sig->param_count; ++i) {
6933                 if (!type_is_reference (sig->params [i]))
6934                         g_free (params [i]);
6935         }
6936 }
6937
6938 /*
6939  * Find the field index in the metadata FieldDef table.
6940  */
6941 static guint32
6942 find_field_index (MonoClass *klass, MonoClassField *field) {
6943         int i;
6944
6945         for (i = 0; i < klass->field.count; ++i) {
6946                 if (field == &klass->fields [i])
6947                         return klass->field.first + 1 + i;
6948         }
6949         return 0;
6950 }
6951
6952 /*
6953  * Find the property index in the metadata Property table.
6954  */
6955 static guint32
6956 find_property_index (MonoClass *klass, MonoProperty *property) {
6957         int i;
6958
6959         for (i = 0; i < klass->property.count; ++i) {
6960                 if (property == &klass->properties [i])
6961                         return klass->property.first + 1 + i;
6962         }
6963         return 0;
6964 }
6965
6966 /*
6967  * Find the event index in the metadata Event table.
6968  */
6969 static guint32
6970 find_event_index (MonoClass *klass, MonoEvent *event) {
6971         int i;
6972
6973         for (i = 0; i < klass->event.count; ++i) {
6974                 if (event == &klass->events [i])
6975                         return klass->event.first + 1 + i;
6976         }
6977         return 0;
6978 }
6979
6980 static MonoObject*
6981 create_custom_attr (MonoImage *image, MonoMethod *method, const guchar *data, guint32 len)
6982 {
6983         const char *p = (const char*)data;
6984         const char *named;
6985         guint32 i, j, num_named;
6986         MonoObject *attr;
6987         void **params;
6988
6989         mono_class_init (method->klass);
6990
6991         if (len == 0) {
6992                 attr = mono_object_new (mono_domain_get (), method->klass);
6993                 mono_runtime_invoke (method, attr, NULL, NULL);
6994                 return attr;
6995         }
6996
6997         if (len < 2 || read16 (p) != 0x0001) /* Prolog */
6998                 return NULL;
6999
7000         /*g_print ("got attr %s\n", method->klass->name);*/
7001
7002         /* Allocate using alloca so it gets GC tracking */
7003         params = alloca (mono_method_signature (method)->param_count * sizeof (void*)); 
7004
7005         /* skip prolog */
7006         p += 2;
7007         for (i = 0; i < mono_method_signature (method)->param_count; ++i) {
7008                 params [i] = load_cattr_value (image, mono_method_signature (method)->params [i], p, &p);
7009         }
7010
7011         named = p;
7012         attr = mono_object_new (mono_domain_get (), method->klass);
7013         mono_runtime_invoke (method, attr, params, NULL);
7014         free_param_data (method->signature, params);
7015         num_named = read16 (named);
7016         named += 2;
7017         for (j = 0; j < num_named; j++) {
7018                 gint name_len;
7019                 char *name, named_type, data_type;
7020                 named_type = *named++;
7021                 data_type = *named++; /* type of data */
7022                 if (data_type == MONO_TYPE_SZARRAY)
7023                         data_type = *named++;
7024                 if (data_type == MONO_TYPE_ENUM) {
7025                         gint type_len;
7026                         char *type_name;
7027                         type_len = mono_metadata_decode_blob_size (named, &named);
7028                         type_name = g_malloc (type_len + 1);
7029                         memcpy (type_name, named, type_len);
7030                         type_name [type_len] = 0;
7031                         named += type_len;
7032                         /* FIXME: lookup the type and check type consistency */
7033                         g_free (type_name);
7034                 }
7035                 name_len = mono_metadata_decode_blob_size (named, &named);
7036                 name = g_malloc (name_len + 1);
7037                 memcpy (name, named, name_len);
7038                 name [name_len] = 0;
7039                 named += name_len;
7040                 if (named_type == 0x53) {
7041                         MonoClassField *field = mono_class_get_field_from_name (mono_object_class (attr), name);
7042                         void *val = load_cattr_value (image, field->type, named, &named);
7043                         mono_field_set_value (attr, field, val);
7044                         if (!type_is_reference (field->type))
7045                                 g_free (val);
7046                 } else if (named_type == 0x54) {
7047                         MonoProperty *prop;
7048                         void *pparams [1];
7049                         MonoType *prop_type;
7050
7051                         prop = mono_class_get_property_from_name (mono_object_class (attr), name);
7052                         /* can we have more that 1 arg in a custom attr named property? */
7053                         prop_type = prop->get? mono_method_signature (prop->get)->ret :
7054                              mono_method_signature (prop->set)->params [mono_method_signature (prop->set)->param_count - 1];
7055                         pparams [0] = load_cattr_value (image, prop_type, named, &named);
7056                         mono_property_set_value (prop, attr, pparams, NULL);
7057                         if (!type_is_reference (prop_type))
7058                                 g_free (pparams [0]);
7059                 }
7060                 g_free (name);
7061         }
7062
7063         return attr;
7064 }
7065
7066 static MonoObject*
7067 create_custom_attr_data (MonoImage *image, MonoMethod *method, const guchar *data, guint32 len)
7068 {
7069         MonoArray *typedargs, *namedargs;
7070         MonoClass *attrklass;
7071         static MonoMethod *ctor;
7072         MonoDomain *domain;
7073         MonoObject *attr;
7074         const char *p = (const char*)data;
7075         const char *named;
7076         guint32 i, j, num_named;
7077         void *params [3];
7078
7079         mono_class_init (method->klass);
7080
7081         if (!ctor)
7082                 ctor = mono_class_get_method_from_name (mono_defaults.customattribute_data_class, ".ctor", 3);
7083
7084         domain = mono_domain_get ();
7085         if (len == 0) {
7086                 /* This is for Attributes with no parameters */
7087                 attr = mono_object_new (domain, mono_defaults.customattribute_data_class);
7088                 params [0] = mono_method_get_object (domain, method, NULL);
7089                 params [1] = params [2] = NULL;
7090                 mono_runtime_invoke (method, attr, params, NULL);
7091                 return attr;
7092         }
7093
7094         if (len < 2 || read16 (p) != 0x0001) /* Prolog */
7095                 return NULL;
7096
7097         typedargs = mono_array_new (domain, mono_get_object_class (), mono_method_signature (method)->param_count);
7098         
7099         /* skip prolog */
7100         p += 2;
7101         for (i = 0; i < mono_method_signature (method)->param_count; ++i) {
7102                 MonoObject *obj, *typedarg;
7103                 void *val;
7104
7105                 val = load_cattr_value (image, mono_method_signature (method)->params [i], p, &p);
7106                 obj = type_is_reference (mono_method_signature (method)->params [i]) ? 
7107                         val : mono_value_box (domain, mono_class_from_mono_type (mono_method_signature (method)->params [i]), val);
7108                 typedarg = create_cattr_typed_arg (mono_method_signature (method)->params [i], obj);
7109                 mono_array_setref (typedargs, i, typedarg);
7110
7111                 if (!type_is_reference (mono_method_signature (method)->params [i]))
7112                         g_free (val);
7113         }
7114
7115         named = p;
7116         num_named = read16 (named);
7117         namedargs = mono_array_new (domain, mono_get_object_class (), num_named);
7118         named += 2;
7119         attrklass = method->klass;
7120         for (j = 0; j < num_named; j++) {
7121                 gint name_len;
7122                 char *name, named_type, data_type;
7123                 named_type = *named++;
7124                 data_type = *named++; /* type of data */
7125                 if (data_type == MONO_TYPE_SZARRAY)
7126                         data_type = *named++;
7127                 if (data_type == MONO_TYPE_ENUM) {
7128                         gint type_len;
7129                         char *type_name;
7130                         type_len = mono_metadata_decode_blob_size (named, &named);
7131                         type_name = g_malloc (type_len + 1);
7132                         memcpy (type_name, named, type_len);
7133                         type_name [type_len] = 0;
7134                         named += type_len;
7135                         /* FIXME: lookup the type and check type consistency */
7136                         g_free (type_name);
7137                 }
7138                 name_len = mono_metadata_decode_blob_size (named, &named);
7139                 name = g_malloc (name_len + 1);
7140                 memcpy (name, named, name_len);
7141                 name [name_len] = 0;
7142                 named += name_len;
7143                 if (named_type == 0x53) {
7144                         MonoObject *obj, *typedarg, *namedarg;
7145                         MonoClassField *field = mono_class_get_field_from_name (attrklass, name);
7146                         void *minfo, *val = load_cattr_value (image, field->type, named, &named);
7147                         
7148                         minfo = mono_field_get_object (domain, NULL, field);
7149                         obj = type_is_reference (field->type) ? val : mono_value_box (domain, mono_class_from_mono_type (field->type), val);
7150                         typedarg = create_cattr_typed_arg (field->type, obj);
7151                         namedarg = create_cattr_named_arg (minfo, typedarg);
7152                         mono_array_setref (namedargs, j, namedarg);
7153                         if (!type_is_reference (field->type))
7154                                 g_free (val);
7155                 } else if (named_type == 0x54) {
7156                         MonoObject *obj, *typedarg, *namedarg;
7157                         MonoType *prop_type;
7158                         void *val, *minfo;
7159                         MonoProperty *prop = mono_class_get_property_from_name (attrklass, name);
7160
7161                         prop_type = prop->get? mono_method_signature (prop->get)->ret :
7162                              mono_method_signature (prop->set)->params [mono_method_signature (prop->set)->param_count - 1];
7163                         minfo =  mono_property_get_object (domain, NULL, prop);
7164                         val = load_cattr_value (image, prop_type, named, &named);
7165                         obj = type_is_reference (prop_type) ? val : mono_value_box (domain, mono_class_from_mono_type (prop_type), val);
7166                         typedarg = create_cattr_typed_arg (prop_type, obj);
7167                         namedarg = create_cattr_named_arg (minfo, typedarg);
7168                         mono_array_setref (namedargs, j, namedarg);
7169                         if (!type_is_reference (prop_type))
7170                                 g_free (val);
7171                 }
7172                 g_free (name);
7173         }
7174         attr = mono_object_new (domain, mono_defaults.customattribute_data_class);
7175         params [0] = mono_method_get_object (domain, method, NULL);
7176         params [1] = typedargs;
7177         params [2] = namedargs;
7178         mono_runtime_invoke (ctor, attr, params, NULL);
7179         return attr;
7180 }
7181
7182 MonoArray*
7183 mono_custom_attrs_construct (MonoCustomAttrInfo *cinfo)
7184 {
7185         MonoArray *result;
7186         MonoObject *attr;
7187         int i;
7188
7189         result = mono_array_new (mono_domain_get (), mono_defaults.attribute_class, cinfo->num_attrs);
7190         for (i = 0; i < cinfo->num_attrs; ++i) {
7191                 attr = create_custom_attr (cinfo->image, cinfo->attrs [i].ctor, cinfo->attrs [i].data, cinfo->attrs [i].data_size);
7192                 mono_array_setref (result, i, attr);
7193         }
7194         return result;
7195 }
7196
7197 static MonoArray*
7198 mono_custom_attrs_construct_by_type (MonoCustomAttrInfo *cinfo, MonoClass *attr_klass)
7199 {
7200         MonoArray *result;
7201         MonoObject *attr;
7202         int i, n;
7203
7204         n = 0;
7205         for (i = 0; i < cinfo->num_attrs; ++i) {
7206                 if (mono_class_is_assignable_from (attr_klass, cinfo->attrs [i].ctor->klass))
7207                         n ++;
7208         }
7209
7210         result = mono_array_new (mono_domain_get (), mono_defaults.attribute_class, n);
7211         n = 0;
7212         for (i = 0; i < cinfo->num_attrs; ++i) {
7213                 if (mono_class_is_assignable_from (attr_klass, cinfo->attrs [i].ctor->klass)) {
7214                         attr = create_custom_attr (cinfo->image, cinfo->attrs [i].ctor, cinfo->attrs [i].data, cinfo->attrs [i].data_size);
7215                         mono_array_setref (result, n, attr);
7216                         n ++;
7217                 }
7218         }
7219         return result;
7220 }
7221
7222 static MonoArray*
7223 mono_custom_attrs_data_construct (MonoCustomAttrInfo *cinfo)
7224 {
7225         MonoArray *result;
7226         MonoObject *attr;
7227         int i;
7228         
7229         result = mono_array_new (mono_domain_get (), mono_defaults.customattribute_data_class, cinfo->num_attrs);
7230         for (i = 0; i < cinfo->num_attrs; ++i) {
7231                 attr = create_custom_attr_data (cinfo->image, cinfo->attrs [i].ctor, cinfo->attrs [i].data, cinfo->attrs [i].data_size);
7232                 mono_array_setref (result, i, attr);
7233         }
7234         return result;
7235 }
7236
7237 /**
7238  * mono_custom_attrs_from_index:
7239  *
7240  * Returns: NULL if no attributes are found or if a loading error occurs.
7241  */
7242 MonoCustomAttrInfo*
7243 mono_custom_attrs_from_index (MonoImage *image, guint32 idx)
7244 {
7245         guint32 mtoken, i, len;
7246         guint32 cols [MONO_CUSTOM_ATTR_SIZE];
7247         MonoTableInfo *ca;
7248         MonoCustomAttrInfo *ainfo;
7249         GList *tmp, *list = NULL;
7250         const char *data;
7251
7252         ca = &image->tables [MONO_TABLE_CUSTOMATTRIBUTE];
7253
7254         i = mono_metadata_custom_attrs_from_index (image, idx);
7255         if (!i)
7256                 return NULL;
7257         i --;
7258         while (i < ca->rows) {
7259                 if (mono_metadata_decode_row_col (ca, i, MONO_CUSTOM_ATTR_PARENT) != idx)
7260                         break;
7261                 list = g_list_prepend (list, GUINT_TO_POINTER (i));
7262                 ++i;
7263         }
7264         len = g_list_length (list);
7265         if (!len)
7266                 return NULL;
7267         ainfo = g_malloc0 (sizeof (MonoCustomAttrInfo) + sizeof (MonoCustomAttrEntry) * (len - MONO_ZERO_LEN_ARRAY));
7268         ainfo->num_attrs = len;
7269         ainfo->image = image;
7270         for (i = 0, tmp = list; i < len; ++i, tmp = tmp->next) {
7271                 mono_metadata_decode_row (ca, GPOINTER_TO_UINT (tmp->data), cols, MONO_CUSTOM_ATTR_SIZE);
7272                 mtoken = cols [MONO_CUSTOM_ATTR_TYPE] >> MONO_CUSTOM_ATTR_TYPE_BITS;
7273                 switch (cols [MONO_CUSTOM_ATTR_TYPE] & MONO_CUSTOM_ATTR_TYPE_MASK) {
7274                 case MONO_CUSTOM_ATTR_TYPE_METHODDEF:
7275                         mtoken |= MONO_TOKEN_METHOD_DEF;
7276                         break;
7277                 case MONO_CUSTOM_ATTR_TYPE_MEMBERREF:
7278                         mtoken |= MONO_TOKEN_MEMBER_REF;
7279                         break;
7280                 default:
7281                         g_error ("Unknown table for custom attr type %08x", cols [MONO_CUSTOM_ATTR_TYPE]);
7282                         break;
7283                 }
7284                 ainfo->attrs [i].ctor = mono_get_method (image, mtoken, NULL);
7285                 if (!ainfo->attrs [i].ctor) {
7286                         g_warning ("Can't find custom attr constructor image: %s mtoken: 0x%08x", image->name, mtoken);
7287                         g_list_free (list);
7288                         g_free (ainfo);
7289                         return NULL;
7290                 }
7291                 data = mono_metadata_blob_heap (image, cols [MONO_CUSTOM_ATTR_VALUE]);
7292                 ainfo->attrs [i].data_size = mono_metadata_decode_value (data, &data);
7293                 ainfo->attrs [i].data = (guchar*)data;
7294         }
7295         g_list_free (list);
7296
7297         return ainfo;
7298 }
7299
7300 MonoCustomAttrInfo*
7301 mono_custom_attrs_from_method (MonoMethod *method)
7302 {
7303         MonoCustomAttrInfo *cinfo;
7304         guint32 idx;
7305         
7306         if (dynamic_custom_attrs && (cinfo = lookup_custom_attr (method)))
7307                 return cinfo;
7308         idx = mono_method_get_index (method);
7309         idx <<= MONO_CUSTOM_ATTR_BITS;
7310         idx |= MONO_CUSTOM_ATTR_METHODDEF;
7311         return mono_custom_attrs_from_index (method->klass->image, idx);
7312 }
7313
7314 MonoCustomAttrInfo*
7315 mono_custom_attrs_from_class (MonoClass *klass)
7316 {
7317         MonoCustomAttrInfo *cinfo;
7318         guint32 idx;
7319         
7320         if (dynamic_custom_attrs && (cinfo = lookup_custom_attr (klass)))
7321                 return cinfo;
7322         idx = mono_metadata_token_index (klass->type_token);
7323         idx <<= MONO_CUSTOM_ATTR_BITS;
7324         idx |= MONO_CUSTOM_ATTR_TYPEDEF;
7325         return mono_custom_attrs_from_index (klass->image, idx);
7326 }
7327
7328 MonoCustomAttrInfo*
7329 mono_custom_attrs_from_assembly (MonoAssembly *assembly)
7330 {
7331         MonoCustomAttrInfo *cinfo;
7332         guint32 idx;
7333         
7334         if (dynamic_custom_attrs && (cinfo = lookup_custom_attr (assembly)))
7335                 return cinfo;
7336         idx = 1; /* there is only one assembly */
7337         idx <<= MONO_CUSTOM_ATTR_BITS;
7338         idx |= MONO_CUSTOM_ATTR_ASSEMBLY;
7339         return mono_custom_attrs_from_index (assembly->image, idx);
7340 }
7341
7342 static MonoCustomAttrInfo*
7343 mono_custom_attrs_from_module (MonoImage *image)
7344 {
7345         MonoCustomAttrInfo *cinfo;
7346         guint32 idx;
7347         
7348         if (dynamic_custom_attrs && (cinfo = lookup_custom_attr (image)))
7349                 return cinfo;
7350         idx = 1; /* there is only one module */
7351         idx <<= MONO_CUSTOM_ATTR_BITS;
7352         idx |= MONO_CUSTOM_ATTR_MODULE;
7353         return mono_custom_attrs_from_index (image, idx);
7354 }
7355
7356 MonoCustomAttrInfo*
7357 mono_custom_attrs_from_property (MonoClass *klass, MonoProperty *property)
7358 {
7359         MonoCustomAttrInfo *cinfo;
7360         guint32 idx;
7361         
7362         if (dynamic_custom_attrs && (cinfo = lookup_custom_attr (property)))
7363                 return cinfo;
7364         idx = find_property_index (klass, property);
7365         idx <<= MONO_CUSTOM_ATTR_BITS;
7366         idx |= MONO_CUSTOM_ATTR_PROPERTY;
7367         return mono_custom_attrs_from_index (klass->image, idx);
7368 }
7369
7370 MonoCustomAttrInfo*
7371 mono_custom_attrs_from_event (MonoClass *klass, MonoEvent *event)
7372 {
7373         MonoCustomAttrInfo *cinfo;
7374         guint32 idx;
7375         
7376         if (dynamic_custom_attrs && (cinfo = lookup_custom_attr (event)))
7377                 return cinfo;
7378         idx = find_event_index (klass, event);
7379         idx <<= MONO_CUSTOM_ATTR_BITS;
7380         idx |= MONO_CUSTOM_ATTR_EVENT;
7381         return mono_custom_attrs_from_index (klass->image, idx);
7382 }
7383
7384 MonoCustomAttrInfo*
7385 mono_custom_attrs_from_field (MonoClass *klass, MonoClassField *field)
7386 {
7387         MonoCustomAttrInfo *cinfo;
7388         guint32 idx;
7389         
7390         if (dynamic_custom_attrs && (cinfo = lookup_custom_attr (field)))
7391                 return cinfo;
7392         idx = find_field_index (klass, field);
7393         idx <<= MONO_CUSTOM_ATTR_BITS;
7394         idx |= MONO_CUSTOM_ATTR_FIELDDEF;
7395         return mono_custom_attrs_from_index (klass->image, idx);
7396 }
7397
7398 MonoCustomAttrInfo*
7399 mono_custom_attrs_from_param (MonoMethod *method, guint32 param)
7400 {
7401         MonoTableInfo *ca;
7402         guint32 i, idx, method_index;
7403         guint32 param_list, param_last, param_pos, found;
7404         MonoImage *image;
7405         MonoReflectionMethodAux *aux;
7406
7407         if (method->klass->image->dynamic) {
7408                 MonoCustomAttrInfo *res, *ainfo;
7409                 int size;
7410
7411                 aux = g_hash_table_lookup (((MonoDynamicImage*)method->klass->image)->method_aux_hash, method);
7412                 if (!aux || !aux->param_cattr)
7413                         return NULL;
7414
7415                 /* Need to copy since it will be freed later */
7416                 ainfo = aux->param_cattr [param];
7417                 size = sizeof (MonoCustomAttrInfo) + sizeof (MonoCustomAttrEntry) * (ainfo->num_attrs - MONO_ZERO_LEN_ARRAY);
7418                 res = g_malloc0 (size);
7419                 memcpy (res, ainfo, size);
7420                 return res;
7421         }
7422
7423         image = method->klass->image;
7424         method_index = mono_method_get_index (method);
7425         ca = &image->tables [MONO_TABLE_METHOD];
7426
7427         param_list = mono_metadata_decode_row_col (ca, method_index - 1, MONO_METHOD_PARAMLIST);
7428         if (method_index == ca->rows) {
7429                 ca = &image->tables [MONO_TABLE_PARAM];
7430                 param_last = ca->rows + 1;
7431         } else {
7432                 param_last = mono_metadata_decode_row_col (ca, method_index, MONO_METHOD_PARAMLIST);
7433                 ca = &image->tables [MONO_TABLE_PARAM];
7434         }
7435         found = FALSE;
7436         for (i = param_list; i < param_last; ++i) {
7437                 param_pos = mono_metadata_decode_row_col (ca, i - 1, MONO_PARAM_SEQUENCE);
7438                 if (param_pos == param) {
7439                         found = TRUE;
7440                         break;
7441                 }
7442         }
7443         if (!found)
7444                 return NULL;
7445         idx = i;
7446         idx <<= MONO_CUSTOM_ATTR_BITS;
7447         idx |= MONO_CUSTOM_ATTR_PARAMDEF;
7448         return mono_custom_attrs_from_index (image, idx);
7449 }
7450
7451 gboolean
7452 mono_custom_attrs_has_attr (MonoCustomAttrInfo *ainfo, MonoClass *attr_klass)
7453 {
7454         int i;
7455         MonoClass *klass;
7456         for (i = 0; i < ainfo->num_attrs; ++i) {
7457                 klass = ainfo->attrs [i].ctor->klass;
7458                 if (mono_class_has_parent (klass, attr_klass))
7459                         return TRUE;
7460         }
7461         return FALSE;
7462 }
7463
7464 MonoObject*
7465 mono_custom_attrs_get_attr (MonoCustomAttrInfo *ainfo, MonoClass *attr_klass)
7466 {
7467         int i, attr_index;
7468         MonoClass *klass;
7469         MonoArray *attrs;
7470
7471         attr_index = -1;
7472         for (i = 0; i < ainfo->num_attrs; ++i) {
7473                 klass = ainfo->attrs [i].ctor->klass;
7474                 if (mono_class_has_parent (klass, attr_klass)) {
7475                         attr_index = i;
7476                         break;
7477                 }
7478         }
7479         if (attr_index == -1)
7480                 return NULL;
7481
7482         attrs = mono_custom_attrs_construct (ainfo);
7483         if (attrs)
7484                 return mono_array_get (attrs, MonoObject*, attr_index);
7485         else
7486                 return NULL;
7487 }
7488
7489 /*
7490  * mono_reflection_get_custom_attrs_info:
7491  * @obj: a reflection object handle
7492  *
7493  * Return the custom attribute info for attributes defined for the
7494  * reflection handle @obj. The objects.
7495  */
7496 MonoCustomAttrInfo*
7497 mono_reflection_get_custom_attrs_info (MonoObject *obj)
7498 {
7499         MonoClass *klass;
7500         MonoCustomAttrInfo *cinfo = NULL;
7501         
7502         klass = obj->vtable->klass;
7503         if (klass == mono_defaults.monotype_class) {
7504                 MonoReflectionType *rtype = (MonoReflectionType*)obj;
7505                 klass = mono_class_from_mono_type (rtype->type);
7506                 cinfo = mono_custom_attrs_from_class (klass);
7507         } else if (strcmp ("Assembly", klass->name) == 0) {
7508                 MonoReflectionAssembly *rassembly = (MonoReflectionAssembly*)obj;
7509                 cinfo = mono_custom_attrs_from_assembly (rassembly->assembly);
7510         } else if (strcmp ("Module", klass->name) == 0) {
7511                 MonoReflectionModule *module = (MonoReflectionModule*)obj;
7512                 cinfo = mono_custom_attrs_from_module (module->image);
7513         } else if (strcmp ("MonoProperty", klass->name) == 0) {
7514                 MonoReflectionProperty *rprop = (MonoReflectionProperty*)obj;
7515                 cinfo = mono_custom_attrs_from_property (rprop->property->parent, rprop->property);
7516         } else if (strcmp ("MonoEvent", klass->name) == 0) {
7517                 MonoReflectionEvent *revent = (MonoReflectionEvent*)obj;
7518                 cinfo = mono_custom_attrs_from_event (revent->event->parent, revent->event);
7519         } else if (strcmp ("MonoField", klass->name) == 0) {
7520                 MonoReflectionField *rfield = (MonoReflectionField*)obj;
7521                 cinfo = mono_custom_attrs_from_field (rfield->field->parent, rfield->field);
7522         } else if ((strcmp ("MonoMethod", klass->name) == 0) || (strcmp ("MonoCMethod", klass->name) == 0)) {
7523                 MonoReflectionMethod *rmethod = (MonoReflectionMethod*)obj;
7524                 cinfo = mono_custom_attrs_from_method (rmethod->method);
7525         } else if ((strcmp ("MonoGenericMethod", klass->name) == 0) || (strcmp ("MonoGenericCMethod", klass->name) == 0)) {
7526                 MonoReflectionMethod *rmethod = (MonoReflectionMethod*)obj;
7527                 cinfo = mono_custom_attrs_from_method (rmethod->method);
7528         } else if (strcmp ("ParameterInfo", klass->name) == 0) {
7529                 MonoReflectionParameter *param = (MonoReflectionParameter*)obj;
7530                 MonoReflectionMethod *rmethod = (MonoReflectionMethod*)param->MemberImpl;
7531                 cinfo = mono_custom_attrs_from_param (rmethod->method, param->PositionImpl + 1);
7532         } else if (strcmp ("AssemblyBuilder", klass->name) == 0) {
7533                 MonoReflectionAssemblyBuilder *assemblyb = (MonoReflectionAssemblyBuilder*)obj;
7534                 cinfo = mono_custom_attrs_from_builders (assemblyb->assembly.assembly->image, assemblyb->cattrs);
7535         } else if (strcmp ("TypeBuilder", klass->name) == 0) {
7536                 MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder*)obj;
7537                 cinfo = mono_custom_attrs_from_builders (&tb->module->dynamic_image->image, tb->cattrs);
7538         } else if (strcmp ("ModuleBuilder", klass->name) == 0) {
7539                 MonoReflectionModuleBuilder *mb = (MonoReflectionModuleBuilder*)obj;
7540                 cinfo = mono_custom_attrs_from_builders (&mb->dynamic_image->image, mb->cattrs);
7541         } else if (strcmp ("ConstructorBuilder", klass->name) == 0) {
7542                 MonoReflectionCtorBuilder *cb = (MonoReflectionCtorBuilder*)obj;
7543                 cinfo = mono_custom_attrs_from_builders (cb->mhandle->klass->image, cb->cattrs);
7544         } else if (strcmp ("MethodBuilder", klass->name) == 0) {
7545                 MonoReflectionMethodBuilder *mb = (MonoReflectionMethodBuilder*)obj;
7546                 cinfo = mono_custom_attrs_from_builders (mb->mhandle->klass->image, mb->cattrs);
7547         } else if (strcmp ("FieldBuilder", klass->name) == 0) {
7548                 MonoReflectionFieldBuilder *fb = (MonoReflectionFieldBuilder*)obj;
7549                 cinfo = mono_custom_attrs_from_builders (&((MonoReflectionTypeBuilder*)fb->typeb)->module->dynamic_image->image, fb->cattrs);
7550         } else if (strcmp ("MonoGenericClass", klass->name) == 0) {
7551                 MonoReflectionGenericClass *gclass = (MonoReflectionGenericClass*)obj;
7552                 cinfo = mono_reflection_get_custom_attrs_info ((MonoObject*)gclass->generic_type);
7553         } else { /* handle other types here... */
7554                 g_error ("get custom attrs not yet supported for %s", klass->name);
7555         }
7556
7557         return cinfo;
7558 }
7559
7560 /*
7561  * mono_reflection_get_custom_attrs_by_type:
7562  * @obj: a reflection object handle
7563  *
7564  * Return an array with all the custom attributes defined of the
7565  * reflection handle @obj. If @attr_klass is non-NULL, only custom attributes 
7566  * of that type are returned. The objects are fully build. Return NULL if a loading error
7567  * occurs.
7568  */
7569 MonoArray*
7570 mono_reflection_get_custom_attrs_by_type (MonoObject *obj, MonoClass *attr_klass)
7571 {
7572         MonoArray *result;
7573         MonoCustomAttrInfo *cinfo;
7574
7575         cinfo = mono_reflection_get_custom_attrs_info (obj);
7576         if (cinfo) {
7577                 if (attr_klass)
7578                         result = mono_custom_attrs_construct_by_type (cinfo, attr_klass);
7579                 else
7580                         result = mono_custom_attrs_construct (cinfo);
7581                 if (!cinfo->cached)
7582                         mono_custom_attrs_free (cinfo);
7583         } else {
7584                 if (mono_loader_get_last_error ())
7585                         return NULL;
7586                 result = mono_array_new (mono_domain_get (), mono_defaults.attribute_class, 0);
7587         }
7588
7589         return result;
7590 }
7591
7592 /*
7593  * mono_reflection_get_custom_attrs:
7594  * @obj: a reflection object handle
7595  *
7596  * Return an array with all the custom attributes defined of the
7597  * reflection handle @obj. The objects are fully build. Return NULL if a loading error
7598  * occurs.
7599  */
7600 MonoArray*
7601 mono_reflection_get_custom_attrs (MonoObject *obj)
7602 {
7603         return mono_reflection_get_custom_attrs_by_type (obj, NULL);
7604 }
7605
7606 /*
7607  * mono_reflection_get_custom_attrs_data:
7608  * @obj: a reflection obj handle
7609  *
7610  * Returns an array of System.Reflection.CustomAttributeData,
7611  * which include information about attributes reflected on
7612  * types loaded using the Reflection Only methods
7613  */
7614 MonoArray*
7615 mono_reflection_get_custom_attrs_data (MonoObject *obj)
7616 {
7617         MonoArray *result;
7618         MonoCustomAttrInfo *cinfo;
7619
7620         cinfo = mono_reflection_get_custom_attrs_info (obj);
7621         if (cinfo) {
7622                 result = mono_custom_attrs_data_construct (cinfo);
7623                 if (!cinfo->cached)
7624                         mono_custom_attrs_free (cinfo);
7625         } else
7626                 result = mono_array_new (mono_domain_get (), mono_defaults.customattribute_data_class, 0);
7627
7628         return result;
7629 }
7630
7631 static MonoReflectionType*
7632 mono_reflection_type_get_underlying_system_type (MonoReflectionType* t)
7633 {
7634         MonoMethod *method_get_underlying_system_type;
7635
7636         method_get_underlying_system_type = mono_object_get_virtual_method ((MonoObject *) t,
7637                                                                             mono_class_get_method_from_name (mono_object_class (t),
7638                                                                                                              "get_UnderlyingSystemType",
7639                                                                                                              0));
7640         return (MonoReflectionType *) mono_runtime_invoke (method_get_underlying_system_type, t, NULL, NULL);
7641 }
7642
7643 static MonoType*
7644 mono_reflection_type_get_handle (MonoReflectionType* t)
7645 {
7646         if (t->type)
7647             return t->type;
7648
7649         t = mono_reflection_type_get_underlying_system_type (t);
7650         if (t)
7651             return t->type;
7652
7653         return NULL;
7654 }
7655
7656 /**
7657  * LOCKING: Assumes the loader lock is held.
7658  */
7659 static MonoMethodSignature*
7660 parameters_to_signature (MonoMemPool *mp, MonoArray *parameters) {
7661         MonoMethodSignature *sig;
7662         int count, i;
7663
7664         count = parameters? mono_array_length (parameters): 0;
7665
7666         sig = mp_g_malloc0 (mp, sizeof (MonoMethodSignature) + sizeof (MonoType*) * count);
7667         sig->param_count = count;
7668         sig->sentinelpos = -1; /* FIXME */
7669         for (i = 0; i < count; ++i) {
7670                 MonoReflectionType *pt = mono_array_get (parameters, MonoReflectionType*, i);
7671                 sig->params [i] = mono_reflection_type_get_handle (pt);
7672         }
7673         return sig;
7674 }
7675
7676 /**
7677  * LOCKING: Assumes the loader lock is held.
7678  */
7679 static MonoMethodSignature*
7680 ctor_builder_to_signature (MonoMemPool *mp, MonoReflectionCtorBuilder *ctor) {
7681         MonoMethodSignature *sig;
7682
7683         sig = parameters_to_signature (mp, ctor->parameters);
7684         sig->hasthis = ctor->attrs & METHOD_ATTRIBUTE_STATIC? 0: 1;
7685         sig->ret = &mono_defaults.void_class->byval_arg;
7686         return sig;
7687 }
7688
7689 /**
7690  * LOCKING: Assumes the loader lock is held.
7691  */
7692 static MonoMethodSignature*
7693 method_builder_to_signature (MonoMemPool *mp, MonoReflectionMethodBuilder *method) {
7694         MonoMethodSignature *sig;
7695
7696         sig = parameters_to_signature (mp, method->parameters);
7697         sig->hasthis = method->attrs & METHOD_ATTRIBUTE_STATIC? 0: 1;
7698         sig->ret = method->rtype? method->rtype->type: &mono_defaults.void_class->byval_arg;
7699         sig->generic_param_count = method->generic_params ? mono_array_length (method->generic_params) : 0;
7700         return sig;
7701 }
7702
7703 static MonoMethodSignature*
7704 dynamic_method_to_signature (MonoReflectionDynamicMethod *method) {
7705         MonoMethodSignature *sig;
7706
7707         sig = parameters_to_signature (NULL, method->parameters);
7708         sig->hasthis = method->attrs & METHOD_ATTRIBUTE_STATIC? 0: 1;
7709         sig->ret = method->rtype? method->rtype->type: &mono_defaults.void_class->byval_arg;
7710         sig->generic_param_count = 0;
7711         return sig;
7712 }
7713
7714 static void
7715 get_prop_name_and_type (MonoObject *prop, char **name, MonoType **type)
7716 {
7717         MonoClass *klass = mono_object_class (prop);
7718         if (strcmp (klass->name, "PropertyBuilder") == 0) {
7719                 MonoReflectionPropertyBuilder *pb = (MonoReflectionPropertyBuilder *)prop;
7720                 *name = mono_string_to_utf8 (pb->name);
7721                 *type = pb->type->type;
7722         } else {
7723                 MonoReflectionProperty *p = (MonoReflectionProperty *)prop;
7724                 *name = g_strdup (p->property->name);
7725                 if (p->property->get)
7726                         *type = mono_method_signature (p->property->get)->ret;
7727                 else
7728                         *type = mono_method_signature (p->property->set)->params [mono_method_signature (p->property->set)->param_count - 1];
7729         }
7730 }
7731
7732 static void
7733 get_field_name_and_type (MonoObject *field, char **name, MonoType **type)
7734 {
7735         MonoClass *klass = mono_object_class (field);
7736         if (strcmp (klass->name, "FieldBuilder") == 0) {
7737                 MonoReflectionFieldBuilder *fb = (MonoReflectionFieldBuilder *)field;
7738                 *name = mono_string_to_utf8 (fb->name);
7739                 *type = fb->type->type;
7740         } else {
7741                 MonoReflectionField *f = (MonoReflectionField *)field;
7742                 *name = g_strdup (f->field->name);
7743                 *type = f->field->type;
7744         }
7745 }
7746
7747 /*
7748  * Encode a value in a custom attribute stream of bytes.
7749  * The value to encode is either supplied as an object in argument val
7750  * (valuetypes are boxed), or as a pointer to the data in the
7751  * argument argval.
7752  * @type represents the type of the value
7753  * @buffer is the start of the buffer
7754  * @p the current position in the buffer
7755  * @buflen contains the size of the buffer and is used to return the new buffer size
7756  * if this needs to be realloced.
7757  * @retbuffer and @retp return the start and the position of the buffer
7758  */
7759 static void
7760 encode_cattr_value (MonoAssembly *assembly, char *buffer, char *p, char **retbuffer, char **retp, guint32 *buflen, MonoType *type, MonoObject *arg, char *argval)
7761 {
7762         MonoTypeEnum simple_type;
7763         
7764         if ((p-buffer) + 10 >= *buflen) {
7765                 char *newbuf;
7766                 *buflen *= 2;
7767                 newbuf = g_realloc (buffer, *buflen);
7768                 p = newbuf + (p-buffer);
7769                 buffer = newbuf;
7770         }
7771         if (!argval)
7772                 argval = ((char*)arg + sizeof (MonoObject));
7773         simple_type = type->type;
7774 handle_enum:
7775         switch (simple_type) {
7776         case MONO_TYPE_BOOLEAN:
7777         case MONO_TYPE_U1:
7778         case MONO_TYPE_I1:
7779                 *p++ = *argval;
7780                 break;
7781         case MONO_TYPE_CHAR:
7782         case MONO_TYPE_U2:
7783         case MONO_TYPE_I2:
7784                 swap_with_size (p, argval, 2, 1);
7785                 p += 2;
7786                 break;
7787         case MONO_TYPE_U4:
7788         case MONO_TYPE_I4:
7789         case MONO_TYPE_R4:
7790                 swap_with_size (p, argval, 4, 1);
7791                 p += 4;
7792                 break;
7793         case MONO_TYPE_R8:
7794 #if defined(ARM_FPU_FPA) && G_BYTE_ORDER == G_LITTLE_ENDIAN
7795                 p [0] = argval [4];
7796                 p [1] = argval [5];
7797                 p [2] = argval [6];
7798                 p [3] = argval [7];
7799                 p [4] = argval [0];
7800                 p [5] = argval [1];
7801                 p [6] = argval [2];
7802                 p [7] = argval [3];
7803 #else
7804                 swap_with_size (p, argval, 8, 1);
7805 #endif
7806                 p += 8;
7807                 break;
7808         case MONO_TYPE_U8:
7809         case MONO_TYPE_I8:
7810                 swap_with_size (p, argval, 8, 1);
7811                 p += 8;
7812                 break;
7813         case MONO_TYPE_VALUETYPE:
7814                 if (type->data.klass->enumtype) {
7815                         simple_type = type->data.klass->enum_basetype->type;
7816                         goto handle_enum;
7817                 } else {
7818                         g_warning ("generic valutype %s not handled in custom attr value decoding", type->data.klass->name);
7819                 }
7820                 break;
7821         case MONO_TYPE_STRING: {
7822                 char *str;
7823                 guint32 slen;
7824                 if (!arg) {
7825                         *p++ = 0xFF;
7826                         break;
7827                 }
7828                 str = mono_string_to_utf8 ((MonoString*)arg);
7829                 slen = strlen (str);
7830                 if ((p-buffer) + 10 + slen >= *buflen) {
7831                         char *newbuf;
7832                         *buflen *= 2;
7833                         *buflen += slen;
7834                         newbuf = g_realloc (buffer, *buflen);
7835                         p = newbuf + (p-buffer);
7836                         buffer = newbuf;
7837                 }
7838                 mono_metadata_encode_value (slen, p, &p);
7839                 memcpy (p, str, slen);
7840                 p += slen;
7841                 g_free (str);
7842                 break;
7843         }
7844         case MONO_TYPE_CLASS: {
7845                 char *str;
7846                 guint32 slen;
7847                 MonoClass *k;
7848                 if (!arg) {
7849                         *p++ = 0xFF;
7850                         break;
7851                 }
7852                 k = mono_object_class (arg);
7853                 if (!mono_object_isinst (arg, mono_defaults.monotype_class) &&
7854                         (strcmp (k->name, "TypeBuilder") || strcmp (k->name_space, "System.Reflection.Emit"))) {
7855                         MonoReflectionType* rt = mono_reflection_type_get_underlying_system_type ((MonoReflectionType*) arg);
7856                         MonoClass *rtc;
7857                         
7858                         if (rt && (rtc = mono_object_class (rt)) &&
7859                                    (mono_object_isinst ((MonoObject *) rt, mono_defaults.monotype_class) ||
7860                                     !strcmp (rtc->name, "TypeBuilder") || !strcmp (rtc->name_space, "System.Reflection.Emit"))) {
7861                                 arg = (MonoObject *) rt;
7862                                 k = rtc;
7863                         } else
7864                                 g_error ("Only System.Type allowed, not %s.%s", k->name_space, k->name);
7865                 }
7866 handle_type:
7867                 str = type_get_qualified_name (((MonoReflectionType*)arg)->type, NULL);
7868                 slen = strlen (str);
7869                 if ((p-buffer) + 10 + slen >= *buflen) {
7870                         char *newbuf;
7871                         *buflen *= 2;
7872                         *buflen += slen;
7873                         newbuf = g_realloc (buffer, *buflen);
7874                         p = newbuf + (p-buffer);
7875                         buffer = newbuf;
7876                 }
7877                 mono_metadata_encode_value (slen, p, &p);
7878                 memcpy (p, str, slen);
7879                 p += slen;
7880                 g_free (str);
7881                 break;
7882         }
7883         case MONO_TYPE_SZARRAY: {
7884                 int len, i;
7885                 MonoClass *eclass, *arg_eclass;
7886
7887                 if (!arg) {
7888                         *p++ = 0xff; *p++ = 0xff; *p++ = 0xff; *p++ = 0xff;
7889                         break;
7890                 }
7891                 len = mono_array_length ((MonoArray*)arg);
7892                 *p++ = len & 0xff;
7893                 *p++ = (len >> 8) & 0xff;
7894                 *p++ = (len >> 16) & 0xff;
7895                 *p++ = (len >> 24) & 0xff;
7896                 *retp = p;
7897                 *retbuffer = buffer;
7898                 eclass = type->data.klass;
7899                 arg_eclass = mono_object_class (arg)->element_class;
7900
7901                 if (!eclass) {
7902                         /* Happens when we are called from the MONO_TYPE_OBJECT case below */
7903                         eclass = mono_defaults.object_class;
7904                 }
7905                 if (eclass == mono_defaults.object_class && arg_eclass->valuetype) {
7906                         char *elptr = mono_array_addr ((MonoArray*)arg, char, 0);
7907                         int elsize = mono_class_array_element_size (arg_eclass);
7908                         for (i = 0; i < len; ++i) {
7909                                 encode_cattr_value (assembly, buffer, p, &buffer, &p, buflen, &arg_eclass->byval_arg, NULL, elptr);
7910                                 elptr += elsize;
7911                         }
7912                 } else if (eclass->valuetype && arg_eclass->valuetype) {
7913                         char *elptr = mono_array_addr ((MonoArray*)arg, char, 0);
7914                         int elsize = mono_class_array_element_size (eclass);
7915                         for (i = 0; i < len; ++i) {
7916                                 encode_cattr_value (assembly, buffer, p, &buffer, &p, buflen, &eclass->byval_arg, NULL, elptr);
7917                                 elptr += elsize;
7918                         }
7919                 } else {
7920                         for (i = 0; i < len; ++i) {
7921                                 encode_cattr_value (assembly, buffer, p, &buffer, &p, buflen, &eclass->byval_arg, mono_array_get ((MonoArray*)arg, MonoObject*, i), NULL);
7922                         }
7923                 }
7924                 break;
7925         }
7926         case MONO_TYPE_OBJECT: {
7927                 MonoClass *klass;
7928                 char *str;
7929                 guint32 slen;
7930
7931                 /*
7932                  * The parameter type is 'object' but the type of the actual
7933                  * argument is not. So we have to add type information to the blob
7934                  * too. This is completely undocumented in the spec.
7935                  */
7936
7937                 if (arg == NULL) {
7938                         *p++ = MONO_TYPE_STRING;        // It's same hack as MS uses
7939                         *p++ = 0xFF;
7940                         break;
7941                 }
7942                 
7943                 klass = mono_object_class (arg);
7944
7945                 if (mono_object_isinst (arg, mono_defaults.systemtype_class)) {
7946                         *p++ = 0x50;
7947                         goto handle_type;
7948                 } else if (klass->enumtype) {
7949                         *p++ = 0x55;
7950                 } else if (klass == mono_defaults.string_class) {
7951                         simple_type = MONO_TYPE_STRING;
7952                         *p++ = 0x0E;
7953                         goto handle_enum;
7954                 } else if (klass->rank == 1) {
7955                         *p++ = 0x1D;
7956                         if (klass->element_class->byval_arg.type == MONO_TYPE_OBJECT)
7957                                 /* See Partition II, Appendix B3 */
7958                                 *p++ = 0x51;
7959                         else
7960                                 *p++ = klass->element_class->byval_arg.type;
7961                         encode_cattr_value (assembly, buffer, p, &buffer, &p, buflen, &klass->byval_arg, arg, NULL);
7962                         break;
7963                 } else if (klass->byval_arg.type >= MONO_TYPE_BOOLEAN && klass->byval_arg.type <= MONO_TYPE_R8) {
7964                         *p++ = simple_type = klass->byval_arg.type;
7965                         goto handle_enum;
7966                 } else {
7967                         g_error ("unhandled type in custom attr");
7968                 }
7969                 str = type_get_qualified_name (mono_class_get_type(klass), NULL);
7970                 slen = strlen (str);
7971                 if ((p-buffer) + 10 + slen >= *buflen) {
7972                         char *newbuf;
7973                         *buflen *= 2;
7974                         *buflen += slen;
7975                         newbuf = g_realloc (buffer, *buflen);
7976                         p = newbuf + (p-buffer);
7977                         buffer = newbuf;
7978                 }
7979                 mono_metadata_encode_value (slen, p, &p);
7980                 memcpy (p, str, slen);
7981                 p += slen;
7982                 g_free (str);
7983                 simple_type = klass->enum_basetype->type;
7984                 goto handle_enum;
7985         }
7986         default:
7987                 g_error ("type 0x%02x not yet supported in custom attr encoder", simple_type);
7988         }
7989         *retp = p;
7990         *retbuffer = buffer;
7991 }
7992
7993 static void
7994 encode_field_or_prop_type (MonoType *type, char *p, char **retp)
7995 {
7996         if (type->type == MONO_TYPE_VALUETYPE && type->data.klass->enumtype) {
7997                 char *str = type_get_qualified_name (type, NULL);
7998                 int slen = strlen (str);
7999
8000                 *p++ = 0x55;
8001                 /*
8002                  * This seems to be optional...
8003                  * *p++ = 0x80;
8004                  */
8005                 mono_metadata_encode_value (slen, p, &p);
8006                 memcpy (p, str, slen);
8007                 p += slen;
8008                 g_free (str);
8009         } else if (type->type == MONO_TYPE_OBJECT) {
8010                 *p++ = 0x51;
8011         } else if (type->type == MONO_TYPE_CLASS) {
8012                 /* it should be a type: encode_cattr_value () has the check */
8013                 *p++ = 0x50;
8014         } else {
8015                 mono_metadata_encode_value (type->type, p, &p);
8016                 if (type->type == MONO_TYPE_SZARRAY)
8017                         /* See the examples in Partition VI, Annex B */
8018                         encode_field_or_prop_type (&type->data.klass->byval_arg, p, &p);
8019         }
8020
8021         *retp = p;
8022 }
8023
8024 static void
8025 encode_named_val (MonoReflectionAssembly *assembly, char *buffer, char *p, char **retbuffer, char **retp, guint32 *buflen, MonoType *type, char *name, MonoObject *value)
8026 {
8027         int len;
8028         /* Preallocate a large enough buffer */
8029         if (type->type == MONO_TYPE_VALUETYPE && type->data.klass->enumtype) {
8030                 char *str = type_get_qualified_name (type, NULL);
8031                 len = strlen (str);
8032                 g_free (str);
8033         } else if (type->type == MONO_TYPE_SZARRAY && type->data.klass->enumtype) {
8034                 char *str = type_get_qualified_name (&type->data.klass->byval_arg, NULL);
8035                 len = strlen (str);
8036                 g_free (str);
8037         } else {
8038                 len = 0;
8039         }
8040         len += strlen (name);
8041
8042         if ((p-buffer) + 20 + len >= *buflen) {
8043                 char *newbuf;
8044                 *buflen *= 2;
8045                 *buflen += len;
8046                 newbuf = g_realloc (buffer, *buflen);
8047                 p = newbuf + (p-buffer);
8048                 buffer = newbuf;
8049         }
8050
8051         encode_field_or_prop_type (type, p, &p);
8052
8053         len = strlen (name);
8054         mono_metadata_encode_value (len, p, &p);
8055         memcpy (p, name, len);
8056         p += len;
8057         encode_cattr_value (assembly->assembly, buffer, p, &buffer, &p, buflen, type, value, NULL);
8058         *retp = p;
8059         *retbuffer = buffer;
8060 }
8061
8062 /*
8063  * mono_reflection_get_custom_attrs_blob:
8064  * @ctor: custom attribute constructor
8065  * @ctorArgs: arguments o the constructor
8066  * @properties:
8067  * @propValues:
8068  * @fields:
8069  * @fieldValues:
8070  * 
8071  * Creates the blob of data that needs to be saved in the metadata and that represents
8072  * the custom attributed described by @ctor, @ctorArgs etc.
8073  * Returns: a Byte array representing the blob of data.
8074  */
8075 MonoArray*
8076 mono_reflection_get_custom_attrs_blob (MonoReflectionAssembly *assembly, MonoObject *ctor, MonoArray *ctorArgs, MonoArray *properties, MonoArray *propValues, MonoArray *fields, MonoArray* fieldValues) 
8077 {
8078         MonoArray *result;
8079         MonoMethodSignature *sig;
8080         MonoObject *arg;
8081         char *buffer, *p;
8082         guint32 buflen, i;
8083
8084         MONO_ARCH_SAVE_REGS;
8085
8086         if (strcmp (ctor->vtable->klass->name, "MonoCMethod")) {
8087                 /* sig is freed later so allocate it in the heap */
8088                 sig = ctor_builder_to_signature (NULL, (MonoReflectionCtorBuilder*)ctor);
8089         } else {
8090                 sig = mono_method_signature (((MonoReflectionMethod*)ctor)->method);
8091         }
8092
8093         g_assert (mono_array_length (ctorArgs) == sig->param_count);
8094         buflen = 256;
8095         p = buffer = g_malloc (buflen);
8096         /* write the prolog */
8097         *p++ = 1;
8098         *p++ = 0;
8099         for (i = 0; i < sig->param_count; ++i) {
8100                 arg = mono_array_get (ctorArgs, MonoObject*, i);
8101                 encode_cattr_value (assembly->assembly, buffer, p, &buffer, &p, &buflen, sig->params [i], arg, NULL);
8102         }
8103         i = 0;
8104         if (properties)
8105                 i += mono_array_length (properties);
8106         if (fields)
8107                 i += mono_array_length (fields);
8108         *p++ = i & 0xff;
8109         *p++ = (i >> 8) & 0xff;
8110         if (properties) {
8111                 MonoObject *prop;
8112                 for (i = 0; i < mono_array_length (properties); ++i) {
8113                         MonoType *ptype;
8114                         char *pname;
8115
8116                         prop = mono_array_get (properties, gpointer, i);
8117                         get_prop_name_and_type (prop, &pname, &ptype);
8118                         *p++ = 0x54; /* PROPERTY signature */
8119                         encode_named_val (assembly, buffer, p, &buffer, &p, &buflen, ptype, pname, (MonoObject*)mono_array_get (propValues, gpointer, i));
8120                         g_free (pname);
8121                 }
8122         }
8123
8124         if (fields) {
8125                 MonoObject *field;
8126                 for (i = 0; i < mono_array_length (fields); ++i) {
8127                         MonoType *ftype;
8128                         char *fname;
8129
8130                         field = mono_array_get (fields, gpointer, i);
8131                         get_field_name_and_type (field, &fname, &ftype);
8132                         *p++ = 0x53; /* FIELD signature */
8133                         encode_named_val (assembly, buffer, p, &buffer, &p, &buflen, ftype, fname, (MonoObject*)mono_array_get (fieldValues, gpointer, i));
8134                         g_free (fname);
8135                 }
8136         }
8137
8138         g_assert (p - buffer <= buflen);
8139         buflen = p - buffer;
8140         result = mono_array_new (mono_domain_get (), mono_defaults.byte_class, buflen);
8141         p = mono_array_addr (result, char, 0);
8142         memcpy (p, buffer, buflen);
8143         g_free (buffer);
8144         if (strcmp (ctor->vtable->klass->name, "MonoCMethod"))
8145                 g_free (sig);
8146         return result;
8147 }
8148
8149 #if HAVE_SGEN_GC
8150 static void* reflection_info_desc = NULL;
8151 #define MOVING_GC_REGISTER(addr) do {   \
8152                 if (!reflection_info_desc) {    \
8153                         gsize bmap = 1;         \
8154                         reflection_info_desc = mono_gc_make_descr_from_bitmap (&bmap, 1);       \
8155                 }       \
8156                 mono_gc_register_root ((addr), sizeof (gpointer), reflection_info_desc);        \
8157         } while (0)
8158 #else
8159 #define MOVING_GC_REGISTER(addr)
8160 #endif
8161
8162 /*
8163  * mono_reflection_setup_internal_class:
8164  * @tb: a TypeBuilder object
8165  *
8166  * Creates a MonoClass that represents the TypeBuilder.
8167  * This is a trick that lets us simplify a lot of reflection code
8168  * (and will allow us to support Build and Run assemblies easier).
8169  */
8170 void
8171 mono_reflection_setup_internal_class (MonoReflectionTypeBuilder *tb)
8172 {
8173         MonoClass *klass, *parent;
8174
8175         MONO_ARCH_SAVE_REGS;
8176
8177         mono_loader_lock ();
8178
8179         if (tb->parent) {
8180                 /* check so we can compile corlib correctly */
8181                 if (strcmp (mono_object_class (tb->parent)->name, "TypeBuilder") == 0) {
8182                         /* mono_class_setup_mono_type () guaranteess type->data.klass is valid */
8183                         parent = tb->parent->type->data.klass;
8184                 } else {
8185                         parent = my_mono_class_from_mono_type (tb->parent->type);
8186                 }
8187         } else {
8188                 parent = NULL;
8189         }
8190         
8191         /* the type has already being created: it means we just have to change the parent */
8192         if (tb->type.type) {
8193                 klass = mono_class_from_mono_type (tb->type.type);
8194                 klass->parent = NULL;
8195                 /* fool mono_class_setup_parent */
8196                 klass->supertypes = NULL;
8197                 mono_class_setup_parent (klass, parent);
8198                 mono_class_setup_mono_type (klass);
8199                 mono_loader_unlock ();
8200                 return;
8201         }
8202
8203         klass = mono_mempool_alloc0 (tb->module->dynamic_image->image.mempool, sizeof (MonoClass));
8204
8205         klass->image = &tb->module->dynamic_image->image;
8206
8207         klass->inited = 1; /* we lie to the runtime */
8208         klass->name = mono_string_to_utf8_mp (klass->image->mempool, tb->name);
8209         klass->name_space = mono_string_to_utf8_mp (klass->image->mempool, tb->nspace);
8210         klass->type_token = MONO_TOKEN_TYPE_DEF | tb->table_idx;
8211         klass->flags = tb->attrs;
8212
8213         klass->element_class = klass;
8214
8215         MOVING_GC_REGISTER (&klass->reflection_info);
8216         klass->reflection_info = tb;
8217
8218         /* Put into cache so mono_class_get () will find it */
8219         mono_image_add_to_name_cache (klass->image, klass->name_space, klass->name, tb->table_idx);
8220
8221         mono_g_hash_table_insert (tb->module->dynamic_image->tokens,
8222                 GUINT_TO_POINTER (MONO_TOKEN_TYPE_DEF | tb->table_idx), tb);
8223
8224         if (parent != NULL) {
8225                 mono_class_setup_parent (klass, parent);
8226         } else if (strcmp (klass->name, "Object") == 0 && strcmp (klass->name_space, "System") == 0) {
8227                 const char *old_n = klass->name;
8228                 /* trick to get relative numbering right when compiling corlib */
8229                 klass->name = "BuildingObject";
8230                 mono_class_setup_parent (klass, mono_defaults.object_class);
8231                 klass->name = old_n;
8232         }
8233
8234         if ((!strcmp (klass->name, "ValueType") && !strcmp (klass->name_space, "System")) ||
8235                         (!strcmp (klass->name, "Object") && !strcmp (klass->name_space, "System")) ||
8236                         (!strcmp (klass->name, "Enum") && !strcmp (klass->name_space, "System"))) {
8237                 klass->instance_size = sizeof (MonoObject);
8238                 klass->size_inited = 1;
8239                 mono_class_setup_vtable_general (klass, NULL, 0);
8240         }
8241
8242         mono_class_setup_mono_type (klass);
8243
8244         mono_class_setup_supertypes (klass);
8245
8246         /*
8247          * FIXME: handle interfaces.
8248          */
8249
8250         tb->type.type = &klass->byval_arg;
8251
8252         if (tb->nesting_type) {
8253                 g_assert (tb->nesting_type->type);
8254                 klass->nested_in = mono_class_from_mono_type (tb->nesting_type->type);
8255         }
8256
8257         /*g_print ("setup %s as %s (%p)\n", klass->name, ((MonoObject*)tb)->vtable->klass->name, tb);*/
8258
8259         mono_loader_unlock ();
8260 }
8261
8262 /*
8263  * mono_reflection_setup_generic_class:
8264  * @tb: a TypeBuilder object
8265  *
8266  * Setup the generic class before adding the first generic parameter.
8267  */
8268 void
8269 mono_reflection_setup_generic_class (MonoReflectionTypeBuilder *tb)
8270 {
8271         MonoClass *klass;
8272
8273         MONO_ARCH_SAVE_REGS;
8274
8275         klass = my_mono_class_from_mono_type (tb->type.type);
8276         if (tb->generic_container)
8277                 return;
8278
8279         tb->generic_container = g_new0 (MonoGenericContainer, 1);
8280         tb->generic_container->owner.klass = klass;
8281 }
8282
8283 /*
8284  * mono_reflection_create_generic_class:
8285  * @tb: a TypeBuilder object
8286  *
8287  * Creates the generic class after all generic parameters have been added.
8288  */
8289 void
8290 mono_reflection_create_generic_class (MonoReflectionTypeBuilder *tb)
8291 {
8292         MonoClass *klass;
8293         int count, i;
8294
8295         MONO_ARCH_SAVE_REGS;
8296
8297         klass = my_mono_class_from_mono_type (tb->type.type);
8298
8299         count = tb->generic_params ? mono_array_length (tb->generic_params) : 0;
8300
8301         if (klass->generic_container || (count == 0))
8302                 return;
8303
8304         g_assert (tb->generic_container && (tb->generic_container->owner.klass == klass));
8305
8306         klass->generic_container = tb->generic_container;
8307
8308         klass->generic_container->type_argc = count;
8309         klass->generic_container->type_params = g_new0 (MonoGenericParam, count);
8310
8311         for (i = 0; i < count; i++) {
8312                 MonoReflectionGenericParam *gparam = mono_array_get (tb->generic_params, gpointer, i);
8313                 klass->generic_container->type_params [i] = *gparam->type.type->data.generic_param;
8314                 g_assert (klass->generic_container->type_params [i].owner);
8315         }
8316
8317         klass->generic_container->context.class_inst = mono_get_shared_generic_inst (klass->generic_container);
8318 }
8319
8320 /*
8321  * mono_reflection_create_internal_class:
8322  * @tb: a TypeBuilder object
8323  *
8324  * Actually create the MonoClass that is associated with the TypeBuilder.
8325  */
8326 void
8327 mono_reflection_create_internal_class (MonoReflectionTypeBuilder *tb)
8328 {
8329         MonoClass *klass;
8330
8331         MONO_ARCH_SAVE_REGS;
8332
8333         klass = my_mono_class_from_mono_type (tb->type.type);
8334
8335         mono_loader_lock ();
8336         if (klass->enumtype && klass->enum_basetype == NULL) {
8337                 MonoReflectionFieldBuilder *fb;
8338                 MonoClass *ec;
8339
8340                 g_assert (tb->fields != NULL);
8341                 g_assert (mono_array_length (tb->fields) >= 1);
8342
8343                 fb = mono_array_get (tb->fields, MonoReflectionFieldBuilder*, 0);
8344
8345                 if (!mono_type_is_valid_enum_basetype (fb->type->type)) {
8346                         mono_loader_unlock ();
8347                         return;
8348                 }
8349
8350                 klass->enum_basetype = fb->type->type;
8351                 klass->element_class = my_mono_class_from_mono_type (klass->enum_basetype);
8352                 if (!klass->element_class)
8353                         klass->element_class = mono_class_from_mono_type (klass->enum_basetype);
8354
8355                 /*
8356                  * get the element_class from the current corlib.
8357                  */
8358                 ec = default_class_from_mono_type (klass->enum_basetype);
8359                 klass->instance_size = ec->instance_size;
8360                 klass->size_inited = 1;
8361                 /* 
8362                  * this is almost safe to do with enums and it's needed to be able
8363                  * to create objects of the enum type (for use in SetConstant).
8364                  */
8365                 /* FIXME: Does this mean enums can't have method overrides ? */
8366                 mono_class_setup_vtable_general (klass, NULL, 0);
8367         }
8368         mono_loader_unlock ();
8369 }
8370
8371 static MonoMarshalSpec*
8372 mono_marshal_spec_from_builder (MonoAssembly *assembly,
8373                                                                 MonoReflectionMarshal *minfo)
8374 {
8375         MonoMarshalSpec *res;
8376
8377         res = g_new0 (MonoMarshalSpec, 1);
8378         res->native = minfo->type;
8379
8380         switch (minfo->type) {
8381         case MONO_NATIVE_LPARRAY:
8382                 res->data.array_data.elem_type = minfo->eltype;
8383                 if (minfo->has_size) {
8384                         res->data.array_data.param_num = minfo->param_num;
8385                         res->data.array_data.num_elem = minfo->count;
8386                         res->data.array_data.elem_mult = minfo->param_num == -1 ? 0 : 1;
8387                 }
8388                 else {
8389                         res->data.array_data.param_num = -1;
8390                         res->data.array_data.num_elem = -1;
8391                         res->data.array_data.elem_mult = -1;
8392                 }
8393                 break;
8394
8395         case MONO_NATIVE_BYVALTSTR:
8396         case MONO_NATIVE_BYVALARRAY:
8397                 res->data.array_data.num_elem = minfo->count;
8398                 break;
8399
8400         case MONO_NATIVE_CUSTOM:
8401                 if (minfo->marshaltyperef)
8402                         res->data.custom_data.custom_name =
8403                                 type_get_fully_qualified_name (minfo->marshaltyperef->type);
8404                 if (minfo->mcookie)
8405                         res->data.custom_data.cookie = mono_string_to_utf8 (minfo->mcookie);
8406                 break;
8407
8408         default:
8409                 break;
8410         }
8411
8412         return res;
8413 }
8414
8415 MonoReflectionMarshal*
8416 mono_reflection_marshal_from_marshal_spec (MonoDomain *domain, MonoClass *klass,
8417                                                                                    MonoMarshalSpec *spec)
8418 {
8419         static MonoClass *System_Reflection_Emit_UnmanagedMarshalClass;
8420         MonoReflectionMarshal *minfo;
8421         MonoType *mtype;
8422
8423         if (!System_Reflection_Emit_UnmanagedMarshalClass) {
8424                 System_Reflection_Emit_UnmanagedMarshalClass = mono_class_from_name (
8425                    mono_defaults.corlib, "System.Reflection.Emit", "UnmanagedMarshal");
8426                 g_assert (System_Reflection_Emit_UnmanagedMarshalClass);
8427         }
8428
8429         minfo = (MonoReflectionMarshal*)mono_object_new (domain, System_Reflection_Emit_UnmanagedMarshalClass);
8430         minfo->type = spec->native;
8431
8432         switch (minfo->type) {
8433         case MONO_NATIVE_LPARRAY:
8434                 minfo->eltype = spec->data.array_data.elem_type;
8435                 minfo->count = spec->data.array_data.num_elem;
8436                 minfo->param_num = spec->data.array_data.param_num;
8437                 break;
8438
8439         case MONO_NATIVE_BYVALTSTR:
8440         case MONO_NATIVE_BYVALARRAY:
8441                 minfo->count = spec->data.array_data.num_elem;
8442                 break;
8443
8444         case MONO_NATIVE_CUSTOM:
8445                 if (spec->data.custom_data.custom_name) {
8446                         mtype = mono_reflection_type_from_name (spec->data.custom_data.custom_name, klass->image);
8447                         if (mtype)
8448                                 MONO_OBJECT_SETREF (minfo, marshaltyperef, mono_type_get_object (domain, mtype));
8449
8450                         MONO_OBJECT_SETREF (minfo, marshaltype, mono_string_new (domain, spec->data.custom_data.custom_name));
8451                 }
8452                 if (spec->data.custom_data.cookie)
8453                         MONO_OBJECT_SETREF (minfo, mcookie, mono_string_new (domain, spec->data.custom_data.cookie));
8454                 break;
8455
8456         default:
8457                 break;
8458         }
8459
8460         return minfo;
8461 }
8462
8463 static MonoMethod*
8464 reflection_methodbuilder_to_mono_method (MonoClass *klass,
8465                                          ReflectionMethodBuilder *rmb,
8466                                          MonoMethodSignature *sig)
8467 {
8468         MonoMethod *m;
8469         MonoMethodNormal *pm;
8470         MonoMarshalSpec **specs;
8471         MonoReflectionMethodAux *method_aux;
8472         MonoMemPool *mp;
8473         gboolean dynamic;
8474         int i;
8475
8476         g_assert (!klass->generic_class);
8477
8478         /*
8479          * Methods created using a MethodBuilder should have their memory allocated
8480          * inside the image mempool, while dynamic methods should have their memory
8481          * malloc'd.
8482          */
8483         dynamic = rmb->refs != NULL;
8484         mp = dynamic ? NULL : klass->image->mempool;
8485
8486         mono_loader_lock ();
8487
8488         if ((rmb->attrs & METHOD_ATTRIBUTE_PINVOKE_IMPL) ||
8489                         (rmb->iattrs & METHOD_IMPL_ATTRIBUTE_INTERNAL_CALL))
8490                 m = (MonoMethod *)mp_g_new0 (mp, MonoMethodPInvoke, 1);
8491         else if (rmb->refs)
8492                 m = (MonoMethod *)mp_g_new0 (mp, MonoMethodWrapper, 1);
8493         else
8494                 m = (MonoMethod *)mp_g_new0 (mp, MonoMethodNormal, 1);
8495
8496         pm = (MonoMethodNormal*)m;
8497
8498         m->dynamic = dynamic;
8499         m->slot = -1;
8500         m->flags = rmb->attrs;
8501         m->iflags = rmb->iattrs;
8502         m->name = mp_string_to_utf8 (mp, rmb->name);
8503         m->klass = klass;
8504         m->signature = sig;
8505         m->skip_visibility = rmb->skip_visibility;
8506         if (rmb->table_idx)
8507                 m->token = MONO_TOKEN_METHOD_DEF | (*rmb->table_idx);
8508
8509         if (m->iflags & METHOD_IMPL_ATTRIBUTE_INTERNAL_CALL) {
8510                 if (klass == mono_defaults.string_class && !strcmp (m->name, ".ctor"))
8511                         m->string_ctor = 1;
8512
8513                 m->signature->pinvoke = 1;
8514         } else if (m->flags & METHOD_ATTRIBUTE_PINVOKE_IMPL) {
8515                 m->signature->pinvoke = 1;
8516
8517                 method_aux = g_new0 (MonoReflectionMethodAux, 1);
8518
8519                 method_aux->dllentry = rmb->dllentry ? mono_string_to_utf8_mp (mp, rmb->dllentry) : mono_mempool_strdup (mp, m->name);
8520                 method_aux->dll = mono_string_to_utf8_mp (mp, rmb->dll);
8521                 
8522                 ((MonoMethodPInvoke*)m)->piflags = (rmb->native_cc << 8) | (rmb->charset ? (rmb->charset - 1) * 2 : 0) | rmb->extra_flags;
8523
8524                 if (klass->image->dynamic)
8525                         g_hash_table_insert (((MonoDynamicImage*)klass->image)->method_aux_hash, m, method_aux);
8526
8527                 mono_loader_unlock ();
8528
8529                 return m;
8530         } else if (!(m->flags & METHOD_ATTRIBUTE_ABSTRACT) &&
8531                            !(m->iflags & METHOD_IMPL_ATTRIBUTE_RUNTIME)) {
8532                 MonoMethodHeader *header;
8533                 guint32 code_size;
8534                 gint32 max_stack, i;
8535                 gint32 num_locals = 0;
8536                 gint32 num_clauses = 0;
8537                 guint8 *code;
8538
8539                 if (rmb->ilgen) {
8540                         code = mono_array_addr (rmb->ilgen->code, guint8, 0);
8541                         code_size = rmb->ilgen->code_len;
8542                         max_stack = rmb->ilgen->max_stack;
8543                         num_locals = rmb->ilgen->locals ? mono_array_length (rmb->ilgen->locals) : 0;
8544                         if (rmb->ilgen->ex_handlers)
8545                                 num_clauses = method_count_clauses (rmb->ilgen);
8546                 } else {
8547                         if (rmb->code) {
8548                                 code = mono_array_addr (rmb->code, guint8, 0);
8549                                 code_size = mono_array_length (rmb->code);
8550                                 /* we probably need to run a verifier on the code... */
8551                                 max_stack = 8; 
8552                         }
8553                         else {
8554                                 code = NULL;
8555                                 code_size = 0;
8556                                 max_stack = 8;
8557                         }
8558                 }
8559
8560                 header = mp_g_malloc0 (mp, sizeof (MonoMethodHeader) + 
8561                         (num_locals - MONO_ZERO_LEN_ARRAY) * sizeof (MonoType*));
8562                 header->code_size = code_size;
8563                 header->code = mp_g_malloc (mp, code_size);
8564                 memcpy ((char*)header->code, code, code_size);
8565                 header->max_stack = max_stack;
8566                 header->init_locals = rmb->init_locals;
8567                 header->num_locals = num_locals;
8568
8569                 for (i = 0; i < num_locals; ++i) {
8570                         MonoReflectionLocalBuilder *lb = 
8571                                 mono_array_get (rmb->ilgen->locals, MonoReflectionLocalBuilder*, i);
8572
8573                         header->locals [i] = mp_g_new0 (mp, MonoType, 1);
8574                         memcpy (header->locals [i], lb->type->type, sizeof (MonoType));
8575                 }
8576
8577                 header->num_clauses = num_clauses;
8578                 if (num_clauses) {
8579                         header->clauses = method_encode_clauses ((MonoDynamicImage*)klass->image,
8580                                  rmb->ilgen, num_clauses);
8581                 }
8582
8583                 pm->header = header;
8584         }
8585
8586         if (rmb->generic_params) {
8587                 int count = mono_array_length (rmb->generic_params);
8588                 MonoGenericContainer *container;
8589
8590                 m->generic_container = container = rmb->generic_container;
8591                 container->type_argc = count;
8592                 container->type_params = g_new0 (MonoGenericParam, count);
8593                 container->is_method = TRUE;
8594                 container->owner.method = m;
8595
8596                 for (i = 0; i < count; i++) {
8597                         MonoReflectionGenericParam *gp =
8598                                 mono_array_get (rmb->generic_params, MonoReflectionGenericParam*, i);
8599
8600                         container->type_params [i] = *gp->type.type->data.generic_param;
8601                 }
8602
8603                 if (klass->generic_container) {
8604                         container->parent = klass->generic_container;
8605                         container->context.class_inst = klass->generic_container->context.class_inst;
8606                 }
8607                 container->context.method_inst = mono_get_shared_generic_inst (container);
8608         }
8609
8610         if (rmb->refs) {
8611                 MonoMethodWrapper *mw = (MonoMethodWrapper*)m;
8612                 int i;
8613                 void **data;
8614
8615                 m->wrapper_type = MONO_WRAPPER_DYNAMIC_METHOD;
8616
8617                 mw->method_data = data = mp_g_new (mp, gpointer, rmb->nrefs + 1);
8618                 data [0] = GUINT_TO_POINTER (rmb->nrefs);
8619                 for (i = 0; i < rmb->nrefs; ++i)
8620                         data [i + 1] = rmb->refs [i];
8621         }
8622
8623         method_aux = NULL;
8624
8625         /* Parameter info */
8626         if (rmb->pinfo) {
8627                 if (!method_aux)
8628                         method_aux = mp_g_new0 (mp, MonoReflectionMethodAux, 1);
8629                 method_aux->param_names = mp_g_new0 (mp, char *, mono_method_signature (m)->param_count + 1);
8630                 for (i = 0; i <= m->signature->param_count; ++i) {
8631                         MonoReflectionParamBuilder *pb;
8632                         if ((pb = mono_array_get (rmb->pinfo, MonoReflectionParamBuilder*, i))) {
8633                                 if ((i > 0) && (pb->attrs)) {
8634                                         /* Make a copy since it might point to a shared type structure */
8635                                         /* FIXME: Alloc this from a mempool */
8636                                         m->signature->params [i - 1] = mono_metadata_type_dup (NULL, m->signature->params [i - 1]);
8637                                         m->signature->params [i - 1]->attrs = pb->attrs;
8638                                 }
8639
8640                                 if (pb->attrs & PARAM_ATTRIBUTE_HAS_DEFAULT) {
8641                                         MonoDynamicImage *assembly;
8642                                         guint32 idx, def_type, len;
8643                                         char *p;
8644                                         const char *p2;
8645
8646                                         if (!method_aux->param_defaults) {
8647                                                 method_aux->param_defaults = mp_g_new0 (mp, guint8*, m->signature->param_count + 1);
8648                                                 method_aux->param_default_types = mp_g_new0 (mp, guint32, m->signature->param_count + 1);
8649                                         }
8650                                         assembly = (MonoDynamicImage*)klass->image;
8651                                         idx = encode_constant (assembly, pb->def_value, &def_type);
8652                                         /* Copy the data from the blob since it might get realloc-ed */
8653                                         p = assembly->blob.data + idx;
8654                                         len = mono_metadata_decode_blob_size (p, &p2);
8655                                         len += p2 - p;
8656                                         method_aux->param_defaults [i] = mp_g_malloc (mp, len);
8657                                         method_aux->param_default_types [i] = def_type;
8658                                         memcpy ((gpointer)method_aux->param_defaults [i], p, len);
8659                                 }
8660
8661                                 if (pb->name)
8662                                         method_aux->param_names [i] = mp_string_to_utf8 (mp, pb->name);
8663                                 if (pb->cattrs) {
8664                                         if (!method_aux->param_cattr)
8665                                                 method_aux->param_cattr = mp_g_new0 (mp, MonoCustomAttrInfo*, m->signature->param_count + 1);
8666                                         method_aux->param_cattr [i] = mono_custom_attrs_from_builders (klass->image, pb->cattrs);
8667                                 }
8668                         }
8669                 }
8670         }
8671
8672         /* Parameter marshalling */
8673         specs = NULL;
8674         if (rmb->pinfo)         
8675                 for (i = 0; i < mono_array_length (rmb->pinfo); ++i) {
8676                         MonoReflectionParamBuilder *pb;
8677                         if ((pb = mono_array_get (rmb->pinfo, MonoReflectionParamBuilder*, i))) {
8678                                 if (pb->marshal_info) {
8679                                         if (specs == NULL)
8680                                                 specs = mp_g_new0 (mp, MonoMarshalSpec*, sig->param_count + 1);
8681                                         specs [pb->position] = 
8682                                                 mono_marshal_spec_from_builder (klass->image->assembly, pb->marshal_info);
8683                                 }
8684                         }
8685                 }
8686         if (specs != NULL) {
8687                 if (!method_aux)
8688                         method_aux = mp_g_new0 (mp, MonoReflectionMethodAux, 1);
8689                 method_aux->param_marshall = specs;
8690         }
8691
8692         if (klass->image->dynamic && method_aux)
8693                 g_hash_table_insert (((MonoDynamicImage*)klass->image)->method_aux_hash, m, method_aux);
8694
8695         mono_loader_unlock ();
8696
8697         return m;
8698 }       
8699
8700 static MonoMethod*
8701 ctorbuilder_to_mono_method (MonoClass *klass, MonoReflectionCtorBuilder* mb)
8702 {
8703         ReflectionMethodBuilder rmb;
8704         MonoMethodSignature *sig;
8705
8706         if (mb->mhandle)
8707                 /* Can happen if this was called from inflate_method () earlier */
8708                 return mb->mhandle;
8709
8710         mono_loader_lock ();
8711         sig = ctor_builder_to_signature (klass->image->mempool, mb);
8712         mono_loader_unlock ();
8713
8714         reflection_methodbuilder_from_ctor_builder (&rmb, mb);
8715
8716         mb->mhandle = reflection_methodbuilder_to_mono_method (klass, &rmb, sig);
8717         mono_save_custom_attrs (klass->image, mb->mhandle, mb->cattrs);
8718
8719         if (!((MonoDynamicImage*)(MonoDynamicImage*)klass->image)->save) {
8720                 /* ilgen is no longer needed */
8721                 mb->ilgen = NULL;
8722         }
8723
8724         return mb->mhandle;
8725 }
8726
8727 static MonoMethod*
8728 methodbuilder_to_mono_method (MonoClass *klass, MonoReflectionMethodBuilder* mb)
8729 {
8730         ReflectionMethodBuilder rmb;
8731         MonoMethodSignature *sig;
8732
8733         if (mb->mhandle)
8734                 /* Can happen if this was called from inflate_method () earlier */
8735                 return mb->mhandle;
8736
8737         mono_loader_lock ();
8738         sig = method_builder_to_signature (klass->image->mempool, mb);
8739         mono_loader_unlock ();
8740
8741         reflection_methodbuilder_from_method_builder (&rmb, mb);
8742
8743         mb->mhandle = reflection_methodbuilder_to_mono_method (klass, &rmb, sig);
8744         mono_save_custom_attrs (klass->image, mb->mhandle, mb->cattrs);
8745
8746         if (!((MonoDynamicImage*)(MonoDynamicImage*)klass->image)->save) {
8747                 /* ilgen is no longer needed */
8748                 mb->ilgen = NULL;
8749         }
8750         return mb->mhandle;
8751 }
8752
8753 static MonoClassField*
8754 fieldbuilder_to_mono_class_field (MonoClass *klass, MonoReflectionFieldBuilder* fb)
8755 {
8756         MonoClassField *field;
8757         const char *p, *p2;
8758         guint32 len, idx;
8759
8760         field = g_new0 (MonoClassField, 1);
8761
8762         field->name = mono_string_to_utf8 (fb->name);
8763         if (fb->attrs) {
8764                 /* FIXME: handle type modifiers */
8765                 field->type = g_memdup (fb->type->type, sizeof (MonoType));
8766                 field->type->attrs = fb->attrs;
8767         } else {
8768                 field->type = fb->type->type;
8769         }
8770         if ((fb->attrs & FIELD_ATTRIBUTE_HAS_FIELD_RVA) && fb->rva_data)
8771                 field->data = mono_array_addr (fb->rva_data, char, 0); /* FIXME: GC pin array */
8772         if (fb->offset != -1)
8773                 field->offset = fb->offset;
8774         field->parent = klass;
8775         mono_save_custom_attrs (klass->image, field, fb->cattrs);
8776
8777         if (fb->def_value) {
8778                 MonoDynamicImage *assembly = (MonoDynamicImage*)klass->image;
8779                 field->type->attrs |= FIELD_ATTRIBUTE_HAS_DEFAULT;
8780                 idx = encode_constant (assembly, fb->def_value, &field->def_type);
8781                 /* Copy the data from the blob since it might get realloc-ed */
8782                 p = assembly->blob.data + idx;
8783                 len = mono_metadata_decode_blob_size (p, &p2);
8784                 len += p2 - p;
8785                 field->data = g_malloc (len);
8786                 memcpy ((gpointer)field->data, p, len);
8787         }
8788
8789         return field;
8790 }
8791
8792 MonoType*
8793 mono_reflection_bind_generic_parameters (MonoReflectionType *type, int type_argc, MonoType **types)
8794 {
8795         MonoClass *klass;
8796         MonoReflectionTypeBuilder *tb = NULL;
8797         gboolean is_dynamic = FALSE;
8798         MonoDomain *domain;
8799         MonoClass *geninst;
8800
8801         mono_loader_lock ();
8802
8803         domain = mono_object_domain (type);
8804
8805         if (!strcmp (((MonoObject *) type)->vtable->klass->name, "TypeBuilder")) {
8806                 tb = (MonoReflectionTypeBuilder *) type;
8807
8808                 is_dynamic = TRUE;
8809         } else if (!strcmp (((MonoObject *) type)->vtable->klass->name, "MonoGenericClass")) {
8810                 MonoReflectionGenericClass *rgi = (MonoReflectionGenericClass *) type;
8811                 MonoReflectionType *rgt = rgi->generic_type;
8812
8813                 g_assert (!strcmp (((MonoObject *) rgt)->vtable->klass->name, "TypeBuilder"));
8814                 tb = (MonoReflectionTypeBuilder *) rgt;
8815
8816                 is_dynamic = TRUE;
8817         }
8818
8819         /* FIXME: fix the CreateGenericParameters protocol to avoid the two stage setup of TypeBuilders */
8820         if (tb && tb->generic_container)
8821                 mono_reflection_create_generic_class (tb);
8822
8823         klass = mono_class_from_mono_type (type->type);
8824         if (!klass->generic_container) {
8825                 mono_loader_unlock ();
8826                 return NULL;
8827         }
8828
8829         if (klass->wastypebuilder) {
8830                 tb = (MonoReflectionTypeBuilder *) klass->reflection_info;
8831
8832                 is_dynamic = TRUE;
8833         }
8834
8835         mono_loader_unlock ();
8836
8837         geninst = mono_class_bind_generic_parameters (klass, type_argc, types, is_dynamic);
8838
8839         return &geninst->byval_arg;
8840 }
8841
8842 MonoClass*
8843 mono_class_bind_generic_parameters (MonoClass *klass, int type_argc, MonoType **types, gboolean is_dynamic)
8844 {
8845         MonoGenericClass *gclass;
8846         MonoGenericInst *inst;
8847
8848         g_assert (klass->generic_container);
8849
8850         inst = mono_metadata_get_generic_inst (type_argc, types);
8851         gclass = mono_metadata_lookup_generic_class (klass, inst, is_dynamic);
8852
8853         return mono_generic_class_get_class (gclass);
8854 }
8855
8856 MonoReflectionMethod*
8857 mono_reflection_bind_generic_method_parameters (MonoReflectionMethod *rmethod, MonoArray *types)
8858 {
8859         MonoClass *klass;
8860         MonoMethod *method, *inflated;
8861         MonoMethodInflated *imethod;
8862         MonoReflectionMethodBuilder *mb = NULL;
8863         MonoGenericContext tmp_context;
8864         MonoGenericInst *ginst;
8865         MonoType **type_argv;
8866         int count, i;
8867
8868         MONO_ARCH_SAVE_REGS;
8869         if (!strcmp (rmethod->object.vtable->klass->name, "MethodBuilder")) {
8870                 MonoReflectionTypeBuilder *tb;
8871                 MonoClass *klass;
8872
8873                 mb = (MonoReflectionMethodBuilder *) rmethod;
8874                 tb = (MonoReflectionTypeBuilder *) mb->type;
8875                 klass = mono_class_from_mono_type (tb->type.type);
8876
8877                 method = methodbuilder_to_mono_method (klass, mb);
8878         } else {
8879                 method = rmethod->method;
8880         }
8881
8882         klass = method->klass;
8883
8884         if (method->is_inflated)
8885                 method = ((MonoMethodInflated *) method)->declaring;
8886
8887         count = mono_method_signature (method)->generic_param_count;
8888         if (count != mono_array_length (types))
8889                 return NULL;
8890
8891         type_argv = g_new0 (MonoType *, count);
8892         for (i = 0; i < count; i++) {
8893                 MonoReflectionType *garg = mono_array_get (types, gpointer, i);
8894                 type_argv [i] = garg->type;
8895         }
8896         ginst = mono_metadata_get_generic_inst (count, type_argv);
8897         g_free (type_argv);
8898
8899         tmp_context.class_inst = klass->generic_class ? klass->generic_class->context.class_inst : NULL;
8900         tmp_context.method_inst = ginst;
8901
8902         inflated = mono_class_inflate_generic_method (method, &tmp_context);
8903         imethod = (MonoMethodInflated *) inflated;
8904
8905         MOVING_GC_REGISTER (&imethod->reflection_info);
8906         imethod->reflection_info = rmethod;
8907
8908         return mono_method_get_object (mono_object_domain (rmethod), inflated, NULL);
8909 }
8910
8911 static MonoMethod *
8912 inflate_mono_method (MonoReflectionGenericClass *type, MonoMethod *method, MonoObject *obj)
8913 {
8914         MonoMethodInflated *imethod;
8915         MonoGenericContext tmp_context;
8916         MonoGenericContext *context;
8917         MonoClass *klass;
8918
8919         klass = mono_class_from_mono_type (type->type.type);
8920         g_assert (klass->generic_class);
8921         context = mono_class_get_context (klass);
8922
8923         if (method->generic_container) {
8924                 g_assert (method->klass == klass->generic_class->container_class);
8925
8926                 tmp_context.class_inst = klass->generic_class->context.class_inst;
8927                 tmp_context.method_inst = method->generic_container->context.method_inst;
8928                 context = &tmp_context;
8929         }
8930
8931         imethod = (MonoMethodInflated *) mono_class_inflate_generic_method_full (method, klass, context);
8932         if (method->generic_container) {
8933                 MOVING_GC_REGISTER (&imethod->reflection_info);
8934                 imethod->reflection_info = obj;
8935         }
8936         return (MonoMethod *) imethod;
8937 }
8938
8939 static MonoMethod *
8940 inflate_method (MonoReflectionGenericClass *type, MonoObject *obj)
8941 {
8942         MonoMethod *method;
8943         MonoClass *gklass;
8944
8945         gklass = mono_class_from_mono_type (type->generic_type->type);
8946
8947         if (!strcmp (obj->vtable->klass->name, "MethodBuilder"))
8948                 method = methodbuilder_to_mono_method (gklass, (MonoReflectionMethodBuilder *) obj);
8949         else if (!strcmp (obj->vtable->klass->name, "ConstructorBuilder"))
8950                 method = ctorbuilder_to_mono_method (gklass, (MonoReflectionCtorBuilder *) obj);
8951         else if (!strcmp (obj->vtable->klass->name, "MonoMethod") || !strcmp (obj->vtable->klass->name, "MonoCMethod"))
8952                 method = ((MonoReflectionMethod *) obj)->method;
8953         else {
8954                 method = NULL; /* prevent compiler warning */
8955                 g_assert_not_reached ();
8956         }
8957
8958         return inflate_mono_method (type, method, obj);
8959 }
8960
8961 void
8962 mono_reflection_generic_class_initialize (MonoReflectionGenericClass *type, MonoArray *methods, 
8963                                           MonoArray *ctors, MonoArray *fields, MonoArray *properties,
8964                                           MonoArray *events)
8965 {
8966         MonoGenericClass *gclass;
8967         MonoDynamicGenericClass *dgclass;
8968         MonoClass *klass, *gklass;
8969         int i;
8970
8971         MONO_ARCH_SAVE_REGS;
8972
8973         klass = mono_class_from_mono_type (type->type.type);
8974         g_assert (type->type.type->type == MONO_TYPE_GENERICINST);
8975         gclass = type->type.type->data.generic_class;
8976
8977         g_assert (gclass->is_dynamic);
8978         dgclass = (MonoDynamicGenericClass *) gclass;
8979
8980         if (dgclass->initialized)
8981                 return;
8982
8983         gklass = gclass->container_class;
8984         mono_class_init (gklass);
8985
8986         dgclass->count_methods = methods ? mono_array_length (methods) : 0;
8987         dgclass->count_ctors = ctors ? mono_array_length (ctors) : 0;
8988         dgclass->count_fields = fields ? mono_array_length (fields) : 0;
8989         dgclass->count_properties = properties ? mono_array_length (properties) : 0;
8990         dgclass->count_events = events ? mono_array_length (events) : 0;
8991
8992         dgclass->methods = g_new0 (MonoMethod *, dgclass->count_methods);
8993         dgclass->ctors = g_new0 (MonoMethod *, dgclass->count_ctors);
8994         dgclass->fields = g_new0 (MonoClassField, dgclass->count_fields);
8995         dgclass->properties = g_new0 (MonoProperty, dgclass->count_properties);
8996         dgclass->events = g_new0 (MonoEvent, dgclass->count_events);
8997
8998         for (i = 0; i < dgclass->count_methods; i++) {
8999                 MonoObject *obj = mono_array_get (methods, gpointer, i);
9000
9001                 dgclass->methods [i] = inflate_method (type, obj);
9002         }
9003
9004         for (i = 0; i < dgclass->count_ctors; i++) {
9005                 MonoObject *obj = mono_array_get (ctors, gpointer, i);
9006
9007                 dgclass->ctors [i] = inflate_method (type, obj);
9008         }
9009
9010         for (i = 0; i < dgclass->count_fields; i++) {
9011                 MonoObject *obj = mono_array_get (fields, gpointer, i);
9012                 MonoClassField *field;
9013                 MonoInflatedField *ifield;
9014
9015                 if (!strcmp (obj->vtable->klass->name, "FieldBuilder"))
9016                         field = fieldbuilder_to_mono_class_field (klass, (MonoReflectionFieldBuilder *) obj);
9017                 else if (!strcmp (obj->vtable->klass->name, "MonoField"))
9018                         field = ((MonoReflectionField *) obj)->field;
9019                 else {
9020                         field = NULL; /* prevent compiler warning */
9021                         g_assert_not_reached ();
9022                 }
9023
9024                 ifield = g_new0 (MonoInflatedField, 1);
9025                 ifield->generic_type = field->type;
9026                 MOVING_GC_REGISTER (&ifield->reflection_info);
9027                 ifield->reflection_info = obj;
9028
9029                 dgclass->fields [i] = *field;
9030                 dgclass->fields [i].parent = klass;
9031                 dgclass->fields [i].generic_info = ifield;
9032                 dgclass->fields [i].type = mono_class_inflate_generic_type (
9033                         field->type, mono_generic_class_get_context ((MonoGenericClass *) dgclass));
9034         }
9035
9036         for (i = 0; i < dgclass->count_properties; i++) {
9037                 MonoObject *obj = mono_array_get (properties, gpointer, i);
9038                 MonoProperty *property = &dgclass->properties [i];
9039
9040                 if (!strcmp (obj->vtable->klass->name, "PropertyBuilder")) {
9041                         MonoReflectionPropertyBuilder *pb = (MonoReflectionPropertyBuilder *) obj;
9042
9043                         property->parent = klass;
9044                         property->attrs = pb->attrs;
9045                         property->name = mono_string_to_utf8 (pb->name);
9046                         if (pb->get_method)
9047                                 property->get = inflate_method (type, (MonoObject *) pb->get_method);
9048                         if (pb->set_method)
9049                                 property->set = inflate_method (type, (MonoObject *) pb->set_method);
9050                 } else if (!strcmp (obj->vtable->klass->name, "MonoProperty")) {
9051                         *property = *((MonoReflectionProperty *) obj)->property;
9052
9053                         if (property->get)
9054                                 property->get = inflate_mono_method (type, property->get, NULL);
9055                         if (property->set)
9056                                 property->set = inflate_mono_method (type, property->set, NULL);
9057                 } else
9058                         g_assert_not_reached ();
9059         }
9060
9061         for (i = 0; i < dgclass->count_events; i++) {
9062                 MonoObject *obj = mono_array_get (events, gpointer, i);
9063                 MonoEvent *event = &dgclass->events [i];
9064
9065                 if (!strcmp (obj->vtable->klass->name, "EventBuilder")) {
9066                         MonoReflectionEventBuilder *eb = (MonoReflectionEventBuilder *) obj;
9067
9068                         event->parent = klass;
9069                         event->attrs = eb->attrs;
9070                         event->name = mono_string_to_utf8 (eb->name);
9071                         if (eb->add_method)
9072                                 event->add = inflate_method (type, (MonoObject *) eb->add_method);
9073                         if (eb->remove_method)
9074                                 event->remove = inflate_method (type, (MonoObject *) eb->remove_method);
9075                 } else if (!strcmp (obj->vtable->klass->name, "MonoEvent")) {
9076                         *event = *((MonoReflectionEvent *) obj)->event;
9077
9078                         if (event->add)
9079                                 event->add = inflate_mono_method (type, event->add, NULL);
9080                         if (event->remove)
9081                                 event->remove = inflate_mono_method (type, event->remove, NULL);
9082                 } else
9083                         g_assert_not_reached ();
9084         }
9085
9086         dgclass->initialized = TRUE;
9087 }
9088
9089 static void
9090 ensure_runtime_vtable (MonoClass *klass)
9091 {
9092         MonoReflectionTypeBuilder *tb = klass->reflection_info;
9093         int i, num, j;
9094
9095         if (!tb || klass->wastypebuilder)
9096                 return;
9097         if (klass->parent)
9098                 ensure_runtime_vtable (klass->parent);
9099
9100         num = tb->ctors? mono_array_length (tb->ctors): 0;
9101         num += tb->num_methods;
9102         klass->method.count = num;
9103         klass->methods = mono_mempool_alloc (klass->image->mempool, sizeof (MonoMethod*) * num);
9104         num = tb->ctors? mono_array_length (tb->ctors): 0;
9105         for (i = 0; i < num; ++i)
9106                 klass->methods [i] = ctorbuilder_to_mono_method (klass, mono_array_get (tb->ctors, MonoReflectionCtorBuilder*, i));
9107         num = tb->num_methods;
9108         j = i;
9109         for (i = 0; i < num; ++i)
9110                 klass->methods [j++] = methodbuilder_to_mono_method (klass, mono_array_get (tb->methods, MonoReflectionMethodBuilder*, i));
9111
9112         if (tb->interfaces) {
9113                 klass->interface_count = mono_array_length (tb->interfaces);
9114                 klass->interfaces = mono_mempool_alloc (klass->image->mempool, sizeof (MonoClass*) * klass->interface_count);
9115                 for (i = 0; i < klass->interface_count; ++i) {
9116                         MonoReflectionType *iface = mono_array_get (tb->interfaces, gpointer, i);
9117                         klass->interfaces [i] = mono_class_from_mono_type (iface->type);
9118                 }
9119         }
9120
9121         if (klass->flags & TYPE_ATTRIBUTE_INTERFACE) {
9122                 for (i = 0; i < klass->method.count; ++i)
9123                         klass->methods [i]->slot = i;
9124                 
9125                 mono_class_setup_interface_offsets (klass);
9126         }
9127
9128         /*
9129          * The generic vtable is needed even if image->run is not set since some
9130          * runtime code like ves_icall_Type_GetMethodsByName depends on 
9131          * method->slot being defined.
9132          */
9133
9134         /* 
9135          * tb->methods could not be freed since it is used for determining 
9136          * overrides during dynamic vtable construction.
9137          */
9138 }
9139
9140 void
9141 mono_reflection_get_dynamic_overrides (MonoClass *klass, MonoMethod ***overrides, int *num_overrides)
9142 {
9143         MonoReflectionTypeBuilder *tb;
9144         int i, onum;
9145
9146         *overrides = NULL;
9147         *num_overrides = 0;
9148
9149         g_assert (klass->image->dynamic);
9150
9151         if (!klass->reflection_info)
9152                 return;
9153
9154         g_assert (strcmp (((MonoObject*)klass->reflection_info)->vtable->klass->name, "TypeBuilder") == 0);
9155
9156         tb = (MonoReflectionTypeBuilder*)klass->reflection_info;
9157
9158         onum = 0;
9159         if (tb->methods) {
9160                 for (i = 0; i < tb->num_methods; ++i) {
9161                         MonoReflectionMethodBuilder *mb = 
9162                                 mono_array_get (tb->methods, MonoReflectionMethodBuilder*, i);
9163                         if (mb->override_method)
9164                                 onum ++;
9165                 }
9166         }
9167
9168         if (onum) {
9169                 *overrides = g_new0 (MonoMethod*, onum * 2);
9170
9171                 onum = 0;
9172                 for (i = 0; i < tb->num_methods; ++i) {
9173                         MonoReflectionMethodBuilder *mb = 
9174                                 mono_array_get (tb->methods, MonoReflectionMethodBuilder*, i);
9175                         if (mb->override_method) {
9176                                 (*overrides) [onum * 2] = 
9177                                         mb->override_method->method;
9178                                 (*overrides) [onum * 2 + 1] =
9179                                         mb->mhandle;
9180
9181                                 /* FIXME: What if 'override_method' is a MethodBuilder ? */
9182                                 g_assert (mb->override_method->method);
9183                                 g_assert (mb->mhandle);
9184
9185                                 onum ++;
9186                         }
9187                 }
9188         }
9189
9190         *num_overrides = onum;
9191 }
9192
9193 static void
9194 typebuilder_setup_fields (MonoClass *klass)
9195 {
9196         MonoReflectionTypeBuilder *tb = klass->reflection_info;
9197         MonoReflectionFieldBuilder *fb;
9198         MonoClassField *field;
9199         const char *p, *p2;
9200         int i;
9201         guint32 len, idx;
9202
9203         klass->field.count = tb->num_fields;
9204         klass->field.first = 0;
9205
9206         if (!klass->field.count)
9207                 return;
9208         
9209         klass->fields = g_new0 (MonoClassField, klass->field.count);
9210
9211         for (i = 0; i < klass->field.count; ++i) {
9212                 fb = mono_array_get (tb->fields, gpointer, i);
9213                 field = &klass->fields [i];
9214                 field->name = mono_string_to_utf8 (fb->name);
9215                 if (fb->attrs) {
9216                         /* FIXME: handle type modifiers */
9217                         field->type = g_memdup (fb->type->type, sizeof (MonoType));
9218                         field->type->attrs = fb->attrs;
9219                 } else {
9220                         field->type = fb->type->type;
9221                 }
9222                 if ((fb->attrs & FIELD_ATTRIBUTE_HAS_FIELD_RVA) && fb->rva_data)
9223                         field->data = mono_array_addr (fb->rva_data, char, 0);
9224                 if (fb->offset != -1)
9225                         field->offset = fb->offset;
9226                 field->parent = klass;
9227                 fb->handle = field;
9228                 mono_save_custom_attrs (klass->image, field, fb->cattrs);
9229
9230                 if (fb->def_value) {
9231                         MonoDynamicImage *assembly = (MonoDynamicImage*)klass->image;
9232                         field->type->attrs |= FIELD_ATTRIBUTE_HAS_DEFAULT;
9233                         idx = encode_constant (assembly, fb->def_value, &field->def_type);
9234                         /* Copy the data from the blob since it might get realloc-ed */
9235                         p = assembly->blob.data + idx;
9236                         len = mono_metadata_decode_blob_size (p, &p2);
9237                         len += p2 - p;
9238                         field->data = g_malloc (len);
9239                         memcpy ((gpointer)field->data, p, len);
9240                 }
9241         }
9242         mono_class_layout_fields (klass);
9243 }
9244
9245 static void
9246 typebuilder_setup_properties (MonoClass *klass)
9247 {
9248         MonoReflectionTypeBuilder *tb = klass->reflection_info;
9249         MonoReflectionPropertyBuilder *pb;
9250         int i;
9251
9252         klass->property.count = tb->properties ? mono_array_length (tb->properties) : 0;
9253         klass->property.first = 0;
9254
9255         klass->properties = g_new0 (MonoProperty, klass->property.count);
9256         for (i = 0; i < klass->property.count; ++i) {
9257                 pb = mono_array_get (tb->properties, MonoReflectionPropertyBuilder*, i);
9258                 klass->properties [i].parent = klass;
9259                 klass->properties [i].attrs = pb->attrs;
9260                 klass->properties [i].name = mono_string_to_utf8 (pb->name);
9261                 if (pb->get_method)
9262                         klass->properties [i].get = pb->get_method->mhandle;
9263                 if (pb->set_method)
9264                         klass->properties [i].set = pb->set_method->mhandle;
9265
9266                 mono_save_custom_attrs (klass->image, &klass->properties [i], pb->cattrs);
9267         }
9268 }
9269
9270 MonoReflectionEvent *
9271 mono_reflection_event_builder_get_event_info (MonoReflectionTypeBuilder *tb, MonoReflectionEventBuilder *eb)
9272 {
9273         MonoEvent *event = g_new0 (MonoEvent, 1);
9274         MonoClass *klass;
9275         int j;
9276
9277         klass = my_mono_class_from_mono_type (tb->type.type);
9278
9279         event->parent = klass;
9280         event->attrs = eb->attrs;
9281         event->name = mono_string_to_utf8 (eb->name);
9282         if (eb->add_method)
9283                 event->add = eb->add_method->mhandle;
9284         if (eb->remove_method)
9285                 event->remove = eb->remove_method->mhandle;
9286         if (eb->raise_method)
9287                 event->raise = eb->raise_method->mhandle;
9288
9289         if (eb->other_methods) {
9290                 event->other = g_new0 (MonoMethod*, mono_array_length (eb->other_methods) + 1);
9291                 for (j = 0; j < mono_array_length (eb->other_methods); ++j) {
9292                         MonoReflectionMethodBuilder *mb = 
9293                                 mono_array_get (eb->other_methods,
9294                                                 MonoReflectionMethodBuilder*, j);
9295                         event->other [j] = mb->mhandle;
9296                 }
9297         }
9298
9299         return mono_event_get_object (mono_object_domain (tb), klass, event);
9300 }
9301
9302 static void
9303 typebuilder_setup_events (MonoClass *klass)
9304 {
9305         MonoReflectionTypeBuilder *tb = klass->reflection_info;
9306         MonoReflectionEventBuilder *eb;
9307         int i, j;
9308
9309         klass->event.count = tb->events ? mono_array_length (tb->events) : 0;
9310         klass->event.first = 0;
9311
9312         klass->events = g_new0 (MonoEvent, klass->event.count);
9313         for (i = 0; i < klass->event.count; ++i) {
9314                 eb = mono_array_get (tb->events, MonoReflectionEventBuilder*, i);
9315                 klass->events [i].parent = klass;
9316                 klass->events [i].attrs = eb->attrs;
9317                 klass->events [i].name = mono_string_to_utf8 (eb->name);
9318                 if (eb->add_method)
9319                         klass->events [i].add = eb->add_method->mhandle;
9320                 if (eb->remove_method)
9321                         klass->events [i].remove = eb->remove_method->mhandle;
9322                 if (eb->raise_method)
9323                         klass->events [i].raise = eb->raise_method->mhandle;
9324
9325                 if (eb->other_methods) {
9326                         klass->events [i].other = g_new0 (MonoMethod*, mono_array_length (eb->other_methods) + 1);
9327                         for (j = 0; j < mono_array_length (eb->other_methods); ++j) {
9328                                 MonoReflectionMethodBuilder *mb = 
9329                                         mono_array_get (eb->other_methods,
9330                                                                         MonoReflectionMethodBuilder*, j);
9331                                 klass->events [i].other [j] = mb->mhandle;
9332                         }
9333                 }
9334         }
9335 }
9336
9337 MonoReflectionType*
9338 mono_reflection_create_runtime_class (MonoReflectionTypeBuilder *tb)
9339 {
9340         MonoClass *klass;
9341         MonoDomain* domain;
9342         MonoReflectionType* res;
9343         int i;
9344
9345         MONO_ARCH_SAVE_REGS;
9346
9347         domain = mono_object_domain (tb);
9348         klass = my_mono_class_from_mono_type (tb->type.type);
9349
9350         mono_save_custom_attrs (klass->image, klass, tb->cattrs);
9351         
9352         /* 
9353          * we need to lock the domain because the lock will be taken inside
9354          * So, we need to keep the locking order correct.
9355          */
9356         mono_domain_lock (domain);
9357         mono_loader_lock ();
9358         if (klass->wastypebuilder) {
9359                 mono_loader_unlock ();
9360                 mono_domain_unlock (domain);
9361                 return mono_type_get_object (mono_object_domain (tb), &klass->byval_arg);
9362         }
9363         /*
9364          * Fields to set in klass:
9365          * the various flags: delegate/unicode/contextbound etc.
9366          */
9367         klass->flags = tb->attrs;
9368         klass->has_cctor = 1;
9369         klass->has_finalize = 1;
9370
9371 #if 0
9372         if (!((MonoDynamicImage*)klass->image)->run) {
9373                 if (klass->generic_container) {
9374                         /* FIXME: The code below can't handle generic classes */
9375                         klass->wastypebuilder = TRUE;
9376                         mono_loader_unlock ();
9377                         mono_domain_unlock (domain);
9378                         return mono_type_get_object (mono_object_domain (tb), &klass->byval_arg);
9379                 }
9380         }
9381 #endif
9382
9383         /* enums are done right away */
9384         if (!klass->enumtype)
9385                 ensure_runtime_vtable (klass);
9386
9387         if (tb->subtypes) {
9388                 for (i = 0; i < mono_array_length (tb->subtypes); ++i) {
9389                         MonoReflectionTypeBuilder *subtb = mono_array_get (tb->subtypes, MonoReflectionTypeBuilder*, i);
9390                         klass->nested_classes = g_list_prepend (klass->nested_classes, my_mono_class_from_mono_type (subtb->type.type));
9391                 }
9392         }
9393
9394         /* fields and object layout */
9395         if (klass->parent) {
9396                 if (!klass->parent->size_inited)
9397                         mono_class_init (klass->parent);
9398                 klass->instance_size = klass->parent->instance_size;
9399                 klass->sizes.class_size = 0;
9400                 klass->min_align = klass->parent->min_align;
9401                 /* if the type has no fields we won't call the field_setup
9402                  * routine which sets up klass->has_references.
9403                  */
9404                 klass->has_references |= klass->parent->has_references;
9405         } else {
9406                 klass->instance_size = sizeof (MonoObject);
9407                 klass->min_align = 1;
9408         }
9409
9410         /* FIXME: handle packing_size and instance_size */
9411         typebuilder_setup_fields (klass);
9412
9413         typebuilder_setup_properties (klass);
9414
9415         typebuilder_setup_events (klass);
9416         
9417         klass->wastypebuilder = TRUE;
9418         mono_loader_unlock ();
9419         mono_domain_unlock (domain);
9420
9421         if (klass->enumtype && !mono_class_is_valid_enum (klass)) {
9422                 mono_class_set_failure (klass, MONO_EXCEPTION_TYPE_LOAD, NULL);
9423                 mono_raise_exception (mono_get_exception_type_load (tb->name, NULL));
9424         }
9425
9426         res = mono_type_get_object (mono_object_domain (tb), &klass->byval_arg);
9427         g_assert (res != (MonoReflectionType*)tb);
9428
9429         return res;
9430 }
9431
9432 void
9433 mono_reflection_initialize_generic_parameter (MonoReflectionGenericParam *gparam)
9434 {
9435         MonoGenericParam *param;
9436         MonoImage *image;
9437
9438         MONO_ARCH_SAVE_REGS;
9439
9440         param = g_new0 (MonoGenericParam, 1);
9441
9442         if (gparam->mbuilder) {
9443                 if (!gparam->mbuilder->generic_container)
9444                         gparam->mbuilder->generic_container = g_new0 (MonoGenericContainer, 1);
9445                 param->owner = gparam->mbuilder->generic_container;
9446         } else if (gparam->tbuilder) {
9447                 g_assert (gparam->tbuilder->generic_container);
9448                 param->owner = gparam->tbuilder->generic_container;
9449         }
9450
9451         param->name = mono_string_to_utf8 (gparam->name);
9452         param->num = gparam->index;
9453
9454         image = &gparam->tbuilder->module->dynamic_image->image;
9455         mono_class_from_generic_parameter (param, image, gparam->mbuilder != NULL);
9456
9457         MOVING_GC_REGISTER (&param->pklass->reflection_info);
9458         param->pklass->reflection_info = gparam; /* FIXME: GC pin gparam */
9459
9460         gparam->type.type = g_new0 (MonoType, 1);
9461         gparam->type.type->type = gparam->mbuilder ? MONO_TYPE_MVAR : MONO_TYPE_VAR;
9462         gparam->type.type->attrs = TYPE_ATTRIBUTE_PUBLIC;
9463         gparam->type.type->data.generic_param = param;
9464 }
9465
9466 MonoArray *
9467 mono_reflection_sighelper_get_signature_local (MonoReflectionSigHelper *sig)
9468 {
9469         MonoDynamicImage *assembly = sig->module->dynamic_image;
9470         guint32 na = mono_array_length (sig->arguments);
9471         guint32 buflen, i;
9472         MonoArray *result;
9473         SigBuffer buf;
9474
9475         sigbuffer_init (&buf, 32);
9476
9477         sigbuffer_add_value (&buf, 0x07);
9478         sigbuffer_add_value (&buf, na);
9479         for (i = 0; i < na; ++i) {
9480                 MonoReflectionType *type = mono_array_get (sig->arguments, MonoReflectionType *, i);
9481                 encode_reflection_type (assembly, type, &buf);
9482         }
9483
9484         buflen = buf.p - buf.buf;
9485         result = mono_array_new (mono_domain_get (), mono_defaults.byte_class, buflen);
9486         memcpy (mono_array_addr (result, char, 0), buf.buf, buflen);
9487         sigbuffer_free (&buf);
9488
9489         return result;
9490 }
9491
9492 MonoArray *
9493 mono_reflection_sighelper_get_signature_field (MonoReflectionSigHelper *sig)
9494 {
9495         MonoDynamicImage *assembly = sig->module->dynamic_image;
9496         guint32 na = mono_array_length (sig->arguments);
9497         guint32 buflen, i;
9498         MonoArray *result;
9499         SigBuffer buf;
9500
9501         sigbuffer_init (&buf, 32);
9502
9503         sigbuffer_add_value (&buf, 0x06);
9504         for (i = 0; i < na; ++i) {
9505                 MonoReflectionType *type = mono_array_get (sig->arguments, MonoReflectionType *, i);
9506                 encode_reflection_type (assembly, type, &buf);
9507         }
9508
9509         buflen = buf.p - buf.buf;
9510         result = mono_array_new (mono_domain_get (), mono_defaults.byte_class, buflen);
9511         memcpy (mono_array_addr (result, char, 0), buf.buf, buflen);
9512         sigbuffer_free (&buf);
9513
9514         return result;
9515 }
9516
9517 void 
9518 mono_reflection_create_dynamic_method (MonoReflectionDynamicMethod *mb)
9519 {
9520         ReflectionMethodBuilder rmb;
9521         MonoMethodSignature *sig;
9522         MonoClass *klass;
9523         GSList *l;
9524         int i;
9525
9526         sig = dynamic_method_to_signature (mb);
9527
9528         reflection_methodbuilder_from_dynamic_method (&rmb, mb);
9529
9530         /*
9531          * Resolve references.
9532          */
9533         /* 
9534          * Every second entry in the refs array is reserved for storing handle_class,
9535          * which is needed by the ldtoken implementation in the JIT.
9536          */
9537         rmb.nrefs = mb->nrefs;
9538         rmb.refs = g_new0 (gpointer, mb->nrefs + 1);
9539         for (i = 0; i < mb->nrefs; i += 2) {
9540                 MonoClass *handle_class;
9541                 gpointer ref;
9542                 MonoObject *obj = mono_array_get (mb->refs, MonoObject*, i);
9543
9544                 if (strcmp (obj->vtable->klass->name, "DynamicMethod") == 0) {
9545                         MonoReflectionDynamicMethod *method = (MonoReflectionDynamicMethod*)obj;
9546                         /*
9547                          * The referenced DynamicMethod should already be created by the managed
9548                          * code, except in the case of circular references. In that case, we store
9549                          * method in the refs array, and fix it up later when the referenced 
9550                          * DynamicMethod is created.
9551                          */
9552                         if (method->mhandle) {
9553                                 ref = method->mhandle;
9554                         } else {
9555                                 /* FIXME: GC object stored in unmanaged memory */
9556                                 ref = method;
9557
9558                                 /* FIXME: GC object stored in unmanaged memory */
9559                                 method->referenced_by = g_slist_append (method->referenced_by, mb);
9560                         }
9561                         handle_class = mono_defaults.methodhandle_class;
9562                 } else {
9563                         ref = resolve_object (mb->module->image, obj, &handle_class, NULL);
9564                         if (!ref) {
9565                                 g_free (rmb.refs);
9566                                 mono_raise_exception (mono_get_exception_type_load (NULL, NULL));
9567                                 return;
9568                         }
9569                 }
9570
9571                 rmb.refs [i] = ref; /* FIXME: GC object stored in unmanaged memory (change also resolve_object() signature) */
9572                 rmb.refs [i + 1] = handle_class;
9573         }               
9574
9575         klass = mb->owner ? mono_class_from_mono_type (mb->owner->type) : mono_defaults.object_class;
9576
9577         mb->mhandle = reflection_methodbuilder_to_mono_method (klass, &rmb, sig);
9578
9579         /* Fix up refs entries pointing at us */
9580         for (l = mb->referenced_by; l; l = l->next) {
9581                 MonoReflectionDynamicMethod *method = (MonoReflectionDynamicMethod*)l->data;
9582                 MonoMethodWrapper *wrapper = (MonoMethodWrapper*)method->mhandle;
9583                 gpointer *data;
9584                 
9585                 g_assert (method->mhandle);
9586
9587                 data = (gpointer*)wrapper->method_data;
9588                 for (i = 0; i < GPOINTER_TO_UINT (data [0]); i += 2) {
9589                         if ((data [i + 1] == mb) && (data [i + 1 + 1] == mono_defaults.methodhandle_class))
9590                                 data [i + 1] = mb->mhandle;
9591                 }
9592         }
9593         g_slist_free (mb->referenced_by);
9594
9595         g_free (rmb.refs);
9596
9597         /* ilgen is no longer needed */
9598         mb->ilgen = NULL;
9599 }
9600
9601 void
9602 mono_reflection_destroy_dynamic_method (MonoReflectionDynamicMethod *mb)
9603 {
9604         g_assert (mb);
9605
9606         if (mb->mhandle)
9607                 mono_runtime_free_method (
9608                         mono_object_get_domain ((MonoObject*)mb), mb->mhandle);
9609 }
9610
9611 /**
9612  * mono_reflection_lookup_dynamic_token:
9613  *
9614  * Finish the Builder object pointed to by TOKEN and return the corresponding
9615  * runtime structure. HANDLE_CLASS is set to the class required by 
9616  * mono_ldtoken.
9617  */
9618 gpointer
9619 mono_reflection_lookup_dynamic_token (MonoImage *image, guint32 token, MonoClass **handle_class, MonoGenericContext *context)
9620 {
9621         MonoDynamicImage *assembly = (MonoDynamicImage*)image;
9622         MonoObject *obj;
9623
9624         obj = mono_g_hash_table_lookup (assembly->tokens, GUINT_TO_POINTER (token));
9625         g_assert (obj);
9626
9627         return resolve_object (image, obj, handle_class, context);
9628 }
9629
9630 static gpointer
9631 resolve_object (MonoImage *image, MonoObject *obj, MonoClass **handle_class, MonoGenericContext *context)
9632 {
9633         gpointer result = NULL;
9634
9635         if (strcmp (obj->vtable->klass->name, "String") == 0) {
9636                 result = mono_string_intern ((MonoString*)obj);
9637                 *handle_class = NULL;
9638                 g_assert (result);
9639         } else if (strcmp (obj->vtable->klass->name, "MonoType") == 0) {
9640                 MonoReflectionType *tb = (MonoReflectionType*)obj;
9641                 if (context) {
9642                         MonoType *inflated = mono_class_inflate_generic_type (tb->type, context);
9643                         result = mono_class_from_mono_type (inflated);
9644                         mono_metadata_free_type (inflated);
9645                 } else {
9646                         result = mono_class_from_mono_type (tb->type);
9647                 }
9648                 *handle_class = mono_defaults.typehandle_class;
9649                 g_assert (result);
9650         } else if (strcmp (obj->vtable->klass->name, "MonoMethod") == 0 ||
9651                    strcmp (obj->vtable->klass->name, "MonoCMethod") == 0 ||
9652                    strcmp (obj->vtable->klass->name, "MonoGenericCMethod") == 0 ||
9653                    strcmp (obj->vtable->klass->name, "MonoGenericMethod") == 0) {
9654                 result = ((MonoReflectionMethod*)obj)->method;
9655                 result = mono_class_inflate_generic_method (result, context);
9656                 *handle_class = mono_defaults.methodhandle_class;
9657                 g_assert (result);
9658         } else if (strcmp (obj->vtable->klass->name, "MethodBuilder") == 0) {
9659                 MonoReflectionMethodBuilder *mb = (MonoReflectionMethodBuilder*)obj;
9660                 result = mb->mhandle;
9661                 if (!result) {
9662                         /* Type is not yet created */
9663                         MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder*)mb->type;
9664
9665                         mono_domain_try_type_resolve (mono_domain_get (), NULL, (MonoObject*)tb);
9666
9667                         /*
9668                          * Hopefully this has been filled in by calling CreateType() on the
9669                          * TypeBuilder.
9670                          */
9671                         /*
9672                          * TODO: This won't work if the application finishes another 
9673                          * TypeBuilder instance instead of this one.
9674                          */
9675                         result = mb->mhandle;
9676                 }
9677                 result = mono_class_inflate_generic_method (result, context);
9678                 *handle_class = mono_defaults.methodhandle_class;
9679         } else if (strcmp (obj->vtable->klass->name, "ConstructorBuilder") == 0) {
9680                 MonoReflectionCtorBuilder *cb = (MonoReflectionCtorBuilder*)obj;
9681
9682                 result = cb->mhandle;
9683                 if (!result) {
9684                         MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder*)cb->type;
9685
9686                         mono_domain_try_type_resolve (mono_domain_get (), NULL, (MonoObject*)tb);
9687                         result = cb->mhandle;
9688                 }
9689                 result = mono_class_inflate_generic_method (result, context);
9690                 *handle_class = mono_defaults.methodhandle_class;
9691         } else if (strcmp (obj->vtable->klass->name, "MonoField") == 0) {
9692                 result = ((MonoReflectionField*)obj)->field;
9693                 *handle_class = mono_defaults.fieldhandle_class;
9694                 g_assert (result);
9695         } else if (strcmp (obj->vtable->klass->name, "FieldBuilder") == 0) {
9696                 MonoReflectionFieldBuilder *fb = (MonoReflectionFieldBuilder*)obj;
9697                 result = fb->handle;
9698
9699                 if (!result) {
9700                         MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder*)fb->typeb;
9701
9702                         mono_domain_try_type_resolve (mono_domain_get (), NULL, (MonoObject*)tb);
9703                         result = fb->handle;
9704                 }
9705
9706                 if (fb->handle && fb->handle->parent->generic_container) {
9707                         MonoClass *klass = fb->handle->parent;
9708                         MonoClass *inflated = mono_class_from_mono_type (mono_class_inflate_generic_type (&klass->byval_arg, context));
9709
9710                         result = mono_class_get_field_from_name (inflated, fb->handle->name);
9711                         g_assert (result);
9712                 }
9713                 *handle_class = mono_defaults.fieldhandle_class;
9714         } else if (strcmp (obj->vtable->klass->name, "TypeBuilder") == 0) {
9715                 MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder*)obj;
9716                 MonoClass *klass;
9717
9718                 klass = tb->type.type->data.klass;
9719                 if (klass->wastypebuilder) {
9720                         /* Already created */
9721                         result = klass;
9722                 }
9723                 else {
9724                         mono_domain_try_type_resolve (mono_domain_get (), NULL, (MonoObject*)tb);
9725                         result = tb->type.type->data.klass;
9726                         g_assert (result);
9727                 }
9728                 *handle_class = mono_defaults.typehandle_class;
9729         } else if (strcmp (obj->vtable->klass->name, "SignatureHelper") == 0) {
9730                 MonoReflectionSigHelper *helper = (MonoReflectionSigHelper*)obj;
9731                 MonoMethodSignature *sig;
9732                 int nargs, i;
9733
9734                 if (helper->arguments)
9735                         nargs = mono_array_length (helper->arguments);
9736                 else
9737                         nargs = 0;
9738
9739                 sig = mono_metadata_signature_alloc (image, nargs);
9740                 sig->explicit_this = helper->call_conv & 64 ? 1 : 0;
9741                 sig->hasthis = helper->call_conv & 32 ? 1 : 0;
9742
9743                 if (helper->call_conv == 0) /* unmanaged */
9744                         sig->call_convention = helper->unmanaged_call_conv - 1;
9745                 else
9746                         if (helper->call_conv & 0x02)
9747                                 sig->call_convention = MONO_CALL_VARARG;
9748                 else
9749                         sig->call_convention = MONO_CALL_DEFAULT;
9750
9751                 sig->param_count = nargs;
9752                 /* TODO: Copy type ? */
9753                 sig->ret = helper->return_type->type;
9754                 for (i = 0; i < nargs; ++i) {
9755                         MonoReflectionType *rt = mono_array_get (helper->arguments, MonoReflectionType*, i);
9756                         sig->params [i] = rt->type;
9757                 }
9758
9759                 result = sig;
9760                 *handle_class = NULL;
9761         } else if (strcmp (obj->vtable->klass->name, "DynamicMethod") == 0) {
9762                 MonoReflectionDynamicMethod *method = (MonoReflectionDynamicMethod*)obj;
9763                 /* Already created by the managed code */
9764                 g_assert (method->mhandle);
9765                 result = method->mhandle;
9766                 *handle_class = mono_defaults.methodhandle_class;
9767         } else if (strcmp (obj->vtable->klass->name, "GenericTypeParameterBuilder") == 0) {
9768                 MonoReflectionType *tb = (MonoReflectionType*)obj;
9769                 result = mono_class_from_mono_type (mono_class_inflate_generic_type (tb->type, context));
9770                 *handle_class = mono_defaults.typehandle_class;
9771                 g_assert (result);
9772         } else if (strcmp (obj->vtable->klass->name, "MonoGenericClass") == 0) {
9773                 MonoReflectionGenericClass *ref = (MonoReflectionGenericClass*)obj;
9774                 result = mono_class_from_mono_type (mono_class_inflate_generic_type (ref->type.type, context));
9775                 *handle_class = mono_defaults.typehandle_class;
9776                 g_assert (result);
9777         } else {
9778                 g_print (obj->vtable->klass->name);
9779                 g_assert_not_reached ();
9780         }
9781         return result;
9782 }
9783
9784
9785 /* SECURITY_ACTION_* are defined in mono/metadata/tabledefs.h */
9786 const static guint32 declsec_flags_map[] = {
9787         0x00000000,                                     /* empty */
9788         MONO_DECLSEC_FLAG_REQUEST,                      /* SECURITY_ACTION_REQUEST                      (x01) */
9789         MONO_DECLSEC_FLAG_DEMAND,                       /* SECURITY_ACTION_DEMAND                       (x02) */
9790         MONO_DECLSEC_FLAG_ASSERT,                       /* SECURITY_ACTION_ASSERT                       (x03) */
9791         MONO_DECLSEC_FLAG_DENY,                         /* SECURITY_ACTION_DENY                         (x04) */
9792         MONO_DECLSEC_FLAG_PERMITONLY,                   /* SECURITY_ACTION_PERMITONLY                   (x05) */
9793         MONO_DECLSEC_FLAG_LINKDEMAND,                   /* SECURITY_ACTION_LINKDEMAND                   (x06) */
9794         MONO_DECLSEC_FLAG_INHERITANCEDEMAND,            /* SECURITY_ACTION_INHERITANCEDEMAND            (x07) */
9795         MONO_DECLSEC_FLAG_REQUEST_MINIMUM,              /* SECURITY_ACTION_REQUEST_MINIMUM              (x08) */
9796         MONO_DECLSEC_FLAG_REQUEST_OPTIONAL,             /* SECURITY_ACTION_REQUEST_OPTIONAL             (x09) */
9797         MONO_DECLSEC_FLAG_REQUEST_REFUSE,               /* SECURITY_ACTION_REQUEST_REFUSE               (x0A) */
9798         MONO_DECLSEC_FLAG_PREJIT_GRANT,                 /* SECURITY_ACTION_PREJIT_GRANT                 (x0B) */
9799         MONO_DECLSEC_FLAG_PREJIT_DENY,                  /* SECURITY_ACTION_PREJIT_DENY                  (x0C) */
9800         MONO_DECLSEC_FLAG_NONCAS_DEMAND,                /* SECURITY_ACTION_NONCAS_DEMAND                (x0D) */
9801         MONO_DECLSEC_FLAG_NONCAS_LINKDEMAND,            /* SECURITY_ACTION_NONCAS_LINKDEMAND            (x0E) */
9802         MONO_DECLSEC_FLAG_NONCAS_INHERITANCEDEMAND,     /* SECURITY_ACTION_NONCAS_INHERITANCEDEMAND     (x0F) */
9803         MONO_DECLSEC_FLAG_LINKDEMAND_CHOICE,            /* SECURITY_ACTION_LINKDEMAND_CHOICE            (x10) */
9804         MONO_DECLSEC_FLAG_INHERITANCEDEMAND_CHOICE,     /* SECURITY_ACTION_INHERITANCEDEMAND_CHOICE     (x11) */
9805         MONO_DECLSEC_FLAG_DEMAND_CHOICE,                /* SECURITY_ACTION_DEMAND_CHOICE                (x12) */
9806 };
9807
9808 /*
9809  * Returns flags that includes all available security action associated to the handle.
9810  * @token: metadata token (either for a class or a method)
9811  * @image: image where resides the metadata.
9812  */
9813 static guint32
9814 mono_declsec_get_flags (MonoImage *image, guint32 token)
9815 {
9816         int index = mono_metadata_declsec_from_index (image, token);
9817         MonoTableInfo *t = &image->tables [MONO_TABLE_DECLSECURITY];
9818         guint32 result = 0;
9819         guint32 action;
9820         int i;
9821
9822         /* HasSecurity can be present for other, not specially encoded, attributes,
9823            e.g. SuppressUnmanagedCodeSecurityAttribute */
9824         if (index < 0)
9825                 return 0;
9826
9827         for (i = index; i < t->rows; i++) {
9828                 guint32 cols [MONO_DECL_SECURITY_SIZE];
9829
9830                 mono_metadata_decode_row (t, i, cols, MONO_DECL_SECURITY_SIZE);
9831                 if (cols [MONO_DECL_SECURITY_PARENT] != token)
9832                         break;
9833
9834                 action = cols [MONO_DECL_SECURITY_ACTION];
9835                 if ((action >= MONO_DECLSEC_ACTION_MIN) && (action <= MONO_DECLSEC_ACTION_MAX)) {
9836                         result |= declsec_flags_map [action];
9837                 } else {
9838                         g_assert_not_reached ();
9839                 }
9840         }
9841         return result;
9842 }
9843
9844 /*
9845  * Get the security actions (in the form of flags) associated with the specified method.
9846  *
9847  * @method: The method for which we want the declarative security flags.
9848  * Return the declarative security flags for the method (only).
9849  *
9850  * Note: To keep MonoMethod size down we do not cache the declarative security flags
9851  *       (except for the stack modifiers which are kept in the MonoJitInfo structure)
9852  */
9853 guint32
9854 mono_declsec_flags_from_method (MonoMethod *method)
9855 {
9856         if (method->flags & METHOD_ATTRIBUTE_HAS_SECURITY) {
9857                 /* FIXME: No cache (for the moment) */
9858                 guint32 idx = mono_method_get_index (method);
9859                 idx <<= MONO_HAS_DECL_SECURITY_BITS;
9860                 idx |= MONO_HAS_DECL_SECURITY_METHODDEF;
9861                 return mono_declsec_get_flags (method->klass->image, idx);
9862         }
9863         return 0;
9864 }
9865
9866 /*
9867  * Get the security actions (in the form of flags) associated with the specified class.
9868  *
9869  * @klass: The class for which we want the declarative security flags.
9870  * Return the declarative security flags for the class.
9871  *
9872  * Note: We cache the flags inside the MonoClass structure as this will get 
9873  *       called very often (at least for each method).
9874  */
9875 guint32
9876 mono_declsec_flags_from_class (MonoClass *klass)
9877 {
9878         if (klass->flags & TYPE_ATTRIBUTE_HAS_SECURITY) {
9879                 if (!klass->declsec_flags) {
9880                         guint32 idx = mono_metadata_token_index (klass->type_token);
9881                         idx <<= MONO_HAS_DECL_SECURITY_BITS;
9882                         idx |= MONO_HAS_DECL_SECURITY_TYPEDEF;
9883                         /* we cache the flags on classes */
9884                         klass->declsec_flags = mono_declsec_get_flags (klass->image, idx);
9885                 }
9886                 return klass->declsec_flags;
9887         }
9888         return 0;
9889 }
9890
9891 /*
9892  * Get the security actions (in the form of flags) associated with the specified assembly.
9893  *
9894  * @assembly: The assembly for which we want the declarative security flags.
9895  * Return the declarative security flags for the assembly.
9896  */
9897 guint32
9898 mono_declsec_flags_from_assembly (MonoAssembly *assembly)
9899 {
9900         guint32 idx = 1; /* there is only one assembly */
9901         idx <<= MONO_HAS_DECL_SECURITY_BITS;
9902         idx |= MONO_HAS_DECL_SECURITY_ASSEMBLY;
9903         return mono_declsec_get_flags (assembly->image, idx);
9904 }
9905
9906
9907 /*
9908  * Fill actions for the specific index (which may either be an encoded class token or
9909  * an encoded method token) from the metadata image.
9910  * Returns TRUE if some actions requiring code generation are present, FALSE otherwise.
9911  */
9912 static MonoBoolean
9913 fill_actions_from_index (MonoImage *image, guint32 token, MonoDeclSecurityActions* actions,
9914         guint32 id_std, guint32 id_noncas, guint32 id_choice)
9915 {
9916         MonoBoolean result = FALSE;
9917         MonoTableInfo *t;
9918         guint32 cols [MONO_DECL_SECURITY_SIZE];
9919         int index = mono_metadata_declsec_from_index (image, token);
9920         int i;
9921
9922         t  = &image->tables [MONO_TABLE_DECLSECURITY];
9923         for (i = index; i < t->rows; i++) {
9924                 mono_metadata_decode_row (t, i, cols, MONO_DECL_SECURITY_SIZE);
9925
9926                 if (cols [MONO_DECL_SECURITY_PARENT] != token)
9927                         return result;
9928
9929                 /* if present only replace (class) permissions with method permissions */
9930                 /* if empty accept either class or method permissions */
9931                 if (cols [MONO_DECL_SECURITY_ACTION] == id_std) {
9932                         if (!actions->demand.blob) {
9933                                 const char *blob = mono_metadata_blob_heap (image, cols [MONO_DECL_SECURITY_PERMISSIONSET]);
9934                                 actions->demand.index = cols [MONO_DECL_SECURITY_PERMISSIONSET];
9935                                 actions->demand.blob = (char*) (blob + 2);
9936                                 actions->demand.size = mono_metadata_decode_blob_size (blob, &blob);
9937                                 result = TRUE;
9938                         }
9939                 } else if (cols [MONO_DECL_SECURITY_ACTION] == id_noncas) {
9940                         if (!actions->noncasdemand.blob) {
9941                                 const char *blob = mono_metadata_blob_heap (image, cols [MONO_DECL_SECURITY_PERMISSIONSET]);
9942                                 actions->noncasdemand.index = cols [MONO_DECL_SECURITY_PERMISSIONSET];
9943                                 actions->noncasdemand.blob = (char*) (blob + 2);
9944                                 actions->noncasdemand.size = mono_metadata_decode_blob_size (blob, &blob);
9945                                 result = TRUE;
9946                         }
9947                 } else if (cols [MONO_DECL_SECURITY_ACTION] == id_choice) {
9948                         if (!actions->demandchoice.blob) {
9949                                 const char *blob = mono_metadata_blob_heap (image, cols [MONO_DECL_SECURITY_PERMISSIONSET]);
9950                                 actions->demandchoice.index = cols [MONO_DECL_SECURITY_PERMISSIONSET];
9951                                 actions->demandchoice.blob = (char*) (blob + 2);
9952                                 actions->demandchoice.size = mono_metadata_decode_blob_size (blob, &blob);
9953                                 result = TRUE;
9954                         }
9955                 }
9956         }
9957
9958         return result;
9959 }
9960
9961 static MonoBoolean
9962 mono_declsec_get_class_demands_params (MonoClass *klass, MonoDeclSecurityActions* demands, 
9963         guint32 id_std, guint32 id_noncas, guint32 id_choice)
9964 {
9965         guint32 idx = mono_metadata_token_index (klass->type_token);
9966         idx <<= MONO_HAS_DECL_SECURITY_BITS;
9967         idx |= MONO_HAS_DECL_SECURITY_TYPEDEF;
9968         return fill_actions_from_index (klass->image, idx, demands, id_std, id_noncas, id_choice);
9969 }
9970
9971 static MonoBoolean
9972 mono_declsec_get_method_demands_params (MonoMethod *method, MonoDeclSecurityActions* demands, 
9973         guint32 id_std, guint32 id_noncas, guint32 id_choice)
9974 {
9975         guint32 idx = mono_method_get_index (method);
9976         idx <<= MONO_HAS_DECL_SECURITY_BITS;
9977         idx |= MONO_HAS_DECL_SECURITY_METHODDEF;
9978         return fill_actions_from_index (method->klass->image, idx, demands, id_std, id_noncas, id_choice);
9979 }
9980
9981 /*
9982  * Collect all actions (that requires to generate code in mini) assigned for
9983  * the specified method.
9984  * Note: Don't use the content of actions if the function return FALSE.
9985  */
9986 MonoBoolean
9987 mono_declsec_get_demands (MonoMethod *method, MonoDeclSecurityActions* demands)
9988 {
9989         guint32 mask = MONO_DECLSEC_FLAG_DEMAND | MONO_DECLSEC_FLAG_NONCAS_DEMAND | 
9990                 MONO_DECLSEC_FLAG_DEMAND_CHOICE;
9991         MonoBoolean result = FALSE;
9992         guint32 flags;
9993
9994         /* quick exit if no declarative security is present in the metadata */
9995         if (!method->klass->image->tables [MONO_TABLE_DECLSECURITY].rows)
9996                 return FALSE;
9997
9998         /* we want the original as the wrapper is "free" of the security informations */
9999         if (method->wrapper_type == MONO_WRAPPER_MANAGED_TO_NATIVE || method->wrapper_type == MONO_WRAPPER_MANAGED_TO_MANAGED) {
10000                 method = mono_marshal_method_from_wrapper (method);
10001                 if (!method)
10002                         return FALSE;
10003         }
10004
10005         /* First we look for method-level attributes */
10006         if (method->flags & METHOD_ATTRIBUTE_HAS_SECURITY) {
10007                 mono_class_init (method->klass);
10008                 memset (demands, 0, sizeof (MonoDeclSecurityActions));
10009
10010                 result = mono_declsec_get_method_demands_params (method, demands, 
10011                         SECURITY_ACTION_DEMAND, SECURITY_ACTION_NONCASDEMAND, SECURITY_ACTION_DEMANDCHOICE);
10012         }
10013
10014         /* Here we use (or create) the class declarative cache to look for demands */
10015         flags = mono_declsec_flags_from_class (method->klass);
10016         if (flags & mask) {
10017                 if (!result) {
10018                         mono_class_init (method->klass);
10019                         memset (demands, 0, sizeof (MonoDeclSecurityActions));
10020                 }
10021                 result |= mono_declsec_get_class_demands_params (method->klass, demands, 
10022                         SECURITY_ACTION_DEMAND, SECURITY_ACTION_NONCASDEMAND, SECURITY_ACTION_DEMANDCHOICE);
10023         }
10024
10025         /* The boolean return value is used as a shortcut in case nothing needs to
10026            be generated (e.g. LinkDemand[Choice] and InheritanceDemand[Choice]) */
10027         return result;
10028 }
10029
10030
10031 /*
10032  * Collect all Link actions: LinkDemand, NonCasLinkDemand and LinkDemandChoice (2.0).
10033  *
10034  * Note: Don't use the content of actions if the function return FALSE.
10035  */
10036 MonoBoolean
10037 mono_declsec_get_linkdemands (MonoMethod *method, MonoDeclSecurityActions* klass, MonoDeclSecurityActions *cmethod)
10038 {
10039         MonoBoolean result = FALSE;
10040         guint32 flags;
10041
10042         /* quick exit if no declarative security is present in the metadata */
10043         if (!method->klass->image->tables [MONO_TABLE_DECLSECURITY].rows)
10044                 return FALSE;
10045
10046         /* we want the original as the wrapper is "free" of the security informations */
10047         if (method->wrapper_type == MONO_WRAPPER_MANAGED_TO_NATIVE || method->wrapper_type == MONO_WRAPPER_MANAGED_TO_MANAGED) {
10048                 method = mono_marshal_method_from_wrapper (method);
10049                 if (!method)
10050                         return FALSE;
10051         }
10052
10053         /* results are independant - zeroize both */
10054         memset (cmethod, 0, sizeof (MonoDeclSecurityActions));
10055         memset (klass, 0, sizeof (MonoDeclSecurityActions));
10056
10057         /* First we look for method-level attributes */
10058         if (method->flags & METHOD_ATTRIBUTE_HAS_SECURITY) {
10059                 mono_class_init (method->klass);
10060
10061                 result = mono_declsec_get_method_demands_params (method, cmethod, 
10062                         SECURITY_ACTION_LINKDEMAND, SECURITY_ACTION_NONCASLINKDEMAND, SECURITY_ACTION_LINKDEMANDCHOICE);
10063         }
10064
10065         /* Here we use (or create) the class declarative cache to look for demands */
10066         flags = mono_declsec_flags_from_class (method->klass);
10067         if (flags & (MONO_DECLSEC_FLAG_LINKDEMAND | MONO_DECLSEC_FLAG_NONCAS_LINKDEMAND | MONO_DECLSEC_FLAG_LINKDEMAND_CHOICE)) {
10068                 mono_class_init (method->klass);
10069
10070                 result |= mono_declsec_get_class_demands_params (method->klass, klass, 
10071                         SECURITY_ACTION_LINKDEMAND, SECURITY_ACTION_NONCASLINKDEMAND, SECURITY_ACTION_LINKDEMANDCHOICE);
10072         }
10073
10074         return result;
10075 }
10076
10077 /*
10078  * Collect all Inherit actions: InheritanceDemand, NonCasInheritanceDemand and InheritanceDemandChoice (2.0).
10079  *
10080  * @klass       The inherited class - this is the class that provides the security check (attributes)
10081  * @demans      
10082  * return TRUE if inheritance demands (any kind) are present, FALSE otherwise.
10083  * 
10084  * Note: Don't use the content of actions if the function return FALSE.
10085  */
10086 MonoBoolean
10087 mono_declsec_get_inheritdemands_class (MonoClass *klass, MonoDeclSecurityActions* demands)
10088 {
10089         MonoBoolean result = FALSE;
10090         guint32 flags;
10091
10092         /* quick exit if no declarative security is present in the metadata */
10093         if (!klass->image->tables [MONO_TABLE_DECLSECURITY].rows)
10094                 return FALSE;
10095
10096         /* Here we use (or create) the class declarative cache to look for demands */
10097         flags = mono_declsec_flags_from_class (klass);
10098         if (flags & (MONO_DECLSEC_FLAG_INHERITANCEDEMAND | MONO_DECLSEC_FLAG_NONCAS_INHERITANCEDEMAND | MONO_DECLSEC_FLAG_INHERITANCEDEMAND_CHOICE)) {
10099                 mono_class_init (klass);
10100                 memset (demands, 0, sizeof (MonoDeclSecurityActions));
10101
10102                 result |= mono_declsec_get_class_demands_params (klass, demands, 
10103                         SECURITY_ACTION_INHERITDEMAND, SECURITY_ACTION_NONCASINHERITANCE, SECURITY_ACTION_INHERITDEMANDCHOICE);
10104         }
10105
10106         return result;
10107 }
10108
10109 /*
10110  * Collect all Inherit actions: InheritanceDemand, NonCasInheritanceDemand and InheritanceDemandChoice (2.0).
10111  *
10112  * Note: Don't use the content of actions if the function return FALSE.
10113  */
10114 MonoBoolean
10115 mono_declsec_get_inheritdemands_method (MonoMethod *method, MonoDeclSecurityActions* demands)
10116 {
10117         /* quick exit if no declarative security is present in the metadata */
10118         if (!method->klass->image->tables [MONO_TABLE_DECLSECURITY].rows)
10119                 return FALSE;
10120
10121         /* we want the original as the wrapper is "free" of the security informations */
10122         if (method->wrapper_type == MONO_WRAPPER_MANAGED_TO_NATIVE || method->wrapper_type == MONO_WRAPPER_MANAGED_TO_MANAGED) {
10123                 method = mono_marshal_method_from_wrapper (method);
10124                 if (!method)
10125                         return FALSE;
10126         }
10127
10128         if (method->flags & METHOD_ATTRIBUTE_HAS_SECURITY) {
10129                 mono_class_init (method->klass);
10130                 memset (demands, 0, sizeof (MonoDeclSecurityActions));
10131
10132                 return mono_declsec_get_method_demands_params (method, demands, 
10133                         SECURITY_ACTION_INHERITDEMAND, SECURITY_ACTION_NONCASINHERITANCE, SECURITY_ACTION_INHERITDEMANDCHOICE);
10134         }
10135         return FALSE;
10136 }
10137
10138
10139 static MonoBoolean
10140 get_declsec_action (MonoImage *image, guint32 token, guint32 action, MonoDeclSecurityEntry *entry)
10141 {
10142         guint32 cols [MONO_DECL_SECURITY_SIZE];
10143         MonoTableInfo *t;
10144         int i;
10145
10146         int index = mono_metadata_declsec_from_index (image, token);
10147         if (index == -1)
10148                 return FALSE;
10149
10150         t =  &image->tables [MONO_TABLE_DECLSECURITY];
10151         for (i = index; i < t->rows; i++) {
10152                 mono_metadata_decode_row (t, i, cols, MONO_DECL_SECURITY_SIZE);
10153
10154                 /* shortcut - index are ordered */
10155                 if (token != cols [MONO_DECL_SECURITY_PARENT])
10156                         return FALSE;
10157
10158                 if (cols [MONO_DECL_SECURITY_ACTION] == action) {
10159                         const char *metadata = mono_metadata_blob_heap (image, cols [MONO_DECL_SECURITY_PERMISSIONSET]);
10160                         entry->blob = (char*) (metadata + 2);
10161                         entry->size = mono_metadata_decode_blob_size (metadata, &metadata);
10162                         return TRUE;
10163                 }
10164         }
10165
10166         return FALSE;
10167 }
10168
10169 MonoBoolean
10170 mono_declsec_get_method_action (MonoMethod *method, guint32 action, MonoDeclSecurityEntry *entry)
10171 {
10172         if (method->flags & METHOD_ATTRIBUTE_HAS_SECURITY) {
10173                 guint32 idx = mono_method_get_index (method);
10174                 idx <<= MONO_HAS_DECL_SECURITY_BITS;
10175                 idx |= MONO_HAS_DECL_SECURITY_METHODDEF;
10176                 return get_declsec_action (method->klass->image, idx, action, entry);
10177         }
10178         return FALSE;
10179 }
10180
10181 MonoBoolean
10182 mono_declsec_get_class_action (MonoClass *klass, guint32 action, MonoDeclSecurityEntry *entry)
10183 {
10184         /* use cache */
10185         guint32 flags = mono_declsec_flags_from_class (klass);
10186         if (declsec_flags_map [action] & flags) {
10187                 guint32 idx = mono_metadata_token_index (klass->type_token);
10188                 idx <<= MONO_HAS_DECL_SECURITY_BITS;
10189                 idx |= MONO_HAS_DECL_SECURITY_TYPEDEF;
10190                 return get_declsec_action (klass->image, idx, action, entry);
10191         }
10192         return FALSE;
10193 }
10194
10195 MonoBoolean
10196 mono_declsec_get_assembly_action (MonoAssembly *assembly, guint32 action, MonoDeclSecurityEntry *entry)
10197 {
10198         guint32 idx = 1; /* there is only one assembly */
10199         idx <<= MONO_HAS_DECL_SECURITY_BITS;
10200         idx |= MONO_HAS_DECL_SECURITY_ASSEMBLY;
10201
10202         return get_declsec_action (assembly->image, idx, action, entry);
10203 }
10204
10205 gboolean
10206 mono_reflection_call_is_assignable_to (MonoClass *klass, MonoClass *oklass)
10207 {
10208         MonoObject *res, *exc;
10209         void *params [1];
10210         static MonoClass *System_Reflection_Emit_TypeBuilder = NULL;
10211         static MonoMethod *method = NULL;
10212
10213         if (!System_Reflection_Emit_TypeBuilder) {
10214                 System_Reflection_Emit_TypeBuilder = mono_class_from_name (mono_defaults.corlib, "System.Reflection.Emit", "TypeBuilder");
10215                 g_assert (System_Reflection_Emit_TypeBuilder);
10216         }
10217         if (method == NULL) {
10218                 method = mono_class_get_method_from_name (System_Reflection_Emit_TypeBuilder, "IsAssignableTo", 1);
10219                 g_assert (method);
10220         }
10221
10222         /* 
10223          * The result of mono_type_get_object () might be a System.MonoType but we
10224          * need a TypeBuilder so use klass->reflection_info.
10225          */
10226         g_assert (klass->reflection_info);
10227         g_assert (!strcmp (((MonoObject*)(klass->reflection_info))->vtable->klass->name, "TypeBuilder"));
10228
10229         params [0] = mono_type_get_object (mono_domain_get (), &oklass->byval_arg);
10230
10231         res = mono_runtime_invoke (method, (MonoObject*)(klass->reflection_info), params, &exc);
10232         if (exc)
10233                 return FALSE;
10234         else
10235                 return *(MonoBoolean*)mono_object_unbox (res);
10236 }