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