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