Rename Changelog -> ChangeLog.
[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->field->parent->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->field->parent->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         if (!domain->refobject_hash)
5085                 domain->refobject_hash = mono_g_hash_table_new (reflected_hash, reflected_equal);
5086         CACHE_OBJECT (assembly, res, NULL);
5087 }
5088
5089 static void
5090 register_module (MonoDomain *domain, MonoReflectionModuleBuilder *res, MonoDynamicImage *module)
5091 {
5092         /* this is done only once */
5093         mono_domain_lock (domain);
5094         if (!domain->refobject_hash)
5095                 domain->refobject_hash = mono_g_hash_table_new (reflected_hash, reflected_equal);
5096         CACHE_OBJECT (module, res, NULL);
5097 }
5098
5099 void
5100 mono_image_module_basic_init (MonoReflectionModuleBuilder *moduleb)
5101 {
5102         MonoDynamicImage *image = moduleb->dynamic_image;
5103         MonoReflectionAssemblyBuilder *ab = moduleb->assemblyb;
5104         if (!image) {
5105                 int module_count;
5106                 MonoImage **new_modules;
5107                 MonoImage *ass;
5108                 /*
5109                  * FIXME: we already created an image in mono_image_basic_init (), but
5110                  * we don't know which module it belongs to, since that is only 
5111                  * determined at assembly save time.
5112                  */
5113                 /*image = (MonoDynamicImage*)ab->dynamic_assembly->assembly.image; */
5114                 image = create_dynamic_mono_image (ab->dynamic_assembly, mono_string_to_utf8 (ab->name), mono_string_to_utf8 (moduleb->module.fqname));
5115
5116                 moduleb->module.image = &image->image;
5117                 moduleb->dynamic_image = image;
5118                 register_module (mono_object_domain (moduleb), moduleb, image);
5119
5120                 /* register the module with the assembly */
5121                 ass = ab->dynamic_assembly->assembly.image;
5122                 module_count = ass->module_count;
5123                 new_modules = g_new0 (MonoImage *, module_count + 1);
5124
5125                 if (ass->modules)
5126                         memcpy (new_modules, ass->modules, module_count * sizeof (MonoImage *));
5127                 new_modules [module_count] = &image->image;
5128
5129                 g_free (ass->modules);
5130                 ass->modules = new_modules;
5131                 ass->module_count ++;
5132         }
5133 }
5134
5135 /*
5136  * mono_assembly_get_object:
5137  * @domain: an app domain
5138  * @assembly: an assembly
5139  *
5140  * Return an System.Reflection.Assembly object representing the MonoAssembly @assembly.
5141  */
5142 MonoReflectionAssembly*
5143 mono_assembly_get_object (MonoDomain *domain, MonoAssembly *assembly)
5144 {
5145         static MonoClass *System_Reflection_Assembly;
5146         MonoReflectionAssembly *res;
5147         
5148         CHECK_OBJECT (MonoReflectionAssembly *, assembly, NULL);
5149         if (!System_Reflection_Assembly)
5150                 System_Reflection_Assembly = mono_class_from_name (
5151                         mono_defaults.corlib, "System.Reflection", "Assembly");
5152         res = (MonoReflectionAssembly *)mono_object_new (domain, System_Reflection_Assembly);
5153         res->assembly = assembly;
5154
5155         CACHE_OBJECT (assembly, res, NULL);
5156         return res;
5157 }
5158
5159
5160
5161 MonoReflectionModule*   
5162 mono_module_get_object   (MonoDomain *domain, MonoImage *image)
5163 {
5164         static MonoClass *System_Reflection_Module;
5165         MonoReflectionModule *res;
5166         char* basename;
5167         
5168         CHECK_OBJECT (MonoReflectionModule *, image, NULL);
5169         if (!System_Reflection_Module)
5170                 System_Reflection_Module = mono_class_from_name (
5171                         mono_defaults.corlib, "System.Reflection", "Module");
5172         res = (MonoReflectionModule *)mono_object_new (domain, System_Reflection_Module);
5173
5174         res->image = image;
5175         res->assembly = (MonoReflectionAssembly *) mono_assembly_get_object(domain, image->assembly);
5176
5177         res->fqname    = mono_string_new (domain, image->name);
5178         res->name      = mono_string_new (domain, basename = g_path_get_basename (image->name));
5179         res->scopename = mono_string_new (domain, image->module_name);
5180         
5181         g_free (basename);
5182
5183         if (image->assembly->image == image) {
5184                 res->token = mono_metadata_make_token (MONO_TABLE_MODULE, 1);
5185         } else {
5186                 int i;
5187                 g_assert (image->assembly->image->modules);
5188                 res->token = 0;
5189                 for (i = 0; i < image->assembly->image->module_count; i++) {
5190                         if (image->assembly->image->modules [i] == image)
5191                                 res->token = mono_metadata_make_token (MONO_TABLE_MODULEREF, i + 1);
5192                 }
5193                 g_assert (res->token);
5194         }
5195
5196         mono_image_addref (image);
5197
5198         CACHE_OBJECT (image, res, NULL);
5199         return res;
5200 }
5201
5202 MonoReflectionModule*   
5203 mono_module_file_get_object (MonoDomain *domain, MonoImage *image, int table_index)
5204 {
5205         static MonoClass *System_Reflection_Module;
5206         MonoReflectionModule *res;
5207         MonoTableInfo *table;
5208         guint32 cols [MONO_FILE_SIZE];
5209         const char *name;
5210         guint32 i, name_idx;
5211         const char *val;
5212         
5213         if (!System_Reflection_Module)
5214                 System_Reflection_Module = mono_class_from_name (
5215                         mono_defaults.corlib, "System.Reflection", "Module");
5216         res = (MonoReflectionModule *)mono_object_new (domain, System_Reflection_Module);
5217
5218         table = &image->tables [MONO_TABLE_FILE];
5219         g_assert (table_index < table->rows);
5220         mono_metadata_decode_row (table, table_index, cols, MONO_FILE_SIZE);
5221
5222         res->image = 0;
5223         res->assembly = (MonoReflectionAssembly *) mono_assembly_get_object(domain, image->assembly);
5224         name = mono_metadata_string_heap (image, cols [MONO_FILE_NAME]);
5225
5226         /* Check whenever the row has a corresponding row in the moduleref table */
5227         table = &image->tables [MONO_TABLE_MODULEREF];
5228         for (i = 0; i < table->rows; ++i) {
5229                 name_idx = mono_metadata_decode_row_col (table, i, MONO_MODULEREF_NAME);
5230                 val = mono_metadata_string_heap (image, name_idx);
5231                 if (strcmp (val, name) == 0)
5232                         res->image = image->modules [i];
5233         }
5234
5235         res->fqname    = mono_string_new (domain, name);
5236         res->name      = mono_string_new (domain, name);
5237         res->scopename = mono_string_new (domain, name);
5238         res->is_resource = cols [MONO_FILE_FLAGS] && FILE_CONTAINS_NO_METADATA;
5239         res->token = mono_metadata_make_token (MONO_TABLE_FILE, table_index + 1);
5240
5241         return res;
5242 }
5243
5244 static gboolean
5245 mymono_metadata_type_equal (MonoType *t1, MonoType *t2)
5246 {
5247         if ((t1->type != t2->type) ||
5248             (t1->byref != t2->byref))
5249                 return FALSE;
5250
5251         switch (t1->type) {
5252         case MONO_TYPE_VOID:
5253         case MONO_TYPE_BOOLEAN:
5254         case MONO_TYPE_CHAR:
5255         case MONO_TYPE_I1:
5256         case MONO_TYPE_U1:
5257         case MONO_TYPE_I2:
5258         case MONO_TYPE_U2:
5259         case MONO_TYPE_I4:
5260         case MONO_TYPE_U4:
5261         case MONO_TYPE_I8:
5262         case MONO_TYPE_U8:
5263         case MONO_TYPE_R4:
5264         case MONO_TYPE_R8:
5265         case MONO_TYPE_STRING:
5266         case MONO_TYPE_I:
5267         case MONO_TYPE_U:
5268         case MONO_TYPE_OBJECT:
5269         case MONO_TYPE_TYPEDBYREF:
5270                 return TRUE;
5271         case MONO_TYPE_VALUETYPE:
5272         case MONO_TYPE_CLASS:
5273         case MONO_TYPE_SZARRAY:
5274                 return t1->data.klass == t2->data.klass;
5275         case MONO_TYPE_PTR:
5276                 return mymono_metadata_type_equal (t1->data.type, t2->data.type);
5277         case MONO_TYPE_ARRAY:
5278                 if (t1->data.array->rank != t2->data.array->rank)
5279                         return FALSE;
5280                 return t1->data.array->eklass == t2->data.array->eklass;
5281         case MONO_TYPE_GENERICINST: {
5282                 int i;
5283                 if (t1->data.generic_class->inst->type_argc != t2->data.generic_class->inst->type_argc)
5284                         return FALSE;
5285                 if (!mono_metadata_type_equal (&t1->data.generic_class->container_class->byval_arg,
5286                                                &t2->data.generic_class->container_class->byval_arg))
5287                         return FALSE;
5288                 for (i = 0; i < t1->data.generic_class->inst->type_argc; ++i) {
5289                         if (!mono_metadata_type_equal (t1->data.generic_class->inst->type_argv [i], t2->data.generic_class->inst->type_argv [i]))
5290                                 return FALSE;
5291                 }
5292                 return TRUE;
5293         }
5294         case MONO_TYPE_VAR:
5295         case MONO_TYPE_MVAR:
5296                 return t1->data.generic_param == t2->data.generic_param;
5297         default:
5298                 g_error ("implement type compare for %0x!", t1->type);
5299                 return FALSE;
5300         }
5301
5302         return FALSE;
5303 }
5304
5305 static guint
5306 mymono_metadata_type_hash (MonoType *t1)
5307 {
5308         guint hash;
5309
5310         hash = t1->type;
5311
5312         hash |= t1->byref << 6; /* do not collide with t1->type values */
5313         switch (t1->type) {
5314         case MONO_TYPE_VALUETYPE:
5315         case MONO_TYPE_CLASS:
5316         case MONO_TYPE_SZARRAY:
5317                 /* check if the distribution is good enough */
5318                 return ((hash << 5) - hash) ^ g_str_hash (t1->data.klass->name);
5319         case MONO_TYPE_PTR:
5320                 return ((hash << 5) - hash) ^ mymono_metadata_type_hash (t1->data.type);
5321         }
5322         return hash;
5323 }
5324
5325 static MonoReflectionGenericClass*
5326 mono_generic_class_get_object (MonoDomain *domain, MonoType *geninst)
5327 {
5328         static MonoClass *System_Reflection_MonoGenericClass;
5329         MonoReflectionGenericClass *res;
5330         MonoInflatedGenericClass *gclass;
5331         MonoClass *gklass;
5332
5333         if (!System_Reflection_MonoGenericClass) {
5334                 System_Reflection_MonoGenericClass = mono_class_from_name (
5335                         mono_defaults.corlib, "System.Reflection", "MonoGenericClass");
5336                 g_assert (System_Reflection_MonoGenericClass);
5337         }
5338
5339         gclass = mono_get_inflated_generic_class (geninst->data.generic_class);
5340         gklass = gclass->generic_class.container_class;
5341
5342         mono_class_init (gclass->klass);
5343
5344         res = (MonoReflectionGenericClass *) mono_object_new (domain, System_Reflection_MonoGenericClass);
5345
5346         res->type.type = geninst;
5347         if (gklass->wastypebuilder && gklass->reflection_info)
5348                 res->generic_type = gklass->reflection_info;
5349         else
5350                 res->generic_type = mono_type_get_object (
5351                         domain, &gclass->generic_class.container_class->byval_arg);
5352
5353         return res;
5354 }
5355
5356 /*
5357  * mono_type_get_object:
5358  * @domain: an app domain
5359  * @type: a type
5360  *
5361  * Return an System.MonoType object representing the type @type.
5362  */
5363 MonoReflectionType*
5364 mono_type_get_object (MonoDomain *domain, MonoType *type)
5365 {
5366         MonoReflectionType *res;
5367         MonoClass *klass = mono_class_from_mono_type (type);
5368
5369         mono_domain_lock (domain);
5370         if (!domain->type_hash)
5371                 domain->type_hash = mono_g_hash_table_new ((GHashFunc)mymono_metadata_type_hash, 
5372                                 (GCompareFunc)mymono_metadata_type_equal);
5373         if ((res = mono_g_hash_table_lookup (domain->type_hash, type))) {
5374                 mono_domain_unlock (domain);
5375                 return res;
5376         }
5377         if ((type->type == MONO_TYPE_GENERICINST) && type->data.generic_class->is_dynamic) {
5378                 res = (MonoReflectionType *)mono_generic_class_get_object (domain, type);
5379                 mono_g_hash_table_insert (domain->type_hash, type, res);
5380                 mono_domain_unlock (domain);
5381                 return res;
5382         }
5383         if (klass->reflection_info && !klass->wastypebuilder) {
5384                 /* g_assert_not_reached (); */
5385                 /* should this be considered an error condition? */
5386                 if (!type->byref) {
5387                         mono_domain_unlock (domain);
5388                         return klass->reflection_info;
5389                 }
5390         }
5391         mono_class_init (klass);
5392         res = (MonoReflectionType *)mono_object_new (domain, mono_defaults.monotype_class);
5393         res->type = type;
5394         mono_g_hash_table_insert (domain->type_hash, type, res);
5395         mono_domain_unlock (domain);
5396         return res;
5397 }
5398
5399 /*
5400  * mono_method_get_object:
5401  * @domain: an app domain
5402  * @method: a method
5403  * @refclass: the reflected type (can be NULL)
5404  *
5405  * Return an System.Reflection.MonoMethod object representing the method @method.
5406  */
5407 MonoReflectionMethod*
5408 mono_method_get_object (MonoDomain *domain, MonoMethod *method, MonoClass *refclass)
5409 {
5410         /*
5411          * We use the same C representation for methods and constructors, but the type 
5412          * name in C# is different.
5413          */
5414         const char *cname;
5415         MonoClass *klass;
5416         MonoReflectionMethod *ret;
5417
5418         if (method->is_inflated) {
5419                 MonoReflectionGenericMethod *gret;
5420
5421                 refclass = method->klass;
5422                 CHECK_OBJECT (MonoReflectionMethod *, method, refclass);
5423                 if ((*method->name == '.') && (!strcmp (method->name, ".ctor") || !strcmp (method->name, ".cctor")))
5424                         cname = "MonoGenericCMethod";
5425                 else
5426                         cname = "MonoGenericMethod";
5427                 klass = mono_class_from_name (mono_defaults.corlib, "System.Reflection", cname);
5428
5429                 gret = (MonoReflectionGenericMethod*)mono_object_new (domain, klass);
5430                 gret->method.method = method;
5431                 gret->method.name = mono_string_new (domain, method->name);
5432                 gret->method.reftype = mono_type_get_object (domain, &refclass->byval_arg);
5433                 CACHE_OBJECT (method, gret, refclass);
5434                 return (MonoReflectionMethod *) gret;
5435         }
5436
5437         if (!refclass)
5438                 refclass = method->klass;
5439
5440         CHECK_OBJECT (MonoReflectionMethod *, method, refclass);
5441         if (*method->name == '.' && (strcmp (method->name, ".ctor") == 0 || strcmp (method->name, ".cctor") == 0))
5442                 cname = "MonoCMethod";
5443         else
5444                 cname = "MonoMethod";
5445         klass = mono_class_from_name (mono_defaults.corlib, "System.Reflection", cname);
5446
5447         ret = (MonoReflectionMethod*)mono_object_new (domain, klass);
5448         ret->method = method;
5449         ret->name = mono_string_new (domain, method->name);
5450         ret->reftype = mono_type_get_object (domain, &refclass->byval_arg);
5451         CACHE_OBJECT (method, ret, refclass);
5452         return ret;
5453 }
5454
5455 /*
5456  * mono_field_get_object:
5457  * @domain: an app domain
5458  * @klass: a type
5459  * @field: a field
5460  *
5461  * Return an System.Reflection.MonoField object representing the field @field
5462  * in class @klass.
5463  */
5464 MonoReflectionField*
5465 mono_field_get_object (MonoDomain *domain, MonoClass *klass, MonoClassField *field)
5466 {
5467         MonoReflectionField *res;
5468         MonoClass *oklass;
5469
5470         CHECK_OBJECT (MonoReflectionField *, field, klass);
5471         oklass = mono_class_from_name (mono_defaults.corlib, "System.Reflection", "MonoField");
5472         res = (MonoReflectionField *)mono_object_new (domain, oklass);
5473         res->klass = klass;
5474         res->field = field;
5475         res->name = mono_string_new (domain, field->name);
5476         if (field->generic_info)
5477                 res->attrs = field->generic_info->generic_type->attrs;
5478         else
5479                 res->attrs = field->type->attrs;
5480         res->type = mono_type_get_object (domain, field->type);
5481         CACHE_OBJECT (field, res, klass);
5482         return res;
5483 }
5484
5485 /*
5486  * mono_property_get_object:
5487  * @domain: an app domain
5488  * @klass: a type
5489  * @property: a property
5490  *
5491  * Return an System.Reflection.MonoProperty object representing the property @property
5492  * in class @klass.
5493  */
5494 MonoReflectionProperty*
5495 mono_property_get_object (MonoDomain *domain, MonoClass *klass, MonoProperty *property)
5496 {
5497         MonoReflectionProperty *res;
5498         MonoClass *oklass;
5499
5500         CHECK_OBJECT (MonoReflectionProperty *, property, klass);
5501         oklass = mono_class_from_name (mono_defaults.corlib, "System.Reflection", "MonoProperty");
5502         res = (MonoReflectionProperty *)mono_object_new (domain, oklass);
5503         res->klass = klass;
5504         res->property = property;
5505         CACHE_OBJECT (property, res, klass);
5506         return res;
5507 }
5508
5509 /*
5510  * mono_event_get_object:
5511  * @domain: an app domain
5512  * @klass: a type
5513  * @event: a event
5514  *
5515  * Return an System.Reflection.MonoEvent object representing the event @event
5516  * in class @klass.
5517  */
5518 MonoReflectionEvent*
5519 mono_event_get_object (MonoDomain *domain, MonoClass *klass, MonoEvent *event)
5520 {
5521         MonoReflectionEvent *res;
5522         MonoClass *oklass;
5523
5524         CHECK_OBJECT (MonoReflectionEvent *, event, klass);
5525         oklass = mono_class_from_name (mono_defaults.corlib, "System.Reflection", "MonoEvent");
5526         res = (MonoReflectionEvent *)mono_object_new (domain, oklass);
5527         res->klass = klass;
5528         res->event = event;
5529         CACHE_OBJECT (event, res, klass);
5530         return res;
5531 }
5532
5533 /*
5534  * mono_param_get_objects:
5535  * @domain: an app domain
5536  * @method: a method
5537  *
5538  * Return an System.Reflection.ParameterInfo array object representing the parameters
5539  * in the method @method.
5540  */
5541 MonoArray*
5542 mono_param_get_objects (MonoDomain *domain, MonoMethod *method)
5543 {
5544         static MonoClass *System_Reflection_ParameterInfo;
5545         MonoArray *res = NULL;
5546         MonoReflectionMethod *member = NULL;
5547         MonoReflectionParameter *param = NULL;
5548         char **names, **blobs = NULL;
5549         guint32 *types = NULL;
5550         MonoType *type = NULL;
5551         MonoObject *dbnull = mono_get_dbnull_object (domain);
5552         MonoMarshalSpec **mspecs;
5553         int i;
5554
5555         if (!System_Reflection_ParameterInfo)
5556                 System_Reflection_ParameterInfo = mono_class_from_name (
5557                         mono_defaults.corlib, "System.Reflection", "ParameterInfo");
5558         
5559         if (!mono_method_signature (method)->param_count)
5560                 return mono_array_new (domain, System_Reflection_ParameterInfo, 0);
5561
5562         /* Note: the cache is based on the address of the signature into the method
5563          * since we already cache MethodInfos with the method as keys.
5564          */
5565         CHECK_OBJECT (MonoArray*, &(method->signature), NULL);
5566
5567         member = mono_method_get_object (domain, method, NULL);
5568         names = g_new (char *, mono_method_signature (method)->param_count);
5569         mono_method_get_param_names (method, (const char **) names);
5570
5571         mspecs = g_new (MonoMarshalSpec*, mono_method_signature (method)->param_count + 1);
5572         mono_method_get_marshal_info (method, mspecs);
5573
5574         res = mono_array_new (domain, System_Reflection_ParameterInfo, mono_method_signature (method)->param_count);
5575         for (i = 0; i < mono_method_signature (method)->param_count; ++i) {
5576                 param = (MonoReflectionParameter *)mono_object_new (domain, System_Reflection_ParameterInfo);
5577                 param->ClassImpl = mono_type_get_object (domain, mono_method_signature (method)->params [i]);
5578                 param->MemberImpl = (MonoObject*)member;
5579                 param->NameImpl = mono_string_new (domain, names [i]);
5580                 param->PositionImpl = i;
5581                 param->AttrsImpl = mono_method_signature (method)->params [i]->attrs;
5582
5583                 if (!(param->AttrsImpl & PARAM_ATTRIBUTE_HAS_DEFAULT)) {
5584                         param->DefaultValueImpl = dbnull;
5585                 } else {
5586
5587                         if (!blobs) {
5588                                 blobs = g_new0 (char *, mono_method_signature (method)->param_count);
5589                                 types = g_new0 (guint32, mono_method_signature (method)->param_count);
5590                                 get_default_param_value_blobs (method, blobs, types); 
5591                         }
5592
5593                         /* Build MonoType for the type from the Constant Table */
5594                         if (!type)
5595                                 type = g_new0 (MonoType, 1);
5596                         type->type = types [i];
5597                         type->data.klass = NULL;
5598                         if (types [i] == MONO_TYPE_CLASS)
5599                                 type->data.klass = mono_defaults.object_class;
5600                         else    
5601                                 type->data.klass = mono_class_from_mono_type (type);
5602                         
5603                         param->DefaultValueImpl = mono_get_object_from_blob (domain, type, blobs [i]);
5604
5605                         /* Type in the Constant table is MONO_TYPE_CLASS for nulls */
5606                         if (types [i] != MONO_TYPE_CLASS && !param->DefaultValueImpl) 
5607                                 param->DefaultValueImpl = dbnull;
5608                         
5609                 }
5610
5611                 if (mspecs [i + 1])
5612                         param->MarshalAsImpl = (MonoObject*)mono_reflection_marshal_from_marshal_spec (domain, method->klass, mspecs [i + 1]);
5613                 
5614                 mono_array_set (res, gpointer, i, param);
5615         }
5616         g_free (names);
5617         g_free (blobs);
5618         g_free (types);
5619         g_free (type);
5620
5621         for (i = mono_method_signature (method)->param_count; i >= 0; i--)
5622                 if (mspecs [i])
5623                         mono_metadata_free_marshal_spec (mspecs [i]);
5624         g_free (mspecs);
5625         
5626         CACHE_OBJECT (&(method->signature), res, NULL);
5627         return res;
5628 }
5629
5630 /*
5631  * mono_method_body_get_object:
5632  * @domain: an app domain
5633  * @method: a method
5634  *
5635  * Return an System.Reflection.MethodBody object representing the method @method.
5636  */
5637 MonoReflectionMethodBody*
5638 mono_method_body_get_object (MonoDomain *domain, MonoMethod *method)
5639 {
5640         static MonoClass *System_Reflection_MethodBody = NULL;
5641         static MonoClass *System_Reflection_LocalVariableInfo = NULL;
5642         static MonoClass *System_Reflection_ExceptionHandlingClause = NULL;
5643         MonoReflectionMethodBody *ret;
5644         MonoMethodNormal *mn;
5645         MonoMethodHeader *header;
5646         guint32 method_rva, local_var_sig_token;
5647     char *ptr;
5648         unsigned char format, flags;
5649         int i;
5650
5651         if (!System_Reflection_MethodBody)
5652                 System_Reflection_MethodBody = mono_class_from_name (mono_defaults.corlib, "System.Reflection", "MethodBody");
5653         if (!System_Reflection_LocalVariableInfo)
5654                 System_Reflection_LocalVariableInfo = mono_class_from_name (mono_defaults.corlib, "System.Reflection", "LocalVariableInfo");
5655         if (!System_Reflection_ExceptionHandlingClause)
5656                 System_Reflection_ExceptionHandlingClause = mono_class_from_name (mono_defaults.corlib, "System.Reflection", "ExceptionHandlingClause");
5657
5658         CHECK_OBJECT (MonoReflectionMethodBody *, method, NULL);
5659
5660         if ((method->flags & METHOD_ATTRIBUTE_PINVOKE_IMPL) ||
5661                 (method->flags & METHOD_ATTRIBUTE_ABSTRACT) ||
5662             (method->iflags & METHOD_IMPL_ATTRIBUTE_INTERNAL_CALL) ||
5663             (method->iflags & METHOD_IMPL_ATTRIBUTE_RUNTIME))
5664                 return NULL;
5665         mn = (MonoMethodNormal *)method;
5666         header = mono_method_get_header (method);
5667         
5668         /* Obtain local vars signature token */
5669         method_rva = mono_metadata_decode_row_col (&method->klass->image->tables [MONO_TABLE_METHOD], mono_metadata_token_index (method->token) - 1, MONO_METHOD_RVA);
5670         ptr = mono_image_rva_map (method->klass->image, method_rva);
5671         flags = *(const unsigned char *) ptr;
5672         format = flags & METHOD_HEADER_FORMAT_MASK;
5673         switch (format){
5674         case METHOD_HEADER_TINY_FORMAT:
5675         case METHOD_HEADER_TINY_FORMAT1:
5676                 local_var_sig_token = 0;
5677                 break;
5678         case METHOD_HEADER_FAT_FORMAT:
5679                 ptr += 2;
5680                 ptr += 2;
5681                 ptr += 4;
5682                 local_var_sig_token = read32 (ptr);
5683                 break;
5684         default:
5685                 g_assert_not_reached ();
5686         }
5687
5688         ret = (MonoReflectionMethodBody*)mono_object_new (domain, System_Reflection_MethodBody);
5689
5690         ret->init_locals = header->init_locals;
5691         ret->max_stack = header->max_stack;
5692         ret->local_var_sig_token = local_var_sig_token;
5693         ret->il = mono_array_new (domain, mono_defaults.byte_class, header->code_size);
5694         memcpy (mono_array_addr (ret->il, guint8*, 0), header->code, header->code_size);
5695
5696         /* Locals */
5697         ret->locals = mono_array_new (domain, System_Reflection_LocalVariableInfo, header->num_locals);
5698         for (i = 0; i < header->num_locals; ++i) {
5699                 MonoReflectionLocalVariableInfo *info = (MonoReflectionLocalVariableInfo*)mono_object_new (domain, System_Reflection_LocalVariableInfo);
5700                 info->local_type = mono_type_get_object (domain, header->locals [i]);
5701                 info->is_pinned = header->locals [i]->pinned;
5702                 info->local_index = i;
5703                 mono_array_set (ret->locals, MonoReflectionLocalVariableInfo*, i, info);
5704         }
5705
5706         /* Exceptions */
5707         ret->clauses = mono_array_new (domain, System_Reflection_ExceptionHandlingClause, header->num_clauses);
5708         for (i = 0; i < header->num_clauses; ++i) {
5709                 MonoReflectionExceptionHandlingClause *info = (MonoReflectionExceptionHandlingClause*)mono_object_new (domain, System_Reflection_ExceptionHandlingClause);
5710                 MonoExceptionClause *clause = &header->clauses [i];
5711
5712                 info->flags = clause->flags;
5713                 info->try_offset = clause->try_offset;
5714                 info->try_length = clause->try_len;
5715                 info->handler_offset = clause->handler_offset;
5716                 info->handler_length = clause->handler_len;
5717                 if (clause->flags == MONO_EXCEPTION_CLAUSE_FILTER)
5718                         info->filter_offset = clause->data.filter_offset;
5719                 else if (clause->data.catch_class)
5720                         info->catch_type = mono_type_get_object (mono_domain_get (), &clause->data.catch_class->byval_arg);
5721
5722                 mono_array_set (ret->clauses, MonoReflectionExceptionHandlingClause*, i, info);
5723         }
5724
5725         CACHE_OBJECT (method, ret, NULL);
5726         return ret;
5727 }
5728
5729 MonoObject *
5730 mono_get_dbnull_object (MonoDomain *domain)
5731 {
5732         MonoObject *obj;
5733         MonoClass *klass;
5734         static MonoClassField *dbnull_value_field = NULL;
5735         
5736         if (!dbnull_value_field) {
5737                 klass = mono_class_from_name (mono_defaults.corlib, "System", "DBNull");
5738                 mono_class_init (klass);
5739                 dbnull_value_field = mono_class_get_field_from_name (klass, "Value");
5740                 g_assert (dbnull_value_field);
5741         }
5742         obj = mono_field_get_value_object (domain, dbnull_value_field, NULL); 
5743         g_assert (obj);
5744         return obj;
5745 }
5746
5747
5748 static void
5749 get_default_param_value_blobs (MonoMethod *method, char **blobs, guint32 *types)
5750 {
5751         guint32 param_index, i, lastp, crow = 0;
5752         guint32 param_cols [MONO_PARAM_SIZE], const_cols [MONO_CONSTANT_SIZE];
5753         gint32 idx;
5754
5755         MonoClass *klass = method->klass;
5756         MonoImage *image = klass->image;
5757         MonoMethodSignature *methodsig = mono_method_signature (method);
5758
5759         MonoTableInfo *constt;
5760         MonoTableInfo *methodt;
5761         MonoTableInfo *paramt;
5762
5763         if (!methodsig->param_count)
5764                 return;
5765
5766         if (klass->generic_class) {
5767                 return; /* FIXME - ??? */
5768         }
5769
5770         mono_class_init (klass);
5771
5772         if (klass->image->dynamic) {
5773                 MonoReflectionMethodAux *aux = g_hash_table_lookup (((MonoDynamicImage*)method->klass->image)->method_aux_hash, method);
5774                 if (aux && aux->param_defaults) {
5775                         memcpy (blobs, &(aux->param_defaults [1]), methodsig->param_count * sizeof (char*));
5776                         memcpy (types, &(aux->param_default_types [1]), methodsig->param_count * sizeof (guint32));
5777                 }
5778                 return;
5779         }
5780
5781         methodt = &klass->image->tables [MONO_TABLE_METHOD];
5782         paramt = &klass->image->tables [MONO_TABLE_PARAM];
5783         constt = &image->tables [MONO_TABLE_CONSTANT];
5784
5785         idx = mono_method_get_index (method) - 1;
5786         g_assert (idx != -1);
5787
5788         param_index = mono_metadata_decode_row_col (methodt, idx, MONO_METHOD_PARAMLIST);
5789         if (idx + 1 < methodt->rows)
5790                 lastp = mono_metadata_decode_row_col (methodt, idx + 1, MONO_METHOD_PARAMLIST);
5791         else
5792                 lastp = paramt->rows + 1;
5793
5794         for (i = param_index; i < lastp; ++i) {
5795                 guint32 paramseq;
5796
5797                 mono_metadata_decode_row (paramt, i - 1, param_cols, MONO_PARAM_SIZE);
5798                 paramseq = param_cols [MONO_PARAM_SEQUENCE];
5799
5800                 if (!param_cols [MONO_PARAM_FLAGS] & PARAM_ATTRIBUTE_HAS_DEFAULT) 
5801                         continue;
5802
5803                 crow = mono_metadata_get_constant_index (image, MONO_TOKEN_PARAM_DEF | i, crow + 1);
5804                 if (!crow) {
5805                         continue;
5806                 }
5807         
5808                 mono_metadata_decode_row (constt, crow - 1, const_cols, MONO_CONSTANT_SIZE);
5809                 blobs [paramseq - 1] = (gpointer) mono_metadata_blob_heap (image, const_cols [MONO_CONSTANT_VALUE]);
5810                 types [paramseq - 1] = const_cols [MONO_CONSTANT_TYPE];
5811         }
5812
5813         return;
5814 }
5815
5816 static MonoObject *
5817 mono_get_object_from_blob (MonoDomain *domain, MonoType *type, const char *blob)
5818 {
5819         void *retval;
5820         MonoClass *klass;
5821         MonoObject *object;
5822         MonoType *basetype = type;
5823
5824         if (!blob)
5825                 return NULL;
5826         
5827         klass = mono_class_from_mono_type (type);
5828         if (klass->valuetype) {
5829                 object = mono_object_new (domain, klass);
5830                 retval = ((gchar *) object + sizeof (MonoObject));
5831                 if (klass->enumtype)
5832                         basetype = klass->enum_basetype;
5833         } else {
5834                 retval = &object;
5835         }
5836                         
5837         if (!mono_get_constant_value_from_blob (domain, basetype->type,  blob, retval))
5838                 return object;
5839         else
5840                 return NULL;
5841 }
5842
5843 static int
5844 assembly_name_to_aname (MonoAssemblyName *assembly, char *p) {
5845         int found_sep;
5846         char *s;
5847
5848         memset (assembly, 0, sizeof (MonoAssemblyName));
5849         assembly->name = p;
5850         assembly->culture = "";
5851         memset (assembly->public_key_token, 0, MONO_PUBLIC_KEY_TOKEN_LENGTH);
5852
5853         while (*p && (isalnum (*p) || *p == '.' || *p == '-' || *p == '_' || *p == '$' || *p == '@'))
5854                 p++;
5855         found_sep = 0;
5856         while (g_ascii_isspace (*p) || *p == ',') {
5857                 *p++ = 0;
5858                 found_sep = 1;
5859                 continue;
5860         }
5861         /* failed */
5862         if (!found_sep)
5863                 return 1;
5864         while (*p) {
5865                 if (*p == 'V' && g_ascii_strncasecmp (p, "Version=", 8) == 0) {
5866                         p += 8;
5867                         assembly->major = strtoul (p, &s, 10);
5868                         if (s == p || *s != '.')
5869                                 return 1;
5870                         p = ++s;
5871                         assembly->minor = strtoul (p, &s, 10);
5872                         if (s == p || *s != '.')
5873                                 return 1;
5874                         p = ++s;
5875                         assembly->build = strtoul (p, &s, 10);
5876                         if (s == p || *s != '.')
5877                                 return 1;
5878                         p = ++s;
5879                         assembly->revision = strtoul (p, &s, 10);
5880                         if (s == p)
5881                                 return 1;
5882                         p = s;
5883                 } else if (*p == 'C' && g_ascii_strncasecmp (p, "Culture=", 8) == 0) {
5884                         p += 8;
5885                         if (g_ascii_strncasecmp (p, "neutral", 7) == 0) {
5886                                 assembly->culture = "";
5887                                 p += 7;
5888                         } else {
5889                                 assembly->culture = p;
5890                                 while (*p && *p != ',') {
5891                                         p++;
5892                                 }
5893                         }
5894                 } else if (*p == 'P' && g_ascii_strncasecmp (p, "PublicKeyToken=", 15) == 0) {
5895                         p += 15;
5896                         if (strncmp (p, "null", 4) == 0) {
5897                                 p += 4;
5898                         } else {
5899                                 int len;
5900                                 gchar *start = p;
5901                                 while (*p && *p != ',') {
5902                                         p++;
5903                                 }
5904                                 len = (p - start + 1);
5905                                 if (len > MONO_PUBLIC_KEY_TOKEN_LENGTH)
5906                                         len = MONO_PUBLIC_KEY_TOKEN_LENGTH;
5907                                 g_strlcpy (assembly->public_key_token, start, len);
5908                         }
5909                 } else {
5910                         while (*p && *p != ',')
5911                                 p++;
5912                 }
5913                 found_sep = 0;
5914                 while (g_ascii_isspace (*p) || *p == ',') {
5915                         *p++ = 0;
5916                         found_sep = 1;
5917                         continue;
5918                 }
5919                 /* failed */
5920                 if (!found_sep)
5921                         return 1;
5922         }
5923
5924         return 0;
5925 }
5926
5927 /*
5928  * mono_reflection_parse_type:
5929  * @name: type name
5930  *
5931  * Parse a type name as accepted by the GetType () method and output the info
5932  * extracted in the info structure.
5933  * the name param will be mangled, so, make a copy before passing it to this function.
5934  * The fields in info will be valid until the memory pointed to by name is valid.
5935  *
5936  * See also mono_type_get_name () below.
5937  *
5938  * Returns: 0 on parse error.
5939  */
5940 static int
5941 _mono_reflection_parse_type (char *name, char **endptr, gboolean is_recursed,
5942                              MonoTypeNameParse *info)
5943 {
5944         char *start, *p, *w, *temp, *last_point, *startn;
5945         int in_modifiers = 0;
5946         int isbyref = 0, rank, arity = 0, i;
5947
5948         start = p = w = name;
5949
5950         memset (&info->assembly, 0, sizeof (MonoAssemblyName));
5951         info->name = info->name_space = NULL;
5952         info->nested = NULL;
5953         info->modifiers = NULL;
5954         info->type_arguments = NULL;
5955
5956         /* last_point separates the namespace from the name */
5957         last_point = NULL;
5958
5959         while (*p) {
5960                 switch (*p) {
5961                 case '+':
5962                         *p = 0; /* NULL terminate the name */
5963                         startn = p + 1;
5964                         info->nested = g_list_append (info->nested, startn);
5965                         /* we have parsed the nesting namespace + name */
5966                         if (info->name)
5967                                 break;
5968                         if (last_point) {
5969                                 info->name_space = start;
5970                                 *last_point = 0;
5971                                 info->name = last_point + 1;
5972                         } else {
5973                                 info->name_space = (char *)"";
5974                                 info->name = start;
5975                         }
5976                         break;
5977                 case '.':
5978                         last_point = p;
5979                         break;
5980                 case '\\':
5981                         ++p;
5982                         break;
5983                 case '&':
5984                 case '*':
5985                 case '[':
5986                 case ',':
5987                 case ']':
5988                         in_modifiers = 1;
5989                         break;
5990                 case '`':
5991                         ++p;
5992                         i = strtol (p, &temp, 10);
5993                         arity += i;
5994                         if (p == temp)
5995                                 return 0;
5996                         p = temp-1;
5997                         break;
5998                 default:
5999                         break;
6000                 }
6001                 if (in_modifiers)
6002                         break;
6003                 // *w++ = *p++;
6004                 p++;
6005         }
6006         
6007         if (!info->name) {
6008                 if (last_point) {
6009                         info->name_space = start;
6010                         *last_point = 0;
6011                         info->name = last_point + 1;
6012                 } else {
6013                         info->name_space = (char *)"";
6014                         info->name = start;
6015                 }
6016         }
6017         while (*p) {
6018                 switch (*p) {
6019                 case '&':
6020                         if (isbyref) /* only one level allowed by the spec */
6021                                 return 0;
6022                         isbyref = 1;
6023                         info->modifiers = g_list_append (info->modifiers, GUINT_TO_POINTER (0));
6024                         *p++ = 0;
6025                         break;
6026                 case '*':
6027                         info->modifiers = g_list_append (info->modifiers, GUINT_TO_POINTER (-1));
6028                         *p++ = 0;
6029                         break;
6030                 case '[':
6031                         if (arity != 0) {
6032                                 *p++ = 0;
6033                                 info->type_arguments = g_ptr_array_new ();
6034                                 for (i = 0; i < arity; i++) {
6035                                         MonoTypeNameParse *subinfo = g_new0 (MonoTypeNameParse, 1);
6036                                         gboolean fqname = FALSE;
6037
6038                                         g_ptr_array_add (info->type_arguments, subinfo);
6039
6040                                         if (*p == '[') {
6041                                                 p++;
6042                                                 fqname = TRUE;
6043                                         }
6044
6045                                         if (!_mono_reflection_parse_type (p, &p, TRUE, subinfo))
6046                                                 return 0;
6047
6048                                         if (fqname) {
6049                                                 char *aname;
6050
6051                                                 if (*p != ',')
6052                                                         return 0;
6053                                                 *p++ = 0;
6054
6055                                                 aname = p;
6056                                                 while (*p && (*p != ']'))
6057                                                         p++;
6058
6059                                                 if (*p != ']')
6060                                                         return 0;
6061
6062                                                 *p++ = 0;
6063                                                 while (*aname) {
6064                                                         if (g_ascii_isspace (*aname)) {
6065                                                                 ++aname;
6066                                                                 continue;
6067                                                         }
6068                                                         break;
6069                                                 }
6070                                                 if (!*aname ||
6071                                                     !assembly_name_to_aname (&subinfo->assembly, aname))
6072                                                         return 0;
6073                                         }
6074
6075                                         if (i + 1 < arity) {
6076                                                 if (*p != ',')
6077                                                         return 0;
6078                                         } else {
6079                                                 if (*p != ']')
6080                                                         return 0;
6081                                         }
6082                                         *p++ = 0;
6083                                 }
6084
6085                                 arity = 0;
6086                                 break;
6087                         }
6088                         rank = 1;
6089                         *p++ = 0;
6090                         while (*p) {
6091                                 if (*p == ']')
6092                                         break;
6093                                 if (*p == ',')
6094                                         rank++;
6095                                 else if (*p != '*') /* '*' means unknown lower bound */
6096                                         return 0;
6097                                 ++p;
6098                         }
6099                         if (*p++ != ']')
6100                                 return 0;
6101                         info->modifiers = g_list_append (info->modifiers, GUINT_TO_POINTER (rank));
6102                         break;
6103                 case ']':
6104                         if (is_recursed)
6105                                 goto end;
6106                         return 0;
6107                 case ',':
6108                         if (is_recursed)
6109                                 goto end;
6110                         *p++ = 0;
6111                         while (*p) {
6112                                 if (g_ascii_isspace (*p)) {
6113                                         ++p;
6114                                         continue;
6115                                 }
6116                                 break;
6117                         }
6118                         if (!*p)
6119                                 return 0; /* missing assembly name */
6120                         if (!assembly_name_to_aname (&info->assembly, p))
6121                                 return 0;
6122                         break;
6123                 default:
6124                         return 0;
6125                 }
6126                 if (info->assembly.name)
6127                         break;
6128         }
6129         // *w = 0; /* terminate class name */
6130  end:
6131         if (!info->name || !*info->name)
6132                 return 0;
6133         if (endptr)
6134                 *endptr = p;
6135         /* add other consistency checks */
6136         return 1;
6137 }
6138
6139 int
6140 mono_reflection_parse_type (char *name, MonoTypeNameParse *info)
6141 {
6142         return _mono_reflection_parse_type (name, NULL, FALSE, info);
6143 }
6144
6145 static MonoType*
6146 _mono_reflection_get_type_from_info (MonoTypeNameParse *info, MonoImage *image, gboolean ignorecase)
6147 {
6148         gboolean type_resolve = FALSE;
6149         MonoType *type;
6150
6151         if (info->assembly.name) {
6152                 MonoAssembly *assembly = mono_assembly_loaded (&info->assembly);
6153                 if (!assembly) {
6154                         /* then we must load the assembly ourselve - see #60439 */
6155                         assembly = mono_assembly_load (&info->assembly, NULL, NULL);
6156                         if (!assembly)
6157                                 return NULL;
6158                 }
6159                 image = assembly->image;
6160         } else if (!image) {
6161                 image = mono_defaults.corlib;
6162         }
6163
6164         type = mono_reflection_get_type (image, info, ignorecase, &type_resolve);
6165         if (type == NULL && !info->assembly.name && image != mono_defaults.corlib) {
6166                 image = mono_defaults.corlib;
6167                 type = mono_reflection_get_type (image, info, ignorecase, &type_resolve);
6168         }
6169
6170         return type;
6171 }
6172
6173 static MonoType*
6174 mono_reflection_get_type_internal (MonoImage* image, MonoTypeNameParse *info, gboolean ignorecase)
6175 {
6176         MonoClass *klass;
6177         GList *mod;
6178         int modval;
6179         
6180         if (!image)
6181                 image = mono_defaults.corlib;
6182
6183         if (ignorecase)
6184                 klass = mono_class_from_name_case (image, info->name_space, info->name);
6185         else
6186                 klass = mono_class_from_name (image, info->name_space, info->name);
6187         if (!klass)
6188                 return NULL;
6189         for (mod = info->nested; mod; mod = mod->next) {
6190                 GList *nested;
6191
6192                 mono_class_init (klass);
6193                 nested = klass->nested_classes;
6194                 klass = NULL;
6195                 while (nested) {
6196                         klass = nested->data;
6197                         if (ignorecase) {
6198                                 if (g_strcasecmp (klass->name, mod->data) == 0)
6199                                         break;
6200                         } else {
6201                                 if (strcmp (klass->name, mod->data) == 0)
6202                                         break;
6203                         }
6204                         klass = NULL;
6205                         nested = nested->next;
6206                 }
6207                 if (!klass)
6208                         break;
6209         }
6210         if (!klass)
6211                 return NULL;
6212         mono_class_init (klass);
6213
6214         if (info->type_arguments) {
6215                 MonoType **type_args = g_new0 (MonoType *, info->type_arguments->len);
6216                 MonoReflectionType *the_type;
6217                 MonoType *instance;
6218                 int i;
6219
6220                 for (i = 0; i < info->type_arguments->len; i++) {
6221                         MonoTypeNameParse *subinfo = g_ptr_array_index (info->type_arguments, i);
6222
6223                         type_args [i] = _mono_reflection_get_type_from_info (subinfo, image, ignorecase);
6224                         if (!type_args [i]) {
6225                                 g_free (type_args);
6226                                 return NULL;
6227                         }
6228                 }
6229
6230                 the_type = mono_type_get_object (mono_domain_get (), &klass->byval_arg);
6231
6232                 instance = mono_reflection_bind_generic_parameters (
6233                         the_type, info->type_arguments->len, type_args);
6234
6235                 if (!instance) {
6236                         g_free (type_args);
6237                         return NULL;
6238                 }
6239
6240                 klass = mono_class_from_mono_type (instance);
6241         }
6242
6243         for (mod = info->modifiers; mod; mod = mod->next) {
6244                 modval = GPOINTER_TO_UINT (mod->data);
6245                 if (!modval) { /* byref: must be last modifier */
6246                         return &klass->this_arg;
6247                 } else if (modval == -1) {
6248                         klass = mono_ptr_class_get (&klass->byval_arg);
6249                 } else { /* array rank */
6250                         klass = mono_array_class_get (klass, modval);
6251                 }
6252                 mono_class_init (klass);
6253         }
6254
6255         return &klass->byval_arg;
6256 }
6257
6258 /*
6259  * mono_reflection_get_type:
6260  * @image: a metadata context
6261  * @info: type description structure
6262  * @ignorecase: flag for case-insensitive string compares
6263  * @type_resolve: whenever type resolve was already tried
6264  *
6265  * Build a MonoType from the type description in @info.
6266  * 
6267  */
6268
6269 MonoType*
6270 mono_reflection_get_type (MonoImage* image, MonoTypeNameParse *info, gboolean ignorecase, gboolean *type_resolve)
6271 {
6272         MonoType *type;
6273         MonoReflectionAssembly *assembly;
6274         GString *fullName;
6275         GList *mod;
6276
6277         type = mono_reflection_get_type_internal (image, info, ignorecase);
6278         if (type)
6279                 return type;
6280         if (!mono_domain_has_type_resolve (mono_domain_get ()))
6281                 return NULL;
6282
6283         if (type_resolve) {
6284                 if (*type_resolve) 
6285                         return NULL;
6286                 else
6287                         *type_resolve = TRUE;
6288         }
6289         
6290         /* Reconstruct the type name */
6291         fullName = g_string_new ("");
6292         if (info->name_space && (info->name_space [0] != '\0'))
6293                 g_string_printf (fullName, "%s.%s", info->name_space, info->name);
6294         else
6295                 g_string_printf (fullName, info->name);
6296         for (mod = info->nested; mod; mod = mod->next)
6297                 g_string_append_printf (fullName, "+%s", (char*)mod->data);
6298
6299         assembly = mono_domain_try_type_resolve ( mono_domain_get (), fullName->str, NULL);
6300         if (assembly) {
6301                 if (assembly->assembly->dynamic) {
6302                         /* Enumerate all modules */
6303                         MonoReflectionAssemblyBuilder *abuilder = (MonoReflectionAssemblyBuilder*)assembly;
6304                         int i;
6305
6306                         type = NULL;
6307                         if (abuilder->modules) {
6308                                 for (i = 0; i < mono_array_length (abuilder->modules); ++i) {
6309                                         MonoReflectionModuleBuilder *mb = mono_array_get (abuilder->modules, MonoReflectionModuleBuilder*, i);
6310                                         type = mono_reflection_get_type_internal (&mb->dynamic_image->image, info, ignorecase);
6311                                         if (type)
6312                                                 break;
6313                                 }
6314                         }
6315
6316                         if (!type && abuilder->loaded_modules) {
6317                                 for (i = 0; i < mono_array_length (abuilder->loaded_modules); ++i) {
6318                                         MonoReflectionModule *mod = mono_array_get (abuilder->loaded_modules, MonoReflectionModule*, i);
6319                                         type = mono_reflection_get_type_internal (mod->image, info, ignorecase);
6320                                         if (type)
6321                                                 break;
6322                                 }
6323                         }
6324                 }
6325                 else
6326                         type = mono_reflection_get_type_internal (assembly->assembly->image, 
6327                                                                                                           info, ignorecase);
6328         }
6329         g_string_free (fullName, TRUE);
6330         return type;
6331 }
6332
6333 static void
6334 free_type_info (MonoTypeNameParse *info)
6335 {
6336         g_list_free (info->modifiers);
6337         g_list_free (info->nested);
6338
6339         if (info->type_arguments) {
6340                 int i;
6341
6342                 for (i = 0; i < info->type_arguments->len; i++) {
6343                         MonoTypeNameParse *subinfo = g_ptr_array_index (info->type_arguments, i);
6344
6345                         free_type_info (subinfo);
6346                 }
6347
6348                 g_ptr_array_free (info->type_arguments, TRUE);
6349         }
6350 }
6351
6352 /*
6353  * mono_reflection_type_from_name:
6354  * @name: type name.
6355  * @image: a metadata context (can be NULL).
6356  *
6357  * Retrieves a MonoType from its @name. If the name is not fully qualified,
6358  * it defaults to get the type from @image or, if @image is NULL or loading
6359  * from it fails, uses corlib.
6360  * 
6361  */
6362 MonoType*
6363 mono_reflection_type_from_name (char *name, MonoImage *image)
6364 {
6365         MonoType *type = NULL;
6366         MonoTypeNameParse info;
6367         char *tmp;
6368
6369         /* Make a copy since parse_type modifies its argument */
6370         tmp = g_strdup (name);
6371         
6372         /*g_print ("requested type %s\n", str);*/
6373         if (mono_reflection_parse_type (tmp, &info)) {
6374                 type = _mono_reflection_get_type_from_info (&info, image, FALSE);
6375         }
6376
6377         g_free (tmp);
6378         free_type_info (&info);
6379         return type;
6380 }
6381
6382 /*
6383  * mono_reflection_get_token:
6384  *
6385  *   Return the metadata token of OBJ which should be an object
6386  * representing a metadata element.
6387  */
6388 guint32
6389 mono_reflection_get_token (MonoObject *obj)
6390 {
6391         MonoClass *klass;
6392         guint32 token = 0;
6393
6394         klass = obj->vtable->klass;
6395
6396         if (strcmp (klass->name, "MethodBuilder") == 0) {
6397                 MonoReflectionMethodBuilder *mb = (MonoReflectionMethodBuilder *)obj;
6398
6399                 token = mb->table_idx | MONO_TOKEN_METHOD_DEF;
6400         } else if (strcmp (klass->name, "ConstructorBuilder") == 0) {
6401                 MonoReflectionCtorBuilder *mb = (MonoReflectionCtorBuilder *)obj;
6402
6403                 token = mb->table_idx | MONO_TOKEN_METHOD_DEF;
6404         } else if (strcmp (klass->name, "FieldBuilder") == 0) {
6405                 MonoReflectionFieldBuilder *fb = (MonoReflectionFieldBuilder *)obj;
6406                 MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder *)fb->typeb;
6407                 if (tb->generic_params) {
6408                         g_assert_not_reached ();
6409                 } else {
6410                         token = fb->table_idx | MONO_TOKEN_FIELD_DEF;
6411                 }
6412         } else if (strcmp (klass->name, "TypeBuilder") == 0) {
6413                 MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder *)obj;
6414                 token = tb->table_idx | MONO_TOKEN_TYPE_DEF;
6415         } else if (strcmp (klass->name, "MonoType") == 0) {
6416                 MonoReflectionType *tb = (MonoReflectionType *)obj;
6417                 token = mono_class_from_mono_type (tb->type)->type_token;
6418         } else if (strcmp (klass->name, "MonoCMethod") == 0 ||
6419                         strcmp (klass->name, "MonoMethod") == 0) {
6420                 MonoReflectionMethod *m = (MonoReflectionMethod *)obj;
6421                 if (m->method->is_inflated) {
6422                         g_assert_not_reached ();
6423                 } else if (mono_method_signature (m->method)->generic_param_count) {
6424                         g_assert_not_reached ();
6425                 } else if (m->method->klass->generic_class) {
6426                         g_assert_not_reached ();
6427                 } else {
6428                         token = m->method->token;
6429                 }
6430         } else if (strcmp (klass->name, "MonoField") == 0) {
6431                 MonoReflectionField *f = (MonoReflectionField*)obj;
6432
6433                 token = mono_class_get_field_token (f->field);
6434         } else if (strcmp (klass->name, "MonoProperty") == 0) {
6435                 MonoReflectionProperty *p = (MonoReflectionProperty*)obj;
6436
6437                 token = mono_class_get_property_token (p->property);
6438         } else if (strcmp (klass->name, "MonoEvent") == 0) {
6439                 MonoReflectionEvent *p = (MonoReflectionEvent*)obj;
6440
6441                 token = mono_class_get_event_token (p->event);
6442         } else if (strcmp (klass->name, "ParameterInfo") == 0) {
6443                 MonoReflectionParameter *p = (MonoReflectionParameter*)obj;
6444
6445                 token = mono_method_get_param_token (((MonoReflectionMethod*)p->MemberImpl)->method, p->PositionImpl);
6446         } else if (strcmp (klass->name, "Module") == 0) {
6447                 MonoReflectionModule *m = (MonoReflectionModule*)obj;
6448
6449                 token = m->token;
6450         } else if (strcmp (klass->name, "Assembly") == 0) {
6451                 token = mono_metadata_make_token (MONO_TABLE_ASSEMBLY, 1);
6452         } else {
6453                 gchar *msg = g_strdup_printf ("MetadataToken is not supported for type '%s.%s'", klass->name_space, klass->name);
6454                 MonoException *ex = mono_get_exception_not_implemented (msg);
6455                 g_free (msg);
6456                 mono_raise_exception (ex);
6457         }
6458
6459         return token;
6460 }
6461
6462 static void*
6463 load_cattr_value (MonoImage *image, MonoType *t, const char *p, const char **end)
6464 {
6465         int slen, type = t->type;
6466 handle_enum:
6467         switch (type) {
6468         case MONO_TYPE_U1:
6469         case MONO_TYPE_I1:
6470         case MONO_TYPE_BOOLEAN: {
6471                 MonoBoolean *bval = g_malloc (sizeof (MonoBoolean));
6472                 *bval = *p;
6473                 *end = p + 1;
6474                 return bval;
6475         }
6476         case MONO_TYPE_CHAR:
6477         case MONO_TYPE_U2:
6478         case MONO_TYPE_I2: {
6479                 guint16 *val = g_malloc (sizeof (guint16));
6480                 *val = read16 (p);
6481                 *end = p + 2;
6482                 return val;
6483         }
6484 #if SIZEOF_VOID_P == 4
6485         case MONO_TYPE_U:
6486         case MONO_TYPE_I:
6487 #endif
6488         case MONO_TYPE_R4:
6489         case MONO_TYPE_U4:
6490         case MONO_TYPE_I4: {
6491                 guint32 *val = g_malloc (sizeof (guint32));
6492                 *val = read32 (p);
6493                 *end = p + 4;
6494                 return val;
6495         }
6496 #if SIZEOF_VOID_P == 8
6497         case MONO_TYPE_U: /* error out instead? this should probably not happen */
6498         case MONO_TYPE_I:
6499 #endif
6500         case MONO_TYPE_R8:
6501         case MONO_TYPE_U8:
6502         case MONO_TYPE_I8: {
6503                 guint64 *val = g_malloc (sizeof (guint64));
6504                 *val = read64 (p);
6505                 *end = p + 8;
6506                 return val;
6507         }
6508         case MONO_TYPE_VALUETYPE:
6509                 if (t->data.klass->enumtype) {
6510                         type = t->data.klass->enum_basetype->type;
6511                         goto handle_enum;
6512                 } else {
6513                         g_error ("generic valutype %s not handled in custom attr value decoding", t->data.klass->name);
6514                 }
6515                 break;
6516         case MONO_TYPE_STRING:
6517                 if (*p == (char)0xFF) {
6518                         *end = p + 1;
6519                         return NULL;
6520                 }
6521                 slen = mono_metadata_decode_value (p, &p);
6522                 *end = p + slen;
6523                 return mono_string_new_len (mono_domain_get (), p, slen);
6524         case MONO_TYPE_CLASS: {
6525                 char *n;
6526                 MonoType *t;
6527                 if (*p == (char)0xFF) {
6528                         *end = p + 1;
6529                         return NULL;
6530                 }
6531 handle_type:
6532                 slen = mono_metadata_decode_value (p, &p);
6533                 n = g_memdup (p, slen + 1);
6534                 n [slen] = 0;
6535                 t = mono_reflection_type_from_name (n, image);
6536                 if (!t)
6537                         g_warning ("Cannot load type '%s'", n);
6538                 g_free (n);
6539                 *end = p + slen;
6540                 if (t)
6541                         return mono_type_get_object (mono_domain_get (), t);
6542                 else
6543                         return NULL;
6544         }
6545         case MONO_TYPE_OBJECT: {
6546                 char subt = *p++;
6547                 MonoObject *obj;
6548                 MonoClass *subc = NULL;
6549                 void *val;
6550
6551                 if (subt == 0x50) {
6552                         goto handle_type;
6553                 } else if (subt == 0x0E) {
6554                         type = MONO_TYPE_STRING;
6555                         goto handle_enum;
6556                 } else if (subt == 0x55) {
6557                         char *n;
6558                         MonoType *t;
6559                         slen = mono_metadata_decode_value (p, &p);
6560                         n = g_memdup (p, slen + 1);
6561                         n [slen] = 0;
6562                         t = mono_reflection_type_from_name (n, image);
6563                         if (!t)
6564                                 g_warning ("Cannot load type '%s'", n);
6565                         g_free (n);
6566                         p += slen;
6567                         subc = mono_class_from_mono_type (t);
6568                 } else if (subt >= MONO_TYPE_BOOLEAN && subt <= MONO_TYPE_R8) {
6569                         MonoType simple_type = {{0}};
6570                         simple_type.type = subt;
6571                         subc = mono_class_from_mono_type (&simple_type);
6572                 } else {
6573                         g_error ("Unknown type 0x%02x for object type encoding in custom attr", subt);
6574                 }
6575                 val = load_cattr_value (image, &subc->byval_arg, p, end);
6576                 obj = mono_object_new (mono_domain_get (), subc);
6577                 memcpy ((char*)obj + sizeof (MonoObject), val, mono_class_value_size (subc, NULL));
6578                 g_free (val);
6579                 return obj;
6580         }
6581         case MONO_TYPE_SZARRAY: {
6582                 MonoArray *arr;
6583                 guint32 i, alen, basetype;
6584                 alen = read32 (p);
6585                 p += 4;
6586                 if (alen == 0xffffffff) {
6587                         *end = p;
6588                         return NULL;
6589                 }
6590                 arr = mono_array_new (mono_domain_get(), t->data.klass, alen);
6591                 basetype = t->data.klass->byval_arg.type;
6592                 switch (basetype)
6593                 {
6594                         case MONO_TYPE_U1:
6595                         case MONO_TYPE_I1:
6596                         case MONO_TYPE_BOOLEAN:
6597                                 for (i = 0; i < alen; i++) {
6598                                         MonoBoolean val = *p++;
6599                                         mono_array_set (arr, MonoBoolean, i, val);
6600                                 }
6601                                 break;
6602                         case MONO_TYPE_CHAR:
6603                         case MONO_TYPE_U2:
6604                         case MONO_TYPE_I2:
6605                                 for (i = 0; i < alen; i++) {
6606                                         guint16 val = read16 (p);
6607                                         mono_array_set (arr, guint16, i, val);
6608                                         p += 2;
6609                                 }
6610                                 break;
6611                         case MONO_TYPE_R4:
6612                         case MONO_TYPE_U4:
6613                         case MONO_TYPE_I4:
6614                                 for (i = 0; i < alen; i++) {
6615                                         guint32 val = read32 (p);
6616                                         mono_array_set (arr, guint32, i, val);
6617                                         p += 4;
6618                                 }
6619                                 break;
6620                         case MONO_TYPE_R8:
6621                         case MONO_TYPE_U8:
6622                         case MONO_TYPE_I8:
6623                                 for (i = 0; i < alen; i++) {
6624                                         guint64 val = read64 (p);
6625                                         mono_array_set (arr, guint64, i, val);
6626                                         p += 8;
6627                                 }
6628                                 break;
6629                         case MONO_TYPE_CLASS:
6630                         case MONO_TYPE_OBJECT:
6631                         case MONO_TYPE_STRING:
6632                                 for (i = 0; i < alen; i++) {
6633                                         MonoObject *item = load_cattr_value (image, &t->data.klass->byval_arg, p, &p);
6634                                         mono_array_set (arr, gpointer, i, item);
6635                                 }
6636                                 break;
6637                         default:
6638                                 g_error("Type 0x%02x not handled in custom attr array decoding",t->data.type->type);
6639                 }
6640                 *end=p;
6641                 return arr;
6642         }
6643         default:
6644                 g_error ("Type 0x%02x not handled in custom attr value decoding", type);
6645         }
6646         return NULL;
6647 }
6648
6649 static MonoObject*
6650 create_cattr_typed_arg (MonoType *t, MonoObject *val)
6651 {
6652         static MonoClass *klass;
6653         static MonoMethod *ctor;
6654         MonoObject *retval;
6655         void *params [2], *unboxed;
6656
6657         if (!klass)
6658                 klass = mono_class_from_name (mono_defaults.corlib, "System.Reflection", "CustomAttributeTypedArgument");
6659         if (!ctor)
6660                 ctor = mono_class_get_method_from_name (klass, ".ctor", 2);
6661         
6662         params [0] = mono_type_get_object (mono_domain_get (), t);
6663         params [1] = val;
6664         retval = mono_object_new (mono_domain_get (), klass);
6665         unboxed = mono_object_unbox (retval);
6666         mono_runtime_invoke (ctor, unboxed, params, NULL);
6667
6668         return retval;
6669 }
6670
6671 static MonoObject*
6672 create_cattr_named_arg (void *minfo, MonoObject *typedarg)
6673 {
6674         static MonoClass *klass;
6675         static MonoMethod *ctor;
6676         MonoObject *retval;
6677         void *unboxed, *params [2];
6678
6679         if (!klass)
6680                 klass = mono_class_from_name (mono_defaults.corlib, "System.Reflection", "CustomAttributeNamedArgument");
6681         if (!ctor)
6682                 ctor = mono_class_get_method_from_name (klass, ".ctor", 2);
6683
6684         params [0] = minfo;
6685         params [1] = typedarg;
6686         retval = mono_object_new (mono_domain_get (), klass);
6687         unboxed = mono_object_unbox (retval);
6688         mono_runtime_invoke (ctor, unboxed, params, NULL);
6689
6690         return retval;
6691 }
6692
6693 static gboolean
6694 type_is_reference (MonoType *type)
6695 {
6696         switch (type->type) {
6697         case MONO_TYPE_BOOLEAN:
6698         case MONO_TYPE_CHAR:
6699         case MONO_TYPE_U:
6700         case MONO_TYPE_I:
6701         case MONO_TYPE_U1:
6702         case MONO_TYPE_I1:
6703         case MONO_TYPE_U2:
6704         case MONO_TYPE_I2:
6705         case MONO_TYPE_U4:
6706         case MONO_TYPE_I4:
6707         case MONO_TYPE_U8:
6708         case MONO_TYPE_I8:
6709         case MONO_TYPE_R8:
6710         case MONO_TYPE_R4:
6711         case MONO_TYPE_VALUETYPE:
6712                 return FALSE;
6713         default:
6714                 return TRUE;
6715         }
6716 }
6717
6718 static void
6719 free_param_data (MonoMethodSignature *sig, void **params) {
6720         int i;
6721         for (i = 0; i < sig->param_count; ++i) {
6722                 if (!type_is_reference (sig->params [i]))
6723                         g_free (params [i]);
6724         }
6725 }
6726
6727 /*
6728  * Find the field index in the metadata FieldDef table.
6729  */
6730 static guint32
6731 find_field_index (MonoClass *klass, MonoClassField *field) {
6732         int i;
6733
6734         for (i = 0; i < klass->field.count; ++i) {
6735                 if (field == &klass->fields [i])
6736                         return klass->field.first + 1 + i;
6737         }
6738         return 0;
6739 }
6740
6741 /*
6742  * Find the property index in the metadata Property table.
6743  */
6744 static guint32
6745 find_property_index (MonoClass *klass, MonoProperty *property) {
6746         int i;
6747
6748         for (i = 0; i < klass->property.count; ++i) {
6749                 if (property == &klass->properties [i])
6750                         return klass->property.first + 1 + i;
6751         }
6752         return 0;
6753 }
6754
6755 /*
6756  * Find the event index in the metadata Event table.
6757  */
6758 static guint32
6759 find_event_index (MonoClass *klass, MonoEvent *event) {
6760         int i;
6761
6762         for (i = 0; i < klass->event.count; ++i) {
6763                 if (event == &klass->events [i])
6764                         return klass->event.first + 1 + i;
6765         }
6766         return 0;
6767 }
6768
6769 static MonoObject*
6770 create_custom_attr (MonoImage *image, MonoMethod *method, const char *data, guint32 len)
6771 {
6772         const char *p = data;
6773         const char *named;
6774         guint32 i, j, num_named;
6775         MonoObject *attr;
6776         void **params;
6777
6778         mono_class_init (method->klass);
6779
6780         if (len == 0) {
6781                 attr = mono_object_new (mono_domain_get (), method->klass);
6782                 mono_runtime_invoke (method, attr, NULL, NULL);
6783                 return attr;
6784         }
6785
6786         if (len < 2 || read16 (p) != 0x0001) /* Prolog */
6787                 return NULL;
6788
6789         /*g_print ("got attr %s\n", method->klass->name);*/
6790
6791         /* Allocate using alloca so it gets GC tracking */
6792         params = alloca (mono_method_signature (method)->param_count * sizeof (void*)); 
6793
6794         /* skip prolog */
6795         p += 2;
6796         for (i = 0; i < mono_method_signature (method)->param_count; ++i) {
6797                 params [i] = load_cattr_value (image, mono_method_signature (method)->params [i], p, &p);
6798         }
6799
6800         named = p;
6801         attr = mono_object_new (mono_domain_get (), method->klass);
6802         mono_runtime_invoke (method, attr, params, NULL);
6803         free_param_data (method->signature, params);
6804         num_named = read16 (named);
6805         named += 2;
6806         for (j = 0; j < num_named; j++) {
6807                 gint name_len;
6808                 gboolean is_boxed = FALSE;
6809                 char *name, named_type, data_type;
6810                 named_type = *named++;
6811                 data_type = *named++; /* type of data */
6812                 if (data_type == 0x51)
6813                         is_boxed = TRUE;
6814
6815                 if (data_type == 0x55) {
6816                         gint type_len;
6817                         char *type_name;
6818                         type_len = mono_metadata_decode_blob_size (named, &named);
6819                         type_name = g_malloc (type_len + 1);
6820                         memcpy (type_name, named, type_len);
6821                         type_name [type_len] = 0;
6822                         named += type_len;
6823                         /* FIXME: lookup the type and check type consistency */
6824                 } else if (data_type == MONO_TYPE_SZARRAY && (named_type == 0x54 || named_type == 0x53)) {
6825                         /* this seems to be the type of the element of the array */
6826                         /* g_print ("skipping 0x%02x after prop\n", *named); */
6827                         named++;
6828                 }
6829                 name_len = mono_metadata_decode_blob_size (named, &named);
6830                 name = g_malloc (name_len + 1);
6831                 memcpy (name, named, name_len);
6832                 name [name_len] = 0;
6833                 named += name_len;
6834                 if (named_type == 0x53) {
6835                         MonoClassField *field = mono_class_get_field_from_name (mono_object_class (attr), name);
6836                         void *val = load_cattr_value (image, field->type, named, &named);
6837                         mono_field_set_value (attr, field, val);
6838                         if (!type_is_reference (field->type))
6839                                 g_free (val);
6840                 } else if (named_type == 0x54) {
6841                         MonoProperty *prop;
6842                         void *pparams [1];
6843                         MonoType *prop_type;
6844
6845                         prop = mono_class_get_property_from_name (mono_object_class (attr), name);
6846                         /* can we have more that 1 arg in a custom attr named property? */
6847                         prop_type = prop->get? mono_method_signature (prop->get)->ret :
6848                              mono_method_signature (prop->set)->params [mono_method_signature (prop->set)->param_count - 1];
6849                         pparams [0] = load_cattr_value (image, prop_type, named, &named);
6850                         mono_property_set_value (prop, attr, pparams, NULL);
6851                         if (!type_is_reference (prop_type))
6852                                 g_free (pparams [0]);
6853                 }
6854                 g_free (name);
6855         }
6856
6857         return attr;
6858 }
6859
6860 static MonoObject*
6861 create_custom_attr_data (MonoImage *image, MonoMethod *method, const char *data, guint32 len)
6862 {
6863         MonoArray *typedargs, *namedargs;
6864         MonoClass *attrklass;
6865         static MonoClass *klass;
6866         static MonoMethod *ctor;
6867         MonoDomain *domain;
6868         MonoObject *attr;
6869         const char *p = data;
6870         const char *named;
6871         guint32 i, j, num_named;
6872         void *params [3];
6873
6874         mono_class_init (method->klass);
6875         
6876         if (!klass)
6877                 klass = mono_class_from_name (mono_defaults.corlib, "System.Reflection", "CustomAttributeData");
6878         if (!ctor)
6879                 ctor = mono_class_get_method_from_name (klass, ".ctor", 3);
6880         
6881         domain = mono_domain_get ();
6882         if (len == 0) {
6883                 /* This is for Attributes with no parameters */
6884                 attr = mono_object_new (domain, klass);
6885                 params [0] = mono_method_get_object (domain, method, NULL);
6886                 params [1] = params [2] = NULL;
6887                 mono_runtime_invoke (method, attr, params, NULL);
6888                 return attr;
6889         }
6890
6891         if (len < 2 || read16 (p) != 0x0001) /* Prolog */
6892                 return NULL;
6893
6894         typedargs = mono_array_new (domain, mono_get_object_class (), mono_method_signature (method)->param_count);
6895         
6896         /* skip prolog */
6897         p += 2;
6898         for (i = 0; i < mono_method_signature (method)->param_count; ++i) {
6899                 MonoObject *obj, *typedarg;
6900                 void *val;
6901
6902                 val = load_cattr_value (image, mono_method_signature (method)->params [i], p, &p);
6903                 obj = type_is_reference (mono_method_signature (method)->params [i]) ? 
6904                         val : mono_value_box (domain, mono_class_from_mono_type (mono_method_signature (method)->params [i]), val);
6905                 typedarg = create_cattr_typed_arg (mono_method_signature (method)->params [i], obj);
6906                 mono_array_set (typedargs, void*, i, typedarg);
6907
6908                 if (!type_is_reference (mono_method_signature (method)->params [i]))
6909                         g_free (val);
6910         }
6911
6912         named = p;
6913         num_named = read16 (named);
6914         namedargs = mono_array_new (domain, mono_get_object_class (), num_named);
6915         named += 2;
6916         attrklass = method->klass;
6917         for (j = 0; j < num_named; j++) {
6918                 gint name_len;
6919                 char *name, named_type, data_type;
6920                 named_type = *named++;
6921                 data_type = *named++; /* type of data */
6922                 if (data_type == 0x55) {
6923                         gint type_len;
6924                         char *type_name;
6925                         type_len = mono_metadata_decode_blob_size (named, &named);
6926                         type_name = g_malloc (type_len + 1);
6927                         memcpy (type_name, named, type_len);
6928                         type_name [type_len] = 0;
6929                         named += type_len;
6930                         /* FIXME: lookup the type and check type consistency */
6931                 } else if (data_type == MONO_TYPE_SZARRAY && (named_type == 0x54 || named_type == 0x53)) {
6932                         /* this seems to be the type of the element of the array */
6933                         /* g_print ("skipping 0x%02x after prop\n", *named); */
6934                         named++;
6935                 }
6936                 name_len = mono_metadata_decode_blob_size (named, &named);
6937                 name = g_malloc (name_len + 1);
6938                 memcpy (name, named, name_len);
6939                 name [name_len] = 0;
6940                 named += name_len;
6941                 if (named_type == 0x53) {
6942                         MonoObject *obj, *typedarg, *namedarg;
6943                         MonoClassField *field = mono_class_get_field_from_name (attrklass, name);
6944                         void *minfo, *val = load_cattr_value (image, field->type, named, &named);
6945                         
6946                         minfo = mono_field_get_object (domain, NULL, field);
6947                         obj = type_is_reference (field->type) ? val : mono_value_box (domain, mono_class_from_mono_type (field->type), val);
6948                         typedarg = create_cattr_typed_arg (field->type, obj);
6949                         namedarg = create_cattr_named_arg (minfo, typedarg);
6950                         mono_array_set (namedargs, void*, j, namedarg);
6951                         if (!type_is_reference (field->type))
6952                                 g_free (val);
6953                 } else if (named_type == 0x54) {
6954                         MonoObject *obj, *typedarg, *namedarg;
6955                         MonoType *prop_type;
6956                         void *val, *minfo;
6957                         MonoProperty *prop = mono_class_get_property_from_name (attrklass, name);
6958
6959                         prop_type = prop->get? mono_method_signature (prop->get)->ret :
6960                              mono_method_signature (prop->set)->params [mono_method_signature (prop->set)->param_count - 1];
6961                         minfo =  mono_property_get_object (domain, NULL, prop);
6962                         val = load_cattr_value (image, prop_type, named, &named);
6963                         obj = type_is_reference (prop_type) ? val : mono_value_box (domain, mono_class_from_mono_type (prop_type), val);
6964                         typedarg = create_cattr_typed_arg (prop_type, obj);
6965                         namedarg = create_cattr_named_arg (minfo, typedarg);
6966                         mono_array_set (namedargs, void*, j, namedarg);
6967                         if (!type_is_reference (prop_type))
6968                                 g_free (val);
6969                 }
6970                 g_free (name);
6971         }
6972         attr = mono_object_new (domain, klass);
6973         params [0] = mono_method_get_object (domain, method, NULL);
6974         params [1] = typedargs;
6975         params [2] = namedargs;
6976         mono_runtime_invoke (ctor, attr, params, NULL);
6977         return attr;
6978 }
6979
6980 MonoArray*
6981 mono_custom_attrs_construct (MonoCustomAttrInfo *cinfo)
6982 {
6983         MonoArray *result;
6984         MonoClass *klass;
6985         MonoObject *attr;
6986         int i;
6987
6988         klass = mono_class_from_name (mono_defaults.corlib, "System", "Attribute");
6989         result = mono_array_new (mono_domain_get (), klass, cinfo->num_attrs);
6990         for (i = 0; i < cinfo->num_attrs; ++i) {
6991                 attr = create_custom_attr (cinfo->image, cinfo->attrs [i].ctor, cinfo->attrs [i].data, cinfo->attrs [i].data_size);
6992                 mono_array_set (result, gpointer, i, attr);
6993         }
6994         return result;
6995 }
6996
6997 MonoArray*
6998 mono_custom_attrs_data_construct (MonoCustomAttrInfo *cinfo)
6999 {
7000         MonoArray *result;
7001         static MonoClass *klass;
7002         MonoObject *attr;
7003         int i;
7004
7005         if (!klass)
7006                 klass = mono_class_from_name (mono_defaults.corlib, "System.Reflection", "CustomAttributeData");
7007         
7008         result = mono_array_new (mono_domain_get (), klass, cinfo->num_attrs);
7009         for (i = 0; i < cinfo->num_attrs; ++i) {
7010                 attr = create_custom_attr_data (cinfo->image, cinfo->attrs [i].ctor, cinfo->attrs [i].data, cinfo->attrs [i].data_size);
7011                 mono_array_set (result, gpointer, i, attr);
7012         }
7013         return result;
7014 }
7015
7016 MonoCustomAttrInfo*
7017 mono_custom_attrs_from_index (MonoImage *image, guint32 idx)
7018 {
7019         guint32 mtoken, i, len;
7020         guint32 cols [MONO_CUSTOM_ATTR_SIZE];
7021         MonoTableInfo *ca;
7022         MonoCustomAttrInfo *ainfo;
7023         GList *tmp, *list = NULL;
7024         const char *data;
7025
7026         ca = &image->tables [MONO_TABLE_CUSTOMATTRIBUTE];
7027
7028         i = mono_metadata_custom_attrs_from_index (image, idx);
7029         if (!i)
7030                 return NULL;
7031         i --;
7032         while (i < ca->rows) {
7033                 if (mono_metadata_decode_row_col (ca, i, MONO_CUSTOM_ATTR_PARENT) != idx)
7034                         break;
7035                 list = g_list_prepend (list, GUINT_TO_POINTER (i));
7036                 ++i;
7037         }
7038         len = g_list_length (list);
7039         if (!len)
7040                 return NULL;
7041         ainfo = g_malloc0 (sizeof (MonoCustomAttrInfo) + sizeof (MonoCustomAttrEntry) * (len - MONO_ZERO_LEN_ARRAY));
7042         ainfo->num_attrs = len;
7043         ainfo->image = image;
7044         for (i = 0, tmp = list; i < len; ++i, tmp = tmp->next) {
7045                 mono_metadata_decode_row (ca, GPOINTER_TO_UINT (tmp->data), cols, MONO_CUSTOM_ATTR_SIZE);
7046                 mtoken = cols [MONO_CUSTOM_ATTR_TYPE] >> MONO_CUSTOM_ATTR_TYPE_BITS;
7047                 switch (cols [MONO_CUSTOM_ATTR_TYPE] & MONO_CUSTOM_ATTR_TYPE_MASK) {
7048                 case MONO_CUSTOM_ATTR_TYPE_METHODDEF:
7049                         mtoken |= MONO_TOKEN_METHOD_DEF;
7050                         break;
7051                 case MONO_CUSTOM_ATTR_TYPE_MEMBERREF:
7052                         mtoken |= MONO_TOKEN_MEMBER_REF;
7053                         break;
7054                 default:
7055                         g_error ("Unknown table for custom attr type %08x", cols [MONO_CUSTOM_ATTR_TYPE]);
7056                         break;
7057                 }
7058                 ainfo->attrs [i].ctor = mono_get_method (image, mtoken, NULL);
7059                 if (!ainfo->attrs [i].ctor)
7060                         g_error ("Can't find custom attr constructor image: %s mtoken: 0x%08x", image->name, mtoken);
7061                 data = mono_metadata_blob_heap (image, cols [MONO_CUSTOM_ATTR_VALUE]);
7062                 ainfo->attrs [i].data_size = mono_metadata_decode_value (data, &data);
7063                 ainfo->attrs [i].data = data;
7064         }
7065         g_list_free (list);
7066
7067         return ainfo;
7068 }
7069
7070 MonoCustomAttrInfo*
7071 mono_custom_attrs_from_method (MonoMethod *method)
7072 {
7073         MonoCustomAttrInfo *cinfo;
7074         guint32 idx;
7075         
7076         if (dynamic_custom_attrs && (cinfo = g_hash_table_lookup (dynamic_custom_attrs, method)))
7077                 return cinfo;
7078         idx = mono_method_get_index (method);
7079         idx <<= MONO_CUSTOM_ATTR_BITS;
7080         idx |= MONO_CUSTOM_ATTR_METHODDEF;
7081         return mono_custom_attrs_from_index (method->klass->image, idx);
7082 }
7083
7084 MonoCustomAttrInfo*
7085 mono_custom_attrs_from_class (MonoClass *klass)
7086 {
7087         MonoCustomAttrInfo *cinfo;
7088         guint32 idx;
7089         
7090         if (dynamic_custom_attrs && (cinfo = g_hash_table_lookup (dynamic_custom_attrs, klass)))
7091                 return cinfo;
7092         idx = mono_metadata_token_index (klass->type_token);
7093         idx <<= MONO_CUSTOM_ATTR_BITS;
7094         idx |= MONO_CUSTOM_ATTR_TYPEDEF;
7095         return mono_custom_attrs_from_index (klass->image, idx);
7096 }
7097
7098 MonoCustomAttrInfo*
7099 mono_custom_attrs_from_assembly (MonoAssembly *assembly)
7100 {
7101         MonoCustomAttrInfo *cinfo;
7102         guint32 idx;
7103         
7104         if (dynamic_custom_attrs && (cinfo = g_hash_table_lookup (dynamic_custom_attrs, assembly)))
7105                 return cinfo;
7106         idx = 1; /* there is only one assembly */
7107         idx <<= MONO_CUSTOM_ATTR_BITS;
7108         idx |= MONO_CUSTOM_ATTR_ASSEMBLY;
7109         return mono_custom_attrs_from_index (assembly->image, idx);
7110 }
7111
7112 static MonoCustomAttrInfo*
7113 mono_custom_attrs_from_module (MonoImage *image)
7114 {
7115         MonoCustomAttrInfo *cinfo;
7116         guint32 idx;
7117         
7118         if (dynamic_custom_attrs && (cinfo = g_hash_table_lookup (dynamic_custom_attrs, image)))
7119                 return cinfo;
7120         idx = 1; /* there is only one module */
7121         idx <<= MONO_CUSTOM_ATTR_BITS;
7122         idx |= MONO_CUSTOM_ATTR_MODULE;
7123         return mono_custom_attrs_from_index (image, idx);
7124 }
7125
7126 MonoCustomAttrInfo*
7127 mono_custom_attrs_from_property (MonoClass *klass, MonoProperty *property)
7128 {
7129         MonoCustomAttrInfo *cinfo;
7130         guint32 idx;
7131         
7132         if (dynamic_custom_attrs && (cinfo = g_hash_table_lookup (dynamic_custom_attrs, property)))
7133                 return cinfo;
7134         idx = find_property_index (klass, property);
7135         idx <<= MONO_CUSTOM_ATTR_BITS;
7136         idx |= MONO_CUSTOM_ATTR_PROPERTY;
7137         return mono_custom_attrs_from_index (klass->image, idx);
7138 }
7139
7140 MonoCustomAttrInfo*
7141 mono_custom_attrs_from_event (MonoClass *klass, MonoEvent *event)
7142 {
7143         MonoCustomAttrInfo *cinfo;
7144         guint32 idx;
7145         
7146         if (dynamic_custom_attrs && (cinfo = g_hash_table_lookup (dynamic_custom_attrs, event)))
7147                 return cinfo;
7148         idx = find_event_index (klass, event);
7149         idx <<= MONO_CUSTOM_ATTR_BITS;
7150         idx |= MONO_CUSTOM_ATTR_EVENT;
7151         return mono_custom_attrs_from_index (klass->image, idx);
7152 }
7153
7154 MonoCustomAttrInfo*
7155 mono_custom_attrs_from_field (MonoClass *klass, MonoClassField *field)
7156 {
7157         MonoCustomAttrInfo *cinfo;
7158         guint32 idx;
7159         
7160         if (dynamic_custom_attrs && (cinfo = g_hash_table_lookup (dynamic_custom_attrs, field)))
7161                 return cinfo;
7162         idx = find_field_index (klass, field);
7163         idx <<= MONO_CUSTOM_ATTR_BITS;
7164         idx |= MONO_CUSTOM_ATTR_FIELDDEF;
7165         return mono_custom_attrs_from_index (klass->image, idx);
7166 }
7167
7168 MonoCustomAttrInfo*
7169 mono_custom_attrs_from_param (MonoMethod *method, guint32 param)
7170 {
7171         MonoTableInfo *ca;
7172         guint32 i, idx, method_index;
7173         guint32 param_list, param_last, param_pos, found;
7174         MonoImage *image;
7175         MonoReflectionMethodAux *aux;
7176
7177         if (method->klass->image->dynamic) {
7178                 aux = g_hash_table_lookup (((MonoDynamicImage*)method->klass->image)->method_aux_hash, method);
7179                 if (!aux || !aux->param_cattr)
7180                         return NULL;
7181                 return aux->param_cattr [param];
7182         }
7183
7184         image = method->klass->image;
7185         method_index = mono_method_get_index (method);
7186         ca = &image->tables [MONO_TABLE_METHOD];
7187
7188         if (method->klass->generic_class || mono_method_signature (method)->generic_param_count) {
7189                 /* FIXME FIXME FIXME */
7190                 return NULL;
7191         }
7192
7193         param_list = mono_metadata_decode_row_col (ca, method_index - 1, MONO_METHOD_PARAMLIST);
7194         if (method_index == ca->rows) {
7195                 ca = &image->tables [MONO_TABLE_PARAM];
7196                 param_last = ca->rows + 1;
7197         } else {
7198                 param_last = mono_metadata_decode_row_col (ca, method_index, MONO_METHOD_PARAMLIST);
7199                 ca = &image->tables [MONO_TABLE_PARAM];
7200         }
7201         found = FALSE;
7202         for (i = param_list; i < param_last; ++i) {
7203                 param_pos = mono_metadata_decode_row_col (ca, i - 1, MONO_PARAM_SEQUENCE);
7204                 if (param_pos == param) {
7205                         found = TRUE;
7206                         break;
7207                 }
7208         }
7209         if (!found)
7210                 return NULL;
7211         idx = i;
7212         idx <<= MONO_CUSTOM_ATTR_BITS;
7213         idx |= MONO_CUSTOM_ATTR_PARAMDEF;
7214         return mono_custom_attrs_from_index (image, idx);
7215 }
7216
7217 gboolean
7218 mono_custom_attrs_has_attr (MonoCustomAttrInfo *ainfo, MonoClass *attr_klass)
7219 {
7220         int i;
7221         MonoClass *klass;
7222         for (i = 0; i < ainfo->num_attrs; ++i) {
7223                 klass = ainfo->attrs [i].ctor->klass;
7224                 if (mono_class_has_parent (klass, attr_klass))
7225                         return TRUE;
7226         }
7227         return FALSE;
7228 }
7229
7230 MonoObject*
7231 mono_custom_attrs_get_attr (MonoCustomAttrInfo *ainfo, MonoClass *attr_klass)
7232 {
7233         int i, attr_index;
7234         MonoClass *klass;
7235         MonoArray *attrs;
7236
7237         attr_index = -1;
7238         for (i = 0; i < ainfo->num_attrs; ++i) {
7239                 klass = ainfo->attrs [i].ctor->klass;
7240                 if (mono_class_has_parent (klass, attr_klass)) {
7241                         attr_index = i;
7242                         break;
7243                 }
7244         }
7245         if (attr_index == -1)
7246                 return NULL;
7247
7248         attrs = mono_custom_attrs_construct (ainfo);
7249         if (attrs)
7250                 return mono_array_get (attrs, MonoObject*, attr_index);
7251         else
7252                 return NULL;
7253 }
7254
7255 /*
7256  * mono_reflection_get_custom_attrs_info:
7257  * @obj: a reflection object handle
7258  *
7259  * Return the custom attribute info for attributes defined for the
7260  * reflection handle @obj. The objects.
7261  */
7262 MonoCustomAttrInfo*
7263 mono_reflection_get_custom_attrs_info (MonoObject *obj)
7264 {
7265         MonoClass *klass;
7266         MonoCustomAttrInfo *cinfo = NULL;
7267         
7268         klass = obj->vtable->klass;
7269         if (klass == mono_defaults.monotype_class) {
7270                 MonoReflectionType *rtype = (MonoReflectionType*)obj;
7271                 klass = mono_class_from_mono_type (rtype->type);
7272                 cinfo = mono_custom_attrs_from_class (klass);
7273         } else if (strcmp ("Assembly", klass->name) == 0) {
7274                 MonoReflectionAssembly *rassembly = (MonoReflectionAssembly*)obj;
7275                 cinfo = mono_custom_attrs_from_assembly (rassembly->assembly);
7276         } else if (strcmp ("Module", klass->name) == 0) {
7277                 MonoReflectionModule *module = (MonoReflectionModule*)obj;
7278                 cinfo = mono_custom_attrs_from_module (module->image);
7279         } else if (strcmp ("MonoProperty", klass->name) == 0) {
7280                 MonoReflectionProperty *rprop = (MonoReflectionProperty*)obj;
7281                 cinfo = mono_custom_attrs_from_property (rprop->property->parent, rprop->property);
7282         } else if (strcmp ("MonoEvent", klass->name) == 0) {
7283                 MonoReflectionEvent *revent = (MonoReflectionEvent*)obj;
7284                 cinfo = mono_custom_attrs_from_event (revent->event->parent, revent->event);
7285         } else if (strcmp ("MonoField", klass->name) == 0) {
7286                 MonoReflectionField *rfield = (MonoReflectionField*)obj;
7287                 cinfo = mono_custom_attrs_from_field (rfield->field->parent, rfield->field);
7288         } else if ((strcmp ("MonoMethod", klass->name) == 0) || (strcmp ("MonoCMethod", klass->name) == 0)) {
7289                 MonoReflectionMethod *rmethod = (MonoReflectionMethod*)obj;
7290                 cinfo = mono_custom_attrs_from_method (rmethod->method);
7291         } else if ((strcmp ("MonoGenericMethod", klass->name) == 0) || (strcmp ("MonoGenericCMethod", klass->name) == 0)) {
7292                 MonoMethod *method = mono_get_inflated_method (((MonoReflectionMethod*)obj)->method);
7293                 cinfo = mono_custom_attrs_from_method (method);
7294         } else if (strcmp ("ParameterInfo", klass->name) == 0) {
7295                 MonoReflectionParameter *param = (MonoReflectionParameter*)obj;
7296                 MonoReflectionMethod *rmethod = (MonoReflectionMethod*)param->MemberImpl;
7297                 cinfo = mono_custom_attrs_from_param (rmethod->method, param->PositionImpl + 1);
7298         } else if (strcmp ("AssemblyBuilder", klass->name) == 0) {
7299                 MonoReflectionAssemblyBuilder *assemblyb = (MonoReflectionAssemblyBuilder*)obj;
7300                 cinfo = mono_custom_attrs_from_builders (assemblyb->assembly.assembly->image, assemblyb->cattrs);
7301         } else if (strcmp ("TypeBuilder", klass->name) == 0) {
7302                 MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder*)obj;
7303                 cinfo = mono_custom_attrs_from_builders (&tb->module->dynamic_image->image, tb->cattrs);
7304         } else if (strcmp ("ModuleBuilder", klass->name) == 0) {
7305                 MonoReflectionModuleBuilder *mb = (MonoReflectionModuleBuilder*)obj;
7306                 cinfo = mono_custom_attrs_from_builders (&mb->dynamic_image->image, mb->cattrs);
7307         } else { /* handle other types here... */
7308                 g_error ("get custom attrs not yet supported for %s", klass->name);
7309         }
7310
7311         return cinfo;
7312 }
7313
7314 /*
7315  * mono_reflection_get_custom_attrs:
7316  * @obj: a reflection object handle
7317  *
7318  * Return an array with all the custom attributes defined of the
7319  * reflection handle @obj. The objects are fully build.
7320  */
7321 MonoArray*
7322 mono_reflection_get_custom_attrs (MonoObject *obj)
7323 {
7324         MonoArray *result;
7325         MonoCustomAttrInfo *cinfo;
7326
7327         cinfo = mono_reflection_get_custom_attrs_info (obj);
7328         if (cinfo) {
7329                 result = mono_custom_attrs_construct (cinfo);
7330                 if (!cinfo->cached)
7331                         mono_custom_attrs_free (cinfo);
7332         } else {
7333                 MonoClass *klass;
7334                 klass = mono_class_from_name (mono_defaults.corlib, "System", "Attribute");
7335                 result = mono_array_new (mono_domain_get (), klass, 0);
7336         }
7337
7338         return result;
7339 }
7340
7341 /*
7342  * mono_reflection_get_custom_attrs_data:
7343  * @obj: a reflection obj handle
7344  *
7345  * Returns an array of System.Reflection.CustomAttributeData,
7346  * which include information about attributes reflected on
7347  * types loaded using the Reflection Only methods
7348  */
7349 MonoArray*
7350 mono_reflection_get_custom_attrs_data (MonoObject *obj)
7351 {
7352         MonoArray *result;
7353         MonoCustomAttrInfo *cinfo;
7354
7355         cinfo = mono_reflection_get_custom_attrs_info (obj);
7356         if (cinfo) {
7357                 result = mono_custom_attrs_data_construct (cinfo);
7358                 if (!cinfo->cached)
7359                         mono_custom_attrs_free (cinfo);
7360         } else {
7361                 MonoClass *klass;
7362                 klass = mono_class_from_name (mono_defaults.corlib, "System.Reflection", "CustomAttributeData");
7363                 result = mono_array_new (mono_domain_get (), klass, 0);
7364         }
7365
7366         return result;
7367 }
7368
7369 static MonoMethodSignature*
7370 parameters_to_signature (MonoArray *parameters) {
7371         MonoMethodSignature *sig;
7372         int count, i;
7373
7374         count = parameters? mono_array_length (parameters): 0;
7375
7376         sig = g_malloc0 (sizeof (MonoMethodSignature) + sizeof (MonoType*) * count);
7377         sig->param_count = count;
7378         sig->sentinelpos = -1; /* FIXME */
7379         for (i = 0; i < count; ++i) {
7380                 MonoReflectionType *pt = mono_array_get (parameters, MonoReflectionType*, i);
7381                 sig->params [i] = pt->type;
7382         }
7383         return sig;
7384 }
7385
7386 static MonoMethodSignature*
7387 ctor_builder_to_signature (MonoReflectionCtorBuilder *ctor) {
7388         MonoMethodSignature *sig;
7389
7390         sig = parameters_to_signature (ctor->parameters);
7391         sig->hasthis = ctor->attrs & METHOD_ATTRIBUTE_STATIC? 0: 1;
7392         sig->ret = &mono_defaults.void_class->byval_arg;
7393         return sig;
7394 }
7395
7396 static MonoMethodSignature*
7397 method_builder_to_signature (MonoReflectionMethodBuilder *method) {
7398         MonoMethodSignature *sig;
7399
7400         sig = parameters_to_signature (method->parameters);
7401         sig->hasthis = method->attrs & METHOD_ATTRIBUTE_STATIC? 0: 1;
7402         sig->ret = method->rtype? method->rtype->type: &mono_defaults.void_class->byval_arg;
7403         sig->generic_param_count = method->generic_params ? mono_array_length (method->generic_params) : 0;
7404         return sig;
7405 }
7406
7407 static MonoMethodSignature*
7408 dynamic_method_to_signature (MonoReflectionDynamicMethod *method) {
7409         MonoMethodSignature *sig;
7410
7411         sig = parameters_to_signature (method->parameters);
7412         sig->hasthis = method->attrs & METHOD_ATTRIBUTE_STATIC? 0: 1;
7413         sig->ret = method->rtype? method->rtype->type: &mono_defaults.void_class->byval_arg;
7414         sig->generic_param_count = 0;
7415         return sig;
7416 }
7417
7418 static void
7419 get_prop_name_and_type (MonoObject *prop, char **name, MonoType **type)
7420 {
7421         MonoClass *klass = mono_object_class (prop);
7422         if (strcmp (klass->name, "PropertyBuilder") == 0) {
7423                 MonoReflectionPropertyBuilder *pb = (MonoReflectionPropertyBuilder *)prop;
7424                 *name = mono_string_to_utf8 (pb->name);
7425                 *type = pb->type->type;
7426         } else {
7427                 MonoReflectionProperty *p = (MonoReflectionProperty *)prop;
7428                 *name = g_strdup (p->property->name);
7429                 if (p->property->get)
7430                         *type = mono_method_signature (p->property->get)->ret;
7431                 else
7432                         *type = mono_method_signature (p->property->set)->params [mono_method_signature (p->property->set)->param_count - 1];
7433         }
7434 }
7435
7436 static void
7437 get_field_name_and_type (MonoObject *field, char **name, MonoType **type)
7438 {
7439         MonoClass *klass = mono_object_class (field);
7440         if (strcmp (klass->name, "FieldBuilder") == 0) {
7441                 MonoReflectionFieldBuilder *fb = (MonoReflectionFieldBuilder *)field;
7442                 *name = mono_string_to_utf8 (fb->name);
7443                 *type = fb->type->type;
7444         } else {
7445                 MonoReflectionField *f = (MonoReflectionField *)field;
7446                 *name = g_strdup (f->field->name);
7447                 *type = f->field->type;
7448         }
7449 }
7450
7451 /*
7452  * Encode a value in a custom attribute stream of bytes.
7453  * The value to encode is either supplied as an object in argument val
7454  * (valuetypes are boxed), or as a pointer to the data in the
7455  * argument argval.
7456  * @type represents the type of the value
7457  * @buffer is the start of the buffer
7458  * @p the current position in the buffer
7459  * @buflen contains the size of the buffer and is used to return the new buffer size
7460  * if this needs to be realloced.
7461  * @retbuffer and @retp return the start and the position of the buffer
7462  */
7463 static void
7464 encode_cattr_value (MonoAssembly *assembly, char *buffer, char *p, char **retbuffer, char **retp, guint32 *buflen, MonoType *type, MonoObject *arg, char *argval)
7465 {
7466         MonoTypeEnum simple_type;
7467         
7468         if ((p-buffer) + 10 >= *buflen) {
7469                 char *newbuf;
7470                 *buflen *= 2;
7471                 newbuf = g_realloc (buffer, *buflen);
7472                 p = newbuf + (p-buffer);
7473                 buffer = newbuf;
7474         }
7475         if (!argval)
7476                 argval = ((char*)arg + sizeof (MonoObject));
7477         simple_type = type->type;
7478 handle_enum:
7479         switch (simple_type) {
7480         case MONO_TYPE_BOOLEAN:
7481         case MONO_TYPE_U1:
7482         case MONO_TYPE_I1:
7483                 *p++ = *argval;
7484                 break;
7485         case MONO_TYPE_CHAR:
7486         case MONO_TYPE_U2:
7487         case MONO_TYPE_I2:
7488                 swap_with_size (p, argval, 2, 1);
7489                 p += 2;
7490                 break;
7491         case MONO_TYPE_U4:
7492         case MONO_TYPE_I4:
7493         case MONO_TYPE_R4:
7494                 swap_with_size (p, argval, 4, 1);
7495                 p += 4;
7496                 break;
7497         case MONO_TYPE_U8:
7498         case MONO_TYPE_I8:
7499         case MONO_TYPE_R8:
7500                 swap_with_size (p, argval, 8, 1);
7501                 p += 8;
7502                 break;
7503         case MONO_TYPE_VALUETYPE:
7504                 if (type->data.klass->enumtype) {
7505                         simple_type = type->data.klass->enum_basetype->type;
7506                         goto handle_enum;
7507                 } else {
7508                         g_warning ("generic valutype %s not handled in custom attr value decoding", type->data.klass->name);
7509                 }
7510                 break;
7511         case MONO_TYPE_STRING: {
7512                 char *str;
7513                 guint32 slen;
7514                 if (!arg) {
7515                         *p++ = 0xFF;
7516                         break;
7517                 }
7518                 str = mono_string_to_utf8 ((MonoString*)arg);
7519                 slen = strlen (str);
7520                 if ((p-buffer) + 10 + slen >= *buflen) {
7521                         char *newbuf;
7522                         *buflen *= 2;
7523                         *buflen += slen;
7524                         newbuf = g_realloc (buffer, *buflen);
7525                         p = newbuf + (p-buffer);
7526                         buffer = newbuf;
7527                 }
7528                 mono_metadata_encode_value (slen, p, &p);
7529                 memcpy (p, str, slen);
7530                 p += slen;
7531                 g_free (str);
7532                 break;
7533         }
7534         case MONO_TYPE_CLASS: {
7535                 char *str;
7536                 guint32 slen;
7537                 MonoClass *k;
7538                 if (!arg) {
7539                         *p++ = 0xFF;
7540                         break;
7541                 }
7542                 k = mono_object_class (arg);
7543                 if (!mono_object_isinst (arg, mono_defaults.monotype_class) &&
7544                                 (strcmp (k->name, "TypeBuilder") || strcmp (k->name_space, "System.Reflection.Emit")))
7545                         g_error ("only types allowed, not %s.%s", k->name_space, k->name);
7546 handle_type:
7547                 str = type_get_qualified_name (((MonoReflectionType*)arg)->type, NULL);
7548                 slen = strlen (str);
7549                 if ((p-buffer) + 10 + slen >= *buflen) {
7550                         char *newbuf;
7551                         *buflen *= 2;
7552                         *buflen += slen;
7553                         newbuf = g_realloc (buffer, *buflen);
7554                         p = newbuf + (p-buffer);
7555                         buffer = newbuf;
7556                 }
7557                 mono_metadata_encode_value (slen, p, &p);
7558                 memcpy (p, str, slen);
7559                 p += slen;
7560                 g_free (str);
7561                 break;
7562         }
7563         case MONO_TYPE_SZARRAY: {
7564                 int len, i;
7565                 MonoClass *eclass, *arg_eclass;
7566
7567                 if (!arg) {
7568                         *p++ = 0xff; *p++ = 0xff; *p++ = 0xff; *p++ = 0xff;
7569                         break;
7570                 }
7571                 len = mono_array_length ((MonoArray*)arg);
7572                 *p++ = len & 0xff;
7573                 *p++ = (len >> 8) & 0xff;
7574                 *p++ = (len >> 16) & 0xff;
7575                 *p++ = (len >> 24) & 0xff;
7576                 *retp = p;
7577                 *retbuffer = buffer;
7578                 eclass = type->data.klass;
7579                 arg_eclass = mono_object_class (arg)->element_class;
7580                 if (eclass->valuetype && arg_eclass->valuetype) {
7581                         char *elptr = mono_array_addr ((MonoArray*)arg, char, 0);
7582                         int elsize = mono_class_array_element_size (eclass);
7583                         for (i = 0; i < len; ++i) {
7584                                 encode_cattr_value (assembly, buffer, p, &buffer, &p, buflen, &eclass->byval_arg, NULL, elptr);
7585                                 elptr += elsize;
7586                         }
7587                 } else {
7588                         for (i = 0; i < len; ++i) {
7589                                 encode_cattr_value (assembly, buffer, p, &buffer, &p, buflen, &eclass->byval_arg, mono_array_get ((MonoArray*)arg, MonoObject*, i), NULL);
7590                         }
7591                 }
7592                 break;
7593         }
7594         /* it may be a boxed value or a Type */
7595         case MONO_TYPE_OBJECT: {
7596                 MonoClass *klass;
7597                 char *str;
7598                 guint32 slen;
7599
7600                 if (arg == NULL) {
7601                         *p++ = MONO_TYPE_STRING;        // It's same hack as MS uses
7602                         *p++ = 0xFF;
7603                         break;
7604                 }
7605                 
7606                 klass = mono_object_class (arg);
7607
7608                 if (mono_object_isinst (arg, mono_defaults.monotype_class)) {
7609                         *p++ = 0x50;
7610                         goto handle_type;
7611                 } else if (klass->enumtype) {
7612                         *p++ = 0x55;
7613                 } else if (klass == mono_defaults.string_class) {
7614                         simple_type = MONO_TYPE_STRING;
7615                         *p++ = 0x0E;
7616                         goto handle_enum;
7617                 } else if (klass->byval_arg.type >= MONO_TYPE_BOOLEAN && klass->byval_arg.type <= MONO_TYPE_R8) {
7618                         *p++ = simple_type = klass->byval_arg.type;
7619                         goto handle_enum;
7620                 } else {
7621                         g_error ("unhandled type in custom attr");
7622                 }
7623                 str = type_get_qualified_name (mono_class_get_type(klass), NULL);
7624                 slen = strlen (str);
7625                 if ((p-buffer) + 10 + slen >= *buflen) {
7626                         char *newbuf;
7627                         *buflen *= 2;
7628                         *buflen += slen;
7629                         newbuf = g_realloc (buffer, *buflen);
7630                         p = newbuf + (p-buffer);
7631                         buffer = newbuf;
7632                 }
7633                 mono_metadata_encode_value (slen, p, &p);
7634                 memcpy (p, str, slen);
7635                 p += slen;
7636                 g_free (str);
7637                 simple_type = klass->enum_basetype->type;
7638                 goto handle_enum;
7639         }
7640         default:
7641                 g_error ("type 0x%02x not yet supported in custom attr encoder", simple_type);
7642         }
7643         *retp = p;
7644         *retbuffer = buffer;
7645 }
7646
7647 static void
7648 encode_named_val (MonoReflectionAssembly *assembly, char *buffer, char *p, char **retbuffer, char **retp, guint32 *buflen, MonoType *type, char *name, MonoObject *value)
7649 {
7650         int len;
7651         /* Preallocate a large enough buffer */
7652         if (type->type == MONO_TYPE_VALUETYPE && type->data.klass->enumtype) {
7653                 char *str = type_get_qualified_name (type, NULL);
7654                 len = strlen (str);
7655                 g_free (str);
7656         } else {
7657                 len = 0;
7658         }
7659         len += strlen (name);
7660
7661         if ((p-buffer) + 20 + len >= *buflen) {
7662                 char *newbuf;
7663                 *buflen *= 2;
7664                 *buflen += len;
7665                 newbuf = g_realloc (buffer, *buflen);
7666                 p = newbuf + (p-buffer);
7667                 buffer = newbuf;
7668         }
7669
7670         if (type->type == MONO_TYPE_VALUETYPE && type->data.klass->enumtype) {
7671                 char *str = type_get_qualified_name (type, NULL);
7672                 int slen = strlen (str);
7673
7674                 *p++ = 0x55;
7675                 /*
7676                  * This seems to be optional...
7677                  * *p++ = 0x80;
7678                  */
7679                 mono_metadata_encode_value (slen, p, &p);
7680                 memcpy (p, str, slen);
7681                 p += slen;
7682                 g_free (str);
7683         } else if (type->type == MONO_TYPE_OBJECT) {
7684                 *p++ = 0x51;
7685         } else if (type->type == MONO_TYPE_CLASS) {
7686                 /* it should be a type: encode_cattr_value () has the check */
7687                 *p++ = 0x50;
7688         } else {
7689                 mono_metadata_encode_value (type->type, p, &p);
7690                 if (type->type == MONO_TYPE_SZARRAY)
7691                         mono_metadata_encode_value (type->data.klass->this_arg.type, p, &p);
7692         }
7693         len = strlen (name);
7694         mono_metadata_encode_value (len, p, &p);
7695         memcpy (p, name, len);
7696         p += len;
7697         encode_cattr_value (assembly->assembly, buffer, p, &buffer, &p, buflen, type, value, NULL);
7698         *retp = p;
7699         *retbuffer = buffer;
7700 }
7701
7702 /*
7703  * mono_reflection_get_custom_attrs_blob:
7704  * @ctor: custom attribute constructor
7705  * @ctorArgs: arguments o the constructor
7706  * @properties:
7707  * @propValues:
7708  * @fields:
7709  * @fieldValues:
7710  * 
7711  * Creates the blob of data that needs to be saved in the metadata and that represents
7712  * the custom attributed described by @ctor, @ctorArgs etc.
7713  * Returns: a Byte array representing the blob of data.
7714  */
7715 MonoArray*
7716 mono_reflection_get_custom_attrs_blob (MonoReflectionAssembly *assembly, MonoObject *ctor, MonoArray *ctorArgs, MonoArray *properties, MonoArray *propValues, MonoArray *fields, MonoArray* fieldValues) 
7717 {
7718         MonoArray *result;
7719         MonoMethodSignature *sig;
7720         MonoObject *arg;
7721         char *buffer, *p;
7722         guint32 buflen, i;
7723
7724         MONO_ARCH_SAVE_REGS;
7725
7726         if (strcmp (ctor->vtable->klass->name, "MonoCMethod")) {
7727                 sig = ctor_builder_to_signature ((MonoReflectionCtorBuilder*)ctor);
7728         } else {
7729                 sig = mono_method_signature (((MonoReflectionMethod*)ctor)->method);
7730         }
7731         g_assert (mono_array_length (ctorArgs) == sig->param_count);
7732         buflen = 256;
7733         p = buffer = g_malloc (buflen);
7734         /* write the prolog */
7735         *p++ = 1;
7736         *p++ = 0;
7737         for (i = 0; i < sig->param_count; ++i) {
7738                 arg = mono_array_get (ctorArgs, MonoObject*, i);
7739                 encode_cattr_value (assembly->assembly, buffer, p, &buffer, &p, &buflen, sig->params [i], arg, NULL);
7740         }
7741         i = 0;
7742         if (properties)
7743                 i += mono_array_length (properties);
7744         if (fields)
7745                 i += mono_array_length (fields);
7746         *p++ = i & 0xff;
7747         *p++ = (i >> 8) & 0xff;
7748         if (properties) {
7749                 MonoObject *prop;
7750                 for (i = 0; i < mono_array_length (properties); ++i) {
7751                         MonoType *ptype;
7752                         char *pname;
7753
7754                         prop = mono_array_get (properties, gpointer, i);
7755                         get_prop_name_and_type (prop, &pname, &ptype);
7756                         *p++ = 0x54; /* PROPERTY signature */
7757                         encode_named_val (assembly, buffer, p, &buffer, &p, &buflen, ptype, pname, (MonoObject*)mono_array_get (propValues, gpointer, i));
7758                         g_free (pname);
7759                 }
7760         }
7761
7762         if (fields) {
7763                 MonoObject *field;
7764                 for (i = 0; i < mono_array_length (fields); ++i) {
7765                         MonoType *ftype;
7766                         char *fname;
7767
7768                         field = mono_array_get (fields, gpointer, i);
7769                         get_field_name_and_type (field, &fname, &ftype);
7770                         *p++ = 0x53; /* FIELD signature */
7771                         encode_named_val (assembly, buffer, p, &buffer, &p, &buflen, ftype, fname, (MonoObject*)mono_array_get (fieldValues, gpointer, i));
7772                         g_free (fname);
7773                 }
7774         }
7775
7776         g_assert (p - buffer <= buflen);
7777         buflen = p - buffer;
7778         result = mono_array_new (mono_domain_get (), mono_defaults.byte_class, buflen);
7779         p = mono_array_addr (result, char, 0);
7780         memcpy (p, buffer, buflen);
7781         g_free (buffer);
7782         if (strcmp (ctor->vtable->klass->name, "MonoCMethod"))
7783                 g_free (sig);
7784         return result;
7785 }
7786
7787 /*
7788  * mono_reflection_setup_internal_class:
7789  * @tb: a TypeBuilder object
7790  *
7791  * Creates a MonoClass that represents the TypeBuilder.
7792  * This is a trick that lets us simplify a lot of reflection code
7793  * (and will allow us to support Build and Run assemblies easier).
7794  */
7795 void
7796 mono_reflection_setup_internal_class (MonoReflectionTypeBuilder *tb)
7797 {
7798         MonoClass *klass, *parent;
7799
7800         MONO_ARCH_SAVE_REGS;
7801
7802         mono_loader_lock ();
7803
7804         if (tb->parent) {
7805                 /* check so we can compile corlib correctly */
7806                 if (strcmp (mono_object_class (tb->parent)->name, "TypeBuilder") == 0) {
7807                         /* mono_class_setup_mono_type () guaranteess type->data.klass is valid */
7808                         parent = tb->parent->type->data.klass;
7809                 } else {
7810                         parent = my_mono_class_from_mono_type (tb->parent->type);
7811                 }
7812         } else {
7813                 parent = NULL;
7814         }
7815         
7816         /* the type has already being created: it means we just have to change the parent */
7817         if (tb->type.type) {
7818                 klass = mono_class_from_mono_type (tb->type.type);
7819                 klass->parent = NULL;
7820                 /* fool mono_class_setup_parent */
7821                 g_free (klass->supertypes);
7822                 klass->supertypes = NULL;
7823                 mono_class_setup_parent (klass, parent);
7824                 mono_class_setup_mono_type (klass);
7825                 mono_loader_unlock ();
7826                 return;
7827         }
7828         
7829         klass = g_new0 (MonoClass, 1);
7830
7831         klass->image = &tb->module->dynamic_image->image;
7832
7833         klass->inited = 1; /* we lie to the runtime */
7834         klass->name = mono_string_to_utf8 (tb->name);
7835         klass->name_space = mono_string_to_utf8 (tb->nspace);
7836         klass->type_token = MONO_TOKEN_TYPE_DEF | tb->table_idx;
7837         klass->flags = tb->attrs;
7838
7839         klass->element_class = klass;
7840         klass->reflection_info = tb; /* need to pin. */
7841
7842         /* Put into cache so mono_class_get () will find it */
7843         mono_image_add_to_name_cache (klass->image, klass->name_space, klass->name, tb->table_idx);
7844
7845         mono_g_hash_table_insert (tb->module->dynamic_image->tokens,
7846                 GUINT_TO_POINTER (MONO_TOKEN_TYPE_DEF | tb->table_idx), tb);
7847
7848         if (parent != NULL) {
7849                 mono_class_setup_parent (klass, parent);
7850         } else if (strcmp (klass->name, "Object") == 0 && strcmp (klass->name_space, "System") == 0) {
7851                 const char *old_n = klass->name;
7852                 /* trick to get relative numbering right when compiling corlib */
7853                 klass->name = "BuildingObject";
7854                 mono_class_setup_parent (klass, mono_defaults.object_class);
7855                 klass->name = old_n;
7856         }
7857
7858         if ((!strcmp (klass->name, "ValueType") && !strcmp (klass->name_space, "System")) ||
7859                         (!strcmp (klass->name, "Object") && !strcmp (klass->name_space, "System")) ||
7860                         (!strcmp (klass->name, "Enum") && !strcmp (klass->name_space, "System"))) {
7861                 klass->instance_size = sizeof (MonoObject);
7862                 klass->size_inited = 1;
7863                 mono_class_setup_vtable_general (klass, NULL, 0);
7864         }
7865
7866         mono_class_setup_mono_type (klass);
7867
7868         mono_class_setup_supertypes (klass);
7869
7870         /*
7871          * FIXME: handle interfaces.
7872          */
7873
7874         tb->type.type = &klass->byval_arg;
7875
7876         if (tb->nesting_type) {
7877                 g_assert (tb->nesting_type->type);
7878                 klass->nested_in = mono_class_from_mono_type (tb->nesting_type->type);
7879         }
7880
7881         /*g_print ("setup %s as %s (%p)\n", klass->name, ((MonoObject*)tb)->vtable->klass->name, tb);*/
7882
7883         mono_loader_unlock ();
7884 }
7885
7886 /*
7887  * mono_reflection_setup_generic_class:
7888  * @tb: a TypeBuilder object
7889  *
7890  * Setup the generic class before adding the first generic parameter.
7891  */
7892 void
7893 mono_reflection_setup_generic_class (MonoReflectionTypeBuilder *tb)
7894 {
7895         MonoClass *klass;
7896
7897         MONO_ARCH_SAVE_REGS;
7898
7899         klass = my_mono_class_from_mono_type (tb->type.type);
7900         if (tb->generic_container)
7901                 return;
7902
7903         tb->generic_container = g_new0 (MonoGenericContainer, 1);
7904         tb->generic_container->klass = klass;
7905
7906         tb->generic_container->context.container = tb->generic_container;
7907 }
7908
7909 /*
7910  * mono_reflection_create_generic_class:
7911  * @tb: a TypeBuilder object
7912  *
7913  * Creates the generic class after all generic parameters have been added.
7914  */
7915 void
7916 mono_reflection_create_generic_class (MonoReflectionTypeBuilder *tb)
7917 {
7918         MonoClass *klass;
7919         int count, i;
7920
7921         MONO_ARCH_SAVE_REGS;
7922
7923         klass = my_mono_class_from_mono_type (tb->type.type);
7924
7925         count = tb->generic_params ? mono_array_length (tb->generic_params) : 0;
7926
7927         if (klass->generic_container || (count == 0))
7928                 return;
7929
7930         g_assert (tb->generic_container && (tb->generic_container->klass == klass));
7931
7932         klass->generic_container = tb->generic_container;
7933
7934         klass->generic_container->type_argc = count;
7935         klass->generic_container->type_params = g_new0 (MonoGenericParam, count);
7936
7937         for (i = 0; i < count; i++) {
7938                 MonoReflectionGenericParam *gparam = mono_array_get (tb->generic_params, gpointer, i);
7939                 klass->generic_container->type_params [i] = *gparam->type.type->data.generic_param;
7940                 g_assert (klass->generic_container->type_params [i].owner);
7941         }
7942
7943         klass->generic_container->context.gclass = mono_get_shared_generic_class (klass->generic_container, TRUE);
7944 }
7945
7946 /*
7947  * mono_reflection_create_internal_class:
7948  * @tb: a TypeBuilder object
7949  *
7950  * Actually create the MonoClass that is associated with the TypeBuilder.
7951  */
7952 void
7953 mono_reflection_create_internal_class (MonoReflectionTypeBuilder *tb)
7954 {
7955         MonoClass *klass;
7956
7957         MONO_ARCH_SAVE_REGS;
7958
7959         klass = my_mono_class_from_mono_type (tb->type.type);
7960
7961         mono_loader_lock ();
7962         if (klass->enumtype && klass->enum_basetype == NULL) {
7963                 MonoReflectionFieldBuilder *fb;
7964                 MonoClass *ec;
7965
7966                 g_assert (tb->fields != NULL);
7967                 g_assert (mono_array_length (tb->fields) >= 1);
7968
7969                 fb = mono_array_get (tb->fields, MonoReflectionFieldBuilder*, 0);
7970
7971                 klass->enum_basetype = fb->type->type;
7972                 klass->element_class = my_mono_class_from_mono_type (klass->enum_basetype);
7973                 if (!klass->element_class)
7974                         klass->element_class = mono_class_from_mono_type (klass->enum_basetype);
7975
7976                 /*
7977                  * get the element_class from the current corlib.
7978                  */
7979                 ec = default_class_from_mono_type (klass->enum_basetype);
7980                 klass->instance_size = ec->instance_size;
7981                 klass->size_inited = 1;
7982                 /* 
7983                  * this is almost safe to do with enums and it's needed to be able
7984                  * to create objects of the enum type (for use in SetConstant).
7985                  */
7986                 /* FIXME: Does this mean enums can't have method overrides ? */
7987                 mono_class_setup_vtable_general (klass, NULL, 0);
7988         }
7989         mono_loader_unlock ();
7990 }
7991
7992 static MonoMarshalSpec*
7993 mono_marshal_spec_from_builder (MonoAssembly *assembly,
7994                                                                 MonoReflectionMarshal *minfo)
7995 {
7996         MonoMarshalSpec *res;
7997
7998         res = g_new0 (MonoMarshalSpec, 1);
7999         res->native = minfo->type;
8000
8001         switch (minfo->type) {
8002         case MONO_NATIVE_LPARRAY:
8003                 res->data.array_data.elem_type = minfo->eltype;
8004                 if (minfo->has_size) {
8005                         res->data.array_data.param_num = minfo->param_num;
8006                         res->data.array_data.num_elem = minfo->count;
8007                         res->data.array_data.elem_mult = minfo->param_num == -1 ? 0 : 1;
8008                 }
8009                 else {
8010                         res->data.array_data.param_num = -1;
8011                         res->data.array_data.num_elem = -1;
8012                         res->data.array_data.elem_mult = -1;
8013                 }
8014                 break;
8015
8016         case MONO_NATIVE_BYVALTSTR:
8017         case MONO_NATIVE_BYVALARRAY:
8018                 res->data.array_data.num_elem = minfo->count;
8019                 break;
8020
8021         case MONO_NATIVE_CUSTOM:
8022                 if (minfo->marshaltyperef)
8023                         res->data.custom_data.custom_name =
8024                                 type_get_fully_qualified_name (minfo->marshaltyperef->type);
8025                 if (minfo->mcookie)
8026                         res->data.custom_data.cookie = mono_string_to_utf8 (minfo->mcookie);
8027                 break;
8028
8029         default:
8030                 break;
8031         }
8032
8033         return res;
8034 }
8035
8036 MonoReflectionMarshal*
8037 mono_reflection_marshal_from_marshal_spec (MonoDomain *domain, MonoClass *klass,
8038                                                                                    MonoMarshalSpec *spec)
8039 {
8040         static MonoClass *System_Reflection_Emit_UnmanagedMarshalClass;
8041         MonoReflectionMarshal *minfo;
8042         MonoType *mtype;
8043
8044         if (!System_Reflection_Emit_UnmanagedMarshalClass) {
8045                 System_Reflection_Emit_UnmanagedMarshalClass = mono_class_from_name (
8046                    mono_defaults.corlib, "System.Reflection.Emit", "UnmanagedMarshal");
8047                 g_assert (System_Reflection_Emit_UnmanagedMarshalClass);
8048         }
8049
8050         minfo = (MonoReflectionMarshal*)mono_object_new (domain, System_Reflection_Emit_UnmanagedMarshalClass);
8051         minfo->type = spec->native;
8052
8053         switch (minfo->type) {
8054         case MONO_NATIVE_LPARRAY:
8055                 minfo->eltype = spec->data.array_data.elem_type;
8056                 minfo->count = spec->data.array_data.num_elem;
8057                 minfo->param_num = spec->data.array_data.param_num;
8058                 break;
8059
8060         case MONO_NATIVE_BYVALTSTR:
8061         case MONO_NATIVE_BYVALARRAY:
8062                 minfo->count = spec->data.array_data.num_elem;
8063                 break;
8064
8065         case MONO_NATIVE_CUSTOM:
8066                 if (spec->data.custom_data.custom_name) {
8067                         mtype = mono_reflection_type_from_name (spec->data.custom_data.custom_name, klass->image);
8068                         if (mtype)
8069                                 minfo->marshaltyperef = mono_type_get_object (domain, mtype);
8070
8071                         minfo->marshaltype = mono_string_new (domain, spec->data.custom_data.custom_name);
8072                 }
8073                 if (spec->data.custom_data.cookie)
8074                         minfo->mcookie = mono_string_new (domain, spec->data.custom_data.cookie);
8075                 break;
8076
8077         default:
8078                 break;
8079         }
8080
8081         return minfo;
8082 }
8083
8084 static MonoMethod*
8085 reflection_methodbuilder_to_mono_method (MonoClass *klass,
8086                                          ReflectionMethodBuilder *rmb,
8087                                          MonoMethodSignature *sig)
8088 {
8089         MonoMethod *m;
8090         MonoMethodNormal *pm;
8091         MonoMarshalSpec **specs;
8092         MonoReflectionMethodAux *method_aux;
8093         int i;
8094
8095         if ((rmb->attrs & METHOD_ATTRIBUTE_PINVOKE_IMPL) ||
8096                         (rmb->iattrs & METHOD_IMPL_ATTRIBUTE_INTERNAL_CALL))
8097                 m = (MonoMethod *)g_new0 (MonoMethodPInvoke, 1);
8098         else if (rmb->refs)
8099                 m = (MonoMethod *)g_new0 (MonoMethodWrapper, 1);
8100         else
8101                 m = (MonoMethod *)g_new0 (MonoMethodNormal, 1);
8102
8103         pm = (MonoMethodNormal*)m;
8104
8105         m->slot = -1;
8106         m->flags = rmb->attrs;
8107         m->iflags = rmb->iattrs;
8108         m->name = mono_string_to_utf8 (rmb->name);
8109         m->klass = klass;
8110         m->signature = sig;
8111         if (rmb->table_idx)
8112                 m->token = MONO_TOKEN_METHOD_DEF | (*rmb->table_idx);
8113
8114         if (m->iflags & METHOD_IMPL_ATTRIBUTE_INTERNAL_CALL) {
8115                 if (klass == mono_defaults.string_class && !strcmp (m->name, ".ctor"))
8116                         m->string_ctor = 1;
8117
8118                 m->signature->pinvoke = 1;
8119         } else if (m->flags & METHOD_ATTRIBUTE_PINVOKE_IMPL) {
8120                 m->signature->pinvoke = 1;
8121
8122                 method_aux = g_new0 (MonoReflectionMethodAux, 1);
8123
8124                 method_aux->dllentry = rmb->dllentry ? g_strdup (mono_string_to_utf8 (rmb->dllentry)) : g_strdup (m->name);
8125                 method_aux->dll = g_strdup (mono_string_to_utf8 (rmb->dll));
8126                 
8127                 ((MonoMethodPInvoke*)m)->piflags = (rmb->native_cc << 8) | (rmb->charset ? (rmb->charset - 1) * 2 : 0) | rmb->extra_flags;
8128
8129                 if (klass->image->dynamic)
8130                         g_hash_table_insert (((MonoDynamicImage*)klass->image)->method_aux_hash, m, method_aux);
8131
8132                 return m;
8133         } else if (!m->klass->dummy && 
8134                            !(m->flags & METHOD_ATTRIBUTE_ABSTRACT) &&
8135                            !(m->iflags & METHOD_IMPL_ATTRIBUTE_RUNTIME)) {
8136                 MonoMethodHeader *header;
8137                 guint32 code_size;
8138                 gint32 max_stack, i;
8139                 gint32 num_locals = 0;
8140                 gint32 num_clauses = 0;
8141                 guint8 *code;
8142
8143                 if (rmb->ilgen) {
8144                         code = mono_array_addr (rmb->ilgen->code, guint8, 0);
8145                         code_size = rmb->ilgen->code_len;
8146                         max_stack = rmb->ilgen->max_stack;
8147                         num_locals = rmb->ilgen->locals ? mono_array_length (rmb->ilgen->locals) : 0;
8148                         if (rmb->ilgen->ex_handlers)
8149                                 num_clauses = method_count_clauses (rmb->ilgen);
8150                 } else {
8151                         if (rmb->code) {
8152                                 code = mono_array_addr (rmb->code, guint8, 0);
8153                                 code_size = mono_array_length (rmb->code);
8154                                 /* we probably need to run a verifier on the code... */
8155                                 max_stack = 8; 
8156                         }
8157                         else {
8158                                 code = NULL;
8159                                 code_size = 0;
8160                                 max_stack = 8;
8161                         }
8162                 }
8163
8164                 header = g_malloc0 (sizeof (MonoMethodHeader) + 
8165                         (num_locals - MONO_ZERO_LEN_ARRAY) * sizeof (MonoType*));
8166                 header->code_size = code_size;
8167                 header->code = g_malloc (code_size);
8168                 memcpy ((char*)header->code, code, code_size);
8169                 header->max_stack = max_stack;
8170                 header->init_locals = rmb->init_locals;
8171                 header->num_locals = num_locals;
8172
8173                 for (i = 0; i < num_locals; ++i) {
8174                         MonoReflectionLocalBuilder *lb = 
8175                                 mono_array_get (rmb->ilgen->locals, MonoReflectionLocalBuilder*, i);
8176
8177                         header->locals [i] = g_new0 (MonoType, 1);
8178                         memcpy (header->locals [i], lb->type->type, sizeof (MonoType));
8179                 }
8180
8181                 header->num_clauses = num_clauses;
8182                 if (num_clauses) {
8183                         header->clauses = method_encode_clauses ((MonoDynamicImage*)klass->image,
8184                                  rmb->ilgen, num_clauses);
8185                 }
8186
8187                 pm->header = header;
8188         }
8189
8190         if (rmb->generic_params) {
8191                 int count = mono_array_length (rmb->generic_params);
8192                 MonoGenericContainer *container;
8193
8194                 pm->generic_container = container = rmb->generic_container;
8195                 container->type_argc = count;
8196                 container->type_params = g_new0 (MonoGenericParam, count);
8197
8198                 for (i = 0; i < count; i++) {
8199                         MonoReflectionGenericParam *gp =
8200                                 mono_array_get (rmb->generic_params, MonoReflectionGenericParam*, i);
8201
8202                         container->type_params [i] = *gp->type.type->data.generic_param;
8203                 }
8204         }
8205
8206         if (rmb->refs) {
8207                 MonoMethodWrapper *mw = (MonoMethodWrapper*)m;
8208                 int i;
8209                 void **data;
8210
8211                 m->wrapper_type = MONO_WRAPPER_DYNAMIC_METHOD;
8212
8213                 mw->method_data = data = g_new (gpointer, rmb->nrefs + 1);
8214                 data [0] = GUINT_TO_POINTER (rmb->nrefs);
8215                 for (i = 0; i < rmb->nrefs; ++i)
8216                         data [i + 1] = rmb->refs [i];
8217         }
8218
8219         method_aux = NULL;
8220
8221         /* Parameter info */
8222         if (rmb->pinfo) {
8223                 if (!method_aux)
8224                         method_aux = g_new0 (MonoReflectionMethodAux, 1);
8225                 method_aux->param_names = g_new0 (char *, mono_method_signature (m)->param_count + 1);
8226                 for (i = 0; i <= m->signature->param_count; ++i) {
8227                         MonoReflectionParamBuilder *pb;
8228                         if ((pb = mono_array_get (rmb->pinfo, MonoReflectionParamBuilder*, i))) {
8229                                 if ((i > 0) && (pb->attrs)) {
8230                                         /* Make a copy since it might point to a shared type structure */
8231                                         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)));
8232                                         m->signature->params [i - 1]->attrs = pb->attrs;
8233                                 }
8234
8235                                 if (pb->def_value) {
8236                                         MonoDynamicImage *assembly;
8237                                         guint32 idx, def_type, len;
8238                                         char *p;
8239                                         const char *p2;
8240
8241                                         if (!method_aux->param_defaults) {
8242                                                 method_aux->param_defaults = g_new0 (guint8*, m->signature->param_count + 1);
8243                                                 method_aux->param_default_types = g_new0 (guint32, m->signature->param_count + 1);
8244                                         }
8245                                         assembly = (MonoDynamicImage*)klass->image;
8246                                         idx = encode_constant (assembly, pb->def_value, &def_type);
8247                                         /* Copy the data from the blob since it might get realloc-ed */
8248                                         p = assembly->blob.data + idx;
8249                                         len = mono_metadata_decode_blob_size (p, &p2);
8250                                         len += p2 - p;
8251                                         method_aux->param_defaults [i] = g_malloc (len);
8252                                         method_aux->param_default_types [i] = def_type;
8253                                         memcpy ((gpointer)method_aux->param_defaults [i], p, len);
8254                                 }
8255
8256                                 if (pb->name)
8257                                         method_aux->param_names [i] = mono_string_to_utf8 (pb->name);
8258                                 if (pb->cattrs) {
8259                                         if (!method_aux->param_cattr)
8260                                                 method_aux->param_cattr = g_new0 (MonoCustomAttrInfo*, m->signature->param_count + 1);
8261                                         method_aux->param_cattr [i] = mono_custom_attrs_from_builders (klass->image, pb->cattrs);
8262                                 }
8263                         }
8264                 }
8265         }
8266
8267         /* Parameter marshalling */
8268         specs = NULL;
8269         if (rmb->pinfo)         
8270                 for (i = 0; i < mono_array_length (rmb->pinfo); ++i) {
8271                         MonoReflectionParamBuilder *pb;
8272                         if ((pb = mono_array_get (rmb->pinfo, MonoReflectionParamBuilder*, i))) {
8273                                 if (pb->marshal_info) {
8274                                         if (specs == NULL)
8275                                                 specs = g_new0 (MonoMarshalSpec*, sig->param_count + 1);
8276                                         specs [pb->position] = 
8277                                                 mono_marshal_spec_from_builder (klass->image->assembly, pb->marshal_info);
8278                                 }
8279                         }
8280                 }
8281         if (specs != NULL) {
8282                 if (!method_aux)
8283                         method_aux = g_new0 (MonoReflectionMethodAux, 1);
8284                 method_aux->param_marshall = specs;
8285         }
8286
8287         if (klass->image->dynamic && method_aux)
8288                 g_hash_table_insert (((MonoDynamicImage*)klass->image)->method_aux_hash, m, method_aux);
8289
8290         return m;
8291 }       
8292
8293 static MonoMethod*
8294 ctorbuilder_to_mono_method (MonoClass *klass, MonoReflectionCtorBuilder* mb)
8295 {
8296         ReflectionMethodBuilder rmb;
8297         MonoMethodSignature *sig;
8298
8299         sig = ctor_builder_to_signature (mb);
8300
8301         reflection_methodbuilder_from_ctor_builder (&rmb, mb);
8302
8303         mb->mhandle = reflection_methodbuilder_to_mono_method (klass, &rmb, sig);
8304         mono_save_custom_attrs (klass->image, mb->mhandle, mb->cattrs);
8305
8306         if (!((MonoDynamicImage*)(MonoDynamicImage*)klass->image)->save) {
8307                 /* ilgen is no longer needed */
8308                 mb->ilgen = NULL;
8309         }
8310
8311         return mb->mhandle;
8312 }
8313
8314 static MonoMethod*
8315 methodbuilder_to_mono_method (MonoClass *klass, MonoReflectionMethodBuilder* mb)
8316 {
8317         ReflectionMethodBuilder rmb;
8318         MonoMethodSignature *sig;
8319
8320         sig = method_builder_to_signature (mb);
8321
8322         reflection_methodbuilder_from_method_builder (&rmb, mb);
8323
8324         mb->mhandle = reflection_methodbuilder_to_mono_method (klass, &rmb, sig);
8325         mono_save_custom_attrs (klass->image, mb->mhandle, mb->cattrs);
8326
8327         if (!((MonoDynamicImage*)(MonoDynamicImage*)klass->image)->save) {
8328                 /* ilgen is no longer needed */
8329                 mb->ilgen = NULL;
8330         }
8331         return mb->mhandle;
8332 }
8333
8334 static MonoClassField*
8335 fieldbuilder_to_mono_class_field (MonoClass *klass, MonoReflectionFieldBuilder* fb)
8336 {
8337         MonoClassField *field;
8338         const char *p, *p2;
8339         guint32 len, idx;
8340
8341         if (fb->handle)
8342                 return fb->handle;
8343
8344         field = g_new0 (MonoClassField, 1);
8345
8346         field->name = mono_string_to_utf8 (fb->name);
8347         if (fb->attrs) {
8348                 /* FIXME: handle type modifiers */
8349                 field->type = g_memdup (fb->type->type, sizeof (MonoType));
8350                 field->type->attrs = fb->attrs;
8351         } else {
8352                 field->type = fb->type->type;
8353         }
8354         if ((fb->attrs & FIELD_ATTRIBUTE_HAS_FIELD_RVA) && fb->rva_data)
8355                 field->data = mono_array_addr (fb->rva_data, char, 0);
8356         if (fb->offset != -1)
8357                 field->offset = fb->offset;
8358         field->parent = klass;
8359         fb->handle = field;
8360         mono_save_custom_attrs (klass->image, field, fb->cattrs);
8361
8362         if (fb->def_value) {
8363                 MonoDynamicImage *assembly = (MonoDynamicImage*)klass->image;
8364                 field->type->attrs |= FIELD_ATTRIBUTE_HAS_DEFAULT;
8365                 idx = encode_constant (assembly, fb->def_value, &field->def_type);
8366                 /* Copy the data from the blob since it might get realloc-ed */
8367                 p = assembly->blob.data + idx;
8368                 len = mono_metadata_decode_blob_size (p, &p2);
8369                 len += p2 - p;
8370                 field->data = g_malloc (len);
8371                 memcpy ((gpointer)field->data, p, len);
8372         }
8373
8374         return field;
8375 }
8376
8377 static MonoType*
8378 do_mono_reflection_bind_generic_parameters (MonoReflectionType *type, int type_argc, MonoType **types,
8379                                             MonoType *parent)
8380 {
8381         MonoClass *klass;
8382         MonoReflectionTypeBuilder *tb = NULL;
8383         MonoGenericClass *gclass, *cached;
8384         MonoInflatedGenericClass *igclass;
8385         MonoDynamicGenericClass *dgclass = NULL;
8386         gboolean is_dynamic = FALSE;
8387         MonoDomain *domain;
8388         MonoType *geninst;
8389         int icount, i;
8390
8391         klass = mono_class_from_mono_type (type->type);
8392         if (!klass->generic_container && !klass->generic_class &&
8393             !(klass->nested_in && klass->nested_in->generic_container))
8394                 return NULL;
8395
8396         mono_loader_lock ();
8397
8398         domain = mono_object_domain (type);
8399
8400         if (!strcmp (((MonoObject *) type)->vtable->klass->name, "TypeBuilder")) {
8401                 tb = (MonoReflectionTypeBuilder *) type;
8402
8403                 icount = tb->interfaces ? mono_array_length (tb->interfaces) : 0;
8404                 is_dynamic = TRUE;
8405         } else if (!strcmp (((MonoObject *) type)->vtable->klass->name, "MonoGenericClass")) {
8406                 MonoReflectionGenericClass *rgi = (MonoReflectionGenericClass *) type;
8407                 MonoReflectionType *rgt = rgi->generic_type;
8408
8409                 g_assert (!strcmp (((MonoObject *) rgt)->vtable->klass->name, "TypeBuilder"));
8410                 tb = (MonoReflectionTypeBuilder *) rgt;
8411
8412                 icount = tb->interfaces ? mono_array_length (tb->interfaces) : 0;
8413                 is_dynamic = TRUE;
8414         } else {
8415                 icount = klass->interface_count;
8416         }
8417
8418         if (is_dynamic) {
8419                 dgclass = g_new0 (MonoDynamicGenericClass, 1);
8420                 igclass = &dgclass->generic_class;
8421                 gclass = &igclass->generic_class;
8422                 gclass->is_dynamic = TRUE;
8423                 gclass->is_inflated = TRUE;
8424         } else {
8425                 igclass = g_new0 (MonoInflatedGenericClass, 1);
8426                 gclass = &igclass->generic_class;
8427                 gclass->is_inflated = TRUE;
8428         }
8429
8430         gclass->inst = g_new0 (MonoGenericInst, 1);
8431
8432         gclass->inst->type_argc = type_argc;
8433         gclass->inst->type_argv = types;
8434         gclass->inst->is_reference = 1;
8435
8436         for (i = 0; i < gclass->inst->type_argc; ++i) {
8437                 if (!gclass->inst->is_open)
8438                         gclass->inst->is_open = mono_class_is_open_constructed_type (types [i]);
8439                 if (gclass->inst->is_reference)
8440                         gclass->inst->is_reference = MONO_TYPE_IS_REFERENCE (types [i]);
8441         }
8442
8443         gclass->container_class = klass;
8444
8445         if (klass->generic_class) {
8446                 MonoGenericClass *kgclass = klass->generic_class;
8447                 MonoGenericClass *ogclass = gclass;
8448
8449                 ogclass->context = g_new0 (MonoGenericContext, 1);
8450                 ogclass->context->container = gclass->container_class->generic_container;
8451                 ogclass->context->gclass = gclass;
8452
8453                 if (is_dynamic) {
8454                         dgclass = g_new0 (MonoDynamicGenericClass, 1);
8455                         igclass = &dgclass->generic_class;
8456                         gclass = &igclass->generic_class;
8457                         gclass->is_dynamic = TRUE;
8458                         gclass->is_inflated = TRUE;
8459                 } else {
8460                         igclass = g_new0 (MonoInflatedGenericClass, 1);
8461                         gclass = &igclass->generic_class;
8462                         gclass->is_inflated = TRUE;
8463                 }
8464
8465                 gclass->inst = g_new0 (MonoGenericInst, 1);
8466
8467                 gclass->inst->type_argc = kgclass->inst->type_argc;
8468                 gclass->inst->type_argv = g_new0 (MonoType *, gclass->inst->type_argc);
8469                 gclass->inst->is_reference = 1;
8470
8471                 for (i = 0; i < gclass->inst->type_argc; i++) {
8472                         MonoType *t = kgclass->inst->type_argv [i];
8473
8474                         t = mono_class_inflate_generic_type (t, ogclass->context);
8475
8476                         if (!gclass->inst->is_open)
8477                                 gclass->inst->is_open = mono_class_is_open_constructed_type (t);
8478                         if (gclass->inst->is_reference)
8479                                 gclass->inst->is_reference = MONO_TYPE_IS_REFERENCE (t);
8480
8481                         gclass->inst->type_argv [i] = t;
8482                 }
8483
8484                 gclass->container_class = kgclass->container_class;
8485         }
8486
8487         geninst = g_new0 (MonoType, 1);
8488         geninst->type = MONO_TYPE_GENERICINST;
8489
8490         cached = mono_metadata_lookup_generic_class (gclass);
8491         if (cached) {
8492                 g_free (gclass);
8493                 mono_loader_unlock ();
8494                 geninst->data.generic_class = cached;
8495                 return geninst;
8496         }
8497
8498         geninst->data.generic_class = gclass;
8499
8500         igclass->parent = parent;
8501
8502         gclass->context = g_new0 (MonoGenericContext, 1);
8503         gclass->context->container = gclass->container_class->generic_container;
8504         gclass->context->gclass = gclass;
8505
8506         if (is_dynamic) {
8507                 dgclass->ifaces = g_new0 (MonoType *, icount);
8508                 dgclass->count_ifaces = icount;
8509
8510                 for (i = 0; i < icount; i++) {
8511                         MonoReflectionType *itype;
8512
8513                         if (tb)
8514                                 itype = mono_array_get (tb->interfaces, MonoReflectionType *, i);
8515                         else
8516                                 itype = mono_type_get_object (domain, &klass->interfaces [i]->byval_arg);
8517                         dgclass->ifaces [i] = mono_reflection_bind_generic_parameters (itype, type_argc, types);
8518                         if (!dgclass->ifaces [i])
8519                                 dgclass->ifaces [i] = itype->type;
8520                 }
8521         }
8522
8523         mono_loader_unlock ();
8524
8525         return geninst;
8526 }
8527
8528 MonoType*
8529 mono_reflection_bind_generic_parameters (MonoReflectionType *type, int type_argc, MonoType **types)
8530 {
8531         MonoClass *klass, *pklass = NULL;
8532         MonoReflectionType *parent = NULL;
8533         MonoType *the_parent = NULL, *geninst;
8534         MonoReflectionTypeBuilder *tb = NULL;
8535         MonoGenericClass *gclass;
8536         MonoDomain *domain;
8537
8538         domain = mono_object_domain (type);
8539         klass = mono_class_from_mono_type (type->type);
8540
8541         if (!strcmp (((MonoObject *) type)->vtable->klass->name, "TypeBuilder")) {
8542                 tb = (MonoReflectionTypeBuilder *) type;
8543
8544                 if (tb->parent) {
8545                         parent = tb->parent;
8546                         pklass = mono_class_from_mono_type (parent->type);
8547                 }
8548         } else {
8549                 pklass = klass->parent;
8550                 if (pklass)
8551                         parent = mono_type_get_object (domain, &pklass->byval_arg);
8552                 else if (klass->generic_class) {
8553                         MonoInflatedGenericClass *igclass;
8554                         igclass = mono_get_inflated_generic_class (klass->generic_class);
8555                         if (igclass->parent) {
8556                                 parent = mono_type_get_object (domain, igclass->parent);
8557                                 pklass = mono_class_from_mono_type (igclass->parent);
8558                         }
8559                 }
8560         }
8561
8562         if (pklass && pklass->generic_class)
8563                 the_parent = mono_reflection_bind_generic_parameters (parent, type_argc, types);
8564
8565         geninst = do_mono_reflection_bind_generic_parameters (type, type_argc, types, the_parent);
8566         if (!geninst)
8567                 return NULL;
8568
8569         gclass = geninst->data.generic_class;
8570
8571         return geninst;
8572 }
8573
8574 static MonoType*
8575 do_mono_class_bind_generic_parameters (MonoType *type, int type_argc, MonoType **types, MonoType *parent)
8576 {
8577         MonoClass *klass;
8578         MonoGenericClass *gclass, *cached;
8579         MonoInflatedGenericClass *igclass;
8580         MonoType *geninst;
8581         int icount, i;
8582
8583         klass = mono_class_from_mono_type (type);
8584         if (!klass->generic_container && !klass->generic_class &&
8585             !(klass->nested_in && klass->nested_in->generic_container))
8586                 return NULL;
8587
8588         mono_loader_lock ();
8589
8590         icount = klass->interface_count;
8591
8592         igclass = g_new0 (MonoInflatedGenericClass, 1);
8593         gclass = &igclass->generic_class;
8594         gclass->is_inflated = TRUE;
8595
8596         gclass->inst = g_new0 (MonoGenericInst, 1);
8597         gclass->inst->type_argc = type_argc;
8598         gclass->inst->type_argv = types;
8599         gclass->inst->is_reference = 1;
8600
8601         for (i = 0; i < gclass->inst->type_argc; ++i) {
8602                 if (!gclass->inst->is_open)
8603                         gclass->inst->is_open = mono_class_is_open_constructed_type (types [i]);
8604                 if (gclass->inst->is_reference)
8605                         gclass->inst->is_reference = MONO_TYPE_IS_REFERENCE (types [i]);
8606         }
8607
8608         gclass->container_class = klass;
8609
8610         if (klass->generic_class) {
8611                 MonoGenericClass *kgclass = klass->generic_class;
8612                 MonoGenericClass *ogclass = gclass;
8613
8614                 gclass->context = g_new0 (MonoGenericContext, 1);
8615                 gclass->context->container = gclass->container_class->generic_container;
8616                 gclass->context->gclass = gclass;
8617
8618                 igclass = g_new0 (MonoInflatedGenericClass, 1);
8619                 gclass = &igclass->generic_class;
8620                 gclass->is_inflated = TRUE;
8621
8622                 gclass->inst = g_new0 (MonoGenericInst, 1);
8623                 gclass->inst->type_argc = kgclass->inst->type_argc;
8624                 gclass->inst->type_argv = g_new0 (MonoType *, gclass->inst->type_argc);
8625                 gclass->inst->is_reference = 1;
8626
8627                 for (i = 0; i < gclass->inst->type_argc; i++) {
8628                         MonoType *t = kgclass->inst->type_argv [i];
8629
8630                         t = mono_class_inflate_generic_type (t, ogclass->context);
8631
8632                         if (!gclass->inst->is_open)
8633                                 gclass->inst->is_open = mono_class_is_open_constructed_type (t);
8634                         if (gclass->inst->is_reference)
8635                                 gclass->inst->is_reference = MONO_TYPE_IS_REFERENCE (t);
8636
8637                         gclass->inst->type_argv [i] = t;
8638                 }
8639
8640                 gclass->container_class = kgclass->container_class;
8641         }
8642
8643         geninst = g_new0 (MonoType, 1);
8644         geninst->type = MONO_TYPE_GENERICINST;
8645
8646         cached = mono_metadata_lookup_generic_class (gclass);
8647         if (cached) {
8648                 g_free (gclass);
8649                 mono_loader_unlock ();
8650                 geninst->data.generic_class = cached;
8651                 return geninst;
8652         }
8653
8654         geninst->data.generic_class = gclass;
8655
8656         igclass->parent = parent;
8657
8658         gclass->context = g_new0 (MonoGenericContext, 1);
8659         gclass->context->container = gclass->container_class->generic_container;
8660         gclass->context->gclass = gclass;
8661
8662         mono_loader_unlock ();
8663
8664         return geninst;
8665 }
8666
8667 MonoType*
8668 mono_class_bind_generic_parameters (MonoType *type, int type_argc, MonoType **types)
8669 {
8670         MonoClass *klass, *pklass = NULL;
8671         MonoType *parent = NULL, *the_parent = NULL, *geninst;
8672         MonoGenericClass *gclass;
8673
8674         klass = mono_class_from_mono_type (type);
8675
8676         pklass = klass->parent;
8677         if (pklass)
8678                 parent = &pklass->byval_arg;
8679         else if (klass->generic_class) {
8680                 MonoInflatedGenericClass *igclass;
8681                 igclass = mono_get_inflated_generic_class (klass->generic_class);
8682                 if (igclass->parent) {
8683                         parent = igclass->parent;
8684                         pklass = mono_class_from_mono_type (igclass->parent);
8685                 }
8686         }
8687
8688         if (pklass && pklass->generic_class)
8689                 the_parent = mono_class_bind_generic_parameters (parent, type_argc, types);
8690
8691         geninst = do_mono_class_bind_generic_parameters (type, type_argc, types, the_parent);
8692         if (!geninst)
8693                 return NULL;
8694
8695         gclass = geninst->data.generic_class;
8696
8697         return geninst;
8698 }
8699
8700 static inline MonoType*
8701 dup_type (const MonoType *original)
8702 {
8703         MonoType *r = g_new0 (MonoType, 1);
8704         *r = *original;
8705         r->attrs = original->attrs;
8706         r->byref = original->byref;
8707         if (original->type == MONO_TYPE_PTR)
8708                 r->data.type = dup_type (original->data.type);
8709         mono_stats.generics_metadata_size += sizeof (MonoType);
8710         return r;
8711 }
8712
8713 MonoReflectionMethod*
8714 mono_reflection_bind_generic_method_parameters (MonoReflectionMethod *rmethod, MonoArray *types)
8715 {
8716         MonoMethod *method, *inflated;
8717         MonoReflectionMethodBuilder *mb = NULL;
8718         MonoGenericContainer *container;
8719         MonoGenericMethod *gmethod;
8720         MonoGenericContext *context;
8721         MonoGenericInst *ginst;
8722         int count, i;
8723
8724         MONO_ARCH_SAVE_REGS;
8725         if (!strcmp (rmethod->object.vtable->klass->name, "MethodBuilder")) {
8726                 MonoReflectionTypeBuilder *tb;
8727                 MonoClass *klass;
8728
8729                 mb = (MonoReflectionMethodBuilder *) rmethod;
8730                 tb = (MonoReflectionTypeBuilder *) mb->type;
8731                 klass = mono_class_from_mono_type (tb->type.type);
8732
8733                 method = methodbuilder_to_mono_method (klass, mb);
8734         } else {
8735                 method = rmethod->method;
8736         }
8737
8738         method = mono_get_inflated_method (method);
8739
8740         count = mono_method_signature (method)->generic_param_count;
8741         if (count != mono_array_length (types))
8742                 return NULL;
8743
8744         container = ((MonoMethodNormal*) method)->generic_container;
8745         g_assert (container);
8746
8747         if (!container->method_hash)
8748                 container->method_hash = g_hash_table_new (
8749                         (GHashFunc) mono_metadata_generic_method_hash,
8750                         (GCompareFunc) mono_metadata_generic_method_equal);
8751
8752         ginst = g_new0 (MonoGenericInst,1 );
8753         ginst->type_argc = count;
8754         ginst->type_argv = g_new0 (MonoType *, count);
8755         ginst->is_reference = 1;
8756         for (i = 0; i < count; i++) {
8757                 MonoReflectionType *garg = mono_array_get (types, gpointer, i);
8758                 ginst->type_argv [i] = dup_type (garg->type);
8759
8760                 if (!ginst->is_open)
8761                         ginst->is_open = mono_class_is_open_constructed_type (ginst->type_argv [i]);
8762                 if (ginst->is_reference)
8763                         ginst->is_reference = MONO_TYPE_IS_REFERENCE (ginst->type_argv [i]);
8764         }
8765         ginst = mono_metadata_lookup_generic_inst (ginst);
8766
8767         gmethod = g_new0 (MonoGenericMethod, 1);
8768         gmethod->generic_class = method->klass->generic_class;
8769         gmethod->container = container;
8770         gmethod->inst = ginst;
8771
8772         inflated = g_hash_table_lookup (container->method_hash, gmethod);
8773         if (inflated) {
8774                 g_free (gmethod);
8775
8776                 return mono_method_get_object (mono_object_domain (rmethod), inflated, NULL);
8777         }
8778
8779         gmethod->reflection_info = rmethod;
8780
8781         context = g_new0 (MonoGenericContext, 1);
8782         context->container = container;
8783         context->gclass = method->klass->generic_class;
8784         context->gmethod = gmethod;
8785
8786         if (method->is_inflated)
8787                 method = ((MonoMethodInflated *) method)->declaring;
8788
8789         inflated = mono_class_inflate_generic_method (method, context);
8790         g_hash_table_insert (container->method_hash, gmethod, inflated);
8791
8792         return mono_method_get_object (mono_object_domain (rmethod), inflated, NULL);
8793 }
8794
8795 static MonoMethod *
8796 inflate_mono_method (MonoReflectionGenericClass *type, MonoMethod *method, MonoObject *obj)
8797 {
8798         MonoGenericMethod *gmethod;
8799         MonoInflatedGenericClass *gclass;
8800         MonoGenericContext *context;
8801         int i;
8802
8803         gclass = mono_get_inflated_generic_class (type->type.type->data.generic_class);
8804
8805         gmethod = g_new0 (MonoGenericMethod, 1);
8806         gmethod->generic_class = &gclass->generic_class;
8807         gmethod->inst = g_new0 (MonoGenericInst, 1);
8808         gmethod->reflection_info = obj;
8809
8810         gmethod->inst->type_argc = mono_method_signature (method)->generic_param_count;
8811         gmethod->inst->type_argv = g_new0 (MonoType *, gmethod->inst->type_argc);
8812
8813         for (i = 0; i < gmethod->inst->type_argc; i++) {
8814                 MonoMethodNormal *mn = (MonoMethodNormal *) method;
8815                 MonoGenericParam *gparam = &mn->generic_container->type_params [i];
8816
8817                 g_assert (gparam->pklass);
8818                 gmethod->inst->type_argv [i] = &gparam->pklass->byval_arg;
8819         }
8820
8821         context = g_new0 (MonoGenericContext, 1);
8822         context->container = gclass->generic_class.container_class->generic_container;
8823         context->gclass = &gclass->generic_class;
8824         context->gmethod = gmethod;
8825
8826         return mono_class_inflate_generic_method (method, context);
8827 }
8828
8829 static MonoMethod *
8830 inflate_method (MonoReflectionGenericClass *type, MonoObject *obj)
8831 {
8832         MonoMethod *method;
8833         MonoClass *klass;
8834
8835         klass = mono_class_from_mono_type (type->type.type);
8836
8837         if (!strcmp (obj->vtable->klass->name, "MethodBuilder"))
8838                 method = methodbuilder_to_mono_method (klass, (MonoReflectionMethodBuilder *) obj);
8839         else if (!strcmp (obj->vtable->klass->name, "ConstructorBuilder"))
8840                 method = ctorbuilder_to_mono_method (klass, (MonoReflectionCtorBuilder *) obj);
8841         else if (!strcmp (obj->vtable->klass->name, "MonoMethod") || !strcmp (obj->vtable->klass->name, "MonoCMethod"))
8842                 method = ((MonoReflectionMethod *) obj)->method;
8843         else {
8844                 method = NULL; /* prevent compiler warning */
8845                 g_assert_not_reached ();
8846         }
8847
8848         return inflate_mono_method (type, method, obj);
8849 }
8850
8851 void
8852 mono_reflection_generic_class_initialize (MonoReflectionGenericClass *type, MonoArray *methods, 
8853                                           MonoArray *ctors, MonoArray *fields, MonoArray *properties,
8854                                           MonoArray *events)
8855 {
8856         MonoGenericClass *gclass;
8857         MonoDynamicGenericClass *dgclass;
8858         MonoClass *klass, *gklass, *pklass;
8859         int i;
8860
8861         MONO_ARCH_SAVE_REGS;
8862
8863         klass = mono_class_from_mono_type (type->type.type);
8864         gclass = type->type.type->data.generic_class;
8865
8866         g_assert (gclass->is_dynamic);
8867         dgclass = (MonoDynamicGenericClass *) gclass;
8868
8869         if (dgclass->initialized)
8870                 return;
8871
8872         gklass = gclass->container_class;
8873         mono_class_init (gklass);
8874
8875         if (dgclass->generic_class.parent)
8876                 pklass = mono_class_from_mono_type (dgclass->generic_class.parent);
8877         else
8878                 pklass = gklass->parent;
8879
8880         dgclass->count_methods = methods ? mono_array_length (methods) : 0;
8881         dgclass->count_ctors = ctors ? mono_array_length (ctors) : 0;
8882         dgclass->count_fields = fields ? mono_array_length (fields) : 0;
8883         dgclass->count_properties = properties ? mono_array_length (properties) : 0;
8884         dgclass->count_events = events ? mono_array_length (events) : 0;
8885
8886         dgclass->methods = g_new0 (MonoMethod *, dgclass->count_methods);
8887         dgclass->ctors = g_new0 (MonoMethod *, dgclass->count_ctors);
8888         dgclass->fields = g_new0 (MonoClassField, dgclass->count_fields);
8889         dgclass->properties = g_new0 (MonoProperty, dgclass->count_properties);
8890         dgclass->events = g_new0 (MonoEvent, dgclass->count_events);
8891
8892         for (i = 0; i < dgclass->count_methods; i++) {
8893                 MonoObject *obj = mono_array_get (methods, gpointer, i);
8894
8895                 dgclass->methods [i] = inflate_method (type, obj);
8896         }
8897
8898         for (i = 0; i < dgclass->count_ctors; i++) {
8899                 MonoObject *obj = mono_array_get (ctors, gpointer, i);
8900
8901                 dgclass->ctors [i] = inflate_method (type, obj);
8902         }
8903
8904         for (i = 0; i < dgclass->count_fields; i++) {
8905                 MonoObject *obj = mono_array_get (fields, gpointer, i);
8906                 MonoClassField *field;
8907                 MonoInflatedField *ifield;
8908
8909                 if (!strcmp (obj->vtable->klass->name, "FieldBuilder"))
8910                         field = fieldbuilder_to_mono_class_field (klass, (MonoReflectionFieldBuilder *) obj);
8911                 else if (!strcmp (obj->vtable->klass->name, "MonoField"))
8912                         field = ((MonoReflectionField *) obj)->field;
8913                 else {
8914                         field = NULL; /* prevent compiler warning */
8915                         g_assert_not_reached ();
8916                 }
8917
8918                 ifield = g_new0 (MonoInflatedField, 1);
8919                 ifield->generic_type = field->type;
8920                 ifield->reflection_info = obj;
8921
8922                 dgclass->fields [i] = *field;
8923                 dgclass->fields [i].parent = klass;
8924                 dgclass->fields [i].generic_info = ifield;
8925                 dgclass->fields [i].type = mono_class_inflate_generic_type (
8926                         field->type, dgclass->generic_class.generic_class.context);
8927         }
8928
8929         for (i = 0; i < dgclass->count_properties; i++) {
8930                 MonoObject *obj = mono_array_get (properties, gpointer, i);
8931                 MonoProperty *property = &dgclass->properties [i];
8932
8933                 if (!strcmp (obj->vtable->klass->name, "PropertyBuilder")) {
8934                         MonoReflectionPropertyBuilder *pb = (MonoReflectionPropertyBuilder *) obj;
8935
8936                         property->parent = klass;
8937                         property->attrs = pb->attrs;
8938                         property->name = mono_string_to_utf8 (pb->name);
8939                         if (pb->get_method)
8940                                 property->get = inflate_method (type, (MonoObject *) pb->get_method);
8941                         if (pb->set_method)
8942                                 property->set = inflate_method (type, (MonoObject *) pb->set_method);
8943                 } else if (!strcmp (obj->vtable->klass->name, "MonoProperty")) {
8944                         *property = *((MonoReflectionProperty *) obj)->property;
8945
8946                         if (property->get)
8947                                 property->get = inflate_mono_method (type, property->get, NULL);
8948                         if (property->set)
8949                                 property->set = inflate_mono_method (type, property->set, NULL);
8950                 } else
8951                         g_assert_not_reached ();
8952         }
8953
8954         for (i = 0; i < dgclass->count_events; i++) {
8955                 MonoObject *obj = mono_array_get (events, gpointer, i);
8956                 MonoEvent *event = &dgclass->events [i];
8957
8958                 if (!strcmp (obj->vtable->klass->name, "EventBuilder")) {
8959                         MonoReflectionEventBuilder *eb = (MonoReflectionEventBuilder *) obj;
8960
8961                         event->parent = klass;
8962                         event->attrs = eb->attrs;
8963                         event->name = mono_string_to_utf8 (eb->name);
8964                         if (eb->add_method)
8965                                 event->add = inflate_method (type, (MonoObject *) eb->add_method);
8966                         if (eb->remove_method)
8967                                 event->remove = inflate_method (type, (MonoObject *) eb->remove_method);
8968                 } else if (!strcmp (obj->vtable->klass->name, "MonoEvent")) {
8969                         *event = *((MonoReflectionEvent *) obj)->event;
8970
8971                         if (event->add)
8972                                 event->add = inflate_mono_method (type, event->add, NULL);
8973                         if (event->remove)
8974                                 event->remove = inflate_mono_method (type, event->remove, NULL);
8975                 } else
8976                         g_assert_not_reached ();
8977         }
8978
8979         dgclass->initialized = TRUE;
8980 }
8981
8982 static void
8983 ensure_runtime_vtable (MonoClass *klass)
8984 {
8985         MonoReflectionTypeBuilder *tb = klass->reflection_info;
8986         int i, num, j, onum;
8987         MonoMethod **overrides;
8988
8989         if (!tb || klass->wastypebuilder)
8990                 return;
8991         if (klass->parent)
8992                 ensure_runtime_vtable (klass->parent);
8993
8994         num = tb->ctors? mono_array_length (tb->ctors): 0;
8995         num += tb->num_methods;
8996         klass->method.count = num;
8997         klass->methods = g_new (MonoMethod*, num);
8998         num = tb->ctors? mono_array_length (tb->ctors): 0;
8999         for (i = 0; i < num; ++i)
9000                 klass->methods [i] = ctorbuilder_to_mono_method (klass, mono_array_get (tb->ctors, MonoReflectionCtorBuilder*, i));
9001         num = tb->num_methods;
9002         j = i;
9003         for (i = 0; i < num; ++i)
9004                 klass->methods [j++] = methodbuilder_to_mono_method (klass, mono_array_get (tb->methods, MonoReflectionMethodBuilder*, i));
9005
9006         if (tb->interfaces) {
9007                 klass->interface_count = mono_array_length (tb->interfaces);
9008                 klass->interfaces = g_new (MonoClass*, klass->interface_count);
9009                 for (i = 0; i < klass->interface_count; ++i) {
9010                         MonoReflectionType *iface = mono_array_get (tb->interfaces, gpointer, i);
9011                         klass->interfaces [i] = mono_class_from_mono_type (iface->type);
9012                 }
9013         }
9014
9015         if (klass->flags & TYPE_ATTRIBUTE_INTERFACE)
9016                 for (i = 0; i < klass->method.count; ++i)
9017                         klass->methods [i]->slot = i;
9018
9019         if (!((MonoDynamicImage*)klass->image)->run)
9020                 /* No need to create a generic vtable */
9021                 return;
9022
9023         /* Overrides */
9024         onum = 0;
9025         if (tb->methods) {
9026                 for (i = 0; i < tb->num_methods; ++i) {
9027                         MonoReflectionMethodBuilder *mb = 
9028                                 mono_array_get (tb->methods, MonoReflectionMethodBuilder*, i);
9029                         if (mb->override_method)
9030                                 onum ++;
9031                 }
9032         }
9033
9034         overrides = g_new0 (MonoMethod*, onum * 2);
9035
9036         if (tb->methods) {
9037                 onum = 0;
9038                 for (i = 0; i < tb->num_methods; ++i) {
9039                         MonoReflectionMethodBuilder *mb = 
9040                                 mono_array_get (tb->methods, MonoReflectionMethodBuilder*, i);
9041                         if (mb->override_method) {
9042                                 /* FIXME: What if 'override_method' is a MethodBuilder ? */
9043                                 overrides [onum * 2] = 
9044                                         mb->override_method->method;
9045                                 overrides [onum * 2 + 1] =
9046                                         mb->mhandle;
9047
9048                                 g_assert (mb->mhandle);
9049
9050                                 onum ++;
9051                         }
9052                 }
9053         }
9054
9055         mono_class_setup_vtable_general (klass, overrides, onum);
9056         g_free (overrides);
9057 }
9058
9059 static void
9060 typebuilder_setup_fields (MonoClass *klass)
9061 {
9062         MonoReflectionTypeBuilder *tb = klass->reflection_info;
9063         MonoReflectionFieldBuilder *fb;
9064         MonoClassField *field;
9065         const char *p, *p2;
9066         int i;
9067         guint32 len, idx;
9068
9069         klass->field.count = tb->num_fields;
9070         klass->field.first = 0;
9071         klass->field.last = klass->field.count;
9072
9073         if (!klass->field.count)
9074                 return;
9075         
9076         klass->fields = g_new0 (MonoClassField, klass->field.count);
9077
9078         for (i = 0; i < klass->field.count; ++i) {
9079                 fb = mono_array_get (tb->fields, gpointer, i);
9080                 field = &klass->fields [i];
9081                 field->name = mono_string_to_utf8 (fb->name);
9082                 if (fb->attrs) {
9083                         /* FIXME: handle type modifiers */
9084                         field->type = g_memdup (fb->type->type, sizeof (MonoType));
9085                         field->type->attrs = fb->attrs;
9086                 } else {
9087                         field->type = fb->type->type;
9088                 }
9089                 if ((fb->attrs & FIELD_ATTRIBUTE_HAS_FIELD_RVA) && fb->rva_data)
9090                         field->data = mono_array_addr (fb->rva_data, char, 0);
9091                 if (fb->offset != -1)
9092                         field->offset = fb->offset;
9093                 field->parent = klass;
9094                 fb->handle = field;
9095                 mono_save_custom_attrs (klass->image, field, fb->cattrs);
9096
9097                 if (fb->def_value) {
9098                         MonoDynamicImage *assembly = (MonoDynamicImage*)klass->image;
9099                         field->type->attrs |= FIELD_ATTRIBUTE_HAS_DEFAULT;
9100                         idx = encode_constant (assembly, fb->def_value, &field->def_type);
9101                         /* Copy the data from the blob since it might get realloc-ed */
9102                         p = assembly->blob.data + idx;
9103                         len = mono_metadata_decode_blob_size (p, &p2);
9104                         len += p2 - p;
9105                         field->data = g_malloc (len);
9106                         memcpy ((gpointer)field->data, p, len);
9107                 }
9108         }
9109         mono_class_layout_fields (klass);
9110 }
9111
9112 static void
9113 typebuilder_setup_properties (MonoClass *klass)
9114 {
9115         MonoReflectionTypeBuilder *tb = klass->reflection_info;
9116         MonoReflectionPropertyBuilder *pb;
9117         int i;
9118
9119         klass->property.count = tb->properties ? mono_array_length (tb->properties) : 0;
9120         klass->property.first = 0;
9121         klass->property.last = klass->property.count;
9122
9123         klass->properties = g_new0 (MonoProperty, klass->property.count);
9124         for (i = 0; i < klass->property.count; ++i) {
9125                 pb = mono_array_get (tb->properties, MonoReflectionPropertyBuilder*, i);
9126                 klass->properties [i].parent = klass;
9127                 klass->properties [i].attrs = pb->attrs;
9128                 klass->properties [i].name = mono_string_to_utf8 (pb->name);
9129                 if (pb->get_method)
9130                         klass->properties [i].get = pb->get_method->mhandle;
9131                 if (pb->set_method)
9132                         klass->properties [i].set = pb->set_method->mhandle;
9133         }
9134 }
9135
9136 MonoReflectionEvent *
9137 mono_reflection_event_builder_get_event_info (MonoReflectionTypeBuilder *tb, MonoReflectionEventBuilder *eb)
9138 {
9139         MonoEvent *event = g_new0 (MonoEvent, 1);
9140         MonoClass *klass;
9141         int j;
9142
9143         klass = my_mono_class_from_mono_type (tb->type.type);
9144
9145         event->parent = klass;
9146         event->attrs = eb->attrs;
9147         event->name = mono_string_to_utf8 (eb->name);
9148         if (eb->add_method)
9149                 event->add = eb->add_method->mhandle;
9150         if (eb->remove_method)
9151                 event->remove = eb->remove_method->mhandle;
9152         if (eb->raise_method)
9153                 event->raise = eb->raise_method->mhandle;
9154
9155         if (eb->other_methods) {
9156                 event->other = g_new0 (MonoMethod*, mono_array_length (eb->other_methods) + 1);
9157                 for (j = 0; j < mono_array_length (eb->other_methods); ++j) {
9158                         MonoReflectionMethodBuilder *mb = 
9159                                 mono_array_get (eb->other_methods,
9160                                                 MonoReflectionMethodBuilder*, j);
9161                         event->other [j] = mb->mhandle;
9162                 }
9163         }
9164
9165         return mono_event_get_object (mono_object_domain (tb), klass, event);
9166 }
9167
9168 static void
9169 typebuilder_setup_events (MonoClass *klass)
9170 {
9171         MonoReflectionTypeBuilder *tb = klass->reflection_info;
9172         MonoReflectionEventBuilder *eb;
9173         int i, j;
9174
9175         klass->event.count = tb->events ? mono_array_length (tb->events) : 0;
9176         klass->event.first = 0;
9177         klass->event.last = klass->event.count;
9178
9179         klass->events = g_new0 (MonoEvent, klass->event.count);
9180         for (i = 0; i < klass->event.count; ++i) {
9181                 eb = mono_array_get (tb->events, MonoReflectionEventBuilder*, i);
9182                 klass->events [i].parent = klass;
9183                 klass->events [i].attrs = eb->attrs;
9184                 klass->events [i].name = mono_string_to_utf8 (eb->name);
9185                 if (eb->add_method)
9186                         klass->events [i].add = eb->add_method->mhandle;
9187                 if (eb->remove_method)
9188                         klass->events [i].remove = eb->remove_method->mhandle;
9189                 if (eb->raise_method)
9190                         klass->events [i].raise = eb->raise_method->mhandle;
9191
9192                 if (eb->other_methods) {
9193                         klass->events [i].other = g_new0 (MonoMethod*, mono_array_length (eb->other_methods) + 1);
9194                         for (j = 0; j < mono_array_length (eb->other_methods); ++j) {
9195                                 MonoReflectionMethodBuilder *mb = 
9196                                         mono_array_get (eb->other_methods,
9197                                                                         MonoReflectionMethodBuilder*, j);
9198                                 klass->events [i].other [j] = mb->mhandle;
9199                         }
9200                 }
9201         }
9202 }
9203
9204 MonoReflectionType*
9205 mono_reflection_create_runtime_class (MonoReflectionTypeBuilder *tb)
9206 {
9207         MonoClass *klass;
9208         MonoDomain* domain;
9209         MonoReflectionType* res;
9210         int i;
9211
9212         MONO_ARCH_SAVE_REGS;
9213
9214         domain = mono_object_domain (tb);
9215         klass = my_mono_class_from_mono_type (tb->type.type);
9216
9217         mono_save_custom_attrs (klass->image, klass, tb->cattrs);
9218         
9219         /* 
9220          * we need to lock the domain because the lock will be taken inside
9221          * So, we need to keep the locking order correct.
9222          */
9223         mono_domain_lock (domain);
9224         mono_loader_lock ();
9225         if (klass->wastypebuilder) {
9226                 mono_loader_unlock ();
9227                 mono_domain_unlock (domain);
9228                 return mono_type_get_object (mono_object_domain (tb), &klass->byval_arg);
9229         }
9230         /*
9231          * Fields to set in klass:
9232          * the various flags: delegate/unicode/contextbound etc.
9233          */
9234         klass->flags = tb->attrs;
9235         klass->has_cctor = 1;
9236         klass->has_finalize = 1;
9237
9238         if (!((MonoDynamicImage*)klass->image)->run) {
9239                 if (klass->generic_container) {
9240                         /* FIXME: The code below can't handle generic classes */
9241                         klass->wastypebuilder = TRUE;
9242                         mono_loader_unlock ();
9243                         mono_domain_unlock (domain);
9244                         return mono_type_get_object (mono_object_domain (tb), &klass->byval_arg);
9245                 }
9246         }
9247
9248         /* enums are done right away */
9249         if (!klass->enumtype)
9250                 ensure_runtime_vtable (klass);
9251
9252         if (tb->subtypes) {
9253                 for (i = 0; i < mono_array_length (tb->subtypes); ++i) {
9254                         MonoReflectionTypeBuilder *subtb = mono_array_get (tb->subtypes, MonoReflectionTypeBuilder*, i);
9255                         klass->nested_classes = g_list_prepend (klass->nested_classes, my_mono_class_from_mono_type (subtb->type.type));
9256                 }
9257         }
9258
9259         /* fields and object layout */
9260         if (klass->parent) {
9261                 if (!klass->parent->size_inited)
9262                         mono_class_init (klass->parent);
9263                 klass->instance_size += klass->parent->instance_size;
9264                 klass->class_size += klass->parent->class_size;
9265                 klass->min_align = klass->parent->min_align;
9266                 /* if the type has no fields we won't call the field_setup
9267                  * routine which sets up klass->has_references.
9268                  */
9269                 klass->has_references |= klass->parent->has_references;
9270         } else {
9271                 klass->instance_size = sizeof (MonoObject);
9272                 klass->min_align = 1;
9273         }
9274
9275         /* FIXME: handle packing_size and instance_size */
9276         typebuilder_setup_fields (klass);
9277
9278         typebuilder_setup_properties (klass);
9279
9280         typebuilder_setup_events (klass);
9281
9282         klass->wastypebuilder = TRUE;
9283         mono_loader_unlock ();
9284         mono_domain_unlock (domain);
9285
9286         res = mono_type_get_object (mono_object_domain (tb), &klass->byval_arg);
9287         g_assert (res != (MonoReflectionType*)tb);
9288         return res;
9289 }
9290
9291 void
9292 mono_reflection_initialize_generic_parameter (MonoReflectionGenericParam *gparam)
9293 {
9294         MonoGenericParam *param;
9295         MonoImage *image;
9296
9297         MONO_ARCH_SAVE_REGS;
9298
9299         param = g_new0 (MonoGenericParam, 1);
9300
9301         if (gparam->mbuilder) {
9302                 if (!gparam->mbuilder->generic_container)
9303                         gparam->mbuilder->generic_container = g_new0 (MonoGenericContainer, 1);
9304                 param->owner = gparam->mbuilder->generic_container;
9305         } else if (gparam->tbuilder) {
9306                 MonoReflectionTypeBuilder *nesting = (MonoReflectionTypeBuilder*) gparam->tbuilder->nesting_type;
9307                 MonoGenericContainer *container = gparam->tbuilder->generic_container;
9308
9309                 while (nesting) {
9310                         int count;
9311
9312                         count = nesting->generic_params ? mono_array_length (nesting->generic_params) : 0;
9313                         if (gparam->index >= count)
9314                                 break;
9315
9316                         container = nesting->generic_container;
9317                         nesting = (MonoReflectionTypeBuilder*) nesting->nesting_type;
9318                 }
9319
9320                 g_assert (container);
9321                 param->owner = container;
9322         }
9323
9324         param->method = NULL;
9325         param->name = mono_string_to_utf8 (gparam->name);
9326         param->num = gparam->index;
9327
9328         image = &gparam->tbuilder->module->dynamic_image->image;
9329         mono_class_from_generic_parameter (param, image, gparam->mbuilder != NULL);
9330
9331         param->pklass->reflection_info = gparam;
9332
9333         gparam->type.type = g_new0 (MonoType, 1);
9334         gparam->type.type->type = gparam->mbuilder ? MONO_TYPE_MVAR : MONO_TYPE_VAR;
9335         gparam->type.type->attrs = TYPE_ATTRIBUTE_PUBLIC;
9336         gparam->type.type->data.generic_param = param;
9337 }
9338
9339 MonoArray *
9340 mono_reflection_sighelper_get_signature_local (MonoReflectionSigHelper *sig)
9341 {
9342         MonoDynamicImage *assembly = sig->module->dynamic_image;
9343         guint32 na = mono_array_length (sig->arguments);
9344         guint32 buflen, i, size;
9345         MonoArray *result;
9346         char *buf, *p;
9347
9348         MONO_ARCH_SAVE_REGS;
9349
9350         p = buf = g_malloc (size = 10 + na * 10);
9351
9352         mono_metadata_encode_value (0x07, p, &p);
9353         mono_metadata_encode_value (na, p, &p);
9354         for (i = 0; i < na; ++i) {
9355                 MonoReflectionType *type = mono_array_get (sig->arguments, MonoReflectionType *, i);
9356                 encode_reflection_type (assembly, type, p, &p);
9357         }
9358
9359         buflen = p - buf;
9360         g_assert (buflen < size);
9361         result = mono_array_new (mono_domain_get (), mono_defaults.byte_class, buflen);
9362         p = mono_array_addr (result, char, 0);
9363         memcpy (p, buf, buflen);
9364         g_free (buf);
9365
9366         return result;
9367 }
9368
9369 MonoArray *
9370 mono_reflection_sighelper_get_signature_field (MonoReflectionSigHelper *sig)
9371 {
9372         MonoDynamicImage *assembly = sig->module->dynamic_image;
9373         guint32 na = mono_array_length (sig->arguments);
9374         guint32 buflen, i, size;
9375         MonoArray *result;
9376         char *buf, *p;
9377
9378         MONO_ARCH_SAVE_REGS;
9379
9380         p = buf = g_malloc (size = 10 + na * 10);
9381
9382         mono_metadata_encode_value (0x06, p, &p);
9383         for (i = 0; i < na; ++i) {
9384                 MonoReflectionType *type = mono_array_get (sig->arguments, MonoReflectionType *, i);
9385                 encode_reflection_type (assembly, type, p, &p);
9386         }
9387
9388         buflen = p - buf;
9389         g_assert (buflen < size);
9390         result = mono_array_new (mono_domain_get (), mono_defaults.byte_class, buflen);
9391         p = mono_array_addr (result, char, 0);
9392         memcpy (p, buf, buflen);
9393         g_free (buf);
9394
9395         return result;
9396 }
9397
9398 void 
9399 mono_reflection_create_dynamic_method (MonoReflectionDynamicMethod *mb)
9400 {
9401         ReflectionMethodBuilder rmb;
9402         MonoMethodSignature *sig;
9403         int i;
9404
9405         sig = dynamic_method_to_signature (mb);
9406
9407         reflection_methodbuilder_from_dynamic_method (&rmb, mb);
9408
9409         /*
9410          * Resolve references.
9411          */
9412         rmb.nrefs = mb->nrefs;
9413         rmb.refs = g_new0 (gpointer, mb->nrefs + 1);
9414         for (i = 0; i < mb->nrefs; ++i) {
9415                 MonoClass *handle_class;
9416                 gpointer ref = resolve_object (mb->module->image, 
9417                                                mono_array_get (mb->refs, MonoObject*, i), &handle_class);
9418                 if (!ref) {
9419                         g_free (rmb.refs);
9420                         mono_raise_exception (mono_get_exception_type_load (NULL));
9421                         return;
9422                 }
9423                 rmb.refs [i] = ref;
9424         }               
9425
9426         /* FIXME: class */
9427         mb->mhandle = reflection_methodbuilder_to_mono_method (mono_defaults.object_class, &rmb, sig);
9428
9429         g_free (rmb.refs);
9430
9431         /* ilgen is no longer needed */
9432         mb->ilgen = NULL;
9433 }
9434
9435 /**
9436  * mono_reflection_lookup_dynamic_token:
9437  *
9438  * Finish the Builder object pointed to by TOKEN and return the corresponding
9439  * runtime structure. HANDLE_CLASS is set to the class required by 
9440  * mono_ldtoken.
9441  */
9442 gpointer
9443 mono_reflection_lookup_dynamic_token (MonoImage *image, guint32 token, MonoClass **handle_class)
9444 {
9445         MonoDynamicImage *assembly = (MonoDynamicImage*)image;
9446         MonoObject *obj;
9447
9448         obj = mono_g_hash_table_lookup (assembly->tokens, GUINT_TO_POINTER (token));
9449         g_assert (obj);
9450
9451         return resolve_object (image, obj, handle_class);
9452 }
9453
9454 static gpointer
9455 resolve_object (MonoImage *image, MonoObject *obj, MonoClass **handle_class)
9456 {
9457         gpointer result = NULL;
9458
9459         if (strcmp (obj->vtable->klass->name, "String") == 0) {
9460                 result = mono_string_intern ((MonoString*)obj);
9461                 *handle_class = NULL;
9462                 g_assert (result);
9463         } else if (strcmp (obj->vtable->klass->name, "MonoType") == 0) {
9464                 MonoReflectionType *tb = (MonoReflectionType*)obj;
9465                 result = mono_class_from_mono_type (tb->type);
9466                 *handle_class = mono_defaults.typehandle_class;
9467                 g_assert (result);
9468         } else if (strcmp (obj->vtable->klass->name, "MonoMethod") == 0) {
9469                 result = ((MonoReflectionMethod*)obj)->method;
9470                 *handle_class = mono_defaults.methodhandle_class;
9471                 g_assert (result);
9472         } else if (strcmp (obj->vtable->klass->name, "MonoCMethod") == 0) {
9473                 result = ((MonoReflectionMethod*)obj)->method;
9474                 *handle_class = mono_defaults.methodhandle_class;
9475                 g_assert (result);
9476         } else if (strcmp (obj->vtable->klass->name, "MethodBuilder") == 0) {
9477                 MonoReflectionMethodBuilder *mb = (MonoReflectionMethodBuilder*)obj;
9478                 result = mb->mhandle;
9479                 if (!result) {
9480                         /* Type is not yet created */
9481                         MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder*)mb->type;
9482
9483                         mono_domain_try_type_resolve (mono_domain_get (), NULL, (MonoObject*)tb);
9484
9485                         /*
9486                          * Hopefully this has been filled in by calling CreateType() on the
9487                          * TypeBuilder.
9488                          */
9489                         /*
9490                          * TODO: This won't work if the application finishes another 
9491                          * TypeBuilder instance instead of this one.
9492                          */
9493                         result = mb->mhandle;
9494                 }
9495                 *handle_class = mono_defaults.methodhandle_class;
9496         } else if (strcmp (obj->vtable->klass->name, "ConstructorBuilder") == 0) {
9497                 MonoReflectionCtorBuilder *cb = (MonoReflectionCtorBuilder*)obj;
9498
9499                 result = cb->mhandle;
9500                 if (!result) {
9501                         MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder*)cb->type;
9502
9503                         mono_domain_try_type_resolve (mono_domain_get (), NULL, (MonoObject*)tb);
9504                         result = cb->mhandle;
9505                 }
9506                 *handle_class = mono_defaults.methodhandle_class;
9507         } else if (strcmp (obj->vtable->klass->name, "MonoField") == 0) {
9508                 result = ((MonoReflectionField*)obj)->field;
9509                 *handle_class = mono_defaults.fieldhandle_class;
9510                 g_assert (result);
9511         } else if (strcmp (obj->vtable->klass->name, "FieldBuilder") == 0) {
9512                 MonoReflectionFieldBuilder *fb = (MonoReflectionFieldBuilder*)obj;
9513                 result = fb->handle;
9514
9515                 if (!result) {
9516                         MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder*)fb->typeb;
9517
9518                         mono_domain_try_type_resolve (mono_domain_get (), NULL, (MonoObject*)tb);
9519                         result = fb->handle;
9520                 }
9521                 *handle_class = mono_defaults.fieldhandle_class;
9522         } else if (strcmp (obj->vtable->klass->name, "TypeBuilder") == 0) {
9523                 MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder*)obj;
9524                 MonoClass *klass;
9525
9526                 klass = tb->type.type->data.klass;
9527                 if (klass->wastypebuilder) {
9528                         /* Already created */
9529                         result = klass;
9530                 }
9531                 else {
9532                         mono_domain_try_type_resolve (mono_domain_get (), NULL, (MonoObject*)tb);
9533                         result = tb->type.type->data.klass;
9534                         g_assert (result);
9535                 }
9536                 *handle_class = mono_defaults.typehandle_class;
9537         } else if (strcmp (obj->vtable->klass->name, "SignatureHelper") == 0) {
9538                 MonoReflectionSigHelper *helper = (MonoReflectionSigHelper*)obj;
9539                 MonoMethodSignature *sig;
9540                 int nargs, i;
9541
9542                 if (helper->arguments)
9543                         nargs = mono_array_length (helper->arguments);
9544                 else
9545                         nargs = 0;
9546
9547                 sig = mono_metadata_signature_alloc (image, nargs);
9548                 sig->explicit_this = helper->call_conv & 64 ? 1 : 0;
9549                 sig->hasthis = helper->call_conv & 32 ? 1 : 0;
9550
9551                 if (helper->call_conv == 0) /* unmanaged */
9552                         sig->call_convention = helper->unmanaged_call_conv - 1;
9553                 else
9554                         if (helper->call_conv & 0x02)
9555                                 sig->call_convention = MONO_CALL_VARARG;
9556                 else
9557                         sig->call_convention = MONO_CALL_DEFAULT;
9558
9559                 sig->param_count = nargs;
9560                 /* TODO: Copy type ? */
9561                 sig->ret = helper->return_type->type;
9562                 for (i = 0; i < nargs; ++i) {
9563                         MonoReflectionType *rt = mono_array_get (helper->arguments, MonoReflectionType*, i);
9564                         sig->params [i] = rt->type;
9565                 }
9566
9567                 result = sig;
9568                 *handle_class = NULL;
9569         } else {
9570                 g_print (obj->vtable->klass->name);
9571                 g_assert_not_reached ();
9572         }
9573         return result;
9574 }
9575
9576
9577 /* SECURITY_ACTION_* are defined in mono/metadata/tabledefs.h */
9578 const static guint32 declsec_flags_map[] = {
9579         0x00000000,                                     /* empty */
9580         MONO_DECLSEC_FLAG_REQUEST,                      /* SECURITY_ACTION_REQUEST                      (x01) */
9581         MONO_DECLSEC_FLAG_DEMAND,                       /* SECURITY_ACTION_DEMAND                       (x02) */
9582         MONO_DECLSEC_FLAG_ASSERT,                       /* SECURITY_ACTION_ASSERT                       (x03) */
9583         MONO_DECLSEC_FLAG_DENY,                         /* SECURITY_ACTION_DENY                         (x04) */
9584         MONO_DECLSEC_FLAG_PERMITONLY,                   /* SECURITY_ACTION_PERMITONLY                   (x05) */
9585         MONO_DECLSEC_FLAG_LINKDEMAND,                   /* SECURITY_ACTION_LINKDEMAND                   (x06) */
9586         MONO_DECLSEC_FLAG_INHERITANCEDEMAND,            /* SECURITY_ACTION_INHERITANCEDEMAND            (x07) */
9587         MONO_DECLSEC_FLAG_REQUEST_MINIMUM,              /* SECURITY_ACTION_REQUEST_MINIMUM              (x08) */
9588         MONO_DECLSEC_FLAG_REQUEST_OPTIONAL,             /* SECURITY_ACTION_REQUEST_OPTIONAL             (x09) */
9589         MONO_DECLSEC_FLAG_REQUEST_REFUSE,               /* SECURITY_ACTION_REQUEST_REFUSE               (x0A) */
9590         MONO_DECLSEC_FLAG_PREJIT_GRANT,                 /* SECURITY_ACTION_PREJIT_GRANT                 (x0B) */
9591         MONO_DECLSEC_FLAG_PREJIT_DENY,                  /* SECURITY_ACTION_PREJIT_DENY                  (x0C) */
9592         MONO_DECLSEC_FLAG_NONCAS_DEMAND,                /* SECURITY_ACTION_NONCAS_DEMAND                (x0D) */
9593         MONO_DECLSEC_FLAG_NONCAS_LINKDEMAND,            /* SECURITY_ACTION_NONCAS_LINKDEMAND            (x0E) */
9594         MONO_DECLSEC_FLAG_NONCAS_INHERITANCEDEMAND,     /* SECURITY_ACTION_NONCAS_INHERITANCEDEMAND     (x0F) */
9595         MONO_DECLSEC_FLAG_LINKDEMAND_CHOICE,            /* SECURITY_ACTION_LINKDEMAND_CHOICE            (x10) */
9596         MONO_DECLSEC_FLAG_INHERITANCEDEMAND_CHOICE,     /* SECURITY_ACTION_INHERITANCEDEMAND_CHOICE     (x11) */
9597         MONO_DECLSEC_FLAG_DEMAND_CHOICE,                /* SECURITY_ACTION_DEMAND_CHOICE                (x12) */
9598 };
9599
9600 /*
9601  * Returns flags that includes all available security action associated to the handle.
9602  * @token: metadata token (either for a class or a method)
9603  * @image: image where resides the metadata.
9604  */
9605 static guint32
9606 mono_declsec_get_flags (MonoImage *image, guint32 token)
9607 {
9608         guint32 index = mono_metadata_declsec_from_index (image, token);
9609         MonoTableInfo *t = &image->tables [MONO_TABLE_DECLSECURITY];
9610         guint32 result = 0;
9611         guint32 action;
9612         int i;
9613
9614         for (i = index; i < t->rows; i++) {
9615                 guint32 cols [MONO_DECL_SECURITY_SIZE];
9616
9617                 mono_metadata_decode_row (t, i, cols, MONO_DECL_SECURITY_SIZE);
9618                 if (cols [MONO_DECL_SECURITY_PARENT] != token)
9619                         break;
9620
9621                 action = cols [MONO_DECL_SECURITY_ACTION];
9622                 if ((action >= MONO_DECLSEC_ACTION_MIN) && (action <= MONO_DECLSEC_ACTION_MAX)) {
9623                         result |= declsec_flags_map [action];
9624                 } else {
9625                         g_assert_not_reached ();
9626                 }
9627         }
9628         return result;
9629 }
9630
9631 /*
9632  * Get the security actions (in the form of flags) associated with the specified method.
9633  *
9634  * @method: The method for which we want the declarative security flags.
9635  * Return the declarative security flags for the method (only).
9636  *
9637  * Note: To keep MonoMethod size down we do not cache the declarative security flags
9638  *       (except for the stack modifiers which are kept in the MonoJitInfo structure)
9639  */
9640 guint32
9641 mono_declsec_flags_from_method (MonoMethod *method)
9642 {
9643         if (method->flags & METHOD_ATTRIBUTE_HAS_SECURITY) {
9644                 /* FIXME: No cache (for the moment) */
9645                 guint32 idx = mono_method_get_index (method);
9646                 idx <<= MONO_HAS_DECL_SECURITY_BITS;
9647                 idx |= MONO_HAS_DECL_SECURITY_METHODDEF;
9648                 return mono_declsec_get_flags (method->klass->image, idx);
9649         }
9650         return 0;
9651 }
9652
9653 /*
9654  * Get the security actions (in the form of flags) associated with the specified class.
9655  *
9656  * @klass: The class for which we want the declarative security flags.
9657  * Return the declarative security flags for the class.
9658  *
9659  * Note: We cache the flags inside the MonoClass structure as this will get 
9660  *       called very often (at least for each method).
9661  */
9662 guint32
9663 mono_declsec_flags_from_class (MonoClass *klass)
9664 {
9665         if (klass->flags & TYPE_ATTRIBUTE_HAS_SECURITY) {
9666                 if (!klass->declsec_flags) {
9667                         guint32 idx = mono_metadata_token_index (klass->type_token);
9668                         idx <<= MONO_HAS_DECL_SECURITY_BITS;
9669                         idx |= MONO_HAS_DECL_SECURITY_TYPEDEF;
9670                         /* we cache the flags on classes */
9671                         klass->declsec_flags = mono_declsec_get_flags (klass->image, idx);
9672                 }
9673                 return klass->declsec_flags;
9674         }
9675         return 0;
9676 }
9677
9678 /*
9679  * Get the security actions (in the form of flags) associated with the specified assembly.
9680  *
9681  * @assembly: The assembly for which we want the declarative security flags.
9682  * Return the declarative security flags for the assembly.
9683  */
9684 guint32
9685 mono_declsec_flags_from_assembly (MonoAssembly *assembly)
9686 {
9687         guint32 idx = 1; /* there is only one assembly */
9688         idx <<= MONO_HAS_DECL_SECURITY_BITS;
9689         idx |= MONO_HAS_DECL_SECURITY_ASSEMBLY;
9690         return mono_declsec_get_flags (assembly->image, idx);
9691 }
9692
9693
9694 /*
9695  * Fill actions for the specific index (which may either be an encoded class token or
9696  * an encoded method token) from the metadata image.
9697  * Returns TRUE if some actions requiring code generation are present, FALSE otherwise.
9698  */
9699 static MonoBoolean
9700 fill_actions_from_index (MonoImage *image, guint32 token, MonoDeclSecurityActions* actions,
9701         guint32 id_std, guint32 id_noncas, guint32 id_choice)
9702 {
9703         MonoBoolean result = FALSE;
9704         MonoTableInfo *t;
9705         guint32 cols [MONO_DECL_SECURITY_SIZE];
9706         int index = mono_metadata_declsec_from_index (image, token);
9707         int i;
9708
9709         t  = &image->tables [MONO_TABLE_DECLSECURITY];
9710         for (i = index; i < t->rows; i++) {
9711                 mono_metadata_decode_row (t, i, cols, MONO_DECL_SECURITY_SIZE);
9712
9713                 if (cols [MONO_DECL_SECURITY_PARENT] != token)
9714                         return result;
9715
9716                 /* if present only replace (class) permissions with method permissions */
9717                 /* if empty accept either class or method permissions */
9718                 if (cols [MONO_DECL_SECURITY_ACTION] == id_std) {
9719                         if (!actions->demand.blob) {
9720                                 const char *blob = mono_metadata_blob_heap (image, cols [MONO_DECL_SECURITY_PERMISSIONSET]);
9721                                 actions->demand.index = cols [MONO_DECL_SECURITY_PERMISSIONSET];
9722                                 actions->demand.blob = (char*) (blob + 2);
9723                                 actions->demand.size = mono_metadata_decode_blob_size (blob, &blob);
9724                                 result = TRUE;
9725                         }
9726                 } else if (cols [MONO_DECL_SECURITY_ACTION] == id_noncas) {
9727                         if (!actions->noncasdemand.blob) {
9728                                 const char *blob = mono_metadata_blob_heap (image, cols [MONO_DECL_SECURITY_PERMISSIONSET]);
9729                                 actions->noncasdemand.index = cols [MONO_DECL_SECURITY_PERMISSIONSET];
9730                                 actions->noncasdemand.blob = (char*) (blob + 2);
9731                                 actions->noncasdemand.size = mono_metadata_decode_blob_size (blob, &blob);
9732                                 result = TRUE;
9733                         }
9734                 } else if (cols [MONO_DECL_SECURITY_ACTION] == id_choice) {
9735                         if (!actions->demandchoice.blob) {
9736                                 const char *blob = mono_metadata_blob_heap (image, cols [MONO_DECL_SECURITY_PERMISSIONSET]);
9737                                 actions->demandchoice.index = cols [MONO_DECL_SECURITY_PERMISSIONSET];
9738                                 actions->demandchoice.blob = (char*) (blob + 2);
9739                                 actions->demandchoice.size = mono_metadata_decode_blob_size (blob, &blob);
9740                                 result = TRUE;
9741                         }
9742                 }
9743         }
9744
9745         return result;
9746 }
9747
9748 static MonoBoolean
9749 mono_declsec_get_class_demands_params (MonoClass *klass, MonoDeclSecurityActions* demands, 
9750         guint32 id_std, guint32 id_noncas, guint32 id_choice)
9751 {
9752         guint32 idx = mono_metadata_token_index (klass->type_token);
9753         idx <<= MONO_HAS_DECL_SECURITY_BITS;
9754         idx |= MONO_HAS_DECL_SECURITY_TYPEDEF;
9755         return fill_actions_from_index (klass->image, idx, demands, id_std, id_noncas, id_choice);
9756 }
9757
9758 static MonoBoolean
9759 mono_declsec_get_method_demands_params (MonoMethod *method, MonoDeclSecurityActions* demands, 
9760         guint32 id_std, guint32 id_noncas, guint32 id_choice)
9761 {
9762         guint32 idx = mono_method_get_index (method);
9763         idx <<= MONO_HAS_DECL_SECURITY_BITS;
9764         idx |= MONO_HAS_DECL_SECURITY_METHODDEF;
9765         return fill_actions_from_index (method->klass->image, idx, demands, id_std, id_noncas, id_choice);
9766 }
9767
9768 /*
9769  * Collect all actions (that requires to generate code in mini) assigned for
9770  * the specified method.
9771  * Note: Don't use the content of actions if the function return FALSE.
9772  */
9773 MonoBoolean
9774 mono_declsec_get_demands (MonoMethod *method, MonoDeclSecurityActions* demands)
9775 {
9776         guint32 mask = MONO_DECLSEC_FLAG_DEMAND | MONO_DECLSEC_FLAG_NONCAS_DEMAND | 
9777                 MONO_DECLSEC_FLAG_DEMAND_CHOICE;
9778         MonoBoolean result = FALSE;
9779         guint32 flags;
9780
9781         /* quick exit if no declarative security is present in the metadata */
9782         if (!method->klass->image->tables [MONO_TABLE_DECLSECURITY].rows)
9783                 return FALSE;
9784
9785         /* we want the original as the wrapper is "free" of the security informations */
9786         if (method->wrapper_type == MONO_WRAPPER_MANAGED_TO_NATIVE) {
9787                 method = mono_marshal_method_from_wrapper (method);
9788                 if (!method)
9789                         return FALSE;
9790         }
9791
9792         /* First we look for method-level attributes */
9793         if (method->flags & METHOD_ATTRIBUTE_HAS_SECURITY) {
9794                 mono_class_init (method->klass);
9795                 memset (demands, 0, sizeof (MonoDeclSecurityActions));
9796
9797                 result = mono_declsec_get_method_demands_params (method, demands, 
9798                         SECURITY_ACTION_DEMAND, SECURITY_ACTION_NONCASDEMAND, SECURITY_ACTION_DEMANDCHOICE);
9799         }
9800
9801         /* Here we use (or create) the class declarative cache to look for demands */
9802         flags = mono_declsec_flags_from_class (method->klass);
9803         if (flags & mask) {
9804                 if (!result) {
9805                         mono_class_init (method->klass);
9806                         memset (demands, 0, sizeof (MonoDeclSecurityActions));
9807                 }
9808                 result |= mono_declsec_get_class_demands_params (method->klass, demands, 
9809                         SECURITY_ACTION_DEMAND, SECURITY_ACTION_NONCASDEMAND, SECURITY_ACTION_DEMANDCHOICE);
9810         }
9811
9812         /* The boolean return value is used as a shortcut in case nothing needs to
9813            be generated (e.g. LinkDemand[Choice] and InheritanceDemand[Choice]) */
9814         return result;
9815 }
9816
9817
9818 /*
9819  * Collect all Link actions: LinkDemand, NonCasLinkDemand and LinkDemandChoice (2.0).
9820  *
9821  * Note: Don't use the content of actions if the function return FALSE.
9822  */
9823 MonoBoolean
9824 mono_declsec_get_linkdemands (MonoMethod *method, MonoDeclSecurityActions* klass, MonoDeclSecurityActions *cmethod)
9825 {
9826         MonoBoolean result = FALSE;
9827         guint32 flags;
9828
9829         /* quick exit if no declarative security is present in the metadata */
9830         if (!method->klass->image->tables [MONO_TABLE_DECLSECURITY].rows)
9831                 return FALSE;
9832
9833         /* we want the original as the wrapper is "free" of the security informations */
9834         if (method->wrapper_type == MONO_WRAPPER_MANAGED_TO_NATIVE) {
9835                 method = mono_marshal_method_from_wrapper (method);
9836                 if (!method)
9837                         return FALSE;
9838         }
9839
9840         /* results are independant - zeroize both */
9841         memset (cmethod, 0, sizeof (MonoDeclSecurityActions));
9842         memset (klass, 0, sizeof (MonoDeclSecurityActions));
9843
9844         /* First we look for method-level attributes */
9845         if (method->flags & METHOD_ATTRIBUTE_HAS_SECURITY) {
9846                 mono_class_init (method->klass);
9847
9848                 result = mono_declsec_get_method_demands_params (method, cmethod, 
9849                         SECURITY_ACTION_LINKDEMAND, SECURITY_ACTION_NONCASLINKDEMAND, SECURITY_ACTION_LINKDEMANDCHOICE);
9850         }
9851
9852         /* Here we use (or create) the class declarative cache to look for demands */
9853         flags = mono_declsec_flags_from_class (method->klass);
9854         if (flags & (MONO_DECLSEC_FLAG_LINKDEMAND | MONO_DECLSEC_FLAG_NONCAS_LINKDEMAND | MONO_DECLSEC_FLAG_LINKDEMAND_CHOICE)) {
9855                 mono_class_init (method->klass);
9856
9857                 result |= mono_declsec_get_class_demands_params (method->klass, klass, 
9858                         SECURITY_ACTION_LINKDEMAND, SECURITY_ACTION_NONCASLINKDEMAND, SECURITY_ACTION_LINKDEMANDCHOICE);
9859         }
9860
9861         return result;
9862 }
9863
9864 /*
9865  * Collect all Inherit actions: InheritanceDemand, NonCasInheritanceDemand and InheritanceDemandChoice (2.0).
9866  *
9867  * @klass       The inherited class - this is the class that provides the security check (attributes)
9868  * @demans      
9869  * return TRUE if inheritance demands (any kind) are present, FALSE otherwise.
9870  * 
9871  * Note: Don't use the content of actions if the function return FALSE.
9872  */
9873 MonoBoolean
9874 mono_declsec_get_inheritdemands_class (MonoClass *klass, MonoDeclSecurityActions* demands)
9875 {
9876         MonoBoolean result = FALSE;
9877         guint32 flags;
9878
9879         /* quick exit if no declarative security is present in the metadata */
9880         if (!klass->image->tables [MONO_TABLE_DECLSECURITY].rows)
9881                 return FALSE;
9882
9883         /* Here we use (or create) the class declarative cache to look for demands */
9884         flags = mono_declsec_flags_from_class (klass);
9885         if (flags & (MONO_DECLSEC_FLAG_INHERITANCEDEMAND | MONO_DECLSEC_FLAG_NONCAS_INHERITANCEDEMAND | MONO_DECLSEC_FLAG_INHERITANCEDEMAND_CHOICE)) {
9886                 mono_class_init (klass);
9887                 memset (demands, 0, sizeof (MonoDeclSecurityActions));
9888
9889                 result |= mono_declsec_get_class_demands_params (klass, demands, 
9890                         SECURITY_ACTION_INHERITDEMAND, SECURITY_ACTION_NONCASINHERITANCE, SECURITY_ACTION_INHERITDEMANDCHOICE);
9891         }
9892
9893         return result;
9894 }
9895
9896 /*
9897  * Collect all Inherit actions: InheritanceDemand, NonCasInheritanceDemand and InheritanceDemandChoice (2.0).
9898  *
9899  * Note: Don't use the content of actions if the function return FALSE.
9900  */
9901 MonoBoolean
9902 mono_declsec_get_inheritdemands_method (MonoMethod *method, MonoDeclSecurityActions* demands)
9903 {
9904         /* quick exit if no declarative security is present in the metadata */
9905         if (!method->klass->image->tables [MONO_TABLE_DECLSECURITY].rows)
9906                 return FALSE;
9907
9908         /* we want the original as the wrapper is "free" of the security informations */
9909         if (method->wrapper_type == MONO_WRAPPER_MANAGED_TO_NATIVE) {
9910                 method = mono_marshal_method_from_wrapper (method);
9911                 if (!method)
9912                         return FALSE;
9913         }
9914
9915         if (method->flags & METHOD_ATTRIBUTE_HAS_SECURITY) {
9916                 mono_class_init (method->klass);
9917                 memset (demands, 0, sizeof (MonoDeclSecurityActions));
9918
9919                 return mono_declsec_get_method_demands_params (method, demands, 
9920                         SECURITY_ACTION_INHERITDEMAND, SECURITY_ACTION_NONCASINHERITANCE, SECURITY_ACTION_INHERITDEMANDCHOICE);
9921         }
9922         return FALSE;
9923 }
9924
9925
9926 static MonoBoolean
9927 get_declsec_action (MonoImage *image, guint32 token, guint32 action, MonoDeclSecurityEntry *entry)
9928 {
9929         guint32 cols [MONO_DECL_SECURITY_SIZE];
9930         MonoTableInfo *t;
9931         int i;
9932
9933         int index = mono_metadata_declsec_from_index (image, token);
9934         if (index == -1)
9935                 return FALSE;
9936
9937         t =  &image->tables [MONO_TABLE_DECLSECURITY];
9938         for (i = index; i < t->rows; i++) {
9939                 mono_metadata_decode_row (t, i, cols, MONO_DECL_SECURITY_SIZE);
9940
9941                 /* shortcut - index are ordered */
9942                 if (token != cols [MONO_DECL_SECURITY_PARENT])
9943                         return FALSE;
9944
9945                 if (cols [MONO_DECL_SECURITY_ACTION] == action) {
9946                         const char *metadata = mono_metadata_blob_heap (image, cols [MONO_DECL_SECURITY_PERMISSIONSET]);
9947                         entry->blob = (char*) (metadata + 2);
9948                         entry->size = mono_metadata_decode_blob_size (metadata, &metadata);
9949                         return TRUE;
9950                 }
9951         }
9952
9953         return FALSE;
9954 }
9955
9956 MonoBoolean
9957 mono_declsec_get_method_action (MonoMethod *method, guint32 action, MonoDeclSecurityEntry *entry)
9958 {
9959         if (method->flags & METHOD_ATTRIBUTE_HAS_SECURITY) {
9960                 guint32 idx = mono_method_get_index (method);
9961                 idx <<= MONO_HAS_DECL_SECURITY_BITS;
9962                 idx |= MONO_HAS_DECL_SECURITY_METHODDEF;
9963                 return get_declsec_action (method->klass->image, idx, action, entry);
9964         }
9965         return FALSE;
9966 }
9967
9968 MonoBoolean
9969 mono_declsec_get_class_action (MonoClass *klass, guint32 action, MonoDeclSecurityEntry *entry)
9970 {
9971         /* use cache */
9972         guint32 flags = mono_declsec_flags_from_class (klass);
9973         if (declsec_flags_map [action] & flags) {
9974                 guint32 idx = mono_metadata_token_index (klass->type_token);
9975                 idx <<= MONO_HAS_DECL_SECURITY_BITS;
9976                 idx |= MONO_HAS_DECL_SECURITY_TYPEDEF;
9977                 return get_declsec_action (klass->image, idx, action, entry);
9978         }
9979         return FALSE;
9980 }
9981
9982 MonoBoolean
9983 mono_declsec_get_assembly_action (MonoAssembly *assembly, guint32 action, MonoDeclSecurityEntry *entry)
9984 {
9985         guint32 idx = 1; /* there is only one assembly */
9986         idx <<= MONO_HAS_DECL_SECURITY_BITS;
9987         idx |= MONO_HAS_DECL_SECURITY_ASSEMBLY;
9988
9989         return get_declsec_action (assembly->image, idx, action, entry);
9990 }
9991
9992 gboolean
9993 mono_reflection_call_is_assignable_to (MonoClass *klass, MonoClass *oklass)
9994 {
9995         MonoObject *res, *exc;
9996         void *params [1];
9997         static MonoClass *System_Reflection_Emit_TypeBuilder = NULL;
9998         static MonoMethod *method = NULL;
9999
10000         if (!System_Reflection_Emit_TypeBuilder) {
10001                 System_Reflection_Emit_TypeBuilder = mono_class_from_name (mono_defaults.corlib, "System.Reflection.Emit", "TypeBuilder");
10002                 g_assert (System_Reflection_Emit_TypeBuilder);
10003         }
10004         if (method == NULL) {
10005                 method = mono_class_get_method_from_name (System_Reflection_Emit_TypeBuilder, "IsAssignableTo", 1);
10006                 g_assert (method);
10007         }
10008
10009         /* 
10010          * The result of mono_type_get_object () might be a System.MonoType but we
10011          * need a TypeBuilder so use klass->reflection_info.
10012          */
10013         g_assert (klass->reflection_info);
10014         g_assert (!strcmp (((MonoObject*)(klass->reflection_info))->vtable->klass->name, "TypeBuilder"));
10015
10016         params [0] = mono_type_get_object (mono_domain_get (), &oklass->byval_arg);
10017
10018         res = mono_runtime_invoke (method, (MonoObject*)(klass->reflection_info), params, &exc);
10019         if (exc)
10020                 return FALSE;
10021         else
10022                 return *(MonoBoolean*)mono_object_unbox (res);
10023 }