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