2003-08-27 Zoltan Varga <vargaz@freemail.hu>
[mono.git] / mono / metadata / reflection.c
1
2 /*
3  * reflection.c: Routines for creating an image at runtime.
4  * 
5  * Author:
6  *   Paolo Molaro (lupus@ximian.com)
7  *
8  * (C) 2001, 2002 Ximian, Inc.  http://www.ximian.com
9  *
10  */
11 #include <config.h>
12 #include "mono/utils/mono-digest.h"
13 #include "mono/metadata/reflection.h"
14 #include "mono/metadata/tabledefs.h"
15 #include "mono/metadata/tokentype.h"
16 #include "mono/metadata/appdomain.h"
17 #include "mono/metadata/opcodes.h"
18 #include "mono/metadata/assembly.h"
19 #include <mono/metadata/exception.h>
20 #include <stdio.h>
21 #include <glib.h>
22 #include <errno.h>
23 #include <time.h>
24 #include <string.h>
25 #include <ctype.h>
26 #include "image.h"
27 #include "cil-coff.h"
28 #include "rawbuffer.h"
29 #include "mono-endian.h"
30 #include "private.h"
31 #include <mono/os/gc_wrapper.h>
32
33 #define TEXT_OFFSET 512
34 #define CLI_H_SIZE 136
35 #define FILE_ALIGN 512
36 #define VIRT_ALIGN 8192
37 #define START_TEXT_RVA  0x00002000
38
39 typedef struct {
40         MonoReflectionILGen *ilgen;
41         MonoReflectionType *rtype;
42         MonoArray *parameters;
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         MonoMethod *mhandle;
53 } ReflectionMethodBuilder;
54
55 const unsigned char table_sizes [64] = {
56         MONO_MODULE_SIZE,
57         MONO_TYPEREF_SIZE,
58         MONO_TYPEDEF_SIZE,
59         0,
60         MONO_FIELD_SIZE,
61         0,
62         MONO_METHOD_SIZE,
63         0,
64         MONO_PARAM_SIZE,
65         MONO_INTERFACEIMPL_SIZE,
66         MONO_MEMBERREF_SIZE,    /* 0x0A */
67         MONO_CONSTANT_SIZE,
68         MONO_CUSTOM_ATTR_SIZE,
69         MONO_FIELD_MARSHAL_SIZE,
70         MONO_DECL_SECURITY_SIZE,
71         MONO_CLASS_LAYOUT_SIZE,
72         MONO_FIELD_LAYOUT_SIZE, /* 0x10 */
73         MONO_STAND_ALONE_SIGNATURE_SIZE,
74         MONO_EVENT_MAP_SIZE,
75         0,
76         MONO_EVENT_SIZE,
77         MONO_PROPERTY_MAP_SIZE,
78         0,
79         MONO_PROPERTY_SIZE,
80         MONO_METHOD_SEMA_SIZE,
81         MONO_METHODIMPL_SIZE,
82         MONO_MODULEREF_SIZE,    /* 0x1A */
83         MONO_TYPESPEC_SIZE,
84         MONO_IMPLMAP_SIZE,      
85         MONO_FIELD_RVA_SIZE,
86         0,
87         0,
88         MONO_ASSEMBLY_SIZE,     /* 0x20 */
89         MONO_ASSEMBLY_PROCESSOR_SIZE,
90         MONO_ASSEMBLYOS_SIZE,
91         MONO_ASSEMBLYREF_SIZE,
92         MONO_ASSEMBLYREFPROC_SIZE,
93         MONO_ASSEMBLYREFOS_SIZE,
94         MONO_FILE_SIZE,
95         MONO_EXP_TYPE_SIZE,
96         MONO_MANIFEST_SIZE,
97         MONO_NESTED_CLASS_SIZE,
98         0       /* 0x2A */
99 };
100
101 /**
102  * These macros can be used to allocate long living atomic data so it won't be
103  * tracked by the garbage collector. We use libgc because it's apparently faster
104  * than g_malloc.
105  */
106 #ifdef HAVE_BOEHM_GC
107 #define ALLOC_ATOMIC(size) GC_MALLOC_ATOMIC (size)
108 #define FREE_ATOMIC(ptr)
109 #define REALLOC_ATOMIC(ptr, size) GC_REALLOC ((ptr), (size))
110 #else
111 #define ALLOC_ATOMIC(size) g_malloc (size)
112 #define FREE_ATOMIC(ptr) g_free (ptr)
113 #define REALLOC_ATOMIC(ptr, size) g_realloc ((ptr), (size))
114 #endif
115
116 static guint32 mono_image_typedef_or_ref (MonoDynamicAssembly *assembly, MonoType *type);
117 static guint32 mono_image_get_methodref_token (MonoDynamicAssembly *assembly, MonoMethod *method);
118 static guint32 mono_image_get_sighelper_token (MonoDynamicAssembly *assembly, MonoReflectionSigHelper *helper);
119 static guint32 encode_marshal_blob (MonoDynamicAssembly *assembly, MonoReflectionMarshal *minfo);
120 static char*   type_get_qualified_name (MonoType *type, MonoAssembly *ass);
121
122 static void
123 alloc_table (MonoDynamicTable *table, guint nrows)
124 {
125         table->rows = nrows;
126         g_assert (table->columns);
127         if (nrows + 1 >= table->alloc_rows) {
128                 while (nrows + 1 >= table->alloc_rows)
129                         if (table->alloc_rows == 0)
130                                 table->alloc_rows = 16;
131                         else
132                                 table->alloc_rows *= 2;
133
134                 if (table->values)
135                         table->values = REALLOC_ATOMIC (table->values, (table->alloc_rows) * table->columns * sizeof (guint32));
136                 else
137                         table->values = ALLOC_ATOMIC ((table->alloc_rows) * table->columns * sizeof (guint32));
138         }
139 }
140
141 static void
142 make_room_in_stream (MonoDynamicStream *stream, int size)
143 {
144         while (stream->alloc_size <= size) {
145                 if (stream->alloc_size < 4096)
146                         stream->alloc_size = 4096;
147                 else
148                         stream->alloc_size *= 2;
149         }
150         if (stream->data)
151                 stream->data = REALLOC_ATOMIC (stream->data, stream->alloc_size);
152         else
153                 stream->data = ALLOC_ATOMIC (stream->alloc_size);
154 }       
155
156 static guint32
157 string_heap_insert (MonoDynamicStream *sh, const char *str)
158 {
159         guint32 idx;
160         guint32 len;
161         gpointer oldkey, oldval;
162
163         if (g_hash_table_lookup_extended (sh->hash, str, &oldkey, &oldval))
164                 return GPOINTER_TO_UINT (oldval);
165
166         len = strlen (str) + 1;
167         idx = sh->index;
168         if (idx + len > sh->alloc_size)
169                 make_room_in_stream (sh, idx + len);
170
171         /*
172          * We strdup the string even if we already copy them in sh->data
173          * so that the string pointers in the hash remain valid even if
174          * we need to realloc sh->data. We may want to avoid that later.
175          */
176         g_hash_table_insert (sh->hash, g_strdup (str), GUINT_TO_POINTER (idx));
177         memcpy (sh->data + idx, str, len);
178         sh->index += len;
179         return idx;
180 }
181
182 static void
183 string_heap_init (MonoDynamicStream *sh)
184 {
185         sh->index = 0;
186         sh->alloc_size = 4096;
187         sh->data = ALLOC_ATOMIC (4096);
188         sh->hash = g_hash_table_new (g_str_hash, g_str_equal);
189         string_heap_insert (sh, "");
190 }
191
192 #if 0 /* never used */
193 static void
194 string_heap_free (MonoDynamicStream *sh)
195 {
196         FREE_ATOMIC (sh->data);
197         g_hash_table_foreach (sh->hash, (GHFunc)g_free, NULL);
198         g_hash_table_destroy (sh->hash);
199 }
200 #endif
201
202 static guint32
203 mono_image_add_stream_data (MonoDynamicStream *stream, const char *data, guint32 len)
204 {
205         guint32 idx;
206         if (stream->alloc_size < stream->index + len)
207                 make_room_in_stream (stream, stream->index + len);
208         memcpy (stream->data + stream->index, data, len);
209         idx = stream->index;
210         stream->index += len;
211         /* 
212          * align index? Not without adding an additional param that controls it since
213          * we may store a blob value in pieces.
214          */
215         return idx;
216 }
217
218 static guint32
219 mono_image_add_stream_zero (MonoDynamicStream *stream, guint32 len)
220 {
221         guint32 idx;
222         if (stream->alloc_size < stream->index + len)
223                 make_room_in_stream (stream, stream->index + len);
224         memset (stream->data + stream->index, 0, len);
225         idx = stream->index;
226         stream->index += len;
227         return idx;
228 }
229
230 static void
231 stream_data_align (MonoDynamicStream *stream)
232 {
233         char buf [4] = {0};
234         guint32 count = stream->index % 4;
235
236         /* we assume the stream data will be aligned */
237         if (count)
238                 mono_image_add_stream_data (stream, buf, 4 - count);
239 }
240
241 static int
242 mono_blob_entry_hash (const char* str)
243 {
244         guint len, h;
245         const char *end;
246         len = mono_metadata_decode_blob_size (str, &str);
247         if (len > 0) {
248                 end = str + len;
249                 h = *str;
250                 for (str += 1; str < end; str++)
251                         h = (h << 5) - h + *str;
252                 return h;
253         }
254         else
255                 return 0;
256 }
257
258 static gboolean
259 mono_blob_entry_equal (const char *str1, const char *str2) {
260         int len, len2;
261         const char *end1;
262         const char *end2;
263         len = mono_metadata_decode_blob_size (str1, &end1);
264         len2 = mono_metadata_decode_blob_size (str2, &end2);
265         if (len != len2)
266                 return 0;
267         return memcmp (end1, end2, len) == 0;
268 }
269
270 static guint32
271 add_to_blob_cached (MonoDynamicAssembly *assembly, char *b1, int s1, char *b2, int s2)
272 {
273         guint32 idx;
274         char *copy;
275         gpointer oldkey, oldval;
276         
277         copy = ALLOC_ATOMIC (s1+s2);
278         memcpy (copy, b1, s1);
279         memcpy (copy + s1, b2, s2);
280         if (mono_g_hash_table_lookup_extended (assembly->blob_cache, copy, &oldkey, &oldval)) {
281                 FREE_ATOMIC (copy);
282                 idx = GPOINTER_TO_UINT (oldval);
283         } else {
284                 idx = mono_image_add_stream_data (&assembly->blob, b1, s1);
285                 mono_image_add_stream_data (&assembly->blob, b2, s2);
286                 mono_g_hash_table_insert (assembly->blob_cache, copy, GUINT_TO_POINTER (idx));
287         }
288         return idx;
289 }
290
291 /* modified version needed to handle building corlib */
292 static MonoClass*
293 my_mono_class_from_mono_type (MonoType *type) {
294         switch (type->type) {
295         case MONO_TYPE_ARRAY:
296         case MONO_TYPE_PTR:
297         case MONO_TYPE_SZARRAY:
298                 return mono_class_from_mono_type (type);
299         default:
300                 /* should be always valid when we reach this case... */
301                 return type->data.klass;
302         }
303 }
304
305 static void
306 encode_type (MonoDynamicAssembly *assembly, MonoType *type, char *p, char **endbuf)
307 {
308         if (!type) {
309                 g_assert_not_reached ();
310                 return;
311         }
312                 
313         if (type->byref)
314                 mono_metadata_encode_value (MONO_TYPE_BYREF, p, &p);
315
316         switch (type->type){
317         case MONO_TYPE_VOID:
318         case MONO_TYPE_BOOLEAN:
319         case MONO_TYPE_CHAR:
320         case MONO_TYPE_I1:
321         case MONO_TYPE_U1:
322         case MONO_TYPE_I2:
323         case MONO_TYPE_U2:
324         case MONO_TYPE_I4:
325         case MONO_TYPE_U4:
326         case MONO_TYPE_I8:
327         case MONO_TYPE_U8:
328         case MONO_TYPE_R4:
329         case MONO_TYPE_R8:
330         case MONO_TYPE_I:
331         case MONO_TYPE_U:
332         case MONO_TYPE_STRING:
333         case MONO_TYPE_OBJECT:
334         case MONO_TYPE_TYPEDBYREF:
335                 mono_metadata_encode_value (type->type, p, &p);
336                 break;
337         case MONO_TYPE_PTR:
338                 mono_metadata_encode_value (type->type, p, &p);
339                 encode_type (assembly, type->data.type, p, &p);
340                 break;
341         case MONO_TYPE_SZARRAY:
342                 mono_metadata_encode_value (type->type, p, &p);
343                 encode_type (assembly, &type->data.klass->byval_arg, p, &p);
344                 break;
345         case MONO_TYPE_VALUETYPE:
346         case MONO_TYPE_CLASS:
347                 mono_metadata_encode_value (type->type, p, &p);
348                 mono_metadata_encode_value (mono_image_typedef_or_ref (assembly, type), p, &p);
349                 break;
350 #if 0
351         case MONO_TYPE_VALUETYPE:
352         case MONO_TYPE_CLASS: {
353                 MonoClass *k = mono_class_from_mono_type (type);
354                 mono_metadata_encode_value (type->type, p, &p);
355                 /* ensure only non-byref gets passed to mono_image_typedef_or_ref() */
356                 mono_metadata_encode_value (mono_image_typedef_or_ref (assembly, &k->byval_arg), p, &p);
357                 break;
358         }
359 #endif
360         case MONO_TYPE_ARRAY:
361                 mono_metadata_encode_value (type->type, p, &p);
362                 encode_type (assembly, &type->data.array->eklass->byval_arg, p, &p);
363                 mono_metadata_encode_value (type->data.array->rank, p, &p);
364                 mono_metadata_encode_value (0, p, &p); /* FIXME: set to 0 for now */
365                 mono_metadata_encode_value (0, p, &p);
366                 break;
367         case MONO_TYPE_GENERICINST: {
368                 int i;
369                 mono_metadata_encode_value (type->type, p, &p);
370                 encode_type (assembly, type->data.generic_inst->generic_type, p, &p);
371                 mono_metadata_encode_value (type->data.generic_inst->type_argc, p, &p);
372                 for (i = 0; i < type->data.generic_inst->type_argc; ++i) {
373                         encode_type (assembly, type->data.generic_inst->type_argv [i], p, &p);
374                 }
375                 break;
376         }
377         default:
378                 g_error ("need to encode type %x", type->type);
379         }
380         *endbuf = p;
381 }
382
383 static void
384 encode_reflection_type (MonoDynamicAssembly *assembly, MonoReflectionType *type, char *p, char **endbuf)
385 {
386         if (!type) {
387                 mono_metadata_encode_value (MONO_TYPE_VOID, p, endbuf);
388                 return;
389         }
390         if (type->type) {
391                 encode_type (assembly, type->type, p, endbuf);
392                 return;
393         }
394
395         g_assert_not_reached ();
396
397 }
398
399 static guint32
400 method_encode_signature (MonoDynamicAssembly *assembly, MonoMethodSignature *sig)
401 {
402         char *buf;
403         char *p;
404         int i;
405         guint32 nparams =  sig->param_count;
406         guint32 size = 10 + nparams * 10;
407         guint32 idx;
408         char blob_size [6];
409         char *b = blob_size;
410
411         if (!assembly->save)
412                 return 0;
413
414         p = buf = g_malloc (size);
415         /*
416          * FIXME: vararg, explicit_this, differenc call_conv values...
417          */
418         *p = sig->call_convention;
419         if (sig->hasthis)
420                 *p |= 0x20; /* hasthis */
421         p++;
422         mono_metadata_encode_value (nparams, p, &p);
423         encode_type (assembly, sig->ret, p, &p);
424         for (i = 0; i < nparams; ++i)
425                 encode_type (assembly, sig->params [i], p, &p);
426         /* store length */
427         g_assert (p - buf < size);
428         mono_metadata_encode_value (p-buf, b, &b);
429         idx = add_to_blob_cached (assembly, blob_size, b-blob_size, buf, p-buf);
430         g_free (buf);
431         return idx;
432 }
433
434 static guint32
435 method_builder_encode_signature (MonoDynamicAssembly *assembly, ReflectionMethodBuilder *mb)
436 {
437         /*
438          * FIXME: reuse code from method_encode_signature().
439          */
440         char *buf;
441         char *p;
442         int i;
443         guint32 nparams =  mb->parameters ? mono_array_length (mb->parameters): 0;
444         guint32 size = 10 + nparams * 10;
445         guint32 idx;
446         char blob_size [6];
447         char *b = blob_size;
448         
449         p = buf = g_malloc (size);
450         /* LAMESPEC: all the call conv spec is foobared */
451         *p = mb->call_conv & 0x60; /* has-this, explicit-this */
452         if (mb->call_conv & 2)
453                 *p |= 0x5; /* vararg */
454         if (!(mb->attrs & METHOD_ATTRIBUTE_STATIC))
455                 *p |= 0x20; /* hasthis */
456         p++;
457         mono_metadata_encode_value (nparams, p, &p);
458         encode_reflection_type (assembly, mb->rtype, p, &p);
459         for (i = 0; i < nparams; ++i) {
460                 MonoReflectionType *pt = mono_array_get (mb->parameters, MonoReflectionType*, i);
461                 encode_reflection_type (assembly, pt, p, &p);
462         }
463         /* store length */
464         g_assert (p - buf < size);
465         mono_metadata_encode_value (p-buf, b, &b);
466         idx = add_to_blob_cached (assembly, blob_size, b-blob_size, buf, p-buf);
467         g_free (buf);
468         return idx;
469 }
470
471 static guint32
472 encode_locals (MonoDynamicAssembly *assembly, MonoReflectionILGen *ilgen)
473 {
474         MonoDynamicTable *table;
475         guint32 *values;
476         char *p;
477         guint32 idx, sig_idx, size;
478         guint nl = mono_array_length (ilgen->locals);
479         char *buf;
480         char blob_size [6];
481         char *b = blob_size;
482         int i;
483
484         size = 10 + nl * 10;
485         p = buf = g_malloc (size);
486         table = &assembly->tables [MONO_TABLE_STANDALONESIG];
487         idx = table->next_idx ++;
488         table->rows ++;
489         alloc_table (table, table->rows);
490         values = table->values + idx * MONO_STAND_ALONE_SIGNATURE_SIZE;
491
492         mono_metadata_encode_value (0x07, p, &p);
493         mono_metadata_encode_value (nl, p, &p);
494         for (i = 0; i < nl; ++i) {
495                 MonoReflectionLocalBuilder *lb = mono_array_get (ilgen->locals, MonoReflectionLocalBuilder*, i);
496                 encode_reflection_type (assembly, lb->type, p, &p);
497         }
498         g_assert (p - buf < size);
499         mono_metadata_encode_value (p-buf, b, &b);
500         sig_idx = add_to_blob_cached (assembly, blob_size, b-blob_size, buf, p-buf);
501         g_free (buf);
502
503         values [MONO_STAND_ALONE_SIGNATURE] = sig_idx;
504
505         return idx;
506 }
507
508 static guint32
509 method_count_clauses (MonoReflectionILGen *ilgen)
510 {
511         guint32 num_clauses = 0;
512         int i;
513
514         MonoILExceptionInfo *ex_info;
515         for (i = 0; i < mono_array_length (ilgen->ex_handlers); ++i) {
516                 ex_info = (MonoILExceptionInfo*)mono_array_addr (ilgen->ex_handlers, MonoILExceptionInfo, i);
517                 if (ex_info->handlers)
518                         num_clauses += mono_array_length (ex_info->handlers);
519                 else
520                         num_clauses++;
521         }
522
523         return num_clauses;
524 }
525
526 static MonoExceptionClause*
527 method_encode_clauses (MonoDynamicAssembly *assembly,
528                                            MonoReflectionILGen *ilgen, guint32 num_clauses)
529 {
530         MonoExceptionClause *clauses;
531         MonoExceptionClause *clause;
532         MonoILExceptionInfo *ex_info;
533         MonoILExceptionBlock *ex_block;
534         guint32 finally_start;
535         int i, j, clause_index;;
536
537         clauses = g_new0 (MonoExceptionClause, num_clauses);
538
539         clause_index = 0;
540         for (i = mono_array_length (ilgen->ex_handlers) - 1; i >= 0; --i) {
541                 ex_info = (MonoILExceptionInfo*)mono_array_addr (ilgen->ex_handlers, MonoILExceptionInfo, i);
542                 finally_start = ex_info->start + ex_info->len;
543                 g_assert (ex_info->handlers);
544                 for (j = 0; j < mono_array_length (ex_info->handlers); ++j) {
545                         ex_block = (MonoILExceptionBlock*)mono_array_addr (ex_info->handlers, MonoILExceptionBlock, j);
546                         clause = &(clauses [clause_index]);
547
548                         clause->flags = ex_block->type;
549                         clause->try_offset = ex_info->start;
550
551                         if (ex_block->type == MONO_EXCEPTION_CLAUSE_FINALLY)
552                                 clause->try_len = finally_start - ex_info->start;
553                         else
554                                 clause->try_len = ex_info->len;
555                         clause->handler_offset = ex_block->start;
556                         clause->handler_len = ex_block->len;
557                         clause->token_or_filter = ex_block->extype ? mono_metadata_token_from_dor (
558                                 mono_image_typedef_or_ref (assembly, ex_block->extype->type)): 0;
559                         if (ex_block->extype) {
560                                 mono_g_hash_table_insert (assembly->tokens,
561                                                                                   GUINT_TO_POINTER (clause->token_or_filter),
562                                                                                   ex_block->extype);
563                         }
564                         finally_start = ex_block->start + ex_block->len;
565
566                         clause_index ++;
567                 }
568         }
569
570         return clauses;
571 }
572
573 static guint32
574 method_encode_code (MonoDynamicAssembly *assembly, ReflectionMethodBuilder *mb)
575 {
576         char flags = 0;
577         guint32 idx;
578         guint32 code_size;
579         gint32 max_stack, i;
580         gint32 num_locals = 0;
581         gint32 num_exception = 0;
582         gint maybe_small;
583         guint32 fat_flags;
584         char fat_header [12];
585         guint32 *intp;
586         guint16 *shortp;
587         guint32 local_sig = 0;
588         guint32 header_size = 12;
589         MonoArray *code;
590
591         if ((mb->attrs & METHOD_ATTRIBUTE_PINVOKE_IMPL) ||
592                         (mb->iattrs & METHOD_IMPL_ATTRIBUTE_INTERNAL_CALL) ||
593                         (mb->iattrs & METHOD_IMPL_ATTRIBUTE_RUNTIME) ||
594                         (mb->attrs & METHOD_ATTRIBUTE_ABSTRACT))
595                 return 0;
596
597         /*if (mb->name)
598                 g_print ("Encode method %s\n", mono_string_to_utf8 (mb->name));*/
599         if (mb->ilgen) {
600                 code = mb->ilgen->code;
601                 code_size = mb->ilgen->code_len;
602                 max_stack = mb->ilgen->max_stack;
603                 num_locals = mb->ilgen->locals ? mono_array_length (mb->ilgen->locals) : 0;
604                 if (mb->ilgen->ex_handlers)
605                         num_exception = method_count_clauses (mb->ilgen);
606         } else {
607                 code = mb->code;
608                 if (code == NULL)
609                         mono_raise_exception (mono_get_exception_argument (NULL, "a method does not have any IL associated"));
610
611                 code_size = mono_array_length (code);
612                 max_stack = 8; /* we probably need to run a verifier on the code... */
613         }
614
615         /* check for exceptions, maxstack, locals */
616         maybe_small = (max_stack <= 8) && (!num_locals) && (!num_exception);
617         if (maybe_small) {
618                 if (code_size < 64 && !(code_size & 1)) {
619                         flags = (code_size << 2) | 0x2;
620                 } else if (code_size < 32 && (code_size & 1)) {
621                         flags = (code_size << 2) | 0x6; /* LAMESPEC: see metadata.c */
622                 } else {
623                         goto fat_header;
624                 }
625                 idx = mono_image_add_stream_data (&assembly->code, &flags, 1);
626                 /* add to the fixup todo list */
627                 if (mb->ilgen && mb->ilgen->num_token_fixups)
628                         mono_g_hash_table_insert (assembly->token_fixups, mb->ilgen, GUINT_TO_POINTER (idx + 1));
629                 mono_image_add_stream_data (&assembly->code, mono_array_addr (code, char, 0), code_size);
630                 return assembly->text_rva + idx;
631         } 
632 fat_header:
633         if (num_locals)
634                 local_sig = MONO_TOKEN_SIGNATURE | encode_locals (assembly, mb->ilgen);
635         /* 
636          * FIXME: need to set also the header size in fat_flags.
637          * (and more sects and init locals flags)
638          */
639         fat_flags =  0x03;
640         if (num_exception)
641                 fat_flags |= METHOD_HEADER_MORE_SECTS;
642         if (mb->init_locals)
643                 fat_flags |= METHOD_HEADER_INIT_LOCALS;
644         fat_header [0] = fat_flags;
645         fat_header [1] = (header_size / 4 ) << 4;
646         shortp = (guint16*)(fat_header + 2);
647         *shortp = GUINT16_TO_LE (max_stack);
648         intp = (guint32*)(fat_header + 4);
649         *intp = GUINT32_TO_LE (code_size);
650         intp = (guint32*)(fat_header + 8);
651         *intp = GUINT32_TO_LE (local_sig);
652         idx = mono_image_add_stream_data (&assembly->code, fat_header, 12);
653         /* add to the fixup todo list */
654         if (mb->ilgen && mb->ilgen->num_token_fixups)
655                 mono_g_hash_table_insert (assembly->token_fixups, mb->ilgen, GUINT_TO_POINTER (idx + 12));
656         
657         mono_image_add_stream_data (&assembly->code, mono_array_addr (code, char, 0), code_size);
658         if (num_exception) {
659                 unsigned char sheader [4];
660                 MonoExceptionClause clause;
661                 MonoILExceptionInfo * ex_info;
662                 MonoILExceptionBlock * ex_block;
663                 int j;
664
665                 stream_data_align (&assembly->code);
666                 /* always use fat format for now */
667                 sheader [0] = METHOD_HEADER_SECTION_FAT_FORMAT | METHOD_HEADER_SECTION_EHTABLE;
668                 num_exception *= sizeof (MonoExceptionClause);
669                 num_exception += 4; /* include the size of the header */
670                 sheader [1] = num_exception & 0xff;
671                 sheader [2] = (num_exception >> 8) & 0xff;
672                 sheader [3] = (num_exception >> 16) & 0xff;
673                 mono_image_add_stream_data (&assembly->code, sheader, 4);
674                 /* fat header, so we are already aligned */
675                 /* reverse order */
676                 for (i = mono_array_length (mb->ilgen->ex_handlers) - 1; i >= 0; --i) {
677                         ex_info = (MonoILExceptionInfo *)mono_array_addr (mb->ilgen->ex_handlers, MonoILExceptionInfo, i);
678                         if (ex_info->handlers) {
679                                 int finally_start = ex_info->start + ex_info->len;
680                                 for (j = 0; j < mono_array_length (ex_info->handlers); ++j) {
681                                         ex_block = (MonoILExceptionBlock*)mono_array_addr (ex_info->handlers, MonoILExceptionBlock, j);
682                                         clause.flags = GUINT32_TO_LE (ex_block->type);
683                                         clause.try_offset = GUINT32_TO_LE (ex_info->start);
684                                         /* need fault, too, probably */
685                                         if (ex_block->type == MONO_EXCEPTION_CLAUSE_FINALLY)
686                                                 clause.try_len = GUINT32_TO_LE (finally_start - ex_info->start);
687                                         else
688                                                 clause.try_len = GUINT32_TO_LE (ex_info->len);
689                                         clause.handler_offset = GUINT32_TO_LE (ex_block->start);
690                                         clause.handler_len = GUINT32_TO_LE (ex_block->len);
691                                         finally_start = ex_block->start + ex_block->len;
692                                         clause.token_or_filter = ex_block->extype ? mono_metadata_token_from_dor (
693                                                         mono_image_typedef_or_ref (assembly, ex_block->extype->type)): 0;
694                                         clause.token_or_filter = GUINT32_TO_LE (clause.token_or_filter);
695                                         /*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", 
696                                                         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);*/
697                                         mono_image_add_stream_data (&assembly->code, (char*)&clause, sizeof (clause));
698                                 }
699                         } else {
700                                 g_error ("No clauses for ex info block %d", i);
701                         }
702                 }
703         }
704         return assembly->text_rva + idx;
705 }
706
707 static guint32
708 find_index_in_table (MonoDynamicAssembly *assembly, int table_idx, int col, guint32 token)
709 {
710         int i;
711         MonoDynamicTable *table;
712         guint32 *values;
713         
714         table = &assembly->tables [table_idx];
715
716         g_assert (col < table->columns);
717
718         values = table->values + table->columns;
719         for (i = 1; i <= table->rows; ++i) {
720                 if (values [col] == token)
721                         return i;
722                 values += table->columns;
723         }
724         return 0;
725 }
726
727 static GHashTable *dynamic_custom_attrs = NULL;
728
729 static MonoCustomAttrInfo*
730 mono_custom_attrs_from_builders (MonoImage *image, MonoArray *cattrs)
731 {
732         int i, count;
733         MonoCustomAttrInfo *ainfo;
734         MonoReflectionCustomAttr *cattr;
735
736         if (!cattrs)
737                 return NULL;
738         /* FIXME: check in assembly the Run flag is set */
739
740         count = mono_array_length (cattrs);
741
742         ainfo = g_malloc0 (sizeof (MonoCustomAttrInfo) + sizeof (MonoCustomAttrEntry) * (count - MONO_ZERO_LEN_ARRAY));
743
744         ainfo->image = image;
745         ainfo->num_attrs = count;
746         for (i = 0; i < count; ++i) {
747                 cattr = (MonoReflectionCustomAttr*)mono_array_get (cattrs, gpointer, i);
748                 ainfo->attrs [i].ctor = cattr->ctor->method;
749                 /* FIXME: might want to memdup the data here */
750                 ainfo->attrs [i].data = mono_array_addr (cattr->data, char, 0);
751                 ainfo->attrs [i].data_size = mono_array_length (cattr->data);
752         }
753
754         return ainfo;
755 }
756
757 static void
758 mono_save_custom_attrs (MonoImage *image, void *obj, MonoArray *cattrs)
759 {
760         MonoCustomAttrInfo *ainfo = mono_custom_attrs_from_builders (image, cattrs);
761
762         if (!ainfo)
763                 return;
764
765         if (!dynamic_custom_attrs)
766                 dynamic_custom_attrs = g_hash_table_new (NULL, NULL);
767
768         g_hash_table_insert (dynamic_custom_attrs, obj, ainfo);
769 }
770
771 void
772 mono_custom_attrs_free (MonoCustomAttrInfo *ainfo)
773 {
774         /* they are cached, so we don't free them */
775         if (dynamic_custom_attrs && g_hash_table_lookup (dynamic_custom_attrs, ainfo))
776                 return;
777         g_free (ainfo);
778 }
779
780 /*
781  * idx is the table index of the object
782  * type is one of CUSTOM_ATTR_*
783  */
784 static void
785 mono_image_add_cattrs (MonoDynamicAssembly *assembly, guint32 idx, guint32 type, MonoArray *cattrs)
786 {
787         MonoDynamicTable *table;
788         MonoReflectionCustomAttr *cattr;
789         guint32 *values;
790         guint32 count, i, token;
791         char blob_size [6];
792         char *p = blob_size;
793         
794         /* it is legal to pass a NULL cattrs: we avoid to use the if in a lot of places */
795         if (!cattrs)
796                 return;
797         count = mono_array_length (cattrs);
798         table = &assembly->tables [MONO_TABLE_CUSTOMATTRIBUTE];
799         table->rows += count;
800         alloc_table (table, table->rows);
801         values = table->values + table->next_idx * MONO_CUSTOM_ATTR_SIZE;
802         idx <<= CUSTOM_ATTR_BITS;
803         idx |= type;
804         for (i = 0; i < count; ++i) {
805                 cattr = (MonoReflectionCustomAttr*)mono_array_get (cattrs, gpointer, i);
806                 values [MONO_CUSTOM_ATTR_PARENT] = idx;
807                 token = mono_image_create_token (assembly, (MonoObject*)cattr->ctor);
808                 type = mono_metadata_token_index (token);
809                 type <<= CUSTOM_ATTR_TYPE_BITS;
810                 switch (mono_metadata_token_table (token)) {
811                 case MONO_TABLE_METHOD:
812                         type |= CUSTOM_ATTR_TYPE_METHODDEF;
813                         break;
814                 case MONO_TABLE_MEMBERREF:
815                         type |= CUSTOM_ATTR_TYPE_MEMBERREF;
816                         break;
817                 default:
818                         g_warning ("got wrong token in custom attr");
819                         continue;
820                 }
821                 values [MONO_CUSTOM_ATTR_TYPE] = type;
822                 p = blob_size;
823                 mono_metadata_encode_value (mono_array_length (cattr->data), p, &p);
824                 values [MONO_CUSTOM_ATTR_VALUE] = add_to_blob_cached (assembly, blob_size, p - blob_size,
825                         mono_array_addr (cattr->data, char, 0), mono_array_length (cattr->data));
826                 values += MONO_CUSTOM_ATTR_SIZE;
827                 ++table->next_idx;
828         }
829 }
830
831 /*
832  * Fill in the MethodDef and ParamDef tables for a method.
833  * This is used for both normal methods and constructors.
834  */
835 static void
836 mono_image_basic_method (ReflectionMethodBuilder *mb, MonoDynamicAssembly *assembly)
837 {
838         MonoDynamicTable *table;
839         guint32 *values;
840         char *name;
841         guint i, count;
842
843         /* room in this table is already allocated */
844         table = &assembly->tables [MONO_TABLE_METHOD];
845         *mb->table_idx = table->next_idx ++;
846         mono_g_hash_table_insert (assembly->method_to_table_idx, mb->mhandle, GUINT_TO_POINTER ((*mb->table_idx)));
847         values = table->values + *mb->table_idx * MONO_METHOD_SIZE;
848         if (mb->name) {
849                 name = mono_string_to_utf8 (mb->name);
850                 values [MONO_METHOD_NAME] = string_heap_insert (&assembly->sheap, name);
851                 g_free (name);
852         } else { /* a constructor */
853                 values [MONO_METHOD_NAME] = string_heap_insert (&assembly->sheap, mb->attrs & METHOD_ATTRIBUTE_STATIC? ".cctor": ".ctor");
854                 // MS.NET adds this automatically
855                 mb->attrs |= METHOD_ATTRIBUTE_RT_SPECIAL_NAME;
856         }
857         values [MONO_METHOD_FLAGS] = mb->attrs;
858         values [MONO_METHOD_IMPLFLAGS] = mb->iattrs;
859         values [MONO_METHOD_SIGNATURE] = method_builder_encode_signature (assembly, mb);
860         values [MONO_METHOD_RVA] = method_encode_code (assembly, mb);
861         
862         table = &assembly->tables [MONO_TABLE_PARAM];
863         values [MONO_METHOD_PARAMLIST] = table->next_idx;
864
865         if (mb->pinfo) {
866                 MonoDynamicTable *mtable;
867                 guint32 *mvalues;
868                 
869                 mtable = &assembly->tables [MONO_TABLE_FIELDMARSHAL];
870                 mvalues = mtable->values + mtable->next_idx * MONO_FIELD_MARSHAL_SIZE;
871                 
872                 count = 0;
873                 for (i = 0; i < mono_array_length (mb->pinfo); ++i) {
874                         if (mono_array_get (mb->pinfo, gpointer, i))
875                                 count++;
876                 }
877                 table->rows += count;
878                 alloc_table (table, table->rows);
879                 values = table->values + table->next_idx * MONO_PARAM_SIZE;
880                 for (i = 0; i < mono_array_length (mb->pinfo); ++i) {
881                         MonoReflectionParamBuilder *pb;
882                         if ((pb = mono_array_get (mb->pinfo, MonoReflectionParamBuilder*, i))) {
883                                 values [MONO_PARAM_FLAGS] = pb->attrs;
884                                 values [MONO_PARAM_SEQUENCE] = i;
885                                 if (pb->name != NULL) {
886                                         name = mono_string_to_utf8 (pb->name);
887                                         values [MONO_PARAM_NAME] = string_heap_insert (&assembly->sheap, name);
888                                         g_free (name);
889                                 }
890                                 else
891                                         values [MONO_PARAM_NAME] = 0;
892                                 values += MONO_PARAM_SIZE;
893                                 if (pb->marshal_info) {
894                                         mtable->rows++;
895                                         alloc_table (mtable, mtable->rows);
896                                         mvalues = mtable->values + mtable->rows * MONO_FIELD_MARSHAL_SIZE;
897                                         mvalues [MONO_FIELD_MARSHAL_PARENT] = (table->next_idx << HAS_FIELD_MARSHAL_BITS) | HAS_FIELD_MARSHAL_PARAMDEF;
898                                         mvalues [MONO_FIELD_MARSHAL_NATIVE_TYPE] = encode_marshal_blob (assembly, pb->marshal_info);
899                                 }
900                                 pb->table_idx = table->next_idx++;
901                         }
902                 }
903         }
904 }
905
906 static void
907 mono_image_get_method_info (MonoReflectionMethodBuilder *mb, MonoDynamicAssembly *assembly)
908 {
909         MonoDynamicTable *table;
910         guint32 *values;
911         char *name;
912         ReflectionMethodBuilder rmb;
913
914         rmb.ilgen = mb->ilgen;
915         rmb.rtype = mb->rtype;
916         rmb.parameters = mb->parameters;
917         rmb.pinfo = mb->pinfo;
918         rmb.attrs = mb->attrs;
919         rmb.iattrs = mb->iattrs;
920         rmb.call_conv = mb->call_conv;
921         rmb.code = mb->code;
922         rmb.type = mb->type;
923         rmb.name = mb->name;
924         rmb.table_idx = &mb->table_idx;
925         rmb.init_locals = mb->init_locals;
926         rmb.mhandle = mb->mhandle;
927
928         mono_image_basic_method (&rmb, assembly);
929
930         if (mb->dll) { /* It's a P/Invoke method */
931                 guint32 moduleref;
932                 int charset = mb->charset & 0xf;
933                 int lasterr = mb->charset & 0x40;
934                 table = &assembly->tables [MONO_TABLE_IMPLMAP];
935                 table->rows ++;
936                 alloc_table (table, table->rows);
937                 values = table->values + table->rows * MONO_IMPLMAP_SIZE;
938                 /* map CharSet values to on-disk values */
939                 
940                 values [MONO_IMPLMAP_FLAGS] = (mb->native_cc << 8) | (charset ? (charset - 1) * 2: 1) | lasterr;
941                 values [MONO_IMPLMAP_MEMBER] = (mb->table_idx << 1) | 1; /* memberforwarded: method */
942                 name = mono_string_to_utf8 (mb->dllentry);
943                 values [MONO_IMPLMAP_NAME] = string_heap_insert (&assembly->sheap, name);
944                 g_free (name);
945                 name = mono_string_to_utf8 (mb->dll);
946                 moduleref = string_heap_insert (&assembly->sheap, name);
947                 g_free (name);
948                 if (!(values [MONO_IMPLMAP_SCOPE] = find_index_in_table (assembly, MONO_TABLE_MODULEREF, MONO_MODULEREF_NAME, moduleref))) {
949                         table = &assembly->tables [MONO_TABLE_MODULEREF];
950                         table->rows ++;
951                         alloc_table (table, table->rows);
952                         table->values [table->rows * MONO_MODULEREF_SIZE + MONO_MODULEREF_NAME] = moduleref;
953                         values [MONO_IMPLMAP_SCOPE] = table->rows;
954                 }
955         }
956
957         if (mb->override_method) {
958                 MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder *)mb->type;
959                 guint32 tok;
960                 table = &assembly->tables [MONO_TABLE_METHODIMPL];
961                 table->rows ++;
962                 alloc_table (table, table->rows);
963                 values = table->values + table->rows * MONO_METHODIMPL_SIZE;
964                 values [MONO_METHODIMPL_CLASS] = tb->table_idx;
965                 values [MONO_METHODIMPL_BODY] = METHODDEFORREF_METHODDEF | (mb->table_idx << METHODDEFORREF_BITS);
966                 tok = mono_image_create_token (assembly, (MonoObject*)mb->override_method);
967                 switch (mono_metadata_token_table (tok)) {
968                 case MONO_TABLE_MEMBERREF:
969                         tok = (mono_metadata_token_index (tok) << METHODDEFORREF_BITS ) | METHODDEFORREF_METHODREF;
970                         break;
971                 case MONO_TABLE_METHOD:
972                         tok = (mono_metadata_token_index (tok) << METHODDEFORREF_BITS ) | METHODDEFORREF_METHODDEF;
973                         break;
974                 default:
975                         g_assert_not_reached ();
976                 }
977                 values [MONO_METHODIMPL_DECLARATION] = tok;
978         }
979 }
980
981 static void
982 mono_image_get_ctor_info (MonoDomain *domain, MonoReflectionCtorBuilder *mb, MonoDynamicAssembly *assembly)
983 {
984         ReflectionMethodBuilder rmb;
985
986         rmb.ilgen = mb->ilgen;
987         rmb.rtype = mono_type_get_object (domain, &mono_defaults.void_class->byval_arg);
988         rmb.parameters = mb->parameters;
989         rmb.pinfo = mb->pinfo;
990         rmb.attrs = mb->attrs;
991         rmb.iattrs = mb->iattrs;
992         rmb.call_conv = mb->call_conv;
993         rmb.code = NULL;
994         rmb.type = mb->type;
995         rmb.name = NULL;
996         rmb.table_idx = &mb->table_idx;
997         rmb.init_locals = mb->init_locals;
998         rmb.mhandle = mb->mhandle;
999
1000         mono_image_basic_method (&rmb, assembly);
1001
1002 }
1003
1004 static guint32
1005 fieldref_encode_signature (MonoDynamicAssembly *assembly, MonoClassField *field)
1006 {
1007         char blob_size [64];
1008         char *b = blob_size;
1009         char *p;
1010         char* buf;
1011         guint32 idx;
1012
1013         if (!assembly->save)
1014                 return 0;
1015
1016         p = buf = g_malloc (64);
1017         
1018         mono_metadata_encode_value (0x06, p, &p);
1019         /* encode custom attributes before the type */
1020         encode_type (assembly, field->type, p, &p);
1021         g_assert (p-buf < 64);
1022         mono_metadata_encode_value (p-buf, b, &b);
1023         idx = add_to_blob_cached (assembly, blob_size, b-blob_size, buf, p-buf);
1024         g_free (buf);
1025         return idx;
1026 }
1027
1028 static guint32
1029 field_encode_signature (MonoDynamicAssembly *assembly, MonoReflectionFieldBuilder *fb)
1030 {
1031         char blob_size [64];
1032         char *b = blob_size;
1033         char *p;
1034         char* buf;
1035         guint32 idx;
1036         
1037         p = buf = g_malloc (64);
1038         
1039         mono_metadata_encode_value (0x06, p, &p);
1040         /* encode custom attributes before the type */
1041         encode_reflection_type (assembly, fb->type, p, &p);
1042         g_assert (p-buf < 64);
1043         mono_metadata_encode_value (p-buf, b, &b);
1044         idx = add_to_blob_cached (assembly, blob_size, b-blob_size, buf, p-buf);
1045         g_free (buf);
1046         return idx;
1047 }
1048
1049 /*
1050  * Copy len * nelem bytes from val to dest, swapping bytes to LE if necessary.
1051  * dest may be misaligned.
1052  */
1053 static void
1054 swap_with_size (char *dest, const char* val, int len, int nelem) {
1055 #if G_BYTE_ORDER != G_LITTLE_ENDIAN
1056         int elem;
1057
1058         for (elem = 0; elem < nelem; ++elem) {
1059                 switch (len) {
1060                 case 1:
1061                         *dest = *val;
1062                         break;
1063                 case 2:
1064                         dest [0] = val [1];
1065                         dest [1] = val [0];
1066                         break;
1067                 case 4:
1068                         dest [0] = val [3];
1069                         dest [1] = val [2];
1070                         dest [2] = val [1];
1071                         dest [3] = val [0];
1072                         break;
1073                 case 8:
1074                         dest [0] = val [7];
1075                         dest [1] = val [6];
1076                         dest [2] = val [5];
1077                         dest [3] = val [4];
1078                         dest [4] = val [3];
1079                         dest [5] = val [2];
1080                         dest [6] = val [1];
1081                         dest [7] = val [0];
1082                         break;
1083                 default:
1084                         g_assert_not_reached ();
1085                 }
1086                 dest += len;
1087                 val += len;
1088         }
1089 #else
1090         memcpy (dest, val, len * nelem);
1091 #endif
1092 }
1093
1094 static guint32
1095 encode_constant (MonoDynamicAssembly *assembly, MonoObject *val, guint32 *ret_type) {
1096         char blob_size [64];
1097         char *b = blob_size;
1098         char *p, *box_val;
1099         char* buf;
1100         guint32 idx, len, dummy = 0;
1101         
1102         p = buf = g_malloc (64);
1103         if (!val) {
1104                 *ret_type = MONO_TYPE_CLASS;
1105                 len = 4;
1106                 box_val = (char*)&dummy;
1107         } else {
1108                 box_val = ((char*)val) + sizeof (MonoObject);
1109                 *ret_type = val->vtable->klass->byval_arg.type;
1110         }
1111 handle_enum:
1112         switch (*ret_type) {
1113         case MONO_TYPE_BOOLEAN:
1114         case MONO_TYPE_U1:
1115         case MONO_TYPE_I1:
1116                 len = 1;
1117                 break;
1118         case MONO_TYPE_CHAR:
1119         case MONO_TYPE_U2:
1120         case MONO_TYPE_I2:
1121                 len = 2;
1122                 break;
1123         case MONO_TYPE_U4:
1124         case MONO_TYPE_I4:
1125         case MONO_TYPE_R4:
1126                 len = 4;
1127                 break;
1128         case MONO_TYPE_U8:
1129         case MONO_TYPE_I8:
1130         case MONO_TYPE_R8:
1131                 len = 8;
1132                 break;
1133         case MONO_TYPE_VALUETYPE:
1134                 if (val->vtable->klass->enumtype) {
1135                         *ret_type = val->vtable->klass->enum_basetype->type;
1136                         goto handle_enum;
1137                 } else
1138                         g_error ("we can't encode valuetypes");
1139         case MONO_TYPE_CLASS:
1140                 break;
1141         case MONO_TYPE_STRING: {
1142                 MonoString *str = (MonoString*)val;
1143                 /* there is no signature */
1144                 len = str->length * 2;
1145                 mono_metadata_encode_value (len, b, &b);
1146 #if G_BYTE_ORDER != G_LITTLE_ENDIAN
1147                 {
1148                         char *swapped = g_malloc (2 * mono_string_length (str));
1149                         const char *p = (const char*)mono_string_chars (str);
1150
1151                         swap_with_size (swapped, p, 2, mono_string_length (str));
1152                         idx = add_to_blob_cached (assembly, blob_size, b-blob_size, swapped, len);
1153                         g_free (swapped);
1154                 }
1155 #else
1156                 idx = add_to_blob_cached (assembly, blob_size, b-blob_size, (char*)mono_string_chars (str), len);
1157 #endif
1158
1159                 g_free (buf);
1160                 return idx;
1161         }
1162         default:
1163                 g_error ("we don't encode constant type 0x%02x yet", *ret_type);
1164         }
1165
1166         /* there is no signature */
1167         mono_metadata_encode_value (len, b, &b);
1168 #if G_BYTE_ORDER != G_LITTLE_ENDIAN
1169         idx = mono_image_add_stream_data (&assembly->blob, blob_size, b-blob_size);
1170         swap_with_size (blob_size, box_val, len, 1);
1171         mono_image_add_stream_data (&assembly->blob, blob_size, len);
1172 #else
1173         idx = add_to_blob_cached (assembly, blob_size, b-blob_size, box_val, len);
1174 #endif
1175
1176         g_free (buf);
1177         return idx;
1178 }
1179
1180 static guint32
1181 encode_marshal_blob (MonoDynamicAssembly *assembly, MonoReflectionMarshal *minfo) {
1182         char blob_size [64];
1183         char *b = blob_size;
1184         char *p, *buf, *str;
1185         guint32 idx, len, bufsize = 256;
1186         
1187         p = buf = g_malloc (bufsize);
1188
1189         switch (minfo->type) {
1190         case MONO_NATIVE_BYVALTSTR:
1191         case MONO_NATIVE_BYVALARRAY:
1192                 mono_metadata_encode_value (minfo->type, p, &p);
1193                 mono_metadata_encode_value (minfo->count, p, &p);
1194                 break;
1195                 /* FIXME: handle ARRAY and other unmanaged types that need extra info */
1196         case MONO_NATIVE_CUSTOM:
1197                 mono_metadata_encode_value (minfo->type, p, &p);
1198                 if (minfo->guid) {
1199                         str = mono_string_to_utf8 (minfo->guid);
1200                         len = strlen (str);
1201                         mono_metadata_encode_value (len, p, &p);
1202                         memcpy (p, str, len);
1203                         p += len;
1204                         g_free (str);
1205                 } else {
1206                         mono_metadata_encode_value (0, p, &p);
1207                 }
1208                 if (minfo->marshaltype) {
1209                         str = mono_string_to_utf8 (minfo->marshaltype);
1210                         len = strlen (str);
1211                         mono_metadata_encode_value (len, p, &p);
1212                         if (p + len >= buf + bufsize) {
1213                                 idx = p - buf;
1214                                 bufsize *= 2;
1215                                 buf = g_realloc (buf, bufsize);
1216                                 p = buf + idx;
1217                         }
1218                         memcpy (p, str, len);
1219                         p += len;
1220                         g_free (str);
1221                 } else {
1222                         mono_metadata_encode_value (0, p, &p);
1223                 }
1224                 if (minfo->marshaltyperef) {
1225                         str = type_get_qualified_name (minfo->marshaltyperef->type, &assembly->assembly);
1226                         len = strlen (str);
1227                         mono_metadata_encode_value (len, p, &p);
1228                         if (p + len >= buf + bufsize) {
1229                                 idx = p - buf;
1230                                 bufsize *= 2;
1231                                 buf = g_realloc (buf, bufsize);
1232                                 p = buf + idx;
1233                         }
1234                         memcpy (p, str, len);
1235                         p += len;
1236                         g_free (str);
1237                 } else {
1238                         mono_metadata_encode_value (0, p, &p);
1239                 }
1240                 if (minfo->mcookie) {
1241                         str = mono_string_to_utf8 (minfo->mcookie);
1242                         len = strlen (str);
1243                         mono_metadata_encode_value (len, p, &p);
1244                         if (p + len >= buf + bufsize) {
1245                                 idx = p - buf;
1246                                 bufsize *= 2;
1247                                 buf = g_realloc (buf, bufsize);
1248                                 p = buf + idx;
1249                         }
1250                         memcpy (p, str, len);
1251                         p += len;
1252                         g_free (str);
1253                 } else {
1254                         mono_metadata_encode_value (0, p, &p);
1255                 }
1256                 break;
1257         default:
1258                 mono_metadata_encode_value (minfo->type, p, &p);
1259                 break;
1260         }
1261         len = p-buf;
1262         mono_metadata_encode_value (len, b, &b);
1263         idx = add_to_blob_cached (assembly, blob_size, b-blob_size, buf, len);
1264         g_free (buf);
1265         return idx;
1266 }
1267
1268 static void
1269 mono_image_get_field_info (MonoReflectionFieldBuilder *fb, MonoDynamicAssembly *assembly)
1270 {
1271         MonoDynamicTable *table;
1272         guint32 *values;
1273         char *name;
1274
1275         /* maybe this fixup should be done in the C# code */
1276         if (fb->attrs & FIELD_ATTRIBUTE_LITERAL)
1277                 fb->attrs |= FIELD_ATTRIBUTE_HAS_DEFAULT;
1278         table = &assembly->tables [MONO_TABLE_FIELD];
1279         fb->table_idx = table->next_idx ++;
1280         mono_g_hash_table_insert (assembly->field_to_table_idx, fb->handle, GUINT_TO_POINTER (fb->table_idx));
1281         values = table->values + fb->table_idx * MONO_FIELD_SIZE;
1282         name = mono_string_to_utf8 (fb->name);
1283         values [MONO_FIELD_NAME] = string_heap_insert (&assembly->sheap, name);
1284         g_free (name);
1285         values [MONO_FIELD_FLAGS] = fb->attrs;
1286         values [MONO_FIELD_SIGNATURE] = field_encode_signature (assembly, fb);
1287
1288         if (fb->offset != -1) {
1289                 table = &assembly->tables [MONO_TABLE_FIELDLAYOUT];
1290                 table->rows ++;
1291                 alloc_table (table, table->rows);
1292                 values = table->values + table->rows * MONO_FIELD_LAYOUT_SIZE;
1293                 values [MONO_FIELD_LAYOUT_FIELD] = fb->table_idx;
1294                 values [MONO_FIELD_LAYOUT_OFFSET] = fb->offset;
1295         }
1296         if (fb->attrs & FIELD_ATTRIBUTE_LITERAL) {
1297                 guint32 field_type = 0;
1298                 table = &assembly->tables [MONO_TABLE_CONSTANT];
1299                 table->rows ++;
1300                 alloc_table (table, table->rows);
1301                 values = table->values + table->rows * MONO_CONSTANT_SIZE;
1302                 values [MONO_CONSTANT_PARENT] = HASCONSTANT_FIEDDEF | (fb->table_idx << HASCONSTANT_BITS);
1303                 values [MONO_CONSTANT_VALUE] = encode_constant (assembly, fb->def_value, &field_type);
1304                 values [MONO_CONSTANT_TYPE] = field_type;
1305                 values [MONO_CONSTANT_PADDING] = 0;
1306         }
1307         if (fb->rva_data) {
1308                 guint32 rva_idx;
1309                 table = &assembly->tables [MONO_TABLE_FIELDRVA];
1310                 table->rows ++;
1311                 alloc_table (table, table->rows);
1312                 values = table->values + table->rows * MONO_FIELD_RVA_SIZE;
1313                 values [MONO_FIELD_RVA_FIELD] = fb->table_idx;
1314                 /*
1315                  * We store it in the code section because it's simpler for now.
1316                  */
1317                 rva_idx = mono_image_add_stream_data (&assembly->code, mono_array_addr (fb->rva_data, char, 0), mono_array_length (fb->rva_data));
1318                 values [MONO_FIELD_RVA_RVA] = rva_idx + assembly->text_rva;
1319         }
1320         if (fb->marshal_info) {
1321                 table = &assembly->tables [MONO_TABLE_FIELDMARSHAL];
1322                 table->rows ++;
1323                 alloc_table (table, table->rows);
1324                 values = table->values + table->rows * MONO_FIELD_MARSHAL_SIZE;
1325                 values [MONO_FIELD_MARSHAL_PARENT] = (fb->table_idx << HAS_FIELD_MARSHAL_BITS) | HAS_FIELD_MARSHAL_FIELDSREF;
1326                 values [MONO_FIELD_MARSHAL_NATIVE_TYPE] = encode_marshal_blob (assembly, fb->marshal_info);
1327         }
1328 }
1329
1330 static guint32
1331 property_encode_signature (MonoDynamicAssembly *assembly, MonoReflectionPropertyBuilder *fb)
1332 {
1333         char *buf, *p;
1334         char blob_size [6];
1335         char *b = blob_size;
1336         guint32 nparams = 0;
1337         MonoReflectionMethodBuilder *mb = fb->get_method;
1338         MonoReflectionMethodBuilder *smb = fb->set_method;
1339         guint32 idx, i, size;
1340
1341         if (mb && mb->parameters)
1342                 nparams = mono_array_length (mb->parameters);
1343         if (!mb && smb && smb->parameters)
1344                 nparams = mono_array_length (smb->parameters) - 1;
1345         size = 24 + nparams * 10;
1346         buf = p = g_malloc (size);
1347         *p = 0x08;
1348         p++;
1349         mono_metadata_encode_value (nparams, p, &p);
1350         if (mb) {
1351                 encode_reflection_type (assembly, mb->rtype, p, &p);
1352                 for (i = 0; i < nparams; ++i) {
1353                         MonoReflectionType *pt = mono_array_get (mb->parameters, MonoReflectionType*, i);
1354                         encode_reflection_type (assembly, pt, p, &p);
1355                 }
1356         } else {
1357                 /* the property type is the last param */
1358                 encode_reflection_type (assembly, mono_array_get (smb->parameters, MonoReflectionType*, nparams), p, &p);
1359                 for (i = 0; i < nparams; ++i) {
1360                         MonoReflectionType *pt = mono_array_get (smb->parameters, MonoReflectionType*, i);
1361                         encode_reflection_type (assembly, pt, p, &p);
1362                 }
1363         }
1364         /* store length */
1365         g_assert (p - buf < size);
1366         mono_metadata_encode_value (p-buf, b, &b);
1367         idx = add_to_blob_cached (assembly, blob_size, b-blob_size, buf, p-buf);
1368         g_free (buf);
1369         return idx;
1370 }
1371
1372 static void
1373 mono_image_get_property_info (MonoReflectionPropertyBuilder *pb, MonoDynamicAssembly *assembly)
1374 {
1375         MonoDynamicTable *table;
1376         guint32 *values;
1377         char *name;
1378         guint num_methods = 0;
1379         guint32 semaidx;
1380
1381         /* 
1382          * we need to set things in the following tables:
1383          * PROPERTYMAP (info already filled in _get_type_info ())
1384          * PROPERTY    (rows already preallocated in _get_type_info ())
1385          * METHOD      (method info already done with the generic method code)
1386          * METHODSEMANTICS
1387          */
1388         table = &assembly->tables [MONO_TABLE_PROPERTY];
1389         pb->table_idx = table->next_idx ++;
1390         values = table->values + pb->table_idx * MONO_PROPERTY_SIZE;
1391         name = mono_string_to_utf8 (pb->name);
1392         values [MONO_PROPERTY_NAME] = string_heap_insert (&assembly->sheap, name);
1393         g_free (name);
1394         values [MONO_PROPERTY_FLAGS] = pb->attrs;
1395         values [MONO_PROPERTY_TYPE] = property_encode_signature (assembly, pb);
1396
1397         /* FIXME: we still don't handle 'other' methods */
1398         if (pb->get_method) num_methods ++;
1399         if (pb->set_method) num_methods ++;
1400
1401         table = &assembly->tables [MONO_TABLE_METHODSEMANTICS];
1402         table->rows += num_methods;
1403         alloc_table (table, table->rows);
1404
1405         if (pb->get_method) {
1406                 semaidx = table->next_idx ++;
1407                 values = table->values + semaidx * MONO_METHOD_SEMA_SIZE;
1408                 values [MONO_METHOD_SEMA_SEMANTICS] = METHOD_SEMANTIC_GETTER;
1409                 values [MONO_METHOD_SEMA_METHOD] = pb->get_method->table_idx;
1410                 values [MONO_METHOD_SEMA_ASSOCIATION] = (pb->table_idx << HAS_SEMANTICS_BITS) | HAS_SEMANTICS_PROPERTY;
1411         }
1412         if (pb->set_method) {
1413                 semaidx = table->next_idx ++;
1414                 values = table->values + semaidx * MONO_METHOD_SEMA_SIZE;
1415                 values [MONO_METHOD_SEMA_SEMANTICS] = METHOD_SEMANTIC_SETTER;
1416                 values [MONO_METHOD_SEMA_METHOD] = pb->set_method->table_idx;
1417                 values [MONO_METHOD_SEMA_ASSOCIATION] = (pb->table_idx << HAS_SEMANTICS_BITS) | HAS_SEMANTICS_PROPERTY;
1418         }
1419 }
1420
1421 static void
1422 mono_image_get_event_info (MonoReflectionEventBuilder *eb, MonoDynamicAssembly *assembly)
1423 {
1424         MonoDynamicTable *table;
1425         guint32 *values;
1426         char *name;
1427         guint num_methods = 0;
1428         guint32 semaidx;
1429
1430         /* 
1431          * we need to set things in the following tables:
1432          * EVENTMAP (info already filled in _get_type_info ())
1433          * EVENT    (rows already preallocated in _get_type_info ())
1434          * METHOD      (method info already done with the generic method code)
1435          * METHODSEMANTICS
1436          */
1437         table = &assembly->tables [MONO_TABLE_EVENT];
1438         eb->table_idx = table->next_idx ++;
1439         values = table->values + eb->table_idx * MONO_EVENT_SIZE;
1440         name = mono_string_to_utf8 (eb->name);
1441         values [MONO_EVENT_NAME] = string_heap_insert (&assembly->sheap, name);
1442         g_free (name);
1443         values [MONO_EVENT_FLAGS] = eb->attrs;
1444         values [MONO_EVENT_TYPE] = mono_image_typedef_or_ref (assembly, eb->type->type);
1445
1446         /*
1447          * FIXME: we still don't handle 'other' methods 
1448          */
1449         if (eb->add_method) num_methods ++;
1450         if (eb->remove_method) num_methods ++;
1451         if (eb->raise_method) num_methods ++;
1452
1453         table = &assembly->tables [MONO_TABLE_METHODSEMANTICS];
1454         table->rows += num_methods;
1455         alloc_table (table, table->rows);
1456
1457         if (eb->add_method) {
1458                 semaidx = table->next_idx ++;
1459                 values = table->values + semaidx * MONO_METHOD_SEMA_SIZE;
1460                 values [MONO_METHOD_SEMA_SEMANTICS] = METHOD_SEMANTIC_ADD_ON;
1461                 values [MONO_METHOD_SEMA_METHOD] = eb->add_method->table_idx;
1462                 values [MONO_METHOD_SEMA_ASSOCIATION] = (eb->table_idx << HAS_SEMANTICS_BITS) | HAS_SEMANTICS_EVENT;
1463         }
1464         if (eb->remove_method) {
1465                 semaidx = table->next_idx ++;
1466                 values = table->values + semaidx * MONO_METHOD_SEMA_SIZE;
1467                 values [MONO_METHOD_SEMA_SEMANTICS] = METHOD_SEMANTIC_REMOVE_ON;
1468                 values [MONO_METHOD_SEMA_METHOD] = eb->remove_method->table_idx;
1469                 values [MONO_METHOD_SEMA_ASSOCIATION] = (eb->table_idx << HAS_SEMANTICS_BITS) | HAS_SEMANTICS_EVENT;
1470         }
1471         if (eb->raise_method) {
1472                 semaidx = table->next_idx ++;
1473                 values = table->values + semaidx * MONO_METHOD_SEMA_SIZE;
1474                 values [MONO_METHOD_SEMA_SEMANTICS] = METHOD_SEMANTIC_FIRE;
1475                 values [MONO_METHOD_SEMA_METHOD] = eb->raise_method->table_idx;
1476                 values [MONO_METHOD_SEMA_ASSOCIATION] = (eb->table_idx << HAS_SEMANTICS_BITS) | HAS_SEMANTICS_EVENT;
1477         }
1478 }
1479
1480 static guint32
1481 resolution_scope_from_image (MonoDynamicAssembly *assembly, MonoImage *image)
1482 {
1483         MonoDynamicTable *table;
1484         guint32 token;
1485         guint32 *values;
1486         guint32 cols [MONO_ASSEMBLY_SIZE];
1487         const char *pubkey;
1488         guint32 publen;
1489
1490         if ((token = GPOINTER_TO_UINT (g_hash_table_lookup (assembly->handleref, image))))
1491                 return token;
1492
1493         if (image->assembly->dynamic)
1494                 /* FIXME: */
1495                 memset (cols, 0, sizeof (cols));
1496         else
1497                 mono_metadata_decode_row (&image->tables [MONO_TABLE_ASSEMBLY], 0, cols, MONO_ASSEMBLY_SIZE);
1498
1499         table = &assembly->tables [MONO_TABLE_ASSEMBLYREF];
1500         token = table->next_idx ++;
1501         table->rows ++;
1502         alloc_table (table, table->rows);
1503         values = table->values + token * MONO_ASSEMBLYREF_SIZE;
1504         if (strcmp ("corlib", image->assembly_name) == 0)
1505                 values [MONO_ASSEMBLYREF_NAME] = string_heap_insert (&assembly->sheap, "mscorlib");
1506         else
1507                 values [MONO_ASSEMBLYREF_NAME] = string_heap_insert (&assembly->sheap, image->assembly_name);
1508         values [MONO_ASSEMBLYREF_MAJOR_VERSION] = cols [MONO_ASSEMBLY_MAJOR_VERSION];
1509         values [MONO_ASSEMBLYREF_MINOR_VERSION] = cols [MONO_ASSEMBLY_MINOR_VERSION];
1510         values [MONO_ASSEMBLYREF_BUILD_NUMBER] = cols [MONO_ASSEMBLY_BUILD_NUMBER];
1511         values [MONO_ASSEMBLYREF_REV_NUMBER] = cols [MONO_ASSEMBLY_REV_NUMBER];
1512         values [MONO_ASSEMBLYREF_FLAGS] = 0;
1513         values [MONO_ASSEMBLYREF_CULTURE] = 0;
1514         values [MONO_ASSEMBLYREF_HASH_VALUE] = 0;
1515
1516         if ((pubkey = mono_image_get_public_key (image, &publen))) {
1517                 guchar pubtoken [9];
1518                 pubtoken [0] = 8;
1519                 mono_digest_get_public_token (pubtoken + 1, pubkey, publen);
1520                 values [MONO_ASSEMBLYREF_PUBLIC_KEY] = mono_image_add_stream_data (&assembly->blob, pubtoken, 9);
1521         } else {
1522                 /* 
1523                  * We add the pubtoken from ms, so that the ms runtime can handle our binaries.
1524                  * This is currently only a problem with references to System.Xml (see bug#27706),
1525                  * but there may be other cases that makes this necessary. Note, we need to set 
1526                  * the version as well. When/if we sign our assemblies, we'd need to get our pubtoken 
1527                  * recognized by ms, yuck!
1528                  * FIXME: need to add more assembly names, as needed.
1529                  */
1530                 if (strcmp (image->assembly_name, "corlib") == 0 ||
1531                                 strcmp (image->assembly_name, "mscorlib") == 0 ||
1532                                 strcmp (image->assembly_name, "System") == 0 ||
1533                                 strcmp (image->assembly_name, "System.Runtime.Remoting") == 0 ||
1534                                 strcmp (image->assembly_name, "System.Xml") == 0 ||
1535                                 strcmp (image->assembly_name, "System.Data") == 0 ||
1536                                 strcmp (image->assembly_name, "System.Windows.Forms") == 0) {
1537                         static const guchar ptoken [9] = {8, '\xB7', '\x7A', '\x5C', '\x56', '\x19', '\x34', '\xE0', '\x89'};
1538                         values [MONO_ASSEMBLYREF_PUBLIC_KEY] = mono_image_add_stream_data (&assembly->blob, ptoken, 9);
1539                         values [MONO_ASSEMBLYREF_MAJOR_VERSION] = 1;
1540                         values [MONO_ASSEMBLYREF_BUILD_NUMBER] = 3300;
1541                 } else if (strcmp (image->assembly_name, "Accessibility") == 0 ||
1542                                 strcmp (image->assembly_name, "cscompmgd") == 0 ||
1543                                 strcmp (image->assembly_name, "CustomMarshalers") == 0 ||
1544                                 strcmp (image->assembly_name, "Microsoft.JScript") == 0 ||
1545                                 strcmp (image->assembly_name, "Microsoft.VisualBasic") == 0 ||
1546                                 strcmp (image->assembly_name, "Microsoft.VisualBasic.Vsa") == 0 ||
1547                                 strcmp (image->assembly_name, "Microsoft.VisualC") == 0 ||
1548                                 strcmp (image->assembly_name, "Microsoft.Vsa") == 0 ||
1549                                 strcmp (image->assembly_name, "System.Configuration.Install") == 0 ||
1550                                 strcmp (image->assembly_name, "System.DirectoryServices") == 0 ||
1551                                 strcmp (image->assembly_name, "System.Design") == 0 ||
1552                                 strcmp (image->assembly_name, "System.Drawing") == 0 ||
1553                                 strcmp (image->assembly_name, "System.Drawing.Design") == 0 ||
1554                                 strcmp (image->assembly_name, "System.EnterpriseServices") == 0 ||
1555                                 strcmp (image->assembly_name, "System.Management") == 0 ||
1556                                 strcmp (image->assembly_name, "System.Messaging") == 0 ||
1557                                 strcmp (image->assembly_name, "System.Runtime.Serialization.Formatters.Soap") == 0 ||
1558                                 strcmp (image->assembly_name, "System.Security") == 0 ||
1559                                 strcmp (image->assembly_name, "System.ServiceProcess") == 0 ||
1560                                 strcmp (image->assembly_name, "System.Web.Services") == 0 ||
1561                                 strcmp (image->assembly_name, "CustomMarshalers") == 0 ||
1562                                 strcmp (image->assembly_name, "System.Web") == 0) {
1563                         static const guchar ptoken [9] = {8, '\xb0', '\x3f', '\x5f', '\x7f', '\x11', '\xd5', '\x0a', '\x3a'};
1564                         values [MONO_ASSEMBLYREF_PUBLIC_KEY] = mono_image_add_stream_data (&assembly->blob, ptoken, 9);
1565                         values [MONO_ASSEMBLYREF_MAJOR_VERSION] = 1;
1566                         values [MONO_ASSEMBLYREF_BUILD_NUMBER] = 3300;
1567                 } else {
1568                         values [MONO_ASSEMBLYREF_PUBLIC_KEY] = 0;
1569                 }
1570         }
1571         token <<= RESOLTION_SCOPE_BITS;
1572         token |= RESOLTION_SCOPE_ASSEMBLYREF;
1573         g_hash_table_insert (assembly->handleref, image, GUINT_TO_POINTER (token));
1574         return token;
1575 }
1576
1577 static guint32
1578 create_typespec (MonoDynamicAssembly *assembly, MonoType *type)
1579 {
1580         MonoDynamicTable *table;
1581         guint32 *values;
1582         guint32 token;
1583         char sig [128];
1584         char *p = sig;
1585         char blob_size [6];
1586         char *b = blob_size;
1587
1588         switch (type->type) {
1589         case MONO_TYPE_FNPTR:
1590         case MONO_TYPE_PTR:
1591         case MONO_TYPE_SZARRAY:
1592         case MONO_TYPE_ARRAY:
1593                 encode_type (assembly, type, p, &p);
1594                 break;
1595         case MONO_TYPE_CLASS:
1596         case MONO_TYPE_VALUETYPE: {
1597                 MonoClass *k = mono_class_from_mono_type (type);
1598                 if (!k || !k->generic_inst)
1599                         return 0;
1600                 encode_type (assembly, k->generic_inst, p, &p);
1601                 break;
1602         }
1603         default:
1604                 return 0;
1605         }
1606
1607         table = &assembly->tables [MONO_TABLE_TYPESPEC];
1608         if (assembly->save) {
1609                 g_assert (p-sig < 128);
1610                 mono_metadata_encode_value (p-sig, b, &b);
1611                 token = add_to_blob_cached (assembly, blob_size, b-blob_size, sig, p-sig);
1612                 alloc_table (table, table->rows + 1);
1613                 values = table->values + table->next_idx * MONO_TYPESPEC_SIZE;
1614                 values [MONO_TYPESPEC_SIGNATURE] = token;
1615         }
1616
1617         token = TYPEDEFORREF_TYPESPEC | (table->next_idx << TYPEDEFORREF_BITS);
1618         g_hash_table_insert (assembly->typeref, type, GUINT_TO_POINTER(token));
1619         table->next_idx ++;
1620         return token;
1621 }
1622
1623 /*
1624  * Despite the name, we handle also TypeSpec (with the above helper).
1625  */
1626 static guint32
1627 mono_image_typedef_or_ref (MonoDynamicAssembly *assembly, MonoType *type)
1628 {
1629         MonoDynamicTable *table;
1630         guint32 *values;
1631         guint32 token, scope, enclosing;
1632         MonoClass *klass;
1633
1634         token = GPOINTER_TO_UINT (g_hash_table_lookup (assembly->typeref, type));
1635         if (token)
1636                 return token;
1637         token = create_typespec (assembly, type);
1638         if (token)
1639                 return token;
1640         klass = my_mono_class_from_mono_type (type);
1641         if (!klass)
1642                 klass = mono_class_from_mono_type (type);
1643
1644         /*
1645          * If it's in the same module:
1646          */
1647         if (klass->image == assembly->assembly.image) {
1648                 MonoReflectionTypeBuilder *tb = klass->reflection_info;
1649                 token = TYPEDEFORREF_TYPEDEF | (tb->table_idx << TYPEDEFORREF_BITS);
1650                 mono_g_hash_table_insert (assembly->tokens, GUINT_TO_POINTER (token), klass->reflection_info);
1651                 return token;
1652         }
1653
1654         if (klass->nested_in) {
1655                 enclosing = mono_image_typedef_or_ref (assembly, &klass->nested_in->byval_arg);
1656                 /* get the typeref idx of the enclosing type */
1657                 enclosing >>= TYPEDEFORREF_BITS;
1658                 scope = (enclosing << RESOLTION_SCOPE_BITS) | RESOLTION_SCOPE_TYPEREF;
1659         } else {
1660                 scope = resolution_scope_from_image (assembly, klass->image);
1661         }
1662         table = &assembly->tables [MONO_TABLE_TYPEREF];
1663         if (assembly->save) {
1664                 alloc_table (table, table->rows + 1);
1665                 values = table->values + table->next_idx * MONO_TYPEREF_SIZE;
1666                 values [MONO_TYPEREF_SCOPE] = scope;
1667                 values [MONO_TYPEREF_NAME] = string_heap_insert (&assembly->sheap, klass->name);
1668                 values [MONO_TYPEREF_NAMESPACE] = string_heap_insert (&assembly->sheap, klass->name_space);
1669         }
1670         token = TYPEDEFORREF_TYPEREF | (table->next_idx << TYPEDEFORREF_BITS); /* typeref */
1671         g_hash_table_insert (assembly->typeref, type, GUINT_TO_POINTER(token));
1672         table->next_idx ++;
1673         mono_g_hash_table_insert (assembly->tokens, GUINT_TO_POINTER (token), klass->reflection_info);
1674         return token;
1675 }
1676
1677 /*
1678  * Insert a memberef row into the metadata: the token that point to the memberref
1679  * is returned. Caching is done in the caller (mono_image_get_methodref_token() or
1680  * mono_image_get_fieldref_token()).
1681  * The sig param is an index to an already built signature.
1682  */
1683 static guint32
1684 mono_image_get_memberref_token (MonoDynamicAssembly *assembly, MonoType *type, const char *name, guint32 sig)
1685 {
1686         MonoDynamicTable *table;
1687         guint32 *values;
1688         guint32 token, pclass;
1689         guint32 parent;
1690
1691         parent = mono_image_typedef_or_ref (assembly, type);
1692         switch (parent & TYPEDEFORREF_MASK) {
1693         case TYPEDEFORREF_TYPEREF:
1694                 pclass = MEMBERREF_PARENT_TYPEREF;
1695                 break;
1696         case TYPEDEFORREF_TYPESPEC:
1697                 pclass = MEMBERREF_PARENT_TYPESPEC;
1698                 break;
1699         case TYPEDEFORREF_TYPEDEF:
1700                 /* should never get here */
1701         default:
1702                 g_warning ("unknown typeref or def token 0x%08x for %s", parent, name);
1703                 return 0;
1704         }
1705         /* extract the index */
1706         parent >>= TYPEDEFORREF_BITS;
1707
1708         table = &assembly->tables [MONO_TABLE_MEMBERREF];
1709
1710         if (assembly->save) {
1711                 alloc_table (table, table->rows + 1);
1712                 values = table->values + table->next_idx * MONO_MEMBERREF_SIZE;
1713                 values [MONO_MEMBERREF_CLASS] = pclass | (parent << MEMBERREF_PARENT_BITS);
1714                 values [MONO_MEMBERREF_NAME] = string_heap_insert (&assembly->sheap, name);
1715                 values [MONO_MEMBERREF_SIGNATURE] = sig;
1716         }
1717
1718         token = MONO_TOKEN_MEMBER_REF | table->next_idx;
1719         table->next_idx ++;
1720
1721         return token;
1722 }
1723
1724 static guint32
1725 mono_image_get_methodref_token (MonoDynamicAssembly *assembly, MonoMethod *method)
1726 {
1727         guint32 token;
1728         
1729         token = GPOINTER_TO_UINT (g_hash_table_lookup (assembly->handleref, method));
1730         if (token)
1731                 return token;
1732         token = mono_image_get_memberref_token (assembly, &method->klass->byval_arg,
1733                 method->name,  method_encode_signature (assembly, method->signature));
1734         g_hash_table_insert (assembly->handleref, method, GUINT_TO_POINTER(token));
1735         return token;
1736 }
1737
1738 static guint32
1739 mono_image_get_fieldref_token (MonoDynamicAssembly *assembly, MonoClassField *field, MonoClass *klass)
1740 {
1741         guint32 token;
1742         
1743         token = GPOINTER_TO_UINT (g_hash_table_lookup (assembly->handleref, field));
1744         if (token)
1745                 return token;
1746         field->parent = klass;
1747         token = mono_image_get_memberref_token (assembly, &klass->byval_arg, 
1748                 field->name,  fieldref_encode_signature (assembly, field));
1749         g_hash_table_insert (assembly->handleref, field, GUINT_TO_POINTER(token));
1750         return token;
1751 }
1752
1753 static guint32
1754 mono_reflection_encode_sighelper (MonoDynamicAssembly *assembly, MonoReflectionSigHelper *helper)
1755 {
1756         char *buf;
1757         char *p;
1758         guint32 nargs;
1759         guint32 size;
1760         guint32 i, idx;
1761         char blob_size [6];
1762         char *b = blob_size;
1763
1764         if (!assembly->save)
1765                 return 0;
1766
1767         /* FIXME: */
1768         g_assert (helper->type == 2);
1769
1770         if (helper->arguments)
1771                 nargs = mono_array_length (helper->arguments);
1772         else
1773                 nargs = 0;
1774
1775         size = 10 + (nargs * 10);
1776         
1777         p = buf = g_malloc (size);
1778
1779         /* Encode calling convention */
1780         /* Change Any to Standard */
1781         if ((helper->call_conv & 0x03) == 0x03)
1782                 helper->call_conv = 0x01;
1783         /* explicit_this implies has_this */
1784         if (helper->call_conv & 0x40)
1785                 helper->call_conv &= 0x20;
1786
1787         if (helper->call_conv == 0) /* Unmanaged */
1788                 *p = helper->unmanaged_call_conv - 1;
1789         else {
1790                 /* Managed */
1791                 *p = helper->call_conv & 0x60; /* has_this + explicit_this */
1792                 if (helper->call_conv & 0x02) /* varargs */
1793                         *p += 0x05;
1794         }
1795
1796         p++;
1797         mono_metadata_encode_value (nargs, p, &p);
1798         encode_reflection_type (assembly, helper->return_type, p, &p);
1799         for (i = 0; i < nargs; ++i) {
1800                 MonoReflectionType *pt = mono_array_get (helper->arguments, MonoReflectionType*, i);
1801                 encode_reflection_type (assembly, pt, p, &p);
1802         }
1803         /* store length */
1804         g_assert (p - buf < size);
1805         mono_metadata_encode_value (p-buf, b, &b);
1806         idx = add_to_blob_cached (assembly, blob_size, b-blob_size, buf, p-buf);
1807         g_free (buf);
1808
1809         return idx;
1810 }
1811         
1812 static guint32 
1813 mono_image_get_sighelper_token (MonoDynamicAssembly *assembly, MonoReflectionSigHelper *helper)
1814 {
1815         guint32 idx;
1816         MonoDynamicTable *table;
1817         guint32 *values;
1818
1819         table = &assembly->tables [MONO_TABLE_STANDALONESIG];
1820         idx = table->next_idx ++;
1821         table->rows ++;
1822         alloc_table (table, table->rows);
1823         values = table->values + idx * MONO_STAND_ALONE_SIGNATURE_SIZE;
1824
1825         values [MONO_STAND_ALONE_SIGNATURE] =
1826                 mono_reflection_encode_sighelper (assembly, helper);
1827
1828         return idx;
1829 }
1830
1831 static int
1832 reflection_cc_to_file (int call_conv) {
1833         switch (call_conv & 0x3) {
1834         case 0:
1835         case 1: return MONO_CALL_DEFAULT;
1836         case 2: return MONO_CALL_VARARG;
1837         default:
1838                 g_assert_not_reached ();
1839         }
1840         return 0;
1841 }
1842
1843 typedef struct {
1844         MonoType *parent;
1845         MonoMethodSignature *sig;
1846         char *name;
1847         guint32 token;
1848 } ArrayMethod;
1849
1850 static guint32
1851 mono_image_get_array_token (MonoDynamicAssembly *assembly, MonoReflectionArrayMethod *m)
1852 {
1853         guint32 nparams, i;
1854         GList *tmp;
1855         char *name;
1856         MonoMethodSignature *sig;
1857         ArrayMethod *am;
1858         
1859         name = mono_string_to_utf8 (m->name);
1860         nparams = mono_array_length (m->parameters);
1861         sig = g_malloc0 (sizeof (MonoMethodSignature) + sizeof (MonoType*) * nparams);
1862         sig->hasthis = 1;
1863         sig->call_convention = reflection_cc_to_file (m->call_conv);
1864         sig->param_count = nparams;
1865         sig->ret = m->ret? m->ret->type: &mono_defaults.void_class->byval_arg;
1866         for (i = 0; i < nparams; ++i) {
1867                 MonoReflectionType *t = mono_array_get (m->parameters, gpointer, i);
1868                 sig->params [i] = t->type;
1869         }
1870
1871         for (tmp = assembly->array_methods; tmp; tmp = tmp->next) {
1872                 am = tmp->data;
1873                 if (strcmp (name, am->name) == 0 && 
1874                                 mono_metadata_type_equal (am->parent, m->parent->type) &&
1875                                 mono_metadata_signature_equal (am->sig, sig)) {
1876                         g_free (name);
1877                         g_free (sig);
1878                         m->table_idx = am->token & 0xffffff;
1879                         return am->token;
1880                 }
1881         }
1882         am = g_new0 (ArrayMethod, 1);
1883         am->name = name;
1884         am->sig = sig;
1885         am->parent = m->parent->type;
1886         am->token = mono_image_get_memberref_token (assembly, am->parent,
1887                         name,  method_encode_signature (assembly, sig));
1888         assembly->array_methods = g_list_prepend (assembly->array_methods, am);
1889         m->table_idx = am->token & 0xffffff;
1890         return am->token;
1891 }
1892
1893 /*
1894  * Insert into the metadata tables all the info about the TypeBuilder tb.
1895  * Data in the tables is inserted in a predefined order, since some tables need to be sorted.
1896  */
1897 static void
1898 mono_image_get_type_info (MonoDomain *domain, MonoReflectionTypeBuilder *tb, MonoDynamicAssembly *assembly)
1899 {
1900         MonoDynamicTable *table;
1901         guint *values;
1902         int i, is_object = 0, is_system = 0;
1903         char *n;
1904
1905         table = &assembly->tables [MONO_TABLE_TYPEDEF];
1906         values = table->values + tb->table_idx * MONO_TYPEDEF_SIZE;
1907         values [MONO_TYPEDEF_FLAGS] = tb->attrs;
1908         n = mono_string_to_utf8 (tb->name);
1909         if (strcmp (n, "Object") == 0)
1910                 is_object++;
1911         values [MONO_TYPEDEF_NAME] = string_heap_insert (&assembly->sheap, n);
1912         g_free (n);
1913         n = mono_string_to_utf8 (tb->nspace);
1914         if (strcmp (n, "System") == 0)
1915                 is_system++;
1916         values [MONO_TYPEDEF_NAMESPACE] = string_heap_insert (&assembly->sheap, n);
1917         g_free (n);
1918         if (tb->parent && !(is_system && is_object) && 
1919                 !(tb->attrs & TYPE_ATTRIBUTE_INTERFACE)) { /* interfaces don't have a parent */
1920                 values [MONO_TYPEDEF_EXTENDS] = mono_image_typedef_or_ref (assembly, tb->parent->type);
1921         } else
1922                 values [MONO_TYPEDEF_EXTENDS] = 0;
1923         values [MONO_TYPEDEF_FIELD_LIST] = assembly->tables [MONO_TABLE_FIELD].next_idx;
1924         values [MONO_TYPEDEF_METHOD_LIST] = assembly->tables [MONO_TABLE_METHOD].next_idx;
1925
1926         /*
1927          * if we have explicitlayout or sequentiallayouts, output data in the
1928          * ClassLayout table.
1929          */
1930         if (((tb->attrs & TYPE_ATTRIBUTE_LAYOUT_MASK) != TYPE_ATTRIBUTE_AUTO_LAYOUT) && (tb->class_size != -1)) {
1931                 table = &assembly->tables [MONO_TABLE_CLASSLAYOUT];
1932                 table->rows++;
1933                 alloc_table (table, table->rows);
1934                 values = table->values + table->rows * MONO_CLASS_LAYOUT_SIZE;
1935                 values [MONO_CLASS_LAYOUT_PARENT] = tb->table_idx;
1936                 values [MONO_CLASS_LAYOUT_CLASS_SIZE] = tb->class_size;
1937                 values [MONO_CLASS_LAYOUT_PACKING_SIZE] = tb->packing_size;
1938         }
1939
1940         /* handle interfaces */
1941         if (tb->interfaces) {
1942                 table = &assembly->tables [MONO_TABLE_INTERFACEIMPL];
1943                 i = table->rows;
1944                 table->rows += mono_array_length (tb->interfaces);
1945                 alloc_table (table, table->rows);
1946                 values = table->values + (i + 1) * MONO_INTERFACEIMPL_SIZE;
1947                 for (i = 0; i < mono_array_length (tb->interfaces); ++i) {
1948                         MonoReflectionType* iface = (MonoReflectionType*) mono_array_get (tb->interfaces, gpointer, i);
1949                         values [MONO_INTERFACEIMPL_CLASS] = tb->table_idx;
1950                         values [MONO_INTERFACEIMPL_INTERFACE] = mono_image_typedef_or_ref (assembly, iface->type);
1951                         values += MONO_INTERFACEIMPL_SIZE;
1952                 }
1953         }
1954
1955         /* handle fields */
1956         if (tb->fields) {
1957                 table = &assembly->tables [MONO_TABLE_FIELD];
1958                 table->rows += mono_array_length (tb->fields);
1959                 alloc_table (table, table->rows);
1960                 for (i = 0; i < mono_array_length (tb->fields); ++i)
1961                         mono_image_get_field_info (
1962                                 mono_array_get (tb->fields, MonoReflectionFieldBuilder*, i), assembly);
1963         }
1964
1965         /* handle constructors */
1966         if (tb->ctors) {
1967                 table = &assembly->tables [MONO_TABLE_METHOD];
1968                 table->rows += mono_array_length (tb->ctors);
1969                 alloc_table (table, table->rows);
1970                 for (i = 0; i < mono_array_length (tb->ctors); ++i)
1971                         mono_image_get_ctor_info (domain,
1972                                 mono_array_get (tb->ctors, MonoReflectionCtorBuilder*, i), assembly);
1973         }
1974
1975         /* handle methods */
1976         if (tb->methods) {
1977                 table = &assembly->tables [MONO_TABLE_METHOD];
1978                 table->rows += mono_array_length (tb->methods);
1979                 alloc_table (table, table->rows);
1980                 for (i = 0; i < mono_array_length (tb->methods); ++i)
1981                         mono_image_get_method_info (
1982                                 mono_array_get (tb->methods, MonoReflectionMethodBuilder*, i), assembly);
1983         }
1984
1985         /* Do the same with properties etc.. */
1986         if (tb->events && mono_array_length (tb->events)) {
1987                 table = &assembly->tables [MONO_TABLE_EVENT];
1988                 table->rows += mono_array_length (tb->events);
1989                 alloc_table (table, table->rows);
1990                 table = &assembly->tables [MONO_TABLE_EVENTMAP];
1991                 table->rows ++;
1992                 alloc_table (table, table->rows);
1993                 values = table->values + table->rows * MONO_EVENT_MAP_SIZE;
1994                 values [MONO_EVENT_MAP_PARENT] = tb->table_idx;
1995                 values [MONO_EVENT_MAP_EVENTLIST] = assembly->tables [MONO_TABLE_EVENT].next_idx;
1996                 for (i = 0; i < mono_array_length (tb->events); ++i)
1997                         mono_image_get_event_info (
1998                                 mono_array_get (tb->events, MonoReflectionEventBuilder*, i), assembly);
1999         }
2000         if (tb->properties && mono_array_length (tb->properties)) {
2001                 table = &assembly->tables [MONO_TABLE_PROPERTY];
2002                 table->rows += mono_array_length (tb->properties);
2003                 alloc_table (table, table->rows);
2004                 table = &assembly->tables [MONO_TABLE_PROPERTYMAP];
2005                 table->rows ++;
2006                 alloc_table (table, table->rows);
2007                 values = table->values + table->rows * MONO_PROPERTY_MAP_SIZE;
2008                 values [MONO_PROPERTY_MAP_PARENT] = tb->table_idx;
2009                 values [MONO_PROPERTY_MAP_PROPERTY_LIST] = assembly->tables [MONO_TABLE_PROPERTY].next_idx;
2010                 for (i = 0; i < mono_array_length (tb->properties); ++i)
2011                         mono_image_get_property_info (
2012                                 mono_array_get (tb->properties, MonoReflectionPropertyBuilder*, i), assembly);
2013         }
2014         if (tb->subtypes) {
2015                 MonoDynamicTable *ntable;
2016                 
2017                 ntable = &assembly->tables [MONO_TABLE_NESTEDCLASS];
2018                 ntable->rows += mono_array_length (tb->subtypes);
2019                 alloc_table (ntable, ntable->rows);
2020                 values = ntable->values + ntable->next_idx * MONO_NESTED_CLASS_SIZE;
2021
2022                 for (i = 0; i < mono_array_length (tb->subtypes); ++i) {
2023                         MonoReflectionTypeBuilder *subtype = mono_array_get (tb->subtypes, MonoReflectionTypeBuilder*, i);
2024
2025                         values [MONO_NESTED_CLASS_NESTED] = subtype->table_idx;
2026                         values [MONO_NESTED_CLASS_ENCLOSING] = tb->table_idx;
2027                         /*g_print ("nesting %s (%d) in %s (%d) (rows %d/%d)\n",
2028                                 mono_string_to_utf8 (subtype->name), subtype->table_idx,
2029                                 mono_string_to_utf8 (tb->name), tb->table_idx,
2030                                 ntable->next_idx, ntable->rows);*/
2031                         values += MONO_NESTED_CLASS_SIZE;
2032                         ntable->next_idx++;
2033                 }
2034         }
2035 }
2036
2037 static void
2038 collect_types (GPtrArray *types, MonoReflectionTypeBuilder *type)
2039 {
2040         int i;
2041
2042         g_ptr_array_add (types, type);
2043
2044         if (!type->subtypes)
2045                 return;
2046
2047         for (i = 0; i < mono_array_length (type->subtypes); ++i) {
2048                 MonoReflectionTypeBuilder *subtype = mono_array_get (type->subtypes, MonoReflectionTypeBuilder*, i);
2049                 collect_types (types, subtype);
2050         }
2051 }
2052
2053 static gint
2054 compare_types_by_table_idx (MonoReflectionTypeBuilder **type1, 
2055                                                         MonoReflectionTypeBuilder **type2)
2056 {
2057         if ((*type1)->table_idx < (*type2)->table_idx)
2058                 return -1;
2059         else
2060                 if ((*type1)->table_idx > (*type2)->table_idx)
2061                         return 1;
2062         else
2063                 return 0;
2064 }
2065
2066 static void
2067 params_add_cattrs (MonoDynamicAssembly *assembly, MonoArray *pinfo) {
2068         int i;
2069
2070         if (!pinfo)
2071                 return;
2072         for (i = 0; i < mono_array_length (pinfo); ++i) {
2073                 MonoReflectionParamBuilder *pb;
2074                 pb = mono_array_get (pinfo, MonoReflectionParamBuilder *, i);
2075                 if (!pb)
2076                         continue;
2077                 mono_image_add_cattrs (assembly, pb->table_idx, CUSTOM_ATTR_PARAMDEF, pb->cattrs);
2078         }
2079 }
2080
2081 static void
2082 type_add_cattrs (MonoDynamicAssembly *assembly, MonoReflectionTypeBuilder *tb) {
2083         int i;
2084         
2085         mono_image_add_cattrs (assembly, tb->table_idx, CUSTOM_ATTR_TYPEDEF, tb->cattrs);
2086         if (tb->fields) {
2087                 for (i = 0; i < mono_array_length (tb->fields); ++i) {
2088                         MonoReflectionFieldBuilder* fb;
2089                         fb = mono_array_get (tb->fields, MonoReflectionFieldBuilder*, i);
2090                         mono_image_add_cattrs (assembly, fb->table_idx, CUSTOM_ATTR_FIELDDEF, fb->cattrs);
2091                 }
2092         }
2093         if (tb->events) {
2094                 for (i = 0; i < mono_array_length (tb->events); ++i) {
2095                         MonoReflectionEventBuilder* eb;
2096                         eb = mono_array_get (tb->events, MonoReflectionEventBuilder*, i);
2097                         mono_image_add_cattrs (assembly, eb->table_idx, CUSTOM_ATTR_EVENT, eb->cattrs);
2098                 }
2099         }
2100         if (tb->properties) {
2101                 for (i = 0; i < mono_array_length (tb->properties); ++i) {
2102                         MonoReflectionPropertyBuilder* pb;
2103                         pb = mono_array_get (tb->properties, MonoReflectionPropertyBuilder*, i);
2104                         mono_image_add_cattrs (assembly, pb->table_idx, CUSTOM_ATTR_PROPERTY, pb->cattrs);
2105                 }
2106         }
2107         if (tb->ctors) {
2108                 for (i = 0; i < mono_array_length (tb->ctors); ++i) {
2109                         MonoReflectionCtorBuilder* cb;
2110                         cb = mono_array_get (tb->ctors, MonoReflectionCtorBuilder*, i);
2111                         mono_image_add_cattrs (assembly, cb->table_idx, CUSTOM_ATTR_METHODDEF, cb->cattrs);
2112                         params_add_cattrs (assembly, cb->pinfo);
2113                 }
2114         }
2115
2116         if (tb->methods) {
2117                 for (i = 0; i < mono_array_length (tb->methods); ++i) {
2118                         MonoReflectionMethodBuilder* mb;
2119                         mb = mono_array_get (tb->methods, MonoReflectionMethodBuilder*, i);
2120                         mono_image_add_cattrs (assembly, mb->table_idx, CUSTOM_ATTR_METHODDEF, mb->cattrs);
2121                         params_add_cattrs (assembly, mb->pinfo);
2122                 }
2123         }
2124
2125         if (tb->subtypes) {
2126                 for (i = 0; i < mono_array_length (tb->subtypes); ++i)
2127                         type_add_cattrs (assembly, mono_array_get (tb->subtypes, MonoReflectionTypeBuilder*, i));
2128         }
2129 }
2130
2131 static void
2132 module_add_cattrs (MonoDynamicAssembly *assembly, MonoReflectionModuleBuilder *mb) {
2133         int i;
2134         
2135         mono_image_add_cattrs (assembly, mb->table_idx, CUSTOM_ATTR_MODULE, mb->cattrs);
2136         
2137         /* no types in the module */
2138         if (!mb->types)
2139                 return;
2140         
2141         for (i = 0; i < mono_array_length (mb->types); ++i)
2142                 type_add_cattrs (assembly, mono_array_get (mb->types, MonoReflectionTypeBuilder*, i));
2143 }
2144
2145 static void
2146 mono_image_fill_module_table (MonoDomain *domain, MonoReflectionModuleBuilder *mb, MonoDynamicAssembly *assembly)
2147 {
2148         MonoDynamicTable *table;
2149         int i;
2150         char *name;
2151
2152         table = &assembly->tables [MONO_TABLE_MODULE];
2153         mb->table_idx = table->next_idx ++;
2154         name = mono_string_to_utf8 (mb->module.name);
2155         table->values [mb->table_idx * MONO_MODULE_SIZE + MONO_MODULE_NAME] = string_heap_insert (&assembly->sheap, name);
2156         g_free (name);
2157         i = mono_image_add_stream_data (&assembly->guid, mono_array_addr (mb->guid, char, 0), 16);
2158         i /= 16;
2159         ++i;
2160         table->values [mb->table_idx * MONO_MODULE_SIZE + MONO_MODULE_MVID] = i;
2161         table->values [mb->table_idx * MONO_MODULE_SIZE + MONO_MODULE_ENC] = 0;
2162         table->values [mb->table_idx * MONO_MODULE_SIZE + MONO_MODULE_ENCBASE] = 0;
2163 }
2164
2165 #define align_pointer(base,p)\
2166         do {\
2167                 guint32 __diff = (unsigned char*)(p)-(unsigned char*)(base);\
2168                 if (__diff & 3)\
2169                         (p) += 4 - (__diff & 3);\
2170         } while (0)
2171
2172 static int
2173 compare_semantics (const void *a, const void *b)
2174 {
2175         const guint32 *a_values = a;
2176         const guint32 *b_values = b;
2177         int assoc = a_values [MONO_METHOD_SEMA_ASSOCIATION] - b_values [MONO_METHOD_SEMA_ASSOCIATION];
2178         if (assoc)
2179                 return assoc;
2180         return a_values [MONO_METHOD_SEMA_SEMANTICS] - b_values [MONO_METHOD_SEMA_SEMANTICS];
2181 }
2182
2183 static int
2184 compare_custom_attrs (const void *a, const void *b)
2185 {
2186         const guint32 *a_values = a;
2187         const guint32 *b_values = b;
2188
2189         return a_values [MONO_CUSTOM_ATTR_PARENT] - b_values [MONO_CUSTOM_ATTR_PARENT];
2190 }
2191
2192 static int
2193 compare_field_marshal (const void *a, const void *b)
2194 {
2195         const guint32 *a_values = a;
2196         const guint32 *b_values = b;
2197
2198         return a_values [MONO_FIELD_MARSHAL_PARENT] - b_values [MONO_FIELD_MARSHAL_PARENT];
2199 }
2200
2201 static int
2202 compare_nested (const void *a, const void *b)
2203 {
2204         const guint32 *a_values = a;
2205         const guint32 *b_values = b;
2206
2207         return a_values [MONO_NESTED_CLASS_NESTED] - b_values [MONO_NESTED_CLASS_NESTED];
2208 }
2209
2210 /*
2211  * build_compressed_metadata() fills in the blob of data that represents the 
2212  * raw metadata as it will be saved in the PE file. The five streams are output 
2213  * and the metadata tables are comnpressed from the guint32 array representation, 
2214  * to the compressed on-disk format.
2215  */
2216 static void
2217 build_compressed_metadata (MonoDynamicAssembly *assembly)
2218 {
2219         MonoDynamicTable *table;
2220         int i;
2221         guint64 valid_mask = 0;
2222         guint64 sorted_mask;
2223         guint32 heapt_size = 0;
2224         guint32 meta_size = 256; /* allow for header and other stuff */
2225         guint32 table_offset;
2226         guint32 ntables = 0;
2227         guint64 *int64val;
2228         guint32 *int32val;
2229         guint16 *int16val;
2230         MonoImage *meta;
2231         unsigned char *p;
2232
2233         struct StreamDesc {
2234                 const char *name;
2235                 MonoDynamicStream *stream;
2236         } stream_desc [5];
2237
2238         stream_desc[0].name  = "#~"; stream_desc[0].stream = &assembly->tstream;
2239         stream_desc[1].name  = "#Strings"; stream_desc[1].stream = &assembly->sheap;
2240         stream_desc[2].name  = "#US"; stream_desc[2].stream = &assembly->us;
2241         stream_desc[3].name  = "#Blob"; stream_desc[3].stream = &assembly->blob;
2242         stream_desc[4].name  = "#GUID"; stream_desc[4].stream = &assembly->guid;
2243         
2244         /* tables that are sorted */
2245         sorted_mask = ((guint64)1 << MONO_TABLE_CONSTANT) | ((guint64)1 << MONO_TABLE_FIELDMARSHAL)
2246                 | ((guint64)1 << MONO_TABLE_METHODSEMANTICS) | ((guint64)1 << MONO_TABLE_CLASSLAYOUT)
2247                 | ((guint64)1 << MONO_TABLE_FIELDLAYOUT) | ((guint64)1 << MONO_TABLE_FIELDRVA)
2248                 | ((guint64)1 << MONO_TABLE_IMPLMAP) | ((guint64)1 << MONO_TABLE_NESTEDCLASS)
2249                 | ((guint64)1 << MONO_TABLE_METHODIMPL) | ((guint64)1 << MONO_TABLE_CUSTOMATTRIBUTE)
2250                 | ((guint64)1 << MONO_TABLE_DECLSECURITY);
2251         
2252         /* Compute table sizes */
2253         /* the MonoImage has already been created in mono_image_basic_init() */
2254         meta = assembly->assembly.image;
2255         
2256         /* Setup the info used by compute_sizes () */
2257         meta->idx_blob_wide = assembly->blob.index >= 65536 ? 1 : 0;
2258         meta->idx_guid_wide = assembly->guid.index >= 65536 ? 1 : 0;
2259         meta->idx_string_wide = assembly->sheap.index >= 65536 ? 1 : 0;
2260
2261         meta_size += assembly->blob.index;
2262         meta_size += assembly->guid.index;
2263         meta_size += assembly->sheap.index;
2264         meta_size += assembly->us.index;
2265
2266         for (i=0; i < 64; ++i)
2267                 meta->tables [i].rows = assembly->tables [i].rows;
2268         
2269         for (i = 0; i < 64; i++){
2270                 if (meta->tables [i].rows == 0)
2271                         continue;
2272                 valid_mask |= (guint64)1 << i;
2273                 ntables ++;
2274                 meta->tables [i].row_size = mono_metadata_compute_size (
2275                         meta, i, &meta->tables [i].size_bitfield);
2276                 heapt_size += meta->tables [i].row_size * meta->tables [i].rows;
2277         }
2278         heapt_size += 24; /* #~ header size */
2279         heapt_size += ntables * 4;
2280         meta_size += heapt_size;
2281         meta->raw_metadata = g_malloc0 (meta_size);
2282         p = meta->raw_metadata;
2283         /* the metadata signature */
2284         *p++ = 'B'; *p++ = 'S'; *p++ = 'J'; *p++ = 'B';
2285         /* version numbers and 4 bytes reserved */
2286         int16val = (guint16*)p;
2287         *int16val++ = GUINT16_TO_LE (1);
2288         *int16val = GUINT16_TO_LE (1);
2289         p += 8;
2290         /* version string */
2291         int32val = (guint32*)p;
2292         *int32val = GUINT32_TO_LE ((strlen (meta->version) + 3) & (~3)); /* needs to be multiple of 4 */
2293         p += 4;
2294         memcpy (p, meta->version, GUINT32_FROM_LE (*int32val));
2295         p += GUINT32_FROM_LE (*int32val);
2296         align_pointer (meta->raw_metadata, p);
2297         int16val = (guint16*)p;
2298         *int16val++ = GUINT16_TO_LE (0); /* flags must be 0 */
2299         *int16val = GUINT16_TO_LE (5); /* number of streams */
2300         p += 4;
2301
2302         /*
2303          * write the stream info.
2304          */
2305         table_offset = (p - (unsigned char*)meta->raw_metadata) + 5 * 8 + 40; /* room needed for stream headers */
2306         table_offset += 3; table_offset &= ~3;
2307
2308         assembly->tstream.index = heapt_size;
2309         for (i = 0; i < 5; ++i) {
2310                 int32val = (guint32*)p;
2311                 stream_desc [i].stream->offset = table_offset;
2312                 *int32val++ = GUINT32_TO_LE (table_offset);
2313                 *int32val = GUINT32_TO_LE (stream_desc [i].stream->index);
2314                 table_offset += GUINT32_FROM_LE (*int32val);
2315                 table_offset += 3; table_offset &= ~3;
2316                 p += 8;
2317                 strcpy (p, stream_desc [i].name);
2318                 p += strlen (stream_desc [i].name) + 1;
2319                 align_pointer (meta->raw_metadata, p);
2320         }
2321         /* 
2322          * now copy the data, the table stream header and contents goes first.
2323          */
2324         g_assert ((p - (unsigned char*)meta->raw_metadata) < assembly->tstream.offset);
2325         p = meta->raw_metadata + assembly->tstream.offset;
2326         int32val = (guint32*)p;
2327         *int32val = GUINT32_TO_LE (0); /* reserved */
2328         p += 4;
2329         *p++ = 1; /* version */
2330         *p++ = 0;
2331         if (meta->idx_string_wide)
2332                 *p |= 0x01;
2333         if (meta->idx_guid_wide)
2334                 *p |= 0x02;
2335         if (meta->idx_blob_wide)
2336                 *p |= 0x04;
2337         ++p;
2338         *p++ = 0; /* reserved */
2339         int64val = (guint64*)p;
2340         *int64val++ = GUINT64_TO_LE (valid_mask);
2341         *int64val++ = GUINT64_TO_LE (valid_mask & sorted_mask); /* bitvector of sorted tables  */
2342         p += 16;
2343         int32val = (guint32*)p;
2344         for (i = 0; i < 64; i++){
2345                 if (meta->tables [i].rows == 0)
2346                         continue;
2347                 *int32val++ = GUINT32_TO_LE (meta->tables [i].rows);
2348         }
2349         p = (unsigned char*)int32val;
2350
2351         /* sort the tables that still need sorting */
2352         table = &assembly->tables [MONO_TABLE_METHODSEMANTICS];
2353         if (table->rows)
2354                 qsort (table->values + MONO_METHOD_SEMA_SIZE, table->rows, sizeof (guint32) * MONO_METHOD_SEMA_SIZE, compare_semantics);
2355         table = &assembly->tables [MONO_TABLE_CUSTOMATTRIBUTE];
2356         if (table->rows)
2357                 qsort (table->values + MONO_CUSTOM_ATTR_SIZE, table->rows, sizeof (guint32) * MONO_CUSTOM_ATTR_SIZE, compare_custom_attrs);
2358         table = &assembly->tables [MONO_TABLE_FIELDMARSHAL];
2359         if (table->rows)
2360                 qsort (table->values + MONO_FIELD_MARSHAL_SIZE, table->rows, sizeof (guint32) * MONO_FIELD_MARSHAL_SIZE, compare_field_marshal);
2361         table = &assembly->tables [MONO_TABLE_NESTEDCLASS];
2362         if (table->rows)
2363                 qsort (table->values + MONO_NESTED_CLASS_SIZE, table->rows, sizeof (guint32) * MONO_NESTED_CLASS_SIZE, compare_nested);
2364
2365         /* compress the tables */
2366         for (i = 0; i < 64; i++){
2367                 int row, col;
2368                 guint32 *values;
2369                 guint32 bitfield = meta->tables [i].size_bitfield;
2370                 if (!meta->tables [i].rows)
2371                         continue;
2372                 if (assembly->tables [i].columns != mono_metadata_table_count (bitfield))
2373                         g_error ("col count mismatch in %d: %d %d", i, assembly->tables [i].columns, mono_metadata_table_count (bitfield));
2374                 meta->tables [i].base = p;
2375                 for (row = 1; row <= meta->tables [i].rows; ++row) {
2376                         values = assembly->tables [i].values + row * assembly->tables [i].columns;
2377                         for (col = 0; col < assembly->tables [i].columns; ++col) {
2378                                 switch (mono_metadata_table_size (bitfield, col)) {
2379                                 case 1:
2380                                         *p++ = values [col];
2381                                         break;
2382                                 case 2:
2383                                         *p++ = values [col] & 0xff;
2384                                         *p++ = (values [col] >> 8) & 0xff;
2385                                         break;
2386                                 case 4:
2387                                         *p++ = values [col] & 0xff;
2388                                         *p++ = (values [col] >> 8) & 0xff;
2389                                         *p++ = (values [col] >> 16) & 0xff;
2390                                         *p++ = (values [col] >> 24) & 0xff;
2391                                         break;
2392                                 default:
2393                                         g_assert_not_reached ();
2394                                 }
2395                         }
2396                 }
2397                 g_assert ((p - (const unsigned char*)meta->tables [i].base) == (meta->tables [i].rows * meta->tables [i].row_size));
2398         }
2399         
2400         g_assert (assembly->guid.offset + assembly->guid.index < meta_size);
2401         memcpy (meta->raw_metadata + assembly->sheap.offset, assembly->sheap.data, assembly->sheap.index);
2402         memcpy (meta->raw_metadata + assembly->us.offset, assembly->us.data, assembly->us.index);
2403         memcpy (meta->raw_metadata + assembly->blob.offset, assembly->blob.data, assembly->blob.index);
2404         memcpy (meta->raw_metadata + assembly->guid.offset, assembly->guid.data, assembly->guid.index);
2405
2406         assembly->meta_size = assembly->guid.offset + assembly->guid.index;
2407 }
2408
2409 /*
2410  * Some tables in metadata need to be sorted according to some criteria, but
2411  * when methods and fields are first created with reflection, they may be assigned a token
2412  * that doesn't correspond to the final token they will get assigned after the sorting.
2413  * ILGenerator.cs keeps a fixup table that maps the position of tokens in the IL code stream
2414  * with the reflection objects that represent them. Once all the tables are set up, the 
2415  * reflection objects will contains the correct table index. fixup_method() will fixup the
2416  * tokens for the method with ILGenerator @ilgen.
2417  */
2418 static void
2419 fixup_method (MonoReflectionILGen *ilgen, gpointer value, MonoDynamicAssembly *assembly) {
2420         guint32 code_idx = GPOINTER_TO_UINT (value);
2421         MonoReflectionILTokenInfo *iltoken;
2422         MonoReflectionFieldBuilder *field;
2423         MonoReflectionCtorBuilder *ctor;
2424         MonoReflectionMethodBuilder *method;
2425         MonoReflectionTypeBuilder *tb;
2426         MonoReflectionArrayMethod *am;
2427         guint32 i, idx;
2428         unsigned char *target;
2429
2430         for (i = 0; i < ilgen->num_token_fixups; ++i) {
2431                 iltoken = (MonoReflectionILTokenInfo *)mono_array_addr_with_size (ilgen->token_fixups, sizeof (MonoReflectionILTokenInfo), i);
2432                 target = assembly->code.data + code_idx + iltoken->code_pos;
2433                 switch (target [3]) {
2434                 case MONO_TABLE_FIELD:
2435                         if (!strcmp (iltoken->member->vtable->klass->name, "FieldBuilder")) {
2436                                 field = (MonoReflectionFieldBuilder *)iltoken->member;
2437                                 idx = field->table_idx;
2438                         } else if (!strcmp (iltoken->member->vtable->klass->name, "MonoField")) {
2439                                 MonoClassField *f = ((MonoReflectionField*)iltoken->member)->field;
2440                                 idx = GPOINTER_TO_UINT (mono_g_hash_table_lookup (assembly->field_to_table_idx, f));
2441                         } else {
2442                                 g_assert_not_reached ();
2443                         }
2444                         break;
2445                 case MONO_TABLE_METHOD:
2446                         if (!strcmp (iltoken->member->vtable->klass->name, "MethodBuilder")) {
2447                                 method = (MonoReflectionMethodBuilder *)iltoken->member;
2448                                 idx = method->table_idx;
2449                         } else if (!strcmp (iltoken->member->vtable->klass->name, "ConstructorBuilder")) {
2450                                 ctor = (MonoReflectionCtorBuilder *)iltoken->member;
2451                                 idx = ctor->table_idx;
2452                         } else if (!strcmp (iltoken->member->vtable->klass->name, "MonoMethod")) {
2453                                 MonoMethod *m = ((MonoReflectionMethod*)iltoken->member)->method;
2454                                 idx = GPOINTER_TO_UINT (mono_g_hash_table_lookup (assembly->method_to_table_idx, m));
2455                         } else {
2456                                 g_assert_not_reached ();
2457                         }
2458                         break;
2459                 case MONO_TABLE_TYPEDEF:
2460                         if (strcmp (iltoken->member->vtable->klass->name, "TypeBuilder"))
2461                                 g_assert_not_reached ();
2462                         tb = (MonoReflectionTypeBuilder *)iltoken->member;
2463                         idx = tb->table_idx;
2464                         break;
2465                 case MONO_TABLE_MEMBERREF:
2466                         if (strcmp (iltoken->member->vtable->klass->name, "MonoArrayMethod"))
2467                                 g_assert_not_reached ();
2468                         am = (MonoReflectionArrayMethod*)iltoken->member;
2469                         idx = am->table_idx;
2470                         break;
2471                 default:
2472                         g_error ("got unexpected table 0x%02x in fixup", target [3]);
2473                 }
2474                 target [0] = idx & 0xff;
2475                 target [1] = (idx >> 8) & 0xff;
2476                 target [2] = (idx >> 16) & 0xff;
2477         }
2478 }
2479
2480 static void
2481 assembly_add_resource (MonoDynamicAssembly *assembly, MonoReflectionResource *rsrc)
2482 {
2483         MonoDynamicTable *table;
2484         guint32 *values;
2485         char blob_size [6];
2486         guchar hash [20];
2487         char *b = blob_size;
2488         char *name, *sname;
2489         guint32 idx, offset;
2490
2491         if (rsrc->filename) {
2492                 name = mono_string_to_utf8 (rsrc->filename);
2493                 sname = g_path_get_basename (name);
2494         
2495                 table = &assembly->tables [MONO_TABLE_FILE];
2496                 table->rows++;
2497                 alloc_table (table, table->rows);
2498                 values = table->values + table->next_idx * MONO_FILE_SIZE;
2499                 values [MONO_FILE_FLAGS] = FILE_CONTAINS_NO_METADATA;
2500                 values [MONO_FILE_NAME] = string_heap_insert (&assembly->sheap, sname);
2501                 g_free (sname);
2502
2503                 mono_sha1_get_digest_from_file (name, hash);
2504                 mono_metadata_encode_value (20, b, &b);
2505                 values [MONO_FILE_HASH_VALUE] = mono_image_add_stream_data (&assembly->blob, blob_size, b-blob_size);
2506                 mono_image_add_stream_data (&assembly->blob, hash, 20);
2507                 g_free (name);
2508                 idx = table->next_idx++;
2509                 idx = IMPLEMENTATION_FILE | (idx << IMPLEMENTATION_BITS);
2510                 offset = 0;
2511         } else {
2512                 char sizebuf [4];
2513                 offset = mono_array_length (rsrc->data);
2514                 sizebuf [0] = offset; sizebuf [1] = offset >> 8;
2515                 sizebuf [2] = offset >> 16; sizebuf [3] = offset >> 24;
2516                 offset = mono_image_add_stream_data (&assembly->resources, sizebuf, 4);
2517                 mono_image_add_stream_data (&assembly->resources, mono_array_addr (rsrc->data, char, 0), mono_array_length (rsrc->data));
2518                 idx = 0;
2519         }
2520
2521         table = &assembly->tables [MONO_TABLE_MANIFESTRESOURCE];
2522         table->rows++;
2523         alloc_table (table, table->rows);
2524         values = table->values + table->next_idx * MONO_MANIFEST_SIZE;
2525         values [MONO_MANIFEST_OFFSET] = offset;
2526         values [MONO_MANIFEST_FLAGS] = rsrc->attrs;
2527         name = mono_string_to_utf8 (rsrc->name);
2528         values [MONO_MANIFEST_NAME] = string_heap_insert (&assembly->sheap, name);
2529         g_free (name);
2530         values [MONO_MANIFEST_IMPLEMENTATION] = idx;
2531         table->next_idx++;
2532 }
2533
2534 static void
2535 set_version_from_string (MonoString *version, guint32 *values)
2536 {
2537         gchar *ver, *p, *str;
2538         guint32 i;
2539         
2540         values [MONO_ASSEMBLY_MAJOR_VERSION] = 0;
2541         values [MONO_ASSEMBLY_MINOR_VERSION] = 0;
2542         values [MONO_ASSEMBLY_REV_NUMBER] = 0;
2543         values [MONO_ASSEMBLY_BUILD_NUMBER] = 0;
2544         if (!version)
2545                 return;
2546         ver = str = mono_string_to_utf8 (version);
2547         for (i = 0; i < 4; ++i) {
2548                 values [MONO_ASSEMBLY_MAJOR_VERSION + i] = strtol (ver, &p, 10);
2549                 switch (*p) {
2550                 case '.':
2551                         p++;
2552                         break;
2553                 case '*':
2554                         /* handle Revision and Build */
2555                         p++;
2556                         break;
2557                 }
2558                 ver = p;
2559         }
2560         g_free (str);
2561 }
2562
2563 static guint32
2564 load_public_key (MonoString *fname, MonoDynamicAssembly *assembly) {
2565         char *name, *content;
2566         gsize len;
2567         guint32 token = 0;
2568
2569         if (!fname)
2570                 return token;
2571         name = mono_string_to_utf8 (fname);
2572         if (g_file_get_contents (name, &content, &len, NULL)) {
2573                 char blob_size [6];
2574                 char *b = blob_size;
2575                 /* check it's a public key or keypair */
2576                 mono_metadata_encode_value (len, b, &b);
2577                 token = mono_image_add_stream_data (&assembly->blob, blob_size, b - blob_size);
2578                 mono_image_add_stream_data (&assembly->blob, content, len);
2579                 g_free (content);
2580                 /* need to get the actual value from the key type... */
2581                 assembly->strong_name_size = 128;
2582                 assembly->strong_name = g_malloc0 (assembly->strong_name_size);
2583         }
2584         /* FIXME: how do we tell mcs if loading fails? */
2585         g_free (name);
2586         return token;
2587 }
2588
2589 /*
2590  * mono_image_build_metadata() will fill the info in all the needed metadata tables
2591  * for the AssemblyBuilder @assemblyb: it iterates over the assembly modules
2592  * and recursively outputs the info for a module. Each module will output all the info
2593  * about it's types etc.
2594  * At the end of the process, method and field tokens are fixed up and the on-disk
2595  * compressed metadata representation is created.
2596  */
2597 void
2598 mono_image_build_metadata (MonoReflectionAssemblyBuilder *assemblyb)
2599 {
2600         MonoDynamicTable *table;
2601         MonoDynamicAssembly *assembly = assemblyb->dynamic_assembly;
2602         MonoDomain *domain = mono_object_domain (assemblyb);
2603         guint32 len;
2604         guint32 *values;
2605         char *name;
2606         int i;
2607
2608         if (assembly->text_rva)
2609                 return;
2610
2611         assembly->text_rva = START_TEXT_RVA;
2612
2613         table = &assembly->tables [MONO_TABLE_ASSEMBLY];
2614         alloc_table (table, 1);
2615         values = table->values + MONO_ASSEMBLY_SIZE;
2616         values [MONO_ASSEMBLY_HASH_ALG] = assemblyb->algid? assemblyb->algid: ASSEMBLY_HASH_SHA1;
2617         name = mono_string_to_utf8 (assemblyb->name);
2618         values [MONO_ASSEMBLY_NAME] = string_heap_insert (&assembly->sheap, name);
2619         g_free (name);
2620         if (assemblyb->culture) {
2621                 name = mono_string_to_utf8 (assemblyb->culture);
2622                 values [MONO_ASSEMBLY_CULTURE] = string_heap_insert (&assembly->sheap, name);
2623                 g_free (name);
2624         } else {
2625                 values [MONO_ASSEMBLY_CULTURE] = string_heap_insert (&assembly->sheap, "");
2626         }
2627         values [MONO_ASSEMBLY_PUBLIC_KEY] = load_public_key (assemblyb->keyfile, assembly);
2628         values [MONO_ASSEMBLY_FLAGS] = assemblyb->flags;
2629         set_version_from_string (assemblyb->version, values);
2630
2631         table = &assembly->tables [MONO_TABLE_TYPEDEF];
2632         table->rows = 1; /* .<Module> */
2633         table->next_idx++;
2634         alloc_table (table, table->rows);
2635         /*
2636          * Set the first entry.
2637          */
2638         values = table->values + table->columns;
2639         values [MONO_TYPEDEF_FLAGS] = 0;
2640         values [MONO_TYPEDEF_NAME] = string_heap_insert (&assembly->sheap, "<Module>") ;
2641         values [MONO_TYPEDEF_NAMESPACE] = string_heap_insert (&assembly->sheap, "") ;
2642         values [MONO_TYPEDEF_EXTENDS] = 0;
2643         values [MONO_TYPEDEF_FIELD_LIST] = 1;
2644         values [MONO_TYPEDEF_METHOD_LIST] = 1;
2645
2646         /* 
2647          * handle global methods 
2648          * FIXME: test what to do when global methods are defined in multiple modules.
2649          */
2650         if (assemblyb->modules) {
2651                 MonoReflectionModuleBuilder *mod = mono_array_get (assemblyb->modules, MonoReflectionModuleBuilder*, 0);
2652                 if (mod->global_methods) {
2653                         table = &assembly->tables [MONO_TABLE_METHOD];
2654                         table->rows += mono_array_length (mod->global_methods);
2655                         alloc_table (table, table->rows);
2656                         for (i = 0; i < mono_array_length (mod->global_methods); ++i)
2657                                 mono_image_get_method_info (
2658                                         mono_array_get (mod->global_methods, MonoReflectionMethodBuilder*, i), assembly);
2659                 }
2660                 if (mod->global_fields) {
2661                         table = &assembly->tables [MONO_TABLE_FIELD];
2662                         table->rows += mono_array_length (mod->global_fields);
2663                         alloc_table (table, table->rows);
2664                         for (i = 0; i < mono_array_length (mod->global_fields); ++i)
2665                                 mono_image_get_field_info (
2666                                         mono_array_get (mod->global_fields, MonoReflectionFieldBuilder*, i), assembly);
2667                 }
2668         }
2669
2670         if (assemblyb->modules) {
2671                 len = mono_array_length (assemblyb->modules);
2672                 table = &assembly->tables [MONO_TABLE_MODULE];
2673                 alloc_table (table, len);
2674                 for (i = 0; i < len; ++i)
2675                         mono_image_fill_module_table (domain, mono_array_get (assemblyb->modules, MonoReflectionModuleBuilder*, i), assembly);
2676         } else {
2677                 table = &assembly->tables [MONO_TABLE_MODULE];
2678                 table->rows++;
2679                 alloc_table (table, table->rows);
2680                 table->values [table->next_idx * MONO_MODULE_SIZE + MONO_MODULE_NAME] = string_heap_insert (&assembly->sheap, "RefEmit_YouForgotToDefineAModule");
2681                 table->next_idx ++;
2682         }
2683
2684         /* Emit types */
2685         if (assemblyb->modules) {
2686                 /* Collect all types into a list sorted by their table_idx */
2687                 GPtrArray *types = g_ptr_array_new ();
2688
2689                 len = mono_array_length (assemblyb->modules);
2690                 for (i = 0; i < len; ++i) {
2691                         MonoReflectionModuleBuilder *mb =
2692                                 mono_array_get (assemblyb->modules, MonoReflectionModuleBuilder*, i);
2693                         if (mb->types)
2694                                 for (i = 0; i < mono_array_length (mb->types); ++i) {
2695                                         MonoReflectionTypeBuilder *type = mono_array_get (mb->types, MonoReflectionTypeBuilder*, i);
2696                                         collect_types (types, type);
2697                                 }
2698                 }
2699
2700                 g_ptr_array_sort (types, (GCompareFunc)compare_types_by_table_idx);
2701                 table = &assembly->tables [MONO_TABLE_TYPEDEF];
2702                 table->rows += types->len;
2703                 alloc_table (table, table->rows);
2704                 
2705                 for (i = 0; i < types->len; ++i) {
2706                         MonoReflectionTypeBuilder *type = g_ptr_array_index (types, i);
2707                         mono_image_get_type_info (domain, type, assembly);
2708                 }
2709                 g_ptr_array_free (types, TRUE);
2710         }
2711
2712         /* 
2713          * table->rows is already set above and in mono_image_fill_module_table.
2714          */
2715         /* add all the custom attributes at the end, once all the indexes are stable */
2716         mono_image_add_cattrs (assembly, 1, CUSTOM_ATTR_ASSEMBLY, assemblyb->cattrs);
2717
2718         if (assemblyb->modules) {
2719                 len = mono_array_length (assemblyb->modules);
2720                 for (i = 0; i < len; ++i)
2721                         module_add_cattrs (assembly, mono_array_get (assemblyb->modules, MonoReflectionModuleBuilder*, i));
2722         }
2723
2724         /* fixup tokens */
2725         mono_g_hash_table_foreach (assembly->token_fixups, (GHFunc)fixup_method, assembly);
2726 }
2727
2728 /*
2729  * mono_image_insert_string:
2730  * @assembly: assembly builder object
2731  * @str: a string
2732  *
2733  * Insert @str into the user string stream of @assembly.
2734  */
2735 guint32
2736 mono_image_insert_string (MonoReflectionAssemblyBuilder *assembly, MonoString *str)
2737 {
2738         guint32 idx;
2739         char buf [16];
2740         char *b = buf;
2741         
2742         MONO_ARCH_SAVE_REGS;
2743
2744         if (!assembly->dynamic_assembly)
2745                 mono_image_basic_init (assembly);
2746
2747         if (assembly->dynamic_assembly->save) {
2748                 mono_metadata_encode_value (1 | (str->length * 2), b, &b);
2749                 idx = mono_image_add_stream_data (&assembly->dynamic_assembly->us, buf, b-buf);
2750 #if G_BYTE_ORDER != G_LITTLE_ENDIAN
2751         {
2752                 char *swapped = g_malloc (2 * mono_string_length (str));
2753                 const char *p = (const char*)mono_string_chars (str);
2754
2755                 swap_with_size (swapped, p, 2, mono_string_length (str));
2756                 mono_image_add_stream_data (&assembly->dynamic_assembly->us, swapped, str->length * 2);
2757                 g_free (swapped);
2758         }
2759 #else
2760         mono_image_add_stream_data (&assembly->dynamic_assembly->us, (const char*)mono_string_chars (str), str->length * 2);
2761 #endif
2762         mono_image_add_stream_data (&assembly->dynamic_assembly->us, "", 1);
2763         }
2764         else
2765                 idx = assembly->dynamic_assembly->us.index ++;
2766
2767         mono_g_hash_table_insert (assembly->dynamic_assembly->tokens, 
2768                                                           GUINT_TO_POINTER (MONO_TOKEN_STRING | idx), str);
2769
2770         return MONO_TOKEN_STRING | idx;
2771 }
2772
2773 /*
2774  * mono_image_create_token:
2775  * @assembly: a dynamic assembly
2776  * @obj:
2777  *
2778  * Get a token to insert in the IL code stream for the given MemberInfo.
2779  * @obj can be one of:
2780  *      ConstructorBuilder
2781  *      MethodBuilder
2782  *      FieldBuilder
2783  *      MonoCMethod
2784  *      MonoMethod
2785  *      MonoField
2786  *      MonoType
2787  *      TypeBuilder
2788  */
2789 guint32
2790 mono_image_create_token (MonoDynamicAssembly *assembly, MonoObject *obj)
2791 {
2792         MonoClass *klass;
2793         guint32 token;
2794
2795         klass = obj->vtable->klass;
2796         if (strcmp (klass->name, "MethodBuilder") == 0) {
2797                 MonoReflectionMethodBuilder *mb = (MonoReflectionMethodBuilder *)obj;
2798                 token = mb->table_idx | MONO_TOKEN_METHOD_DEF;
2799                 /*g_print ("got token 0x%08x for %s\n", token, mono_string_to_utf8 (mb->name));*/
2800         }
2801         else if (strcmp (klass->name, "ConstructorBuilder") == 0) {
2802                 MonoReflectionCtorBuilder *mb = (MonoReflectionCtorBuilder *)obj;
2803                 token = mb->table_idx | MONO_TOKEN_METHOD_DEF;
2804                 /*g_print ("got token 0x%08x for %s\n", token, mono_string_to_utf8 (mb->name));*/
2805         }
2806         else if (strcmp (klass->name, "FieldBuilder") == 0) {
2807                 MonoReflectionFieldBuilder *mb = (MonoReflectionFieldBuilder *)obj;
2808                 token = mb->table_idx | MONO_TOKEN_FIELD_DEF;
2809         }
2810         else if (strcmp (klass->name, "TypeBuilder") == 0) {
2811                 MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder *)obj;
2812                 token = tb->table_idx | MONO_TOKEN_TYPE_DEF;
2813         }
2814         else if (strcmp (klass->name, "MonoType") == 0) {
2815                 MonoReflectionType *tb = (MonoReflectionType *)obj;
2816                 token = mono_metadata_token_from_dor (
2817                         mono_image_typedef_or_ref (assembly, tb->type));
2818         }
2819         else if (strcmp (klass->name, "MonoCMethod") == 0 ||
2820                         strcmp (klass->name, "MonoMethod") == 0) {
2821                 MonoReflectionMethod *m = (MonoReflectionMethod *)obj;
2822                 if (m->method->klass->image == assembly->assembly.image) {
2823                         static guint32 method_table_idx = 0xffffff;
2824                         /*
2825                          * Each token should have a unique index, but the indexes are
2826                          * assigned by managed code, so we don't know about them. An
2827                          * easy solution is to count backwards...
2828                          */
2829                         method_table_idx --;
2830                         token = MONO_TOKEN_METHOD_DEF | method_table_idx;
2831                 } else
2832                         token = mono_image_get_methodref_token (assembly, m->method);
2833                 /*g_print ("got token 0x%08x for %s\n", token, m->method->name);*/
2834         }
2835         else if (strcmp (klass->name, "MonoField") == 0) {
2836                 MonoReflectionField *f = (MonoReflectionField *)obj;
2837                 if (f->klass->image == assembly->assembly.image) {
2838                         static guint32 field_table_idx = 0xffffff;
2839                         field_table_idx --;
2840                         token = MONO_TOKEN_FIELD_DEF | field_table_idx;
2841                 } else
2842                         token = mono_image_get_fieldref_token (assembly, f->field, f->klass);
2843                 /*g_print ("got token 0x%08x for %s\n", token, f->field->name);*/
2844         }
2845         else if (strcmp (klass->name, "MonoArrayMethod") == 0) {
2846                 MonoReflectionArrayMethod *m = (MonoReflectionArrayMethod *)obj;
2847                 token = mono_image_get_array_token (assembly, m);
2848         }
2849         else if (strcmp (klass->name, "SignatureHelper") == 0) {
2850                 MonoReflectionSigHelper *s = (MonoReflectionSigHelper*)obj;
2851                 token = MONO_TOKEN_SIGNATURE | mono_image_get_sighelper_token (assembly, s);
2852         }
2853         else
2854                 g_error ("requested token for %s\n", klass->name);
2855
2856         mono_g_hash_table_insert (assembly->tokens, GUINT_TO_POINTER (token),
2857                                                           obj);
2858
2859         return token;
2860 }
2861
2862 typedef struct {
2863         guint32 import_lookup_table;
2864         guint32 timestamp;
2865         guint32 forwarder;
2866         guint32 name_rva;
2867         guint32 import_address_table_rva;
2868 } MonoIDT;
2869
2870 typedef struct {
2871         guint32 name_rva;
2872         guint32 flags;
2873 } MonoILT;
2874
2875 static void register_assembly (MonoDomain *domain, MonoReflectionAssembly *res, MonoAssembly *assembly);
2876
2877 static MonoImage*
2878 create_dynamic_mono_image (char *assembly_name, char *module_name)
2879 {
2880         MonoImage *image;
2881
2882         /*
2883          * We need to use the current ms version or the ms runtime it won't find
2884          * the support dlls. D'oh!
2885          * const char *version = "mono-" VERSION;
2886          */
2887         const char *version = "v1.0.3705";
2888
2889         image = g_new0 (MonoImage, 1);
2890         
2891         /* keep in sync with image.c */
2892         image->name = assembly_name;
2893         image->assembly_name = image->name; /* they may be different */
2894         image->module_name = module_name;
2895         image->version = g_strdup (version);
2896
2897         image->references = g_new0 (MonoAssembly*, 1);
2898         image->references [0] = NULL;
2899
2900         image->method_cache = g_hash_table_new (g_direct_hash, g_direct_equal);
2901         image->class_cache = g_hash_table_new (g_direct_hash, g_direct_equal);
2902         image->name_cache = g_hash_table_new (g_str_hash, g_str_equal);
2903         image->array_cache = g_hash_table_new (g_direct_hash, g_direct_equal);
2904
2905         image->delegate_begin_invoke_cache = 
2906                 g_hash_table_new ((GHashFunc)mono_signature_hash, 
2907                                   (GCompareFunc)mono_metadata_signature_equal);
2908         image->delegate_end_invoke_cache = 
2909                 g_hash_table_new ((GHashFunc)mono_signature_hash, 
2910                                   (GCompareFunc)mono_metadata_signature_equal);
2911         image->delegate_invoke_cache = 
2912                 g_hash_table_new ((GHashFunc)mono_signature_hash, 
2913                                   (GCompareFunc)mono_metadata_signature_equal);
2914
2915         image->runtime_invoke_cache = g_hash_table_new (g_direct_hash, g_direct_equal);
2916         image->managed_wrapper_cache = g_hash_table_new (g_direct_hash, g_direct_equal);
2917         image->native_wrapper_cache = g_hash_table_new (g_direct_hash, g_direct_equal);
2918         image->remoting_invoke_cache = g_hash_table_new (g_direct_hash, g_direct_equal);
2919         image->synchronized_cache = g_hash_table_new (g_direct_hash, g_direct_equal);
2920
2921         return image;
2922 }
2923
2924 /*
2925  * mono_image_basic_init:
2926  * @assembly: an assembly builder object
2927  *
2928  * Create the MonoImage that represents the assembly builder and setup some
2929  * of the helper hash table and the basic metadata streams.
2930  */
2931 void
2932 mono_image_basic_init (MonoReflectionAssemblyBuilder *assemblyb)
2933 {
2934         static const guchar entrycode [16] = {0xff, 0x25, 0};
2935         MonoDynamicAssembly *assembly;
2936         MonoImage *image;
2937         int i;
2938         
2939         MONO_ARCH_SAVE_REGS;
2940
2941         if (assemblyb->dynamic_assembly)
2942                 return;
2943
2944 #if HAVE_BOEHM_GC
2945         assembly = assemblyb->dynamic_assembly = GC_MALLOC (sizeof (MonoDynamicAssembly));
2946 #else
2947         assembly = assemblyb->dynamic_assembly = g_new0 (MonoDynamicAssembly, 1);
2948 #endif
2949
2950         assembly->assembly.dynamic = assembly;
2951         assemblyb->assembly.assembly = (MonoAssembly*)assembly;
2952         assembly->token_fixups = mono_g_hash_table_new (g_direct_hash, g_direct_equal);
2953         assembly->method_to_table_idx = mono_g_hash_table_new (g_direct_hash, g_direct_equal);
2954         assembly->field_to_table_idx = mono_g_hash_table_new (g_direct_hash, g_direct_equal);
2955         assembly->param_marshalling = mono_g_hash_table_new (g_direct_hash, g_direct_equal);
2956         assembly->handleref = g_hash_table_new (g_direct_hash, g_direct_equal);
2957         assembly->tokens = mono_g_hash_table_new (g_direct_hash, g_direct_equal);
2958         assembly->typeref = g_hash_table_new ((GHashFunc)mono_metadata_type_hash, (GCompareFunc)mono_metadata_type_equal);
2959         assembly->blob_cache = mono_g_hash_table_new ((GHashFunc)mono_blob_entry_hash, (GCompareFunc)mono_blob_entry_equal);
2960
2961         string_heap_init (&assembly->sheap);
2962         mono_image_add_stream_data (&assembly->us, "", 1);
2963         add_to_blob_cached (assembly, (char*) "", 1, NULL, 0);
2964         /* import tables... */
2965         mono_image_add_stream_data (&assembly->code, entrycode, sizeof (entrycode));
2966         assembly->iat_offset = mono_image_add_stream_zero (&assembly->code, 8); /* two IAT entries */
2967         assembly->idt_offset = mono_image_add_stream_zero (&assembly->code, 2 * sizeof (MonoIDT)); /* two IDT entries */
2968         mono_image_add_stream_zero (&assembly->code, 2); /* flags for name entry */
2969         assembly->imp_names_offset = mono_image_add_stream_data (&assembly->code, "_CorExeMain", 12);
2970         mono_image_add_stream_data (&assembly->code, "mscoree.dll", 12);
2971         assembly->ilt_offset = mono_image_add_stream_zero (&assembly->code, 8); /* two ILT entries */
2972         stream_data_align (&assembly->code);
2973
2974         assembly->cli_header_offset = mono_image_add_stream_zero (&assembly->code, sizeof (MonoCLIHeader));
2975
2976         for (i=0; i < 64; ++i) {
2977                 assembly->tables [i].next_idx = 1;
2978                 assembly->tables [i].columns = table_sizes [i];
2979         }
2980
2981         assembly->run = assemblyb->access != 2;
2982         assembly->save = assemblyb->access != 1;
2983
2984         image = create_dynamic_mono_image (mono_string_to_utf8 (assemblyb->name), g_strdup ("RefEmit_YouForgotToDefineAModule"));
2985         assembly->assembly.aname.name = image->name;
2986         image->assembly = (MonoAssembly*)assembly;
2987         assembly->assembly.image = image;
2988
2989         register_assembly (mono_object_domain (assemblyb), &assemblyb->assembly, &assembly->assembly);
2990         mono_assembly_invoke_load_hook ((MonoAssembly*)assembly);
2991 }
2992
2993 static int
2994 calc_section_size (MonoDynamicAssembly *assembly)
2995 {
2996         int nsections = 0;
2997
2998         /* alignment constraints */
2999         assembly->code.index += 3;
3000         assembly->code.index &= ~3;
3001         assembly->meta_size += 3;
3002         assembly->meta_size &= ~3;
3003         assembly->resources.index += 3;
3004         assembly->resources.index &= ~3;
3005
3006         assembly->sections [MONO_SECTION_TEXT].size = assembly->meta_size + assembly->code.index + assembly->resources.index + assembly->strong_name_size;
3007         assembly->sections [MONO_SECTION_TEXT].attrs = SECT_FLAGS_HAS_CODE | SECT_FLAGS_MEM_EXECUTE | SECT_FLAGS_MEM_READ;
3008         nsections++;
3009
3010         assembly->sections [MONO_SECTION_RELOC].size = 12;
3011         assembly->sections [MONO_SECTION_RELOC].attrs = SECT_FLAGS_MEM_READ | SECT_FLAGS_MEM_DISCARDABLE | SECT_FLAGS_HAS_INITIALIZED_DATA;
3012         nsections++;
3013
3014         return nsections;
3015 }
3016
3017 /*
3018  * mono_image_create_pefile:
3019  * @assemblyb: an assembly builder object
3020  * 
3021  * When we need to save an assembly, we first call this function that ensures the metadata 
3022  * tables are built for all the modules in the assembly. This function creates the PE-COFF
3023  * header, the image sections, the CLI header etc. all the data is written in
3024  * assembly->pefile where it can be easily retrieved later in chunks.
3025  */
3026 void
3027 mono_image_create_pefile (MonoReflectionAssemblyBuilder *assemblyb) {
3028         MonoMSDOSHeader *msdos;
3029         MonoDotNetHeader *header;
3030         MonoSectionTable *section;
3031         MonoCLIHeader *cli_header;
3032         guint32 size, image_size, virtual_base, text_offset;
3033         guint32 header_start, section_start, file_offset, virtual_offset;
3034         MonoDynamicAssembly *assembly;
3035         MonoDynamicStream *pefile;
3036         int i, nsections;
3037         guint32 *rva, value;
3038         guint16 *data16;
3039         guchar *p;
3040         static const unsigned char msheader[] = {
3041                 0x4d, 0x5a, 0x90, 0x00, 0x03, 0x00, 0x00, 0x00,  0x04, 0x00, 0x00, 0x00, 0xff, 0xff, 0x00, 0x00,
3042                 0xb8, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,  0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
3043                 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
3044                 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,  0x00, 0x00, 0x00, 0x00, 0x80, 0x00, 0x00, 0x00,
3045                 0x0e, 0x1f, 0xba, 0x0e, 0x00, 0xb4, 0x09, 0xcd,  0x21, 0xb8, 0x01, 0x4c, 0xcd, 0x21, 0x54, 0x68,
3046                 0x69, 0x73, 0x20, 0x70, 0x72, 0x6f, 0x67, 0x72,  0x61, 0x6d, 0x20, 0x63, 0x61, 0x6e, 0x6e, 0x6f,
3047                 0x74, 0x20, 0x62, 0x65, 0x20, 0x72, 0x75, 0x6e,  0x20, 0x69, 0x6e, 0x20, 0x44, 0x4f, 0x53, 0x20,
3048                 0x6d, 0x6f, 0x64, 0x65, 0x2e, 0x0d, 0x0d, 0x0a,  0x24, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
3049         };
3050
3051         mono_image_basic_init (assemblyb);
3052         assembly = assemblyb->dynamic_assembly;
3053
3054         /* already created */
3055         if (assembly->pefile.index)
3056                 return;
3057         
3058         mono_image_build_metadata (assemblyb);
3059
3060         if (assemblyb->resources) {
3061                 int len = mono_array_length (assemblyb->resources);
3062                 for (i = 0; i < len; ++i)
3063                         assembly_add_resource (assembly, (MonoReflectionResource*)mono_array_addr (assemblyb->resources, MonoReflectionResource, i));
3064         }
3065
3066         
3067         build_compressed_metadata (assembly);
3068
3069         nsections = calc_section_size (assembly);
3070
3071         pefile = &assembly->pefile;
3072
3073         /* The DOS header and stub */
3074         g_assert (sizeof (MonoMSDOSHeader) == sizeof (msheader));
3075         mono_image_add_stream_data (pefile, msheader, sizeof (msheader));
3076
3077         /* the dotnet header */
3078         header_start = mono_image_add_stream_zero (pefile, sizeof (MonoDotNetHeader));
3079
3080         /* the section tables */
3081         section_start = mono_image_add_stream_zero (pefile, sizeof (MonoSectionTable) * nsections);
3082
3083         file_offset = section_start + sizeof (MonoSectionTable) * nsections;
3084         virtual_offset = VIRT_ALIGN;
3085         image_size = 0;
3086
3087         for (i = 0; i < MONO_SECTION_MAX; ++i) {
3088                 if (!assembly->sections [i].size)
3089                         continue;
3090                 /* align offsets */
3091                 file_offset += FILE_ALIGN - 1;
3092                 file_offset &= ~(FILE_ALIGN - 1);
3093                 virtual_offset += VIRT_ALIGN - 1;
3094                 virtual_offset &= ~(VIRT_ALIGN - 1);
3095
3096                 assembly->sections [i].offset = file_offset;
3097                 assembly->sections [i].rva = virtual_offset;
3098
3099                 file_offset += assembly->sections [i].size;
3100                 virtual_offset += assembly->sections [i].size;
3101                 image_size += (assembly->sections [i].size + VIRT_ALIGN - 1) & ~(VIRT_ALIGN - 1);
3102         }
3103
3104         file_offset += FILE_ALIGN - 1;
3105         file_offset &= ~(FILE_ALIGN - 1);
3106         mono_image_add_stream_zero (pefile, file_offset - pefile->index);
3107
3108         image_size += section_start + sizeof (MonoSectionTable) * nsections;
3109
3110         /* back-patch info */
3111         msdos = (MonoMSDOSHeader*)pefile->data;
3112         msdos->nlast_page = GUINT16_FROM_LE (file_offset & (512 - 1));
3113         msdos->npages = GUINT16_FROM_LE ((file_offset + (512 - 1)) / 512);
3114         msdos->pe_offset = GUINT32_FROM_LE (sizeof (MonoMSDOSHeader));
3115
3116         header = (MonoDotNetHeader*)(pefile->data + header_start);
3117         header->pesig [0] = 'P';
3118         header->pesig [1] = 'E';
3119         
3120         header->coff.coff_machine = GUINT16_FROM_LE (0x14c);
3121         header->coff.coff_sections = GUINT16_FROM_LE (nsections);
3122         header->coff.coff_time = GUINT32_FROM_LE (time (NULL));
3123         header->coff.coff_opt_header_size = GUINT16_FROM_LE (sizeof (MonoDotNetHeader) - sizeof (MonoCOFFHeader) - 4);
3124         if (assemblyb->pekind == 1) {
3125                 /* it's a dll */
3126                 header->coff.coff_attributes = GUINT16_FROM_LE (0x210e);
3127         } else {
3128                 /* it's an exe */
3129                 header->coff.coff_attributes = GUINT16_FROM_LE (0x010e);
3130         }
3131
3132         virtual_base = 0x400000; /* FIXME: 0x10000000 if a DLL */
3133
3134         header->pe.pe_magic = GUINT16_FROM_LE (0x10B);
3135         header->pe.pe_major = 6;
3136         header->pe.pe_minor = 0;
3137         size = assembly->sections [MONO_SECTION_TEXT].size;
3138         size += FILE_ALIGN - 1;
3139         size &= ~(FILE_ALIGN - 1);
3140         header->pe.pe_code_size = size;
3141         size = assembly->sections [MONO_SECTION_RSRC].size;
3142         size += FILE_ALIGN - 1;
3143         size &= ~(FILE_ALIGN - 1);
3144         header->pe.pe_data_size = size;
3145         g_assert (START_TEXT_RVA == assembly->sections [MONO_SECTION_TEXT].rva);
3146         header->pe.pe_rva_code_base = assembly->sections [MONO_SECTION_TEXT].rva;
3147         header->pe.pe_rva_data_base = assembly->sections [MONO_SECTION_RSRC].rva;
3148         /* pe_rva_entry_point always at the beginning of the text section */
3149         header->pe.pe_rva_entry_point = assembly->sections [MONO_SECTION_TEXT].rva;
3150
3151         header->nt.pe_image_base = GUINT32_FROM_LE (virtual_base);
3152         header->nt.pe_section_align = GUINT32_FROM_LE (VIRT_ALIGN);
3153         header->nt.pe_file_alignment = GUINT32_FROM_LE (FILE_ALIGN);
3154         header->nt.pe_os_major = GUINT16_FROM_LE (4);
3155         header->nt.pe_os_minor = GUINT16_FROM_LE (0);
3156         header->nt.pe_subsys_major = GUINT16_FROM_LE (4);
3157         size = section_start;
3158         size += FILE_ALIGN - 1;
3159         size &= ~(FILE_ALIGN - 1);
3160         header->nt.pe_header_size = GUINT32_FROM_LE (size);
3161         size = image_size;
3162         size += VIRT_ALIGN - 1;
3163         size &= ~(VIRT_ALIGN - 1);
3164         header->nt.pe_image_size = GUINT32_FROM_LE (size);
3165
3166         //
3167         // Translate the PEFileKind value to the value expected by the Windows loader
3168         //
3169         {
3170                 short kind = assemblyb->pekind;
3171
3172                 //
3173                 // PEFileKinds.ConsoleApplication == 2
3174                 // PEFileKinds.WindowApplication == 3
3175                 //
3176                 // need to get:
3177                 //     IMAGE_SUBSYSTEM_WINDOWS_GUI 2 // Image runs in the Windows GUI subsystem.
3178                 //     IMAGE_SUBSYSTEM_WINDOWS_CUI 3 // Image runs in the Windows character subsystem.
3179                 if (kind == 2)
3180                         kind = 3;
3181                 else if (kind == 3)
3182                         kind = 2;
3183                 
3184                 header->nt.pe_subsys_required = GUINT16_FROM_LE (kind);
3185         }    
3186         header->nt.pe_stack_reserve = GUINT32_FROM_LE (0x00100000);
3187         header->nt.pe_stack_commit = GUINT32_FROM_LE (0x00001000);
3188         header->nt.pe_heap_reserve = GUINT32_FROM_LE (0x00100000);
3189         header->nt.pe_heap_commit = GUINT32_FROM_LE (0x00001000);
3190         header->nt.pe_loader_flags = GUINT32_FROM_LE (0);
3191         header->nt.pe_data_dir_count = GUINT32_FROM_LE (16);
3192
3193         /* fill data directory entries */
3194
3195         header->datadir.pe_resource_table.size = GUINT32_FROM_LE (assembly->sections [MONO_SECTION_RSRC].size);
3196         header->datadir.pe_resource_table.rva = GUINT32_FROM_LE (assembly->sections [MONO_SECTION_RSRC].rva);
3197
3198         header->datadir.pe_reloc_table.size = GUINT32_FROM_LE (assembly->sections [MONO_SECTION_RELOC].size);
3199         header->datadir.pe_reloc_table.rva = GUINT32_FROM_LE (assembly->sections [MONO_SECTION_RELOC].rva);
3200
3201         header->datadir.pe_cli_header.size = GUINT32_FROM_LE (72);
3202         header->datadir.pe_cli_header.rva = GUINT32_FROM_LE (assembly->text_rva + assembly->cli_header_offset);
3203         header->datadir.pe_iat.size = GUINT32_FROM_LE (8);
3204         header->datadir.pe_iat.rva = GUINT32_FROM_LE (assembly->text_rva + assembly->iat_offset);
3205         /* patch imported function RVA name */
3206         rva = (guint32*)(assembly->code.data + assembly->iat_offset);
3207         *rva = GUINT32_FROM_LE (assembly->text_rva + assembly->imp_names_offset);
3208
3209         /* the import table */
3210         header->datadir.pe_import_table.size = GUINT32_FROM_LE (79); /* FIXME: magic number? */
3211         header->datadir.pe_import_table.rva = GUINT32_FROM_LE (assembly->text_rva + assembly->idt_offset);
3212         /* patch imported dll RVA name and other entries in the dir */
3213         rva = (guint32*)(assembly->code.data + assembly->idt_offset + G_STRUCT_OFFSET (MonoIDT, name_rva));
3214         *rva = GUINT32_FROM_LE (assembly->text_rva + assembly->imp_names_offset + 12); /* 12 is strlen+1 of func name */
3215         rva = (guint32*)(assembly->code.data + assembly->idt_offset + G_STRUCT_OFFSET (MonoIDT, import_address_table_rva));
3216         *rva = GUINT32_FROM_LE (assembly->text_rva + assembly->iat_offset);
3217         rva = (guint32*)(assembly->code.data + assembly->idt_offset + G_STRUCT_OFFSET (MonoIDT, import_lookup_table));
3218         *rva = GUINT32_FROM_LE (assembly->text_rva + assembly->ilt_offset);
3219
3220         p = (assembly->code.data + assembly->ilt_offset);
3221         value = (assembly->text_rva + assembly->imp_names_offset - 2);
3222         *p++ = (value) & 0xff;
3223         *p++ = (value >> 8) & (0xff);
3224         *p++ = (value >> 16) & (0xff);
3225         *p++ = (value >> 24) & (0xff);
3226
3227         /* the CLI header info */
3228         cli_header = (MonoCLIHeader*)(assembly->code.data + assembly->cli_header_offset);
3229         cli_header->ch_size = GUINT32_FROM_LE (72);
3230         cli_header->ch_runtime_major = GUINT16_FROM_LE (2);
3231         cli_header->ch_flags = GUINT32_FROM_LE (CLI_FLAGS_ILONLY);
3232         if (assemblyb->entry_point) 
3233                 cli_header->ch_entry_point = GUINT32_FROM_LE (assemblyb->entry_point->table_idx | MONO_TOKEN_METHOD_DEF);
3234         else
3235                 cli_header->ch_entry_point = GUINT32_FROM_LE (0);
3236         /* The embedded managed resources */
3237         text_offset = assembly->text_rva + assembly->code.index;
3238         cli_header->ch_resources.rva = GUINT32_FROM_LE (text_offset);
3239         cli_header->ch_resources.size = GUINT32_FROM_LE (assembly->resources.index);
3240         text_offset += assembly->resources.index;
3241         cli_header->ch_metadata.rva = GUINT32_FROM_LE (text_offset);
3242         cli_header->ch_metadata.size = GUINT32_FROM_LE (assembly->meta_size);
3243         text_offset += assembly->meta_size;
3244         if (assembly->strong_name_size) {
3245                 cli_header->ch_strong_name.rva = GUINT32_FROM_LE (text_offset);
3246                 cli_header->ch_strong_name.size = GUINT32_FROM_LE (assembly->strong_name_size);
3247                 text_offset += assembly->strong_name_size;
3248         }
3249
3250         /* write the section tables and section content */
3251         section = (MonoSectionTable*)(pefile->data + section_start);
3252         for (i = 0; i < MONO_SECTION_MAX; ++i) {
3253                 static const char *section_names [] = {
3254                         ".text", ".rsrc", ".reloc"
3255                 };
3256                 if (!assembly->sections [i].size)
3257                         continue;
3258                 strcpy (section->st_name, section_names [i]);
3259                 /*g_print ("output section %s (%d), size: %d\n", section->st_name, i, assembly->sections [i].size);*/
3260                 section->st_virtual_address = GUINT32_FROM_LE (assembly->sections [i].rva);
3261                 section->st_virtual_size = GUINT32_FROM_LE (assembly->sections [i].size);
3262                 section->st_raw_data_size = GUINT32_FROM_LE (GUINT32_TO_LE (section->st_virtual_size) + (FILE_ALIGN - 1));
3263                 section->st_raw_data_size &= GUINT32_FROM_LE (~(FILE_ALIGN - 1));
3264                 section->st_raw_data_ptr = GUINT32_FROM_LE (assembly->sections [i].offset);
3265                 section->st_flags = GUINT32_FROM_LE (assembly->sections [i].attrs);
3266                 switch (i) {
3267                 case MONO_SECTION_TEXT:
3268                         /* patch entry point */
3269                         p = (assembly->code.data + 2);
3270                         value = (virtual_base + assembly->text_rva + assembly->iat_offset);
3271                         *p++ = (value) & 0xff;
3272                         *p++ = (value >> 8) & 0xff;
3273                         *p++ = (value >> 16) & 0xff;
3274                         *p++ = (value >> 24) & 0xff;
3275
3276                         text_offset = assembly->sections [i].offset;
3277                         memcpy (pefile->data + text_offset, assembly->code.data, assembly->code.index);
3278                         text_offset += assembly->code.index;
3279                         memcpy (pefile->data + text_offset, assembly->resources.data, assembly->resources.index);
3280                         text_offset += assembly->resources.index;
3281                         memcpy (pefile->data + text_offset, assembly->assembly.image->raw_metadata, assembly->meta_size);
3282                         text_offset += assembly->meta_size;
3283                         memcpy (pefile->data + text_offset, assembly->strong_name, assembly->strong_name_size);
3284
3285                         g_free (assembly->assembly.image->raw_metadata);
3286                         break;
3287                 case MONO_SECTION_RELOC:
3288                         rva = (guint32*)(pefile->data + assembly->sections [i].offset);
3289                         *rva = GUINT32_FROM_LE (assembly->text_rva);
3290                         ++rva;
3291                         *rva = GUINT32_FROM_LE (12);
3292                         ++rva;
3293                         data16 = (guint16*)rva;
3294                         /* 
3295                          * the entrypoint is always at the start of the text section 
3296                          * 3 is IMAGE_REL_BASED_HIGHLOW
3297                          * 2 is patch_size_rva - text_rva
3298                          */
3299                         *data16 = GUINT16_FROM_LE ((3 << 12) + (2));
3300                         data16++;
3301                         *data16 = 0; /* terminate */
3302                         break;
3303                 case MONO_SECTION_RSRC:
3304                 default:
3305                         g_assert_not_reached ();
3306                 }
3307                 section++;
3308         }
3309         
3310         /* check that the file is properly padded */
3311 #if 0
3312         {
3313                 FILE *f = fopen ("mypetest.exe", "w");
3314                 fwrite (pefile->data, pefile->index, 1, f);
3315                 fclose (f);
3316         }
3317 #endif
3318 }
3319
3320 /*
3321  * We need to return always the same object for MethodInfo, FieldInfo etc..
3322  * but we need to consider the reflected type.
3323  * type uses a different hash, since it uses custom hash/equal functions.
3324  */
3325
3326 typedef struct {
3327         gpointer item;
3328         MonoClass *refclass;
3329 } ReflectedEntry;
3330
3331 static gboolean
3332 reflected_equal (gconstpointer a, gconstpointer b) {
3333         const ReflectedEntry *ea = a;
3334         const ReflectedEntry *eb = b;
3335
3336         return (ea->item == eb->item) && (ea->refclass == eb->refclass);
3337 }
3338
3339 static guint
3340 reflected_hash (gconstpointer a) {
3341         const ReflectedEntry *ea = a;
3342         return GPOINTER_TO_UINT (ea->item);
3343 }
3344
3345 #define CHECK_OBJECT(t,p,k)     \
3346         do {    \
3347                 t _obj; \
3348                 ReflectedEntry e;       \
3349                 e.item = (p);   \
3350                 e.refclass = (k);       \
3351                 mono_domain_lock (domain);      \
3352                 if (!domain->refobject_hash)    \
3353                         domain->refobject_hash = mono_g_hash_table_new (reflected_hash, reflected_equal);       \
3354                 if ((_obj = mono_g_hash_table_lookup (domain->refobject_hash, &e))) {   \
3355                         mono_domain_unlock (domain);    \
3356                         return _obj;    \
3357                 }       \
3358         } while (0)
3359
3360 #if HAVE_BOEHM_GC
3361 #define ALLOC_REFENTRY GC_MALLOC (sizeof (ReflectedEntry))
3362 #else
3363 #define ALLOC_REFENTRY mono_mempool_alloc (domain->mp, sizeof (ReflectedEntry))
3364 #endif
3365
3366 #define CACHE_OBJECT(p,o,k)     \
3367         do {    \
3368                 ReflectedEntry *e = ALLOC_REFENTRY;     \
3369                 e->item = (p);  \
3370                 e->refclass = (k);      \
3371                 mono_g_hash_table_insert (domain->refobject_hash, e,o); \
3372                 mono_domain_unlock (domain);    \
3373         } while (0)
3374
3375 static void 
3376 register_assembly (MonoDomain *domain, MonoReflectionAssembly *res, MonoAssembly *assembly)
3377 {
3378         /* this is done only once */
3379         mono_domain_lock (domain);
3380         CACHE_OBJECT (assembly, res, NULL);
3381 }
3382
3383 static void
3384 register_module (MonoDomain *domain, MonoReflectionModuleBuilder *res, MonoImage *module)
3385 {
3386         /* this is done only once */
3387         mono_domain_lock (domain);
3388         CACHE_OBJECT (module, res, NULL);
3389 }
3390
3391 void
3392 mono_image_module_basic_init (MonoReflectionModuleBuilder *moduleb)
3393 {
3394         MonoImage *image = moduleb->module.image;
3395         MonoReflectionAssemblyBuilder *ab = moduleb->assemblyb;
3396         if (!image) {
3397                 if (!ab->modules) {
3398                         /* a MonoImage was already created in mono_image_basic_init () */
3399                         image = ab->dynamic_assembly->assembly.image;
3400                 } else {
3401                         image = create_dynamic_mono_image (mono_string_to_utf8 (ab->name), mono_string_to_utf8 (moduleb->module.name));
3402                 }
3403                 moduleb->module.image = image;
3404                 register_module (mono_object_domain (moduleb), moduleb, image);
3405         }
3406 }
3407
3408 /*
3409  * mono_assembly_get_object:
3410  * @domain: an app domain
3411  * @assembly: an assembly
3412  *
3413  * Return an System.Reflection.Assembly object representing the MonoAssembly @assembly.
3414  */
3415 MonoReflectionAssembly*
3416 mono_assembly_get_object (MonoDomain *domain, MonoAssembly *assembly)
3417 {
3418         static MonoClass *System_Reflection_Assembly;
3419         MonoReflectionAssembly *res;
3420         
3421         CHECK_OBJECT (MonoReflectionAssembly *, assembly, NULL);
3422         if (!System_Reflection_Assembly)
3423                 System_Reflection_Assembly = mono_class_from_name (
3424                         mono_defaults.corlib, "System.Reflection", "Assembly");
3425         res = (MonoReflectionAssembly *)mono_object_new (domain, System_Reflection_Assembly);
3426         res->assembly = assembly;
3427         CACHE_OBJECT (assembly, res, NULL);
3428         return res;
3429 }
3430
3431
3432
3433 MonoReflectionModule*   
3434 mono_module_get_object   (MonoDomain *domain, MonoImage *image)
3435 {
3436         static MonoClass *System_Reflection_Module;
3437         MonoReflectionModule *res;
3438         
3439         CHECK_OBJECT (MonoReflectionModule *, image, NULL);
3440         if (!System_Reflection_Module)
3441                 System_Reflection_Module = mono_class_from_name (
3442                         mono_defaults.corlib, "System.Reflection", "Module");
3443         res = (MonoReflectionModule *)mono_object_new (domain, System_Reflection_Module);
3444
3445         res->image = image;
3446         res->assembly = (MonoReflectionAssembly *) mono_assembly_get_object(domain, image->assembly);
3447
3448         res->fqname    = mono_string_new (domain, image->name);
3449         res->name      = mono_string_new (domain, image->name);
3450         res->scopename = mono_string_new (domain, image->module_name);
3451
3452         CACHE_OBJECT (image, res, NULL);
3453         return res;
3454 }
3455
3456 MonoReflectionModule*   
3457 mono_module_file_get_object (MonoDomain *domain, MonoImage *image, int table_index)
3458 {
3459         static MonoClass *System_Reflection_Module;
3460         MonoReflectionModule *res;
3461         MonoTableInfo *table;
3462         guint32 cols [MONO_FILE_SIZE];
3463         const char *name;
3464         guint32 i, name_idx;
3465         const char *val;
3466         
3467         if (!System_Reflection_Module)
3468                 System_Reflection_Module = mono_class_from_name (
3469                         mono_defaults.corlib, "System.Reflection", "Module");
3470         res = (MonoReflectionModule *)mono_object_new (domain, System_Reflection_Module);
3471
3472         table = &image->tables [MONO_TABLE_FILE];
3473         g_assert (table_index < table->rows);
3474         mono_metadata_decode_row (table, table_index, cols, MONO_FILE_SIZE);
3475
3476         res->image = 0;
3477         res->assembly = (MonoReflectionAssembly *) mono_assembly_get_object(domain, image->assembly);
3478         name = mono_metadata_string_heap (image, cols [MONO_FILE_NAME]);
3479
3480         // Check whenever the row has a corresponding row in the moduleref table
3481         table = &image->tables [MONO_TABLE_MODULEREF];
3482         for (i = 0; i < table->rows; ++i) {
3483                 name_idx = mono_metadata_decode_row_col (table, i, MONO_MODULEREF_NAME);
3484                 val = mono_metadata_string_heap (image, name_idx);
3485                 if (strcmp (val, name) == 0)
3486                         res->image = image->modules [i];
3487         }
3488
3489         res->fqname    = mono_string_new (domain, name);
3490         res->name      = mono_string_new (domain, name);
3491         res->scopename = mono_string_new (domain, name);
3492         res->is_resource = cols [MONO_FILE_FLAGS] && FILE_CONTAINS_NO_METADATA;
3493
3494         return res;
3495 }
3496
3497 static gboolean
3498 mymono_metadata_type_equal (MonoType *t1, MonoType *t2)
3499 {
3500         if ((t1->type != t2->type) ||
3501             (t1->byref != t2->byref))
3502                 return FALSE;
3503
3504         switch (t1->type) {
3505         case MONO_TYPE_VOID:
3506         case MONO_TYPE_BOOLEAN:
3507         case MONO_TYPE_CHAR:
3508         case MONO_TYPE_I1:
3509         case MONO_TYPE_U1:
3510         case MONO_TYPE_I2:
3511         case MONO_TYPE_U2:
3512         case MONO_TYPE_I4:
3513         case MONO_TYPE_U4:
3514         case MONO_TYPE_I8:
3515         case MONO_TYPE_U8:
3516         case MONO_TYPE_R4:
3517         case MONO_TYPE_R8:
3518         case MONO_TYPE_STRING:
3519         case MONO_TYPE_I:
3520         case MONO_TYPE_U:
3521         case MONO_TYPE_OBJECT:
3522         case MONO_TYPE_TYPEDBYREF:
3523                 return TRUE;
3524         case MONO_TYPE_VALUETYPE:
3525         case MONO_TYPE_CLASS:
3526         case MONO_TYPE_SZARRAY:
3527                 return t1->data.klass == t2->data.klass;
3528         case MONO_TYPE_PTR:
3529                 return mymono_metadata_type_equal (t1->data.type, t2->data.type);
3530         case MONO_TYPE_ARRAY:
3531                 if (t1->data.array->rank != t2->data.array->rank)
3532                         return FALSE;
3533                 return t1->data.array->eklass == t2->data.array->eklass;
3534         case MONO_TYPE_GENERICINST: {
3535                 int i;
3536                 if (t1->data.generic_inst->type_argc != t2->data.generic_inst->type_argc)
3537                         return FALSE;
3538                 if (!mono_metadata_type_equal (t1->data.generic_inst->generic_type, t2->data.generic_inst->generic_type))
3539                         return FALSE;
3540                 for (i = 0; i < t1->data.generic_inst->type_argc; ++i) {
3541                         if (!mono_metadata_type_equal (t1->data.generic_inst->type_argv [i], t2->data.generic_inst->type_argv [i]))
3542                                 return FALSE;
3543                 }
3544                 return TRUE;
3545         }
3546         case MONO_TYPE_VAR:
3547         case MONO_TYPE_MVAR:
3548                 return t1->data.type_param == t2->data.type_param;
3549         default:
3550                 g_error ("implement type compare for %0x!", t1->type);
3551                 return FALSE;
3552         }
3553
3554         return FALSE;
3555 }
3556
3557 static guint
3558 mymono_metadata_type_hash (MonoType *t1)
3559 {
3560         guint hash;
3561
3562         hash = t1->type;
3563
3564         hash |= t1->byref << 6; /* do not collide with t1->type values */
3565         switch (t1->type) {
3566         case MONO_TYPE_VALUETYPE:
3567         case MONO_TYPE_CLASS:
3568         case MONO_TYPE_SZARRAY:
3569                 /* check if the distribution is good enough */
3570                 return ((hash << 5) - hash) ^ g_str_hash (t1->data.klass->name);
3571         case MONO_TYPE_PTR:
3572                 return ((hash << 5) - hash) ^ mymono_metadata_type_hash (t1->data.type);
3573         }
3574         return hash;
3575 }
3576
3577 /*
3578  * mono_type_get_object:
3579  * @domain: an app domain
3580  * @type: a type
3581  *
3582  * Return an System.MonoType object representing the type @type.
3583  */
3584 MonoReflectionType*
3585 mono_type_get_object (MonoDomain *domain, MonoType *type)
3586 {
3587         MonoReflectionType *res;
3588         MonoClass *klass = mono_class_from_mono_type (type);
3589
3590         mono_domain_lock (domain);
3591         if (!domain->type_hash)
3592                 domain->type_hash = mono_g_hash_table_new ((GHashFunc)mymono_metadata_type_hash, 
3593                                 (GCompareFunc)mymono_metadata_type_equal);
3594         if ((res = mono_g_hash_table_lookup (domain->type_hash, type))) {
3595                 mono_domain_unlock (domain);
3596                 return res;
3597         }
3598         if (klass->reflection_info && !klass->wastypebuilder) {
3599                 //g_assert_not_reached ();
3600                 /* should this be considered an error condition? */
3601                 if (!type->byref) {
3602                         mono_domain_unlock (domain);
3603                         return klass->reflection_info;
3604                 }
3605         }
3606         mono_class_init (klass);
3607         res = (MonoReflectionType *)mono_object_new (domain, mono_defaults.monotype_class);
3608         res->type = type;
3609         mono_g_hash_table_insert (domain->type_hash, type, res);
3610         mono_domain_unlock (domain);
3611         return res;
3612 }
3613
3614 /*
3615  * mono_method_get_object:
3616  * @domain: an app domain
3617  * @method: a method
3618  * @refclass: the reflected type (can be NULL)
3619  *
3620  * Return an System.Reflection.MonoMethod object representing the method @method.
3621  */
3622 MonoReflectionMethod*
3623 mono_method_get_object (MonoDomain *domain, MonoMethod *method, MonoClass *refclass)
3624 {
3625         /*
3626          * We use the same C representation for methods and constructors, but the type 
3627          * name in C# is different.
3628          */
3629         const char *cname;
3630         MonoClass *klass;
3631         MonoReflectionMethod *ret;
3632
3633         if (!refclass)
3634                 refclass = method->klass;
3635
3636         CHECK_OBJECT (MonoReflectionMethod *, method, refclass);
3637         if (*method->name == '.' && (strcmp (method->name, ".ctor") == 0 || strcmp (method->name, ".cctor") == 0))
3638                 cname = "MonoCMethod";
3639         else
3640                 cname = "MonoMethod";
3641         klass = mono_class_from_name (mono_defaults.corlib, "System.Reflection", cname);
3642
3643         ret = (MonoReflectionMethod*)mono_object_new (domain, klass);
3644         ret->method = method;
3645         ret->name = mono_string_new (domain, method->name);
3646         ret->reftype = mono_type_get_object (domain, &refclass->byval_arg);
3647         CACHE_OBJECT (method, ret, refclass);
3648         return ret;
3649 }
3650
3651 /*
3652  * mono_field_get_object:
3653  * @domain: an app domain
3654  * @klass: a type
3655  * @field: a field
3656  *
3657  * Return an System.Reflection.MonoField object representing the field @field
3658  * in class @klass.
3659  */
3660 MonoReflectionField*
3661 mono_field_get_object (MonoDomain *domain, MonoClass *klass, MonoClassField *field)
3662 {
3663         MonoReflectionField *res;
3664         MonoClass *oklass;
3665
3666         CHECK_OBJECT (MonoReflectionField *, field, klass);
3667         oklass = mono_class_from_name (mono_defaults.corlib, "System.Reflection", "MonoField");
3668         res = (MonoReflectionField *)mono_object_new (domain, oklass);
3669         res->klass = klass;
3670         res->field = field;
3671         res->name = mono_string_new (domain, field->name);
3672         res->attrs = field->type->attrs;
3673         res->type = mono_type_get_object (domain, field->type);
3674         CACHE_OBJECT (field, res, klass);
3675         return res;
3676 }
3677
3678 /*
3679  * mono_property_get_object:
3680  * @domain: an app domain
3681  * @klass: a type
3682  * @property: a property
3683  *
3684  * Return an System.Reflection.MonoProperty object representing the property @property
3685  * in class @klass.
3686  */
3687 MonoReflectionProperty*
3688 mono_property_get_object (MonoDomain *domain, MonoClass *klass, MonoProperty *property)
3689 {
3690         MonoReflectionProperty *res;
3691         MonoClass *oklass;
3692
3693         CHECK_OBJECT (MonoReflectionProperty *, property, klass);
3694         oklass = mono_class_from_name (mono_defaults.corlib, "System.Reflection", "MonoProperty");
3695         res = (MonoReflectionProperty *)mono_object_new (domain, oklass);
3696         res->klass = klass;
3697         res->property = property;
3698         CACHE_OBJECT (property, res, klass);
3699         return res;
3700 }
3701
3702 /*
3703  * mono_event_get_object:
3704  * @domain: an app domain
3705  * @klass: a type
3706  * @event: a event
3707  *
3708  * Return an System.Reflection.MonoEvent object representing the event @event
3709  * in class @klass.
3710  */
3711 MonoReflectionEvent*
3712 mono_event_get_object (MonoDomain *domain, MonoClass *klass, MonoEvent *event)
3713 {
3714         MonoReflectionEvent *res;
3715         MonoClass *oklass;
3716
3717         CHECK_OBJECT (MonoReflectionEvent *, event, klass);
3718         oklass = mono_class_from_name (mono_defaults.corlib, "System.Reflection", "MonoEvent");
3719         res = (MonoReflectionEvent *)mono_object_new (domain, oklass);
3720         res->klass = klass;
3721         res->event = event;
3722         CACHE_OBJECT (event, res, klass);
3723         return res;
3724 }
3725
3726 /*
3727  * mono_param_get_objects:
3728  * @domain: an app domain
3729  * @method: a method
3730  *
3731  * Return an System.Reflection.ParameterInfo array object representing the parameters
3732  * in the method @method.
3733  */
3734 MonoArray*
3735 mono_param_get_objects (MonoDomain *domain, MonoMethod *method)
3736 {
3737         static MonoClass *System_Reflection_ParameterInfo;
3738         MonoArray *res = NULL;
3739         MonoReflectionMethod *member = NULL;
3740         MonoReflectionParameter *param = NULL;
3741         char **names;
3742         int i;
3743
3744         if (!System_Reflection_ParameterInfo)
3745                 System_Reflection_ParameterInfo = mono_class_from_name (
3746                         mono_defaults.corlib, "System.Reflection", "ParameterInfo");
3747         
3748         if (!method->signature->param_count)
3749                 return mono_array_new (domain, System_Reflection_ParameterInfo, 0);
3750
3751         /* Note: the cache is based on the address of the signature into the method
3752          * since we already cache MethodInfos with the method as keys.
3753          */
3754         CHECK_OBJECT (MonoArray*, &(method->signature), NULL);
3755
3756         member = mono_method_get_object (domain, method, NULL);
3757         names = g_new (char *, method->signature->param_count);
3758         mono_method_get_param_names (method, (const char **) names);
3759
3760         res = mono_array_new (domain, System_Reflection_ParameterInfo, method->signature->param_count);
3761         for (i = 0; i < method->signature->param_count; ++i) {
3762                 param = (MonoReflectionParameter *)mono_object_new (domain, 
3763                                                                                                                         System_Reflection_ParameterInfo);
3764                 param->ClassImpl = mono_type_get_object (domain, method->signature->params [i]);
3765                 param->DefaultValueImpl = NULL; /* FIXME */
3766                 param->MemberImpl = (MonoObject*)member;
3767                 param->NameImpl = mono_string_new (domain, names [i]);
3768                 param->PositionImpl = i;
3769                 param->AttrsImpl = method->signature->params [i]->attrs;
3770                 mono_array_set (res, gpointer, i, param);
3771         }
3772         g_free (names);
3773         CACHE_OBJECT (&(method->signature), res, NULL);
3774         return res;
3775 }
3776
3777 static int
3778 assembly_name_to_aname (MonoAssemblyName *assembly, char *p) {
3779         int found_sep;
3780         char *s;
3781
3782         memset (assembly, 0, sizeof (MonoAssemblyName));
3783         assembly->name = p;
3784         assembly->culture = "";
3785         
3786         while (*p && (isalnum (*p) || *p == '.' || *p == '-'))
3787                 p++;
3788         found_sep = 0;
3789         while (*p == ' ' || *p == ',') {
3790                 *p++ = 0;
3791                 found_sep = 1;
3792                 continue;
3793         }
3794         /* failed */
3795         if (!found_sep)
3796                 return 1;
3797         while (*p) {
3798                 if (*p == 'V' && strncmp (p, "Version=", 8) == 0) {
3799                         p += 8;
3800                         assembly->major = strtoul (p, &s, 10);
3801                         if (s == p || *s != '.')
3802                                 return 1;
3803                         p = ++s;
3804                         assembly->minor = strtoul (p, &s, 10);
3805                         if (s == p || *s != '.')
3806                                 return 1;
3807                         p = ++s;
3808                         assembly->build = strtoul (p, &s, 10);
3809                         if (s == p || *s != '.')
3810                                 return 1;
3811                         p = ++s;
3812                         assembly->revision = strtoul (p, &s, 10);
3813                         if (s == p)
3814                                 return 1;
3815                 } else if (*p == 'C' && strncmp (p, "Culture=", 8) == 0) {
3816                         p += 8;
3817                         if (strncmp (p, "neutral", 7) == 0) {
3818                                 assembly->culture = "";
3819                                 p += 7;
3820                         } else {
3821                                 assembly->culture = p;
3822                                 while (*p && *p != ',') {
3823                                         p++;
3824                                 }
3825                         }
3826                 } else if (*p == 'P' && strncmp (p, "PublicKeyToken=", 15) == 0) {
3827                         p += 15;
3828                         s = p;
3829                         while (*s && isxdigit (*s)) {
3830                                 *s = tolower (*s);
3831                                 s++;
3832                         }
3833                         assembly->hash_len = s - p;
3834                         if (!(s-p) || ((s-p) & 1))
3835                                 return 1;
3836                         assembly->hash_value = s = p;
3837                         while (*s && isxdigit (*s)) {
3838                                 int val;
3839                                 val = *s >= '0' && *s <= '9'? *s - '0': *s - 'a' + 10;
3840                                 s++;
3841                                 *p = val << 4;
3842                                 *p |= *s >= '0' && *s <= '9'? *s - '0': *s - 'a' + 10;
3843                                 p++;
3844                         }
3845                         p = s;
3846                 } else {
3847                         while (*p && *p != ',')
3848                                 p++;
3849                 }
3850                 found_sep = 0;
3851                 while (*p == ' ' || *p == ',') {
3852                         *p++ = 0;
3853                         found_sep = 1;
3854                         continue;
3855                 }
3856                 /* failed */
3857                 if (!found_sep)
3858                         return 1;
3859         }
3860
3861         return 0;
3862 }
3863
3864 /*
3865  * mono_reflection_parse_type:
3866  * @name: type name
3867  *
3868  * Parse a type name as accepted by the GetType () method and output the info
3869  * extracted in the info structure.
3870  * the name param will be mangled, so, make a copy before passing it to this function.
3871  * The fields in info will be valid until the memory pointed to by name is valid.
3872  * Returns 0 on parse error.
3873  * See also mono_type_get_name () below.
3874  */
3875 int
3876 mono_reflection_parse_type (char *name, MonoTypeNameParse *info) {
3877
3878         char *start, *p, *w, *last_point, *startn;
3879         int in_modifiers = 0;
3880         int isbyref = 0, rank;
3881
3882         start = p = w = name;
3883
3884         memset (&info->assembly, 0, sizeof (MonoAssemblyName));
3885         info->name = info->name_space = NULL;
3886         info->nested = NULL;
3887         info->modifiers = NULL;
3888
3889         /* last_point separates the namespace from the name */
3890         last_point = NULL;
3891
3892         while (*p) {
3893                 switch (*p) {
3894                 case '+':
3895                         *p = 0; /* NULL terminate the name */
3896                         startn = p + 1;
3897                         info->nested = g_list_append (info->nested, startn);
3898                         /* we have parsed the nesting namespace + name */
3899                         if (info->name)
3900                                 break;
3901                         if (last_point) {
3902                                 info->name_space = start;
3903                                 *last_point = 0;
3904                                 info->name = last_point + 1;
3905                         } else {
3906                                 info->name_space = (char *)"";
3907                                 info->name = start;
3908                         }
3909                         break;
3910                 case '.':
3911                         last_point = w;
3912                         break;
3913                 case '\\':
3914                         ++p;
3915                         break;
3916                 case '&':
3917                 case '*':
3918                 case '[':
3919                 case ',':
3920                         in_modifiers = 1;
3921                         break;
3922                 default:
3923                         break;
3924                 }
3925                 if (in_modifiers)
3926                         break;
3927                 *w++ = *p++;
3928         }
3929         
3930         if (!info->name) {
3931                 if (last_point) {
3932                         info->name_space = start;
3933                         *last_point = 0;
3934                         info->name = last_point + 1;
3935                 } else {
3936                         info->name_space = (char *)"";
3937                         info->name = start;
3938                 }
3939         }
3940         while (*p) {
3941                 switch (*p) {
3942                 case '&':
3943                         if (isbyref) /* only one level allowed by the spec */
3944                                 return 0;
3945                         isbyref = 1;
3946                         info->modifiers = g_list_append (info->modifiers, GUINT_TO_POINTER (0));
3947                         *p++ = 0;
3948                         break;
3949                 case '*':
3950                         info->modifiers = g_list_append (info->modifiers, GUINT_TO_POINTER (-1));
3951                         *p++ = 0;
3952                         break;
3953                 case '[':
3954                         rank = 1;
3955                         *p++ = 0;
3956                         while (*p) {
3957                                 if (*p == ']')
3958                                         break;
3959                                 if (*p == ',')
3960                                         rank++;
3961                                 else if (*p != '*') /* '*' means unknown lower bound */
3962                                         return 0;
3963                                 ++p;
3964                         }
3965                         if (*p++ != ']')
3966                                 return 0;
3967                         info->modifiers = g_list_append (info->modifiers, GUINT_TO_POINTER (rank));
3968                         break;
3969                 case ',':
3970                         *p++ = 0;
3971                         while (*p) {
3972                                 if (*p == ' ') {
3973                                         ++p;
3974                                         continue;
3975                                 }
3976                                 break;
3977                         }
3978                         if (!*p)
3979                                 return 0; /* missing assembly name */
3980                         if (!assembly_name_to_aname (&info->assembly, p))
3981                                 return 0;
3982                         break;
3983                 default:
3984                         break;
3985                 }
3986                 if (info->assembly.name)
3987                         break;
3988         }
3989         *w = 0; /* terminate class name */
3990         if (!info->name || !*info->name)
3991                 return 0;
3992         /* add other consistency checks */
3993         return 1;
3994 }
3995
3996 static void
3997 mono_type_get_name_recurse (MonoType *type, GString *str)
3998 {
3999         MonoClass *klass;
4000         
4001         switch (type->type) {
4002         case MONO_TYPE_ARRAY: {
4003                 int i, rank = type->data.array->rank;
4004
4005                 mono_type_get_name_recurse (&type->data.array->eklass->byval_arg, str);
4006                 g_string_append_c (str, '[');
4007                 for (i = 1; i < rank; i++)
4008                         g_string_append_c (str, ',');
4009                 g_string_append_c (str, ']');
4010                 break;
4011         }
4012         case MONO_TYPE_SZARRAY:
4013                 mono_type_get_name_recurse (&type->data.klass->byval_arg, str);
4014                 g_string_append (str, "[]");
4015                 break;
4016         case MONO_TYPE_PTR:
4017                 mono_type_get_name_recurse (type->data.type, str);
4018                 g_string_append_c (str, '*');
4019                 break;
4020         default:
4021                 klass = mono_class_from_mono_type (type);
4022                 if (klass->nested_in) {
4023                         mono_type_get_name_recurse (&klass->nested_in->byval_arg, str);
4024                         g_string_append_c (str, '+');
4025                 }
4026                 if (*klass->name_space) {
4027                         g_string_append (str, klass->name_space);
4028                         g_string_append_c (str, '.');
4029                 }
4030                 g_string_append (str, klass->name);
4031                 break;
4032         }
4033 }
4034
4035 /*
4036  * mono_type_get_name:
4037  * @type: a type
4038  *
4039  * Returns the string representation for type as required by System.Reflection.
4040  * The inverse of mono_reflection_parse_type ().
4041  */
4042 char*
4043 mono_type_get_name (MonoType *type)
4044 {
4045         GString* result = g_string_new ("");
4046         mono_type_get_name_recurse (type, result);
4047
4048         if (type->byref)
4049                 g_string_append_c (result, '&');
4050
4051         return g_string_free (result, FALSE);
4052 }
4053
4054 static MonoType*
4055 mono_reflection_get_type_internal (MonoImage* image, MonoTypeNameParse *info, gboolean ignorecase)
4056 {
4057         MonoClass *klass;
4058         GList *mod;
4059         int modval;
4060         
4061         if (!image)
4062                 image = mono_defaults.corlib;
4063
4064         if (ignorecase)
4065                 klass = mono_class_from_name_case (image, info->name_space, info->name);
4066         else
4067                 klass = mono_class_from_name (image, info->name_space, info->name);
4068         if (!klass)
4069                 return NULL;
4070         for (mod = info->nested; mod; mod = mod->next) {
4071                 GList *nested;
4072
4073                 mono_class_init (klass);
4074                 nested = klass->nested_classes;
4075                 klass = NULL;
4076                 while (nested) {
4077                         klass = nested->data;
4078                         if (ignorecase) {
4079                                 if (g_strcasecmp (klass->name, mod->data) == 0)
4080                                         break;
4081                         } else {
4082                                 if (strcmp (klass->name, mod->data) == 0)
4083                                         break;
4084                         }
4085                         klass = NULL;
4086                         nested = nested->next;
4087                 }
4088                 if (!klass)
4089                         break;
4090         }
4091         if (!klass)
4092                 return NULL;
4093         mono_class_init (klass);
4094         for (mod = info->modifiers; mod; mod = mod->next) {
4095                 modval = GPOINTER_TO_UINT (mod->data);
4096                 if (!modval) { /* byref: must be last modifier */
4097                         return &klass->this_arg;
4098                 } else if (modval == -1) {
4099                         klass = mono_ptr_class_get (&klass->byval_arg);
4100                 } else { /* array rank */
4101                         klass = mono_array_class_get (klass, modval);
4102                 }
4103                 mono_class_init (klass);
4104         }
4105
4106         return &klass->byval_arg;
4107 }
4108
4109 /*
4110  * mono_reflection_get_type:
4111  * @image: a metadata context
4112  * @info: type description structure
4113  * @ignorecase: flag for case-insensitive string compares
4114  *
4115  * Build a MonoType from the type description in @info.
4116  * 
4117  */
4118
4119 MonoType*
4120 mono_reflection_get_type (MonoImage* image, MonoTypeNameParse *info, gboolean ignorecase)
4121 {
4122         MonoType *type;
4123         MonoReflectionAssembly *assembly;
4124         GString *fullName;
4125         GList *mod;
4126
4127         type = mono_reflection_get_type_internal (image, info, ignorecase);
4128         if (type)
4129                 return type;
4130         if (!mono_domain_has_type_resolve (mono_domain_get ()))
4131                 return NULL;
4132         
4133         // Reconstruct the type name
4134         fullName = g_string_new ("");
4135         if (info->name_space && (info->name_space [0] != '\0'))
4136                 g_string_printf (fullName, "%s.%s", info->name_space, info->name);
4137         else
4138                 g_string_printf (fullName, info->name);
4139         for (mod = info->nested; mod; mod = mod->next)
4140                 g_string_append_printf (fullName, "+%s", (char*)mod->data);
4141
4142         assembly = 
4143                 mono_domain_try_type_resolve (
4144                         mono_domain_get (), fullName->str, NULL);
4145         if (assembly && (!image || (assembly->assembly->image == image)))
4146                 type = mono_reflection_get_type_internal (assembly->assembly->image, 
4147                                                                                  info, ignorecase);
4148         g_string_free (fullName, TRUE);
4149         return type;
4150 }
4151
4152 /*
4153  * mono_reflection_type_from_name:
4154  * @name: type name.
4155  * @image: a metadata context (can be NULL).
4156  *
4157  * Retrieves a MonoType from its @name. If the name is not fully qualified,
4158  * it defaults to get the type from @image or, if @image is NULL or loading
4159  * from it fails, uses corlib.
4160  * 
4161  */
4162 MonoType*
4163 mono_reflection_type_from_name (char *name, MonoImage *image)
4164 {
4165         MonoType *type;
4166         MonoTypeNameParse info;
4167         
4168         /*g_print ("requested type %s\n", str);*/
4169         if (!mono_reflection_parse_type (name, &info)) {
4170                 g_list_free (info.modifiers);
4171                 g_list_free (info.nested);
4172                 return NULL;
4173         }
4174
4175         if (info.assembly.name) {
4176                 image = mono_image_loaded (info.assembly.name);
4177                 /* do we need to load if it's not already loaded? */
4178                 if (!image) {
4179                         g_list_free (info.modifiers);
4180                         g_list_free (info.nested);
4181                         return NULL;
4182                 }
4183         } else if (image == NULL) {
4184                 image = mono_defaults.corlib;
4185         }
4186
4187         type = mono_reflection_get_type (image, &info, FALSE);
4188         if (type == NULL && !info.assembly.name && image != mono_defaults.corlib) {
4189                 image = mono_defaults.corlib;
4190                 type = mono_reflection_get_type (image, &info, FALSE);
4191         }
4192         
4193         g_list_free (info.modifiers);
4194         g_list_free (info.nested);
4195         return type;
4196 }
4197
4198 static void*
4199 load_cattr_value (MonoImage *image, MonoType *t, const char *p, const char **end)
4200 {
4201         int slen, type = t->type;
4202 handle_enum:
4203         switch (type) {
4204         case MONO_TYPE_U1:
4205         case MONO_TYPE_I1:
4206         case MONO_TYPE_BOOLEAN: {
4207                 MonoBoolean *bval = g_malloc (sizeof (MonoBoolean));
4208                 *bval = *p;
4209                 *end = p + 1;
4210                 return bval;
4211         }
4212         case MONO_TYPE_CHAR:
4213         case MONO_TYPE_U2:
4214         case MONO_TYPE_I2: {
4215                 guint16 *val = g_malloc (sizeof (guint16));
4216                 *val = read16 (p);
4217                 *end = p + 2;
4218                 return val;
4219         }
4220 #if SIZEOF_VOID_P == 4
4221         case MONO_TYPE_U:
4222         case MONO_TYPE_I:
4223 #endif
4224         case MONO_TYPE_R4:
4225         case MONO_TYPE_U4:
4226         case MONO_TYPE_I4: {
4227                 guint32 *val = g_malloc (sizeof (guint32));
4228                 *val = read32 (p);
4229                 *end = p + 4;
4230                 return val;
4231         }
4232 #if SIZEOF_VOID_P == 8
4233         case MONO_TYPE_U: /* error out instead? this should probably not happen */
4234         case MONO_TYPE_I:
4235 #endif
4236         case MONO_TYPE_R8:
4237         case MONO_TYPE_U8:
4238         case MONO_TYPE_I8: {
4239                 guint64 *val = g_malloc (sizeof (guint64));
4240                 *val = read64 (p);
4241                 *end = p + 8;
4242                 return val;
4243         }
4244         case MONO_TYPE_VALUETYPE:
4245                 if (t->data.klass->enumtype) {
4246                         type = t->data.klass->enum_basetype->type;
4247                         goto handle_enum;
4248                 } else {
4249                         g_error ("generic valutype %s not handled in custom attr value decoding", t->data.klass->name);
4250                 }
4251                 break;
4252         case MONO_TYPE_STRING:
4253                 if (*p == (char)0xFF) {
4254                         *end = p + 1;
4255                         return NULL;
4256                 }
4257                 slen = mono_metadata_decode_value (p, &p);
4258                 *end = p + slen;
4259                 return mono_string_new_len (mono_domain_get (), p, slen);
4260         case MONO_TYPE_CLASS: {
4261                 char *n;
4262                 MonoType *t;
4263                 if (*p == (char)0xFF) {
4264                         *end = p + 1;
4265                         return NULL;
4266                 }
4267 handle_type:
4268                 slen = mono_metadata_decode_value (p, &p);
4269                 n = g_memdup (p, slen + 1);
4270                 n [slen] = 0;
4271                 t = mono_reflection_type_from_name (n, image);
4272                 if (!t)
4273                         g_warning ("Cannot load type '%s'", n);
4274                 g_free (n);
4275                 *end = p + slen;
4276                 return mono_type_get_object (mono_domain_get (), t);
4277         }
4278         case MONO_TYPE_OBJECT: {
4279                 char subt = *p++;
4280                 MonoObject *obj;
4281                 MonoClass *subc;
4282                 void *val;
4283
4284                 if (subt == 0x50) {
4285                         goto handle_type;
4286                 } else if (subt == 0x0E) {
4287                         type = MONO_TYPE_STRING;
4288                         goto handle_enum;
4289                 } else if (subt == 0x55) {
4290                         char *n;
4291                         MonoType *t;
4292                         slen = mono_metadata_decode_value (p, &p);
4293                         n = g_memdup (p, slen + 1);
4294                         n [slen] = 0;
4295                         t = mono_reflection_type_from_name (n, image);
4296                         if (!t)
4297                                 g_warning ("Cannot load type '%s'", n);
4298                         g_free (n);
4299                         p += slen;
4300                         subc = mono_class_from_mono_type (t);
4301                 } else if (subt >= MONO_TYPE_BOOLEAN && subt <= MONO_TYPE_R8) {
4302                         MonoType simple_type = {{0}};
4303                         simple_type.type = subt;
4304                         subc = mono_class_from_mono_type (&simple_type);
4305                 } else {
4306                         g_error ("Unknown type 0x%02x for object type encoding in custom attr", subt);
4307                 }
4308                 val = load_cattr_value (image, &subc->byval_arg, p, end);
4309                 obj = mono_object_new (mono_domain_get (), subc);
4310                 memcpy ((char*)obj + sizeof (MonoObject), val, mono_class_value_size (subc, NULL));
4311                 g_free (val);
4312                 return obj;
4313         }
4314         case MONO_TYPE_SZARRAY:
4315         {
4316                 MonoArray *arr;
4317                 guint32 i, alen, basetype;
4318                 alen = read32 (p);
4319                 p += 4;
4320                 if (alen == 0xffffffff) {
4321                         *end = p;
4322                         return NULL;
4323                 }
4324                 arr = mono_array_new (mono_domain_get(), t->data.klass, alen);
4325                 basetype = t->data.klass->byval_arg.type;
4326                 switch (basetype)
4327                 {
4328                         case MONO_TYPE_U1:
4329                         case MONO_TYPE_I1:
4330                         case MONO_TYPE_BOOLEAN:
4331                                 for (i=0;i<alen;i++)
4332                                 {
4333                                         MonoBoolean val=*p++;
4334                                         mono_array_set(arr,MonoBoolean,i,val);
4335                                 }
4336                                 break;
4337                         case MONO_TYPE_CHAR:
4338                         case MONO_TYPE_U2:
4339                         case MONO_TYPE_I2:
4340                                 for (i=0;i<alen;i++)
4341                                 {
4342                                         guint16 val=read16(p);
4343                                         mono_array_set(arr,guint16,i,val);
4344                                         p+=2;
4345                                 }
4346                                 break;
4347                         case MONO_TYPE_R4:
4348                         case MONO_TYPE_U4:
4349                         case MONO_TYPE_I4:
4350                                 for (i=0;i<alen;i++)
4351                                 {
4352                                         guint32 val=read32(p);
4353                                         mono_array_set(arr,guint32,i,val);
4354                                         p+=4;
4355                                 }
4356                                 break;
4357                         case MONO_TYPE_R8:
4358                         case MONO_TYPE_U8:
4359                         case MONO_TYPE_I8:
4360                                 for (i=0;i<alen;i++)
4361                                 {
4362                                         guint64 val=read64(p);
4363                                         mono_array_set(arr,guint64,i,val);
4364                                         p+=8;
4365                                 }
4366                                 break;
4367                         case MONO_TYPE_CLASS:
4368                         case MONO_TYPE_STRING:
4369                                 for (i = 0; i < alen; i++) {
4370                                         MonoObject *item = load_cattr_value (image, &t->data.klass->byval_arg, p, &p);
4371                                         mono_array_set (arr, gpointer, i, item);
4372                                 }
4373                                 break;
4374                         default:
4375                                 g_error("Type 0x%02x not handled in custom attr array decoding",t->data.type->type);
4376                 }
4377                 *end=p;
4378                 return arr;
4379         }
4380         default:
4381                 g_error ("Type 0x%02x not handled in custom attr value decoding", type);
4382         }
4383         return NULL;
4384 }
4385
4386 static gboolean
4387 type_is_reference (MonoType *type)
4388 {
4389         switch (type->type) {
4390         case MONO_TYPE_BOOLEAN:
4391         case MONO_TYPE_CHAR:
4392         case MONO_TYPE_U:
4393         case MONO_TYPE_I:
4394         case MONO_TYPE_U1:
4395         case MONO_TYPE_I1:
4396         case MONO_TYPE_U2:
4397         case MONO_TYPE_I2:
4398         case MONO_TYPE_U4:
4399         case MONO_TYPE_I4:
4400         case MONO_TYPE_U8:
4401         case MONO_TYPE_I8:
4402         case MONO_TYPE_R8:
4403         case MONO_TYPE_R4:
4404         case MONO_TYPE_VALUETYPE:
4405                 return FALSE;
4406         default:
4407                 return TRUE;
4408         }
4409 }
4410
4411 static void
4412 free_param_data (MonoMethodSignature *sig, void **params) {
4413         int i;
4414         for (i = 0; i < sig->param_count; ++i) {
4415                 if (!type_is_reference (sig->params [i]))
4416                         g_free (params [i]);
4417         }
4418 }
4419
4420 /*
4421  * Find the method index in the metadata methodDef table.
4422  * Later put these three helper methods in metadata and export them.
4423  */
4424 static guint32
4425 find_method_index (MonoMethod *method) {
4426         MonoClass *klass = method->klass;
4427         int i;
4428
4429         for (i = 0; i < klass->method.count; ++i) {
4430                 if (method == klass->methods [i])
4431                         return klass->method.first + 1 + i;
4432         }
4433         return 0;
4434 }
4435
4436 /*
4437  * Find the field index in the metadata FieldDef table.
4438  */
4439 static guint32
4440 find_field_index (MonoClass *klass, MonoClassField *field) {
4441         int i;
4442
4443         for (i = 0; i < klass->field.count; ++i) {
4444                 if (field == &klass->fields [i])
4445                         return klass->field.first + 1 + i;
4446         }
4447         return 0;
4448 }
4449
4450 /*
4451  * Find the property index in the metadata Property table.
4452  */
4453 static guint32
4454 find_property_index (MonoClass *klass, MonoProperty *property) {
4455         int i;
4456
4457         for (i = 0; i < klass->property.count; ++i) {
4458                 if (property == &klass->properties [i])
4459                         return klass->property.first + 1 + i;
4460         }
4461         return 0;
4462 }
4463
4464 /*
4465  * Find the event index in the metadata Event table.
4466  */
4467 static guint32
4468 find_event_index (MonoClass *klass, MonoEvent *event) {
4469         int i;
4470
4471         for (i = 0; i < klass->event.count; ++i) {
4472                 if (event == &klass->events [i])
4473                         return klass->event.first + 1 + i;
4474         }
4475         return 0;
4476 }
4477
4478 static MonoObject*
4479 create_custom_attr (MonoImage *image, MonoMethod *method, 
4480                                         const char *data, guint32 len)
4481 {
4482         const char *p = data;
4483         const char *named;
4484         guint32 i, j, num_named;
4485         MonoObject *attr;
4486         void **params;
4487
4488         if (len < 2 || read16 (p) != 0x0001) /* Prolog */
4489                 return NULL;
4490
4491         mono_class_init (method->klass);
4492         /*g_print ("got attr %s\n", method->klass->name);*/
4493         
4494         params = g_new (void*, method->signature->param_count);
4495
4496         /* skip prolog */
4497         p += 2;
4498         for (i = 0; i < method->signature->param_count; ++i) {
4499                 params [i] = load_cattr_value (image, method->signature->params [i], p, &p);
4500         }
4501
4502         named = p;
4503         attr = mono_object_new (mono_domain_get (), method->klass);
4504         mono_runtime_invoke (method, attr, params, NULL);
4505         free_param_data (method->signature, params);
4506         g_free (params);
4507         num_named = read16 (named);
4508         named += 2;
4509         for (j = 0; j < num_named; j++) {
4510                 gint name_len;
4511                 char *name, named_type, data_type;
4512                 named_type = *named++;
4513                 data_type = *named++; /* type of data */
4514                 if (data_type == 0x55) {
4515                         gint type_len;
4516                         char *type_name;
4517                         type_len = mono_metadata_decode_blob_size (named, &named);
4518                         type_name = g_malloc (type_len + 1);
4519                         memcpy (type_name, named, type_len);
4520                         type_name [type_len] = 0;
4521                         named += type_len;
4522                         /* FIXME: lookup the type and check type consistency */
4523                 }
4524                 name_len = mono_metadata_decode_blob_size (named, &named);
4525                 name = g_malloc (name_len + 1);
4526                 memcpy (name, named, name_len);
4527                 name [name_len] = 0;
4528                 named += name_len;
4529                 if (named_type == 0x53) {
4530                         MonoClassField *field = mono_class_get_field_from_name (mono_object_class (attr), name);
4531                         void *val = load_cattr_value (image, field->type, named, &named);
4532                                 mono_field_set_value (attr, field, val);
4533                                 if (!type_is_reference (field->type))
4534                                         g_free (val);
4535                 } else if (named_type == 0x54) {
4536                         MonoProperty *prop;
4537                         void *pparams [1];
4538                         MonoType *prop_type;
4539
4540                         prop = mono_class_get_property_from_name (mono_object_class (attr), name);
4541                         /* can we have more that 1 arg in a custom attr named property? */
4542                         prop_type = prop->get? prop->get->signature->ret: prop->set->signature->params [prop->set->signature->param_count - 1];
4543                         pparams [0] = load_cattr_value (image, prop_type, named, &named);
4544                         mono_property_set_value (prop, attr, pparams, NULL);
4545                         if (!type_is_reference (prop_type))
4546                                 g_free (pparams [0]);
4547                 }
4548                 g_free (name);
4549         }
4550
4551         return attr;
4552 }
4553
4554 MonoArray*
4555 mono_custom_attrs_construct (MonoCustomAttrInfo *cinfo)
4556 {
4557         MonoArray *result;
4558         MonoClass *klass;
4559         MonoObject *attr;
4560         int i;
4561
4562         klass = mono_class_from_name (mono_defaults.corlib, "System", "Attribute");
4563         result = mono_array_new (mono_domain_get (), klass, cinfo->num_attrs);
4564         for (i = 0; i < cinfo->num_attrs; ++i) {
4565                 attr = create_custom_attr (cinfo->image, cinfo->attrs [i].ctor, cinfo->attrs [i].data, cinfo->attrs [i].data_size);
4566                 mono_array_set (result, gpointer, i, attr);
4567         }
4568         return result;
4569 }
4570
4571 MonoCustomAttrInfo*
4572 mono_custom_attrs_from_index (MonoImage *image, guint32 idx)
4573 {
4574         guint32 mtoken, i, len;
4575         guint32 cols [MONO_CUSTOM_ATTR_SIZE];
4576         MonoTableInfo *ca;
4577         MonoCustomAttrInfo *ainfo;
4578         GList *tmp, *list = NULL;
4579         const char *data;
4580         
4581         ca = &image->tables [MONO_TABLE_CUSTOMATTRIBUTE];
4582         /* the table is not sorted */
4583         for (i = 0; i < ca->rows; ++i) {
4584                 if (mono_metadata_decode_row_col (ca, i, MONO_CUSTOM_ATTR_PARENT) != idx)
4585                         continue;
4586                 list = g_list_prepend (list, GUINT_TO_POINTER (i));
4587         }
4588         len = g_list_length (list);
4589         if (!len)
4590                 return NULL;
4591         ainfo = g_malloc0 (sizeof (MonoCustomAttrInfo) + sizeof (MonoCustomAttrEntry) * (len - MONO_ZERO_LEN_ARRAY));
4592         ainfo->num_attrs = len;
4593         ainfo->image = image;
4594         for (i = 0, tmp = list; i < len; ++i, tmp = tmp->next) {
4595                 mono_metadata_decode_row (ca, GPOINTER_TO_UINT (tmp->data), cols, MONO_CUSTOM_ATTR_SIZE);
4596                 mtoken = cols [MONO_CUSTOM_ATTR_TYPE] >> CUSTOM_ATTR_TYPE_BITS;
4597                 switch (cols [MONO_CUSTOM_ATTR_TYPE] & CUSTOM_ATTR_TYPE_MASK) {
4598                 case CUSTOM_ATTR_TYPE_METHODDEF:
4599                         mtoken |= MONO_TOKEN_METHOD_DEF;
4600                         break;
4601                 case CUSTOM_ATTR_TYPE_MEMBERREF:
4602                         mtoken |= MONO_TOKEN_MEMBER_REF;
4603                         break;
4604                 default:
4605                         g_error ("Unknown table for custom attr type %08x", cols [MONO_CUSTOM_ATTR_TYPE]);
4606                         break;
4607                 }
4608                 ainfo->attrs [i].ctor = mono_get_method (image, mtoken, NULL);
4609                 if (!ainfo->attrs [i].ctor)
4610                         g_error ("Can't find custom attr constructor image: %s mtoken: 0x%08x", image->name, mtoken);
4611                 data = mono_metadata_blob_heap (image, cols [MONO_CUSTOM_ATTR_VALUE]);
4612                 ainfo->attrs [i].data_size = mono_metadata_decode_value (data, &data);
4613                 ainfo->attrs [i].data = data;
4614         }
4615         g_list_free (list);
4616
4617         return ainfo;
4618 }
4619
4620 MonoCustomAttrInfo*
4621 mono_custom_attrs_from_method (MonoMethod *method)
4622 {
4623         MonoCustomAttrInfo *cinfo;
4624         guint32 idx;
4625         
4626         if (dynamic_custom_attrs && (cinfo = g_hash_table_lookup (dynamic_custom_attrs, method)))
4627                 return cinfo;
4628         idx = find_method_index (method);
4629         idx <<= CUSTOM_ATTR_BITS;
4630         idx |= CUSTOM_ATTR_METHODDEF;
4631         return mono_custom_attrs_from_index (method->klass->image, idx);
4632 }
4633
4634 MonoCustomAttrInfo*
4635 mono_custom_attrs_from_class (MonoClass *klass)
4636 {
4637         MonoCustomAttrInfo *cinfo;
4638         guint32 idx;
4639         
4640         if (dynamic_custom_attrs && (cinfo = g_hash_table_lookup (dynamic_custom_attrs, klass)))
4641                 return cinfo;
4642         idx = mono_metadata_token_index (klass->type_token);
4643         idx <<= CUSTOM_ATTR_BITS;
4644         idx |= CUSTOM_ATTR_TYPEDEF;
4645         return mono_custom_attrs_from_index (klass->image, idx);
4646 }
4647
4648 MonoCustomAttrInfo*
4649 mono_custom_attrs_from_assembly (MonoAssembly *assembly)
4650 {
4651         MonoCustomAttrInfo *cinfo;
4652         guint32 idx;
4653         
4654         if (dynamic_custom_attrs && (cinfo = g_hash_table_lookup (dynamic_custom_attrs, assembly)))
4655                 return cinfo;
4656         idx = 1; /* there is only one assembly */
4657         idx <<= CUSTOM_ATTR_BITS;
4658         idx |= CUSTOM_ATTR_ASSEMBLY;
4659         return mono_custom_attrs_from_index (assembly->image, idx);
4660 }
4661
4662 MonoCustomAttrInfo*
4663 mono_custom_attrs_from_property (MonoClass *klass, MonoProperty *property)
4664 {
4665         MonoCustomAttrInfo *cinfo;
4666         guint32 idx;
4667         
4668         if (dynamic_custom_attrs && (cinfo = g_hash_table_lookup (dynamic_custom_attrs, property)))
4669                 return cinfo;
4670         idx = find_property_index (klass, property);
4671         idx <<= CUSTOM_ATTR_BITS;
4672         idx |= CUSTOM_ATTR_PROPERTY;
4673         return mono_custom_attrs_from_index (klass->image, idx);
4674 }
4675
4676 MonoCustomAttrInfo*
4677 mono_custom_attrs_from_event (MonoClass *klass, MonoEvent *event)
4678 {
4679         MonoCustomAttrInfo *cinfo;
4680         guint32 idx;
4681         
4682         if (dynamic_custom_attrs && (cinfo = g_hash_table_lookup (dynamic_custom_attrs, event)))
4683                 return cinfo;
4684         idx = find_event_index (klass, event);
4685         idx <<= CUSTOM_ATTR_BITS;
4686         idx |= CUSTOM_ATTR_EVENT;
4687         return mono_custom_attrs_from_index (klass->image, idx);
4688 }
4689
4690 MonoCustomAttrInfo*
4691 mono_custom_attrs_from_field (MonoClass *klass, MonoClassField *field)
4692 {
4693         MonoCustomAttrInfo *cinfo;
4694         guint32 idx;
4695         
4696         if (dynamic_custom_attrs && (cinfo = g_hash_table_lookup (dynamic_custom_attrs, field)))
4697                 return cinfo;
4698         idx = find_field_index (klass, field);
4699         idx <<= CUSTOM_ATTR_BITS;
4700         idx |= CUSTOM_ATTR_FIELDDEF;
4701         return mono_custom_attrs_from_index (klass->image, idx);
4702 }
4703
4704 MonoCustomAttrInfo*
4705 mono_custom_attrs_from_param (MonoMethod *method, guint32 param)
4706 {
4707         MonoTableInfo *ca;
4708         guint32 i, idx, method_index;
4709         guint32 param_list, param_last, param_pos, found;
4710         MonoImage *image;
4711         
4712         /* FIXME: handle dynamic custom attrs for parameters */
4713         /*if (dynamic_custom_attrs && (cinfo = g_hash_table_lookup (dynamic_custom_attrs, field)))
4714                 return cinfo;*/
4715         image = method->klass->image;
4716         method_index = find_method_index (method);
4717         ca = &image->tables [MONO_TABLE_METHOD];
4718
4719         param_list = mono_metadata_decode_row_col (ca, method_index - 1, MONO_METHOD_PARAMLIST);
4720         if (method_index == ca->rows) {
4721                 ca = &image->tables [MONO_TABLE_PARAM];
4722                 param_last = ca->rows + 1;
4723         } else {
4724                 param_last = mono_metadata_decode_row_col (ca, method_index, MONO_METHOD_PARAMLIST);
4725                 ca = &image->tables [MONO_TABLE_PARAM];
4726         }
4727         found = FALSE;
4728         for (i = param_list; i < param_last; ++i) {
4729                 param_pos = mono_metadata_decode_row_col (ca, i - 1, MONO_PARAM_SEQUENCE);
4730                 if (param_pos == param) {
4731                         found = TRUE;
4732                         break;
4733                 }
4734         }
4735         if (!found)
4736                 return NULL;
4737         idx = i;
4738         idx <<= CUSTOM_ATTR_BITS;
4739         idx |= CUSTOM_ATTR_PARAMDEF;
4740         return mono_custom_attrs_from_index (image, idx);
4741 }
4742
4743 /*
4744  * mono_reflection_get_custom_attrs:
4745  * @obj: a reflection object handle
4746  *
4747  * Return an array with all the custom attributes defined of the
4748  * reflection handle @obj. The objects are fully build.
4749  */
4750 MonoArray*
4751 mono_reflection_get_custom_attrs (MonoObject *obj)
4752 {
4753         MonoClass *klass;
4754         MonoArray *result;
4755         MonoCustomAttrInfo *cinfo;
4756         
4757         MONO_ARCH_SAVE_REGS;
4758
4759         klass = obj->vtable->klass;
4760         /* FIXME: need to handle: Module */
4761         if (klass == mono_defaults.monotype_class) {
4762                 MonoReflectionType *rtype = (MonoReflectionType*)obj;
4763                 klass = mono_class_from_mono_type (rtype->type);
4764                 cinfo = mono_custom_attrs_from_class (klass);
4765         } else if (strcmp ("Assembly", klass->name) == 0) {
4766                 MonoReflectionAssembly *rassembly = (MonoReflectionAssembly*)obj;
4767                 cinfo = mono_custom_attrs_from_assembly (rassembly->assembly);
4768         } else if (strcmp ("MonoProperty", klass->name) == 0) {
4769                 MonoReflectionProperty *rprop = (MonoReflectionProperty*)obj;
4770                 cinfo = mono_custom_attrs_from_property (rprop->klass, rprop->property);
4771         } else if (strcmp ("MonoEvent", klass->name) == 0) {
4772                 MonoReflectionEvent *revent = (MonoReflectionEvent*)obj;
4773                 cinfo = mono_custom_attrs_from_event (revent->klass, revent->event);
4774         } else if (strcmp ("MonoField", klass->name) == 0) {
4775                 MonoReflectionField *rfield = (MonoReflectionField*)obj;
4776                 cinfo = mono_custom_attrs_from_field (rfield->klass, rfield->field);
4777         } else if ((strcmp ("MonoMethod", klass->name) == 0) || (strcmp ("MonoCMethod", klass->name) == 0)) {
4778                 MonoReflectionMethod *rmethod = (MonoReflectionMethod*)obj;
4779                 cinfo = mono_custom_attrs_from_method (rmethod->method);
4780         } else if (strcmp ("ParameterInfo", klass->name) == 0) {
4781                 MonoReflectionParameter *param = (MonoReflectionParameter*)obj;
4782                 MonoReflectionMethod *rmethod = (MonoReflectionMethod*)param->MemberImpl;
4783                 cinfo = mono_custom_attrs_from_param (rmethod->method, param->PositionImpl + 1);
4784         } else if (strcmp ("AssemblyBuilder", klass->name) == 0) {
4785                 MonoReflectionAssemblyBuilder *assemblyb = (MonoReflectionAssemblyBuilder*)obj;
4786                 cinfo = mono_custom_attrs_from_builders (assemblyb->assembly.assembly->image, assemblyb->cattrs);
4787         } else { /* handle other types here... */
4788                 g_error ("get custom attrs not yet supported for %s", klass->name);
4789         }
4790
4791         if (cinfo) {
4792                 result = mono_custom_attrs_construct (cinfo);
4793         } else {
4794                 klass = mono_class_from_name (mono_defaults.corlib, "System", "Attribute");
4795                 result = mono_array_new (mono_domain_get (), klass, 0);
4796         }
4797
4798         return result;
4799 }
4800
4801 static MonoMethodSignature*
4802 parameters_to_signature (MonoArray *parameters) {
4803         MonoMethodSignature *sig;
4804         int count, i;
4805
4806         count = parameters? mono_array_length (parameters): 0;
4807
4808         sig = g_malloc0 (sizeof (MonoMethodSignature) + sizeof (MonoType*) * count);
4809         sig->param_count = count;
4810         sig->sentinelpos = -1; /* FIXME */
4811         for (i = 0; i < count; ++i) {
4812                 MonoReflectionType *pt = mono_array_get (parameters, MonoReflectionType*, i);
4813                 sig->params [i] = pt->type;
4814         }
4815         return sig;
4816 }
4817
4818 static MonoMethodSignature*
4819 ctor_builder_to_signature (MonoReflectionCtorBuilder *ctor) {
4820         MonoMethodSignature *sig;
4821
4822         sig = parameters_to_signature (ctor->parameters);
4823         sig->hasthis = ctor->attrs & METHOD_ATTRIBUTE_STATIC? 0: 1;
4824         sig->ret = &mono_defaults.void_class->byval_arg;
4825         return sig;
4826 }
4827
4828 static MonoMethodSignature*
4829 method_builder_to_signature (MonoReflectionMethodBuilder *method) {
4830         MonoMethodSignature *sig;
4831
4832         sig = parameters_to_signature (method->parameters);
4833         sig->hasthis = method->attrs & METHOD_ATTRIBUTE_STATIC? 0: 1;
4834         sig->ret = method->rtype? method->rtype->type: &mono_defaults.void_class->byval_arg;
4835         return sig;
4836 }
4837
4838 static void
4839 get_prop_name_and_type (MonoObject *prop, char **name, MonoType **type)
4840 {
4841         MonoClass *klass = mono_object_class (prop);
4842         if (strcmp (klass->name, "PropertyBuilder") == 0) {
4843                 MonoReflectionPropertyBuilder *pb = (MonoReflectionPropertyBuilder *)prop;
4844                 *name = mono_string_to_utf8 (pb->name);
4845                 *type = pb->type->type;
4846         } else {
4847                 MonoReflectionProperty *p = (MonoReflectionProperty *)prop;
4848                 *name = g_strdup (p->property->name);
4849                 if (p->property->get)
4850                         *type = p->property->get->signature->ret;
4851                 else
4852                         *type = p->property->set->signature->params [p->property->set->signature->param_count - 1];
4853         }
4854 }
4855
4856 static void
4857 get_field_name_and_type (MonoObject *field, char **name, MonoType **type)
4858 {
4859         MonoClass *klass = mono_object_class (field);
4860         if (strcmp (klass->name, "FieldBuilder") == 0) {
4861                 MonoReflectionFieldBuilder *fb = (MonoReflectionFieldBuilder *)field;
4862                 *name = mono_string_to_utf8 (fb->name);
4863                 *type = fb->type->type;
4864         } else {
4865                 MonoReflectionField *f = (MonoReflectionField *)field;
4866                 *name = g_strdup (f->field->name);
4867                 *type = f->field->type;
4868         }
4869 }
4870
4871 static char*
4872 type_get_qualified_name (MonoType *type, MonoAssembly *ass) {
4873         char *name, *result;
4874         MonoClass *klass;
4875         MonoAssembly *ta;
4876
4877         name = mono_type_get_name (type);
4878         klass = my_mono_class_from_mono_type (type);
4879         ta = klass->image->assembly;
4880         if (ta == ass || klass->image == mono_defaults.corlib)
4881                 return name;
4882
4883         /* missing public key */
4884         result = g_strdup_printf ("%s, %s, Version=%d.%d.%d.%d, Culture=%s",
4885                 name, ta->aname.name,
4886                 ta->aname.major, ta->aname.minor, ta->aname.build, ta->aname.revision,
4887                 ta->aname.culture && *ta->aname.culture? ta->aname.culture: "neutral");
4888         g_free (name);
4889         return result;
4890 }
4891
4892 static void
4893 encode_cattr_value (char *buffer, char *p, char **retbuffer, char **retp, guint32 *buflen, MonoType *type, MonoObject *arg)
4894 {
4895         char *argval;
4896         MonoTypeEnum simple_type;
4897         
4898         if ((p-buffer) + 10 >= *buflen) {
4899                 char *newbuf;
4900                 *buflen *= 2;
4901                 newbuf = g_realloc (buffer, *buflen);
4902                 p = newbuf + (p-buffer);
4903                 buffer = newbuf;
4904         }
4905         argval = ((char*)arg + sizeof (MonoObject));
4906         simple_type = type->type;
4907 handle_enum:
4908         switch (simple_type) {
4909         case MONO_TYPE_BOOLEAN:
4910         case MONO_TYPE_U1:
4911         case MONO_TYPE_I1:
4912                 *p++ = *argval;
4913                 break;
4914         case MONO_TYPE_CHAR:
4915         case MONO_TYPE_U2:
4916         case MONO_TYPE_I2:
4917                 swap_with_size (p, argval, 2, 1);
4918                 p += 2;
4919                 break;
4920         case MONO_TYPE_U4:
4921         case MONO_TYPE_I4:
4922         case MONO_TYPE_R4:
4923                 swap_with_size (p, argval, 4, 1);
4924                 p += 4;
4925                 break;
4926         case MONO_TYPE_U8:
4927         case MONO_TYPE_I8:
4928         case MONO_TYPE_R8:
4929                 swap_with_size (p, argval, 8, 1);
4930                 p += 8;
4931                 break;
4932         case MONO_TYPE_VALUETYPE:
4933                 if (type->data.klass->enumtype) {
4934                         simple_type = type->data.klass->enum_basetype->type;
4935                         goto handle_enum;
4936                 } else {
4937                         g_warning ("generic valutype %s not handled in custom attr value decoding", type->data.klass->name);
4938                 }
4939                 break;
4940         case MONO_TYPE_STRING: {
4941                 char *str;
4942                 guint32 slen;
4943                 if (!arg) {
4944                         *p++ = 0xFF;
4945                         break;
4946                 }
4947                 str = mono_string_to_utf8 ((MonoString*)arg);
4948                 slen = strlen (str);
4949                 if ((p-buffer) + 10 + slen >= *buflen) {
4950                         char *newbuf;
4951                         *buflen *= 2;
4952                         *buflen += slen;
4953                         newbuf = g_realloc (buffer, *buflen);
4954                         p = newbuf + (p-buffer);
4955                         buffer = newbuf;
4956                 }
4957                 mono_metadata_encode_value (slen, p, &p);
4958                 memcpy (p, str, slen);
4959                 p += slen;
4960                 g_free (str);
4961                 break;
4962         }
4963         case MONO_TYPE_CLASS: {
4964                 char *str;
4965                 guint32 slen;
4966                 MonoClass *k;
4967                 if (!arg) {
4968                         *p++ = 0xFF;
4969                         break;
4970                 }
4971                 k = mono_object_class (arg);
4972                 if (!mono_object_isinst (arg, mono_defaults.monotype_class) &&
4973                                 (strcmp (k->name, "TypeBuilder") || strcmp (k->name_space, "System.Reflection.Emit")))
4974                         g_error ("only types allowed, not %s.%s", k->name_space, k->name);
4975 handle_type:
4976                 str = type_get_qualified_name (((MonoReflectionType*)arg)->type, NULL);
4977                 slen = strlen (str);
4978                 if ((p-buffer) + 10 + slen >= *buflen) {
4979                         char *newbuf;
4980                         *buflen *= 2;
4981                         *buflen += slen;
4982                         newbuf = g_realloc (buffer, *buflen);
4983                         p = newbuf + (p-buffer);
4984                         buffer = newbuf;
4985                 }
4986                 mono_metadata_encode_value (slen, p, &p);
4987                 memcpy (p, str, slen);
4988                 p += slen;
4989                 g_free (str);
4990                 break;
4991         }
4992         case MONO_TYPE_SZARRAY: {
4993                 int len, i;
4994                 MonoClass *eclass;
4995
4996                 if (!arg) {
4997                         *p++ = 0xff; *p++ = 0xff; *p++ = 0xff; *p++ = 0xff;
4998                         break;
4999                 }
5000                 len = mono_array_length ((MonoArray*)arg);
5001                 *p++ = len & 0xff;
5002                 *p++ = (len >> 8) & 0xff;
5003                 *p++ = (len >> 16) & 0xff;
5004                 *p++ = (len >> 24) & 0xff;
5005                 *retp = p;
5006                 *retbuffer = buffer;
5007                 eclass = type->data.klass;
5008                 for (i = 0; i < len; ++i) {
5009                         encode_cattr_value (buffer, p, &buffer, &p, buflen, &eclass->byval_arg, mono_array_get ((MonoArray*)arg, MonoObject*, i));
5010                 }
5011                 break;
5012         }
5013         /* it may be a boxed value or a Type */
5014         case MONO_TYPE_OBJECT: {
5015                 MonoClass *klass = mono_object_class (arg);
5016                 char *str;
5017                 guint32 slen;
5018                 
5019                 if (mono_object_isinst (arg, mono_defaults.monotype_class)) {
5020                         *p++ = 0x50;
5021                         goto handle_type;
5022                 } else if (klass->enumtype) {
5023                         *p++ = 0x55;
5024                 } else if (klass == mono_defaults.string_class) {
5025                         simple_type = MONO_TYPE_STRING;
5026                         *p++ = 0x0E;
5027                         goto handle_enum;
5028                 } else if (klass->byval_arg.type >= MONO_TYPE_BOOLEAN && klass->byval_arg.type <= MONO_TYPE_R8) {
5029                         *p++ = simple_type = klass->byval_arg.type;
5030                         goto handle_enum;
5031                 } else {
5032                         g_error ("unhandled type in custom attr");
5033                 }
5034                 str = type_get_qualified_name (klass->enum_basetype, NULL);
5035                 slen = strlen (str);
5036                 if ((p-buffer) + 10 + slen >= *buflen) {
5037                         char *newbuf;
5038                         *buflen *= 2;
5039                         *buflen += slen;
5040                         newbuf = g_realloc (buffer, *buflen);
5041                         p = newbuf + (p-buffer);
5042                         buffer = newbuf;
5043                 }
5044                 mono_metadata_encode_value (slen, p, &p);
5045                 memcpy (p, str, slen);
5046                 p += slen;
5047                 g_free (str);
5048                 simple_type = klass->enum_basetype->type;
5049                 goto handle_enum;
5050         }
5051         default:
5052                 g_error ("type 0x%02x not yet supported in custom attr encoder", simple_type);
5053         }
5054         *retp = p;
5055         *retbuffer = buffer;
5056 }
5057
5058 /*
5059  * mono_reflection_get_custom_attrs_blob:
5060  * @ctor: custom attribute constructor
5061  * @ctorArgs: arguments o the constructor
5062  * @properties:
5063  * @propValues:
5064  * @fields:
5065  * @fieldValues:
5066  * 
5067  * Creates the blob of data that needs to be saved in the metadata and that represents
5068  * the custom attributed described by @ctor, @ctorArgs etc.
5069  * Returns: a Byte array representing the blob of data.
5070  */
5071 MonoArray*
5072 mono_reflection_get_custom_attrs_blob (MonoObject *ctor, MonoArray *ctorArgs, MonoArray *properties, MonoArray *propValues, MonoArray *fields, MonoArray* fieldValues) 
5073 {
5074         MonoArray *result;
5075         MonoMethodSignature *sig;
5076         MonoObject *arg;
5077         char *buffer, *p;
5078         guint32 buflen, i;
5079
5080         MONO_ARCH_SAVE_REGS;
5081
5082         if (strcmp (ctor->vtable->klass->name, "MonoCMethod")) {
5083                 sig = ctor_builder_to_signature ((MonoReflectionCtorBuilder*)ctor);
5084         } else {
5085                 sig = ((MonoReflectionMethod*)ctor)->method->signature;
5086         }
5087         g_assert (mono_array_length (ctorArgs) == sig->param_count);
5088         buflen = 256;
5089         p = buffer = g_malloc (buflen);
5090         /* write the prolog */
5091         *p++ = 1;
5092         *p++ = 0;
5093         for (i = 0; i < sig->param_count; ++i) {
5094                 arg = mono_array_get (ctorArgs, MonoObject*, i);
5095                 encode_cattr_value (buffer, p, &buffer, &p, &buflen, sig->params [i], arg);
5096         }
5097         i = 0;
5098         if (properties)
5099                 i += mono_array_length (properties);
5100         if (fields)
5101                 i += mono_array_length (fields);
5102         *p++ = i & 0xff;
5103         *p++ = (i >> 8) & 0xff;
5104         if (properties) {
5105                 MonoObject *prop;
5106                 for (i = 0; i < mono_array_length (properties); ++i) {
5107                         MonoType *ptype;
5108                         char *pname;
5109                         int len;
5110                         
5111                         prop = mono_array_get (properties, gpointer, i);
5112                         get_prop_name_and_type (prop, &pname, &ptype);
5113                         *p++ = 0x54; /* PROPERTY signature */
5114                         if (ptype->type == MONO_TYPE_VALUETYPE && ptype->data.klass->enumtype) {
5115                                 char *str = type_get_qualified_name (ptype, NULL);
5116                                 int slen = strlen (str);
5117                                 if ((p-buffer) + 10 + slen >= buflen) {
5118                                         char *newbuf;
5119                                         buflen *= 2;
5120                                         buflen += slen;
5121                                         newbuf = g_realloc (buffer, buflen);
5122                                         p = newbuf + (p-buffer);
5123                                         buffer = newbuf;
5124                                 }
5125                                 *p++ = 0x55;
5126                                 /*
5127                                  * This seems to be optional...
5128                                  * *p++ = 0x80;
5129                                  */
5130                                 mono_metadata_encode_value (slen, p, &p);
5131                                 memcpy (p, str, slen);
5132                                 p += slen;
5133                                 g_free (str);
5134                         } else {
5135                                 mono_metadata_encode_value (ptype->type, p, &p);
5136                         }
5137                         len = strlen (pname);
5138                         mono_metadata_encode_value (len, p, &p);
5139                         memcpy (p, pname, len);
5140                         p += len;
5141                         encode_cattr_value (buffer, p, &buffer, &p, &buflen, ptype, (MonoObject*)mono_array_get (propValues, gpointer, i));
5142                         g_free (pname);
5143                 }
5144         }
5145
5146         if (fields) {
5147                 MonoObject *field;
5148                 for (i = 0; i < mono_array_length (fields); ++i) {
5149                         MonoType *ftype;
5150                         char *fname;
5151                         int len;
5152                         
5153                         field = mono_array_get (fields, gpointer, i);
5154                         get_field_name_and_type (field, &fname, &ftype);
5155                         *p++ = 0x53; /* FIELD signature */
5156                         if (ftype->type == MONO_TYPE_VALUETYPE && ftype->data.klass->enumtype) {
5157                                 char *str = type_get_qualified_name (ftype, NULL);
5158                                 int slen = strlen (str);
5159                                 if ((p-buffer) + 10 + slen >= buflen) {
5160                                         char *newbuf;
5161                                         buflen *= 2;
5162                                         buflen += slen;
5163                                         newbuf = g_realloc (buffer, buflen);
5164                                         p = newbuf + (p-buffer);
5165                                         buffer = newbuf;
5166                                 }
5167                                 *p++ = 0x55;
5168                                 /*
5169                                  * This seems to be optional...
5170                                  * *p++ = 0x80;
5171                                  */
5172                                 mono_metadata_encode_value (slen, p, &p);
5173                                 memcpy (p, str, slen);
5174                                 p += slen;
5175                                 g_free (str);
5176                         } else {
5177                                 mono_metadata_encode_value (ftype->type, p, &p);
5178                         }
5179                         len = strlen (fname);
5180                         mono_metadata_encode_value (len, p, &p);
5181                         memcpy (p, fname, len);
5182                         p += len;
5183                         encode_cattr_value (buffer, p, &buffer, &p, &buflen, ftype, (MonoObject*)mono_array_get (fieldValues, gpointer, i));
5184                         g_free (fname);
5185                 }
5186         }
5187
5188         g_assert (p - buffer <= buflen);
5189         buflen = p - buffer;
5190         result = mono_array_new (mono_domain_get (), mono_defaults.byte_class, buflen);
5191         p = mono_array_addr (result, char, 0);
5192         memcpy (p, buffer, buflen);
5193         g_free (buffer);
5194         if (strcmp (ctor->vtable->klass->name, "MonoCMethod"))
5195                 g_free (sig);
5196         return result;
5197 }
5198
5199 /*
5200  * mono_reflection_setup_internal_class:
5201  * @tb: a TypeBuilder object
5202  *
5203  * Creates a MonoClass that represents the TypeBuilder.
5204  * This is a trick that lets us simplify a lot of reflection code
5205  * (and will allow us to support Build and Run assemblies easier).
5206  */
5207 void
5208 mono_reflection_setup_internal_class (MonoReflectionTypeBuilder *tb)
5209 {
5210         MonoClass *klass, *parent;
5211
5212         MONO_ARCH_SAVE_REGS;
5213
5214         klass = g_new0 (MonoClass, 1);
5215
5216         klass->image = tb->module->assemblyb->dynamic_assembly->assembly.image;
5217
5218         if (tb->parent) {
5219                 /* check so we can compile corlib correctly */
5220                 if (strcmp (mono_object_class (tb->parent)->name, "TypeBuilder") == 0) {
5221                         /* mono_class_setup_mono_type () guaranteess type->data.klass is valid */
5222                         parent = tb->parent->type->data.klass;
5223                 } else 
5224                         parent = my_mono_class_from_mono_type (tb->parent->type);
5225         } else
5226                 parent = NULL;
5227         
5228         klass->inited = 1; /* we lie to the runtime */
5229         klass->name = mono_string_to_utf8 (tb->name);
5230         klass->name_space = mono_string_to_utf8 (tb->nspace);
5231         klass->type_token = MONO_TOKEN_TYPE_DEF | tb->table_idx;
5232         klass->flags = tb->attrs;
5233
5234         klass->element_class = klass;
5235         klass->reflection_info = tb; /* need to pin. */
5236
5237         /* Put into cache so mono_class_get () will find it */
5238         mono_image_add_to_name_cache (klass->image, klass->name_space, klass->name,
5239                                                                   tb->table_idx);
5240
5241         mono_g_hash_table_insert (tb->module->assemblyb->dynamic_assembly->tokens,
5242                                                           GUINT_TO_POINTER (MONO_TOKEN_TYPE_DEF | tb->table_idx),
5243                                                           tb);
5244
5245         if (parent != NULL)
5246                 mono_class_setup_parent (klass, parent);
5247         else if (strcmp (klass->name, "Object") == 0 && strcmp (klass->name_space, "System") == 0) {
5248                 const char *old_n = klass->name;
5249                 /* trick to get relative numbering right when compiling corlib */
5250                 klass->name = "BuildingObject";
5251                 mono_class_setup_parent (klass, mono_defaults.object_class);
5252                 klass->name = old_n;
5253         }
5254         mono_class_setup_mono_type (klass);
5255
5256         mono_class_setup_supertypes (klass);
5257
5258         /*
5259          * FIXME: handle interfaces.
5260          */
5261
5262         tb->type.type = &klass->byval_arg;
5263
5264         if (tb->nesting_type) {
5265                 g_assert (tb->nesting_type->type);
5266                 klass->nested_in = mono_class_from_mono_type (tb->nesting_type->type);
5267         }
5268
5269         /*g_print ("setup %s as %s (%p)\n", klass->name, ((MonoObject*)tb)->vtable->klass->name, tb);*/
5270 }
5271
5272 /*
5273  * mono_reflection_create_internal_class:
5274  * @tb: a TypeBuilder object
5275  *
5276  * Actually create the MonoClass that is associated with the TypeBuilder.
5277  */
5278 void
5279 mono_reflection_create_internal_class (MonoReflectionTypeBuilder *tb)
5280 {
5281         MonoClass *klass;
5282
5283         MONO_ARCH_SAVE_REGS;
5284
5285         klass = my_mono_class_from_mono_type (tb->type.type);
5286
5287         if (klass->enumtype && klass->enum_basetype == NULL) {
5288                 MonoReflectionFieldBuilder *fb;
5289
5290                 g_assert (tb->fields != NULL);
5291                 g_assert (mono_array_length (tb->fields) >= 1);
5292
5293                 fb = mono_array_get (tb->fields, MonoReflectionFieldBuilder*, 0);
5294
5295                 klass->enum_basetype = fb->type->type;
5296                 klass->element_class = my_mono_class_from_mono_type (klass->enum_basetype);
5297                 if (!klass->element_class)
5298                         klass->element_class = mono_class_from_mono_type (klass->enum_basetype);
5299                 klass->instance_size = klass->element_class->instance_size;
5300                 klass->size_inited = 1;
5301                 /* 
5302                  * this is almost safe to do with enums and it's needed to be able
5303                  * to create objects of the enum type (for use in SetConstant).
5304                  */
5305                 /* FIXME: Does this mean enums can't have method overrides ? */
5306                 mono_class_setup_vtable (klass, NULL, 0);
5307         }
5308 }
5309
5310 static MonoMarshalSpec*
5311 mono_marshal_spec_from_builder (MonoAssembly *assembly,
5312                                                                 MonoReflectionMarshal *minfo)
5313 {
5314         MonoMarshalSpec *res;
5315
5316         res = g_new0 (MonoMarshalSpec, 1);
5317         res->native = minfo->type;
5318
5319         switch (minfo->type) {
5320         case MONO_NATIVE_LPARRAY:
5321                 res->data.array_data.elem_type = minfo->eltype;
5322                 res->data.array_data.param_num = 0; /* Not yet */
5323                 res->data.array_data.num_elem = minfo->count;
5324                 break;
5325
5326         case MONO_NATIVE_BYVALTSTR:
5327         case MONO_NATIVE_BYVALARRAY:
5328                 res->data.array_data.num_elem = minfo->count;
5329                 break;
5330
5331         case MONO_NATIVE_CUSTOM:
5332                 if (minfo->marshaltyperef)
5333                         res->data.custom_data.custom_name =
5334                                 type_get_qualified_name (minfo->marshaltyperef->type, 
5335                                                                                  assembly);
5336                 if (minfo->mcookie)
5337                         res->data.custom_data.cookie = mono_string_to_utf8 (minfo->mcookie);
5338                 break;
5339
5340         default:
5341                 break;
5342         }
5343
5344         return res;
5345 }
5346
5347 static MonoMethod*
5348 reflection_methodbuilder_to_mono_method (MonoClass *klass,
5349                                                                                  ReflectionMethodBuilder *rmb,
5350                                                                                  MonoMethodSignature *sig)
5351 {
5352         MonoMethod *m;
5353         MonoMethodNormal *pm;
5354         MonoMarshalSpec **specs;
5355         int i;
5356
5357         if ((rmb->attrs & METHOD_ATTRIBUTE_PINVOKE_IMPL) ||
5358             (rmb->iattrs & METHOD_IMPL_ATTRIBUTE_INTERNAL_CALL))
5359                 m = (MonoMethod *)g_new0 (MonoMethodPInvoke, 1);
5360         else 
5361                 m = (MonoMethod *)g_new0 (MonoMethodNormal, 1);
5362
5363         pm = (MonoMethodNormal*)m;
5364
5365         m->slot = -1;
5366         m->flags = rmb->attrs;
5367         m->iflags = rmb->iattrs;
5368         m->name = mono_string_to_utf8 (rmb->name);
5369         m->klass = klass;
5370         m->signature = sig;
5371         m->token = MONO_TOKEN_METHOD_DEF | (*rmb->table_idx);
5372
5373         if (m->iflags & METHOD_IMPL_ATTRIBUTE_INTERNAL_CALL) {
5374                 if (klass == mono_defaults.string_class && !strcmp (m->name, ".ctor"))
5375                         m->string_ctor = 1;
5376
5377                 m->addr = mono_lookup_internal_call (m);
5378                 m->signature->pinvoke = 1;
5379         } else if (m->flags & METHOD_ATTRIBUTE_PINVOKE_IMPL) {
5380                 /* TODO */
5381                 m->signature->pinvoke = 1;
5382                 return m;
5383         } else if (!m->klass->dummy && 
5384                            !(m->flags & METHOD_ATTRIBUTE_ABSTRACT) &&
5385                            !(m->iflags & METHOD_IMPL_ATTRIBUTE_RUNTIME)) {
5386                 MonoMethodHeader *header;
5387                 guint32 code_size;
5388                 gint32 max_stack, i;
5389                 gint32 num_locals = 0;
5390                 gint32 num_clauses = 0;
5391                 guint8 *code;
5392
5393                 if (rmb->ilgen) {
5394                         code = mono_array_addr (rmb->ilgen->code, guint8, 0);
5395                         code_size = rmb->ilgen->code_len;
5396                         max_stack = rmb->ilgen->max_stack;
5397                         num_locals = rmb->ilgen->locals ? mono_array_length (rmb->ilgen->locals) : 0;
5398                         if (rmb->ilgen->ex_handlers)
5399                                 num_clauses = method_count_clauses (rmb->ilgen);
5400                 } else {
5401                         if (rmb->code) {
5402                                 code = mono_array_addr (rmb->code, guint8, 0);
5403                                 code_size = mono_array_length (rmb->code);
5404                                 /* we probably need to run a verifier on the code... */
5405                                 max_stack = 8; 
5406                         }
5407                         else {
5408                                 code = NULL;
5409                                 code_size = 0;
5410                                 max_stack = 8;
5411                         }
5412                 }
5413
5414                 header = g_malloc0 (sizeof (MonoMethodHeader) + 
5415                                                         (num_locals - MONO_ZERO_LEN_ARRAY) * sizeof (MonoType*));
5416                 header->code_size = code_size;
5417                 header->code = g_malloc (code_size);
5418                 memcpy ((char*)header->code, code, code_size);
5419                 header->max_stack = max_stack;
5420                 header->init_locals = rmb->init_locals;
5421                 header->num_locals = num_locals;
5422
5423                 for (i = 0; i < num_locals; ++i) {
5424                         MonoReflectionLocalBuilder *lb = 
5425                                 mono_array_get (rmb->ilgen->locals, 
5426                                                                 MonoReflectionLocalBuilder*, i);
5427
5428                         header->locals [i] = g_new0 (MonoType, 1);
5429                         memcpy (header->locals [i], lb->type->type, sizeof (MonoType));
5430                 }
5431
5432                 header->num_clauses = num_clauses;
5433                 if (num_clauses) {
5434                         header->clauses = method_encode_clauses (klass->image->assembly->dynamic,
5435                                                                                                          rmb->ilgen,
5436                                                                                                          num_clauses);
5437                 }
5438
5439                 pm->header = header;
5440         }
5441
5442         /* Parameter marshalling */
5443         specs = NULL;
5444         if (rmb->pinfo)         
5445                 for (i = 0; i < mono_array_length (rmb->pinfo); ++i) {
5446                         MonoReflectionParamBuilder *pb;
5447                         if ((pb = mono_array_get (rmb->pinfo, MonoReflectionParamBuilder*, i))) {
5448                                 if (pb->marshal_info) {
5449                                         if (specs == NULL)
5450                                                 specs = g_new0 (MonoMarshalSpec*, sig->param_count + 1);
5451                                         specs [pb->position] = 
5452                                                 mono_marshal_spec_from_builder (klass->image->assembly, pb->marshal_info);
5453                                 }
5454                         }
5455                 }
5456         if (specs != NULL)
5457                 mono_g_hash_table_insert (
5458                         ((MonoDynamicAssembly*)klass->image->assembly->dynamic)->param_marshalling,
5459                         m, specs);
5460
5461         return m;
5462 }       
5463
5464 static MonoMethod*
5465 ctorbuilder_to_mono_method (MonoClass *klass, MonoReflectionCtorBuilder* mb)
5466 {
5467         ReflectionMethodBuilder rmb;
5468         const char *name;
5469         MonoMethodSignature *sig;
5470
5471         name = mb->attrs & METHOD_ATTRIBUTE_STATIC ? ".cctor": ".ctor";
5472
5473         sig = ctor_builder_to_signature (mb);
5474
5475         rmb.ilgen = mb->ilgen;
5476         rmb.parameters = mb->parameters;
5477         rmb.pinfo = mb->pinfo;
5478         rmb.attrs = mb->attrs | METHOD_ATTRIBUTE_RT_SPECIAL_NAME;
5479         rmb.iattrs = mb->iattrs;
5480         rmb.call_conv = mb->call_conv;
5481         rmb.type = mb->type;
5482         rmb.name = mono_string_new (mono_domain_get (), name);
5483         rmb.table_idx = &mb->table_idx;
5484         rmb.init_locals = mb->init_locals;
5485         rmb.code = NULL;
5486
5487         mb->mhandle = reflection_methodbuilder_to_mono_method (klass, &rmb, sig);
5488         mono_save_custom_attrs (klass->image, mb->mhandle, mb->cattrs);
5489
5490         if (!((MonoDynamicAssembly*)klass->image->assembly->dynamic)->save) {
5491                 /* ilgen is no longer needed */
5492                 mb->ilgen = NULL;
5493         }
5494
5495         return mb->mhandle;
5496 }
5497
5498 static MonoMethod*
5499 methodbuilder_to_mono_method (MonoClass *klass, MonoReflectionMethodBuilder* mb)
5500 {
5501         ReflectionMethodBuilder rmb;
5502         MonoMethodSignature *sig;
5503
5504         sig = method_builder_to_signature (mb);
5505
5506         rmb.ilgen = mb->ilgen;
5507         rmb.parameters = mb->parameters;
5508         rmb.pinfo = mb->pinfo;
5509         rmb.attrs = mb->attrs;
5510         rmb.iattrs = mb->iattrs;
5511         rmb.call_conv = mb->call_conv;
5512         rmb.type = mb->type;
5513         rmb.name = mb->name;
5514         rmb.table_idx = &mb->table_idx;
5515         rmb.init_locals = mb->init_locals;
5516         rmb.code = mb->code;
5517
5518         mb->mhandle = reflection_methodbuilder_to_mono_method (klass, &rmb, sig);
5519         mono_save_custom_attrs (klass->image, mb->mhandle, mb->cattrs);
5520
5521         if (!((MonoDynamicAssembly*)klass->image->assembly->dynamic)->save) {
5522                 /* ilgen is no longer needed */
5523                 mb->ilgen = NULL;
5524         }
5525         return mb->mhandle;
5526 }
5527
5528 static void
5529 ensure_runtime_vtable (MonoClass *klass)
5530 {
5531         MonoReflectionTypeBuilder *tb = klass->reflection_info;
5532         int i, num, j, onum;
5533         MonoMethod **overrides;
5534
5535         if (!tb || klass->wastypebuilder)
5536                 return;
5537         if (klass->parent)
5538                 ensure_runtime_vtable (klass->parent);
5539
5540         num = tb->ctors? mono_array_length (tb->ctors): 0;
5541         num += tb->methods? mono_array_length (tb->methods): 0;
5542         klass->method.count = num;
5543         klass->methods = g_new (MonoMethod*, num);
5544         num = tb->ctors? mono_array_length (tb->ctors): 0;
5545         for (i = 0; i < num; ++i)
5546                 klass->methods [i] = ctorbuilder_to_mono_method (klass, mono_array_get (tb->ctors, MonoReflectionCtorBuilder*, i));
5547         num = tb->methods? mono_array_length (tb->methods): 0;
5548         j = i;
5549         for (i = 0; i < num; ++i)
5550                 klass->methods [j++] = methodbuilder_to_mono_method (klass, mono_array_get (tb->methods, MonoReflectionMethodBuilder*, i));
5551
5552         klass->wastypebuilder = TRUE;
5553         if (tb->interfaces) {
5554                 klass->interface_count = mono_array_length (tb->interfaces);
5555                 klass->interfaces = g_new (MonoClass*, klass->interface_count);
5556                 for (i = 0; i < klass->interface_count; ++i) {
5557                         MonoReflectionType *iface = mono_array_get (tb->interfaces, gpointer, i);
5558                         klass->interfaces [i] = mono_class_from_mono_type (iface->type);
5559                 }
5560         }
5561
5562         if (klass->flags & TYPE_ATTRIBUTE_INTERFACE)
5563                 for (i = 0; i < klass->method.count; ++i)
5564                         klass->methods [i]->slot = i;
5565
5566         /* Overrides */
5567         onum = 0;
5568         if (tb->methods) {
5569                 for (i = 0; i < mono_array_length (tb->methods); ++i) {
5570                         MonoReflectionMethodBuilder *mb = 
5571                                 mono_array_get (tb->methods, MonoReflectionMethodBuilder*, i);
5572                         if (mb->override_method)
5573                                 onum ++;
5574                 }
5575         }
5576
5577         overrides = (MonoMethod**)g_new0 (MonoMethod, onum * 2);
5578
5579         if (tb->methods) {
5580                 onum = 0;
5581                 for (i = 0; i < mono_array_length (tb->methods); ++i) {
5582                         MonoReflectionMethodBuilder *mb = 
5583                                 mono_array_get (tb->methods, MonoReflectionMethodBuilder*, i);
5584                         if (mb->override_method) {
5585                                 /* FIXME: What if 'override_method' is a MethodBuilder ? */
5586                                 overrides [onum * 2] = 
5587                                         mb->override_method->method;
5588                                 overrides [onum * 2 + 1] =
5589                                         mb->mhandle;
5590
5591                                 g_assert (mb->mhandle);
5592
5593                                 onum ++;
5594                         }
5595                 }
5596         }
5597
5598         mono_class_setup_vtable (klass, overrides, onum);
5599 }
5600
5601 static void
5602 typebuilder_setup_fields (MonoClass *klass)
5603 {
5604         MonoReflectionTypeBuilder *tb = klass->reflection_info;
5605         MonoReflectionFieldBuilder *fb;
5606         MonoClassField *field;
5607         const char *p, *p2;
5608         int i;
5609         guint32 len, idx;
5610
5611         klass->field.count = tb->fields? mono_array_length (tb->fields): 0;
5612         klass->field.first = 0;
5613         klass->field.last = klass->field.count;
5614
5615         if (!klass->field.count)
5616                 return;
5617         
5618         klass->fields = g_new0 (MonoClassField, klass->field.count);
5619
5620         for (i = 0; i < klass->field.count; ++i) {
5621                 fb = mono_array_get (tb->fields, gpointer, i);
5622                 field = &klass->fields [i];
5623                 field->name = mono_string_to_utf8 (fb->name);
5624                 if (fb->attrs) {
5625                         /* FIXME: handle type modifiers */
5626                         field->type = g_memdup (fb->type->type, sizeof (MonoType));
5627                         field->type->attrs = fb->attrs;
5628                 } else {
5629                         field->type = fb->type->type;
5630                 }
5631                 if ((fb->attrs & FIELD_ATTRIBUTE_HAS_FIELD_RVA) && fb->rva_data)
5632                         field->data = mono_array_addr (fb->rva_data, char, 0);
5633                 if (fb->offset != -1)
5634                         field->offset = fb->offset;
5635                 field->parent = klass;
5636                 fb->handle = field;
5637                 mono_save_custom_attrs (klass->image, field, fb->cattrs);
5638
5639                 if (fb->def_value) {
5640                         MonoDynamicAssembly *assembly = klass->image->assembly->dynamic;
5641                         field->type->attrs |= FIELD_ATTRIBUTE_HAS_DEFAULT;
5642                         field->def_value = g_new0 (MonoConstant, 1);
5643                         idx = encode_constant (assembly, fb->def_value, &field->def_value->type);
5644                         /* Copy the data from the blob since it might get realloc-ed */
5645                         p = assembly->blob.data + idx;
5646                         len = mono_metadata_decode_blob_size (p, &p2);
5647                         len += p2 - p;
5648                         field->def_value->value = g_malloc (len);
5649                         memcpy (field->def_value->value, p, len);
5650                 }
5651         }
5652         mono_class_layout_fields (klass);
5653 }
5654
5655 static void
5656 typebuilder_setup_properties (MonoClass *klass)
5657 {
5658         MonoReflectionTypeBuilder *tb = klass->reflection_info;
5659         MonoReflectionPropertyBuilder *pb;
5660         int i;
5661
5662         klass->property.count = tb->properties ? mono_array_length (tb->properties) : 0;
5663         klass->property.first = 0;
5664         klass->property.last = klass->property.count;
5665
5666         klass->properties = g_new0 (MonoProperty, klass->property.count);
5667         for (i = 0; i < klass->property.count; ++i) {
5668                 pb = mono_array_get (tb->properties, MonoReflectionPropertyBuilder*, i);
5669                 klass->properties [i].attrs = pb->attrs;
5670                 klass->properties [i].name = mono_string_to_utf8 (pb->name);
5671                 if (pb->get_method)
5672                         klass->properties [i].get = pb->get_method->mhandle;
5673                 if (pb->set_method)
5674                         klass->properties [i].set = pb->set_method->mhandle;
5675         }
5676 }
5677
5678 static void
5679 typebuilder_setup_events (MonoClass *klass)
5680 {
5681         MonoReflectionTypeBuilder *tb = klass->reflection_info;
5682         MonoReflectionEventBuilder *eb;
5683         int i, j;
5684
5685         klass->event.count = tb->events ? mono_array_length (tb->events) : 0;
5686         klass->event.first = 0;
5687         klass->event.last = klass->event.count;
5688
5689         klass->events = g_new0 (MonoEvent, klass->event.count);
5690         for (i = 0; i < klass->event.count; ++i) {
5691                 eb = mono_array_get (tb->events, MonoReflectionEventBuilder*, i);
5692                 klass->events [i].attrs = eb->attrs;
5693                 klass->events [i].name = mono_string_to_utf8 (eb->name);
5694                 if (eb->add_method)
5695                         klass->events [i].add = eb->add_method->mhandle;
5696                 if (eb->remove_method)
5697                         klass->events [i].remove = eb->remove_method->mhandle;
5698                 if (eb->raise_method)
5699                         klass->events [i].raise = eb->raise_method->mhandle;
5700
5701                 if (eb->other_methods) {
5702                         klass->events [i].other = g_new0 (MonoMethod*, mono_array_length (eb->other_methods));
5703                         for (j = 0; j < mono_array_length (eb->other_methods); ++j) {
5704                                 MonoReflectionMethodBuilder *mb = 
5705                                         mono_array_get (eb->other_methods,
5706                                                                         MonoReflectionMethodBuilder*, j);
5707                                 klass->events [i].other [j] = mb->mhandle;
5708                         }
5709                 }
5710         }
5711 }
5712
5713 MonoReflectionType*
5714 mono_reflection_create_runtime_class (MonoReflectionTypeBuilder *tb)
5715 {
5716         MonoClass *klass;
5717         MonoReflectionType* res;
5718
5719         MONO_ARCH_SAVE_REGS;
5720
5721         klass = my_mono_class_from_mono_type (tb->type.type);
5722
5723         mono_save_custom_attrs (klass->image, klass, tb->cattrs);
5724
5725         /*
5726          * Fields to set in klass:
5727          * the various flags: delegate/unicode/contextbound etc.
5728          * nested_classes
5729          */
5730         klass->flags = tb->attrs;
5731         klass->element_class = klass;
5732
5733         if (!((MonoDynamicAssembly*)klass->image->assembly->dynamic)->run)
5734                 /* No need to fully construct the type */
5735                 return mono_type_get_object (mono_object_domain (tb), &klass->byval_arg);
5736
5737         /* enums are done right away */
5738         if (!klass->enumtype)
5739                 ensure_runtime_vtable (klass);
5740
5741         /* fields and object layout */
5742         if (klass->parent) {
5743                 if (!klass->parent->size_inited)
5744                         mono_class_init (klass->parent);
5745                 klass->instance_size += klass->parent->instance_size;
5746                 klass->class_size += klass->parent->class_size;
5747                 klass->min_align = klass->parent->min_align;
5748         } else {
5749                 klass->instance_size = sizeof (MonoObject);
5750                 klass->min_align = 1;
5751         }
5752
5753         /* FIXME: handle packing_size and instance_size */
5754         typebuilder_setup_fields (klass);
5755
5756         typebuilder_setup_properties (klass);
5757
5758         typebuilder_setup_events (klass);
5759
5760         res = mono_type_get_object (mono_object_domain (tb), &klass->byval_arg);
5761         /* with enums res == tb: need to fix that. */
5762         if (!klass->enumtype)
5763                 g_assert (res != (MonoReflectionType*)tb);
5764         return res;
5765 }
5766
5767 MonoArray *
5768 mono_reflection_sighelper_get_signature_local (MonoReflectionSigHelper *sig)
5769 {
5770         MonoDynamicAssembly *assembly = sig->module->assemblyb->dynamic_assembly;
5771         guint32 na = mono_array_length (sig->arguments);
5772         guint32 buflen, i;
5773         MonoArray *result;
5774         char *buf, *p;
5775
5776         MONO_ARCH_SAVE_REGS;
5777
5778         p = buf = g_malloc (10 + na * 10);
5779
5780         mono_metadata_encode_value (0x07, p, &p);
5781         mono_metadata_encode_value (na, p, &p);
5782         for (i = 0; i < na; ++i) {
5783                 MonoReflectionType *type = mono_array_get (sig->arguments, MonoReflectionType *, i);
5784                 encode_reflection_type (assembly, type, p, &p);
5785         }
5786
5787         buflen = p - buf;
5788         result = mono_array_new (mono_domain_get (), mono_defaults.byte_class, buflen);
5789         p = mono_array_addr (result, char, 0);
5790         memcpy (p, buf, buflen);
5791         g_free (buf);
5792
5793         return result;
5794 }
5795
5796 MonoArray *
5797 mono_reflection_sighelper_get_signature_field (MonoReflectionSigHelper *sig)
5798 {
5799         MonoDynamicAssembly *assembly = sig->module->assemblyb->dynamic_assembly;
5800         guint32 na = mono_array_length (sig->arguments);
5801         guint32 buflen, i;
5802         MonoArray *result;
5803         char *buf, *p;
5804
5805         MONO_ARCH_SAVE_REGS;
5806
5807         p = buf = g_malloc (10 + na * 10);
5808
5809         mono_metadata_encode_value (0x06, p, &p);
5810         for (i = 0; i < na; ++i) {
5811                 MonoReflectionType *type = mono_array_get (sig->arguments, MonoReflectionType *, i);
5812                 encode_reflection_type (assembly, type, p, &p);
5813         }
5814
5815         buflen = p - buf;
5816         result = mono_array_new (mono_domain_get (), mono_defaults.byte_class, buflen);
5817         p = mono_array_addr (result, char, 0);
5818         memcpy (p, buf, buflen);
5819         g_free (buf);
5820
5821         return result;
5822 }
5823
5824 /**
5825  * mono_reflection_lookup_dynamic_token:
5826  *
5827  *  Finish the Builder object pointed to by TOKEN and return the corresponding
5828  * runtime structure.
5829  */
5830 gpointer
5831 mono_reflection_lookup_dynamic_token (MonoImage *image, guint32 token)
5832 {
5833         MonoDynamicAssembly *assembly = image->assembly->dynamic;
5834         MonoObject *obj;
5835         gpointer result;
5836
5837         obj = mono_g_hash_table_lookup (assembly->tokens, GUINT_TO_POINTER (token));
5838         g_assert (obj);
5839
5840         if (strcmp (obj->vtable->klass->name, "String") == 0) {
5841                 result = mono_string_intern ((MonoString*)obj);
5842                 g_assert (result);
5843         }
5844         else if (strcmp (obj->vtable->klass->name, "MonoType") == 0) {
5845                 MonoReflectionType *tb = (MonoReflectionType*)obj;
5846                 result = mono_class_from_mono_type (tb->type);
5847                 g_assert (result);
5848         }
5849         else if (strcmp (obj->vtable->klass->name, "MonoMethod") == 0) {
5850                 result = ((MonoReflectionMethod*)obj)->method;
5851                 g_assert (result);
5852         }
5853         else if (strcmp (obj->vtable->klass->name, "MonoCMethod") == 0) {
5854                 result = ((MonoReflectionMethod*)obj)->method;
5855                 g_assert (result);
5856         }
5857         else if (strcmp (obj->vtable->klass->name, "MethodBuilder") == 0) {
5858                 MonoReflectionMethodBuilder *mb = (MonoReflectionMethodBuilder*)obj;
5859                 result = mb->mhandle;
5860                 if (!result) {
5861                         /* Type is not yet created */
5862                         MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder*)mb->type;
5863
5864                         mono_domain_try_type_resolve (mono_domain_get (), NULL, (MonoObject*)tb);
5865
5866                         /*
5867                          * Hopefully this has been filled in by calling CreateType() on the
5868                          * TypeBuilder.
5869                          */
5870                         /**
5871                          * TODO: This won't work if the application finishes another 
5872                          * TypeBuilder instance instead of this one.
5873                          */
5874                         result = mb->mhandle;
5875                 }
5876         }
5877         else if (strcmp (obj->vtable->klass->name, "ConstructorBuilder") == 0) {
5878                 MonoReflectionCtorBuilder *cb = (MonoReflectionCtorBuilder*)obj;
5879
5880                 result = cb->mhandle;
5881                 if (!result) {
5882                         MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder*)cb->type;
5883
5884                         mono_domain_try_type_resolve (mono_domain_get (), NULL, (MonoObject*)tb);
5885                         result = cb->mhandle;
5886                 }
5887         }
5888         else if (strcmp (obj->vtable->klass->name, "MonoField") == 0) {
5889                 result = ((MonoReflectionField*)obj)->field;
5890                 g_assert (result);
5891         }
5892         else if (strcmp (obj->vtable->klass->name, "FieldBuilder") == 0) {
5893                 MonoReflectionFieldBuilder *fb = (MonoReflectionFieldBuilder*)obj;
5894                 result = fb->handle;
5895
5896                 if (!result) {
5897                         MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder*)fb->typeb;
5898
5899                         mono_domain_try_type_resolve (mono_domain_get (), NULL, (MonoObject*)tb);
5900                         result = fb->handle;
5901                 }
5902         }
5903         else if (strcmp (obj->vtable->klass->name, "TypeBuilder") == 0) {
5904                 MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder*)obj;
5905                 MonoClass *klass;
5906
5907                 klass = tb->type.type->data.klass;
5908                 if (klass->wastypebuilder) {
5909                         /* Already created */
5910                         result = klass;
5911                 }
5912                 else {
5913                         mono_domain_try_type_resolve (mono_domain_get (), NULL, (MonoObject*)tb);
5914                         result = tb->type.type->data.klass;
5915                         g_assert (result);
5916                 }
5917         }
5918         else if (strcmp (obj->vtable->klass->name, "SignatureHelper") == 0) {
5919                 MonoReflectionSigHelper *helper = (MonoReflectionSigHelper*)obj;
5920                 MonoMethodSignature *sig;
5921                 int nargs, i;
5922
5923                 if (helper->arguments)
5924                         nargs = mono_array_length (helper->arguments);
5925                 else
5926                         nargs = 0;
5927
5928                 sig = mono_metadata_signature_alloc (image, nargs);
5929                 sig->explicit_this = helper->call_conv & 64;
5930                 sig->hasthis = helper->call_conv & 32;
5931
5932                 if (helper->call_conv == 0) /* unmanaged */
5933                         sig->call_convention = helper->unmanaged_call_conv - 1;
5934                 else
5935                         if (helper->call_conv & 0x02)
5936                                 sig->call_convention = MONO_CALL_VARARG;
5937                 else
5938                         sig->call_convention = MONO_CALL_DEFAULT;
5939
5940                 sig->param_count = nargs;
5941                 /* TODO: Copy type ? */
5942                 sig->ret = helper->return_type->type;
5943                 for (i = 0; i < nargs; ++i) {
5944                         MonoReflectionType *rt = mono_array_get (helper->arguments, MonoReflectionType*, i);
5945                         sig->params [i] = rt->type;
5946                 }
5947
5948                 result = sig;
5949         }
5950         else {
5951                 g_print (obj->vtable->klass->name);
5952                 g_assert_not_reached ();
5953         }
5954         return result;
5955 }
5956
5957
5958
5959
5960