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