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