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