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