renamed to be consistent
[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 (mono_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                 mono_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->generic_type, 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->generic_type);
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         mono_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 = rmb->charset & 0xf;
1317                 rmb->lasterr = rmb->charset & 0x40;
1318                 rmb->native_cc = rmb->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         mono_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->signature->is_inflated);
2466         imethod = (MonoMethodInflated *) method;
2467         declaring = imethod->declaring;
2468
2469         sig = method_encode_signature (assembly, declaring->signature);
2470         mtoken = mono_image_get_memberref_token (assembly, &method->klass->byval_arg, declaring->name, sig);
2471
2472         if (!declaring->signature->generic_param_count)
2473                 return mtoken;
2474
2475         switch (mono_metadata_token_table (mtoken)) {
2476         case MONO_TABLE_MEMBERREF:
2477                 mtoken = (mono_metadata_token_index (mtoken) << MONO_METHODDEFORREF_BITS) | MONO_METHODDEFORREF_METHODREF;
2478                 break;
2479         case MONO_TABLE_METHOD:
2480                 mtoken = (mono_metadata_token_index (mtoken) << MONO_METHODDEFORREF_BITS) | MONO_METHODDEFORREF_METHODDEF;
2481                 break;
2482         default:
2483                 g_assert_not_reached ();
2484         }
2485
2486         sig = encode_generic_method_sig (assembly, imethod->context->gmethod);
2487
2488         if (assembly->save) {
2489                 alloc_table (table, table->rows + 1);
2490                 values = table->values + table->next_idx * MONO_METHODSPEC_SIZE;
2491                 values [MONO_METHODSPEC_METHOD] = mtoken;
2492                 values [MONO_METHODSPEC_SIGNATURE] = sig;
2493         }
2494
2495         token = MONO_TOKEN_METHOD_SPEC | table->next_idx;
2496         table->next_idx ++;
2497
2498         return token;
2499 }
2500
2501 static guint32
2502 mono_image_get_methodspec_token (MonoDynamicImage *assembly, MonoMethod *m)
2503 {
2504         MonoMethodInflated *imethod;
2505         guint32 token;
2506         
2507         token = GPOINTER_TO_UINT (g_hash_table_lookup (assembly->handleref, m));
2508         if (token)
2509                 return token;
2510
2511         g_assert (m->signature->is_inflated);
2512         imethod = (MonoMethodInflated *) m;
2513
2514         if (imethod->declaring->signature->generic_param_count) {
2515                 token = method_encode_methodspec (assembly, m);
2516         } else {
2517                 guint32 sig = method_encode_signature (
2518                         assembly, imethod->declaring->signature);
2519                 token = mono_image_get_memberref_token (
2520                         assembly, &m->klass->byval_arg, m->name, sig);
2521         }
2522
2523         g_hash_table_insert (assembly->handleref, m, GUINT_TO_POINTER(token));
2524         return token;
2525 }
2526
2527 static guint32
2528 mono_image_get_inflated_method_token (MonoDynamicImage *assembly, MonoMethod *m)
2529 {
2530         MonoMethodInflated *imethod = (MonoMethodInflated *) m;
2531         guint32 sig, token;
2532
2533         sig = method_encode_signature (assembly, imethod->declaring->signature);
2534         token = mono_image_get_memberref_token (
2535                 assembly, &m->klass->byval_arg, m->name, sig);
2536
2537         return token;
2538 }
2539
2540 static guint32
2541 create_generic_typespec (MonoDynamicImage *assembly, MonoReflectionTypeBuilder *tb)
2542 {
2543         MonoDynamicTable *table;
2544         MonoClass *klass;
2545         guint32 *values;
2546         guint32 token;
2547         char sig [128];
2548         char *p = sig;
2549         char blob_size [6];
2550         char *b = blob_size;
2551         int count, i;
2552
2553         /*
2554          * We're creating a TypeSpec for the TypeBuilder of a generic type declaration,
2555          * ie. what we'd normally use as the generic type in a TypeSpec signature.
2556          * Because of this, we must not insert it into the `typeref' hash table.
2557          */
2558
2559         token = GPOINTER_TO_UINT (g_hash_table_lookup (assembly->typespec, tb->type.type));
2560         if (token)
2561                 return token;
2562
2563         g_assert (tb->generic_params);
2564         klass = mono_class_from_mono_type (tb->type.type);
2565
2566         mono_metadata_encode_value (MONO_TYPE_GENERICINST, p, &p);
2567         encode_type (assembly, &klass->byval_arg, p, &p);
2568
2569         count = mono_array_length (tb->generic_params);
2570         mono_metadata_encode_value (count, p, &p);
2571         for (i = 0; i < count; i++) {
2572                 MonoReflectionGenericParam *gparam;
2573
2574                 gparam = mono_array_get (tb->generic_params, MonoReflectionGenericParam *, i);
2575
2576                 encode_type (assembly, gparam->type.type, p, &p);
2577         }
2578
2579         table = &assembly->tables [MONO_TABLE_TYPESPEC];
2580         if (assembly->save) {
2581                 g_assert (p-sig < 128);
2582                 mono_metadata_encode_value (p-sig, b, &b);
2583                 token = add_to_blob_cached (assembly, blob_size, b-blob_size, sig, p-sig);
2584                 alloc_table (table, table->rows + 1);
2585                 values = table->values + table->next_idx * MONO_TYPESPEC_SIZE;
2586                 values [MONO_TYPESPEC_SIGNATURE] = token;
2587         }
2588
2589         token = MONO_TYPEDEFORREF_TYPESPEC | (table->next_idx << MONO_TYPEDEFORREF_BITS);
2590         g_hash_table_insert (assembly->typespec, tb->type.type, GUINT_TO_POINTER(token));
2591         table->next_idx ++;
2592         return token;
2593 }
2594
2595 static guint32
2596 mono_image_get_generic_field_token (MonoDynamicImage *assembly, MonoReflectionFieldBuilder *fb)
2597 {
2598         MonoDynamicTable *table;
2599         MonoClass *klass;
2600         guint32 *values;
2601         guint32 token, pclass, parent, sig;
2602         gchar *name;
2603
2604         token = GPOINTER_TO_UINT (g_hash_table_lookup (assembly->handleref, fb));
2605         if (token)
2606                 return token;
2607
2608         klass = mono_class_from_mono_type (fb->typeb->type);
2609         name = mono_string_to_utf8 (fb->name);
2610
2611         sig = fieldref_encode_signature (assembly, fb->type->type);
2612
2613         parent = create_generic_typespec (assembly, (MonoReflectionTypeBuilder *) fb->typeb);
2614         g_assert ((parent & MONO_TYPEDEFORREF_MASK) == MONO_TYPEDEFORREF_TYPESPEC);
2615         
2616         pclass = MONO_MEMBERREF_PARENT_TYPESPEC;
2617         parent >>= MONO_TYPEDEFORREF_BITS;
2618
2619         table = &assembly->tables [MONO_TABLE_MEMBERREF];
2620
2621         if (assembly->save) {
2622                 alloc_table (table, table->rows + 1);
2623                 values = table->values + table->next_idx * MONO_MEMBERREF_SIZE;
2624                 values [MONO_MEMBERREF_CLASS] = pclass | (parent << MONO_MEMBERREF_PARENT_BITS);
2625                 values [MONO_MEMBERREF_NAME] = string_heap_insert (&assembly->sheap, name);
2626                 values [MONO_MEMBERREF_SIGNATURE] = sig;
2627         }
2628
2629         token = MONO_TOKEN_MEMBER_REF | table->next_idx;
2630         table->next_idx ++;
2631         g_hash_table_insert (assembly->handleref, fb, GUINT_TO_POINTER(token));
2632         return token;
2633 }
2634
2635 static guint32
2636 mono_reflection_encode_sighelper (MonoDynamicImage *assembly, MonoReflectionSigHelper *helper)
2637 {
2638         char *buf;
2639         char *p;
2640         guint32 nargs;
2641         guint32 size;
2642         guint32 i, idx;
2643         char blob_size [6];
2644         char *b = blob_size;
2645
2646         if (!assembly->save)
2647                 return 0;
2648
2649         /* FIXME: */
2650         g_assert (helper->type == 2);
2651
2652         if (helper->arguments)
2653                 nargs = mono_array_length (helper->arguments);
2654         else
2655                 nargs = 0;
2656
2657         size = 10 + (nargs * 10);
2658         
2659         p = buf = g_malloc (size);
2660
2661         /* Encode calling convention */
2662         /* Change Any to Standard */
2663         if ((helper->call_conv & 0x03) == 0x03)
2664                 helper->call_conv = 0x01;
2665         /* explicit_this implies has_this */
2666         if (helper->call_conv & 0x40)
2667                 helper->call_conv &= 0x20;
2668
2669         if (helper->call_conv == 0) { /* Unmanaged */
2670                 *p = helper->unmanaged_call_conv - 1;
2671         } else {
2672                 /* Managed */
2673                 *p = helper->call_conv & 0x60; /* has_this + explicit_this */
2674                 if (helper->call_conv & 0x02) /* varargs */
2675                         *p += 0x05;
2676         }
2677
2678         p++;
2679         mono_metadata_encode_value (nargs, p, &p);
2680         encode_reflection_type (assembly, helper->return_type, p, &p);
2681         for (i = 0; i < nargs; ++i) {
2682                 MonoReflectionType *pt = mono_array_get (helper->arguments, MonoReflectionType*, i);
2683                 encode_reflection_type (assembly, pt, p, &p);
2684         }
2685         /* store length */
2686         g_assert (p - buf < size);
2687         mono_metadata_encode_value (p-buf, b, &b);
2688         idx = add_to_blob_cached (assembly, blob_size, b-blob_size, buf, p-buf);
2689         g_free (buf);
2690
2691         return idx;
2692 }
2693         
2694 static guint32 
2695 mono_image_get_sighelper_token (MonoDynamicImage *assembly, MonoReflectionSigHelper *helper)
2696 {
2697         guint32 idx;
2698         MonoDynamicTable *table;
2699         guint32 *values;
2700
2701         table = &assembly->tables [MONO_TABLE_STANDALONESIG];
2702         idx = table->next_idx ++;
2703         table->rows ++;
2704         alloc_table (table, table->rows);
2705         values = table->values + idx * MONO_STAND_ALONE_SIGNATURE_SIZE;
2706
2707         values [MONO_STAND_ALONE_SIGNATURE] =
2708                 mono_reflection_encode_sighelper (assembly, helper);
2709
2710         return idx;
2711 }
2712
2713 static int
2714 reflection_cc_to_file (int call_conv) {
2715         switch (call_conv & 0x3) {
2716         case 0:
2717         case 1: return MONO_CALL_DEFAULT;
2718         case 2: return MONO_CALL_VARARG;
2719         default:
2720                 g_assert_not_reached ();
2721         }
2722         return 0;
2723 }
2724
2725 typedef struct {
2726         MonoType *parent;
2727         MonoMethodSignature *sig;
2728         char *name;
2729         guint32 token;
2730 } ArrayMethod;
2731
2732 static guint32
2733 mono_image_get_array_token (MonoDynamicImage *assembly, MonoReflectionArrayMethod *m)
2734 {
2735         guint32 nparams, i;
2736         GList *tmp;
2737         char *name;
2738         MonoMethodSignature *sig;
2739         ArrayMethod *am;
2740         
2741         name = mono_string_to_utf8 (m->name);
2742         nparams = mono_array_length (m->parameters);
2743         sig = g_malloc0 (sizeof (MonoMethodSignature) + sizeof (MonoType*) * nparams);
2744         sig->hasthis = 1;
2745         sig->sentinelpos = -1;
2746         sig->call_convention = reflection_cc_to_file (m->call_conv);
2747         sig->param_count = nparams;
2748         sig->ret = m->ret? m->ret->type: &mono_defaults.void_class->byval_arg;
2749         for (i = 0; i < nparams; ++i) {
2750                 MonoReflectionType *t = mono_array_get (m->parameters, gpointer, i);
2751                 sig->params [i] = t->type;
2752         }
2753
2754         for (tmp = assembly->array_methods; tmp; tmp = tmp->next) {
2755                 am = tmp->data;
2756                 if (strcmp (name, am->name) == 0 && 
2757                                 mono_metadata_type_equal (am->parent, m->parent->type) &&
2758                                 mono_metadata_signature_equal (am->sig, sig)) {
2759                         g_free (name);
2760                         g_free (sig);
2761                         m->table_idx = am->token & 0xffffff;
2762                         return am->token;
2763                 }
2764         }
2765         am = g_new0 (ArrayMethod, 1);
2766         am->name = name;
2767         am->sig = sig;
2768         am->parent = m->parent->type;
2769         am->token = mono_image_get_memberref_token (assembly, am->parent, name,
2770                 method_encode_signature (assembly, sig));
2771         assembly->array_methods = g_list_prepend (assembly->array_methods, am);
2772         m->table_idx = am->token & 0xffffff;
2773         return am->token;
2774 }
2775
2776 /*
2777  * Insert into the metadata tables all the info about the TypeBuilder tb.
2778  * Data in the tables is inserted in a predefined order, since some tables need to be sorted.
2779  */
2780 static void
2781 mono_image_get_type_info (MonoDomain *domain, MonoReflectionTypeBuilder *tb, MonoDynamicImage *assembly)
2782 {
2783         MonoDynamicTable *table;
2784         guint *values;
2785         int i, is_object = 0, is_system = 0;
2786         char *n;
2787
2788         table = &assembly->tables [MONO_TABLE_TYPEDEF];
2789         values = table->values + tb->table_idx * MONO_TYPEDEF_SIZE;
2790         values [MONO_TYPEDEF_FLAGS] = tb->attrs;
2791         n = mono_string_to_utf8 (tb->name);
2792         if (strcmp (n, "Object") == 0)
2793                 is_object++;
2794         values [MONO_TYPEDEF_NAME] = string_heap_insert (&assembly->sheap, n);
2795         g_free (n);
2796         n = mono_string_to_utf8 (tb->nspace);
2797         if (strcmp (n, "System") == 0)
2798                 is_system++;
2799         values [MONO_TYPEDEF_NAMESPACE] = string_heap_insert (&assembly->sheap, n);
2800         g_free (n);
2801         if (tb->parent && !(is_system && is_object) && 
2802                         !(tb->attrs & TYPE_ATTRIBUTE_INTERFACE)) { /* interfaces don't have a parent */
2803                 values [MONO_TYPEDEF_EXTENDS] = mono_image_typedef_or_ref (assembly, tb->parent->type);
2804         } else {
2805                 values [MONO_TYPEDEF_EXTENDS] = 0;
2806         }
2807         values [MONO_TYPEDEF_FIELD_LIST] = assembly->tables [MONO_TABLE_FIELD].next_idx;
2808         values [MONO_TYPEDEF_METHOD_LIST] = assembly->tables [MONO_TABLE_METHOD].next_idx;
2809
2810         /*
2811          * if we have explicitlayout or sequentiallayouts, output data in the
2812          * ClassLayout table.
2813          */
2814         if (((tb->attrs & TYPE_ATTRIBUTE_LAYOUT_MASK) != TYPE_ATTRIBUTE_AUTO_LAYOUT) &&
2815                         ((tb->class_size > 0) || (tb->packing_size > 0))) {
2816                 table = &assembly->tables [MONO_TABLE_CLASSLAYOUT];
2817                 table->rows++;
2818                 alloc_table (table, table->rows);
2819                 values = table->values + table->rows * MONO_CLASS_LAYOUT_SIZE;
2820                 values [MONO_CLASS_LAYOUT_PARENT] = tb->table_idx;
2821                 values [MONO_CLASS_LAYOUT_CLASS_SIZE] = tb->class_size;
2822                 values [MONO_CLASS_LAYOUT_PACKING_SIZE] = tb->packing_size;
2823         }
2824
2825         /* handle interfaces */
2826         if (tb->interfaces) {
2827                 table = &assembly->tables [MONO_TABLE_INTERFACEIMPL];
2828                 i = table->rows;
2829                 table->rows += mono_array_length (tb->interfaces);
2830                 alloc_table (table, table->rows);
2831                 values = table->values + (i + 1) * MONO_INTERFACEIMPL_SIZE;
2832                 for (i = 0; i < mono_array_length (tb->interfaces); ++i) {
2833                         MonoReflectionType* iface = (MonoReflectionType*) mono_array_get (tb->interfaces, gpointer, i);
2834                         values [MONO_INTERFACEIMPL_CLASS] = tb->table_idx;
2835                         values [MONO_INTERFACEIMPL_INTERFACE] = mono_image_typedef_or_ref (assembly, iface->type);
2836                         values += MONO_INTERFACEIMPL_SIZE;
2837                 }
2838         }
2839
2840         /* handle fields */
2841         if (tb->fields) {
2842                 table = &assembly->tables [MONO_TABLE_FIELD];
2843                 table->rows += tb->num_fields;
2844                 alloc_table (table, table->rows);
2845                 for (i = 0; i < tb->num_fields; ++i)
2846                         mono_image_get_field_info (
2847                                 mono_array_get (tb->fields, MonoReflectionFieldBuilder*, i), assembly);
2848         }
2849
2850         /* handle constructors */
2851         if (tb->ctors) {
2852                 table = &assembly->tables [MONO_TABLE_METHOD];
2853                 table->rows += mono_array_length (tb->ctors);
2854                 alloc_table (table, table->rows);
2855                 for (i = 0; i < mono_array_length (tb->ctors); ++i)
2856                         mono_image_get_ctor_info (domain,
2857                                 mono_array_get (tb->ctors, MonoReflectionCtorBuilder*, i), assembly);
2858         }
2859
2860         /* handle methods */
2861         if (tb->methods) {
2862                 table = &assembly->tables [MONO_TABLE_METHOD];
2863                 table->rows += tb->num_methods;
2864                 alloc_table (table, table->rows);
2865                 for (i = 0; i < tb->num_methods; ++i)
2866                         mono_image_get_method_info (
2867                                 mono_array_get (tb->methods, MonoReflectionMethodBuilder*, i), assembly);
2868         }
2869
2870         /* Do the same with properties etc.. */
2871         if (tb->events && mono_array_length (tb->events)) {
2872                 table = &assembly->tables [MONO_TABLE_EVENT];
2873                 table->rows += mono_array_length (tb->events);
2874                 alloc_table (table, table->rows);
2875                 table = &assembly->tables [MONO_TABLE_EVENTMAP];
2876                 table->rows ++;
2877                 alloc_table (table, table->rows);
2878                 values = table->values + table->rows * MONO_EVENT_MAP_SIZE;
2879                 values [MONO_EVENT_MAP_PARENT] = tb->table_idx;
2880                 values [MONO_EVENT_MAP_EVENTLIST] = assembly->tables [MONO_TABLE_EVENT].next_idx;
2881                 for (i = 0; i < mono_array_length (tb->events); ++i)
2882                         mono_image_get_event_info (
2883                                 mono_array_get (tb->events, MonoReflectionEventBuilder*, i), assembly);
2884         }
2885         if (tb->properties && mono_array_length (tb->properties)) {
2886                 table = &assembly->tables [MONO_TABLE_PROPERTY];
2887                 table->rows += mono_array_length (tb->properties);
2888                 alloc_table (table, table->rows);
2889                 table = &assembly->tables [MONO_TABLE_PROPERTYMAP];
2890                 table->rows ++;
2891                 alloc_table (table, table->rows);
2892                 values = table->values + table->rows * MONO_PROPERTY_MAP_SIZE;
2893                 values [MONO_PROPERTY_MAP_PARENT] = tb->table_idx;
2894                 values [MONO_PROPERTY_MAP_PROPERTY_LIST] = assembly->tables [MONO_TABLE_PROPERTY].next_idx;
2895                 for (i = 0; i < mono_array_length (tb->properties); ++i)
2896                         mono_image_get_property_info (
2897                                 mono_array_get (tb->properties, MonoReflectionPropertyBuilder*, i), assembly);
2898         }
2899
2900         /* handle generic parameters */
2901         if (tb->generic_params) {
2902                 table = &assembly->tables [MONO_TABLE_GENERICPARAM];
2903                 table->rows += mono_array_length (tb->generic_params);
2904                 alloc_table (table, table->rows);
2905                 for (i = 0; i < mono_array_length (tb->generic_params); ++i) {
2906                         guint32 owner = MONO_TYPEORMETHOD_TYPE | (tb->table_idx << MONO_TYPEORMETHOD_BITS);
2907
2908                         mono_image_get_generic_param_info (
2909                                 mono_array_get (tb->generic_params, MonoReflectionGenericParam*, i), owner, assembly);
2910                 }
2911         }
2912
2913         mono_image_add_decl_security (assembly, 
2914                 mono_metadata_make_token (MONO_TABLE_TYPEDEF, tb->table_idx), tb->permissions);
2915
2916         if (tb->subtypes) {
2917                 MonoDynamicTable *ntable;
2918                 
2919                 ntable = &assembly->tables [MONO_TABLE_NESTEDCLASS];
2920                 ntable->rows += mono_array_length (tb->subtypes);
2921                 alloc_table (ntable, ntable->rows);
2922                 values = ntable->values + ntable->next_idx * MONO_NESTED_CLASS_SIZE;
2923
2924                 for (i = 0; i < mono_array_length (tb->subtypes); ++i) {
2925                         MonoReflectionTypeBuilder *subtype = mono_array_get (tb->subtypes, MonoReflectionTypeBuilder*, i);
2926
2927                         values [MONO_NESTED_CLASS_NESTED] = subtype->table_idx;
2928                         values [MONO_NESTED_CLASS_ENCLOSING] = tb->table_idx;
2929                         /*g_print ("nesting %s (%d) in %s (%d) (rows %d/%d)\n",
2930                                 mono_string_to_utf8 (subtype->name), subtype->table_idx,
2931                                 mono_string_to_utf8 (tb->name), tb->table_idx,
2932                                 ntable->next_idx, ntable->rows);*/
2933                         values += MONO_NESTED_CLASS_SIZE;
2934                         ntable->next_idx++;
2935                 }
2936         }
2937 }
2938
2939 static void
2940 collect_types (GPtrArray *types, MonoReflectionTypeBuilder *type)
2941 {
2942         int i;
2943
2944         g_ptr_array_add (types, type);
2945
2946         if (!type->subtypes)
2947                 return;
2948
2949         for (i = 0; i < mono_array_length (type->subtypes); ++i) {
2950                 MonoReflectionTypeBuilder *subtype = mono_array_get (type->subtypes, MonoReflectionTypeBuilder*, i);
2951                 collect_types (types, subtype);
2952         }
2953 }
2954
2955 static gint
2956 compare_types_by_table_idx (MonoReflectionTypeBuilder **type1, MonoReflectionTypeBuilder **type2)
2957 {
2958         if ((*type1)->table_idx < (*type2)->table_idx)
2959                 return -1;
2960         else
2961                 if ((*type1)->table_idx > (*type2)->table_idx)
2962                         return 1;
2963         else
2964                 return 0;
2965 }
2966
2967 static void
2968 params_add_cattrs (MonoDynamicImage *assembly, MonoArray *pinfo) {
2969         int i;
2970
2971         if (!pinfo)
2972                 return;
2973         for (i = 0; i < mono_array_length (pinfo); ++i) {
2974                 MonoReflectionParamBuilder *pb;
2975                 pb = mono_array_get (pinfo, MonoReflectionParamBuilder *, i);
2976                 if (!pb)
2977                         continue;
2978                 mono_image_add_cattrs (assembly, pb->table_idx, MONO_CUSTOM_ATTR_PARAMDEF, pb->cattrs);
2979         }
2980 }
2981
2982 static void
2983 type_add_cattrs (MonoDynamicImage *assembly, MonoReflectionTypeBuilder *tb) {
2984         int i;
2985         
2986         mono_image_add_cattrs (assembly, tb->table_idx, MONO_CUSTOM_ATTR_TYPEDEF, tb->cattrs);
2987         if (tb->fields) {
2988                 for (i = 0; i < tb->num_fields; ++i) {
2989                         MonoReflectionFieldBuilder* fb;
2990                         fb = mono_array_get (tb->fields, MonoReflectionFieldBuilder*, i);
2991                         mono_image_add_cattrs (assembly, fb->table_idx, MONO_CUSTOM_ATTR_FIELDDEF, fb->cattrs);
2992                 }
2993         }
2994         if (tb->events) {
2995                 for (i = 0; i < mono_array_length (tb->events); ++i) {
2996                         MonoReflectionEventBuilder* eb;
2997                         eb = mono_array_get (tb->events, MonoReflectionEventBuilder*, i);
2998                         mono_image_add_cattrs (assembly, eb->table_idx, MONO_CUSTOM_ATTR_EVENT, eb->cattrs);
2999                 }
3000         }
3001         if (tb->properties) {
3002                 for (i = 0; i < mono_array_length (tb->properties); ++i) {
3003                         MonoReflectionPropertyBuilder* pb;
3004                         pb = mono_array_get (tb->properties, MonoReflectionPropertyBuilder*, i);
3005                         mono_image_add_cattrs (assembly, pb->table_idx, MONO_CUSTOM_ATTR_PROPERTY, pb->cattrs);
3006                 }
3007         }
3008         if (tb->ctors) {
3009                 for (i = 0; i < mono_array_length (tb->ctors); ++i) {
3010                         MonoReflectionCtorBuilder* cb;
3011                         cb = mono_array_get (tb->ctors, MonoReflectionCtorBuilder*, i);
3012                         mono_image_add_cattrs (assembly, cb->table_idx, MONO_CUSTOM_ATTR_METHODDEF, cb->cattrs);
3013                         params_add_cattrs (assembly, cb->pinfo);
3014                 }
3015         }
3016
3017         if (tb->methods) {
3018                 for (i = 0; i < tb->num_methods; ++i) {
3019                         MonoReflectionMethodBuilder* mb;
3020                         mb = mono_array_get (tb->methods, MonoReflectionMethodBuilder*, i);
3021                         mono_image_add_cattrs (assembly, mb->table_idx, MONO_CUSTOM_ATTR_METHODDEF, mb->cattrs);
3022                         params_add_cattrs (assembly, mb->pinfo);
3023                 }
3024         }
3025
3026         if (tb->subtypes) {
3027                 for (i = 0; i < mono_array_length (tb->subtypes); ++i)
3028                         type_add_cattrs (assembly, mono_array_get (tb->subtypes, MonoReflectionTypeBuilder*, i));
3029         }
3030 }
3031
3032 static void
3033 module_add_cattrs (MonoDynamicImage *assembly, MonoReflectionModuleBuilder *mb) {
3034         int i;
3035         
3036         mono_image_add_cattrs (assembly, mb->table_idx, MONO_CUSTOM_ATTR_MODULE, mb->cattrs);
3037         
3038         /* no types in the module */
3039         if (!mb->types)
3040                 return;
3041         
3042         for (i = 0; i < mb->num_types; ++i)
3043                 type_add_cattrs (assembly, mono_array_get (mb->types, MonoReflectionTypeBuilder*, i));
3044 }
3045
3046 static void
3047 mono_image_fill_file_table (MonoDomain *domain, MonoReflectionModule *module, MonoDynamicImage *assembly)
3048 {
3049         MonoDynamicTable *table;
3050         guint32 *values;
3051         char blob_size [6];
3052         guchar hash [20];
3053         char *b = blob_size;
3054         char *dir, *path;
3055
3056         table = &assembly->tables [MONO_TABLE_FILE];
3057         table->rows++;
3058         alloc_table (table, table->rows);
3059         values = table->values + table->next_idx * MONO_FILE_SIZE;
3060         values [MONO_FILE_FLAGS] = FILE_CONTAINS_METADATA;
3061         values [MONO_FILE_NAME] = string_heap_insert (&assembly->sheap, module->image->module_name);
3062         if (module->image->dynamic) {
3063                 /* This depends on the fact that the main module is emitted last */
3064                 dir = mono_string_to_utf8 (((MonoReflectionModuleBuilder*)module)->assemblyb->dir);
3065                 path = g_strdup_printf ("%s%c%s", dir, G_DIR_SEPARATOR, module->image->module_name);
3066         } else {
3067                 dir = NULL;
3068                 path = g_strdup (module->image->name);
3069         }
3070         mono_sha1_get_digest_from_file (path, hash);
3071         g_free (dir);
3072         g_free (path);
3073         mono_metadata_encode_value (20, b, &b);
3074         values [MONO_FILE_HASH_VALUE] = mono_image_add_stream_data (&assembly->blob, blob_size, b-blob_size);
3075         mono_image_add_stream_data (&assembly->blob, hash, 20);
3076         table->next_idx ++;
3077 }
3078
3079 static void
3080 mono_image_fill_module_table (MonoDomain *domain, MonoReflectionModuleBuilder *mb, MonoDynamicImage *assembly)
3081 {
3082         MonoDynamicTable *table;
3083         int i;
3084         char *name;
3085
3086         table = &assembly->tables [MONO_TABLE_MODULE];
3087         mb->table_idx = table->next_idx ++;
3088         name = mono_string_to_utf8 (mb->module.name);
3089         table->values [mb->table_idx * MONO_MODULE_SIZE + MONO_MODULE_NAME] = string_heap_insert (&assembly->sheap, name);
3090         g_free (name);
3091         i = mono_image_add_stream_data (&assembly->guid, mono_array_addr (mb->guid, char, 0), 16);
3092         i /= 16;
3093         ++i;
3094         table->values [mb->table_idx * MONO_MODULE_SIZE + MONO_MODULE_MVID] = i;
3095         table->values [mb->table_idx * MONO_MODULE_SIZE + MONO_MODULE_ENC] = 0;
3096         table->values [mb->table_idx * MONO_MODULE_SIZE + MONO_MODULE_ENCBASE] = 0;
3097 }
3098
3099 static guint32
3100 mono_image_fill_export_table_from_class (MonoDomain *domain, MonoClass *klass,
3101         guint32 module_index, guint32 parent_index, MonoDynamicImage *assembly)
3102 {
3103         MonoDynamicTable *table;
3104         guint32 *values;
3105         guint32 visib, res;
3106
3107         visib = klass->flags & TYPE_ATTRIBUTE_VISIBILITY_MASK;
3108         if (! ((visib & TYPE_ATTRIBUTE_PUBLIC) || (visib & TYPE_ATTRIBUTE_NESTED_PUBLIC)))
3109                 return 0;
3110
3111         table = &assembly->tables [MONO_TABLE_EXPORTEDTYPE];
3112         table->rows++;
3113         alloc_table (table, table->rows);
3114         values = table->values + table->next_idx * MONO_EXP_TYPE_SIZE;
3115
3116         values [MONO_EXP_TYPE_FLAGS] = klass->flags;
3117         values [MONO_EXP_TYPE_TYPEDEF] = klass->type_token;
3118         if (klass->nested_in)
3119                 values [MONO_EXP_TYPE_IMPLEMENTATION] = (parent_index << MONO_IMPLEMENTATION_BITS) + MONO_IMPLEMENTATION_EXP_TYPE;
3120         else
3121                 values [MONO_EXP_TYPE_IMPLEMENTATION] = (module_index << MONO_IMPLEMENTATION_BITS) + MONO_IMPLEMENTATION_FILE;
3122         values [MONO_EXP_TYPE_NAME] = string_heap_insert (&assembly->sheap, klass->name);
3123         values [MONO_EXP_TYPE_NAMESPACE] = string_heap_insert (&assembly->sheap, klass->name_space);
3124
3125         res = table->next_idx;
3126
3127         table->next_idx ++;
3128
3129         /* Emit nested types */
3130         if (klass->nested_classes) {
3131                 GList *tmp;
3132
3133                 for (tmp = klass->nested_classes; tmp; tmp = tmp->next)
3134                         mono_image_fill_export_table_from_class (domain, tmp->data, module_index, table->next_idx - 1, assembly);
3135         }
3136
3137         return res;
3138 }
3139
3140 static void
3141 mono_image_fill_export_table (MonoDomain *domain, MonoReflectionTypeBuilder *tb,
3142         guint32 module_index, guint32 parent_index, MonoDynamicImage *assembly)
3143 {
3144         MonoClass *klass;
3145         guint32 idx, i;
3146
3147         klass = mono_class_from_mono_type (tb->type.type);
3148
3149         klass->type_token = mono_metadata_make_token (MONO_TABLE_TYPEDEF, tb->table_idx);
3150
3151         idx = mono_image_fill_export_table_from_class (domain, klass, module_index, 
3152                                                                                                    parent_index, assembly);
3153
3154         /* 
3155          * Emit nested types
3156          * We need to do this ourselves since klass->nested_classes is not set up.
3157          */
3158         if (tb->subtypes) {
3159                 for (i = 0; i < mono_array_length (tb->subtypes); ++i)
3160                         mono_image_fill_export_table (domain, mono_array_get (tb->subtypes, MonoReflectionTypeBuilder*, i), module_index, idx, assembly);
3161         }
3162 }
3163
3164 static void
3165 mono_image_fill_export_table_from_module (MonoDomain *domain, MonoReflectionModule *module,
3166         guint32 module_index, MonoDynamicImage *assembly)
3167 {
3168         MonoImage *image = module->image;
3169         MonoTableInfo  *t;
3170         guint32 i;
3171
3172         t = &image->tables [MONO_TABLE_TYPEDEF];
3173
3174         for (i = 0; i < t->rows; ++i) {
3175                 MonoClass *klass = mono_class_get (image, mono_metadata_make_token (MONO_TABLE_TYPEDEF, i + 1));
3176
3177                 if (klass->flags & TYPE_ATTRIBUTE_PUBLIC)
3178                         mono_image_fill_export_table_from_class (domain, klass, module_index, 0, assembly);
3179         }
3180 }
3181
3182 #define align_pointer(base,p)\
3183         do {\
3184                 guint32 __diff = (unsigned char*)(p)-(unsigned char*)(base);\
3185                 if (__diff & 3)\
3186                         (p) += 4 - (__diff & 3);\
3187         } while (0)
3188
3189 static int
3190 compare_semantics (const void *a, const void *b)
3191 {
3192         const guint32 *a_values = a;
3193         const guint32 *b_values = b;
3194         int assoc = a_values [MONO_METHOD_SEMA_ASSOCIATION] - b_values [MONO_METHOD_SEMA_ASSOCIATION];
3195         if (assoc)
3196                 return assoc;
3197         return a_values [MONO_METHOD_SEMA_SEMANTICS] - b_values [MONO_METHOD_SEMA_SEMANTICS];
3198 }
3199
3200 static int
3201 compare_custom_attrs (const void *a, const void *b)
3202 {
3203         const guint32 *a_values = a;
3204         const guint32 *b_values = b;
3205
3206         return a_values [MONO_CUSTOM_ATTR_PARENT] - b_values [MONO_CUSTOM_ATTR_PARENT];
3207 }
3208
3209 static int
3210 compare_field_marshal (const void *a, const void *b)
3211 {
3212         const guint32 *a_values = a;
3213         const guint32 *b_values = b;
3214
3215         return a_values [MONO_FIELD_MARSHAL_PARENT] - b_values [MONO_FIELD_MARSHAL_PARENT];
3216 }
3217
3218 static int
3219 compare_nested (const void *a, const void *b)
3220 {
3221         const guint32 *a_values = a;
3222         const guint32 *b_values = b;
3223
3224         return a_values [MONO_NESTED_CLASS_NESTED] - b_values [MONO_NESTED_CLASS_NESTED];
3225 }
3226
3227 static int
3228 compare_genericparam (const void *a, const void *b)
3229 {
3230         const GenericParamTableEntry **a_entry = (const GenericParamTableEntry **) a;
3231         const GenericParamTableEntry **b_entry = (const GenericParamTableEntry **) b;
3232
3233         if ((*b_entry)->owner == (*a_entry)->owner)
3234                 return 
3235                         (*a_entry)->gparam->type.type->data.generic_param->num - 
3236                         (*b_entry)->gparam->type.type->data.generic_param->num;
3237         else
3238                 return (*b_entry)->owner - (*a_entry)->owner;
3239 }
3240
3241 static int
3242 compare_declsecurity_attrs (const void *a, const void *b)
3243 {
3244         const guint32 *a_values = a;
3245         const guint32 *b_values = b;
3246
3247         return a_values [MONO_DECL_SECURITY_PARENT] - b_values [MONO_DECL_SECURITY_PARENT];
3248 }
3249
3250 static void
3251 pad_heap (MonoDynamicStream *sh)
3252 {
3253         if (sh->index & 3) {
3254                 int sz = 4 - (sh->index & 3);
3255                 memset (sh->data + sh->index, 0, sz);
3256                 sh->index += sz;
3257         }
3258 }
3259
3260 struct StreamDesc {
3261         const char *name;
3262         MonoDynamicStream *stream;
3263 };
3264
3265 /*
3266  * build_compressed_metadata() fills in the blob of data that represents the 
3267  * raw metadata as it will be saved in the PE file. The five streams are output 
3268  * and the metadata tables are comnpressed from the guint32 array representation, 
3269  * to the compressed on-disk format.
3270  */
3271 static void
3272 build_compressed_metadata (MonoDynamicImage *assembly)
3273 {
3274         MonoDynamicTable *table;
3275         int i;
3276         guint64 valid_mask = 0;
3277         guint64 sorted_mask;
3278         guint32 heapt_size = 0;
3279         guint32 meta_size = 256; /* allow for header and other stuff */
3280         guint32 table_offset;
3281         guint32 ntables = 0;
3282         guint64 *int64val;
3283         guint32 *int32val;
3284         guint16 *int16val;
3285         MonoImage *meta;
3286         unsigned char *p;
3287         struct StreamDesc stream_desc [5];
3288
3289         qsort (assembly->gen_params->pdata, assembly->gen_params->len, sizeof (gpointer), compare_genericparam);
3290         for (i = 0; i < assembly->gen_params->len; i++){
3291                 GenericParamTableEntry *entry = g_ptr_array_index (assembly->gen_params, i);
3292                 write_generic_param_entry (assembly, entry);
3293         }
3294
3295         stream_desc [0].name  = "#~";
3296         stream_desc [0].stream = &assembly->tstream;
3297         stream_desc [1].name  = "#Strings";
3298         stream_desc [1].stream = &assembly->sheap;
3299         stream_desc [2].name  = "#US";
3300         stream_desc [2].stream = &assembly->us;
3301         stream_desc [3].name  = "#Blob";
3302         stream_desc [3].stream = &assembly->blob;
3303         stream_desc [4].name  = "#GUID";
3304         stream_desc [4].stream = &assembly->guid;
3305         
3306         /* tables that are sorted */
3307         sorted_mask = ((guint64)1 << MONO_TABLE_CONSTANT) | ((guint64)1 << MONO_TABLE_FIELDMARSHAL)
3308                 | ((guint64)1 << MONO_TABLE_METHODSEMANTICS) | ((guint64)1 << MONO_TABLE_CLASSLAYOUT)
3309                 | ((guint64)1 << MONO_TABLE_FIELDLAYOUT) | ((guint64)1 << MONO_TABLE_FIELDRVA)
3310                 | ((guint64)1 << MONO_TABLE_IMPLMAP) | ((guint64)1 << MONO_TABLE_NESTEDCLASS)
3311                 | ((guint64)1 << MONO_TABLE_METHODIMPL) | ((guint64)1 << MONO_TABLE_CUSTOMATTRIBUTE)
3312                 | ((guint64)1 << MONO_TABLE_DECLSECURITY) | ((guint64)1 << MONO_TABLE_GENERICPARAM);
3313         
3314         /* Compute table sizes */
3315         /* the MonoImage has already been created in mono_image_basic_init() */
3316         meta = &assembly->image;
3317
3318         /* sizes should be multiple of 4 */
3319         pad_heap (&assembly->blob);
3320         pad_heap (&assembly->guid);
3321         pad_heap (&assembly->sheap);
3322         pad_heap (&assembly->us);
3323
3324         /* Setup the info used by compute_sizes () */
3325         meta->idx_blob_wide = assembly->blob.index >= 65536 ? 1 : 0;
3326         meta->idx_guid_wide = assembly->guid.index >= 65536 ? 1 : 0;
3327         meta->idx_string_wide = assembly->sheap.index >= 65536 ? 1 : 0;
3328
3329         meta_size += assembly->blob.index;
3330         meta_size += assembly->guid.index;
3331         meta_size += assembly->sheap.index;
3332         meta_size += assembly->us.index;
3333
3334         for (i=0; i < 64; ++i)
3335                 meta->tables [i].rows = assembly->tables [i].rows;
3336         
3337         for (i = 0; i < 64; i++){
3338                 if (meta->tables [i].rows == 0)
3339                         continue;
3340                 valid_mask |= (guint64)1 << i;
3341                 ntables ++;
3342                 meta->tables [i].row_size = mono_metadata_compute_size (
3343                         meta, i, &meta->tables [i].size_bitfield);
3344                 heapt_size += meta->tables [i].row_size * meta->tables [i].rows;
3345         }
3346         heapt_size += 24; /* #~ header size */
3347         heapt_size += ntables * 4;
3348         /* make multiple of 4 */
3349         heapt_size += 3;
3350         heapt_size &= ~3;
3351         meta_size += heapt_size;
3352         meta->raw_metadata = g_malloc0 (meta_size);
3353         p = meta->raw_metadata;
3354         /* the metadata signature */
3355         *p++ = 'B'; *p++ = 'S'; *p++ = 'J'; *p++ = 'B';
3356         /* version numbers and 4 bytes reserved */
3357         int16val = (guint16*)p;
3358         *int16val++ = GUINT16_TO_LE (1);
3359         *int16val = GUINT16_TO_LE (1);
3360         p += 8;
3361         /* version string */
3362         int32val = (guint32*)p;
3363         *int32val = GUINT32_TO_LE ((strlen (meta->version) + 3) & (~3)); /* needs to be multiple of 4 */
3364         p += 4;
3365         memcpy (p, meta->version, strlen (meta->version));
3366         p += GUINT32_FROM_LE (*int32val);
3367         align_pointer (meta->raw_metadata, p);
3368         int16val = (guint16*)p;
3369         *int16val++ = GUINT16_TO_LE (0); /* flags must be 0 */
3370         *int16val = GUINT16_TO_LE (5); /* number of streams */
3371         p += 4;
3372
3373         /*
3374          * write the stream info.
3375          */
3376         table_offset = (p - (unsigned char*)meta->raw_metadata) + 5 * 8 + 40; /* room needed for stream headers */
3377         table_offset += 3; table_offset &= ~3;
3378
3379         assembly->tstream.index = heapt_size;
3380         for (i = 0; i < 5; ++i) {
3381                 int32val = (guint32*)p;
3382                 stream_desc [i].stream->offset = table_offset;
3383                 *int32val++ = GUINT32_TO_LE (table_offset);
3384                 *int32val = GUINT32_TO_LE (stream_desc [i].stream->index);
3385                 table_offset += GUINT32_FROM_LE (*int32val);
3386                 table_offset += 3; table_offset &= ~3;
3387                 p += 8;
3388                 strcpy (p, stream_desc [i].name);
3389                 p += strlen (stream_desc [i].name) + 1;
3390                 align_pointer (meta->raw_metadata, p);
3391         }
3392         /* 
3393          * now copy the data, the table stream header and contents goes first.
3394          */
3395         g_assert ((p - (unsigned char*)meta->raw_metadata) < assembly->tstream.offset);
3396         p = meta->raw_metadata + assembly->tstream.offset;
3397         int32val = (guint32*)p;
3398         *int32val = GUINT32_TO_LE (0); /* reserved */
3399         p += 4;
3400
3401         if ((assembly->tables [MONO_TABLE_GENERICPARAM].rows > 0) ||
3402                         (assembly->tables [MONO_TABLE_METHODSPEC].rows > 0) ||
3403                         (assembly->tables [MONO_TABLE_GENERICPARAMCONSTRAINT].rows > 0)) {
3404                 *p++ = 1; /* version */
3405                 *p++ = 1;
3406         } else {
3407                 *p++ = 1; /* version */
3408                 *p++ = 0;
3409         }
3410
3411         if (meta->idx_string_wide)
3412                 *p |= 0x01;
3413         if (meta->idx_guid_wide)
3414                 *p |= 0x02;
3415         if (meta->idx_blob_wide)
3416                 *p |= 0x04;
3417         ++p;
3418         *p++ = 1; /* reserved */
3419         int64val = (guint64*)p;
3420         *int64val++ = GUINT64_TO_LE (valid_mask);
3421         *int64val++ = GUINT64_TO_LE (valid_mask & sorted_mask); /* bitvector of sorted tables  */
3422         p += 16;
3423         int32val = (guint32*)p;
3424         for (i = 0; i < 64; i++){
3425                 if (meta->tables [i].rows == 0)
3426                         continue;
3427                 *int32val++ = GUINT32_TO_LE (meta->tables [i].rows);
3428         }
3429         p = (unsigned char*)int32val;
3430
3431         /* sort the tables that still need sorting */
3432         table = &assembly->tables [MONO_TABLE_METHODSEMANTICS];
3433         if (table->rows)
3434                 qsort (table->values + MONO_METHOD_SEMA_SIZE, table->rows, sizeof (guint32) * MONO_METHOD_SEMA_SIZE, compare_semantics);
3435         table = &assembly->tables [MONO_TABLE_CUSTOMATTRIBUTE];
3436         if (table->rows)
3437                 qsort (table->values + MONO_CUSTOM_ATTR_SIZE, table->rows, sizeof (guint32) * MONO_CUSTOM_ATTR_SIZE, compare_custom_attrs);
3438         table = &assembly->tables [MONO_TABLE_FIELDMARSHAL];
3439         if (table->rows)
3440                 qsort (table->values + MONO_FIELD_MARSHAL_SIZE, table->rows, sizeof (guint32) * MONO_FIELD_MARSHAL_SIZE, compare_field_marshal);
3441         table = &assembly->tables [MONO_TABLE_NESTEDCLASS];
3442         if (table->rows)
3443                 qsort (table->values + MONO_NESTED_CLASS_SIZE, table->rows, sizeof (guint32) * MONO_NESTED_CLASS_SIZE, compare_nested);
3444         /* Section 21.11 DeclSecurity in Partition II doesn't specify this to be sorted by MS implementation requires it */
3445         table = &assembly->tables [MONO_TABLE_DECLSECURITY];
3446         if (table->rows)
3447                 qsort (table->values + MONO_DECL_SECURITY_SIZE, table->rows, sizeof (guint32) * MONO_DECL_SECURITY_SIZE, compare_declsecurity_attrs);
3448
3449         /* compress the tables */
3450         for (i = 0; i < 64; i++){
3451                 int row, col;
3452                 guint32 *values;
3453                 guint32 bitfield = meta->tables [i].size_bitfield;
3454                 if (!meta->tables [i].rows)
3455                         continue;
3456                 if (assembly->tables [i].columns != mono_metadata_table_count (bitfield))
3457                         g_error ("col count mismatch in %d: %d %d", i, assembly->tables [i].columns, mono_metadata_table_count (bitfield));
3458                 meta->tables [i].base = p;
3459                 for (row = 1; row <= meta->tables [i].rows; ++row) {
3460                         values = assembly->tables [i].values + row * assembly->tables [i].columns;
3461                         for (col = 0; col < assembly->tables [i].columns; ++col) {
3462                                 switch (mono_metadata_table_size (bitfield, col)) {
3463                                 case 1:
3464                                         *p++ = values [col];
3465                                         break;
3466                                 case 2:
3467                                         *p++ = values [col] & 0xff;
3468                                         *p++ = (values [col] >> 8) & 0xff;
3469                                         break;
3470                                 case 4:
3471                                         *p++ = values [col] & 0xff;
3472                                         *p++ = (values [col] >> 8) & 0xff;
3473                                         *p++ = (values [col] >> 16) & 0xff;
3474                                         *p++ = (values [col] >> 24) & 0xff;
3475                                         break;
3476                                 default:
3477                                         g_assert_not_reached ();
3478                                 }
3479                         }
3480                 }
3481                 g_assert ((p - (const unsigned char*)meta->tables [i].base) == (meta->tables [i].rows * meta->tables [i].row_size));
3482         }
3483         
3484         g_assert (assembly->guid.offset + assembly->guid.index < meta_size);
3485         memcpy (meta->raw_metadata + assembly->sheap.offset, assembly->sheap.data, assembly->sheap.index);
3486         memcpy (meta->raw_metadata + assembly->us.offset, assembly->us.data, assembly->us.index);
3487         memcpy (meta->raw_metadata + assembly->blob.offset, assembly->blob.data, assembly->blob.index);
3488         memcpy (meta->raw_metadata + assembly->guid.offset, assembly->guid.data, assembly->guid.index);
3489
3490         assembly->meta_size = assembly->guid.offset + assembly->guid.index;
3491 }
3492
3493 /*
3494  * Some tables in metadata need to be sorted according to some criteria, but
3495  * when methods and fields are first created with reflection, they may be assigned a token
3496  * that doesn't correspond to the final token they will get assigned after the sorting.
3497  * ILGenerator.cs keeps a fixup table that maps the position of tokens in the IL code stream
3498  * with the reflection objects that represent them. Once all the tables are set up, the 
3499  * reflection objects will contains the correct table index. fixup_method() will fixup the
3500  * tokens for the method with ILGenerator @ilgen.
3501  */
3502 static void
3503 fixup_method (MonoReflectionILGen *ilgen, gpointer value, MonoDynamicImage *assembly) {
3504         guint32 code_idx = GPOINTER_TO_UINT (value);
3505         MonoReflectionILTokenInfo *iltoken;
3506         MonoReflectionFieldBuilder *field;
3507         MonoReflectionCtorBuilder *ctor;
3508         MonoReflectionMethodBuilder *method;
3509         MonoReflectionTypeBuilder *tb;
3510         MonoReflectionArrayMethod *am;
3511         guint32 i, idx = 0;
3512         unsigned char *target;
3513
3514         for (i = 0; i < ilgen->num_token_fixups; ++i) {
3515                 iltoken = (MonoReflectionILTokenInfo *)mono_array_addr_with_size (ilgen->token_fixups, sizeof (MonoReflectionILTokenInfo), i);
3516                 target = assembly->code.data + code_idx + iltoken->code_pos;
3517                 switch (target [3]) {
3518                 case MONO_TABLE_FIELD:
3519                         if (!strcmp (iltoken->member->vtable->klass->name, "FieldBuilder")) {
3520                                 field = (MonoReflectionFieldBuilder *)iltoken->member;
3521                                 idx = field->table_idx;
3522                         } else if (!strcmp (iltoken->member->vtable->klass->name, "MonoField")) {
3523                                 MonoClassField *f = ((MonoReflectionField*)iltoken->member)->field;
3524                                 idx = GPOINTER_TO_UINT (mono_g_hash_table_lookup (assembly->field_to_table_idx, f));
3525                         } else {
3526                                 g_assert_not_reached ();
3527                         }
3528                         break;
3529                 case MONO_TABLE_METHOD:
3530                         if (!strcmp (iltoken->member->vtable->klass->name, "MethodBuilder")) {
3531                                 method = (MonoReflectionMethodBuilder *)iltoken->member;
3532                                 idx = method->table_idx;
3533                         } else if (!strcmp (iltoken->member->vtable->klass->name, "ConstructorBuilder")) {
3534                                 ctor = (MonoReflectionCtorBuilder *)iltoken->member;
3535                                 idx = ctor->table_idx;
3536                         } else if (!strcmp (iltoken->member->vtable->klass->name, "MonoMethod") || 
3537                                            !strcmp (iltoken->member->vtable->klass->name, "MonoCMethod")) {
3538                                 MonoMethod *m = ((MonoReflectionMethod*)iltoken->member)->method;
3539                                 idx = GPOINTER_TO_UINT (mono_g_hash_table_lookup (assembly->method_to_table_idx, m));
3540                         } else {
3541                                 g_assert_not_reached ();
3542                         }
3543                         break;
3544                 case MONO_TABLE_TYPEDEF:
3545                         if (strcmp (iltoken->member->vtable->klass->name, "TypeBuilder"))
3546                                 g_assert_not_reached ();
3547                         tb = (MonoReflectionTypeBuilder *)iltoken->member;
3548                         idx = tb->table_idx;
3549                         break;
3550                 case MONO_TABLE_MEMBERREF:
3551                         if (!strcmp (iltoken->member->vtable->klass->name, "MonoArrayMethod")) {
3552                                 am = (MonoReflectionArrayMethod*)iltoken->member;
3553                                 idx = am->table_idx;
3554                         } else if (!strcmp (iltoken->member->vtable->klass->name, "MonoMethod") ||
3555                                    !strcmp (iltoken->member->vtable->klass->name, "MonoCMethod")) {
3556                                 MonoMethod *m = ((MonoReflectionMethod*)iltoken->member)->method;
3557                                 g_assert (m->klass->generic_class);
3558                                 continue;
3559                         } else if (!strcmp (iltoken->member->vtable->klass->name, "FieldBuilder")) {
3560                                 continue;
3561                         } else if (!strcmp (iltoken->member->vtable->klass->name, "MonoField")) {
3562                                 MonoClassField *f = ((MonoReflectionField*)iltoken->member)->field;
3563                                 g_assert (f->generic_info);
3564                                 continue;
3565                         } else if (!strcmp (iltoken->member->vtable->klass->name, "MethodBuilder")) {
3566                                 continue;
3567                         } else {
3568                                 g_assert_not_reached ();
3569                         }
3570                         break;
3571                 case MONO_TABLE_METHODSPEC:
3572                         if (!strcmp (iltoken->member->vtable->klass->name, "MonoMethod")) {
3573                                 MonoMethod *m = ((MonoReflectionMethod*)iltoken->member)->method;
3574                                 g_assert (m->signature->generic_param_count);
3575                                 continue;
3576                         } else {
3577                                 g_assert_not_reached ();
3578                         }
3579                         break;
3580                 default:
3581                         g_error ("got unexpected table 0x%02x in fixup", target [3]);
3582                 }
3583                 target [0] = idx & 0xff;
3584                 target [1] = (idx >> 8) & 0xff;
3585                 target [2] = (idx >> 16) & 0xff;
3586         }
3587 }
3588
3589 /*
3590  * fixup_cattrs:
3591  *
3592  *   The CUSTOM_ATTRIBUTE table might contain METHODDEF tokens whose final
3593  * value is not known when the table is emitted.
3594  */
3595 static void
3596 fixup_cattrs (MonoDynamicImage *assembly)
3597 {
3598         MonoDynamicTable *table;
3599         guint32 *values;
3600         guint32 type, i, idx, token;
3601         MonoObject *ctor;
3602
3603         table = &assembly->tables [MONO_TABLE_CUSTOMATTRIBUTE];
3604
3605         for (i = 0; i < table->rows; ++i) {
3606                 values = table->values + ((i + 1) * MONO_CUSTOM_ATTR_SIZE);
3607
3608                 type = values [MONO_CUSTOM_ATTR_TYPE];
3609                 if ((type & MONO_CUSTOM_ATTR_TYPE_MASK) == MONO_CUSTOM_ATTR_TYPE_METHODDEF) {
3610                         idx = type >> MONO_CUSTOM_ATTR_TYPE_BITS;
3611                         token = mono_metadata_make_token (MONO_TABLE_METHOD, idx);
3612                         ctor = mono_g_hash_table_lookup (assembly->tokens, GUINT_TO_POINTER (token));
3613                         g_assert (ctor);
3614
3615                         if (!strcmp (ctor->vtable->klass->name, "MonoCMethod")) {
3616                                 MonoMethod *m = ((MonoReflectionMethod*)ctor)->method;
3617                                 idx = GPOINTER_TO_UINT (mono_g_hash_table_lookup (assembly->method_to_table_idx, m));
3618                                 values [MONO_CUSTOM_ATTR_TYPE] = (idx << MONO_CUSTOM_ATTR_TYPE_BITS) | MONO_CUSTOM_ATTR_TYPE_METHODDEF;
3619                         }
3620                 }
3621         }
3622 }
3623
3624 static void
3625 assembly_add_resource_manifest (MonoReflectionModuleBuilder *mb, MonoDynamicImage *assembly, MonoReflectionResource *rsrc, guint32 implementation)
3626 {
3627         MonoDynamicTable *table;
3628         guint32 *values;
3629         char *name;
3630
3631         table = &assembly->tables [MONO_TABLE_MANIFESTRESOURCE];
3632         table->rows++;
3633         alloc_table (table, table->rows);
3634         values = table->values + table->next_idx * MONO_MANIFEST_SIZE;
3635         values [MONO_MANIFEST_OFFSET] = rsrc->offset;
3636         values [MONO_MANIFEST_FLAGS] = rsrc->attrs;
3637         name = mono_string_to_utf8 (rsrc->name);
3638         values [MONO_MANIFEST_NAME] = string_heap_insert (&assembly->sheap, name);
3639         g_free (name);
3640         values [MONO_MANIFEST_IMPLEMENTATION] = implementation;
3641         table->next_idx++;
3642 }
3643
3644 static void
3645 assembly_add_resource (MonoReflectionModuleBuilder *mb, MonoDynamicImage *assembly, MonoReflectionResource *rsrc)
3646 {
3647         MonoDynamicTable *table;
3648         guint32 *values;
3649         char blob_size [6];
3650         guchar hash [20];
3651         char *b = blob_size;
3652         char *name, *sname;
3653         guint32 idx, offset;
3654
3655         if (rsrc->filename) {
3656                 name = mono_string_to_utf8 (rsrc->filename);
3657                 sname = g_path_get_basename (name);
3658         
3659                 table = &assembly->tables [MONO_TABLE_FILE];
3660                 table->rows++;
3661                 alloc_table (table, table->rows);
3662                 values = table->values + table->next_idx * MONO_FILE_SIZE;
3663                 values [MONO_FILE_FLAGS] = FILE_CONTAINS_NO_METADATA;
3664                 values [MONO_FILE_NAME] = string_heap_insert (&assembly->sheap, sname);
3665                 g_free (sname);
3666
3667                 mono_sha1_get_digest_from_file (name, hash);
3668                 mono_metadata_encode_value (20, b, &b);
3669                 values [MONO_FILE_HASH_VALUE] = mono_image_add_stream_data (&assembly->blob, blob_size, b-blob_size);
3670                 mono_image_add_stream_data (&assembly->blob, hash, 20);
3671                 g_free (name);
3672                 idx = table->next_idx++;
3673                 rsrc->offset = 0;
3674                 idx = MONO_IMPLEMENTATION_FILE | (idx << MONO_IMPLEMENTATION_BITS);
3675         } else {
3676                 char sizebuf [4];
3677                 offset = mono_array_length (rsrc->data);
3678                 sizebuf [0] = offset; sizebuf [1] = offset >> 8;
3679                 sizebuf [2] = offset >> 16; sizebuf [3] = offset >> 24;
3680                 rsrc->offset = mono_image_add_stream_data (&assembly->resources, sizebuf, 4);
3681                 mono_image_add_stream_data (&assembly->resources, mono_array_addr (rsrc->data, char, 0), mono_array_length (rsrc->data));
3682
3683                 if (!mb->is_main)
3684                         /* 
3685                          * The entry should be emitted into the MANIFESTRESOURCE table of 
3686                          * the main module, but that needs to reference the FILE table
3687                          * which isn't emitted yet.
3688                          */
3689                         return;
3690                 else
3691                         idx = 0;
3692         }
3693
3694         assembly_add_resource_manifest (mb, assembly, rsrc, idx);
3695 }
3696
3697 static void
3698 set_version_from_string (MonoString *version, guint32 *values)
3699 {
3700         gchar *ver, *p, *str;
3701         guint32 i;
3702         
3703         values [MONO_ASSEMBLY_MAJOR_VERSION] = 0;
3704         values [MONO_ASSEMBLY_MINOR_VERSION] = 0;
3705         values [MONO_ASSEMBLY_REV_NUMBER] = 0;
3706         values [MONO_ASSEMBLY_BUILD_NUMBER] = 0;
3707         if (!version)
3708                 return;
3709         ver = str = mono_string_to_utf8 (version);
3710         for (i = 0; i < 4; ++i) {
3711                 values [MONO_ASSEMBLY_MAJOR_VERSION + i] = strtol (ver, &p, 10);
3712                 switch (*p) {
3713                 case '.':
3714                         p++;
3715                         break;
3716                 case '*':
3717                         /* handle Revision and Build */
3718                         p++;
3719                         break;
3720                 }
3721                 ver = p;
3722         }
3723         g_free (str);
3724 }
3725
3726 static guint32
3727 load_public_key (MonoArray *pkey, MonoDynamicImage *assembly) {
3728         gsize len;
3729         guint32 token = 0;
3730         char blob_size [6];
3731         char *b = blob_size;
3732
3733         if (!pkey)
3734                 return token;
3735
3736         len = mono_array_length (pkey);
3737         mono_metadata_encode_value (len, b, &b);
3738         token = mono_image_add_stream_data (&assembly->blob, blob_size, b - blob_size);
3739         mono_image_add_stream_data (&assembly->blob, mono_array_addr (pkey, guint8, 0), len);
3740
3741         /* need to get the actual value from the key type... */
3742         assembly->strong_name_size = 128;
3743         assembly->strong_name = g_malloc0 (assembly->strong_name_size);
3744
3745         return token;
3746 }
3747
3748 static void
3749 mono_image_emit_manifest (MonoReflectionModuleBuilder *moduleb)
3750 {
3751         MonoDynamicTable *table;
3752         MonoDynamicImage *assembly;
3753         MonoReflectionAssemblyBuilder *assemblyb;
3754         MonoDomain *domain;
3755         guint32 *values;
3756         char *name;
3757         int i;
3758         guint32 module_index;
3759
3760         assemblyb = moduleb->assemblyb;
3761         assembly = moduleb->dynamic_image;
3762         domain = mono_object_domain (assemblyb);
3763
3764         /* Emit ASSEMBLY table */
3765         table = &assembly->tables [MONO_TABLE_ASSEMBLY];
3766         alloc_table (table, 1);
3767         values = table->values + MONO_ASSEMBLY_SIZE;
3768         values [MONO_ASSEMBLY_HASH_ALG] = assemblyb->algid? assemblyb->algid: ASSEMBLY_HASH_SHA1;
3769         name = mono_string_to_utf8 (assemblyb->name);
3770         values [MONO_ASSEMBLY_NAME] = string_heap_insert (&assembly->sheap, name);
3771         g_free (name);
3772         if (assemblyb->culture) {
3773                 name = mono_string_to_utf8 (assemblyb->culture);
3774                 values [MONO_ASSEMBLY_CULTURE] = string_heap_insert (&assembly->sheap, name);
3775                 g_free (name);
3776         } else {
3777                 values [MONO_ASSEMBLY_CULTURE] = string_heap_insert (&assembly->sheap, "");
3778         }
3779         values [MONO_ASSEMBLY_PUBLIC_KEY] = load_public_key (assemblyb->public_key, assembly);
3780         values [MONO_ASSEMBLY_FLAGS] = assemblyb->flags;
3781         set_version_from_string (assemblyb->version, values);
3782
3783         /* Emit FILE + EXPORTED_TYPE table */
3784         module_index = 0;
3785         for (i = 0; i < mono_array_length (assemblyb->modules); ++i) {
3786                 int j;
3787                 MonoReflectionModuleBuilder *file_module = 
3788                         mono_array_get (assemblyb->modules, MonoReflectionModuleBuilder*, i);
3789                 if (file_module != moduleb) {
3790                         mono_image_fill_file_table (domain, (MonoReflectionModule*)file_module, assembly);
3791                         module_index ++;
3792                         if (file_module->types) {
3793                                 for (j = 0; j < file_module->num_types; ++j) {
3794                                         MonoReflectionTypeBuilder *tb = mono_array_get (file_module->types, MonoReflectionTypeBuilder*, j);
3795                                         mono_image_fill_export_table (domain, tb, module_index, 0, assembly);
3796                                 }
3797                         }
3798                 }
3799         }
3800         if (assemblyb->loaded_modules) {
3801                 for (i = 0; i < mono_array_length (assemblyb->loaded_modules); ++i) {
3802                         MonoReflectionModule *file_module = 
3803                                 mono_array_get (assemblyb->loaded_modules, MonoReflectionModule*, i);
3804                         mono_image_fill_file_table (domain, file_module, assembly);
3805                         module_index ++;
3806                         mono_image_fill_export_table_from_module (domain, file_module, module_index, assembly);
3807                 }
3808         }
3809
3810         /* Emit MANIFESTRESOURCE table */
3811         module_index = 0;
3812         for (i = 0; i < mono_array_length (assemblyb->modules); ++i) {
3813                 int j;
3814                 MonoReflectionModuleBuilder *file_module = 
3815                         mono_array_get (assemblyb->modules, MonoReflectionModuleBuilder*, i);
3816                 /* The table for the main module is emitted later */
3817                 if (file_module != moduleb) {
3818                         module_index ++;
3819                         if (file_module->resources) {
3820                                 int len = mono_array_length (file_module->resources);
3821                                 for (j = 0; j < len; ++j) {
3822                                         MonoReflectionResource* res = (MonoReflectionResource*)mono_array_addr (file_module->resources, MonoReflectionResource, j);
3823                                         assembly_add_resource_manifest (file_module, assembly, res, MONO_IMPLEMENTATION_FILE | (module_index << MONO_IMPLEMENTATION_BITS));
3824                                 }
3825                         }
3826                 }
3827         }               
3828 }
3829
3830 /*
3831  * mono_image_build_metadata() will fill the info in all the needed metadata tables
3832  * for the modulebuilder @moduleb.
3833  * At the end of the process, method and field tokens are fixed up and the 
3834  * on-disk compressed metadata representation is created.
3835  */
3836 void
3837 mono_image_build_metadata (MonoReflectionModuleBuilder *moduleb)
3838 {
3839         MonoDynamicTable *table;
3840         MonoDynamicImage *assembly;
3841         MonoReflectionAssemblyBuilder *assemblyb;
3842         MonoDomain *domain;
3843         guint32 *values;
3844         int i;
3845
3846         assemblyb = moduleb->assemblyb;
3847         assembly = moduleb->dynamic_image;
3848         domain = mono_object_domain (assemblyb);
3849
3850         if (assembly->text_rva)
3851                 return;
3852
3853         assembly->text_rva = START_TEXT_RVA;
3854
3855         if (moduleb->is_main) {
3856                 mono_image_emit_manifest (moduleb);
3857         }
3858
3859         table = &assembly->tables [MONO_TABLE_TYPEDEF];
3860         table->rows = 1; /* .<Module> */
3861         table->next_idx++;
3862         alloc_table (table, table->rows);
3863         /*
3864          * Set the first entry.
3865          */
3866         values = table->values + table->columns;
3867         values [MONO_TYPEDEF_FLAGS] = 0;
3868         values [MONO_TYPEDEF_NAME] = string_heap_insert (&assembly->sheap, "<Module>") ;
3869         values [MONO_TYPEDEF_NAMESPACE] = string_heap_insert (&assembly->sheap, "") ;
3870         values [MONO_TYPEDEF_EXTENDS] = 0;
3871         values [MONO_TYPEDEF_FIELD_LIST] = 1;
3872         values [MONO_TYPEDEF_METHOD_LIST] = 1;
3873
3874         /* 
3875          * handle global methods 
3876          * FIXME: test what to do when global methods are defined in multiple modules.
3877          */
3878         if (moduleb->global_methods) {
3879                 table = &assembly->tables [MONO_TABLE_METHOD];
3880                 table->rows += mono_array_length (moduleb->global_methods);
3881                 alloc_table (table, table->rows);
3882                 for (i = 0; i < mono_array_length (moduleb->global_methods); ++i)
3883                         mono_image_get_method_info (
3884                                 mono_array_get (moduleb->global_methods, MonoReflectionMethodBuilder*, i), assembly);
3885         }
3886         if (moduleb->global_fields) {
3887                 table = &assembly->tables [MONO_TABLE_FIELD];
3888                 table->rows += mono_array_length (moduleb->global_fields);
3889                 alloc_table (table, table->rows);
3890                 for (i = 0; i < mono_array_length (moduleb->global_fields); ++i)
3891                         mono_image_get_field_info (
3892                                 mono_array_get (moduleb->global_fields, MonoReflectionFieldBuilder*, i), assembly);
3893         }
3894
3895         table = &assembly->tables [MONO_TABLE_MODULE];
3896         alloc_table (table, 1);
3897         mono_image_fill_module_table (domain, moduleb, assembly);
3898
3899         /* Emit types */
3900         {
3901                 /* Collect all types into a list sorted by their table_idx */
3902                 GPtrArray *types = g_ptr_array_new ();
3903
3904                 if (moduleb->types)
3905                         for (i = 0; i < moduleb->num_types; ++i) {
3906                                 MonoReflectionTypeBuilder *type = mono_array_get (moduleb->types, MonoReflectionTypeBuilder*, i);
3907                                 collect_types (types, type);
3908                         }
3909
3910                 g_ptr_array_sort (types, (GCompareFunc)compare_types_by_table_idx);
3911                 table = &assembly->tables [MONO_TABLE_TYPEDEF];
3912                 table->rows += types->len;
3913                 alloc_table (table, table->rows);
3914
3915                 for (i = 0; i < types->len; ++i) {
3916                         MonoReflectionTypeBuilder *type = g_ptr_array_index (types, i);
3917                         mono_image_get_type_info (domain, type, assembly);
3918                 }
3919                 g_ptr_array_free (types, TRUE);
3920         }
3921
3922         /* 
3923          * table->rows is already set above and in mono_image_fill_module_table.
3924          */
3925         /* add all the custom attributes at the end, once all the indexes are stable */
3926         mono_image_add_cattrs (assembly, 1, MONO_CUSTOM_ATTR_ASSEMBLY, assemblyb->cattrs);
3927
3928         /* CAS assembly permissions */
3929         if (assemblyb->permissions_minimum)
3930                 mono_image_add_decl_security (assembly, mono_metadata_make_token (MONO_TABLE_ASSEMBLY, 1), assemblyb->permissions_minimum);
3931         if (assemblyb->permissions_optional)
3932                 mono_image_add_decl_security (assembly, mono_metadata_make_token (MONO_TABLE_ASSEMBLY, 1), assemblyb->permissions_optional);
3933         if (assemblyb->permissions_refused)
3934                 mono_image_add_decl_security (assembly, mono_metadata_make_token (MONO_TABLE_ASSEMBLY, 1), assemblyb->permissions_refused);
3935
3936         module_add_cattrs (assembly, moduleb);
3937
3938         /* fixup tokens */
3939         mono_g_hash_table_foreach (assembly->token_fixups, (GHFunc)fixup_method, assembly);
3940         fixup_cattrs (assembly);
3941 }
3942
3943 /*
3944  * mono_image_insert_string:
3945  * @module: module builder object
3946  * @str: a string
3947  *
3948  * Insert @str into the user string stream of @module.
3949  */
3950 guint32
3951 mono_image_insert_string (MonoReflectionModuleBuilder *module, MonoString *str)
3952 {
3953         MonoDynamicImage *assembly;
3954         guint32 idx;
3955         char buf [16];
3956         char *b = buf;
3957         
3958         MONO_ARCH_SAVE_REGS;
3959
3960         if (!module->dynamic_image)
3961                 mono_image_module_basic_init (module);
3962
3963         assembly = module->dynamic_image;
3964         
3965         if (assembly->save) {
3966                 mono_metadata_encode_value (1 | (str->length * 2), b, &b);
3967                 idx = mono_image_add_stream_data (&assembly->us, buf, b-buf);
3968 #if G_BYTE_ORDER != G_LITTLE_ENDIAN
3969         {
3970                 char *swapped = g_malloc (2 * mono_string_length (str));
3971                 const char *p = (const char*)mono_string_chars (str);
3972
3973                 swap_with_size (swapped, p, 2, mono_string_length (str));
3974                 mono_image_add_stream_data (&assembly->us, swapped, str->length * 2);
3975                 g_free (swapped);
3976         }
3977 #else
3978                 mono_image_add_stream_data (&assembly->us, (const char*)mono_string_chars (str), str->length * 2);
3979 #endif
3980                 mono_image_add_stream_data (&assembly->us, "", 1);
3981         } else {
3982                 idx = assembly->us.index ++;
3983         }
3984
3985         mono_g_hash_table_insert (assembly->tokens, GUINT_TO_POINTER (MONO_TOKEN_STRING | idx), str);
3986
3987         return MONO_TOKEN_STRING | idx;
3988 }
3989
3990 guint32
3991 mono_image_create_method_token (MonoDynamicImage *assembly, MonoObject *obj, MonoArray *opt_param_types)
3992 {
3993         MonoClass *klass;
3994         guint32 token = 0;
3995
3996         klass = obj->vtable->klass;
3997         if (strcmp (klass->name, "MonoMethod") == 0) {
3998                 MonoMethod *method = ((MonoReflectionMethod *)obj)->method;
3999                 MonoMethodSignature *sig, *old;
4000                 guint32 sig_token, parent;
4001                 int nargs, i;
4002
4003                 g_assert (opt_param_types && (method->signature->sentinelpos >= 0));
4004
4005                 nargs = mono_array_length (opt_param_types);
4006                 old = method->signature;
4007                 sig = mono_metadata_signature_alloc ( &assembly->image, old->param_count + nargs);
4008
4009                 sig->hasthis = old->hasthis;
4010                 sig->explicit_this = old->explicit_this;
4011                 sig->call_convention = old->call_convention;
4012                 sig->generic_param_count = old->generic_param_count;
4013                 sig->param_count = old->param_count + nargs;
4014                 sig->sentinelpos = old->param_count;
4015                 sig->ret = old->ret;
4016
4017                 for (i = 0; i < old->param_count; i++)
4018                         sig->params [i] = old->params [i];
4019
4020                 for (i = 0; i < nargs; i++) {
4021                         MonoReflectionType *rt = mono_array_get (opt_param_types, MonoReflectionType *, i);
4022                         sig->params [old->param_count + i] = rt->type;
4023                 }
4024
4025                 parent = mono_image_typedef_or_ref (assembly, &method->klass->byval_arg);
4026                 g_assert ((parent & MONO_TYPEDEFORREF_MASK) == MONO_MEMBERREF_PARENT_TYPEREF);
4027                 parent >>= MONO_TYPEDEFORREF_BITS;
4028
4029                 parent <<= MONO_MEMBERREF_PARENT_BITS;
4030                 parent |= MONO_MEMBERREF_PARENT_TYPEREF;
4031
4032                 sig_token = method_encode_signature (assembly, sig);
4033                 token = mono_image_get_varargs_method_token (assembly, parent, method->name, sig_token);
4034         } else if (strcmp (klass->name, "MethodBuilder") == 0) {
4035                 MonoReflectionMethodBuilder *mb = (MonoReflectionMethodBuilder *)obj;
4036                 ReflectionMethodBuilder rmb;
4037                 guint32 parent, sig;
4038         
4039                 reflection_methodbuilder_from_method_builder (&rmb, mb);
4040                 rmb.opt_types = opt_param_types;
4041
4042                 sig = method_builder_encode_signature (assembly, &rmb);
4043
4044                 parent = mono_image_create_token (assembly, obj, TRUE);
4045                 g_assert (mono_metadata_token_table (parent) == MONO_TABLE_METHOD);
4046
4047                 parent = mono_metadata_token_index (parent) << MONO_MEMBERREF_PARENT_BITS;
4048                 parent |= MONO_MEMBERREF_PARENT_METHODDEF;
4049
4050                 token = mono_image_get_varargs_method_token (
4051                         assembly, parent, mono_string_to_utf8 (rmb.name), sig);
4052         } else {
4053                 g_error ("requested method token for %s\n", klass->name);
4054         }
4055
4056         return token;
4057 }
4058
4059 /*
4060  * mono_image_create_token:
4061  * @assembly: a dynamic assembly
4062  * @obj:
4063  *
4064  * Get a token to insert in the IL code stream for the given MemberInfo.
4065  * @obj can be one of:
4066  *      ConstructorBuilder
4067  *      MethodBuilder
4068  *      FieldBuilder
4069  *      MonoCMethod
4070  *      MonoMethod
4071  *      MonoField
4072  *      MonoType
4073  *      TypeBuilder
4074  */
4075 guint32
4076 mono_image_create_token (MonoDynamicImage *assembly, MonoObject *obj, gboolean create_methodspec)
4077 {
4078         MonoClass *klass;
4079         guint32 token = 0;
4080
4081         klass = obj->vtable->klass;
4082         if (strcmp (klass->name, "MethodBuilder") == 0) {
4083                 MonoReflectionMethodBuilder *mb = (MonoReflectionMethodBuilder *)obj;
4084
4085                 if (((MonoReflectionTypeBuilder*)mb->type)->module->dynamic_image == assembly)
4086                         token = mb->table_idx | MONO_TOKEN_METHOD_DEF;
4087                 else
4088                         token = mono_image_get_methodbuilder_token (assembly, mb);
4089                 /*g_print ("got token 0x%08x for %s\n", token, mono_string_to_utf8 (mb->name));*/
4090         } else if (strcmp (klass->name, "ConstructorBuilder") == 0) {
4091                 MonoReflectionCtorBuilder *mb = (MonoReflectionCtorBuilder *)obj;
4092
4093                 if (((MonoReflectionTypeBuilder*)mb->type)->module->dynamic_image == assembly)
4094                         token = mb->table_idx | MONO_TOKEN_METHOD_DEF;
4095                 else
4096                         token = mono_image_get_ctorbuilder_token (assembly, mb);
4097                 /*g_print ("got token 0x%08x for %s\n", token, mono_string_to_utf8 (mb->name));*/
4098         } else if (strcmp (klass->name, "FieldBuilder") == 0) {
4099                 MonoReflectionFieldBuilder *fb = (MonoReflectionFieldBuilder *)obj;
4100                 MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder *)fb->typeb;
4101                 if (tb->generic_params) {
4102                         token = mono_image_get_generic_field_token (assembly, fb);
4103                 } else {
4104                         token = fb->table_idx | MONO_TOKEN_FIELD_DEF;
4105                 }
4106         } else if (strcmp (klass->name, "TypeBuilder") == 0) {
4107                 MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder *)obj;
4108                 token = tb->table_idx | MONO_TOKEN_TYPE_DEF;
4109         } else if (strcmp (klass->name, "MonoType") == 0 ||
4110                  strcmp (klass->name, "GenericTypeParameterBuilder") == 0) {
4111                 MonoReflectionType *tb = (MonoReflectionType *)obj;
4112                 token = mono_metadata_token_from_dor (
4113                         mono_image_typedef_or_ref (assembly, tb->type));
4114         } else if (strcmp (klass->name, "MonoGenericClass") == 0) {
4115                 MonoReflectionType *tb = (MonoReflectionType *)obj;
4116                 token = mono_metadata_token_from_dor (
4117                         mono_image_typedef_or_ref (assembly, tb->type));
4118         } else if (strcmp (klass->name, "MonoCMethod") == 0 ||
4119                         strcmp (klass->name, "MonoMethod") == 0) {
4120                 MonoReflectionMethod *m = (MonoReflectionMethod *)obj;
4121                 if (m->method->signature->is_inflated) {
4122                         if (create_methodspec)
4123                                 token = mono_image_get_methodspec_token (assembly, m->method);
4124                         else
4125                                 token = mono_image_get_inflated_method_token (assembly, m->method);
4126                 } else if ((m->method->klass->image == &assembly->image) &&
4127                          !m->method->klass->generic_class) {
4128                         static guint32 method_table_idx = 0xffffff;
4129                         if (m->method->klass->wastypebuilder) {
4130                                 /* we use the same token as the one that was assigned
4131                                  * to the Methodbuilder.
4132                                  * FIXME: do the equivalent for Fields.
4133                                  */
4134                                 token = m->method->token;
4135                         } else {
4136                                 /*
4137                                  * Each token should have a unique index, but the indexes are
4138                                  * assigned by managed code, so we don't know about them. An
4139                                  * easy solution is to count backwards...
4140                                  */
4141                                 method_table_idx --;
4142                                 token = MONO_TOKEN_METHOD_DEF | method_table_idx;
4143                         }
4144                 } else {
4145                         token = mono_image_get_methodref_token (assembly, m->method);
4146                 }
4147                 /*g_print ("got token 0x%08x for %s\n", token, m->method->name);*/
4148         } else if (strcmp (klass->name, "MonoField") == 0) {
4149                 MonoReflectionField *f = (MonoReflectionField *)obj;
4150                 if ((f->klass->image == &assembly->image) && !f->field->generic_info) {
4151                         static guint32 field_table_idx = 0xffffff;
4152                         field_table_idx --;
4153                         token = MONO_TOKEN_FIELD_DEF | field_table_idx;
4154                 } else {
4155                         token = mono_image_get_fieldref_token (assembly, f);
4156                 }
4157                 /*g_print ("got token 0x%08x for %s\n", token, f->field->name);*/
4158         } else if (strcmp (klass->name, "MonoArrayMethod") == 0) {
4159                 MonoReflectionArrayMethod *m = (MonoReflectionArrayMethod *)obj;
4160                 token = mono_image_get_array_token (assembly, m);
4161         } else if (strcmp (klass->name, "SignatureHelper") == 0) {
4162                 MonoReflectionSigHelper *s = (MonoReflectionSigHelper*)obj;
4163                 token = MONO_TOKEN_SIGNATURE | mono_image_get_sighelper_token (assembly, s);
4164         } else {
4165                 g_error ("requested token for %s\n", klass->name);
4166         }
4167
4168         mono_g_hash_table_insert (assembly->tokens, GUINT_TO_POINTER (token), obj);
4169
4170         return token;
4171 }
4172
4173 typedef struct {
4174         guint32 import_lookup_table;
4175         guint32 timestamp;
4176         guint32 forwarder;
4177         guint32 name_rva;
4178         guint32 import_address_table_rva;
4179 } MonoIDT;
4180
4181 typedef struct {
4182         guint32 name_rva;
4183         guint32 flags;
4184 } MonoILT;
4185
4186 static void register_assembly (MonoDomain *domain, MonoReflectionAssembly *res, MonoAssembly *assembly);
4187
4188 static MonoDynamicImage*
4189 create_dynamic_mono_image (MonoDynamicAssembly *assembly, char *assembly_name, char *module_name)
4190 {
4191         static const guchar entrycode [16] = {0xff, 0x25, 0};
4192         MonoDynamicImage *image;
4193         int i;
4194
4195         const char *version = mono_get_runtime_version ();
4196
4197 #if HAVE_BOEHM_GC
4198         image = GC_MALLOC (sizeof (MonoDynamicImage));
4199 #else
4200         image = g_new0 (MonoDynamicImage, 1);
4201 #endif
4202
4203         /* keep in sync with image.c */
4204         image->image.name = assembly_name;
4205         image->image.assembly_name = image->image.name; /* they may be different */
4206         image->image.module_name = module_name;
4207         image->image.version = g_strdup (version);
4208         image->image.dynamic = TRUE;
4209
4210         image->image.references = g_new0 (MonoAssembly*, 1);
4211         image->image.references [0] = NULL;
4212
4213         mono_image_init (&image->image);
4214
4215         image->token_fixups = mono_g_hash_table_new (NULL, NULL);
4216         image->method_to_table_idx = mono_g_hash_table_new (NULL, NULL);
4217         image->field_to_table_idx = mono_g_hash_table_new (NULL, NULL);
4218         image->method_aux_hash = mono_g_hash_table_new (NULL, NULL);
4219         image->handleref = g_hash_table_new (NULL, NULL);
4220         image->tokens = mono_g_hash_table_new (NULL, NULL);
4221         image->typespec = g_hash_table_new ((GHashFunc)mono_metadata_type_hash, (GCompareFunc)mono_metadata_type_equal);
4222         image->typeref = g_hash_table_new ((GHashFunc)mono_metadata_type_hash, (GCompareFunc)mono_metadata_type_equal);
4223         image->blob_cache = mono_g_hash_table_new ((GHashFunc)mono_blob_entry_hash, (GCompareFunc)mono_blob_entry_equal);
4224         image->gen_params = g_ptr_array_new ();
4225
4226         string_heap_init (&image->sheap);
4227         mono_image_add_stream_data (&image->us, "", 1);
4228         add_to_blob_cached (image, (char*) "", 1, NULL, 0);
4229         /* import tables... */
4230         mono_image_add_stream_data (&image->code, entrycode, sizeof (entrycode));
4231         image->iat_offset = mono_image_add_stream_zero (&image->code, 8); /* two IAT entries */
4232         image->idt_offset = mono_image_add_stream_zero (&image->code, 2 * sizeof (MonoIDT)); /* two IDT entries */
4233         image->imp_names_offset = mono_image_add_stream_zero (&image->code, 2); /* flags for name entry */
4234         mono_image_add_stream_data (&image->code, "_CorExeMain", 12);
4235         mono_image_add_stream_data (&image->code, "mscoree.dll", 12);
4236         image->ilt_offset = mono_image_add_stream_zero (&image->code, 8); /* two ILT entries */
4237         stream_data_align (&image->code);
4238
4239         image->cli_header_offset = mono_image_add_stream_zero (&image->code, sizeof (MonoCLIHeader));
4240
4241         for (i=0; i < 64; ++i) {
4242                 image->tables [i].next_idx = 1;
4243                 image->tables [i].columns = table_sizes [i];
4244         }
4245
4246         image->image.assembly = (MonoAssembly*)assembly;
4247         image->run = assembly->run;
4248         image->save = assembly->save;
4249         image->pe_kind = 0x1; /* ILOnly */
4250         image->machine = 0x14c; /* I386 */
4251
4252         return image;
4253 }
4254
4255 /*
4256  * mono_image_basic_init:
4257  * @assembly: an assembly builder object
4258  *
4259  * Create the MonoImage that represents the assembly builder and setup some
4260  * of the helper hash table and the basic metadata streams.
4261  */
4262 void
4263 mono_image_basic_init (MonoReflectionAssemblyBuilder *assemblyb)
4264 {
4265         MonoDynamicAssembly *assembly;
4266         MonoDynamicImage *image;
4267         
4268         MONO_ARCH_SAVE_REGS;
4269
4270         if (assemblyb->dynamic_assembly)
4271                 return;
4272
4273 #if HAVE_BOEHM_GC
4274         assembly = assemblyb->dynamic_assembly = GC_MALLOC (sizeof (MonoDynamicAssembly));
4275 #else
4276         assembly = assemblyb->dynamic_assembly = g_new0 (MonoDynamicImage, 1);
4277 #endif
4278
4279         assembly->assembly.dynamic = TRUE;
4280         assembly->assembly.corlib_internal = assemblyb->corlib_internal;
4281         assemblyb->assembly.assembly = (MonoAssembly*)assembly;
4282         assembly->assembly.basedir = mono_string_to_utf8 (assemblyb->dir);
4283         if (assemblyb->culture)
4284                 assembly->assembly.aname.culture = mono_string_to_utf8 (assemblyb->culture);
4285         else
4286                 assembly->assembly.aname.culture = g_strdup ("");
4287
4288         assembly->run = assemblyb->access != 2;
4289         assembly->save = assemblyb->access != 1;
4290
4291         image = create_dynamic_mono_image (assembly, mono_string_to_utf8 (assemblyb->name), g_strdup ("RefEmit_YouForgotToDefineAModule"));
4292         image->initial_image = TRUE;
4293         assembly->assembly.aname.name = image->image.name;
4294         assembly->assembly.image = &image->image;
4295
4296         register_assembly (mono_object_domain (assemblyb), &assemblyb->assembly, &assembly->assembly);
4297         mono_assembly_invoke_load_hook ((MonoAssembly*)assembly);
4298 }
4299
4300 static int
4301 calc_section_size (MonoDynamicImage *assembly)
4302 {
4303         int nsections = 0;
4304
4305         /* alignment constraints */
4306         assembly->code.index += 3;
4307         assembly->code.index &= ~3;
4308         assembly->meta_size += 3;
4309         assembly->meta_size &= ~3;
4310         assembly->resources.index += 3;
4311         assembly->resources.index &= ~3;
4312
4313         assembly->sections [MONO_SECTION_TEXT].size = assembly->meta_size + assembly->code.index + assembly->resources.index + assembly->strong_name_size;
4314         assembly->sections [MONO_SECTION_TEXT].attrs = SECT_FLAGS_HAS_CODE | SECT_FLAGS_MEM_EXECUTE | SECT_FLAGS_MEM_READ;
4315         nsections++;
4316
4317         if (assembly->win32_res) {
4318                 guint32 res_size = (assembly->win32_res_size + 3) & ~3;
4319
4320                 assembly->sections [MONO_SECTION_RSRC].size = res_size;
4321                 assembly->sections [MONO_SECTION_RSRC].attrs = SECT_FLAGS_HAS_INITIALIZED_DATA | SECT_FLAGS_MEM_READ;
4322                 nsections++;
4323         }
4324
4325         assembly->sections [MONO_SECTION_RELOC].size = 12;
4326         assembly->sections [MONO_SECTION_RELOC].attrs = SECT_FLAGS_MEM_READ | SECT_FLAGS_MEM_DISCARDABLE | SECT_FLAGS_HAS_INITIALIZED_DATA;
4327         nsections++;
4328
4329         return nsections;
4330 }
4331
4332 typedef struct {
4333         guint32 id;
4334         guint32 offset;
4335         GSList *children;
4336         MonoReflectionWin32Resource *win32_res; /* Only for leaf nodes */
4337 } ResTreeNode;
4338
4339 static int
4340 resource_tree_compare_by_id (gconstpointer a, gconstpointer b)
4341 {
4342         ResTreeNode *t1 = (ResTreeNode*)a;
4343         ResTreeNode *t2 = (ResTreeNode*)b;
4344
4345         return t1->id - t2->id;
4346 }
4347
4348 /*
4349  * resource_tree_create:
4350  *
4351  *  Organize the resources into a resource tree.
4352  */
4353 static ResTreeNode *
4354 resource_tree_create (MonoArray *win32_resources)
4355 {
4356         ResTreeNode *tree, *res_node, *type_node, *lang_node;
4357         GSList *l;
4358         int i;
4359
4360         tree = g_new0 (ResTreeNode, 1);
4361         
4362         for (i = 0; i < mono_array_length (win32_resources); ++i) {
4363                 MonoReflectionWin32Resource *win32_res =
4364                         (MonoReflectionWin32Resource*)mono_array_addr (win32_resources, MonoReflectionWin32Resource, i);
4365
4366                 /* Create node */
4367
4368                 lang_node = g_new0 (ResTreeNode, 1);
4369                 lang_node->id = win32_res->lang_id;
4370                 lang_node->win32_res = win32_res;
4371
4372                 /* Create type node if neccesary */
4373                 type_node = NULL;
4374                 for (l = tree->children; l; l = l->next)
4375                         if (((ResTreeNode*)(l->data))->id == win32_res->res_type) {
4376                                 type_node = (ResTreeNode*)l->data;
4377                                 break;
4378                         }
4379
4380                 if (!type_node) {
4381                         type_node = g_new0 (ResTreeNode, 1);
4382                         type_node->id = win32_res->res_type;
4383
4384                         /* 
4385                          * The resource types have to be sorted otherwise
4386                          * Windows Explorer can't display the version information.
4387                          */
4388                         tree->children = g_slist_insert_sorted (tree->children, 
4389                                 type_node, resource_tree_compare_by_id);
4390                 }
4391
4392                 /* Create res node if neccesary */
4393                 res_node = NULL;
4394                 for (l = type_node->children; l; l = l->next)
4395                         if (((ResTreeNode*)(l->data))->id == win32_res->res_id) {
4396                                 res_node = (ResTreeNode*)l->data;
4397                                 break;
4398                         }
4399
4400                 if (!res_node) {
4401                         res_node = g_new0 (ResTreeNode, 1);
4402                         res_node->id = win32_res->res_id;
4403                         type_node->children = g_slist_append (type_node->children, res_node);
4404                 }
4405
4406                 res_node->children = g_slist_append (res_node->children, lang_node);
4407         }
4408
4409         return tree;
4410 }
4411
4412 /*
4413  * resource_tree_encode:
4414  * 
4415  *   Encode the resource tree into the format used in the PE file.
4416  */
4417 static void
4418 resource_tree_encode (ResTreeNode *node, char *begin, char *p, char **endbuf)
4419 {
4420         char *entries;
4421         MonoPEResourceDir dir;
4422         MonoPEResourceDirEntry dir_entry;
4423         MonoPEResourceDataEntry data_entry;
4424         GSList *l;
4425
4426         /*
4427          * For the format of the resource directory, see the article
4428          * "An In-Depth Look into the Win32 Portable Executable File Format" by
4429          * Matt Pietrek
4430          */
4431
4432         memset (&dir, 0, sizeof (dir));
4433         memset (&dir_entry, 0, sizeof (dir_entry));
4434         memset (&data_entry, 0, sizeof (data_entry));
4435
4436         g_assert (sizeof (dir) == 16);
4437         g_assert (sizeof (dir_entry) == 8);
4438         g_assert (sizeof (data_entry) == 16);
4439
4440         node->offset = p - begin;
4441
4442         /* IMAGE_RESOURCE_DIRECTORY */
4443         dir.res_id_entries = GUINT32_TO_LE (g_slist_length (node->children));
4444
4445         memcpy (p, &dir, sizeof (dir));
4446         p += sizeof (dir);
4447
4448         /* Reserve space for entries */
4449         entries = p;
4450         p += sizeof (dir_entry) * dir.res_id_entries;
4451
4452         /* Write children */
4453         for (l = node->children; l; l = l->next) {
4454                 ResTreeNode *child = (ResTreeNode*)l->data;
4455
4456                 if (child->win32_res) {
4457
4458                         child->offset = p - begin;
4459
4460                         /* IMAGE_RESOURCE_DATA_ENTRY */
4461                         data_entry.rde_data_offset = GUINT32_TO_LE (p - begin + sizeof (data_entry));
4462                         data_entry.rde_size = mono_array_length (child->win32_res->res_data);
4463
4464                         memcpy (p, &data_entry, sizeof (data_entry));
4465                         p += sizeof (data_entry);
4466
4467                         memcpy (p, mono_array_addr (child->win32_res->res_data, char, 0), data_entry.rde_size);
4468                         p += data_entry.rde_size;
4469                 } else {
4470                         resource_tree_encode (child, begin, p, &p);
4471                 }
4472         }
4473
4474         /* IMAGE_RESOURCE_ENTRY */
4475         for (l = node->children; l; l = l->next) {
4476                 ResTreeNode *child = (ResTreeNode*)l->data;
4477                 dir_entry.name_offset = GUINT32_TO_LE (child->id);
4478
4479                 dir_entry.is_dir = child->win32_res ? 0 : 1;
4480                 dir_entry.dir_offset = GUINT32_TO_LE (child->offset);
4481
4482                 memcpy (entries, &dir_entry, sizeof (dir_entry));
4483                 entries += sizeof (dir_entry);
4484         }
4485
4486         *endbuf = p;
4487 }
4488
4489 static void
4490 assembly_add_win32_resources (MonoDynamicImage *assembly, MonoReflectionAssemblyBuilder *assemblyb)
4491 {
4492         char *buf;
4493         char *p;
4494         guint32 size, i;
4495         MonoReflectionWin32Resource *win32_res;
4496         ResTreeNode *tree;
4497
4498         if (!assemblyb->win32_resources)
4499                 return;
4500
4501         /*
4502          * Resources are stored in a three level tree inside the PE file.
4503          * - level one contains a node for each type of resource
4504          * - level two contains a node for each resource
4505          * - level three contains a node for each instance of a resource for a
4506          *   specific language.
4507          */
4508
4509         tree = resource_tree_create (assemblyb->win32_resources);
4510
4511         /* Estimate the size of the encoded tree */
4512         size = 0;
4513         for (i = 0; i < mono_array_length (assemblyb->win32_resources); ++i) {
4514                 win32_res = (MonoReflectionWin32Resource*)mono_array_addr (assemblyb->win32_resources, MonoReflectionWin32Resource, i);
4515                 size += mono_array_length (win32_res->res_data);
4516         }
4517         /* Directory structure */
4518         size += mono_array_length (assemblyb->win32_resources) * 256;
4519         p = buf = g_malloc (size);
4520
4521         resource_tree_encode (tree, p, p, &p);
4522
4523         g_assert (p - buf < size);
4524
4525         assembly->win32_res = g_malloc (p - buf);
4526         assembly->win32_res_size = p - buf;
4527         memcpy (assembly->win32_res, buf, p - buf);
4528
4529         g_free (buf);
4530 }
4531
4532 static void
4533 fixup_resource_directory (char *res_section, char *p, guint32 rva)
4534 {
4535         MonoPEResourceDir *dir = (MonoPEResourceDir*)p;
4536         int i;
4537
4538         p += sizeof (MonoPEResourceDir);
4539         for (i = 0; i < dir->res_named_entries + dir->res_id_entries; ++i) {
4540                 MonoPEResourceDirEntry *dir_entry = (MonoPEResourceDirEntry*)p;
4541                 char *child = res_section + (GUINT32_FROM_LE (dir_entry->dir_offset));
4542                 if (dir_entry->is_dir) {
4543                         fixup_resource_directory (res_section, child, rva);
4544                 } else {
4545                         MonoPEResourceDataEntry *data_entry = (MonoPEResourceDataEntry*)child;
4546                         data_entry->rde_data_offset = GUINT32_TO_LE (GUINT32_FROM_LE (data_entry->rde_data_offset) + rva);
4547                 }
4548
4549                 p += sizeof (MonoPEResourceDirEntry);
4550         }
4551 }
4552
4553 static void
4554 checked_write_file (HANDLE f, gconstpointer buffer, guint32 numbytes)
4555 {
4556         guint32 dummy;
4557         if (!WriteFile (f, buffer, numbytes, &dummy, NULL))
4558                 g_error ("WriteFile returned %d\n", GetLastError ());
4559 }
4560
4561 /*
4562  * mono_image_create_pefile:
4563  * @mb: a module builder object
4564  * 
4565  * This function creates the PE-COFF header, the image sections, the CLI header  * etc. all the data is written in
4566  * assembly->pefile where it can be easily retrieved later in chunks.
4567  */
4568 void
4569 mono_image_create_pefile (MonoReflectionModuleBuilder *mb, HANDLE file) {
4570         MonoMSDOSHeader *msdos;
4571         MonoDotNetHeader *header;
4572         MonoSectionTable *section;
4573         MonoCLIHeader *cli_header;
4574         guint32 size, image_size, virtual_base, text_offset;
4575         guint32 header_start, section_start, file_offset, virtual_offset;
4576         MonoDynamicImage *assembly;
4577         MonoReflectionAssemblyBuilder *assemblyb;
4578         MonoDynamicStream pefile_stream = {0};
4579         MonoDynamicStream *pefile = &pefile_stream;
4580         int i, nsections;
4581         guint32 *rva, value;
4582         guchar *p;
4583         static const unsigned char msheader[] = {
4584                 0x4d, 0x5a, 0x90, 0x00, 0x03, 0x00, 0x00, 0x00,  0x04, 0x00, 0x00, 0x00, 0xff, 0xff, 0x00, 0x00,
4585                 0xb8, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,  0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
4586                 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
4587                 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,  0x00, 0x00, 0x00, 0x00, 0x80, 0x00, 0x00, 0x00,
4588                 0x0e, 0x1f, 0xba, 0x0e, 0x00, 0xb4, 0x09, 0xcd,  0x21, 0xb8, 0x01, 0x4c, 0xcd, 0x21, 0x54, 0x68,
4589                 0x69, 0x73, 0x20, 0x70, 0x72, 0x6f, 0x67, 0x72,  0x61, 0x6d, 0x20, 0x63, 0x61, 0x6e, 0x6e, 0x6f,
4590                 0x74, 0x20, 0x62, 0x65, 0x20, 0x72, 0x75, 0x6e,  0x20, 0x69, 0x6e, 0x20, 0x44, 0x4f, 0x53, 0x20,
4591                 0x6d, 0x6f, 0x64, 0x65, 0x2e, 0x0d, 0x0d, 0x0a,  0x24, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
4592         };
4593
4594         assemblyb = mb->assemblyb;
4595
4596         mono_image_basic_init (assemblyb);
4597         assembly = mb->dynamic_image;
4598
4599         assembly->pe_kind = assemblyb->pe_kind;
4600         assembly->machine = assemblyb->machine;
4601         ((MonoDynamicImage*)assemblyb->dynamic_assembly->assembly.image)->pe_kind = assemblyb->pe_kind;
4602         ((MonoDynamicImage*)assemblyb->dynamic_assembly->assembly.image)->machine = assemblyb->machine;
4603         
4604         mono_image_build_metadata (mb);
4605
4606         if (mb->is_main && assemblyb->resources) {
4607                 int len = mono_array_length (assemblyb->resources);
4608                 for (i = 0; i < len; ++i)
4609                         assembly_add_resource (mb, assembly, (MonoReflectionResource*)mono_array_addr (assemblyb->resources, MonoReflectionResource, i));
4610         }
4611
4612         if (mb->resources) {
4613                 int len = mono_array_length (mb->resources);
4614                 for (i = 0; i < len; ++i)
4615                         assembly_add_resource (mb, assembly, (MonoReflectionResource*)mono_array_addr (mb->resources, MonoReflectionResource, i));
4616         }
4617
4618         build_compressed_metadata (assembly);
4619
4620         if (mb->is_main)
4621                 assembly_add_win32_resources (assembly, assemblyb);
4622
4623         nsections = calc_section_size (assembly);
4624         
4625         /* The DOS header and stub */
4626         g_assert (sizeof (MonoMSDOSHeader) == sizeof (msheader));
4627         mono_image_add_stream_data (pefile, msheader, sizeof (msheader));
4628
4629         /* the dotnet header */
4630         header_start = mono_image_add_stream_zero (pefile, sizeof (MonoDotNetHeader));
4631
4632         /* the section tables */
4633         section_start = mono_image_add_stream_zero (pefile, sizeof (MonoSectionTable) * nsections);
4634
4635         file_offset = section_start + sizeof (MonoSectionTable) * nsections;
4636         virtual_offset = VIRT_ALIGN;
4637         image_size = 0;
4638
4639         for (i = 0; i < MONO_SECTION_MAX; ++i) {
4640                 if (!assembly->sections [i].size)
4641                         continue;
4642                 /* align offsets */
4643                 file_offset += FILE_ALIGN - 1;
4644                 file_offset &= ~(FILE_ALIGN - 1);
4645                 virtual_offset += VIRT_ALIGN - 1;
4646                 virtual_offset &= ~(VIRT_ALIGN - 1);
4647
4648                 assembly->sections [i].offset = file_offset;
4649                 assembly->sections [i].rva = virtual_offset;
4650
4651                 file_offset += assembly->sections [i].size;
4652                 virtual_offset += assembly->sections [i].size;
4653                 image_size += (assembly->sections [i].size + VIRT_ALIGN - 1) & ~(VIRT_ALIGN - 1);
4654         }
4655
4656         file_offset += FILE_ALIGN - 1;
4657         file_offset &= ~(FILE_ALIGN - 1);
4658
4659         image_size += section_start + sizeof (MonoSectionTable) * nsections;
4660
4661         /* back-patch info */
4662         msdos = (MonoMSDOSHeader*)pefile->data;
4663         msdos->nlast_page = GUINT16_FROM_LE (file_offset & (512 - 1));
4664         msdos->npages = GUINT16_FROM_LE ((file_offset + (512 - 1)) / 512);
4665         msdos->pe_offset = GUINT32_FROM_LE (sizeof (MonoMSDOSHeader));
4666
4667         header = (MonoDotNetHeader*)(pefile->data + header_start);
4668         header->pesig [0] = 'P';
4669         header->pesig [1] = 'E';
4670         
4671         header->coff.coff_machine = GUINT16_FROM_LE (assemblyb->machine);
4672         header->coff.coff_sections = GUINT16_FROM_LE (nsections);
4673         header->coff.coff_time = GUINT32_FROM_LE (time (NULL));
4674         header->coff.coff_opt_header_size = GUINT16_FROM_LE (sizeof (MonoDotNetHeader) - sizeof (MonoCOFFHeader) - 4);
4675         if (assemblyb->pekind == 1) {
4676                 /* it's a dll */
4677                 header->coff.coff_attributes = GUINT16_FROM_LE (0x210e);
4678         } else {
4679                 /* it's an exe */
4680                 header->coff.coff_attributes = GUINT16_FROM_LE (0x010e);
4681         }
4682
4683         virtual_base = 0x400000; /* FIXME: 0x10000000 if a DLL */
4684
4685         header->pe.pe_magic = GUINT16_FROM_LE (0x10B);
4686         header->pe.pe_major = 6;
4687         header->pe.pe_minor = 0;
4688         size = assembly->sections [MONO_SECTION_TEXT].size;
4689         size += FILE_ALIGN - 1;
4690         size &= ~(FILE_ALIGN - 1);
4691         header->pe.pe_code_size = GUINT32_FROM_LE(size);
4692         size = assembly->sections [MONO_SECTION_RSRC].size;
4693         size += FILE_ALIGN - 1;
4694         size &= ~(FILE_ALIGN - 1);
4695         header->pe.pe_data_size = GUINT32_FROM_LE(size);
4696         g_assert (START_TEXT_RVA == assembly->sections [MONO_SECTION_TEXT].rva);
4697         header->pe.pe_rva_code_base = GUINT32_FROM_LE (assembly->sections [MONO_SECTION_TEXT].rva);
4698         header->pe.pe_rva_data_base = GUINT32_FROM_LE (assembly->sections [MONO_SECTION_RSRC].rva);
4699         /* pe_rva_entry_point always at the beginning of the text section */
4700         header->pe.pe_rva_entry_point = GUINT32_FROM_LE (assembly->sections [MONO_SECTION_TEXT].rva);
4701
4702         header->nt.pe_image_base = GUINT32_FROM_LE (virtual_base);
4703         header->nt.pe_section_align = GUINT32_FROM_LE (VIRT_ALIGN);
4704         header->nt.pe_file_alignment = GUINT32_FROM_LE (FILE_ALIGN);
4705         header->nt.pe_os_major = GUINT16_FROM_LE (4);
4706         header->nt.pe_os_minor = GUINT16_FROM_LE (0);
4707         header->nt.pe_subsys_major = GUINT16_FROM_LE (4);
4708         size = section_start;
4709         size += FILE_ALIGN - 1;
4710         size &= ~(FILE_ALIGN - 1);
4711         header->nt.pe_header_size = GUINT32_FROM_LE (size);
4712         size = image_size;
4713         size += VIRT_ALIGN - 1;
4714         size &= ~(VIRT_ALIGN - 1);
4715         header->nt.pe_image_size = GUINT32_FROM_LE (size);
4716
4717         /*
4718         // Translate the PEFileKind value to the value expected by the Windows loader
4719         */
4720         {
4721                 short kind;
4722
4723                 /*
4724                 // PEFileKinds.Dll == 1
4725                 // PEFileKinds.ConsoleApplication == 2
4726                 // PEFileKinds.WindowApplication == 3
4727                 //
4728                 // need to get:
4729                 //     IMAGE_SUBSYSTEM_WINDOWS_GUI 2 // Image runs in the Windows GUI subsystem.
4730                 //     IMAGE_SUBSYSTEM_WINDOWS_CUI 3 // Image runs in the Windows character subsystem.
4731                 */
4732                 if (assemblyb->pekind == 3)
4733                         kind = 2;
4734                 else
4735                         kind = 3;
4736                 
4737                 header->nt.pe_subsys_required = GUINT16_FROM_LE (kind);
4738         }    
4739         header->nt.pe_stack_reserve = GUINT32_FROM_LE (0x00100000);
4740         header->nt.pe_stack_commit = GUINT32_FROM_LE (0x00001000);
4741         header->nt.pe_heap_reserve = GUINT32_FROM_LE (0x00100000);
4742         header->nt.pe_heap_commit = GUINT32_FROM_LE (0x00001000);
4743         header->nt.pe_loader_flags = GUINT32_FROM_LE (0);
4744         header->nt.pe_data_dir_count = GUINT32_FROM_LE (16);
4745
4746         /* fill data directory entries */
4747
4748         header->datadir.pe_resource_table.size = GUINT32_FROM_LE (assembly->sections [MONO_SECTION_RSRC].size);
4749         header->datadir.pe_resource_table.rva = GUINT32_FROM_LE (assembly->sections [MONO_SECTION_RSRC].rva);
4750
4751         header->datadir.pe_reloc_table.size = GUINT32_FROM_LE (assembly->sections [MONO_SECTION_RELOC].size);
4752         header->datadir.pe_reloc_table.rva = GUINT32_FROM_LE (assembly->sections [MONO_SECTION_RELOC].rva);
4753
4754         header->datadir.pe_cli_header.size = GUINT32_FROM_LE (72);
4755         header->datadir.pe_cli_header.rva = GUINT32_FROM_LE (assembly->text_rva + assembly->cli_header_offset);
4756         header->datadir.pe_iat.size = GUINT32_FROM_LE (8);
4757         header->datadir.pe_iat.rva = GUINT32_FROM_LE (assembly->text_rva + assembly->iat_offset);
4758         /* patch entrypoint name */
4759         if (assemblyb->pekind == 1)
4760                 memcpy (assembly->code.data + assembly->imp_names_offset + 2, "_CorDllMain", 12);
4761         else
4762                 memcpy (assembly->code.data + assembly->imp_names_offset + 2, "_CorExeMain", 12);
4763         /* patch imported function RVA name */
4764         rva = (guint32*)(assembly->code.data + assembly->iat_offset);
4765         *rva = GUINT32_FROM_LE (assembly->text_rva + assembly->imp_names_offset);
4766
4767         /* the import table */
4768         header->datadir.pe_import_table.size = GUINT32_FROM_LE (79); /* FIXME: magic number? */
4769         header->datadir.pe_import_table.rva = GUINT32_FROM_LE (assembly->text_rva + assembly->idt_offset);
4770         /* patch imported dll RVA name and other entries in the dir */
4771         rva = (guint32*)(assembly->code.data + assembly->idt_offset + G_STRUCT_OFFSET (MonoIDT, name_rva));
4772         *rva = GUINT32_FROM_LE (assembly->text_rva + assembly->imp_names_offset + 14); /* 14 is hint+strlen+1 of func name */
4773         rva = (guint32*)(assembly->code.data + assembly->idt_offset + G_STRUCT_OFFSET (MonoIDT, import_address_table_rva));
4774         *rva = GUINT32_FROM_LE (assembly->text_rva + assembly->iat_offset);
4775         rva = (guint32*)(assembly->code.data + assembly->idt_offset + G_STRUCT_OFFSET (MonoIDT, import_lookup_table));
4776         *rva = GUINT32_FROM_LE (assembly->text_rva + assembly->ilt_offset);
4777
4778         p = (assembly->code.data + assembly->ilt_offset);
4779         value = (assembly->text_rva + assembly->imp_names_offset);
4780         *p++ = (value) & 0xff;
4781         *p++ = (value >> 8) & (0xff);
4782         *p++ = (value >> 16) & (0xff);
4783         *p++ = (value >> 24) & (0xff);
4784
4785         /* the CLI header info */
4786         cli_header = (MonoCLIHeader*)(assembly->code.data + assembly->cli_header_offset);
4787         cli_header->ch_size = GUINT32_FROM_LE (72);
4788         cli_header->ch_runtime_major = GUINT16_FROM_LE (2);
4789         cli_header->ch_flags = GUINT32_FROM_LE (assemblyb->pe_kind);
4790         if (assemblyb->entry_point) {
4791                 guint32 table_idx = 0;
4792                 if (!strcmp (assemblyb->entry_point->object.vtable->klass->name, "MethodBuilder")) {
4793                         MonoReflectionMethodBuilder *methodb = (MonoReflectionMethodBuilder*)assemblyb->entry_point;
4794                         table_idx = methodb->table_idx;
4795                 } else {
4796                         table_idx = GPOINTER_TO_UINT (mono_g_hash_table_lookup (assembly->method_to_table_idx, assemblyb->entry_point->method));
4797                 }
4798                 cli_header->ch_entry_point = GUINT32_FROM_LE (table_idx | MONO_TOKEN_METHOD_DEF);
4799         } else {
4800                 cli_header->ch_entry_point = GUINT32_FROM_LE (0);
4801         }
4802         /* The embedded managed resources */
4803         text_offset = assembly->text_rva + assembly->code.index;
4804         cli_header->ch_resources.rva = GUINT32_FROM_LE (text_offset);
4805         cli_header->ch_resources.size = GUINT32_FROM_LE (assembly->resources.index);
4806         text_offset += assembly->resources.index;
4807         cli_header->ch_metadata.rva = GUINT32_FROM_LE (text_offset);
4808         cli_header->ch_metadata.size = GUINT32_FROM_LE (assembly->meta_size);
4809         text_offset += assembly->meta_size;
4810         if (assembly->strong_name_size) {
4811                 cli_header->ch_strong_name.rva = GUINT32_FROM_LE (text_offset);
4812                 cli_header->ch_strong_name.size = GUINT32_FROM_LE (assembly->strong_name_size);
4813                 text_offset += assembly->strong_name_size;
4814         }
4815
4816         /* write the section tables and section content */
4817         section = (MonoSectionTable*)(pefile->data + section_start);
4818         for (i = 0; i < MONO_SECTION_MAX; ++i) {
4819                 static const char *section_names [] = {
4820                         ".text", ".rsrc", ".reloc"
4821                 };
4822                 if (!assembly->sections [i].size)
4823                         continue;
4824                 strcpy (section->st_name, section_names [i]);
4825                 /*g_print ("output section %s (%d), size: %d\n", section->st_name, i, assembly->sections [i].size);*/
4826                 section->st_virtual_address = GUINT32_FROM_LE (assembly->sections [i].rva);
4827                 section->st_virtual_size = GUINT32_FROM_LE (assembly->sections [i].size);
4828                 section->st_raw_data_size = GUINT32_FROM_LE (GUINT32_TO_LE (section->st_virtual_size) + (FILE_ALIGN - 1));
4829                 section->st_raw_data_size &= GUINT32_FROM_LE (~(FILE_ALIGN - 1));
4830                 section->st_raw_data_ptr = GUINT32_FROM_LE (assembly->sections [i].offset);
4831                 section->st_flags = GUINT32_FROM_LE (assembly->sections [i].attrs);
4832                 section ++;
4833         }
4834         
4835         checked_write_file (file, pefile->data, pefile->index);
4836         
4837         mono_dynamic_stream_reset (pefile);
4838         
4839         for (i = 0; i < MONO_SECTION_MAX; ++i) {
4840                 if (!assembly->sections [i].size)
4841                         continue;
4842                 
4843                 if (SetFilePointer (file, assembly->sections [i].offset, NULL, FILE_BEGIN) == INVALID_SET_FILE_POINTER)
4844                         g_error ("SetFilePointer returned %d\n", GetLastError ());
4845                 
4846                 switch (i) {
4847                 case MONO_SECTION_TEXT:
4848                         /* patch entry point */
4849                         p = (assembly->code.data + 2);
4850                         value = (virtual_base + assembly->text_rva + assembly->iat_offset);
4851                         *p++ = (value) & 0xff;
4852                         *p++ = (value >> 8) & 0xff;
4853                         *p++ = (value >> 16) & 0xff;
4854                         *p++ = (value >> 24) & 0xff;
4855                 
4856                         checked_write_file (file, assembly->code.data, assembly->code.index);
4857                         checked_write_file (file, assembly->resources.data, assembly->resources.index);
4858                         checked_write_file (file, assembly->image.raw_metadata, assembly->meta_size);
4859                         checked_write_file (file, assembly->strong_name, assembly->strong_name_size);
4860                                 
4861
4862                         g_free (assembly->image.raw_metadata);
4863                         break;
4864                 case MONO_SECTION_RELOC: {
4865                         struct {
4866                                 guint32 page_rva;
4867                                 guint32 block_size;
4868                                 guint16 type_and_offset;
4869                                 guint16 term;
4870                         } reloc;
4871                         
4872                         g_assert (sizeof (reloc) == 12);
4873                         
4874                         reloc.page_rva = GUINT32_FROM_LE (assembly->text_rva);
4875                         reloc.block_size = GUINT32_FROM_LE (12);
4876                         
4877                         /* 
4878                          * the entrypoint is always at the start of the text section 
4879                          * 3 is IMAGE_REL_BASED_HIGHLOW
4880                          * 2 is patch_size_rva - text_rva
4881                          */
4882                         reloc.type_and_offset = GUINT16_FROM_LE ((3 << 12) + (2));
4883                         reloc.term = 0;
4884                         
4885                         checked_write_file (file, &reloc, sizeof (reloc));
4886                         
4887                         break;
4888                 }
4889                 case MONO_SECTION_RSRC:
4890                         if (assembly->win32_res) {
4891
4892                                 /* Fixup the offsets in the IMAGE_RESOURCE_DATA_ENTRY structures */
4893                                 fixup_resource_directory (assembly->win32_res, assembly->win32_res, assembly->sections [i].rva);
4894                                 checked_write_file (file, assembly->win32_res, assembly->win32_res_size);
4895                         }
4896                         break;
4897                 default:
4898                         g_assert_not_reached ();
4899                 }
4900         }
4901         
4902         /* check that the file is properly padded */
4903         if (SetFilePointer (file, file_offset, NULL, FILE_BEGIN) == INVALID_SET_FILE_POINTER)
4904                 g_error ("SetFilePointer returned %d\n", GetLastError ());
4905         if (! SetEndOfFile (file))
4906                 g_error ("SetEndOfFile returned %d\n", GetLastError ());
4907         
4908         mono_dynamic_stream_reset (&assembly->code);
4909         mono_dynamic_stream_reset (&assembly->us);
4910         mono_dynamic_stream_reset (&assembly->blob);
4911         mono_dynamic_stream_reset (&assembly->guid);
4912         string_heap_free (&assembly->sheap);
4913
4914         mono_g_hash_table_foreach (assembly->blob_cache, (GHFunc)g_free, NULL);
4915         mono_g_hash_table_destroy (assembly->blob_cache);
4916 }
4917
4918 MonoReflectionModule *
4919 mono_image_load_module (MonoReflectionAssemblyBuilder *ab, MonoString *fileName)
4920 {
4921         char *name;
4922         MonoImage *image;
4923         MonoImageOpenStatus status;
4924         MonoDynamicAssembly *assembly;
4925         guint32 module_count;
4926         MonoImage **new_modules;
4927         
4928         name = mono_string_to_utf8 (fileName);
4929
4930         image = mono_image_open (name, &status);
4931         if (status) {
4932                 MonoException *exc;
4933                 if (status == MONO_IMAGE_ERROR_ERRNO)
4934                         exc = mono_get_exception_file_not_found (fileName);
4935                 else
4936                         exc = mono_get_exception_bad_image_format (name);
4937                 g_free (name);
4938                 mono_raise_exception (exc);
4939         }
4940
4941         g_free (name);
4942
4943         assembly = ab->dynamic_assembly;
4944         image->assembly = (MonoAssembly*)assembly;
4945
4946         module_count = image->assembly->image->module_count;
4947         new_modules = g_new0 (MonoImage *, module_count + 1);
4948
4949         if (image->assembly->image->modules)
4950                 memcpy (new_modules, image->assembly->image->modules, module_count * sizeof (MonoImage *));
4951         new_modules [module_count] = image;
4952
4953         g_free (image->assembly->image->modules);
4954         image->assembly->image->modules = new_modules;
4955         image->assembly->image->module_count ++;
4956
4957         mono_assembly_load_references (image, &status);
4958         if (status) {
4959                 mono_image_close (image);
4960                 mono_raise_exception (mono_get_exception_file_not_found (fileName));
4961         }
4962
4963         return mono_module_get_object (mono_domain_get (), image);
4964 }
4965
4966 /*
4967  * We need to return always the same object for MethodInfo, FieldInfo etc..
4968  * but we need to consider the reflected type.
4969  * type uses a different hash, since it uses custom hash/equal functions.
4970  */
4971
4972 typedef struct {
4973         gpointer item;
4974         MonoClass *refclass;
4975 } ReflectedEntry;
4976
4977 static gboolean
4978 reflected_equal (gconstpointer a, gconstpointer b) {
4979         const ReflectedEntry *ea = a;
4980         const ReflectedEntry *eb = b;
4981
4982         return (ea->item == eb->item) && (ea->refclass == eb->refclass);
4983 }
4984
4985 static guint
4986 reflected_hash (gconstpointer a) {
4987         const ReflectedEntry *ea = a;
4988         return GPOINTER_TO_UINT (ea->item);
4989 }
4990
4991 #define CHECK_OBJECT(t,p,k)     \
4992         do {    \
4993                 t _obj; \
4994                 ReflectedEntry e;       \
4995                 e.item = (p);   \
4996                 e.refclass = (k);       \
4997                 mono_domain_lock (domain);      \
4998                 if (!domain->refobject_hash)    \
4999                         domain->refobject_hash = mono_g_hash_table_new (reflected_hash, reflected_equal);       \
5000                 if ((_obj = mono_g_hash_table_lookup (domain->refobject_hash, &e))) {   \
5001                         mono_domain_unlock (domain);    \
5002                         return _obj;    \
5003                 }       \
5004         } while (0)
5005
5006 #if HAVE_BOEHM_GC
5007 #define ALLOC_REFENTRY GC_MALLOC (sizeof (ReflectedEntry))
5008 #else
5009 #define ALLOC_REFENTRY mono_mempool_alloc (domain->mp, sizeof (ReflectedEntry))
5010 #endif
5011
5012 #define CACHE_OBJECT(p,o,k)     \
5013         do {    \
5014                 ReflectedEntry *e = ALLOC_REFENTRY;     \
5015                 e->item = (p);  \
5016                 e->refclass = (k);      \
5017                 mono_g_hash_table_insert (domain->refobject_hash, e,o); \
5018                 mono_domain_unlock (domain);    \
5019         } while (0)
5020
5021 static void 
5022 register_assembly (MonoDomain *domain, MonoReflectionAssembly *res, MonoAssembly *assembly)
5023 {
5024         /* this is done only once */
5025         mono_domain_lock (domain);
5026         CACHE_OBJECT (assembly, res, NULL);
5027 }
5028
5029 static void
5030 register_module (MonoDomain *domain, MonoReflectionModuleBuilder *res, MonoDynamicImage *module)
5031 {
5032         /* this is done only once */
5033         mono_domain_lock (domain);
5034         CACHE_OBJECT (module, res, NULL);
5035 }
5036
5037 void
5038 mono_image_module_basic_init (MonoReflectionModuleBuilder *moduleb)
5039 {
5040         MonoDynamicImage *image = moduleb->dynamic_image;
5041         MonoReflectionAssemblyBuilder *ab = moduleb->assemblyb;
5042         if (!image) {
5043                 /*
5044                  * FIXME: we already created an image in mono_image_basic_init (), but
5045                  * we don't know which module it belongs to, since that is only 
5046                  * determined at assembly save time.
5047                  */
5048                 /*image = (MonoDynamicImage*)ab->dynamic_assembly->assembly.image; */
5049                 image = create_dynamic_mono_image (ab->dynamic_assembly, mono_string_to_utf8 (ab->name), mono_string_to_utf8 (moduleb->module.fqname));
5050
5051                 moduleb->module.image = &image->image;
5052                 moduleb->dynamic_image = image;
5053                 register_module (mono_object_domain (moduleb), moduleb, image);
5054         }
5055 }
5056
5057 /*
5058  * mono_assembly_get_object:
5059  * @domain: an app domain
5060  * @assembly: an assembly
5061  *
5062  * Return an System.Reflection.Assembly object representing the MonoAssembly @assembly.
5063  */
5064 MonoReflectionAssembly*
5065 mono_assembly_get_object (MonoDomain *domain, MonoAssembly *assembly)
5066 {
5067         static MonoClass *System_Reflection_Assembly;
5068         MonoReflectionAssembly *res;
5069         
5070         CHECK_OBJECT (MonoReflectionAssembly *, assembly, NULL);
5071         if (!System_Reflection_Assembly)
5072                 System_Reflection_Assembly = mono_class_from_name (
5073                         mono_defaults.corlib, "System.Reflection", "Assembly");
5074         res = (MonoReflectionAssembly *)mono_object_new (domain, System_Reflection_Assembly);
5075         res->assembly = assembly;
5076
5077         CACHE_OBJECT (assembly, res, NULL);
5078         return res;
5079 }
5080
5081
5082
5083 MonoReflectionModule*   
5084 mono_module_get_object   (MonoDomain *domain, MonoImage *image)
5085 {
5086         static MonoClass *System_Reflection_Module;
5087         MonoReflectionModule *res;
5088         char* basename;
5089         
5090         CHECK_OBJECT (MonoReflectionModule *, image, NULL);
5091         if (!System_Reflection_Module)
5092                 System_Reflection_Module = mono_class_from_name (
5093                         mono_defaults.corlib, "System.Reflection", "Module");
5094         res = (MonoReflectionModule *)mono_object_new (domain, System_Reflection_Module);
5095
5096         res->image = image;
5097         res->assembly = (MonoReflectionAssembly *) mono_assembly_get_object(domain, image->assembly);
5098
5099         res->fqname    = mono_string_new (domain, image->name);
5100         res->name      = mono_string_new (domain, basename = g_path_get_basename (image->name));
5101         res->scopename = mono_string_new (domain, image->module_name);
5102         
5103         g_free (basename);
5104
5105         if (image->assembly->image == image) {
5106                 res->token = mono_metadata_make_token (MONO_TABLE_MODULE, 1);
5107         } else {
5108                 int i;
5109                 g_assert (image->assembly->image->modules);
5110                 res->token = 0;
5111                 for (i = 0; i < image->assembly->image->module_count; i++) {
5112                         if (image->assembly->image->modules [i] == image)
5113                                 res->token = mono_metadata_make_token (MONO_TABLE_MODULEREF, i + 1);
5114                 }
5115                 g_assert (res->token);
5116         }
5117
5118         mono_image_addref (image);
5119
5120         CACHE_OBJECT (image, res, NULL);
5121         return res;
5122 }
5123
5124 MonoReflectionModule*   
5125 mono_module_file_get_object (MonoDomain *domain, MonoImage *image, int table_index)
5126 {
5127         static MonoClass *System_Reflection_Module;
5128         MonoReflectionModule *res;
5129         MonoTableInfo *table;
5130         guint32 cols [MONO_FILE_SIZE];
5131         const char *name;
5132         guint32 i, name_idx;
5133         const char *val;
5134         
5135         if (!System_Reflection_Module)
5136                 System_Reflection_Module = mono_class_from_name (
5137                         mono_defaults.corlib, "System.Reflection", "Module");
5138         res = (MonoReflectionModule *)mono_object_new (domain, System_Reflection_Module);
5139
5140         table = &image->tables [MONO_TABLE_FILE];
5141         g_assert (table_index < table->rows);
5142         mono_metadata_decode_row (table, table_index, cols, MONO_FILE_SIZE);
5143
5144         res->image = 0;
5145         res->assembly = (MonoReflectionAssembly *) mono_assembly_get_object(domain, image->assembly);
5146         name = mono_metadata_string_heap (image, cols [MONO_FILE_NAME]);
5147
5148         /* Check whenever the row has a corresponding row in the moduleref table */
5149         table = &image->tables [MONO_TABLE_MODULEREF];
5150         for (i = 0; i < table->rows; ++i) {
5151                 name_idx = mono_metadata_decode_row_col (table, i, MONO_MODULEREF_NAME);
5152                 val = mono_metadata_string_heap (image, name_idx);
5153                 if (strcmp (val, name) == 0)
5154                         res->image = image->modules [i];
5155         }
5156
5157         res->fqname    = mono_string_new (domain, name);
5158         res->name      = mono_string_new (domain, name);
5159         res->scopename = mono_string_new (domain, name);
5160         res->is_resource = cols [MONO_FILE_FLAGS] && FILE_CONTAINS_NO_METADATA;
5161         res->token = mono_metadata_make_token (MONO_TABLE_FILE, table_index + 1);
5162
5163         return res;
5164 }
5165
5166 static gboolean
5167 mymono_metadata_type_equal (MonoType *t1, MonoType *t2)
5168 {
5169         if ((t1->type != t2->type) ||
5170             (t1->byref != t2->byref))
5171                 return FALSE;
5172
5173         switch (t1->type) {
5174         case MONO_TYPE_VOID:
5175         case MONO_TYPE_BOOLEAN:
5176         case MONO_TYPE_CHAR:
5177         case MONO_TYPE_I1:
5178         case MONO_TYPE_U1:
5179         case MONO_TYPE_I2:
5180         case MONO_TYPE_U2:
5181         case MONO_TYPE_I4:
5182         case MONO_TYPE_U4:
5183         case MONO_TYPE_I8:
5184         case MONO_TYPE_U8:
5185         case MONO_TYPE_R4:
5186         case MONO_TYPE_R8:
5187         case MONO_TYPE_STRING:
5188         case MONO_TYPE_I:
5189         case MONO_TYPE_U:
5190         case MONO_TYPE_OBJECT:
5191         case MONO_TYPE_TYPEDBYREF:
5192                 return TRUE;
5193         case MONO_TYPE_VALUETYPE:
5194         case MONO_TYPE_CLASS:
5195         case MONO_TYPE_SZARRAY:
5196                 return t1->data.klass == t2->data.klass;
5197         case MONO_TYPE_PTR:
5198                 return mymono_metadata_type_equal (t1->data.type, t2->data.type);
5199         case MONO_TYPE_ARRAY:
5200                 if (t1->data.array->rank != t2->data.array->rank)
5201                         return FALSE;
5202                 return t1->data.array->eklass == t2->data.array->eklass;
5203         case MONO_TYPE_GENERICINST: {
5204                 int i;
5205                 if (t1->data.generic_class->inst->type_argc != t2->data.generic_class->inst->type_argc)
5206                         return FALSE;
5207                 if (!mono_metadata_type_equal (t1->data.generic_class->generic_type, t2->data.generic_class->generic_type))
5208                         return FALSE;
5209                 for (i = 0; i < t1->data.generic_class->inst->type_argc; ++i) {
5210                         if (!mono_metadata_type_equal (t1->data.generic_class->inst->type_argv [i], t2->data.generic_class->inst->type_argv [i]))
5211                                 return FALSE;
5212                 }
5213                 return TRUE;
5214         }
5215         case MONO_TYPE_VAR:
5216         case MONO_TYPE_MVAR:
5217                 return t1->data.generic_param == t2->data.generic_param;
5218         default:
5219                 g_error ("implement type compare for %0x!", t1->type);
5220                 return FALSE;
5221         }
5222
5223         return FALSE;
5224 }
5225
5226 static guint
5227 mymono_metadata_type_hash (MonoType *t1)
5228 {
5229         guint hash;
5230
5231         hash = t1->type;
5232
5233         hash |= t1->byref << 6; /* do not collide with t1->type values */
5234         switch (t1->type) {
5235         case MONO_TYPE_VALUETYPE:
5236         case MONO_TYPE_CLASS:
5237         case MONO_TYPE_SZARRAY:
5238                 /* check if the distribution is good enough */
5239                 return ((hash << 5) - hash) ^ g_str_hash (t1->data.klass->name);
5240         case MONO_TYPE_PTR:
5241                 return ((hash << 5) - hash) ^ mymono_metadata_type_hash (t1->data.type);
5242         }
5243         return hash;
5244 }
5245
5246 static MonoReflectionGenericClass*
5247 mono_generic_class_get_object (MonoDomain *domain, MonoType *geninst)
5248 {
5249         static MonoClass *System_Reflection_MonoGenericClass;
5250         MonoReflectionGenericClass *res;
5251         MonoGenericClass *gclass;
5252         MonoClass *gklass;
5253
5254         if (!System_Reflection_MonoGenericClass) {
5255                 System_Reflection_MonoGenericClass = mono_class_from_name (
5256                         mono_defaults.corlib, "System.Reflection", "MonoGenericClass");
5257                 g_assert (System_Reflection_MonoGenericClass);
5258         }
5259
5260         gclass = geninst->data.generic_class;
5261         gklass = mono_class_from_mono_type (gclass->generic_type);
5262
5263         mono_class_init (gclass->klass);
5264
5265         res = (MonoReflectionGenericClass *) mono_object_new (domain, System_Reflection_MonoGenericClass);
5266
5267         res->type.type = geninst;
5268         if (gklass->wastypebuilder && gklass->reflection_info)
5269                 res->generic_type = gklass->reflection_info;
5270         else
5271                 res->generic_type = mono_type_get_object (domain, gclass->generic_type);
5272
5273         return res;
5274 }
5275
5276 /*
5277  * mono_type_get_object:
5278  * @domain: an app domain
5279  * @type: a type
5280  *
5281  * Return an System.MonoType object representing the type @type.
5282  */
5283 MonoReflectionType*
5284 mono_type_get_object (MonoDomain *domain, MonoType *type)
5285 {
5286         MonoReflectionType *res;
5287         MonoClass *klass = mono_class_from_mono_type (type);
5288
5289         mono_domain_lock (domain);
5290         if (!domain->type_hash)
5291                 domain->type_hash = mono_g_hash_table_new ((GHashFunc)mymono_metadata_type_hash, 
5292                                 (GCompareFunc)mymono_metadata_type_equal);
5293         if ((res = mono_g_hash_table_lookup (domain->type_hash, type))) {
5294                 mono_domain_unlock (domain);
5295                 return res;
5296         }
5297         if ((type->type == MONO_TYPE_GENERICINST) && type->data.generic_class->is_dynamic) {
5298                 res = (MonoReflectionType *)mono_generic_class_get_object (domain, type);
5299                 mono_g_hash_table_insert (domain->type_hash, type, res);
5300                 mono_domain_unlock (domain);
5301                 return res;
5302         }
5303         if (klass->reflection_info && !klass->wastypebuilder) {
5304                 /* g_assert_not_reached (); */
5305                 /* should this be considered an error condition? */
5306                 if (!type->byref) {
5307                         mono_domain_unlock (domain);
5308                         return klass->reflection_info;
5309                 }
5310         }
5311         mono_class_init (klass);
5312         res = (MonoReflectionType *)mono_object_new (domain, mono_defaults.monotype_class);
5313         res->type = type;
5314         mono_g_hash_table_insert (domain->type_hash, type, res);
5315         mono_domain_unlock (domain);
5316         return res;
5317 }
5318
5319 /*
5320  * mono_method_get_object:
5321  * @domain: an app domain
5322  * @method: a method
5323  * @refclass: the reflected type (can be NULL)
5324  *
5325  * Return an System.Reflection.MonoMethod object representing the method @method.
5326  */
5327 MonoReflectionMethod*
5328 mono_method_get_object (MonoDomain *domain, MonoMethod *method, MonoClass *refclass)
5329 {
5330         /*
5331          * We use the same C representation for methods and constructors, but the type 
5332          * name in C# is different.
5333          */
5334         const char *cname;
5335         MonoClass *klass;
5336         MonoReflectionMethod *ret;
5337
5338         if (!refclass)
5339                 refclass = method->klass;
5340
5341         CHECK_OBJECT (MonoReflectionMethod *, method, refclass);
5342         if (*method->name == '.' && (strcmp (method->name, ".ctor") == 0 || strcmp (method->name, ".cctor") == 0))
5343                 cname = "MonoCMethod";
5344         else
5345                 cname = "MonoMethod";
5346         klass = mono_class_from_name (mono_defaults.corlib, "System.Reflection", cname);
5347
5348         ret = (MonoReflectionMethod*)mono_object_new (domain, klass);
5349         ret->method = method;
5350         ret->name = mono_string_new (domain, method->name);
5351         ret->reftype = mono_type_get_object (domain, &refclass->byval_arg);
5352         CACHE_OBJECT (method, ret, refclass);
5353         return ret;
5354 }
5355
5356 /*
5357  * mono_field_get_object:
5358  * @domain: an app domain
5359  * @klass: a type
5360  * @field: a field
5361  *
5362  * Return an System.Reflection.MonoField object representing the field @field
5363  * in class @klass.
5364  */
5365 MonoReflectionField*
5366 mono_field_get_object (MonoDomain *domain, MonoClass *klass, MonoClassField *field)
5367 {
5368         MonoReflectionField *res;
5369         MonoClass *oklass;
5370
5371         CHECK_OBJECT (MonoReflectionField *, field, klass);
5372         oklass = mono_class_from_name (mono_defaults.corlib, "System.Reflection", "MonoField");
5373         res = (MonoReflectionField *)mono_object_new (domain, oklass);
5374         res->klass = klass;
5375         res->field = field;
5376         res->name = mono_string_new (domain, field->name);
5377         if (field->generic_info)
5378                 res->attrs = field->generic_info->generic_type->attrs;
5379         else
5380                 res->attrs = field->type->attrs;
5381         res->type = mono_type_get_object (domain, field->type);
5382         CACHE_OBJECT (field, res, klass);
5383         return res;
5384 }
5385
5386 /*
5387  * mono_property_get_object:
5388  * @domain: an app domain
5389  * @klass: a type
5390  * @property: a property
5391  *
5392  * Return an System.Reflection.MonoProperty object representing the property @property
5393  * in class @klass.
5394  */
5395 MonoReflectionProperty*
5396 mono_property_get_object (MonoDomain *domain, MonoClass *klass, MonoProperty *property)
5397 {
5398         MonoReflectionProperty *res;
5399         MonoClass *oklass;
5400
5401         CHECK_OBJECT (MonoReflectionProperty *, property, klass);
5402         oklass = mono_class_from_name (mono_defaults.corlib, "System.Reflection", "MonoProperty");
5403         res = (MonoReflectionProperty *)mono_object_new (domain, oklass);
5404         res->klass = klass;
5405         res->property = property;
5406         CACHE_OBJECT (property, res, klass);
5407         return res;
5408 }
5409
5410 /*
5411  * mono_event_get_object:
5412  * @domain: an app domain
5413  * @klass: a type
5414  * @event: a event
5415  *
5416  * Return an System.Reflection.MonoEvent object representing the event @event
5417  * in class @klass.
5418  */
5419 MonoReflectionEvent*
5420 mono_event_get_object (MonoDomain *domain, MonoClass *klass, MonoEvent *event)
5421 {
5422         MonoReflectionEvent *res;
5423         MonoClass *oklass;
5424
5425         CHECK_OBJECT (MonoReflectionEvent *, event, klass);
5426         oklass = mono_class_from_name (mono_defaults.corlib, "System.Reflection", "MonoEvent");
5427         res = (MonoReflectionEvent *)mono_object_new (domain, oklass);
5428         res->klass = klass;
5429         res->event = event;
5430         CACHE_OBJECT (event, res, klass);
5431         return res;
5432 }
5433
5434 /*
5435  * mono_param_get_objects:
5436  * @domain: an app domain
5437  * @method: a method
5438  *
5439  * Return an System.Reflection.ParameterInfo array object representing the parameters
5440  * in the method @method.
5441  */
5442 MonoArray*
5443 mono_param_get_objects (MonoDomain *domain, MonoMethod *method)
5444 {
5445         static MonoClass *System_Reflection_ParameterInfo;
5446         MonoArray *res = NULL;
5447         MonoReflectionMethod *member = NULL;
5448         MonoReflectionParameter *param = NULL;
5449         char **names, **blobs = NULL;
5450         MonoObject *dbnull = mono_get_dbnull_object (domain);
5451         MonoMarshalSpec **mspecs;
5452         int i;
5453
5454         if (!System_Reflection_ParameterInfo)
5455                 System_Reflection_ParameterInfo = mono_class_from_name (
5456                         mono_defaults.corlib, "System.Reflection", "ParameterInfo");
5457         
5458         if (!method->signature->param_count)
5459                 return mono_array_new (domain, System_Reflection_ParameterInfo, 0);
5460
5461         /* Note: the cache is based on the address of the signature into the method
5462          * since we already cache MethodInfos with the method as keys.
5463          */
5464         CHECK_OBJECT (MonoArray*, &(method->signature), NULL);
5465
5466         member = mono_method_get_object (domain, method, NULL);
5467         names = g_new (char *, method->signature->param_count);
5468         mono_method_get_param_names (method, (const char **) names);
5469
5470         mspecs = g_new (MonoMarshalSpec*, method->signature->param_count + 1);
5471         mono_method_get_marshal_info (method, mspecs);
5472
5473         res = mono_array_new (domain, System_Reflection_ParameterInfo, method->signature->param_count);
5474         for (i = 0; i < method->signature->param_count; ++i) {
5475                 param = (MonoReflectionParameter *)mono_object_new (domain, System_Reflection_ParameterInfo);
5476                 param->ClassImpl = mono_type_get_object (domain, method->signature->params [i]);
5477                 param->MemberImpl = (MonoObject*)member;
5478                 param->NameImpl = mono_string_new (domain, names [i]);
5479                 param->PositionImpl = i;
5480                 param->AttrsImpl = method->signature->params [i]->attrs;
5481
5482                 if (!(param->AttrsImpl & PARAM_ATTRIBUTE_HAS_DEFAULT)) {
5483                         param->DefaultValueImpl = dbnull;
5484                 } else {
5485                         MonoType *type = param->ClassImpl->type;
5486
5487                         if (!blobs) {
5488                                 blobs = g_new0 (char *, method->signature->param_count);
5489                                 get_default_param_value_blobs (method, blobs); 
5490                         }
5491
5492                         param->DefaultValueImpl = mono_get_object_from_blob (domain, type, blobs [i]);
5493
5494                         if (!param->DefaultValueImpl) {
5495                                 param->DefaultValueImpl = dbnull;
5496                         }
5497                 }
5498
5499                 if (mspecs [i + 1])
5500                         param->MarshalAsImpl = (MonoObject*)mono_reflection_marshal_from_marshal_spec (domain, method->klass, mspecs [i + 1]);
5501                 
5502                 mono_array_set (res, gpointer, i, param);
5503         }
5504         g_free (names);
5505         g_free (blobs);
5506
5507         for (i = method->signature->param_count; i >= 0; i--)
5508                 if (mspecs [i])
5509                         mono_metadata_free_marshal_spec (mspecs [i]);
5510         g_free (mspecs);
5511         
5512         CACHE_OBJECT (&(method->signature), res, NULL);
5513         return res;
5514 }
5515
5516 /*
5517  * mono_method_body_get_object:
5518  * @domain: an app domain
5519  * @method: a method
5520  *
5521  * Return an System.Reflection.MethodBody object representing the method @method.
5522  */
5523 MonoReflectionMethodBody*
5524 mono_method_body_get_object (MonoDomain *domain, MonoMethod *method)
5525 {
5526         static MonoClass *System_Reflection_MethodBody = NULL;
5527         static MonoClass *System_Reflection_LocalVariableInfo = NULL;
5528         MonoReflectionMethodBody *ret;
5529         MonoMethodNormal *mn;
5530         MonoMethodHeader *header;
5531         int i;
5532
5533         if (!System_Reflection_MethodBody)
5534                 System_Reflection_MethodBody = mono_class_from_name (mono_defaults.corlib, "System.Reflection", "MethodBody");
5535         if (!System_Reflection_LocalVariableInfo)
5536                 System_Reflection_LocalVariableInfo = mono_class_from_name (mono_defaults.corlib, "System.Reflection", "LocalVariableInfo");
5537
5538         CHECK_OBJECT (MonoReflectionMethodBody *, method, NULL);
5539
5540         if ((method->flags & METHOD_ATTRIBUTE_PINVOKE_IMPL) ||
5541             (method->iflags & METHOD_IMPL_ATTRIBUTE_INTERNAL_CALL))
5542                 return NULL;
5543         mn = (MonoMethodNormal *)method;
5544         header = mono_method_get_header (method);
5545
5546         ret = (MonoReflectionMethodBody*)mono_object_new (domain, System_Reflection_MethodBody);
5547         /* FIXME: Other fields */
5548         ret->init_locals = header->init_locals;
5549         ret->max_stack = header->max_stack;
5550         ret->il = mono_array_new (domain, mono_defaults.byte_class, header->code_size);
5551         memcpy (mono_array_addr (ret->il, guint8*, 0), header->code, header->code_size);
5552         ret->locals = mono_array_new (domain, System_Reflection_LocalVariableInfo, header->num_locals);
5553         for (i = 0; i < header->num_locals; ++i) {
5554                 MonoReflectionLocalVariableInfo *info = (MonoReflectionLocalVariableInfo*)mono_object_new (domain, System_Reflection_LocalVariableInfo);
5555                 info->local_type = mono_type_get_object (domain, header->locals [i]);
5556                 info->is_pinned = header->locals [i]->pinned;
5557                 info->local_index = 0;
5558         }
5559                 
5560         CACHE_OBJECT (method, ret, NULL);
5561         return ret;
5562 }
5563
5564 MonoObject *
5565 mono_get_dbnull_object (MonoDomain *domain)
5566 {
5567         MonoObject *obj;
5568         MonoClass *klass;
5569         static MonoClassField *dbnull_value_field = NULL;
5570         
5571         if (!dbnull_value_field) {
5572                 klass = mono_class_from_name (mono_defaults.corlib, "System", "DBNull");
5573                 mono_class_init (klass);
5574                 dbnull_value_field = mono_class_get_field_from_name (klass, "Value");
5575                 g_assert (dbnull_value_field);
5576         }
5577         obj = mono_field_get_value_object (domain, dbnull_value_field, NULL); 
5578         g_assert (obj);
5579         return obj;
5580 }
5581
5582
5583 static void
5584 get_default_param_value_blobs (MonoMethod *method, char **blobs)
5585 {
5586         guint32 param_index, i, lastp, crow = 0;
5587         guint32 param_cols [MONO_PARAM_SIZE], const_cols [MONO_CONSTANT_SIZE];
5588         gint32 idx = -1;
5589
5590         MonoClass *klass = method->klass;
5591         MonoImage *image = klass->image;
5592         MonoMethodSignature *methodsig = method->signature;
5593
5594         MonoTableInfo *constt;
5595         MonoTableInfo *methodt;
5596         MonoTableInfo *paramt;
5597
5598         if (!methodsig->param_count)
5599                 return;
5600
5601         if (klass->generic_class) {
5602                 return; /* FIXME - ??? */
5603         }
5604
5605         mono_class_init (klass);
5606
5607         if (klass->image->dynamic) {
5608                 MonoReflectionMethodAux *aux = mono_g_hash_table_lookup (((MonoDynamicImage*)method->klass->image)->method_aux_hash, method);
5609                 if (aux && aux->param_defaults)
5610                         memcpy (blobs, &(aux->param_defaults [1]), methodsig->param_count * sizeof (char*));
5611                 return;
5612         }
5613
5614         methodt = &klass->image->tables [MONO_TABLE_METHOD];
5615         paramt = &klass->image->tables [MONO_TABLE_PARAM];
5616         constt = &image->tables [MONO_TABLE_CONSTANT];
5617
5618         for (i = 0; i < klass->method.count; ++i) {
5619                 if (method == klass->methods [i]) {
5620                         idx = klass->method.first + i;
5621                         break;
5622                 }
5623         }
5624
5625         g_assert (idx != -1);
5626
5627         param_index = mono_metadata_decode_row_col (methodt, idx, MONO_METHOD_PARAMLIST);
5628         if (idx + 1 < methodt->rows)
5629                 lastp = mono_metadata_decode_row_col (methodt, idx + 1, MONO_METHOD_PARAMLIST);
5630         else
5631                 lastp = paramt->rows + 1;
5632
5633         for (i = param_index; i < lastp; ++i) {
5634                 guint32 paramseq;
5635
5636                 mono_metadata_decode_row (paramt, i - 1, param_cols, MONO_PARAM_SIZE);
5637                 paramseq = param_cols [MONO_PARAM_SEQUENCE];
5638
5639                 if (!param_cols [MONO_PARAM_FLAGS] & PARAM_ATTRIBUTE_HAS_DEFAULT) 
5640                         continue;
5641
5642                 crow = mono_metadata_get_constant_index (image, MONO_TOKEN_PARAM_DEF | i, crow + 1);
5643                 if (!crow) {
5644                         continue;
5645                 }
5646         
5647                 mono_metadata_decode_row (constt, crow - 1, const_cols, MONO_CONSTANT_SIZE);
5648                 blobs [paramseq - 1] = (gpointer) mono_metadata_blob_heap (image, const_cols [MONO_CONSTANT_VALUE]);
5649         }
5650
5651         return;
5652 }
5653
5654 static MonoObject *
5655 mono_get_object_from_blob (MonoDomain *domain, MonoType *type, const char *blob)
5656 {
5657         void *retval;
5658         MonoClass *klass;
5659         MonoObject *object;
5660
5661         if (!blob)
5662                 return NULL;
5663         
5664         klass = mono_class_from_mono_type (type);
5665         if (klass->valuetype) {
5666                 object = mono_object_new (domain, klass);
5667                 retval = ((gchar *) object + sizeof (MonoObject));
5668         } else {
5669                 retval = &object;
5670         }
5671                         
5672         if (!mono_get_constant_value_from_blob (domain, type->type,  blob, retval))
5673                 return object;
5674         else
5675                 return NULL;
5676 }
5677
5678 static int
5679 assembly_name_to_aname (MonoAssemblyName *assembly, char *p) {
5680         int found_sep;
5681         char *s;
5682
5683         memset (assembly, 0, sizeof (MonoAssemblyName));
5684         assembly->name = p;
5685         assembly->culture = "";
5686         memset (assembly->public_key_token, 0, MONO_PUBLIC_KEY_TOKEN_LENGTH);
5687
5688         while (*p && (isalnum (*p) || *p == '.' || *p == '-' || *p == '_' || *p == '$' || *p == '@'))
5689                 p++;
5690         found_sep = 0;
5691         while (g_ascii_isspace (*p) || *p == ',') {
5692                 *p++ = 0;
5693                 found_sep = 1;
5694                 continue;
5695         }
5696         /* failed */
5697         if (!found_sep)
5698                 return 1;
5699         while (*p) {
5700                 if (*p == 'V' && g_ascii_strncasecmp (p, "Version=", 8) == 0) {
5701                         p += 8;
5702                         assembly->major = strtoul (p, &s, 10);
5703                         if (s == p || *s != '.')
5704                                 return 1;
5705                         p = ++s;
5706                         assembly->minor = strtoul (p, &s, 10);
5707                         if (s == p || *s != '.')
5708                                 return 1;
5709                         p = ++s;
5710                         assembly->build = strtoul (p, &s, 10);
5711                         if (s == p || *s != '.')
5712                                 return 1;
5713                         p = ++s;
5714                         assembly->revision = strtoul (p, &s, 10);
5715                         if (s == p)
5716                                 return 1;
5717                         p = s;
5718                 } else if (*p == 'C' && g_ascii_strncasecmp (p, "Culture=", 8) == 0) {
5719                         p += 8;
5720                         if (g_ascii_strncasecmp (p, "neutral", 7) == 0) {
5721                                 assembly->culture = "";
5722                                 p += 7;
5723                         } else {
5724                                 assembly->culture = p;
5725                                 while (*p && *p != ',') {
5726                                         p++;
5727                                 }
5728                         }
5729                 } else if (*p == 'P' && g_ascii_strncasecmp (p, "PublicKeyToken=", 15) == 0) {
5730                         p += 15;
5731                         if (strncmp (p, "null", 4) == 0) {
5732                                 p += 4;
5733                         } else {
5734                                 int len;
5735                                 gchar *start = p;
5736                                 while (*p && *p != ',') {
5737                                         p++;
5738                                 }
5739                                 len = (p - start + 1);
5740                                 if (len > MONO_PUBLIC_KEY_TOKEN_LENGTH)
5741                                         len = MONO_PUBLIC_KEY_TOKEN_LENGTH;
5742                                 g_strlcpy (assembly->public_key_token, start, len);
5743                         }
5744                 } else {
5745                         while (*p && *p != ',')
5746                                 p++;
5747                 }
5748                 found_sep = 0;
5749                 while (g_ascii_isspace (*p) || *p == ',') {
5750                         *p++ = 0;
5751                         found_sep = 1;
5752                         continue;
5753                 }
5754                 /* failed */
5755                 if (!found_sep)
5756                         return 1;
5757         }
5758
5759         return 0;
5760 }
5761
5762 /*
5763  * mono_reflection_parse_type:
5764  * @name: type name
5765  *
5766  * Parse a type name as accepted by the GetType () method and output the info
5767  * extracted in the info structure.
5768  * the name param will be mangled, so, make a copy before passing it to this function.
5769  * The fields in info will be valid until the memory pointed to by name is valid.
5770  *
5771  * See also mono_type_get_name () below.
5772  *
5773  * Returns: 0 on parse error.
5774  */
5775 int
5776 mono_reflection_parse_type (char *name, MonoTypeNameParse *info) {
5777
5778         char *start, *p, *w, *last_point, *startn;
5779         int in_modifiers = 0;
5780         int isbyref = 0, rank;
5781
5782         start = p = w = name;
5783
5784         memset (&info->assembly, 0, sizeof (MonoAssemblyName));
5785         info->name = info->name_space = NULL;
5786         info->nested = NULL;
5787         info->modifiers = NULL;
5788
5789         /* last_point separates the namespace from the name */
5790         last_point = NULL;
5791
5792         while (*p) {
5793                 switch (*p) {
5794                 case '+':
5795                         *p = 0; /* NULL terminate the name */
5796                         startn = p + 1;
5797                         info->nested = g_list_append (info->nested, startn);
5798                         /* we have parsed the nesting namespace + name */
5799                         if (info->name)
5800                                 break;
5801                         if (last_point) {
5802                                 info->name_space = start;
5803                                 *last_point = 0;
5804                                 info->name = last_point + 1;
5805                         } else {
5806                                 info->name_space = (char *)"";
5807                                 info->name = start;
5808                         }
5809                         break;
5810                 case '.':
5811                         last_point = w;
5812                         break;
5813                 case '\\':
5814                         ++p;
5815                         break;
5816                 case '&':
5817                 case '*':
5818                 case '[':
5819                 case ',':
5820                         in_modifiers = 1;
5821                         break;
5822                 default:
5823                         break;
5824                 }
5825                 if (in_modifiers)
5826                         break;
5827                 *w++ = *p++;
5828         }
5829         
5830         if (!info->name) {
5831                 if (last_point) {
5832                         info->name_space = start;
5833                         *last_point = 0;
5834                         info->name = last_point + 1;
5835                 } else {
5836                         info->name_space = (char *)"";
5837                         info->name = start;
5838                 }
5839         }
5840         while (*p) {
5841                 switch (*p) {
5842                 case '&':
5843                         if (isbyref) /* only one level allowed by the spec */
5844                                 return 0;
5845                         isbyref = 1;
5846                         info->modifiers = g_list_append (info->modifiers, GUINT_TO_POINTER (0));
5847                         *p++ = 0;
5848                         break;
5849                 case '*':
5850                         info->modifiers = g_list_append (info->modifiers, GUINT_TO_POINTER (-1));
5851                         *p++ = 0;
5852                         break;
5853                 case '[':
5854                         rank = 1;
5855                         *p++ = 0;
5856                         while (*p) {
5857                                 if (*p == ']')
5858                                         break;
5859                                 if (*p == ',')
5860                                         rank++;
5861                                 else if (*p != '*') /* '*' means unknown lower bound */
5862                                         return 0;
5863                                 ++p;
5864                         }
5865                         if (*p++ != ']')
5866                                 return 0;
5867                         info->modifiers = g_list_append (info->modifiers, GUINT_TO_POINTER (rank));
5868                         break;
5869                 case ',':
5870                         *p++ = 0;
5871                         while (*p) {
5872                                 if (g_ascii_isspace (*p)) {
5873                                         ++p;
5874                                         continue;
5875                                 }
5876                                 break;
5877                         }
5878                         if (!*p)
5879                                 return 0; /* missing assembly name */
5880                         if (!assembly_name_to_aname (&info->assembly, p))
5881                                 return 0;
5882                         break;
5883                 default:
5884                         return 0;
5885                         break;
5886                 }
5887                 if (info->assembly.name)
5888                         break;
5889         }
5890         *w = 0; /* terminate class name */
5891         if (!info->name || !*info->name)
5892                 return 0;
5893         /* add other consistency checks */
5894         return 1;
5895 }
5896
5897 static MonoType*
5898 mono_reflection_get_type_internal (MonoImage* image, MonoTypeNameParse *info, gboolean ignorecase)
5899 {
5900         MonoClass *klass;
5901         GList *mod;
5902         int modval;
5903         
5904         if (!image)
5905                 image = mono_defaults.corlib;
5906
5907         if (ignorecase)
5908                 klass = mono_class_from_name_case (image, info->name_space, info->name);
5909         else
5910                 klass = mono_class_from_name (image, info->name_space, info->name);
5911         if (!klass)
5912                 return NULL;
5913         for (mod = info->nested; mod; mod = mod->next) {
5914                 GList *nested;
5915
5916                 mono_class_init (klass);
5917                 nested = klass->nested_classes;
5918                 klass = NULL;
5919                 while (nested) {
5920                         klass = nested->data;
5921                         if (ignorecase) {
5922                                 if (g_strcasecmp (klass->name, mod->data) == 0)
5923                                         break;
5924                         } else {
5925                                 if (strcmp (klass->name, mod->data) == 0)
5926                                         break;
5927                         }
5928                         klass = NULL;
5929                         nested = nested->next;
5930                 }
5931                 if (!klass)
5932                         break;
5933         }
5934         if (!klass)
5935                 return NULL;
5936         mono_class_init (klass);
5937         for (mod = info->modifiers; mod; mod = mod->next) {
5938                 modval = GPOINTER_TO_UINT (mod->data);
5939                 if (!modval) { /* byref: must be last modifier */
5940                         return &klass->this_arg;
5941                 } else if (modval == -1) {
5942                         klass = mono_ptr_class_get (&klass->byval_arg);
5943                 } else { /* array rank */
5944                         klass = mono_array_class_get (klass, modval);
5945                 }
5946                 mono_class_init (klass);
5947         }
5948
5949         return &klass->byval_arg;
5950 }
5951
5952 /*
5953  * mono_reflection_get_type:
5954  * @image: a metadata context
5955  * @info: type description structure
5956  * @ignorecase: flag for case-insensitive string compares
5957  * @type_resolve: whenever type resolve was already tried
5958  *
5959  * Build a MonoType from the type description in @info.
5960  * 
5961  */
5962
5963 MonoType*
5964 mono_reflection_get_type (MonoImage* image, MonoTypeNameParse *info, gboolean ignorecase, gboolean *type_resolve)
5965 {
5966         MonoType *type;
5967         MonoReflectionAssembly *assembly;
5968         GString *fullName;
5969         GList *mod;
5970
5971         type = mono_reflection_get_type_internal (image, info, ignorecase);
5972         if (type)
5973                 return type;
5974         if (!mono_domain_has_type_resolve (mono_domain_get ()))
5975                 return NULL;
5976
5977         if (type_resolve) {
5978                 if (*type_resolve) 
5979                         return NULL;
5980                 else
5981                         *type_resolve = TRUE;
5982         }
5983         
5984         /* Reconstruct the type name */
5985         fullName = g_string_new ("");
5986         if (info->name_space && (info->name_space [0] != '\0'))
5987                 g_string_printf (fullName, "%s.%s", info->name_space, info->name);
5988         else
5989                 g_string_printf (fullName, info->name);
5990         for (mod = info->nested; mod; mod = mod->next)
5991                 g_string_append_printf (fullName, "+%s", (char*)mod->data);
5992
5993         assembly = mono_domain_try_type_resolve ( mono_domain_get (), fullName->str, NULL);
5994         if (assembly) {
5995                 if (assembly->assembly->dynamic) {
5996                         /* Enumerate all modules */
5997                         MonoReflectionAssemblyBuilder *abuilder = (MonoReflectionAssemblyBuilder*)assembly;
5998                         int i;
5999
6000                         type = NULL;
6001                         if (abuilder->modules) {
6002                                 for (i = 0; i < mono_array_length (abuilder->modules); ++i) {
6003                                         MonoReflectionModuleBuilder *mb = mono_array_get (abuilder->modules, MonoReflectionModuleBuilder*, i);
6004                                         type = mono_reflection_get_type_internal (&mb->dynamic_image->image, info, ignorecase);
6005                                         if (type)
6006                                                 break;
6007                                 }
6008                         }
6009
6010                         if (!type && abuilder->loaded_modules) {
6011                                 for (i = 0; i < mono_array_length (abuilder->loaded_modules); ++i) {
6012                                         MonoReflectionModule *mod = mono_array_get (abuilder->loaded_modules, MonoReflectionModule*, i);
6013                                         type = mono_reflection_get_type_internal (mod->image, info, ignorecase);
6014                                         if (type)
6015                                                 break;
6016                                 }
6017                         }
6018                 }
6019                 else
6020                         type = mono_reflection_get_type_internal (assembly->assembly->image, 
6021                                                                                                           info, ignorecase);
6022         }
6023         g_string_free (fullName, TRUE);
6024         return type;
6025 }
6026
6027 /*
6028  * mono_reflection_type_from_name:
6029  * @name: type name.
6030  * @image: a metadata context (can be NULL).
6031  *
6032  * Retrieves a MonoType from its @name. If the name is not fully qualified,
6033  * it defaults to get the type from @image or, if @image is NULL or loading
6034  * from it fails, uses corlib.
6035  * 
6036  */
6037 MonoType*
6038 mono_reflection_type_from_name (char *name, MonoImage *image)
6039 {
6040         MonoType *type;
6041         MonoTypeNameParse info;
6042         MonoAssembly *assembly;
6043         char *tmp;
6044         gboolean type_resolve = FALSE;
6045
6046         /* Make a copy since parse_type modifies its argument */
6047         tmp = g_strdup (name);
6048         
6049         /*g_print ("requested type %s\n", str);*/
6050         if (!mono_reflection_parse_type (tmp, &info)) {
6051                 g_free (tmp);
6052                 g_list_free (info.modifiers);
6053                 g_list_free (info.nested);
6054                 return NULL;
6055         }
6056
6057         if (info.assembly.name) {
6058                 assembly = mono_assembly_loaded (&info.assembly);
6059                 if (!assembly) {
6060                         /* then we must load the assembly ourselve - see #60439 */
6061                         assembly = mono_assembly_load (&info.assembly, NULL, NULL);
6062                         if (!assembly) {
6063                                 g_free (tmp);
6064                                 g_list_free (info.modifiers);
6065                                 g_list_free (info.nested);
6066                                 return NULL;
6067                         }
6068                 }
6069                 image = assembly->image;
6070         } else if (image == NULL) {
6071                 image = mono_defaults.corlib;
6072         }
6073
6074         type = mono_reflection_get_type (image, &info, FALSE, &type_resolve);
6075         if (type == NULL && !info.assembly.name && image != mono_defaults.corlib) {
6076                 image = mono_defaults.corlib;
6077                 type = mono_reflection_get_type (image, &info, FALSE, &type_resolve);
6078         }
6079
6080         g_free (tmp);
6081         g_list_free (info.modifiers);
6082         g_list_free (info.nested);
6083         return type;
6084 }
6085
6086 /*
6087  * mono_reflection_get_token:
6088  *
6089  *   Return the metadata token of OBJ which should be an object
6090  * representing a metadata element.
6091  */
6092 guint32
6093 mono_reflection_get_token (MonoObject *obj)
6094 {
6095         MonoClass *klass;
6096         guint32 token = 0;
6097
6098         klass = obj->vtable->klass;
6099
6100         if (strcmp (klass->name, "MethodBuilder") == 0) {
6101                 MonoReflectionMethodBuilder *mb = (MonoReflectionMethodBuilder *)obj;
6102
6103                 token = mb->table_idx | MONO_TOKEN_METHOD_DEF;
6104         } else if (strcmp (klass->name, "ConstructorBuilder") == 0) {
6105                 MonoReflectionCtorBuilder *mb = (MonoReflectionCtorBuilder *)obj;
6106
6107                 token = mb->table_idx | MONO_TOKEN_METHOD_DEF;
6108         } else if (strcmp (klass->name, "FieldBuilder") == 0) {
6109                 MonoReflectionFieldBuilder *fb = (MonoReflectionFieldBuilder *)obj;
6110                 MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder *)fb->typeb;
6111                 if (tb->generic_params) {
6112                         g_assert_not_reached ();
6113                 } else {
6114                         token = fb->table_idx | MONO_TOKEN_FIELD_DEF;
6115                 }
6116         } else if (strcmp (klass->name, "TypeBuilder") == 0) {
6117                 MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder *)obj;
6118                 token = tb->table_idx | MONO_TOKEN_TYPE_DEF;
6119         } else if (strcmp (klass->name, "MonoType") == 0) {
6120                 MonoReflectionType *tb = (MonoReflectionType *)obj;
6121                 token = mono_class_from_mono_type (tb->type)->type_token;
6122         } else if (strcmp (klass->name, "MonoCMethod") == 0 ||
6123                         strcmp (klass->name, "MonoMethod") == 0) {
6124                 MonoReflectionMethod *m = (MonoReflectionMethod *)obj;
6125                 if (m->method->signature->is_inflated) {
6126                         g_assert_not_reached ();
6127                 } else if (m->method->signature->generic_param_count) {
6128                         g_assert_not_reached ();
6129                 } else if (m->method->klass->generic_class) {
6130                         g_assert_not_reached ();
6131                 } else {
6132                         token = m->method->token;
6133                 }
6134         } else if (strcmp (klass->name, "MonoField") == 0) {
6135                 MonoReflectionField *f = (MonoReflectionField*)obj;
6136
6137                 token = mono_class_get_field_token (f->field);
6138         } else if (strcmp (klass->name, "MonoProperty") == 0) {
6139                 MonoReflectionProperty *p = (MonoReflectionProperty*)obj;
6140
6141                 token = mono_class_get_property_token (p->property);
6142         } else if (strcmp (klass->name, "MonoEvent") == 0) {
6143                 MonoReflectionEvent *p = (MonoReflectionEvent*)obj;
6144
6145                 token = mono_class_get_event_token (p->event);
6146         } else if (strcmp (klass->name, "ParameterInfo") == 0) {
6147                 MonoReflectionParameter *p = (MonoReflectionParameter*)obj;
6148
6149                 token = mono_method_get_param_token (((MonoReflectionMethod*)p->MemberImpl)->method, p->PositionImpl);
6150         } else if (strcmp (klass->name, "Module") == 0) {
6151                 MonoReflectionModule *m = (MonoReflectionModule*)obj;
6152
6153                 token = m->token;
6154         } else if (strcmp (klass->name, "Assembly") == 0) {
6155                 token = mono_metadata_make_token (MONO_TABLE_ASSEMBLY, 1);
6156         } else {
6157                 gchar *msg = g_strdup_printf ("MetadataToken is not supported for type '%s.%s'", klass->name_space, klass->name);
6158                 MonoException *ex = mono_get_exception_not_implemented (msg);
6159                 g_free (msg);
6160                 mono_raise_exception (ex);
6161         }
6162
6163         return token;
6164 }
6165
6166 static void*
6167 load_cattr_value (MonoImage *image, MonoType *t, const char *p, const char **end)
6168 {
6169         int slen, type = t->type;
6170 handle_enum:
6171         switch (type) {
6172         case MONO_TYPE_U1:
6173         case MONO_TYPE_I1:
6174         case MONO_TYPE_BOOLEAN: {
6175                 MonoBoolean *bval = g_malloc (sizeof (MonoBoolean));
6176                 *bval = *p;
6177                 *end = p + 1;
6178                 return bval;
6179         }
6180         case MONO_TYPE_CHAR:
6181         case MONO_TYPE_U2:
6182         case MONO_TYPE_I2: {
6183                 guint16 *val = g_malloc (sizeof (guint16));
6184                 *val = read16 (p);
6185                 *end = p + 2;
6186                 return val;
6187         }
6188 #if SIZEOF_VOID_P == 4
6189         case MONO_TYPE_U:
6190         case MONO_TYPE_I:
6191 #endif
6192         case MONO_TYPE_R4:
6193         case MONO_TYPE_U4:
6194         case MONO_TYPE_I4: {
6195                 guint32 *val = g_malloc (sizeof (guint32));
6196                 *val = read32 (p);
6197                 *end = p + 4;
6198                 return val;
6199         }
6200 #if SIZEOF_VOID_P == 8
6201         case MONO_TYPE_U: /* error out instead? this should probably not happen */
6202         case MONO_TYPE_I:
6203 #endif
6204         case MONO_TYPE_R8:
6205         case MONO_TYPE_U8:
6206         case MONO_TYPE_I8: {
6207                 guint64 *val = g_malloc (sizeof (guint64));
6208                 *val = read64 (p);
6209                 *end = p + 8;
6210                 return val;
6211         }
6212         case MONO_TYPE_VALUETYPE:
6213                 if (t->data.klass->enumtype) {
6214                         type = t->data.klass->enum_basetype->type;
6215                         goto handle_enum;
6216                 } else {
6217                         g_error ("generic valutype %s not handled in custom attr value decoding", t->data.klass->name);
6218                 }
6219                 break;
6220         case MONO_TYPE_STRING:
6221                 if (*p == (char)0xFF) {
6222                         *end = p + 1;
6223                         return NULL;
6224                 }
6225                 slen = mono_metadata_decode_value (p, &p);
6226                 *end = p + slen;
6227                 return mono_string_new_len (mono_domain_get (), p, slen);
6228         case MONO_TYPE_CLASS: {
6229                 char *n;
6230                 MonoType *t;
6231                 if (*p == (char)0xFF) {
6232                         *end = p + 1;
6233                         return NULL;
6234                 }
6235 handle_type:
6236                 slen = mono_metadata_decode_value (p, &p);
6237                 n = g_memdup (p, slen + 1);
6238                 n [slen] = 0;
6239                 t = mono_reflection_type_from_name (n, image);
6240                 if (!t)
6241                         g_warning ("Cannot load type '%s'", n);
6242                 g_free (n);
6243                 *end = p + slen;
6244                 if (t)
6245                         return mono_type_get_object (mono_domain_get (), t);
6246                 else
6247                         return NULL;
6248         }
6249         case MONO_TYPE_OBJECT: {
6250                 char subt = *p++;
6251                 MonoObject *obj;
6252                 MonoClass *subc = NULL;
6253                 void *val;
6254
6255                 if (subt == 0x50) {
6256                         goto handle_type;
6257                 } else if (subt == 0x0E) {
6258                         type = MONO_TYPE_STRING;
6259                         goto handle_enum;
6260                 } else if (subt == 0x55) {
6261                         char *n;
6262                         MonoType *t;
6263                         slen = mono_metadata_decode_value (p, &p);
6264                         n = g_memdup (p, slen + 1);
6265                         n [slen] = 0;
6266                         t = mono_reflection_type_from_name (n, image);
6267                         if (!t)
6268                                 g_warning ("Cannot load type '%s'", n);
6269                         g_free (n);
6270                         p += slen;
6271                         subc = mono_class_from_mono_type (t);
6272                 } else if (subt >= MONO_TYPE_BOOLEAN && subt <= MONO_TYPE_R8) {
6273                         MonoType simple_type = {{0}};
6274                         simple_type.type = subt;
6275                         subc = mono_class_from_mono_type (&simple_type);
6276                 } else {
6277                         g_error ("Unknown type 0x%02x for object type encoding in custom attr", subt);
6278                 }
6279                 val = load_cattr_value (image, &subc->byval_arg, p, end);
6280                 obj = mono_object_new (mono_domain_get (), subc);
6281                 memcpy ((char*)obj + sizeof (MonoObject), val, mono_class_value_size (subc, NULL));
6282                 g_free (val);
6283                 return obj;
6284         }
6285         case MONO_TYPE_SZARRAY: {
6286                 MonoArray *arr;
6287                 guint32 i, alen, basetype;
6288                 alen = read32 (p);
6289                 p += 4;
6290                 if (alen == 0xffffffff) {
6291                         *end = p;
6292                         return NULL;
6293                 }
6294                 arr = mono_array_new (mono_domain_get(), t->data.klass, alen);
6295                 basetype = t->data.klass->byval_arg.type;
6296                 switch (basetype)
6297                 {
6298                         case MONO_TYPE_U1:
6299                         case MONO_TYPE_I1:
6300                         case MONO_TYPE_BOOLEAN:
6301                                 for (i = 0; i < alen; i++) {
6302                                         MonoBoolean val = *p++;
6303                                         mono_array_set (arr, MonoBoolean, i, val);
6304                                 }
6305                                 break;
6306                         case MONO_TYPE_CHAR:
6307                         case MONO_TYPE_U2:
6308                         case MONO_TYPE_I2:
6309                                 for (i = 0; i < alen; i++) {
6310                                         guint16 val = read16 (p);
6311                                         mono_array_set (arr, guint16, i, val);
6312                                         p += 2;
6313                                 }
6314                                 break;
6315                         case MONO_TYPE_R4:
6316                         case MONO_TYPE_U4:
6317                         case MONO_TYPE_I4:
6318                                 for (i = 0; i < alen; i++) {
6319                                         guint32 val = read32 (p);
6320                                         mono_array_set (arr, guint32, i, val);
6321                                         p += 4;
6322                                 }
6323                                 break;
6324                         case MONO_TYPE_R8:
6325                         case MONO_TYPE_U8:
6326                         case MONO_TYPE_I8:
6327                                 for (i = 0; i < alen; i++) {
6328                                         guint64 val = read64 (p);
6329                                         mono_array_set (arr, guint64, i, val);
6330                                         p += 8;
6331                                 }
6332                                 break;
6333                         case MONO_TYPE_CLASS:
6334                         case MONO_TYPE_OBJECT:
6335                         case MONO_TYPE_STRING:
6336                                 for (i = 0; i < alen; i++) {
6337                                         MonoObject *item = load_cattr_value (image, &t->data.klass->byval_arg, p, &p);
6338                                         mono_array_set (arr, gpointer, i, item);
6339                                 }
6340                                 break;
6341                         default:
6342                                 g_error("Type 0x%02x not handled in custom attr array decoding",t->data.type->type);
6343                 }
6344                 *end=p;
6345                 return arr;
6346         }
6347         default:
6348                 g_error ("Type 0x%02x not handled in custom attr value decoding", type);
6349         }
6350         return NULL;
6351 }
6352
6353 static gboolean
6354 type_is_reference (MonoType *type)
6355 {
6356         switch (type->type) {
6357         case MONO_TYPE_BOOLEAN:
6358         case MONO_TYPE_CHAR:
6359         case MONO_TYPE_U:
6360         case MONO_TYPE_I:
6361         case MONO_TYPE_U1:
6362         case MONO_TYPE_I1:
6363         case MONO_TYPE_U2:
6364         case MONO_TYPE_I2:
6365         case MONO_TYPE_U4:
6366         case MONO_TYPE_I4:
6367         case MONO_TYPE_U8:
6368         case MONO_TYPE_I8:
6369         case MONO_TYPE_R8:
6370         case MONO_TYPE_R4:
6371         case MONO_TYPE_VALUETYPE:
6372                 return FALSE;
6373         default:
6374                 return TRUE;
6375         }
6376 }
6377
6378 static void
6379 free_param_data (MonoMethodSignature *sig, void **params) {
6380         int i;
6381         for (i = 0; i < sig->param_count; ++i) {
6382                 if (!type_is_reference (sig->params [i]))
6383                         g_free (params [i]);
6384         }
6385 }
6386
6387 /*
6388  * Find the method index in the metadata methodDef table.
6389  * Later put these three helper methods in metadata and export them.
6390  */
6391 static guint32
6392 find_method_index (MonoMethod *method) {
6393         MonoClass *klass = method->klass;
6394         int i;
6395
6396         for (i = 0; i < klass->method.count; ++i) {
6397                 if (method == klass->methods [i])
6398                         return klass->method.first + 1 + i;
6399         }
6400         return 0;
6401 }
6402
6403 /*
6404  * Find the field index in the metadata FieldDef table.
6405  */
6406 static guint32
6407 find_field_index (MonoClass *klass, MonoClassField *field) {
6408         int i;
6409
6410         for (i = 0; i < klass->field.count; ++i) {
6411                 if (field == &klass->fields [i])
6412                         return klass->field.first + 1 + i;
6413         }
6414         return 0;
6415 }
6416
6417 /*
6418  * Find the property index in the metadata Property table.
6419  */
6420 static guint32
6421 find_property_index (MonoClass *klass, MonoProperty *property) {
6422         int i;
6423
6424         for (i = 0; i < klass->property.count; ++i) {
6425                 if (property == &klass->properties [i])
6426                         return klass->property.first + 1 + i;
6427         }
6428         return 0;
6429 }
6430
6431 /*
6432  * Find the event index in the metadata Event table.
6433  */
6434 static guint32
6435 find_event_index (MonoClass *klass, MonoEvent *event) {
6436         int i;
6437
6438         for (i = 0; i < klass->event.count; ++i) {
6439                 if (event == &klass->events [i])
6440                         return klass->event.first + 1 + i;
6441         }
6442         return 0;
6443 }
6444
6445 static MonoObject*
6446 create_custom_attr (MonoImage *image, MonoMethod *method, const char *data, guint32 len)
6447 {
6448         const char *p = data;
6449         const char *named;
6450         guint32 i, j, num_named;
6451         MonoObject *attr;
6452         void **params;
6453
6454         mono_class_init (method->klass);
6455
6456         if (len == 0) {
6457                 attr = mono_object_new (mono_domain_get (), method->klass);
6458                 mono_runtime_invoke (method, attr, NULL, NULL);
6459                 return attr;
6460         }
6461
6462         if (len < 2 || read16 (p) != 0x0001) /* Prolog */
6463                 return NULL;
6464
6465         /*g_print ("got attr %s\n", method->klass->name);*/
6466         
6467         params = g_new (void*, method->signature->param_count);
6468
6469         /* skip prolog */
6470         p += 2;
6471         for (i = 0; i < method->signature->param_count; ++i) {
6472                 params [i] = load_cattr_value (image, method->signature->params [i], p, &p);
6473         }
6474
6475         named = p;
6476         attr = mono_object_new (mono_domain_get (), method->klass);
6477         mono_runtime_invoke (method, attr, params, NULL);
6478         free_param_data (method->signature, params);
6479         g_free (params);
6480         num_named = read16 (named);
6481         named += 2;
6482         for (j = 0; j < num_named; j++) {
6483                 gint name_len;
6484                 char *name, named_type, data_type;
6485                 named_type = *named++;
6486                 data_type = *named++; /* type of data */
6487                 if (data_type == 0x55) {
6488                         gint type_len;
6489                         char *type_name;
6490                         type_len = mono_metadata_decode_blob_size (named, &named);
6491                         type_name = g_malloc (type_len + 1);
6492                         memcpy (type_name, named, type_len);
6493                         type_name [type_len] = 0;
6494                         named += type_len;
6495                         /* FIXME: lookup the type and check type consistency */
6496                 } else if (data_type == MONO_TYPE_SZARRAY && (named_type == 0x54 || named_type == 0x53)) {
6497                         /* this seems to be the type of the element of the array */
6498                         /* g_print ("skipping 0x%02x after prop\n", *named); */
6499                         named++;
6500                 }
6501                 name_len = mono_metadata_decode_blob_size (named, &named);
6502                 name = g_malloc (name_len + 1);
6503                 memcpy (name, named, name_len);
6504                 name [name_len] = 0;
6505                 named += name_len;
6506                 if (named_type == 0x53) {
6507                         MonoClassField *field = mono_class_get_field_from_name (mono_object_class (attr), name);
6508                         void *val = load_cattr_value (image, field->type, named, &named);
6509                         mono_field_set_value (attr, field, val);
6510                         if (!type_is_reference (field->type))
6511                                 g_free (val);
6512                 } else if (named_type == 0x54) {
6513                         MonoProperty *prop;
6514                         void *pparams [1];
6515                         MonoType *prop_type;
6516
6517                         prop = mono_class_get_property_from_name (mono_object_class (attr), name);
6518                         /* can we have more that 1 arg in a custom attr named property? */
6519                         prop_type = prop->get? prop->get->signature->ret: prop->set->signature->params [prop->set->signature->param_count - 1];
6520                         pparams [0] = load_cattr_value (image, prop_type, named, &named);
6521                         mono_property_set_value (prop, attr, pparams, NULL);
6522                         if (!type_is_reference (prop_type))
6523                                 g_free (pparams [0]);
6524                 }
6525                 g_free (name);
6526         }
6527
6528         return attr;
6529 }
6530
6531 MonoArray*
6532 mono_custom_attrs_construct (MonoCustomAttrInfo *cinfo)
6533 {
6534         MonoArray *result;
6535         MonoClass *klass;
6536         MonoObject *attr;
6537         int i;
6538
6539         klass = mono_class_from_name (mono_defaults.corlib, "System", "Attribute");
6540         result = mono_array_new (mono_domain_get (), klass, cinfo->num_attrs);
6541         for (i = 0; i < cinfo->num_attrs; ++i) {
6542                 attr = create_custom_attr (cinfo->image, cinfo->attrs [i].ctor, cinfo->attrs [i].data, cinfo->attrs [i].data_size);
6543                 mono_array_set (result, gpointer, i, attr);
6544         }
6545         return result;
6546 }
6547
6548 MonoCustomAttrInfo*
6549 mono_custom_attrs_from_index (MonoImage *image, guint32 idx)
6550 {
6551         guint32 mtoken, i, len;
6552         guint32 cols [MONO_CUSTOM_ATTR_SIZE];
6553         MonoTableInfo *ca;
6554         MonoCustomAttrInfo *ainfo;
6555         GList *tmp, *list = NULL;
6556         const char *data;
6557
6558         ca = &image->tables [MONO_TABLE_CUSTOMATTRIBUTE];
6559
6560         i = mono_metadata_custom_attrs_from_index (image, idx);
6561         if (!i)
6562                 return NULL;
6563         i --;
6564         while (i < ca->rows) {
6565                 if (mono_metadata_decode_row_col (ca, i, MONO_CUSTOM_ATTR_PARENT) != idx)
6566                         break;
6567                 list = g_list_prepend (list, GUINT_TO_POINTER (i));
6568                 ++i;
6569         }
6570         len = g_list_length (list);
6571         if (!len)
6572                 return NULL;
6573         ainfo = g_malloc0 (sizeof (MonoCustomAttrInfo) + sizeof (MonoCustomAttrEntry) * (len - MONO_ZERO_LEN_ARRAY));
6574         ainfo->num_attrs = len;
6575         ainfo->image = image;
6576         for (i = 0, tmp = list; i < len; ++i, tmp = tmp->next) {
6577                 mono_metadata_decode_row (ca, GPOINTER_TO_UINT (tmp->data), cols, MONO_CUSTOM_ATTR_SIZE);
6578                 mtoken = cols [MONO_CUSTOM_ATTR_TYPE] >> MONO_CUSTOM_ATTR_TYPE_BITS;
6579                 switch (cols [MONO_CUSTOM_ATTR_TYPE] & MONO_CUSTOM_ATTR_TYPE_MASK) {
6580                 case MONO_CUSTOM_ATTR_TYPE_METHODDEF:
6581                         mtoken |= MONO_TOKEN_METHOD_DEF;
6582                         break;
6583                 case MONO_CUSTOM_ATTR_TYPE_MEMBERREF:
6584                         mtoken |= MONO_TOKEN_MEMBER_REF;
6585                         break;
6586                 default:
6587                         g_error ("Unknown table for custom attr type %08x", cols [MONO_CUSTOM_ATTR_TYPE]);
6588                         break;
6589                 }
6590                 ainfo->attrs [i].ctor = mono_get_method (image, mtoken, NULL);
6591                 if (!ainfo->attrs [i].ctor)
6592                         g_error ("Can't find custom attr constructor image: %s mtoken: 0x%08x", image->name, mtoken);
6593                 data = mono_metadata_blob_heap (image, cols [MONO_CUSTOM_ATTR_VALUE]);
6594                 ainfo->attrs [i].data_size = mono_metadata_decode_value (data, &data);
6595                 ainfo->attrs [i].data = data;
6596         }
6597         g_list_free (list);
6598
6599         return ainfo;
6600 }
6601
6602 MonoCustomAttrInfo*
6603 mono_custom_attrs_from_method (MonoMethod *method)
6604 {
6605         MonoCustomAttrInfo *cinfo;
6606         guint32 idx;
6607         
6608         if (dynamic_custom_attrs && (cinfo = g_hash_table_lookup (dynamic_custom_attrs, method)))
6609                 return cinfo;
6610         idx = find_method_index (method);
6611         idx <<= MONO_CUSTOM_ATTR_BITS;
6612         idx |= MONO_CUSTOM_ATTR_METHODDEF;
6613         return mono_custom_attrs_from_index (method->klass->image, idx);
6614 }
6615
6616 MonoCustomAttrInfo*
6617 mono_custom_attrs_from_class (MonoClass *klass)
6618 {
6619         MonoCustomAttrInfo *cinfo;
6620         guint32 idx;
6621         
6622         if (dynamic_custom_attrs && (cinfo = g_hash_table_lookup (dynamic_custom_attrs, klass)))
6623                 return cinfo;
6624         idx = mono_metadata_token_index (klass->type_token);
6625         idx <<= MONO_CUSTOM_ATTR_BITS;
6626         idx |= MONO_CUSTOM_ATTR_TYPEDEF;
6627         return mono_custom_attrs_from_index (klass->image, idx);
6628 }
6629
6630 MonoCustomAttrInfo*
6631 mono_custom_attrs_from_assembly (MonoAssembly *assembly)
6632 {
6633         MonoCustomAttrInfo *cinfo;
6634         guint32 idx;
6635         
6636         if (dynamic_custom_attrs && (cinfo = g_hash_table_lookup (dynamic_custom_attrs, assembly)))
6637                 return cinfo;
6638         idx = 1; /* there is only one assembly */
6639         idx <<= MONO_CUSTOM_ATTR_BITS;
6640         idx |= MONO_CUSTOM_ATTR_ASSEMBLY;
6641         return mono_custom_attrs_from_index (assembly->image, idx);
6642 }
6643
6644 static MonoCustomAttrInfo*
6645 mono_custom_attrs_from_module (MonoImage *image)
6646 {
6647         MonoCustomAttrInfo *cinfo;
6648         guint32 idx;
6649         
6650         if (dynamic_custom_attrs && (cinfo = g_hash_table_lookup (dynamic_custom_attrs, image)))
6651                 return cinfo;
6652         idx = 1; /* there is only one module */
6653         idx <<= MONO_CUSTOM_ATTR_BITS;
6654         idx |= MONO_CUSTOM_ATTR_MODULE;
6655         return mono_custom_attrs_from_index (image, idx);
6656 }
6657
6658 MonoCustomAttrInfo*
6659 mono_custom_attrs_from_property (MonoClass *klass, MonoProperty *property)
6660 {
6661         MonoCustomAttrInfo *cinfo;
6662         guint32 idx;
6663         
6664         if (dynamic_custom_attrs && (cinfo = g_hash_table_lookup (dynamic_custom_attrs, property)))
6665                 return cinfo;
6666         idx = find_property_index (klass, property);
6667         idx <<= MONO_CUSTOM_ATTR_BITS;
6668         idx |= MONO_CUSTOM_ATTR_PROPERTY;
6669         return mono_custom_attrs_from_index (klass->image, idx);
6670 }
6671
6672 MonoCustomAttrInfo*
6673 mono_custom_attrs_from_event (MonoClass *klass, MonoEvent *event)
6674 {
6675         MonoCustomAttrInfo *cinfo;
6676         guint32 idx;
6677         
6678         if (dynamic_custom_attrs && (cinfo = g_hash_table_lookup (dynamic_custom_attrs, event)))
6679                 return cinfo;
6680         idx = find_event_index (klass, event);
6681         idx <<= MONO_CUSTOM_ATTR_BITS;
6682         idx |= MONO_CUSTOM_ATTR_EVENT;
6683         return mono_custom_attrs_from_index (klass->image, idx);
6684 }
6685
6686 MonoCustomAttrInfo*
6687 mono_custom_attrs_from_field (MonoClass *klass, MonoClassField *field)
6688 {
6689         MonoCustomAttrInfo *cinfo;
6690         guint32 idx;
6691         
6692         if (dynamic_custom_attrs && (cinfo = g_hash_table_lookup (dynamic_custom_attrs, field)))
6693                 return cinfo;
6694         idx = find_field_index (klass, field);
6695         idx <<= MONO_CUSTOM_ATTR_BITS;
6696         idx |= MONO_CUSTOM_ATTR_FIELDDEF;
6697         return mono_custom_attrs_from_index (klass->image, idx);
6698 }
6699
6700 MonoCustomAttrInfo*
6701 mono_custom_attrs_from_param (MonoMethod *method, guint32 param)
6702 {
6703         MonoTableInfo *ca;
6704         guint32 i, idx, method_index;
6705         guint32 param_list, param_last, param_pos, found;
6706         MonoImage *image;
6707         MonoReflectionMethodAux *aux;
6708
6709         if (method->klass->image->dynamic) {
6710                 aux = mono_g_hash_table_lookup (((MonoDynamicImage*)method->klass->image)->method_aux_hash, method);
6711                 if (!aux || !aux->param_cattr)
6712                         return NULL;
6713                 return aux->param_cattr [param];
6714         }
6715
6716         image = method->klass->image;
6717         method_index = find_method_index (method);
6718         ca = &image->tables [MONO_TABLE_METHOD];
6719
6720         if (method->klass->generic_class || method->klass->generic_container ||
6721             method->signature->generic_param_count) {
6722                 /* FIXME FIXME FIXME */
6723                 return NULL;
6724         }
6725
6726         param_list = mono_metadata_decode_row_col (ca, method_index - 1, MONO_METHOD_PARAMLIST);
6727         if (method_index == ca->rows) {
6728                 ca = &image->tables [MONO_TABLE_PARAM];
6729                 param_last = ca->rows + 1;
6730         } else {
6731                 param_last = mono_metadata_decode_row_col (ca, method_index, MONO_METHOD_PARAMLIST);
6732                 ca = &image->tables [MONO_TABLE_PARAM];
6733         }
6734         found = FALSE;
6735         for (i = param_list; i < param_last; ++i) {
6736                 param_pos = mono_metadata_decode_row_col (ca, i - 1, MONO_PARAM_SEQUENCE);
6737                 if (param_pos == param) {
6738                         found = TRUE;
6739                         break;
6740                 }
6741         }
6742         if (!found)
6743                 return NULL;
6744         idx = i;
6745         idx <<= MONO_CUSTOM_ATTR_BITS;
6746         idx |= MONO_CUSTOM_ATTR_PARAMDEF;
6747         return mono_custom_attrs_from_index (image, idx);
6748 }
6749
6750 /*
6751  * mono_reflection_get_custom_attrs:
6752  * @obj: a reflection object handle
6753  *
6754  * Return an array with all the custom attributes defined of the
6755  * reflection handle @obj. The objects are fully build.
6756  */
6757 MonoArray*
6758 mono_reflection_get_custom_attrs (MonoObject *obj)
6759 {
6760         MonoClass *klass;
6761         MonoArray *result;
6762         MonoCustomAttrInfo *cinfo = NULL;
6763         
6764         MONO_ARCH_SAVE_REGS;
6765
6766         klass = obj->vtable->klass;
6767         if (klass == mono_defaults.monotype_class) {
6768                 MonoReflectionType *rtype = (MonoReflectionType*)obj;
6769                 klass = mono_class_from_mono_type (rtype->type);
6770                 cinfo = mono_custom_attrs_from_class (klass);
6771         } else if (strcmp ("Assembly", klass->name) == 0) {
6772                 MonoReflectionAssembly *rassembly = (MonoReflectionAssembly*)obj;
6773                 cinfo = mono_custom_attrs_from_assembly (rassembly->assembly);
6774         } else if (strcmp ("Module", klass->name) == 0) {
6775                 MonoReflectionModule *module = (MonoReflectionModule*)obj;
6776                 cinfo = mono_custom_attrs_from_module (module->image);
6777         } else if (strcmp ("MonoProperty", klass->name) == 0) {
6778                 MonoReflectionProperty *rprop = (MonoReflectionProperty*)obj;
6779                 cinfo = mono_custom_attrs_from_property (rprop->property->parent, rprop->property);
6780         } else if (strcmp ("MonoEvent", klass->name) == 0) {
6781                 MonoReflectionEvent *revent = (MonoReflectionEvent*)obj;
6782                 cinfo = mono_custom_attrs_from_event (revent->event->parent, revent->event);
6783         } else if (strcmp ("MonoField", klass->name) == 0) {
6784                 MonoReflectionField *rfield = (MonoReflectionField*)obj;
6785                 cinfo = mono_custom_attrs_from_field (rfield->field->parent, rfield->field);
6786         } else if ((strcmp ("MonoMethod", klass->name) == 0) || (strcmp ("MonoCMethod", klass->name) == 0)) {
6787                 MonoReflectionMethod *rmethod = (MonoReflectionMethod*)obj;
6788                 cinfo = mono_custom_attrs_from_method (rmethod->method);
6789         } else if (strcmp ("ParameterInfo", klass->name) == 0) {
6790                 MonoReflectionParameter *param = (MonoReflectionParameter*)obj;
6791                 MonoReflectionMethod *rmethod = (MonoReflectionMethod*)param->MemberImpl;
6792                 cinfo = mono_custom_attrs_from_param (rmethod->method, param->PositionImpl + 1);
6793         } else if (strcmp ("AssemblyBuilder", klass->name) == 0) {
6794                 MonoReflectionAssemblyBuilder *assemblyb = (MonoReflectionAssemblyBuilder*)obj;
6795                 cinfo = mono_custom_attrs_from_builders (assemblyb->assembly.assembly->image, assemblyb->cattrs);
6796         } else if (strcmp ("TypeBuilder", klass->name) == 0) {
6797                 MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder*)obj;
6798                 cinfo = mono_custom_attrs_from_builders (&tb->module->dynamic_image->image, tb->cattrs);
6799         } else if (strcmp ("ModuleBuilder", klass->name) == 0) {
6800                 MonoReflectionModuleBuilder *mb = (MonoReflectionModuleBuilder*)obj;
6801                 cinfo = mono_custom_attrs_from_builders (&mb->dynamic_image->image, mb->cattrs);
6802         } else { /* handle other types here... */
6803                 g_error ("get custom attrs not yet supported for %s", klass->name);
6804         }
6805
6806         if (cinfo) {
6807                 result = mono_custom_attrs_construct (cinfo);
6808                 if (!cinfo->cached)
6809                         mono_custom_attrs_free (cinfo);
6810         } else {
6811                 klass = mono_class_from_name (mono_defaults.corlib, "System", "Attribute");
6812                 result = mono_array_new (mono_domain_get (), klass, 0);
6813         }
6814
6815         return result;
6816 }
6817
6818 static MonoMethodSignature*
6819 parameters_to_signature (MonoArray *parameters) {
6820         MonoMethodSignature *sig;
6821         int count, i;
6822
6823         count = parameters? mono_array_length (parameters): 0;
6824
6825         sig = g_malloc0 (sizeof (MonoMethodSignature) + sizeof (MonoType*) * count);
6826         sig->param_count = count;
6827         sig->sentinelpos = -1; /* FIXME */
6828         for (i = 0; i < count; ++i) {
6829                 MonoReflectionType *pt = mono_array_get (parameters, MonoReflectionType*, i);
6830                 sig->params [i] = pt->type;
6831         }
6832         return sig;
6833 }
6834
6835 static MonoMethodSignature*
6836 ctor_builder_to_signature (MonoReflectionCtorBuilder *ctor) {
6837         MonoMethodSignature *sig;
6838
6839         sig = parameters_to_signature (ctor->parameters);
6840         sig->hasthis = ctor->attrs & METHOD_ATTRIBUTE_STATIC? 0: 1;
6841         sig->ret = &mono_defaults.void_class->byval_arg;
6842         return sig;
6843 }
6844
6845 static MonoMethodSignature*
6846 method_builder_to_signature (MonoReflectionMethodBuilder *method) {
6847         MonoMethodSignature *sig;
6848
6849         sig = parameters_to_signature (method->parameters);
6850         sig->hasthis = method->attrs & METHOD_ATTRIBUTE_STATIC? 0: 1;
6851         sig->ret = method->rtype? method->rtype->type: &mono_defaults.void_class->byval_arg;
6852         sig->generic_param_count = method->generic_params ? mono_array_length (method->generic_params) : 0;
6853         return sig;
6854 }
6855
6856 static MonoMethodSignature*
6857 dynamic_method_to_signature (MonoReflectionDynamicMethod *method) {
6858         MonoMethodSignature *sig;
6859
6860         sig = parameters_to_signature (method->parameters);
6861         sig->hasthis = method->attrs & METHOD_ATTRIBUTE_STATIC? 0: 1;
6862         sig->ret = method->rtype? method->rtype->type: &mono_defaults.void_class->byval_arg;
6863         sig->generic_param_count = 0;
6864         return sig;
6865 }
6866
6867 static void
6868 get_prop_name_and_type (MonoObject *prop, char **name, MonoType **type)
6869 {
6870         MonoClass *klass = mono_object_class (prop);
6871         if (strcmp (klass->name, "PropertyBuilder") == 0) {
6872                 MonoReflectionPropertyBuilder *pb = (MonoReflectionPropertyBuilder *)prop;
6873                 *name = mono_string_to_utf8 (pb->name);
6874                 *type = pb->type->type;
6875         } else {
6876                 MonoReflectionProperty *p = (MonoReflectionProperty *)prop;
6877                 *name = g_strdup (p->property->name);
6878                 if (p->property->get)
6879                         *type = p->property->get->signature->ret;
6880                 else
6881                         *type = p->property->set->signature->params [p->property->set->signature->param_count - 1];
6882         }
6883 }
6884
6885 static void
6886 get_field_name_and_type (MonoObject *field, char **name, MonoType **type)
6887 {
6888         MonoClass *klass = mono_object_class (field);
6889         if (strcmp (klass->name, "FieldBuilder") == 0) {
6890                 MonoReflectionFieldBuilder *fb = (MonoReflectionFieldBuilder *)field;
6891                 *name = mono_string_to_utf8 (fb->name);
6892                 *type = fb->type->type;
6893         } else {
6894                 MonoReflectionField *f = (MonoReflectionField *)field;
6895                 *name = g_strdup (f->field->name);
6896                 *type = f->field->type;
6897         }
6898 }
6899
6900 /*
6901  * Encode a value in a custom attribute stream of bytes.
6902  * The value to encode is either supplied as an object in argument val
6903  * (valuetypes are boxed), or as a pointer to the data in the
6904  * argument argval.
6905  * @type represents the type of the value
6906  * @buffer is the start of the buffer
6907  * @p the current position in the buffer
6908  * @buflen contains the size of the buffer and is used to return the new buffer size
6909  * if this needs to be realloced.
6910  * @retbuffer and @retp return the start and the position of the buffer
6911  */
6912 static void
6913 encode_cattr_value (MonoAssembly *assembly, char *buffer, char *p, char **retbuffer, char **retp, guint32 *buflen, MonoType *type, MonoObject *arg, char *argval)
6914 {
6915         MonoTypeEnum simple_type;
6916         
6917         if ((p-buffer) + 10 >= *buflen) {
6918                 char *newbuf;
6919                 *buflen *= 2;
6920                 newbuf = g_realloc (buffer, *buflen);
6921                 p = newbuf + (p-buffer);
6922                 buffer = newbuf;
6923         }
6924         if (!argval)
6925                 argval = ((char*)arg + sizeof (MonoObject));
6926         simple_type = type->type;
6927 handle_enum:
6928         switch (simple_type) {
6929         case MONO_TYPE_BOOLEAN:
6930         case MONO_TYPE_U1:
6931         case MONO_TYPE_I1:
6932                 *p++ = *argval;
6933                 break;
6934         case MONO_TYPE_CHAR:
6935         case MONO_TYPE_U2:
6936         case MONO_TYPE_I2:
6937                 swap_with_size (p, argval, 2, 1);
6938                 p += 2;
6939                 break;
6940         case MONO_TYPE_U4:
6941         case MONO_TYPE_I4:
6942         case MONO_TYPE_R4:
6943                 swap_with_size (p, argval, 4, 1);
6944                 p += 4;
6945                 break;
6946         case MONO_TYPE_U8:
6947         case MONO_TYPE_I8:
6948         case MONO_TYPE_R8:
6949                 swap_with_size (p, argval, 8, 1);
6950                 p += 8;
6951                 break;
6952         case MONO_TYPE_VALUETYPE:
6953                 if (type->data.klass->enumtype) {
6954                         simple_type = type->data.klass->enum_basetype->type;
6955                         goto handle_enum;
6956                 } else {
6957                         g_warning ("generic valutype %s not handled in custom attr value decoding", type->data.klass->name);
6958                 }
6959                 break;
6960         case MONO_TYPE_STRING: {
6961                 char *str;
6962                 guint32 slen;
6963                 if (!arg) {
6964                         *p++ = 0xFF;
6965                         break;
6966                 }
6967                 str = mono_string_to_utf8 ((MonoString*)arg);
6968                 slen = strlen (str);
6969                 if ((p-buffer) + 10 + slen >= *buflen) {
6970                         char *newbuf;
6971                         *buflen *= 2;
6972                         *buflen += slen;
6973                         newbuf = g_realloc (buffer, *buflen);
6974                         p = newbuf + (p-buffer);
6975                         buffer = newbuf;
6976                 }
6977                 mono_metadata_encode_value (slen, p, &p);
6978                 memcpy (p, str, slen);
6979                 p += slen;
6980                 g_free (str);
6981                 break;
6982         }
6983         case MONO_TYPE_CLASS: {
6984                 char *str;
6985                 guint32 slen;
6986                 MonoClass *k;
6987                 if (!arg) {
6988                         *p++ = 0xFF;
6989                         break;
6990                 }
6991                 k = mono_object_class (arg);
6992                 if (!mono_object_isinst (arg, mono_defaults.monotype_class) &&
6993                                 (strcmp (k->name, "TypeBuilder") || strcmp (k->name_space, "System.Reflection.Emit")))
6994                         g_error ("only types allowed, not %s.%s", k->name_space, k->name);
6995 handle_type:
6996                 str = type_get_qualified_name (((MonoReflectionType*)arg)->type, NULL);
6997                 slen = strlen (str);
6998                 if ((p-buffer) + 10 + slen >= *buflen) {
6999                         char *newbuf;
7000                         *buflen *= 2;
7001                         *buflen += slen;
7002                         newbuf = g_realloc (buffer, *buflen);
7003                         p = newbuf + (p-buffer);
7004                         buffer = newbuf;
7005                 }
7006                 mono_metadata_encode_value (slen, p, &p);
7007                 memcpy (p, str, slen);
7008                 p += slen;
7009                 g_free (str);
7010                 break;
7011         }
7012         case MONO_TYPE_SZARRAY: {
7013                 int len, i;
7014                 MonoClass *eclass, *arg_eclass;
7015
7016                 if (!arg) {
7017                         *p++ = 0xff; *p++ = 0xff; *p++ = 0xff; *p++ = 0xff;
7018                         break;
7019                 }
7020                 len = mono_array_length ((MonoArray*)arg);
7021                 *p++ = len & 0xff;
7022                 *p++ = (len >> 8) & 0xff;
7023                 *p++ = (len >> 16) & 0xff;
7024                 *p++ = (len >> 24) & 0xff;
7025                 *retp = p;
7026                 *retbuffer = buffer;
7027                 eclass = type->data.klass;
7028                 arg_eclass = mono_object_class (arg)->element_class;
7029                 if (eclass->valuetype && arg_eclass->valuetype) {
7030                         char *elptr = mono_array_addr ((MonoArray*)arg, char, 0);
7031                         int elsize = mono_class_array_element_size (eclass);
7032                         for (i = 0; i < len; ++i) {
7033                                 encode_cattr_value (assembly, buffer, p, &buffer, &p, buflen, &eclass->byval_arg, NULL, elptr);
7034                                 elptr += elsize;
7035                         }
7036                 } else {
7037                         for (i = 0; i < len; ++i) {
7038                                 encode_cattr_value (assembly, buffer, p, &buffer, &p, buflen, &eclass->byval_arg, mono_array_get ((MonoArray*)arg, MonoObject*, i), NULL);
7039                         }
7040                 }
7041                 break;
7042         }
7043         /* it may be a boxed value or a Type */
7044         case MONO_TYPE_OBJECT: {\r
7045                 MonoClass *klass;
7046                 char *str;
7047                 guint32 slen;
7048 \r
7049                 if (arg == NULL) {\r
7050                         *p++ = MONO_TYPE_STRING;        // It's same hack as MS uses\r
7051                         *p++ = 0xFF;\r
7052                         break;\r
7053                 }\r
7054                 
7055                 klass = mono_object_class (arg);
7056
7057                 if (mono_object_isinst (arg, mono_defaults.monotype_class)) {
7058                         *p++ = 0x50;
7059                         goto handle_type;
7060                 } else if (klass->enumtype) {
7061                         *p++ = 0x55;
7062                 } else if (klass == mono_defaults.string_class) {
7063                         simple_type = MONO_TYPE_STRING;
7064                         *p++ = 0x0E;
7065                         goto handle_enum;
7066                 } else if (klass->byval_arg.type >= MONO_TYPE_BOOLEAN && klass->byval_arg.type <= MONO_TYPE_R8) {
7067                         *p++ = simple_type = klass->byval_arg.type;
7068                         goto handle_enum;
7069                 } else {
7070                         g_error ("unhandled type in custom attr");
7071                 }
7072                 str = type_get_qualified_name (mono_class_get_type(klass), NULL);
7073                 slen = strlen (str);
7074                 if ((p-buffer) + 10 + slen >= *buflen) {
7075                         char *newbuf;
7076                         *buflen *= 2;
7077                         *buflen += slen;
7078                         newbuf = g_realloc (buffer, *buflen);
7079                         p = newbuf + (p-buffer);
7080                         buffer = newbuf;
7081                 }
7082                 mono_metadata_encode_value (slen, p, &p);
7083                 memcpy (p, str, slen);
7084                 p += slen;
7085                 g_free (str);
7086                 simple_type = klass->enum_basetype->type;
7087                 goto handle_enum;
7088         }
7089         default:
7090                 g_error ("type 0x%02x not yet supported in custom attr encoder", simple_type);
7091         }
7092         *retp = p;
7093         *retbuffer = buffer;
7094 }
7095
7096 /*
7097  * mono_reflection_get_custom_attrs_blob:
7098  * @ctor: custom attribute constructor
7099  * @ctorArgs: arguments o the constructor
7100  * @properties:
7101  * @propValues:
7102  * @fields:
7103  * @fieldValues:
7104  * 
7105  * Creates the blob of data that needs to be saved in the metadata and that represents
7106  * the custom attributed described by @ctor, @ctorArgs etc.
7107  * Returns: a Byte array representing the blob of data.
7108  */
7109 MonoArray*
7110 mono_reflection_get_custom_attrs_blob (MonoReflectionAssembly *assembly, MonoObject *ctor, MonoArray *ctorArgs, MonoArray *properties, MonoArray *propValues, MonoArray *fields, MonoArray* fieldValues) 
7111 {
7112         MonoArray *result;
7113         MonoMethodSignature *sig;
7114         MonoObject *arg;
7115         char *buffer, *p;
7116         guint32 buflen, i;
7117
7118         MONO_ARCH_SAVE_REGS;
7119
7120         if (strcmp (ctor->vtable->klass->name, "MonoCMethod")) {
7121                 sig = ctor_builder_to_signature ((MonoReflectionCtorBuilder*)ctor);
7122         } else {
7123                 sig = ((MonoReflectionMethod*)ctor)->method->signature;
7124         }
7125         g_assert (mono_array_length (ctorArgs) == sig->param_count);
7126         buflen = 256;
7127         p = buffer = g_malloc (buflen);
7128         /* write the prolog */
7129         *p++ = 1;
7130         *p++ = 0;
7131         for (i = 0; i < sig->param_count; ++i) {
7132                 arg = mono_array_get (ctorArgs, MonoObject*, i);
7133                 encode_cattr_value (assembly->assembly, buffer, p, &buffer, &p, &buflen, sig->params [i], arg, NULL);
7134         }
7135         i = 0;
7136         if (properties)
7137                 i += mono_array_length (properties);
7138         if (fields)
7139                 i += mono_array_length (fields);
7140         *p++ = i & 0xff;
7141         *p++ = (i >> 8) & 0xff;
7142         if (properties) {
7143                 MonoObject *prop;
7144                 for (i = 0; i < mono_array_length (properties); ++i) {
7145                         MonoType *ptype;
7146                         char *pname;
7147                         int len;
7148                         
7149                         prop = mono_array_get (properties, gpointer, i);
7150                         get_prop_name_and_type (prop, &pname, &ptype);
7151                         *p++ = 0x54; /* PROPERTY signature */
7152
7153                         /* Preallocate a large enough buffer */
7154                         if (ptype->type == MONO_TYPE_VALUETYPE && ptype->data.klass->enumtype) {
7155                                 char *str = type_get_qualified_name (ptype, NULL);
7156                                 len = strlen (str);
7157                                 g_free (str);
7158                         }
7159                         else
7160                                 len = 0;
7161                         len += strlen (pname);
7162
7163                         if ((p-buffer) + 20 + len >= buflen) {
7164                                 char *newbuf;
7165                                 buflen *= 2;
7166                                 buflen += len;
7167                                 newbuf = g_realloc (buffer, buflen);
7168                                 p = newbuf + (p-buffer);
7169                                 buffer = newbuf;
7170                         }
7171
7172                         if (ptype->type == MONO_TYPE_VALUETYPE && ptype->data.klass->enumtype) {
7173                                 char *str = type_get_qualified_name (ptype, NULL);
7174                                 int slen = strlen (str);
7175
7176                                 *p++ = 0x55;
7177                                 /*
7178                                  * This seems to be optional...
7179                                  * *p++ = 0x80;
7180                                  */
7181                                 mono_metadata_encode_value (slen, p, &p);
7182                                 memcpy (p, str, slen);
7183                                 p += slen;
7184                                 g_free (str);
7185                         } else {
7186                                 mono_metadata_encode_value (ptype->type, p, &p);
7187                                 if (ptype->type == MONO_TYPE_SZARRAY)
7188                                         mono_metadata_encode_value (ptype->data.klass->this_arg.type, p, &p);
7189                         }
7190                         len = strlen (pname);
7191                         mono_metadata_encode_value (len, p, &p);
7192                         memcpy (p, pname, len);
7193                         p += len;
7194                         encode_cattr_value (assembly->assembly, buffer, p, &buffer, &p, &buflen, ptype, (MonoObject*)mono_array_get (propValues, gpointer, i), NULL);
7195                         g_free (pname);
7196                 }
7197         }
7198
7199         if (fields) {
7200                 MonoObject *field;
7201                 for (i = 0; i < mono_array_length (fields); ++i) {
7202                         MonoType *ftype;
7203                         char *fname;
7204                         int len;
7205                         
7206                         field = mono_array_get (fields, gpointer, i);
7207                         get_field_name_and_type (field, &fname, &ftype);
7208                         *p++ = 0x53; /* FIELD signature */
7209                         if (ftype->type == MONO_TYPE_VALUETYPE && ftype->data.klass->enumtype) {
7210                                 char *str = type_get_qualified_name (ftype, NULL);
7211                                 int slen = strlen (str);
7212                                 if ((p-buffer) + 10 + slen >= buflen) {
7213                                         char *newbuf;
7214                                         buflen *= 2;
7215                                         buflen += slen;
7216                                         newbuf = g_realloc (buffer, buflen);
7217                                         p = newbuf + (p-buffer);
7218                                         buffer = newbuf;
7219                                 }
7220                                 *p++ = 0x55;
7221                                 /*
7222                                  * This seems to be optional...
7223                                  * *p++ = 0x80;
7224                                  */
7225                                 mono_metadata_encode_value (slen, p, &p);
7226                                 memcpy (p, str, slen);
7227                                 p += slen;
7228                                 g_free (str);
7229                         } else {
7230                                 mono_metadata_encode_value (ftype->type, p, &p);
7231                                 if (ftype->type == MONO_TYPE_SZARRAY)
7232                                         mono_metadata_encode_value (ftype->data.klass->this_arg.type, p, &p);
7233                         }
7234                         len = strlen (fname);
7235                         mono_metadata_encode_value (len, p, &p);
7236                         memcpy (p, fname, len);
7237                         p += len;
7238                         encode_cattr_value (assembly->assembly, buffer, p, &buffer, &p, &buflen, ftype, (MonoObject*)mono_array_get (fieldValues, gpointer, i), NULL);
7239                         g_free (fname);
7240                 }
7241         }
7242
7243         g_assert (p - buffer <= buflen);
7244         buflen = p - buffer;
7245         result = mono_array_new (mono_domain_get (), mono_defaults.byte_class, buflen);
7246         p = mono_array_addr (result, char, 0);
7247         memcpy (p, buffer, buflen);
7248         g_free (buffer);
7249         if (strcmp (ctor->vtable->klass->name, "MonoCMethod"))
7250                 g_free (sig);
7251         return result;
7252 }
7253
7254 /*
7255  * mono_reflection_setup_internal_class:
7256  * @tb: a TypeBuilder object
7257  *
7258  * Creates a MonoClass that represents the TypeBuilder.
7259  * This is a trick that lets us simplify a lot of reflection code
7260  * (and will allow us to support Build and Run assemblies easier).
7261  */
7262 void
7263 mono_reflection_setup_internal_class (MonoReflectionTypeBuilder *tb)
7264 {
7265         MonoClass *klass, *parent;
7266
7267         MONO_ARCH_SAVE_REGS;
7268
7269         if (tb->parent) {
7270                 /* check so we can compile corlib correctly */
7271                 if (strcmp (mono_object_class (tb->parent)->name, "TypeBuilder") == 0) {
7272                         /* mono_class_setup_mono_type () guaranteess type->data.klass is valid */
7273                         parent = tb->parent->type->data.klass;
7274                 } else {
7275                         parent = my_mono_class_from_mono_type (tb->parent->type);
7276                 }
7277         } else {
7278                 parent = NULL;
7279         }
7280         
7281         /* the type has already being created: it means we just have to change the parent */
7282         if (tb->type.type) {
7283                 klass = mono_class_from_mono_type (tb->type.type);
7284                 klass->parent = NULL;
7285                 /* fool mono_class_setup_parent */
7286                 g_free (klass->supertypes);
7287                 klass->supertypes = NULL;
7288                 mono_class_setup_parent (klass, parent);
7289                 mono_class_setup_mono_type (klass);
7290                 return;
7291         }
7292         
7293         klass = g_new0 (MonoClass, 1);
7294
7295         klass->image = &tb->module->dynamic_image->image;
7296
7297         klass->inited = 1; /* we lie to the runtime */
7298         klass->name = mono_string_to_utf8 (tb->name);
7299         klass->name_space = mono_string_to_utf8 (tb->nspace);
7300         klass->type_token = MONO_TOKEN_TYPE_DEF | tb->table_idx;
7301         klass->flags = tb->attrs;
7302
7303         klass->element_class = klass;
7304         klass->reflection_info = tb; /* need to pin. */
7305
7306         /* Put into cache so mono_class_get () will find it */
7307         mono_image_add_to_name_cache (klass->image, klass->name_space, klass->name, tb->table_idx);
7308
7309         mono_g_hash_table_insert (tb->module->dynamic_image->tokens,
7310                 GUINT_TO_POINTER (MONO_TOKEN_TYPE_DEF | tb->table_idx), tb);
7311
7312         if (parent != NULL) {
7313                 mono_class_setup_parent (klass, parent);
7314         } else if (strcmp (klass->name, "Object") == 0 && strcmp (klass->name_space, "System") == 0) {
7315                 const char *old_n = klass->name;
7316                 /* trick to get relative numbering right when compiling corlib */
7317                 klass->name = "BuildingObject";
7318                 mono_class_setup_parent (klass, mono_defaults.object_class);
7319                 klass->name = old_n;
7320         }
7321
7322         if ((!strcmp (klass->name, "ValueType") && !strcmp (klass->name_space, "System")) ||
7323                         (!strcmp (klass->name, "Object") && !strcmp (klass->name_space, "System")) ||
7324                         (!strcmp (klass->name, "Enum") && !strcmp (klass->name_space, "System"))) {
7325                 klass->instance_size = sizeof (MonoObject);
7326                 klass->size_inited = 1;
7327                 mono_class_setup_vtable (klass, NULL, 0);
7328         }
7329
7330         mono_class_setup_mono_type (klass);
7331
7332         mono_class_setup_supertypes (klass);
7333
7334         /*
7335          * FIXME: handle interfaces.
7336          */
7337
7338         tb->type.type = &klass->byval_arg;
7339
7340         if (tb->nesting_type) {
7341                 g_assert (tb->nesting_type->type);
7342                 klass->nested_in = mono_class_from_mono_type (tb->nesting_type->type);
7343         }
7344
7345         /*g_print ("setup %s as %s (%p)\n", klass->name, ((MonoObject*)tb)->vtable->klass->name, tb);*/
7346 }
7347
7348 /*
7349  * mono_reflection_setup_generic_class:
7350  * @tb: a TypeBuilder object
7351  *
7352  * Setup the generic class before adding the first generic parameter.
7353  */
7354 void
7355 mono_reflection_setup_generic_class (MonoReflectionTypeBuilder *tb)
7356 {
7357         MonoClass *klass;
7358
7359         MONO_ARCH_SAVE_REGS;
7360
7361         klass = my_mono_class_from_mono_type (tb->type.type);
7362         if (tb->generic_container)
7363                 return;
7364
7365         tb->generic_container = g_new0 (MonoGenericContainer, 1);
7366         tb->generic_container->klass = klass;
7367
7368         tb->generic_container->context.container = tb->generic_container;
7369 }
7370
7371 /*
7372  * mono_reflection_create_generic_class:
7373  * @tb: a TypeBuilder object
7374  *
7375  * Creates the generic class after all generic parameters have been added.
7376  */
7377 void
7378 mono_reflection_create_generic_class (MonoReflectionTypeBuilder *tb)
7379 {
7380         MonoClass *klass;
7381         int count, i;
7382
7383         MONO_ARCH_SAVE_REGS;
7384
7385         klass = my_mono_class_from_mono_type (tb->type.type);
7386
7387         count = tb->generic_params ? mono_array_length (tb->generic_params) : 0;
7388
7389         if (klass->generic_container || (count == 0))
7390                 return;
7391
7392         g_assert (tb->generic_container && (tb->generic_container->klass == klass));
7393
7394         klass->generic_container = tb->generic_container;
7395
7396         klass->generic_container->type_argc = count;
7397         klass->generic_container->type_params = g_new0 (MonoGenericParam, count);
7398
7399         for (i = 0; i < count; i++) {
7400                 MonoReflectionGenericParam *gparam = mono_array_get (tb->generic_params, gpointer, i);
7401                 klass->generic_container->type_params [i] = *gparam->type.type->data.generic_param;
7402                 g_assert (klass->generic_container->type_params [i].owner);
7403         }
7404 }
7405
7406 /*
7407  * mono_reflection_create_internal_class:
7408  * @tb: a TypeBuilder object
7409  *
7410  * Actually create the MonoClass that is associated with the TypeBuilder.
7411  */
7412 void
7413 mono_reflection_create_internal_class (MonoReflectionTypeBuilder *tb)
7414 {
7415         MonoClass *klass;
7416
7417         MONO_ARCH_SAVE_REGS;
7418
7419         klass = my_mono_class_from_mono_type (tb->type.type);
7420
7421         if (klass->enumtype && klass->enum_basetype == NULL) {
7422                 MonoReflectionFieldBuilder *fb;
7423                 MonoClass *ec;
7424
7425                 g_assert (tb->fields != NULL);
7426                 g_assert (mono_array_length (tb->fields) >= 1);
7427
7428                 fb = mono_array_get (tb->fields, MonoReflectionFieldBuilder*, 0);
7429
7430                 klass->enum_basetype = fb->type->type;
7431                 klass->element_class = my_mono_class_from_mono_type (klass->enum_basetype);
7432                 if (!klass->element_class)
7433                         klass->element_class = mono_class_from_mono_type (klass->enum_basetype);
7434
7435                 /*
7436                  * get the element_class from the current corlib.
7437                  */
7438                 ec = default_class_from_mono_type (klass->enum_basetype);
7439                 klass->instance_size = ec->instance_size;
7440                 klass->size_inited = 1;
7441                 /* 
7442                  * this is almost safe to do with enums and it's needed to be able
7443                  * to create objects of the enum type (for use in SetConstant).
7444                  */
7445                 /* FIXME: Does this mean enums can't have method overrides ? */
7446                 mono_class_setup_vtable (klass, NULL, 0);
7447         }
7448 }
7449
7450 static MonoMarshalSpec*
7451 mono_marshal_spec_from_builder (MonoAssembly *assembly,
7452                                                                 MonoReflectionMarshal *minfo)
7453 {
7454         MonoMarshalSpec *res;
7455
7456         res = g_new0 (MonoMarshalSpec, 1);
7457         res->native = minfo->type;
7458
7459         switch (minfo->type) {
7460         case MONO_NATIVE_LPARRAY:
7461                 res->data.array_data.elem_type = minfo->eltype;
7462                 res->data.array_data.param_num = 0; /* Not yet */
7463                 res->data.array_data.num_elem = minfo->count;
7464                 break;
7465
7466         case MONO_NATIVE_BYVALTSTR:
7467         case MONO_NATIVE_BYVALARRAY:
7468                 res->data.array_data.num_elem = minfo->count;
7469                 break;
7470
7471         case MONO_NATIVE_CUSTOM:
7472                 if (minfo->marshaltyperef)
7473                         res->data.custom_data.custom_name =
7474                                 type_get_fully_qualified_name (minfo->marshaltyperef->type);
7475                 if (minfo->mcookie)
7476                         res->data.custom_data.cookie = mono_string_to_utf8 (minfo->mcookie);
7477                 break;
7478
7479         default:
7480                 break;
7481         }
7482
7483         return res;
7484 }
7485
7486 MonoReflectionMarshal*
7487 mono_reflection_marshal_from_marshal_spec (MonoDomain *domain, MonoClass *klass,
7488                                                                                    MonoMarshalSpec *spec)
7489 {
7490         static MonoClass *System_Reflection_Emit_UnmanagedMarshalClass;
7491         MonoReflectionMarshal *minfo;
7492         MonoType *mtype;
7493
7494         if (!System_Reflection_Emit_UnmanagedMarshalClass) {
7495                 System_Reflection_Emit_UnmanagedMarshalClass = mono_class_from_name (
7496                    mono_defaults.corlib, "System.Reflection.Emit", "UnmanagedMarshal");
7497                 g_assert (System_Reflection_Emit_UnmanagedMarshalClass);
7498         }
7499
7500         minfo = (MonoReflectionMarshal*)mono_object_new (domain, System_Reflection_Emit_UnmanagedMarshalClass);
7501         minfo->type = spec->native;
7502
7503         switch (minfo->type) {
7504         case MONO_NATIVE_LPARRAY:
7505                 minfo->eltype = spec->data.array_data.elem_type;
7506                 minfo->count = spec->data.array_data.num_elem;
7507                 break;
7508
7509         case MONO_NATIVE_BYVALTSTR:
7510         case MONO_NATIVE_BYVALARRAY:
7511                 minfo->count = spec->data.array_data.num_elem;
7512                 break;
7513
7514         case MONO_NATIVE_CUSTOM:
7515                 if (spec->data.custom_data.custom_name) {
7516                         mtype = mono_reflection_type_from_name (spec->data.custom_data.custom_name, klass->image);
7517                         if (mtype)
7518                                 minfo->marshaltyperef = mono_type_get_object (domain, mtype);
7519
7520                         minfo->marshaltype = mono_string_new (domain, spec->data.custom_data.custom_name);
7521                 }
7522                 if (spec->data.custom_data.cookie)
7523                         minfo->mcookie = mono_string_new (domain, spec->data.custom_data.cookie);
7524                 break;
7525
7526         default:
7527                 break;
7528         }
7529
7530         return minfo;
7531 }
7532
7533 static MonoMethod*
7534 reflection_methodbuilder_to_mono_method (MonoClass *klass,
7535                                          ReflectionMethodBuilder *rmb,
7536                                          MonoMethodSignature *sig)
7537 {
7538         MonoMethod *m;
7539         MonoMethodNormal *pm;
7540         MonoMarshalSpec **specs;
7541         MonoReflectionMethodAux *method_aux;
7542         int i;
7543
7544         if ((rmb->attrs & METHOD_ATTRIBUTE_PINVOKE_IMPL) ||
7545                         (rmb->iattrs & METHOD_IMPL_ATTRIBUTE_INTERNAL_CALL))
7546                 m = (MonoMethod *)g_new0 (MonoMethodPInvoke, 1);
7547         else if (rmb->refs)
7548                 m = (MonoMethod *)g_new0 (MonoMethodWrapper, 1);
7549         else
7550                 m = (MonoMethod *)g_new0 (MonoMethodNormal, 1);
7551
7552         pm = (MonoMethodNormal*)m;
7553
7554         m->slot = -1;
7555         m->flags = rmb->attrs;
7556         m->iflags = rmb->iattrs;
7557         m->name = mono_string_to_utf8 (rmb->name);
7558         m->klass = klass;
7559         m->signature = sig;
7560         if (rmb->table_idx)
7561                 m->token = MONO_TOKEN_METHOD_DEF | (*rmb->table_idx);
7562
7563         if (m->iflags & METHOD_IMPL_ATTRIBUTE_INTERNAL_CALL) {
7564                 if (klass == mono_defaults.string_class && !strcmp (m->name, ".ctor"))
7565                         m->string_ctor = 1;
7566
7567                 m->signature->pinvoke = 1;
7568         } else if (m->flags & METHOD_ATTRIBUTE_PINVOKE_IMPL) {
7569                 m->signature->pinvoke = 1;
7570
7571                 method_aux = g_new0 (MonoReflectionMethodAux, 1);
7572
7573                 method_aux->dllentry = g_strdup (mono_string_to_utf8 (rmb->dllentry));
7574                 method_aux->dll = g_strdup (mono_string_to_utf8 (rmb->dll));
7575                 
7576                 ((MonoMethodPInvoke*)m)->piflags = (rmb->native_cc << 8) | (rmb->charset ? (rmb->charset - 1) * 2 : 1) | rmb->lasterr;
7577
7578                 if (klass->image->dynamic)
7579                         mono_g_hash_table_insert (((MonoDynamicImage*)klass->image)->method_aux_hash, m, method_aux);
7580
7581                 return m;
7582         } else if (!m->klass->dummy && 
7583                            !(m->flags & METHOD_ATTRIBUTE_ABSTRACT) &&
7584                            !(m->iflags & METHOD_IMPL_ATTRIBUTE_RUNTIME)) {
7585                 MonoMethodHeader *header;
7586                 guint32 code_size;
7587                 gint32 max_stack, i;
7588                 gint32 num_locals = 0;
7589                 gint32 num_clauses = 0;
7590                 guint8 *code;
7591
7592                 if (rmb->ilgen) {
7593                         code = mono_array_addr (rmb->ilgen->code, guint8, 0);
7594                         code_size = rmb->ilgen->code_len;
7595                         max_stack = rmb->ilgen->max_stack;
7596                         num_locals = rmb->ilgen->locals ? mono_array_length (rmb->ilgen->locals) : 0;
7597                         if (rmb->ilgen->ex_handlers)
7598                                 num_clauses = method_count_clauses (rmb->ilgen);
7599                 } else {
7600                         if (rmb->code) {
7601                                 code = mono_array_addr (rmb->code, guint8, 0);
7602                                 code_size = mono_array_length (rmb->code);
7603                                 /* we probably need to run a verifier on the code... */
7604                                 max_stack = 8; 
7605                         }
7606                         else {
7607                                 code = NULL;
7608                                 code_size = 0;
7609                                 max_stack = 8;
7610                         }
7611                 }
7612
7613                 header = g_malloc0 (sizeof (MonoMethodHeader) + 
7614                         (num_locals - MONO_ZERO_LEN_ARRAY) * sizeof (MonoType*));
7615                 header->code_size = code_size;
7616                 header->code = g_malloc (code_size);
7617                 memcpy ((char*)header->code, code, code_size);
7618                 header->max_stack = max_stack;
7619                 header->init_locals = rmb->init_locals;
7620                 header->num_locals = num_locals;
7621
7622                 for (i = 0; i < num_locals; ++i) {
7623                         MonoReflectionLocalBuilder *lb = 
7624                                 mono_array_get (rmb->ilgen->locals, MonoReflectionLocalBuilder*, i);
7625
7626                         header->locals [i] = g_new0 (MonoType, 1);
7627                         memcpy (header->locals [i], lb->type->type, sizeof (MonoType));
7628                 }
7629
7630                 header->num_clauses = num_clauses;
7631                 if (num_clauses) {
7632                         header->clauses = method_encode_clauses ((MonoDynamicImage*)klass->image,
7633                                  rmb->ilgen, num_clauses);
7634                 }
7635
7636                 pm->header = header;
7637         }
7638
7639         if (rmb->generic_params) {
7640                 int count = mono_array_length (rmb->generic_params);
7641                 MonoGenericContainer *container;
7642
7643                 pm->generic_container = container = rmb->generic_container;
7644                 container->type_argc = count;
7645                 container->type_params = g_new0 (MonoGenericParam, count);
7646
7647                 for (i = 0; i < count; i++) {
7648                         MonoReflectionGenericParam *gp =
7649                                 mono_array_get (rmb->generic_params, MonoReflectionGenericParam*, i);
7650
7651                         container->type_params [i] = *gp->type.type->data.generic_param;
7652                 }
7653         }
7654
7655         if (rmb->refs) {
7656                 MonoMethodWrapper *mw = (MonoMethodWrapper*)m;
7657                 int i;
7658
7659                 m->wrapper_type = MONO_WRAPPER_DYNAMIC_METHOD;
7660
7661                 for (i = 0; i < rmb->nrefs; ++i)
7662                         mw->data = g_list_append (mw->data, rmb->refs [i]);
7663         }
7664
7665         method_aux = NULL;
7666
7667         /* Parameter info */
7668         if (rmb->pinfo) {
7669                 if (!method_aux)
7670                         method_aux = g_new0 (MonoReflectionMethodAux, 1);
7671                 method_aux->param_names = g_new0 (char *, m->signature->param_count + 1);
7672                 for (i = 0; i <= m->signature->param_count; ++i) {
7673                         MonoReflectionParamBuilder *pb;
7674                         if ((pb = mono_array_get (rmb->pinfo, MonoReflectionParamBuilder*, i))) {
7675                                 if (i > 0)
7676                                         m->signature->params [i - 1]->attrs = pb->attrs;
7677
7678                                 if (pb->def_value) {
7679                                         MonoDynamicImage *assembly;
7680                                         guint32 idx, def_type, len;
7681                                         char *p;
7682                                         const char *p2;
7683
7684                                         if (!method_aux->param_defaults)
7685                                                 method_aux->param_defaults = g_new0 (guint8*, m->signature->param_count + 1);
7686                                         assembly = (MonoDynamicImage*)klass->image;
7687                                         idx = encode_constant (assembly, pb->def_value, &def_type);
7688                                         /* Copy the data from the blob since it might get realloc-ed */
7689                                         p = assembly->blob.data + idx;
7690                                         len = mono_metadata_decode_blob_size (p, &p2);
7691                                         len += p2 - p;
7692                                         method_aux->param_defaults [i] = g_malloc (len);
7693                                         memcpy ((gpointer)method_aux->param_defaults [i], p, len);
7694                                 }
7695
7696                                 if (pb->name)
7697                                         method_aux->param_names [i] = mono_string_to_utf8 (pb->name);
7698                                 if (pb->cattrs) {
7699                                         if (!method_aux->param_cattr)
7700                                                 method_aux->param_cattr = g_new0 (MonoCustomAttrInfo*, m->signature->param_count + 1);
7701                                         method_aux->param_cattr [i] = mono_custom_attrs_from_builders (klass->image, pb->cattrs);
7702                                 }
7703                         }
7704                 }
7705         }
7706
7707         /* Parameter marshalling */
7708         specs = NULL;
7709         if (rmb->pinfo)         
7710                 for (i = 0; i < mono_array_length (rmb->pinfo); ++i) {
7711                         MonoReflectionParamBuilder *pb;
7712                         if ((pb = mono_array_get (rmb->pinfo, MonoReflectionParamBuilder*, i))) {
7713                                 if (pb->marshal_info) {
7714                                         if (specs == NULL)
7715                                                 specs = g_new0 (MonoMarshalSpec*, sig->param_count + 1);
7716                                         specs [pb->position] = 
7717                                                 mono_marshal_spec_from_builder (klass->image->assembly, pb->marshal_info);
7718                                 }
7719                         }
7720                 }
7721         if (specs != NULL) {
7722                 if (!method_aux)
7723                         method_aux = g_new0 (MonoReflectionMethodAux, 1);
7724                 method_aux->param_marshall = specs;
7725         }
7726
7727         if (klass->image->dynamic && method_aux)
7728                 mono_g_hash_table_insert (((MonoDynamicImage*)klass->image)->method_aux_hash, m, method_aux);
7729
7730         return m;
7731 }       
7732
7733 static MonoMethod*
7734 ctorbuilder_to_mono_method (MonoClass *klass, MonoReflectionCtorBuilder* mb)
7735 {
7736         ReflectionMethodBuilder rmb;
7737         MonoMethodSignature *sig;
7738
7739         sig = ctor_builder_to_signature (mb);
7740
7741         reflection_methodbuilder_from_ctor_builder (&rmb, mb);
7742
7743         mb->mhandle = reflection_methodbuilder_to_mono_method (klass, &rmb, sig);
7744         mono_save_custom_attrs (klass->image, mb->mhandle, mb->cattrs);
7745
7746         if (!((MonoDynamicImage*)(MonoDynamicImage*)klass->image)->save) {
7747                 /* ilgen is no longer needed */
7748                 mb->ilgen = NULL;
7749         }
7750
7751         return mb->mhandle;
7752 }
7753
7754 static MonoMethod*
7755 methodbuilder_to_mono_method (MonoClass *klass, MonoReflectionMethodBuilder* mb)
7756 {
7757         ReflectionMethodBuilder rmb;
7758         MonoMethodSignature *sig;
7759
7760         sig = method_builder_to_signature (mb);
7761
7762         reflection_methodbuilder_from_method_builder (&rmb, mb);
7763
7764         mb->mhandle = reflection_methodbuilder_to_mono_method (klass, &rmb, sig);
7765         mono_save_custom_attrs (klass->image, mb->mhandle, mb->cattrs);
7766
7767         if (!((MonoDynamicImage*)(MonoDynamicImage*)klass->image)->save) {
7768                 /* ilgen is no longer needed */
7769                 mb->ilgen = NULL;
7770         }
7771         return mb->mhandle;
7772 }
7773
7774 static MonoClassField*
7775 fieldbuilder_to_mono_class_field (MonoClass *klass, MonoReflectionFieldBuilder* fb)
7776 {
7777         MonoClassField *field;
7778         const char *p, *p2;
7779         guint32 len, idx;
7780
7781         if (fb->handle)
7782                 return fb->handle;
7783
7784         field = g_new0 (MonoClassField, 1);
7785
7786         field->name = mono_string_to_utf8 (fb->name);
7787         if (fb->attrs) {
7788                 /* FIXME: handle type modifiers */
7789                 field->type = g_memdup (fb->type->type, sizeof (MonoType));
7790                 field->type->attrs = fb->attrs;
7791         } else {
7792                 field->type = fb->type->type;
7793         }
7794         if ((fb->attrs & FIELD_ATTRIBUTE_HAS_FIELD_RVA) && fb->rva_data)
7795                 field->data = mono_array_addr (fb->rva_data, char, 0);
7796         if (fb->offset != -1)
7797                 field->offset = fb->offset;
7798         field->parent = klass;
7799         fb->handle = field;
7800         mono_save_custom_attrs (klass->image, field, fb->cattrs);
7801
7802         if (fb->def_value) {
7803                 MonoDynamicImage *assembly = (MonoDynamicImage*)klass->image;
7804                 field->type->attrs |= FIELD_ATTRIBUTE_HAS_DEFAULT;
7805                 idx = encode_constant (assembly, fb->def_value, &field->def_type);
7806                 /* Copy the data from the blob since it might get realloc-ed */
7807                 p = assembly->blob.data + idx;
7808                 len = mono_metadata_decode_blob_size (p, &p2);
7809                 len += p2 - p;
7810                 field->data = g_malloc (len);
7811                 memcpy ((gpointer)field->data, p, len);
7812         }
7813
7814         return field;
7815 }
7816
7817 static MonoType*
7818 do_mono_reflection_bind_generic_parameters (MonoReflectionType *type, int type_argc, MonoType **types,
7819                                             MonoType *parent)
7820 {
7821         MonoClass *klass, *gklass;
7822         MonoReflectionTypeBuilder *tb = NULL;
7823         MonoGenericClass *gclass, *cached;
7824         MonoDomain *domain;
7825         MonoType *geninst;
7826         int icount, i;
7827
7828         klass = mono_class_from_mono_type (type->type);
7829         if (!klass->generic_container && !klass->generic_class &&
7830             !(klass->nested_in && klass->nested_in->generic_container))
7831                 return NULL;
7832
7833         mono_loader_lock ();
7834
7835         domain = mono_object_domain (type);
7836
7837         gclass = g_new0 (MonoGenericClass, 1);
7838         gclass->inst = g_new0 (MonoGenericInst, 1);
7839
7840         gclass->inst->type_argc = type_argc;
7841         gclass->inst->type_argv = types;
7842
7843         for (i = 0; i < gclass->inst->type_argc; ++i) {
7844                 if (!gclass->inst->is_open)
7845                         gclass->inst->is_open = mono_class_is_open_constructed_type (types [i]);
7846         }
7847
7848         gclass->generic_type = &klass->byval_arg;
7849
7850         if (klass->generic_class) {
7851                 MonoGenericClass *kgclass = klass->generic_class;
7852                 MonoGenericClass *ogclass = gclass;
7853
7854                 ogclass->context = g_new0 (MonoGenericContext, 1);
7855                 ogclass->context->container = ogclass->container;
7856                 ogclass->context->gclass = ogclass;
7857
7858                 gclass = g_new0 (MonoGenericClass, 1);
7859                 gclass->inst = g_new0 (MonoGenericInst, 1);
7860
7861                 gclass->inst->type_argc = kgclass->inst->type_argc;
7862                 gclass->inst->type_argv = g_new0 (MonoType *, gclass->inst->type_argc);
7863
7864                 for (i = 0; i < gclass->inst->type_argc; i++) {
7865                         MonoType *t = kgclass->inst->type_argv [i];
7866
7867                         t = mono_class_inflate_generic_type (t, ogclass->context);
7868
7869                         if (!gclass->inst->is_open)
7870                                 gclass->inst->is_open = mono_class_is_open_constructed_type (t);
7871
7872                         gclass->inst->type_argv [i] = t;
7873                 }
7874
7875                 gclass->generic_type = kgclass->generic_type;
7876         }
7877
7878         geninst = g_new0 (MonoType, 1);
7879         geninst->type = MONO_TYPE_GENERICINST;
7880
7881         cached = mono_metadata_lookup_generic_class (gclass);
7882         if (cached) {
7883                 g_free (gclass);
7884                 mono_loader_unlock ();
7885                 geninst->data.generic_class = cached;
7886                 return geninst;
7887         }
7888
7889         gklass = mono_class_from_mono_type (gclass->generic_type);
7890         g_assert ((gclass->container = gklass->generic_container) != NULL);
7891
7892         geninst->data.generic_class = gclass;
7893
7894         gclass->parent = parent;
7895
7896         gclass->context = g_new0 (MonoGenericContext, 1);
7897         gclass->context->container = gclass->container;
7898         gclass->context->gclass = gclass;
7899
7900         if (!strcmp (((MonoObject *) type)->vtable->klass->name, "TypeBuilder")) {
7901                 tb = (MonoReflectionTypeBuilder *) type;
7902
7903                 icount = tb->interfaces ? mono_array_length (tb->interfaces) : 0;
7904                 gclass->is_dynamic = TRUE;
7905         } else if (!strcmp (((MonoObject *) type)->vtable->klass->name, "MonoGenericClass")) {
7906                 MonoReflectionGenericClass *rgi = (MonoReflectionGenericClass *) type;
7907                 MonoReflectionType *rgt = rgi->generic_type;
7908
7909                 g_assert (!strcmp (((MonoObject *) rgt)->vtable->klass->name, "TypeBuilder"));
7910                 tb = (MonoReflectionTypeBuilder *) rgt;
7911
7912                 icount = tb->interfaces ? mono_array_length (tb->interfaces) : 0;
7913                 gclass->is_dynamic = TRUE;
7914         } else {
7915                 icount = klass->interface_count;
7916         }
7917
7918         gclass->ifaces = g_new0 (MonoType *, icount);
7919         gclass->count_ifaces = icount;
7920
7921         for (i = 0; i < icount; i++) {
7922                 MonoReflectionType *itype;
7923
7924                 if (tb)
7925                         itype = mono_array_get (tb->interfaces, MonoReflectionType *, i);
7926                 else
7927                         itype = mono_type_get_object (domain, &klass->interfaces [i]->byval_arg);
7928                 gclass->ifaces [i] = mono_reflection_bind_generic_parameters (itype, type_argc, types);
7929                 if (!gclass->ifaces [i])
7930                         gclass->ifaces [i] = itype->type;
7931         }
7932
7933         mono_class_create_generic (gclass);
7934         mono_class_create_generic_2 (gclass);
7935
7936         mono_loader_unlock ();
7937
7938         return geninst;
7939 }
7940
7941 MonoType*
7942 mono_reflection_bind_generic_parameters (MonoReflectionType *type, int type_argc, MonoType **types)
7943 {
7944         MonoClass *klass, *pklass = NULL;
7945         MonoReflectionType *parent = NULL;
7946         MonoType *the_parent = NULL, *geninst;
7947         MonoReflectionTypeBuilder *tb = NULL;
7948         MonoGenericClass *gclass;
7949         MonoDomain *domain;
7950
7951         domain = mono_object_domain (type);
7952         klass = mono_class_from_mono_type (type->type);
7953
7954         if (!strcmp (((MonoObject *) type)->vtable->klass->name, "TypeBuilder")) {
7955                 tb = (MonoReflectionTypeBuilder *) type;
7956
7957                 if (tb->parent) {
7958                         parent = tb->parent;
7959                         pklass = mono_class_from_mono_type (parent->type);
7960                 }
7961         } else {
7962                 pklass = klass->parent;
7963                 if (pklass)
7964                         parent = mono_type_get_object (domain, &pklass->byval_arg);
7965                 else if (klass->generic_class && klass->generic_class->parent) {
7966                         parent = mono_type_get_object (domain, klass->generic_class->parent);
7967                         pklass = mono_class_from_mono_type (klass->generic_class->parent);
7968                 }
7969         }
7970
7971         if (pklass && pklass->generic_class)
7972                 the_parent = mono_reflection_bind_generic_parameters (parent, type_argc, types);
7973
7974         geninst = do_mono_reflection_bind_generic_parameters (type, type_argc, types, the_parent);
7975         if (!geninst)
7976                 return NULL;
7977
7978         gclass = geninst->data.generic_class;
7979
7980         return geninst;
7981 }
7982
7983 static MonoType*
7984 dup_type (const MonoType *original)
7985 {
7986         MonoType *r = g_new0 (MonoType, 1);
7987         *r = *original;
7988         r->attrs = original->attrs;
7989         r->byref = original->byref;
7990         mono_stats.generics_metadata_size += sizeof (MonoType);
7991         return r;
7992 }
7993
7994 MonoReflectionMethod*
7995 mono_reflection_bind_generic_method_parameters (MonoReflectionMethod *rmethod, MonoArray *types)
7996 {
7997         MonoMethod *method, *inflated;
7998         MonoReflectionMethodBuilder *mb = NULL;
7999         MonoGenericContainer *container;
8000         MonoGenericMethod *gmethod;
8001         MonoGenericContext *context;
8002         MonoGenericInst *ginst;
8003         int count, i;
8004
8005         MONO_ARCH_SAVE_REGS;
8006         if (!strcmp (rmethod->object.vtable->klass->name, "MethodBuilder")) {
8007                 MonoReflectionTypeBuilder *tb;
8008                 MonoClass *klass;
8009
8010                 mb = (MonoReflectionMethodBuilder *) rmethod;
8011                 tb = (MonoReflectionTypeBuilder *) mb->type;
8012                 klass = mono_class_from_mono_type (tb->type.type);
8013
8014                 method = methodbuilder_to_mono_method (klass, mb);
8015         } else {
8016                 method = rmethod->method;
8017         }
8018
8019         count = method->signature->generic_param_count;
8020         if (count != mono_array_length (types))
8021                 return NULL;
8022
8023         container = ((MonoMethodNormal*) method)->generic_container;
8024         g_assert (container);
8025
8026         if (!container->method_hash)
8027                 container->method_hash = g_hash_table_new (
8028                         (GHashFunc) mono_metadata_generic_method_hash,
8029                         (GCompareFunc) mono_metadata_generic_method_equal);
8030
8031         ginst = g_new0 (MonoGenericInst,1 );
8032         ginst->type_argc = count;
8033         ginst->type_argv = g_new0 (MonoType *, count);
8034         for (i = 0; i < count; i++) {
8035                 MonoReflectionType *garg = mono_array_get (types, gpointer, i);
8036                 ginst->type_argv [i] = dup_type (garg->type);
8037
8038                 if (!ginst->is_open)
8039                         ginst->is_open = mono_class_is_open_constructed_type (ginst->type_argv [i]);
8040         }
8041         ginst = mono_metadata_lookup_generic_inst (ginst);
8042
8043         gmethod = g_new0 (MonoGenericMethod, 1);
8044         gmethod->container = container;
8045         gmethod->inst = ginst;
8046
8047         inflated = g_hash_table_lookup (container->method_hash, gmethod);
8048         if (inflated) {
8049                 g_free (gmethod);
8050
8051                 return mono_method_get_object (mono_object_domain (rmethod), inflated, NULL);
8052         }
8053
8054         gmethod->reflection_info = rmethod;
8055
8056         context = g_new0 (MonoGenericContext, 1);
8057         context->container = container;
8058         context->gclass = method->klass->generic_class;
8059         context->gmethod = gmethod;
8060
8061         inflated = mono_class_inflate_generic_method (method, context, NULL);
8062         g_hash_table_insert (container->method_hash, gmethod, inflated);
8063
8064         return mono_method_get_object (mono_object_domain (rmethod), inflated, NULL);
8065 }
8066
8067 static MonoMethod *
8068 inflate_mono_method (MonoReflectionGenericClass *type, MonoMethod *method, MonoObject *obj)
8069 {
8070         MonoGenericMethod *gmethod;
8071         MonoGenericClass *gclass;
8072         MonoGenericContext *context;
8073         int i;
8074
8075         gclass = type->type.type->data.generic_class;
8076
8077         gmethod = g_new0 (MonoGenericMethod, 1);
8078         gmethod->inst = g_new0 (MonoGenericInst, 1);
8079         gmethod->reflection_info = obj;
8080
8081         gmethod->inst->type_argc = method->signature->generic_param_count;
8082         gmethod->inst->type_argv = g_new0 (MonoType *, gmethod->inst->type_argc);
8083
8084         for (i = 0; i < gmethod->inst->type_argc; i++) {
8085                 MonoMethodNormal *mn = (MonoMethodNormal *) method;
8086                 MonoGenericParam *gparam = &mn->generic_container->type_params [i];
8087
8088                 g_assert (gparam->pklass);
8089                 gmethod->inst->type_argv [i] = &gparam->pklass->byval_arg;
8090         }
8091
8092         context = g_new0 (MonoGenericContext, 1);
8093         context->container = gclass->container;
8094         context->gclass = gclass;
8095         context->gmethod = gmethod;
8096
8097         return mono_class_inflate_generic_method (method, context, gclass->klass);
8098 }
8099
8100 static MonoMethod *
8101 inflate_method (MonoReflectionGenericClass *type, MonoObject *obj)
8102 {
8103         MonoMethod *method;
8104         MonoClass *klass;
8105
8106         klass = mono_class_from_mono_type (type->type.type);
8107
8108         if (!strcmp (obj->vtable->klass->name, "MethodBuilder"))
8109                 method = methodbuilder_to_mono_method (klass, (MonoReflectionMethodBuilder *) obj);
8110         else if (!strcmp (obj->vtable->klass->name, "ConstructorBuilder"))
8111                 method = ctorbuilder_to_mono_method (klass, (MonoReflectionCtorBuilder *) obj);
8112         else if (!strcmp (obj->vtable->klass->name, "MonoMethod") || !strcmp (obj->vtable->klass->name, "MonoCMethod"))
8113                 method = ((MonoReflectionMethod *) obj)->method;
8114         else {
8115                 method = NULL; /* prevent compiler warning */
8116                 g_assert_not_reached ();
8117         }
8118
8119         return inflate_mono_method (type, method, obj);
8120 }
8121
8122 void
8123 mono_reflection_generic_class_initialize (MonoReflectionGenericClass *type, MonoArray *methods, 
8124                                           MonoArray *ctors, MonoArray *fields, MonoArray *properties,
8125                                           MonoArray *events)
8126 {
8127         MonoGenericClass *gclass;
8128         MonoDynamicGenericClass *dgclass;
8129         MonoClass *klass, *gklass, *pklass;
8130         int i;
8131
8132         MONO_ARCH_SAVE_REGS;
8133
8134         klass = mono_class_from_mono_type (type->type.type);
8135         gclass = type->type.type->data.generic_class;
8136
8137         if (gclass->initialized)
8138                 return;
8139
8140         dgclass = gclass->dynamic_info = g_new0 (MonoDynamicGenericClass, 1);
8141
8142         gklass = mono_class_from_mono_type (gclass->generic_type);
8143         mono_class_init (gklass);
8144
8145         if (gclass->parent)
8146                 pklass = mono_class_from_mono_type (gclass->parent);
8147         else
8148                 pklass = gklass->parent;
8149
8150         mono_class_setup_parent (klass, pklass);
8151
8152         dgclass->count_methods = methods ? mono_array_length (methods) : 0;
8153         dgclass->count_ctors = ctors ? mono_array_length (ctors) : 0;
8154         dgclass->count_fields = fields ? mono_array_length (fields) : 0;
8155         dgclass->count_properties = properties ? mono_array_length (properties) : 0;
8156         dgclass->count_events = events ? mono_array_length (events) : 0;
8157
8158         dgclass->methods = g_new0 (MonoMethod *, dgclass->count_methods);
8159         dgclass->ctors = g_new0 (MonoMethod *, dgclass->count_ctors);
8160         dgclass->fields = g_new0 (MonoClassField, dgclass->count_fields);
8161         dgclass->properties = g_new0 (MonoProperty, dgclass->count_properties);
8162         dgclass->events = g_new0 (MonoEvent, dgclass->count_events);
8163
8164         for (i = 0; i < dgclass->count_methods; i++) {
8165                 MonoObject *obj = mono_array_get (methods, gpointer, i);
8166
8167                 dgclass->methods [i] = inflate_method (type, obj);
8168         }
8169
8170         for (i = 0; i < dgclass->count_ctors; i++) {
8171                 MonoObject *obj = mono_array_get (ctors, gpointer, i);
8172
8173                 dgclass->ctors [i] = inflate_method (type, obj);
8174         }
8175
8176         for (i = 0; i < dgclass->count_fields; i++) {
8177                 MonoObject *obj = mono_array_get (fields, gpointer, i);
8178                 MonoClassField *field;
8179                 MonoInflatedField *ifield;
8180
8181                 if (!strcmp (obj->vtable->klass->name, "FieldBuilder"))
8182                         field = fieldbuilder_to_mono_class_field (klass, (MonoReflectionFieldBuilder *) obj);
8183                 else if (!strcmp (obj->vtable->klass->name, "MonoField"))
8184                         field = ((MonoReflectionField *) obj)->field;
8185                 else {
8186                         field = NULL; /* prevent compiler warning */
8187                         g_assert_not_reached ();
8188                 }
8189
8190                 ifield = g_new0 (MonoInflatedField, 1);
8191                 ifield->generic_type = field->type;
8192                 ifield->reflection_info = obj;
8193
8194                 dgclass->fields [i] = *field;
8195                 dgclass->fields [i].generic_info = ifield;
8196                 dgclass->fields [i].type = mono_class_inflate_generic_type (field->type, gclass->context);
8197         }
8198
8199         for (i = 0; i < dgclass->count_properties; i++) {
8200                 MonoObject *obj = mono_array_get (properties, gpointer, i);
8201                 MonoProperty *property = &dgclass->properties [i];
8202
8203                 if (!strcmp (obj->vtable->klass->name, "PropertyBuilder")) {
8204                         MonoReflectionPropertyBuilder *pb = (MonoReflectionPropertyBuilder *) obj;
8205
8206                         property->parent = klass;
8207                         property->attrs = pb->attrs;
8208                         property->name = mono_string_to_utf8 (pb->name);
8209                         if (pb->get_method)
8210                                 property->get = inflate_method (type, (MonoObject *) pb->get_method);
8211                         if (pb->set_method)
8212                                 property->set = inflate_method (type, (MonoObject *) pb->set_method);
8213                 } else if (!strcmp (obj->vtable->klass->name, "MonoProperty")) {
8214                         *property = *((MonoReflectionProperty *) obj)->property;
8215
8216                         if (property->get)
8217                                 property->get = inflate_mono_method (type, property->get, NULL);
8218                         if (property->set)
8219                                 property->set = inflate_mono_method (type, property->set, NULL);
8220                 } else
8221                         g_assert_not_reached ();
8222         }
8223
8224         for (i = 0; i < dgclass->count_events; i++) {
8225                 MonoObject *obj = mono_array_get (events, gpointer, i);
8226                 MonoEvent *event = &dgclass->events [i];
8227
8228                 if (!strcmp (obj->vtable->klass->name, "EventBuilder")) {
8229                         MonoReflectionEventBuilder *eb = (MonoReflectionEventBuilder *) obj;
8230
8231                         event->parent = klass;
8232                         event->attrs = eb->attrs;
8233                         event->name = mono_string_to_utf8 (eb->name);
8234                         if (eb->add_method)
8235                                 event->add = inflate_method (type, (MonoObject *) eb->add_method);
8236                         if (eb->remove_method)
8237                                 event->remove = inflate_method (type, (MonoObject *) eb->remove_method);
8238                 } else if (!strcmp (obj->vtable->klass->name, "MonoEvent")) {
8239                         *event = *((MonoReflectionEvent *) obj)->event;
8240
8241                         if (event->add)
8242                                 event->add = inflate_mono_method (type, event->add, NULL);
8243                         if (event->remove)
8244                                 event->remove = inflate_mono_method (type, event->remove, NULL);
8245                 } else
8246                         g_assert_not_reached ();
8247         }
8248
8249         gclass->initialized = TRUE;
8250 }
8251
8252 static void
8253 ensure_runtime_vtable (MonoClass *klass)
8254 {
8255         MonoReflectionTypeBuilder *tb = klass->reflection_info;
8256         int i, num, j, onum;
8257         MonoMethod **overrides;
8258
8259         if (!tb || klass->wastypebuilder)
8260                 return;
8261         if (klass->parent)
8262                 ensure_runtime_vtable (klass->parent);
8263
8264         num = tb->ctors? mono_array_length (tb->ctors): 0;
8265         num += tb->num_methods;
8266         klass->method.count = num;
8267         klass->methods = g_new (MonoMethod*, num);
8268         num = tb->ctors? mono_array_length (tb->ctors): 0;
8269         for (i = 0; i < num; ++i)
8270                 klass->methods [i] = ctorbuilder_to_mono_method (klass, mono_array_get (tb->ctors, MonoReflectionCtorBuilder*, i));
8271         num = tb->num_methods;
8272         j = i;
8273         for (i = 0; i < num; ++i)
8274                 klass->methods [j++] = methodbuilder_to_mono_method (klass, mono_array_get (tb->methods, MonoReflectionMethodBuilder*, i));
8275
8276         if (tb->interfaces) {
8277                 klass->interface_count = mono_array_length (tb->interfaces);
8278                 klass->interfaces = g_new (MonoClass*, klass->interface_count);
8279                 for (i = 0; i < klass->interface_count; ++i) {
8280                         MonoReflectionType *iface = mono_array_get (tb->interfaces, gpointer, i);
8281                         klass->interfaces [i] = mono_class_from_mono_type (iface->type);
8282                 }
8283         }
8284
8285         if (klass->flags & TYPE_ATTRIBUTE_INTERFACE)
8286                 for (i = 0; i < klass->method.count; ++i)
8287                         klass->methods [i]->slot = i;
8288
8289         /* Overrides */
8290         onum = 0;
8291         if (tb->methods) {
8292                 for (i = 0; i < tb->num_methods; ++i) {
8293                         MonoReflectionMethodBuilder *mb = 
8294                                 mono_array_get (tb->methods, MonoReflectionMethodBuilder*, i);
8295                         if (mb->override_method)
8296                                 onum ++;
8297                 }
8298         }
8299
8300         overrides = g_new0 (MonoMethod*, onum * 2);
8301
8302         if (tb->methods) {
8303                 onum = 0;
8304                 for (i = 0; i < tb->num_methods; ++i) {
8305                         MonoReflectionMethodBuilder *mb = 
8306                                 mono_array_get (tb->methods, MonoReflectionMethodBuilder*, i);
8307                         if (mb->override_method) {
8308                                 /* FIXME: What if 'override_method' is a MethodBuilder ? */
8309                                 overrides [onum * 2] = 
8310                                         mb->override_method->method;
8311                                 overrides [onum * 2 + 1] =
8312                                         mb->mhandle;
8313
8314                                 g_assert (mb->mhandle);
8315
8316                                 onum ++;
8317                         }
8318                 }
8319         }
8320
8321         mono_class_setup_vtable (klass, overrides, onum);
8322         g_free (overrides);
8323 }
8324
8325 static void
8326 typebuilder_setup_fields (MonoClass *klass)
8327 {
8328         MonoReflectionTypeBuilder *tb = klass->reflection_info;
8329         MonoReflectionFieldBuilder *fb;
8330         MonoClassField *field;
8331         const char *p, *p2;
8332         int i;
8333         guint32 len, idx;
8334
8335         klass->field.count = tb->num_fields;
8336         klass->field.first = 0;
8337         klass->field.last = klass->field.count;
8338
8339         if (!klass->field.count)
8340                 return;
8341         
8342         klass->fields = g_new0 (MonoClassField, klass->field.count);
8343
8344         for (i = 0; i < klass->field.count; ++i) {
8345                 fb = mono_array_get (tb->fields, gpointer, i);
8346                 field = &klass->fields [i];
8347                 field->name = mono_string_to_utf8 (fb->name);
8348                 if (fb->attrs) {
8349                         /* FIXME: handle type modifiers */
8350                         field->type = g_memdup (fb->type->type, sizeof (MonoType));
8351                         field->type->attrs = fb->attrs;
8352                 } else {
8353                         field->type = fb->type->type;
8354                 }
8355                 if ((fb->attrs & FIELD_ATTRIBUTE_HAS_FIELD_RVA) && fb->rva_data)
8356                         field->data = mono_array_addr (fb->rva_data, char, 0);
8357                 if (fb->offset != -1)
8358                         field->offset = fb->offset;
8359                 field->parent = klass;
8360                 fb->handle = field;
8361                 mono_save_custom_attrs (klass->image, field, fb->cattrs);
8362
8363                 if (fb->def_value) {
8364                         MonoDynamicImage *assembly = (MonoDynamicImage*)klass->image;
8365                         field->type->attrs |= FIELD_ATTRIBUTE_HAS_DEFAULT;
8366                         idx = encode_constant (assembly, fb->def_value, &field->def_type);
8367                         /* Copy the data from the blob since it might get realloc-ed */
8368                         p = assembly->blob.data + idx;
8369                         len = mono_metadata_decode_blob_size (p, &p2);
8370                         len += p2 - p;
8371                         field->data = g_malloc (len);
8372                         memcpy ((gpointer)field->data, p, len);
8373                 }
8374         }
8375         mono_class_layout_fields (klass);
8376 }
8377
8378 static void
8379 typebuilder_setup_properties (MonoClass *klass)
8380 {
8381         MonoReflectionTypeBuilder *tb = klass->reflection_info;
8382         MonoReflectionPropertyBuilder *pb;
8383         int i;
8384
8385         klass->property.count = tb->properties ? mono_array_length (tb->properties) : 0;
8386         klass->property.first = 0;
8387         klass->property.last = klass->property.count;
8388
8389         klass->properties = g_new0 (MonoProperty, klass->property.count);
8390         for (i = 0; i < klass->property.count; ++i) {
8391                 pb = mono_array_get (tb->properties, MonoReflectionPropertyBuilder*, i);
8392                 klass->properties [i].parent = klass;
8393                 klass->properties [i].attrs = pb->attrs;
8394                 klass->properties [i].name = mono_string_to_utf8 (pb->name);
8395                 if (pb->get_method)
8396                         klass->properties [i].get = pb->get_method->mhandle;
8397                 if (pb->set_method)
8398                         klass->properties [i].set = pb->set_method->mhandle;
8399         }
8400 }
8401
8402 MonoReflectionEvent *
8403 mono_reflection_event_builder_get_event_info (MonoReflectionTypeBuilder *tb, MonoReflectionEventBuilder *eb)
8404 {
8405         MonoEvent *event = g_new0 (MonoEvent, 1);
8406         MonoClass *klass;
8407         int j;
8408
8409         klass = my_mono_class_from_mono_type (tb->type.type);
8410
8411         event->parent = klass;
8412         event->attrs = eb->attrs;
8413         event->name = mono_string_to_utf8 (eb->name);
8414         if (eb->add_method)
8415                 event->add = eb->add_method->mhandle;
8416         if (eb->remove_method)
8417                 event->remove = eb->remove_method->mhandle;
8418         if (eb->raise_method)
8419                 event->raise = eb->raise_method->mhandle;
8420
8421         if (eb->other_methods) {
8422                 event->other = g_new0 (MonoMethod*, mono_array_length (eb->other_methods) + 1);
8423                 for (j = 0; j < mono_array_length (eb->other_methods); ++j) {
8424                         MonoReflectionMethodBuilder *mb = 
8425                                 mono_array_get (eb->other_methods,
8426                                                 MonoReflectionMethodBuilder*, j);
8427                         event->other [j] = mb->mhandle;
8428                 }
8429         }
8430
8431         return mono_event_get_object (mono_object_domain (tb), klass, event);
8432 }
8433
8434 static void
8435 typebuilder_setup_events (MonoClass *klass)
8436 {
8437         MonoReflectionTypeBuilder *tb = klass->reflection_info;
8438         MonoReflectionEventBuilder *eb;
8439         int i, j;
8440
8441         klass->event.count = tb->events ? mono_array_length (tb->events) : 0;
8442         klass->event.first = 0;
8443         klass->event.last = klass->event.count;
8444
8445         klass->events = g_new0 (MonoEvent, klass->event.count);
8446         for (i = 0; i < klass->event.count; ++i) {
8447                 eb = mono_array_get (tb->events, MonoReflectionEventBuilder*, i);
8448                 klass->events [i].parent = klass;
8449                 klass->events [i].attrs = eb->attrs;
8450                 klass->events [i].name = mono_string_to_utf8 (eb->name);
8451                 if (eb->add_method)
8452                         klass->events [i].add = eb->add_method->mhandle;
8453                 if (eb->remove_method)
8454                         klass->events [i].remove = eb->remove_method->mhandle;
8455                 if (eb->raise_method)
8456                         klass->events [i].raise = eb->raise_method->mhandle;
8457
8458                 if (eb->other_methods) {
8459                         klass->events [i].other = g_new0 (MonoMethod*, mono_array_length (eb->other_methods) + 1);
8460                         for (j = 0; j < mono_array_length (eb->other_methods); ++j) {
8461                                 MonoReflectionMethodBuilder *mb = 
8462                                         mono_array_get (eb->other_methods,
8463                                                                         MonoReflectionMethodBuilder*, j);
8464                                 klass->events [i].other [j] = mb->mhandle;
8465                         }
8466                 }
8467         }
8468 }
8469
8470 MonoReflectionType*
8471 mono_reflection_create_runtime_class (MonoReflectionTypeBuilder *tb)
8472 {
8473         MonoClass *klass;
8474         MonoReflectionType* res;
8475         int i;
8476
8477         MONO_ARCH_SAVE_REGS;
8478
8479         klass = my_mono_class_from_mono_type (tb->type.type);
8480
8481         mono_save_custom_attrs (klass->image, klass, tb->cattrs);
8482
8483         /*
8484          * Fields to set in klass:
8485          * the various flags: delegate/unicode/contextbound etc.
8486          */
8487         klass->flags = tb->attrs;
8488
8489         if (!((MonoDynamicImage*)(MonoDynamicImage*)klass->image)->run)
8490                 /* No need to fully construct the type */
8491                 return mono_type_get_object (mono_object_domain (tb), &klass->byval_arg);
8492
8493         /* enums are done right away */
8494         if (!klass->enumtype)
8495                 ensure_runtime_vtable (klass);
8496
8497         if (tb->subtypes) {
8498                 for (i = 0; i < mono_array_length (tb->subtypes); ++i) {
8499                         MonoReflectionTypeBuilder *subtb = mono_array_get (tb->subtypes, MonoReflectionTypeBuilder*, i);
8500                         klass->nested_classes = g_list_prepend (klass->nested_classes, my_mono_class_from_mono_type (subtb->type.type));
8501                 }
8502         }
8503
8504         /* fields and object layout */
8505         if (klass->parent) {
8506                 if (!klass->parent->size_inited)
8507                         mono_class_init (klass->parent);
8508                 klass->instance_size += klass->parent->instance_size;
8509                 klass->class_size += klass->parent->class_size;
8510                 klass->min_align = klass->parent->min_align;
8511         } else {
8512                 klass->instance_size = sizeof (MonoObject);
8513                 klass->min_align = 1;
8514         }
8515
8516         /* FIXME: handle packing_size and instance_size */
8517         typebuilder_setup_fields (klass);
8518
8519         typebuilder_setup_properties (klass);
8520
8521         typebuilder_setup_events (klass);
8522
8523         klass->wastypebuilder = TRUE;
8524
8525         res = mono_type_get_object (mono_object_domain (tb), &klass->byval_arg);
8526         g_assert (res != (MonoReflectionType*)tb);
8527         return res;
8528 }
8529
8530 void
8531 mono_reflection_initialize_generic_parameter (MonoReflectionGenericParam *gparam)
8532 {
8533         MonoGenericParam *param;
8534         MonoImage *image;
8535
8536         MONO_ARCH_SAVE_REGS;
8537
8538         param = g_new0 (MonoGenericParam, 1);
8539
8540         if (gparam->mbuilder) {
8541                 if (!gparam->mbuilder->generic_container)
8542                         gparam->mbuilder->generic_container = g_new0 (MonoGenericContainer, 1);
8543                 param->owner = gparam->mbuilder->generic_container;
8544         } else if (gparam->tbuilder) {
8545                 MonoReflectionTypeBuilder *nesting = (MonoReflectionTypeBuilder*) gparam->tbuilder->nesting_type;
8546                 MonoGenericContainer *container = gparam->tbuilder->generic_container;
8547
8548                 while (nesting) {
8549                         int count;
8550
8551                         count = nesting->generic_params ? mono_array_length (nesting->generic_params) : 0;
8552                         if (gparam->index >= count)
8553                                 break;
8554
8555                         container = nesting->generic_container;
8556                         nesting = (MonoReflectionTypeBuilder*) nesting->nesting_type;
8557                 }
8558
8559                 g_assert (container);
8560                 param->owner = container;
8561         }
8562
8563         param->method = NULL;
8564         param->name = mono_string_to_utf8 (gparam->name);
8565         param->num = gparam->index;
8566
8567         image = &gparam->tbuilder->module->dynamic_image->image;
8568         mono_class_from_generic_parameter (param, image, gparam->mbuilder != NULL);
8569
8570         param->pklass->reflection_info = gparam;
8571
8572         gparam->type.type = g_new0 (MonoType, 1);
8573         gparam->type.type->type = gparam->mbuilder ? MONO_TYPE_MVAR : MONO_TYPE_VAR;
8574         gparam->type.type->attrs = TYPE_ATTRIBUTE_PUBLIC;
8575         gparam->type.type->data.generic_param = param;
8576 }
8577
8578 MonoArray *
8579 mono_reflection_sighelper_get_signature_local (MonoReflectionSigHelper *sig)
8580 {
8581         MonoDynamicImage *assembly = sig->module->dynamic_image;
8582         guint32 na = mono_array_length (sig->arguments);
8583         guint32 buflen, i;
8584         MonoArray *result;
8585         char *buf, *p;
8586
8587         MONO_ARCH_SAVE_REGS;
8588
8589         p = buf = g_malloc (10 + na * 10);
8590
8591         mono_metadata_encode_value (0x07, p, &p);
8592         mono_metadata_encode_value (na, p, &p);
8593         for (i = 0; i < na; ++i) {
8594                 MonoReflectionType *type = mono_array_get (sig->arguments, MonoReflectionType *, i);
8595                 encode_reflection_type (assembly, type, p, &p);
8596         }
8597
8598         buflen = p - buf;
8599         result = mono_array_new (mono_domain_get (), mono_defaults.byte_class, buflen);
8600         p = mono_array_addr (result, char, 0);
8601         memcpy (p, buf, buflen);
8602         g_free (buf);
8603
8604         return result;
8605 }
8606
8607 MonoArray *
8608 mono_reflection_sighelper_get_signature_field (MonoReflectionSigHelper *sig)
8609 {
8610         MonoDynamicImage *assembly = sig->module->dynamic_image;
8611         guint32 na = mono_array_length (sig->arguments);
8612         guint32 buflen, i;
8613         MonoArray *result;
8614         char *buf, *p;
8615
8616         MONO_ARCH_SAVE_REGS;
8617
8618         p = buf = g_malloc (10 + na * 10);
8619
8620         mono_metadata_encode_value (0x06, p, &p);
8621         for (i = 0; i < na; ++i) {
8622                 MonoReflectionType *type = mono_array_get (sig->arguments, MonoReflectionType *, i);
8623                 encode_reflection_type (assembly, type, p, &p);
8624         }
8625
8626         buflen = p - buf;
8627         result = mono_array_new (mono_domain_get (), mono_defaults.byte_class, buflen);
8628         p = mono_array_addr (result, char, 0);
8629         memcpy (p, buf, buflen);
8630         g_free (buf);
8631
8632         return result;
8633 }
8634
8635 void 
8636 mono_reflection_create_dynamic_method (MonoReflectionDynamicMethod *mb)
8637 {
8638         ReflectionMethodBuilder rmb;
8639         MonoMethodSignature *sig;
8640         int i;
8641
8642         sig = dynamic_method_to_signature (mb);
8643
8644         reflection_methodbuilder_from_dynamic_method (&rmb, mb);
8645
8646         /*
8647          * Resolve references.
8648          */
8649         rmb.nrefs = mb->nrefs;
8650         rmb.refs = g_new0 (gpointer, mb->nrefs + 1);
8651         for (i = 0; i < mb->nrefs; ++i) {
8652                 gpointer ref = resolve_object (mb->module->image, 
8653                                                mono_array_get (mb->refs, MonoObject*, i));
8654                 if (!ref) {
8655                         g_free (rmb.refs);
8656                         mono_raise_exception (mono_get_exception_type_load (NULL));
8657                         return;
8658                 }
8659                 rmb.refs [i] = ref;
8660         }               
8661
8662         /* FIXME: class */
8663         mb->mhandle = reflection_methodbuilder_to_mono_method (mono_defaults.object_class, &rmb, sig);
8664
8665         g_free (rmb.refs);
8666
8667         /* ilgen is no longer needed */
8668         mb->ilgen = NULL;
8669 }
8670
8671 /**
8672  * mono_reflection_lookup_dynamic_token:
8673  *
8674  * Finish the Builder object pointed to by TOKEN and return the corresponding
8675  * runtime structure.
8676  */
8677 gpointer
8678 mono_reflection_lookup_dynamic_token (MonoImage *image, guint32 token)
8679 {
8680         MonoDynamicImage *assembly = (MonoDynamicImage*)image;
8681         MonoObject *obj;
8682
8683         obj = mono_g_hash_table_lookup (assembly->tokens, GUINT_TO_POINTER (token));
8684         g_assert (obj);
8685
8686         return resolve_object (image, obj);
8687 }
8688
8689 static gpointer
8690 resolve_object (MonoImage *image, MonoObject *obj)
8691 {
8692         gpointer result = NULL;
8693
8694         if (strcmp (obj->vtable->klass->name, "String") == 0) {
8695                 result = mono_string_intern ((MonoString*)obj);
8696                 g_assert (result);
8697         } else if (strcmp (obj->vtable->klass->name, "MonoType") == 0) {
8698                 MonoReflectionType *tb = (MonoReflectionType*)obj;
8699                 result = mono_class_from_mono_type (tb->type);
8700                 g_assert (result);
8701         } else if (strcmp (obj->vtable->klass->name, "MonoMethod") == 0) {
8702                 result = ((MonoReflectionMethod*)obj)->method;
8703                 g_assert (result);
8704         } else if (strcmp (obj->vtable->klass->name, "MonoCMethod") == 0) {
8705                 result = ((MonoReflectionMethod*)obj)->method;
8706                 g_assert (result);
8707         } else if (strcmp (obj->vtable->klass->name, "MethodBuilder") == 0) {
8708                 MonoReflectionMethodBuilder *mb = (MonoReflectionMethodBuilder*)obj;
8709                 result = mb->mhandle;
8710                 if (!result) {
8711                         /* Type is not yet created */
8712                         MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder*)mb->type;
8713
8714                         mono_domain_try_type_resolve (mono_domain_get (), NULL, (MonoObject*)tb);
8715
8716                         /*
8717                          * Hopefully this has been filled in by calling CreateType() on the
8718                          * TypeBuilder.
8719                          */
8720                         /*
8721                          * TODO: This won't work if the application finishes another 
8722                          * TypeBuilder instance instead of this one.
8723                          */
8724                         result = mb->mhandle;
8725                 }
8726         } else if (strcmp (obj->vtable->klass->name, "ConstructorBuilder") == 0) {
8727                 MonoReflectionCtorBuilder *cb = (MonoReflectionCtorBuilder*)obj;
8728
8729                 result = cb->mhandle;
8730                 if (!result) {
8731                         MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder*)cb->type;
8732
8733                         mono_domain_try_type_resolve (mono_domain_get (), NULL, (MonoObject*)tb);
8734                         result = cb->mhandle;
8735                 }
8736         } else if (strcmp (obj->vtable->klass->name, "MonoField") == 0) {
8737                 result = ((MonoReflectionField*)obj)->field;
8738                 g_assert (result);
8739         } else if (strcmp (obj->vtable->klass->name, "FieldBuilder") == 0) {
8740                 MonoReflectionFieldBuilder *fb = (MonoReflectionFieldBuilder*)obj;
8741                 result = fb->handle;
8742
8743                 if (!result) {
8744                         MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder*)fb->typeb;
8745
8746                         mono_domain_try_type_resolve (mono_domain_get (), NULL, (MonoObject*)tb);
8747                         result = fb->handle;
8748                 }
8749         } else if (strcmp (obj->vtable->klass->name, "TypeBuilder") == 0) {
8750                 MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder*)obj;
8751                 MonoClass *klass;
8752
8753                 klass = tb->type.type->data.klass;
8754                 if (klass->wastypebuilder) {
8755                         /* Already created */
8756                         result = klass;
8757                 }
8758                 else {
8759                         mono_domain_try_type_resolve (mono_domain_get (), NULL, (MonoObject*)tb);
8760                         result = tb->type.type->data.klass;
8761                         g_assert (result);
8762                 }
8763         } else if (strcmp (obj->vtable->klass->name, "SignatureHelper") == 0) {
8764                 MonoReflectionSigHelper *helper = (MonoReflectionSigHelper*)obj;
8765                 MonoMethodSignature *sig;
8766                 int nargs, i;
8767
8768                 if (helper->arguments)
8769                         nargs = mono_array_length (helper->arguments);
8770                 else
8771                         nargs = 0;
8772
8773                 sig = mono_metadata_signature_alloc (image, nargs);
8774                 sig->explicit_this = helper->call_conv & 64;
8775                 sig->hasthis = helper->call_conv & 32;
8776
8777                 if (helper->call_conv == 0) /* unmanaged */
8778                         sig->call_convention = helper->unmanaged_call_conv - 1;
8779                 else
8780                         if (helper->call_conv & 0x02)
8781                                 sig->call_convention = MONO_CALL_VARARG;
8782                 else
8783                         sig->call_convention = MONO_CALL_DEFAULT;
8784
8785                 sig->param_count = nargs;
8786                 /* TODO: Copy type ? */
8787                 sig->ret = helper->return_type->type;
8788                 for (i = 0; i < nargs; ++i) {
8789                         MonoReflectionType *rt = mono_array_get (helper->arguments, MonoReflectionType*, i);
8790                         sig->params [i] = rt->type;
8791                 }
8792
8793                 result = sig;
8794         } else {
8795                 g_print (obj->vtable->klass->name);
8796                 g_assert_not_reached ();
8797         }
8798         return result;
8799 }
8800
8801
8802 /* SECURITY_ACTION_* are defined in mono/metadata/tabledefs.h */
8803 const static guint32 declsec_flags_map[] = {
8804         0x00000000,                                     /* empty */
8805         MONO_DECLSEC_FLAG_REQUEST,                      /* SECURITY_ACTION_REQUEST                      (x01) */
8806         MONO_DECLSEC_FLAG_DEMAND,                       /* SECURITY_ACTION_DEMAND                       (x02) */
8807         MONO_DECLSEC_FLAG_ASSERT,                       /* SECURITY_ACTION_ASSERT                       (x03) */
8808         MONO_DECLSEC_FLAG_DENY,                         /* SECURITY_ACTION_DENY                         (x04) */
8809         MONO_DECLSEC_FLAG_PERMITONLY,                   /* SECURITY_ACTION_PERMITONLY                   (x05) */
8810         MONO_DECLSEC_FLAG_LINKDEMAND,                   /* SECURITY_ACTION_LINKDEMAND                   (x06) */
8811         MONO_DECLSEC_FLAG_INHERITANCEDEMAND,            /* SECURITY_ACTION_INHERITANCEDEMAND            (x07) */
8812         MONO_DECLSEC_FLAG_REQUEST_MINIMUM,              /* SECURITY_ACTION_REQUEST_MINIMUM              (x08) */
8813         MONO_DECLSEC_FLAG_REQUEST_OPTIONAL,             /* SECURITY_ACTION_REQUEST_OPTIONAL             (x09) */
8814         MONO_DECLSEC_FLAG_REQUEST_REFUSE,               /* SECURITY_ACTION_REQUEST_REFUSE               (x0A) */
8815         MONO_DECLSEC_FLAG_PREJIT_GRANT,                 /* SECURITY_ACTION_PREJIT_GRANT                 (x0B) */
8816         MONO_DECLSEC_FLAG_PREJIT_DENY,                  /* SECURITY_ACTION_PREJIT_DENY                  (x0C) */
8817         MONO_DECLSEC_FLAG_NONCAS_DEMAND,                /* SECURITY_ACTION_NONCAS_DEMAND                (x0D) */
8818         MONO_DECLSEC_FLAG_NONCAS_LINKDEMAND,            /* SECURITY_ACTION_NONCAS_LINKDEMAND            (x0E) */
8819         MONO_DECLSEC_FLAG_NONCAS_INHERITANCEDEMAND,     /* SECURITY_ACTION_NONCAS_INHERITANCEDEMAND     (x0F) */
8820         MONO_DECLSEC_FLAG_LINKDEMAND_CHOICE,            /* SECURITY_ACTION_LINKDEMAND_CHOICE            (x10) */
8821         MONO_DECLSEC_FLAG_INHERITANCEDEMAND_CHOICE,     /* SECURITY_ACTION_INHERITANCEDEMAND_CHOICE     (x11) */
8822         MONO_DECLSEC_FLAG_DEMAND_CHOICE,                /* SECURITY_ACTION_DEMAND_CHOICE                (x12) */
8823 };
8824
8825 /*
8826  * Returns flags that includes all available security action associated to the handle.
8827  * @token: metadata token (either for a class or a method)
8828  * @image: image where resides the metadata.
8829  */
8830 static guint32
8831 mono_declsec_get_flags (MonoImage *image, guint32 token)
8832 {
8833         guint32 index = mono_metadata_declsec_from_index (image, token);
8834         MonoTableInfo *t = &image->tables [MONO_TABLE_DECLSECURITY];
8835         guint32 result = 0;
8836         guint32 action;
8837         int i;
8838
8839         for (i = index; i < t->rows; i++) {
8840                 guint32 cols [MONO_DECL_SECURITY_SIZE];
8841
8842                 mono_metadata_decode_row (t, i, cols, MONO_DECL_SECURITY_SIZE);
8843                 if (cols [MONO_DECL_SECURITY_PARENT] != token)
8844                         break;
8845
8846                 action = cols [MONO_DECL_SECURITY_ACTION];
8847                 if ((action >= MONO_DECLSEC_ACTION_MIN) && (action <= MONO_DECLSEC_ACTION_MAX)) {
8848                         result |= declsec_flags_map [action];
8849                 } else {
8850                         g_assert_not_reached ();
8851                 }
8852         }
8853         return result;
8854 }
8855
8856 /*
8857  * Get the security actions (in the form of flags) associated with the specified method.
8858  *
8859  * @method: The method for which we want the declarative security flags.
8860  * Return the declarative security flags for the method (only).
8861  *
8862  * Note: To keep MonoMethod size down we do not cache the declarative security flags
8863  *       (except for the stack modifiers which are kept in the MonoJitInfo structure)
8864  */
8865 guint32
8866 mono_declsec_flags_from_method (MonoMethod *method)
8867 {
8868         if (method->flags & METHOD_ATTRIBUTE_HAS_SECURITY) {
8869                 /* FIXME: No cache (for the moment) */
8870                 guint32 idx = find_method_index (method);
8871                 idx <<= MONO_HAS_DECL_SECURITY_BITS;
8872                 idx |= MONO_HAS_DECL_SECURITY_METHODDEF;
8873                 return mono_declsec_get_flags (method->klass->image, idx);
8874         }
8875         return 0;
8876 }
8877
8878 /*
8879  * Get the security actions (in the form of flags) associated with the specified class.
8880  *
8881  * @klass: The class for which we want the declarative security flags.
8882  * Return the declarative security flags for the class.
8883  *
8884  * Note: We cache the flags inside the MonoClass structure as this will get 
8885  *       called very often (at least for each method).
8886  */
8887 guint32
8888 mono_declsec_flags_from_class (MonoClass *klass)
8889 {
8890         if (klass->flags & TYPE_ATTRIBUTE_HAS_SECURITY) {
8891                 if (!klass->declsec_flags) {
8892                         guint32 idx = mono_metadata_token_index (klass->type_token);
8893                         idx <<= MONO_HAS_DECL_SECURITY_BITS;
8894                         idx |= MONO_HAS_DECL_SECURITY_TYPEDEF;
8895                         /* we cache the flags on classes */
8896                         klass->declsec_flags = mono_declsec_get_flags (klass->image, idx);
8897                 }
8898                 return klass->declsec_flags;
8899         }
8900         return 0;
8901 }
8902
8903 /*
8904  * Get the security actions (in the form of flags) associated with the specified assembly.
8905  *
8906  * @assembly: The assembly for which we want the declarative security flags.
8907  * Return the declarative security flags for the assembly.
8908  */
8909 guint32
8910 mono_declsec_flags_from_assembly (MonoAssembly *assembly)
8911 {
8912         guint32 idx = 1; /* there is only one assembly */
8913         idx <<= MONO_HAS_DECL_SECURITY_BITS;
8914         idx |= MONO_HAS_DECL_SECURITY_ASSEMBLY;
8915         return mono_declsec_get_flags (assembly->image, idx);
8916 }