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