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