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