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