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