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