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