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