Thu Oct 17 13:11:39 CEST 2002 Paolo Molaro <lupus@ximian.com>
[mono.git] / mono / metadata / reflection.c
1
2 /*
3  * reflection.c: Routines for creating an image at runtime.
4  * 
5  * Author:
6  *   Paolo Molaro (lupus@ximian.com)
7  *
8  * (C) 2001, 2002 Ximian, Inc.  http://www.ximian.com
9  *
10  */
11 #include <config.h>
12 #include "mono/utils/mono-digest.h"
13 #include "mono/metadata/reflection.h"
14 #include "mono/metadata/tabledefs.h"
15 #include "mono/metadata/tokentype.h"
16 #include "mono/metadata/appdomain.h"
17 #include "mono/metadata/opcodes.h"
18 #include <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                 values [MONO_ASSEMBLYREF_PUBLIC_KEY] = 0;
1218         }
1219         token <<= RESOLTION_SCOPE_BITS;
1220         token |= RESOLTION_SCOPE_ASSEMBLYREF;
1221         g_hash_table_insert (assembly->handleref, image, GUINT_TO_POINTER (token));
1222         return token;
1223 }
1224
1225 static guint32
1226 create_typespec (MonoDynamicAssembly *assembly, MonoType *type)
1227 {
1228         MonoDynamicTable *table;
1229         guint32 *values;
1230         guint32 token;
1231         char sig [128];
1232         char *p = sig;
1233         char blob_size [6];
1234         char *b = blob_size;
1235
1236         switch (type->type) {
1237         case MONO_TYPE_FNPTR:
1238         case MONO_TYPE_PTR:
1239         case MONO_TYPE_SZARRAY:
1240         case MONO_TYPE_ARRAY:
1241                 encode_type (assembly, type, p, &p);
1242                 break;
1243         default:
1244                 return 0;
1245         }
1246         
1247         g_assert (p-sig < 128);
1248         mono_metadata_encode_value (p-sig, b, &b);
1249         token = mono_image_add_stream_data (&assembly->blob, blob_size, b-blob_size);
1250         mono_image_add_stream_data (&assembly->blob, sig, p-sig);
1251
1252         table = &assembly->tables [MONO_TABLE_TYPESPEC];
1253         alloc_table (table, table->rows + 1);
1254         values = table->values + table->next_idx * MONO_TYPESPEC_SIZE;
1255         values [MONO_TYPESPEC_SIGNATURE] = token;
1256
1257         token = TYPEDEFORREF_TYPESPEC | (table->next_idx << TYPEDEFORREF_BITS);
1258         g_hash_table_insert (assembly->typeref, type, GUINT_TO_POINTER(token));
1259         table->next_idx ++;
1260         return token;
1261 }
1262
1263 /*
1264  * Despite the name, we handle also TypeSpec (with the above helper).
1265  */
1266 static guint32
1267 mono_image_typedef_or_ref (MonoDynamicAssembly *assembly, MonoType *type)
1268 {
1269         MonoDynamicTable *table;
1270         guint32 *values;
1271         guint32 token, scope, enclosing;
1272         MonoClass *klass;
1273
1274 #define COMPILE_CORLIB 0
1275 #if COMPILE_CORLIB
1276         /* nasty hack, need to find the proper solution */
1277         if (type->type == MONO_TYPE_OBJECT)
1278                 return TYPEDEFORREF_TYPEDEF | (2 << TYPEDEFORREF_BITS);
1279 #endif
1280         token = GPOINTER_TO_UINT (g_hash_table_lookup (assembly->typeref, type));
1281         if (token)
1282                 return token;
1283         token = create_typespec (assembly, type);
1284         if (token)
1285                 return token;
1286         klass = my_mono_class_from_mono_type (type);
1287         if (!klass)
1288                 klass = mono_class_from_mono_type (type);
1289         /*
1290          * If it's in the same module:
1291          */
1292         if (klass->image == assembly->assembly.image) {
1293                 MonoReflectionTypeBuilder *tb = klass->reflection_info;
1294                 return TYPEDEFORREF_TYPEDEF | (tb->table_idx << TYPEDEFORREF_BITS);
1295         }
1296
1297         if (klass->nested_in) {
1298                 enclosing = mono_image_typedef_or_ref (assembly, &klass->nested_in->byval_arg);
1299                 /* get the typeref idx of the enclosing type */
1300                 enclosing >>= TYPEDEFORREF_BITS;
1301                 scope = (enclosing << RESOLTION_SCOPE_BITS) | RESOLTION_SCOPE_TYPEREF;
1302         } else {
1303                 scope = resolution_scope_from_image (assembly, klass->image);
1304         }
1305         table = &assembly->tables [MONO_TABLE_TYPEREF];
1306         alloc_table (table, table->rows + 1);
1307         values = table->values + table->next_idx * MONO_TYPEREF_SIZE;
1308         values [MONO_TYPEREF_SCOPE] = scope;
1309         values [MONO_TYPEREF_NAME] = string_heap_insert (&assembly->sheap, klass->name);
1310         values [MONO_TYPEREF_NAMESPACE] = string_heap_insert (&assembly->sheap, klass->name_space);
1311         token = TYPEDEFORREF_TYPEREF | (table->next_idx << TYPEDEFORREF_BITS); /* typeref */
1312         g_hash_table_insert (assembly->typeref, type, GUINT_TO_POINTER(token));
1313         table->next_idx ++;
1314         return token;
1315 }
1316
1317 /*
1318  * Insert a memberef row into the metadata: the token that point to the memberref
1319  * is returned. Caching is done in the caller (mono_image_get_methodref_token() or
1320  * mono_image_get_fieldref_token()).
1321  * The sig param is an index to an already built signature.
1322  */
1323 static guint32
1324 mono_image_get_memberref_token (MonoDynamicAssembly *assembly, MonoType *type, const char *name, guint32 sig)
1325 {
1326         MonoDynamicTable *table;
1327         guint32 *values;
1328         guint32 token, pclass;
1329         guint32 parent;
1330
1331         parent = mono_image_typedef_or_ref (assembly, type);
1332         switch (parent & TYPEDEFORREF_MASK) {
1333         case TYPEDEFORREF_TYPEREF:
1334                 pclass = MEMBERREF_PARENT_TYPEREF;
1335                 break;
1336         case TYPEDEFORREF_TYPESPEC:
1337                 pclass = MEMBERREF_PARENT_TYPESPEC;
1338                 break;
1339         case TYPEDEFORREF_TYPEDEF:
1340                 /* should never get here */
1341         default:
1342                 g_warning ("unknown typeref or def token 0x%08x for %s", parent, name);
1343                 return 0;
1344         }
1345         /* extract the index */
1346         parent >>= TYPEDEFORREF_BITS;
1347
1348         table = &assembly->tables [MONO_TABLE_MEMBERREF];
1349         alloc_table (table, table->rows + 1);
1350         values = table->values + table->next_idx * MONO_MEMBERREF_SIZE;
1351         values [MONO_MEMBERREF_CLASS] = pclass | (parent << MEMBERREF_PARENT_BITS);
1352         values [MONO_MEMBERREF_NAME] = string_heap_insert (&assembly->sheap, name);
1353         values [MONO_MEMBERREF_SIGNATURE] = sig;
1354         token = MONO_TOKEN_MEMBER_REF | table->next_idx;
1355         table->next_idx ++;
1356
1357         return token;
1358 }
1359
1360 static guint32
1361 mono_image_get_methodref_token (MonoDynamicAssembly *assembly, MonoMethod *method)
1362 {
1363         guint32 token;
1364         
1365         token = GPOINTER_TO_UINT (g_hash_table_lookup (assembly->handleref, method));
1366         if (token)
1367                 return token;
1368         token = mono_image_get_memberref_token (assembly, &method->klass->byval_arg,
1369                 method->name,  method_encode_signature (assembly, method->signature));
1370         g_hash_table_insert (assembly->handleref, method, GUINT_TO_POINTER(token));
1371         return token;
1372 }
1373
1374 static guint32
1375 mono_image_get_fieldref_token (MonoDynamicAssembly *assembly, MonoClassField *field, MonoClass *klass)
1376 {
1377         guint32 token;
1378         
1379         token = GPOINTER_TO_UINT (g_hash_table_lookup (assembly->handleref, field));
1380         if (token)
1381                 return token;
1382         token = mono_image_get_memberref_token (assembly, &klass->byval_arg, 
1383                 field->name,  fieldref_encode_signature (assembly, field));
1384         g_hash_table_insert (assembly->handleref, field, GUINT_TO_POINTER(token));
1385         return token;
1386 }
1387
1388 static int
1389 reflection_cc_to_file (int call_conv) {
1390         switch (call_conv & 0x3) {
1391         case 0:
1392         case 1: return MONO_CALL_DEFAULT;
1393         case 2: return MONO_CALL_VARARG;
1394         default:
1395                 g_assert_not_reached ();
1396         }
1397         return 0;
1398 }
1399
1400 typedef struct {
1401         MonoType *parent;
1402         MonoMethodSignature *sig;
1403         char *name;
1404         guint32 token;
1405 } ArrayMethod;
1406
1407 static guint32
1408 mono_image_get_array_token (MonoDynamicAssembly *assembly, MonoReflectionArrayMethod *m)
1409 {
1410         guint32 nparams, i;
1411         GList *tmp;
1412         char *name;
1413         MonoMethodSignature *sig;
1414         ArrayMethod *am;
1415         
1416         name = mono_string_to_utf8 (m->name);
1417         nparams = mono_array_length (m->parameters);
1418         sig = g_malloc0 (sizeof (MonoMethodSignature) + sizeof (MonoType*) * nparams);
1419         sig->hasthis = 1;
1420         sig->call_convention = reflection_cc_to_file (m->call_conv);
1421         sig->param_count = nparams;
1422         sig->ret = m->ret? m->ret->type: &mono_defaults.void_class->byval_arg;
1423         for (i = 0; i < nparams; ++i) {
1424                 MonoReflectionType *t = mono_array_get (m->parameters, gpointer, i);
1425                 sig->params [i] = t->type;
1426         }
1427
1428         for (tmp = assembly->array_methods; tmp; tmp = tmp->next) {
1429                 am = tmp->data;
1430                 if (strcmp (name, am->name) == 0 && 
1431                                 mono_metadata_type_equal (am->parent, m->parent->type) &&
1432                                 mono_metadata_signature_equal (am->sig, sig)) {
1433                         g_free (name);
1434                         g_free (sig);
1435                         return am->token;
1436                 }
1437         }
1438         am = g_new0 (ArrayMethod, 1);
1439         am->name = name;
1440         am->sig = sig;
1441         am->parent = m->parent->type;
1442         am->token = mono_image_get_memberref_token (assembly, am->parent,
1443                 name,  method_encode_signature (assembly, sig));
1444         assembly->array_methods = g_list_prepend (assembly->array_methods, am);
1445         m->table_idx = am->token & 0xffffff;
1446         return am->token;
1447 }
1448
1449 /*
1450  * Insert into the metadata tables all the info about the TypeBuilder tb.
1451  * Data in the tables is inserted in a predefined order, since some tables need to be sorted.
1452  */
1453 static void
1454 mono_image_get_type_info (MonoDomain *domain, MonoReflectionTypeBuilder *tb, MonoDynamicAssembly *assembly)
1455 {
1456         MonoDynamicTable *table;
1457         guint *values;
1458         int i, is_object = 0, is_system = 0;
1459         char *n;
1460
1461         table = &assembly->tables [MONO_TABLE_TYPEDEF];
1462         values = table->values + tb->table_idx * MONO_TYPEDEF_SIZE;
1463         values [MONO_TYPEDEF_FLAGS] = tb->attrs;
1464         n = mono_string_to_utf8 (tb->name);
1465         if (strcmp (n, "Object") == 0)
1466                 is_object++;
1467         values [MONO_TYPEDEF_NAME] = string_heap_insert (&assembly->sheap, n);
1468         g_free (n);
1469         n = mono_string_to_utf8 (tb->nspace);
1470         if (strcmp (n, "System") == 0)
1471                 is_system++;
1472         values [MONO_TYPEDEF_NAMESPACE] = string_heap_insert (&assembly->sheap, n);
1473         g_free (n);
1474         if (tb->parent && !(is_system && is_object)) { /* interfaces don't have a parent */
1475                 values [MONO_TYPEDEF_EXTENDS] = mono_image_typedef_or_ref (assembly, tb->parent->type);
1476         } else
1477                 values [MONO_TYPEDEF_EXTENDS] = 0;
1478         values [MONO_TYPEDEF_FIELD_LIST] = assembly->tables [MONO_TABLE_FIELD].next_idx;
1479         values [MONO_TYPEDEF_METHOD_LIST] = assembly->tables [MONO_TABLE_METHOD].next_idx;
1480
1481         /*
1482          * if we have explicitlayout or sequentiallayouts, output data in the
1483          * ClassLayout table.
1484          */
1485         if (((tb->attrs & TYPE_ATTRIBUTE_LAYOUT_MASK) != TYPE_ATTRIBUTE_AUTO_LAYOUT) && (tb->class_size != -1)) {
1486                 table = &assembly->tables [MONO_TABLE_CLASSLAYOUT];
1487                 table->rows++;
1488                 alloc_table (table, table->rows);
1489                 values = table->values + table->rows * MONO_CLASS_LAYOUT_SIZE;
1490                 values [MONO_CLASS_LAYOUT_PARENT] = tb->table_idx;
1491                 values [MONO_CLASS_LAYOUT_CLASS_SIZE] = tb->class_size;
1492                 values [MONO_CLASS_LAYOUT_PACKING_SIZE] = tb->packing_size;
1493         }
1494
1495         /* handle interfaces */
1496         if (tb->interfaces) {
1497                 table = &assembly->tables [MONO_TABLE_INTERFACEIMPL];
1498                 i = table->rows;
1499                 table->rows += mono_array_length (tb->interfaces);
1500                 alloc_table (table, table->rows);
1501                 values = table->values + (i + 1) * MONO_INTERFACEIMPL_SIZE;
1502                 for (i = 0; i < mono_array_length (tb->interfaces); ++i) {
1503                         MonoReflectionType* iface = (MonoReflectionType*) mono_array_get (tb->interfaces, gpointer, i);
1504                         values [MONO_INTERFACEIMPL_CLASS] = tb->table_idx;
1505                         values [MONO_INTERFACEIMPL_INTERFACE] = mono_image_typedef_or_ref (assembly, iface->type);
1506                         values += MONO_INTERFACEIMPL_SIZE;
1507                 }
1508         }
1509
1510         /* handle fields */
1511         if (tb->fields) {
1512                 table = &assembly->tables [MONO_TABLE_FIELD];
1513                 table->rows += mono_array_length (tb->fields);
1514                 alloc_table (table, table->rows);
1515                 for (i = 0; i < mono_array_length (tb->fields); ++i)
1516                         mono_image_get_field_info (
1517                                 mono_array_get (tb->fields, MonoReflectionFieldBuilder*, i), assembly);
1518         }
1519
1520         /* handle constructors */
1521         if (tb->ctors) {
1522                 table = &assembly->tables [MONO_TABLE_METHOD];
1523                 table->rows += mono_array_length (tb->ctors);
1524                 alloc_table (table, table->rows);
1525                 for (i = 0; i < mono_array_length (tb->ctors); ++i)
1526                         mono_image_get_ctor_info (domain,
1527                                 mono_array_get (tb->ctors, MonoReflectionCtorBuilder*, i), assembly);
1528         }
1529
1530         /* handle methods */
1531         if (tb->methods) {
1532                 table = &assembly->tables [MONO_TABLE_METHOD];
1533                 table->rows += mono_array_length (tb->methods);
1534                 alloc_table (table, table->rows);
1535                 for (i = 0; i < mono_array_length (tb->methods); ++i)
1536                         mono_image_get_method_info (
1537                                 mono_array_get (tb->methods, MonoReflectionMethodBuilder*, i), assembly);
1538         }
1539
1540         /* Do the same with properties etc.. */
1541         if (tb->events && mono_array_length (tb->events)) {
1542                 table = &assembly->tables [MONO_TABLE_EVENT];
1543                 table->rows += mono_array_length (tb->events);
1544                 alloc_table (table, table->rows);
1545                 table = &assembly->tables [MONO_TABLE_EVENTMAP];
1546                 table->rows ++;
1547                 alloc_table (table, table->rows);
1548                 values = table->values + table->rows * MONO_EVENT_MAP_SIZE;
1549                 values [MONO_EVENT_MAP_PARENT] = tb->table_idx;
1550                 values [MONO_EVENT_MAP_EVENTLIST] = assembly->tables [MONO_TABLE_EVENT].next_idx;
1551                 for (i = 0; i < mono_array_length (tb->events); ++i)
1552                         mono_image_get_event_info (
1553                                 mono_array_get (tb->events, MonoReflectionEventBuilder*, i), assembly);
1554         }
1555         if (tb->properties && mono_array_length (tb->properties)) {
1556                 table = &assembly->tables [MONO_TABLE_PROPERTY];
1557                 table->rows += mono_array_length (tb->properties);
1558                 alloc_table (table, table->rows);
1559                 table = &assembly->tables [MONO_TABLE_PROPERTYMAP];
1560                 table->rows ++;
1561                 alloc_table (table, table->rows);
1562                 values = table->values + table->rows * MONO_PROPERTY_MAP_SIZE;
1563                 values [MONO_PROPERTY_MAP_PARENT] = tb->table_idx;
1564                 values [MONO_PROPERTY_MAP_PROPERTY_LIST] = assembly->tables [MONO_TABLE_PROPERTY].next_idx;
1565                 for (i = 0; i < mono_array_length (tb->properties); ++i)
1566                         mono_image_get_property_info (
1567                                 mono_array_get (tb->properties, MonoReflectionPropertyBuilder*, i), assembly);
1568         }
1569         if (tb->subtypes) {
1570                 MonoDynamicTable *ntable;
1571                 
1572                 table = &assembly->tables [MONO_TABLE_TYPEDEF];
1573                 table->rows += mono_array_length (tb->subtypes);
1574                 alloc_table (table, table->rows);
1575
1576                 ntable = &assembly->tables [MONO_TABLE_NESTEDCLASS];
1577                 ntable->rows += mono_array_length (tb->subtypes);
1578                 alloc_table (ntable, ntable->rows);
1579                 values = ntable->values + ntable->next_idx * MONO_NESTED_CLASS_SIZE;
1580
1581                 for (i = 0; i < mono_array_length (tb->subtypes); ++i) {
1582                         MonoReflectionTypeBuilder *subtype = mono_array_get (tb->subtypes, MonoReflectionTypeBuilder*, i);
1583
1584                         values [MONO_NESTED_CLASS_NESTED] = subtype->table_idx;
1585                         values [MONO_NESTED_CLASS_ENCLOSING] = tb->table_idx;
1586                         /*g_print ("nesting %s (%d) in %s (%d) (rows %d/%d)\n",
1587                                 mono_string_to_utf8 (subtype->name), subtype->table_idx,
1588                                 mono_string_to_utf8 (tb->name), tb->table_idx,
1589                                 ntable->next_idx, ntable->rows);*/
1590                         values += MONO_NESTED_CLASS_SIZE;
1591                         ntable->next_idx++;
1592                 }
1593                 for (i = 0; i < mono_array_length (tb->subtypes); ++i) {
1594                         MonoReflectionTypeBuilder *subtype = mono_array_get (tb->subtypes, MonoReflectionTypeBuilder*, i);
1595
1596                         mono_image_get_type_info (domain, subtype, assembly);
1597                 }
1598         }
1599 }
1600
1601 static void
1602 assign_type_idx (MonoReflectionTypeBuilder *type, MonoDynamicTable *table)
1603 {
1604         int j;
1605
1606         type->table_idx = table->next_idx ++;
1607         if (!type->subtypes)
1608                 return;
1609         for (j = 0; j < mono_array_length (type->subtypes); ++j) {
1610                 MonoReflectionTypeBuilder *subtype = mono_array_get (type->subtypes, MonoReflectionTypeBuilder*, j);
1611                 assign_type_idx (subtype, table);
1612         }
1613 }
1614
1615 static void
1616 params_add_cattrs (MonoDynamicAssembly *assembly, MonoArray *pinfo) {
1617         int i;
1618
1619         if (!pinfo)
1620                 return;
1621         for (i = 0; i < mono_array_length (pinfo); ++i) {
1622                 MonoReflectionParamBuilder *pb;
1623                 pb = mono_array_get (pinfo, MonoReflectionParamBuilder *, i);
1624                 if (!pb)
1625                         continue;
1626                 mono_image_add_cattrs (assembly, pb->table_idx, CUSTOM_ATTR_PARAMDEF, pb->cattrs);
1627         }
1628 }
1629
1630 static void
1631 type_add_cattrs (MonoDynamicAssembly *assembly, MonoReflectionTypeBuilder *tb) {
1632         int i;
1633         
1634         mono_image_add_cattrs (assembly, tb->table_idx, CUSTOM_ATTR_TYPEDEF, tb->cattrs);
1635         if (tb->fields) {
1636                 for (i = 0; i < mono_array_length (tb->fields); ++i) {
1637                         MonoReflectionFieldBuilder* fb;
1638                         fb = mono_array_get (tb->fields, MonoReflectionFieldBuilder*, i);
1639                         mono_image_add_cattrs (assembly, fb->table_idx, CUSTOM_ATTR_FIELDDEF, fb->cattrs);
1640                 }
1641         }
1642         if (tb->events) {
1643                 for (i = 0; i < mono_array_length (tb->events); ++i) {
1644                         MonoReflectionEventBuilder* eb;
1645                         eb = mono_array_get (tb->events, MonoReflectionEventBuilder*, i);
1646                         mono_image_add_cattrs (assembly, eb->table_idx, CUSTOM_ATTR_EVENT, eb->cattrs);
1647                 }
1648         }
1649         if (tb->properties) {
1650                 for (i = 0; i < mono_array_length (tb->properties); ++i) {
1651                         MonoReflectionPropertyBuilder* pb;
1652                         pb = mono_array_get (tb->properties, MonoReflectionPropertyBuilder*, i);
1653                         mono_image_add_cattrs (assembly, pb->table_idx, CUSTOM_ATTR_PROPERTY, pb->cattrs);
1654                 }
1655         }
1656         if (tb->ctors) {
1657                 for (i = 0; i < mono_array_length (tb->ctors); ++i) {
1658                         MonoReflectionCtorBuilder* cb;
1659                         cb = mono_array_get (tb->ctors, MonoReflectionCtorBuilder*, i);
1660                         mono_image_add_cattrs (assembly, cb->table_idx, CUSTOM_ATTR_METHODDEF, cb->cattrs);
1661                         params_add_cattrs (assembly, cb->pinfo);
1662                 }
1663         }
1664
1665         if (tb->methods) {
1666                 for (i = 0; i < mono_array_length (tb->methods); ++i) {
1667                         MonoReflectionMethodBuilder* mb;
1668                         mb = mono_array_get (tb->methods, MonoReflectionMethodBuilder*, i);
1669                         mono_image_add_cattrs (assembly, mb->table_idx, CUSTOM_ATTR_METHODDEF, mb->cattrs);
1670                         params_add_cattrs (assembly, mb->pinfo);
1671                 }
1672         }
1673
1674         if (tb->subtypes) {
1675                 for (i = 0; i < mono_array_length (tb->subtypes); ++i)
1676                         type_add_cattrs (assembly, mono_array_get (tb->subtypes, MonoReflectionTypeBuilder*, i));
1677         }
1678 }
1679
1680 static void
1681 module_add_cattrs (MonoDynamicAssembly *assembly, MonoReflectionModuleBuilder *mb) {
1682         int i;
1683         
1684         mono_image_add_cattrs (assembly, mb->table_idx, CUSTOM_ATTR_MODULE, mb->cattrs);
1685         
1686         for (i = 0; i < mono_array_length (mb->types); ++i)
1687                 type_add_cattrs (assembly, mono_array_get (mb->types, MonoReflectionTypeBuilder*, i));
1688 }
1689
1690 static void
1691 mono_image_fill_module_table (MonoDomain *domain, MonoReflectionModuleBuilder *mb, MonoDynamicAssembly *assembly)
1692 {
1693         MonoDynamicTable *table;
1694         int i;
1695         char *name;
1696
1697         table = &assembly->tables [MONO_TABLE_MODULE];
1698         mb->table_idx = table->next_idx ++;
1699         name = mono_string_to_utf8 (mb->module.name);
1700         table->values [mb->table_idx * MONO_MODULE_SIZE + MONO_MODULE_NAME] = string_heap_insert (&assembly->sheap, name);
1701         g_free (name);
1702         i = mono_image_add_stream_data (&assembly->guid, mono_array_addr (mb->guid, char, 0), 16);
1703         i /= 16;
1704         ++i;
1705         table->values [mb->table_idx * MONO_MODULE_SIZE + MONO_MODULE_MVID] = i;
1706         table->values [mb->table_idx * MONO_MODULE_SIZE + MONO_MODULE_ENC] = 0;
1707         table->values [mb->table_idx * MONO_MODULE_SIZE + MONO_MODULE_ENCBASE] = 0;
1708
1709         /*
1710          * fill-in info in other tables as well.
1711          */
1712         table = &assembly->tables [MONO_TABLE_TYPEDEF];
1713         table->rows += mono_array_length (mb->types);
1714         alloc_table (table, table->rows);
1715         /*
1716          * We assign here the typedef indexes to avoid mismatches if a type that
1717          * has not yet been stored in the tables is referenced by another type.
1718          */
1719         for (i = 0; i < mono_array_length (mb->types); ++i) {
1720                 MonoReflectionTypeBuilder *type = mono_array_get (mb->types, MonoReflectionTypeBuilder*, i);
1721                 assign_type_idx (type, table);
1722         }
1723         for (i = 0; i < mono_array_length (mb->types); ++i)
1724                 mono_image_get_type_info (domain, mono_array_get (mb->types, MonoReflectionTypeBuilder*, i), assembly);
1725 }
1726
1727 #define align_pointer(base,p)\
1728         do {\
1729                 guint32 __diff = (unsigned char*)(p)-(unsigned char*)(base);\
1730                 if (__diff & 3)\
1731                         (p) += 4 - (__diff & 3);\
1732         } while (0)
1733
1734 static int
1735 compare_semantics (const void *a, const void *b)
1736 {
1737         const guint32 *a_values = a;
1738         const guint32 *b_values = b;
1739         int assoc = a_values [MONO_METHOD_SEMA_ASSOCIATION] - b_values [MONO_METHOD_SEMA_ASSOCIATION];
1740         if (assoc)
1741                 return assoc;
1742         return a_values [MONO_METHOD_SEMA_SEMANTICS] - b_values [MONO_METHOD_SEMA_SEMANTICS];
1743 }
1744
1745 static int
1746 compare_custom_attrs (const void *a, const void *b)
1747 {
1748         const guint32 *a_values = a;
1749         const guint32 *b_values = b;
1750
1751         return a_values [MONO_CUSTOM_ATTR_PARENT] - b_values [MONO_CUSTOM_ATTR_PARENT];
1752 }
1753
1754 static int
1755 compare_field_marshal (const void *a, const void *b)
1756 {
1757         const guint32 *a_values = a;
1758         const guint32 *b_values = b;
1759
1760         return a_values [MONO_FIELD_MARSHAL_PARENT] - b_values [MONO_FIELD_MARSHAL_PARENT];
1761 }
1762
1763 static int
1764 compare_nested (const void *a, const void *b)
1765 {
1766         const guint32 *a_values = a;
1767         const guint32 *b_values = b;
1768
1769         return a_values [MONO_NESTED_CLASS_NESTED] - b_values [MONO_NESTED_CLASS_NESTED];
1770 }
1771
1772 /*
1773  * build_compressed_metadata() fills in the blob of data that represents the 
1774  * raw metadata as it will be saved in the PE file. The five streams are output 
1775  * and the metadata tables are comnpressed from the guint32 array representation, 
1776  * to the compressed on-disk format.
1777  */
1778 static void
1779 build_compressed_metadata (MonoDynamicAssembly *assembly)
1780 {
1781         MonoDynamicTable *table;
1782         int i;
1783         guint64 valid_mask = 0;
1784         guint64 sorted_mask;
1785         guint32 heapt_size = 0;
1786         guint32 meta_size = 256; /* allow for header and other stuff */
1787         guint32 table_offset;
1788         guint32 ntables = 0;
1789         guint64 *int64val;
1790         guint32 *int32val;
1791         guint16 *int16val;
1792         MonoImage *meta;
1793         unsigned char *p;
1794         /*
1795          * We need to use the current ms version or the ms runtime it won't find
1796          * the support dlls. D'oh!
1797          * const char *version = "mono-" VERSION;
1798          */
1799         const char *version = "v1.0.3705";
1800         struct StreamDesc {
1801                 const char *name;
1802                 MonoDynamicStream *stream;
1803         } stream_desc [] = {
1804                 {"#~", &assembly->tstream},
1805                 {"#Strings", &assembly->sheap},
1806                 {"#US", &assembly->us},
1807                 {"#Blob", &assembly->blob},
1808                 {"#GUID", &assembly->guid}
1809         };
1810         
1811         /* tables that are sorted */
1812         sorted_mask = ((guint64)1 << MONO_TABLE_CONSTANT) | ((guint64)1 << MONO_TABLE_FIELDMARSHAL)
1813                 | ((guint64)1 << MONO_TABLE_METHODSEMANTICS) | ((guint64)1 << MONO_TABLE_CLASSLAYOUT)
1814                 | ((guint64)1 << MONO_TABLE_FIELDLAYOUT) | ((guint64)1 << MONO_TABLE_FIELDRVA)
1815                 | ((guint64)1 << MONO_TABLE_IMPLMAP) | ((guint64)1 << MONO_TABLE_NESTEDCLASS)
1816                 | ((guint64)1 << MONO_TABLE_METHODIMPL) | ((guint64)1 << MONO_TABLE_CUSTOMATTRIBUTE)
1817                 | ((guint64)1 << MONO_TABLE_DECLSECURITY);
1818         
1819         /* Compute table sizes */
1820         /* the MonoImage has already been created in mono_image_basic_init() */
1821         meta = assembly->assembly.image;
1822         
1823         /* Setup the info used by compute_sizes () */
1824         meta->idx_blob_wide = assembly->blob.index >= 65536 ? 1 : 0;
1825         meta->idx_guid_wide = assembly->guid.index >= 65536 ? 1 : 0;
1826         meta->idx_string_wide = assembly->sheap.index >= 65536 ? 1 : 0;
1827
1828         meta_size += assembly->blob.index;
1829         meta_size += assembly->guid.index;
1830         meta_size += assembly->sheap.index;
1831         meta_size += assembly->us.index;
1832
1833         for (i=0; i < 64; ++i)
1834                 meta->tables [i].rows = assembly->tables [i].rows;
1835         
1836         for (i = 0; i < 64; i++){
1837                 if (meta->tables [i].rows == 0)
1838                         continue;
1839                 valid_mask |= (guint64)1 << i;
1840                 ntables ++;
1841                 meta->tables [i].row_size = mono_metadata_compute_size (
1842                         meta, i, &meta->tables [i].size_bitfield);
1843                 heapt_size += meta->tables [i].row_size * meta->tables [i].rows;
1844         }
1845         heapt_size += 24; /* #~ header size */
1846         heapt_size += ntables * 4;
1847         meta_size += heapt_size;
1848         meta->raw_metadata = g_malloc0 (meta_size);
1849         p = meta->raw_metadata;
1850         /* the metadata signature */
1851         *p++ = 'B'; *p++ = 'S'; *p++ = 'J'; *p++ = 'B';
1852         /* version numbers and 4 bytes reserved */
1853         int16val = (guint16*)p;
1854         *int16val++ = GUINT16_TO_LE (1);
1855         *int16val = GUINT16_TO_LE (1);
1856         p += 8;
1857         /* version string */
1858         int32val = (guint32*)p;
1859         *int32val = GUINT32_TO_LE ((strlen (version) + 3) & (~3)); /* needs to be multiple of 4 */
1860         p += 4;
1861         memcpy (p, version, GUINT32_FROM_LE (*int32val));
1862         p += GUINT32_FROM_LE (*int32val);
1863         align_pointer (meta->raw_metadata, p);
1864         int16val = (guint16*)p;
1865         *int16val++ = GUINT16_TO_LE (0); /* flags must be 0 */
1866         *int16val = GUINT16_TO_LE (5); /* number of streams */
1867         p += 4;
1868
1869         /*
1870          * write the stream info.
1871          */
1872         table_offset = (p - (unsigned char*)meta->raw_metadata) + 5 * 8 + 40; /* room needed for stream headers */
1873         table_offset += 3; table_offset &= ~3;
1874
1875         assembly->tstream.index = heapt_size;
1876         for (i = 0; i < 5; ++i) {
1877                 int32val = (guint32*)p;
1878                 stream_desc [i].stream->offset = table_offset;
1879                 *int32val++ = GUINT32_TO_LE (table_offset);
1880                 *int32val = GUINT32_TO_LE (stream_desc [i].stream->index);
1881                 table_offset += GUINT32_FROM_LE (*int32val);
1882                 table_offset += 3; table_offset &= ~3;
1883                 p += 8;
1884                 strcpy (p, stream_desc [i].name);
1885                 p += strlen (stream_desc [i].name) + 1;
1886                 align_pointer (meta->raw_metadata, p);
1887         }
1888         /* 
1889          * now copy the data, the table stream header and contents goes first.
1890          */
1891         g_assert ((p - (unsigned char*)meta->raw_metadata) < assembly->tstream.offset);
1892         p = meta->raw_metadata + assembly->tstream.offset;
1893         int32val = (guint32*)p;
1894         *int32val = GUINT32_TO_LE (0); /* reserved */
1895         p += 4;
1896         *p++ = 1; /* version */
1897         *p++ = 0;
1898         if (meta->idx_string_wide)
1899                 *p |= 0x01;
1900         if (meta->idx_guid_wide)
1901                 *p |= 0x02;
1902         if (meta->idx_blob_wide)
1903                 *p |= 0x04;
1904         ++p;
1905         *p++ = 0; /* reserved */
1906         int64val = (guint64*)p;
1907         *int64val++ = GUINT64_TO_LE (valid_mask);
1908         *int64val++ = GUINT64_TO_LE (valid_mask & sorted_mask); /* bitvector of sorted tables  */
1909         p += 16;
1910         int32val = (guint32*)p;
1911         for (i = 0; i < 64; i++){
1912                 if (meta->tables [i].rows == 0)
1913                         continue;
1914                 *int32val++ = GUINT32_TO_LE (meta->tables [i].rows);
1915         }
1916         p = (unsigned char*)int32val;
1917
1918         /* sort the tables that still need sorting */
1919         table = &assembly->tables [MONO_TABLE_METHODSEMANTICS];
1920         if (table->rows)
1921                 qsort (table->values + MONO_METHOD_SEMA_SIZE, table->rows, sizeof (guint32) * MONO_METHOD_SEMA_SIZE, compare_semantics);
1922         table = &assembly->tables [MONO_TABLE_CUSTOMATTRIBUTE];
1923         if (table->rows)
1924                 qsort (table->values + MONO_CUSTOM_ATTR_SIZE, table->rows, sizeof (guint32) * MONO_CUSTOM_ATTR_SIZE, compare_custom_attrs);
1925         table = &assembly->tables [MONO_TABLE_FIELDMARSHAL];
1926         if (table->rows)
1927                 qsort (table->values + MONO_FIELD_MARSHAL_SIZE, table->rows, sizeof (guint32) * MONO_FIELD_MARSHAL_SIZE, compare_field_marshal);
1928         table = &assembly->tables [MONO_TABLE_NESTEDCLASS];
1929         if (table->rows)
1930                 qsort (table->values + MONO_NESTED_CLASS_SIZE, table->rows, sizeof (guint32) * MONO_NESTED_CLASS_SIZE, compare_nested);
1931
1932         /* compress the tables */
1933         for (i = 0; i < 64; i++){
1934                 int row, col;
1935                 guint32 *values;
1936                 guint32 bitfield = meta->tables [i].size_bitfield;
1937                 if (!meta->tables [i].rows)
1938                         continue;
1939                 if (assembly->tables [i].columns != mono_metadata_table_count (bitfield))
1940                         g_error ("col count mismatch in %d: %d %d", i, assembly->tables [i].columns, mono_metadata_table_count (bitfield));
1941                 meta->tables [i].base = p;
1942                 for (row = 1; row <= meta->tables [i].rows; ++row) {
1943                         values = assembly->tables [i].values + row * assembly->tables [i].columns;
1944                         for (col = 0; col < assembly->tables [i].columns; ++col) {
1945                                 switch (mono_metadata_table_size (bitfield, col)) {
1946                                 case 1:
1947                                         *p++ = values [col];
1948                                         break;
1949                                 case 2:
1950                                         *p++ = values [col] & 0xff;
1951                                         *p++ = (values [col] >> 8) & 0xff;
1952                                         break;
1953                                 case 4:
1954                                         *p++ = values [col] & 0xff;
1955                                         *p++ = (values [col] >> 8) & 0xff;
1956                                         *p++ = (values [col] >> 16) & 0xff;
1957                                         *p++ = (values [col] >> 24) & 0xff;
1958                                         break;
1959                                 default:
1960                                         g_assert_not_reached ();
1961                                 }
1962                         }
1963                 }
1964                 g_assert ((p - (const unsigned char*)meta->tables [i].base) == (meta->tables [i].rows * meta->tables [i].row_size));
1965         }
1966         
1967         g_assert (assembly->guid.offset + assembly->guid.index < meta_size);
1968         memcpy (meta->raw_metadata + assembly->sheap.offset, assembly->sheap.data, assembly->sheap.index);
1969         memcpy (meta->raw_metadata + assembly->us.offset, assembly->us.data, assembly->us.index);
1970         memcpy (meta->raw_metadata + assembly->blob.offset, assembly->blob.data, assembly->blob.index);
1971         memcpy (meta->raw_metadata + assembly->guid.offset, assembly->guid.data, assembly->guid.index);
1972
1973         assembly->meta_size = assembly->guid.offset + assembly->guid.index;
1974 }
1975
1976 /*
1977  * Some tables in metadata need to be sorted according to some criteria, but
1978  * when methods and fields are first created with reflection, they may be assigned a token
1979  * that doesn't correspond to the final token they will get assigned after the sorting.
1980  * ILGenerator.cs keeps a fixup table that maps the position of tokens in the IL code stream
1981  * with the reflection objects that represent them. Once all the tables are set up, the 
1982  * reflection objects will contains the correct table index. fixup_method() will fixup the
1983  * tokens for the method with ILGenerator @ilgen.
1984  */
1985 static void
1986 fixup_method (MonoReflectionILGen *ilgen, gpointer value, MonoDynamicAssembly *assembly) {
1987         guint32 code_idx = GPOINTER_TO_UINT (value);
1988         MonoReflectionILTokenInfo *iltoken;
1989         MonoReflectionFieldBuilder *field;
1990         MonoReflectionCtorBuilder *ctor;
1991         MonoReflectionMethodBuilder *method;
1992         MonoReflectionTypeBuilder *tb;
1993         guint32 i, idx;
1994         unsigned char *target;
1995
1996         for (i = 0; i < ilgen->num_token_fixups; ++i) {
1997                 iltoken = (MonoReflectionILTokenInfo *)mono_array_addr_with_size (ilgen->token_fixups, sizeof (MonoReflectionILTokenInfo), i);
1998                 target = assembly->code.data + code_idx + iltoken->code_pos;
1999                 switch (target [3]) {
2000                 case MONO_TABLE_FIELD:
2001                         if (strcmp (iltoken->member->vtable->klass->name, "FieldBuilder"))
2002                                 g_assert_not_reached ();
2003                         field = (MonoReflectionFieldBuilder *)iltoken->member;
2004                         idx = field->table_idx;
2005                         break;
2006                 case MONO_TABLE_METHOD:
2007                         if (!strcmp (iltoken->member->vtable->klass->name, "MethodBuilder")) {
2008                                 method = (MonoReflectionMethodBuilder *)iltoken->member;
2009                                 idx = method->table_idx;
2010                         } else if (!strcmp (iltoken->member->vtable->klass->name, "ConstructorBuilder")) {
2011                                 ctor = (MonoReflectionCtorBuilder *)iltoken->member;
2012                                 idx = ctor->table_idx;
2013                         } else {
2014                                 g_assert_not_reached ();
2015                         }
2016                         break;
2017                 case MONO_TABLE_TYPEDEF:
2018                         if (strcmp (iltoken->member->vtable->klass->name, "TypeBuilder"))
2019                                 g_assert_not_reached ();
2020                         tb = (MonoReflectionTypeBuilder *)iltoken->member;
2021                         idx = tb->table_idx;
2022                         break;
2023                 default:
2024                         g_error ("got unexpected table 0x%02x in fixup", target [3]);
2025                 }
2026                 target [0] = idx & 0xff;
2027                 target [1] = (idx >> 8) & 0xff;
2028                 target [2] = (idx >> 16) & 0xff;
2029         }
2030 }
2031
2032 static void
2033 assembly_add_resource (MonoDynamicAssembly *assembly, MonoReflectionResource *rsrc)
2034 {
2035         MonoDynamicTable *table;
2036         guint32 *values;
2037         char blob_size [6];
2038         guchar hash [20];
2039         char *b = blob_size;
2040         char *name, *sname;
2041         guint32 idx, offset;
2042
2043         if (rsrc->filename) {
2044                 name = mono_string_to_utf8 (rsrc->filename);
2045                 sname = g_path_get_basename (name);
2046         
2047                 table = &assembly->tables [MONO_TABLE_FILE];
2048                 table->rows++;
2049                 alloc_table (table, table->rows);
2050                 values = table->values + table->next_idx * MONO_FILE_SIZE;
2051                 values [MONO_FILE_FLAGS] = FILE_CONTAINS_NO_METADATA;
2052                 values [MONO_FILE_NAME] = string_heap_insert (&assembly->sheap, sname);
2053                 g_free (sname);
2054
2055                 mono_sha1_get_digest_from_file (name, hash);
2056                 mono_metadata_encode_value (20, b, &b);
2057                 values [MONO_FILE_HASH_VALUE] = mono_image_add_stream_data (&assembly->blob, blob_size, b-blob_size);
2058                 mono_image_add_stream_data (&assembly->blob, hash, 20);
2059                 g_free (name);
2060                 idx = table->next_idx++;
2061                 idx = IMPLEMENTATION_FILE | (idx << IMPLEMENTATION_BITS);
2062                 offset = 0;
2063         } else {
2064                 char sizebuf [4];
2065                 offset = mono_array_length (rsrc->data);
2066                 sizebuf [0] = offset; sizebuf [1] = offset >> 8;
2067                 sizebuf [2] = offset >> 16; sizebuf [3] = offset >> 24;
2068                 offset = mono_image_add_stream_data (&assembly->resources, sizebuf, 4);
2069                 mono_image_add_stream_data (&assembly->resources, mono_array_addr (rsrc->data, char, 0), mono_array_length (rsrc->data));
2070                 idx = 0;
2071         }
2072
2073         table = &assembly->tables [MONO_TABLE_MANIFESTRESOURCE];
2074         table->rows++;
2075         alloc_table (table, table->rows);
2076         values = table->values + table->next_idx * MONO_MANIFEST_SIZE;
2077         values [MONO_MANIFEST_OFFSET] = offset;
2078         values [MONO_MANIFEST_FLAGS] = rsrc->attrs;
2079         name = mono_string_to_utf8 (rsrc->name);
2080         values [MONO_MANIFEST_NAME] = string_heap_insert (&assembly->sheap, name);
2081         g_free (name);
2082         values [MONO_MANIFEST_IMPLEMENTATION] = idx;
2083         table->next_idx++;
2084 }
2085
2086 static void
2087 set_version_from_string (MonoString *version, guint32 *values)
2088 {
2089         gchar *ver, *p, *str;
2090         guint32 i;
2091         
2092         values [MONO_ASSEMBLY_MAJOR_VERSION] = 0;
2093         values [MONO_ASSEMBLY_MINOR_VERSION] = 0;
2094         values [MONO_ASSEMBLY_REV_NUMBER] = 0;
2095         values [MONO_ASSEMBLY_BUILD_NUMBER] = 0;
2096         if (!version)
2097                 return;
2098         ver = str = mono_string_to_utf8 (version);
2099         for (i = 0; i < 4; ++i) {
2100                 values [MONO_ASSEMBLY_MAJOR_VERSION + i] = strtol (ver, &p, 10);
2101                 switch (*p) {
2102                 case '.':
2103                         p++;
2104                         break;
2105                 case '*':
2106                         /* handle Revision and Build */
2107                         p++;
2108                         break;
2109                 }
2110                 ver = p;
2111         }
2112         g_free (str);
2113 }
2114
2115 static guint32
2116 load_public_key (MonoString *fname, MonoDynamicAssembly *assembly) {
2117         char *name, *content;
2118         gsize len;
2119         guint32 token = 0;
2120
2121         if (!fname)
2122                 return token;
2123         name = mono_string_to_utf8 (fname);
2124         if (g_file_get_contents (name, &content, &len, NULL)) {
2125                 char blob_size [6];
2126                 char *b = blob_size;
2127                 /* check it's a public key or keypair */
2128                 mono_metadata_encode_value (len, b, &b);
2129                 token = mono_image_add_stream_data (&assembly->blob, blob_size, b - blob_size);
2130                 mono_image_add_stream_data (&assembly->blob, content, len);
2131                 g_free (content);
2132                 /* need to get the actual value from the key type... */
2133                 assembly->strong_name_size = 128;
2134                 assembly->strong_name = g_malloc0 (assembly->strong_name_size);
2135         }
2136         /* FIXME: how do we tell mcs if loading fails? */
2137         g_free (name);
2138         return token;
2139 }
2140
2141 /*
2142  * mono_image_build_metadata() will fill the info in all the needed metadata tables
2143  * for the AssemblyBuilder @assemblyb: it iterates over the assembly modules
2144  * and recursively outputs the info for a module. Each module will output all the info
2145  * about it's types etc.
2146  * At the end of the process, method and field tokens are fixed up and the on-disk
2147  * compressed metadata representation is created.
2148  */
2149 static void
2150 mono_image_build_metadata (MonoReflectionAssemblyBuilder *assemblyb)
2151 {
2152         MonoDynamicTable *table;
2153         MonoDynamicAssembly *assembly = assemblyb->dynamic_assembly;
2154         MonoDomain *domain = mono_object_domain (assemblyb);
2155         guint32 len;
2156         guint32 *values;
2157         char *name;
2158         int i;
2159         
2160         assembly->text_rva = START_TEXT_RVA;
2161
2162         table = &assembly->tables [MONO_TABLE_ASSEMBLY];
2163         alloc_table (table, 1);
2164         values = table->values + MONO_ASSEMBLY_SIZE;
2165         values [MONO_ASSEMBLY_HASH_ALG] = assemblyb->algid? assemblyb->algid: ASSEMBLY_HASH_SHA1;
2166         name = mono_string_to_utf8 (assemblyb->name);
2167         values [MONO_ASSEMBLY_NAME] = string_heap_insert (&assembly->sheap, name);
2168         g_free (name);
2169         if (assemblyb->culture) {
2170                 name = mono_string_to_utf8 (assemblyb->culture);
2171                 values [MONO_ASSEMBLY_CULTURE] = string_heap_insert (&assembly->sheap, name);
2172                 g_free (name);
2173         } else {
2174                 values [MONO_ASSEMBLY_CULTURE] = string_heap_insert (&assembly->sheap, "");
2175         }
2176         values [MONO_ASSEMBLY_PUBLIC_KEY] = load_public_key (assemblyb->keyfile, assembly);
2177         values [MONO_ASSEMBLY_FLAGS] = assemblyb->flags;
2178         set_version_from_string (assemblyb->version, values);
2179
2180         assembly->tables [MONO_TABLE_TYPEDEF].rows = 1; /* .<Module> */
2181         assembly->tables [MONO_TABLE_TYPEDEF].next_idx++;
2182
2183         if (assemblyb->modules) {
2184                 len = mono_array_length (assemblyb->modules);
2185                 table = &assembly->tables [MONO_TABLE_MODULE];
2186                 alloc_table (table, len);
2187                 for (i = 0; i < len; ++i)
2188                         mono_image_fill_module_table (domain, mono_array_get (assemblyb->modules, MonoReflectionModuleBuilder*, i), assembly);
2189         } else {
2190                 table = &assembly->tables [MONO_TABLE_MODULE];
2191                 table->rows++;
2192                 alloc_table (table, table->rows);
2193                 table->values [table->next_idx * MONO_MODULE_SIZE + MONO_MODULE_NAME] = string_heap_insert (&assembly->sheap, "RefEmit_YouForgotToDefineAModule");
2194                 table->next_idx ++;
2195         }
2196
2197         table = &assembly->tables [MONO_TABLE_TYPEDEF];
2198         /* 
2199          * table->rows is already set above and in mono_image_fill_module_table.
2200          */
2201         alloc_table (table, table->rows);
2202         /*
2203          * Set the first entry.
2204          */
2205         values = table->values + table->columns;
2206         values [MONO_TYPEDEF_FLAGS] = 0;
2207         values [MONO_TYPEDEF_NAME] = string_heap_insert (&assembly->sheap, "<Module>") ;
2208         values [MONO_TYPEDEF_NAMESPACE] = string_heap_insert (&assembly->sheap, "") ;
2209         values [MONO_TYPEDEF_EXTENDS] = 0;
2210         values [MONO_TYPEDEF_FIELD_LIST] = 1;
2211         values [MONO_TYPEDEF_METHOD_LIST] = 1;
2212
2213         /* add all the custom attributes at the end, once all the indexes are stable */
2214         mono_image_add_cattrs (assembly, 1, CUSTOM_ATTR_ASSEMBLY, assemblyb->cattrs);
2215
2216         if (assemblyb->modules) {
2217                 len = mono_array_length (assemblyb->modules);
2218                 for (i = 0; i < len; ++i)
2219                         module_add_cattrs (assembly, mono_array_get (assemblyb->modules, MonoReflectionModuleBuilder*, i));
2220         }
2221
2222         if (assemblyb->resources) {
2223                 len = mono_array_length (assemblyb->resources);
2224                 for (i = 0; i < len; ++i)
2225                         assembly_add_resource (assembly, (MonoReflectionResource*)mono_array_addr (assemblyb->resources, MonoReflectionResource, i));
2226         }
2227         
2228         /* fixup tokens */
2229         mono_g_hash_table_foreach (assembly->token_fixups, (GHFunc)fixup_method, assembly);
2230         
2231         build_compressed_metadata (assembly);
2232 }
2233
2234 /*
2235  * mono_image_insert_string:
2236  * @assembly: assembly builder object
2237  * @str: a string
2238  *
2239  * Insert @str into the user string stream of @assembly.
2240  */
2241 guint32
2242 mono_image_insert_string (MonoReflectionAssemblyBuilder *assembly, MonoString *str)
2243 {
2244         guint32 idx;
2245         char buf [16];
2246         char *b = buf;
2247         
2248         if (!assembly->dynamic_assembly)
2249                 mono_image_basic_init (assembly);
2250         mono_metadata_encode_value (1 | (str->length * 2), b, &b);
2251         idx = mono_image_add_stream_data (&assembly->dynamic_assembly->us, buf, b-buf);
2252 #if G_BYTE_ORDER != G_LITTLE_ENDIAN
2253         {
2254                 char *swapped = g_malloc (2 * mono_string_length (str));
2255                 const char *p = (const char*)mono_string_chars (str);
2256
2257                 swap_with_size (swapped, p, 2, mono_string_length (str));
2258                 mono_image_add_stream_data (&assembly->dynamic_assembly->us, swapped, str->length * 2);
2259                 g_free (swapped);
2260         }
2261 #else
2262         mono_image_add_stream_data (&assembly->dynamic_assembly->us, (const char*)mono_string_chars (str), str->length * 2);
2263 #endif
2264         mono_image_add_stream_data (&assembly->dynamic_assembly->us, "", 1);
2265         return MONO_TOKEN_STRING | idx;
2266 }
2267
2268 /*
2269  * mono_image_create_token:
2270  * @assembly: a dynamic assembly
2271  * @obj:
2272  *
2273  * Get a token to insert in the IL code stream for the given MemberInfo.
2274  * @obj can be one of:
2275  *      ConstructorBuilder
2276  *      MethodBuilder
2277  *      FieldBuilder
2278  *      MonoCMethod
2279  *      MonoMethod
2280  *      MonoField
2281  *      MonoType
2282  *      TypeBuilder
2283  */
2284 guint32
2285 mono_image_create_token (MonoDynamicAssembly *assembly, MonoObject *obj)
2286 {
2287         MonoClass *klass;
2288         guint32 token;
2289
2290         if (!obj)
2291                 g_error ("System.Array methods not yet supported");
2292         
2293         klass = obj->vtable->klass;
2294         if (strcmp (klass->name, "MethodBuilder") == 0) {
2295                 MonoReflectionMethodBuilder *mb = (MonoReflectionMethodBuilder *)obj;
2296                 token = mb->table_idx | MONO_TOKEN_METHOD_DEF;
2297                 /*g_print ("got token 0x%08x for %s\n", token, mono_string_to_utf8 (mb->name));*/
2298                 return token;
2299         }
2300         if (strcmp (klass->name, "ConstructorBuilder") == 0) {
2301                 MonoReflectionCtorBuilder *mb = (MonoReflectionCtorBuilder *)obj;
2302                 token = mb->table_idx | MONO_TOKEN_METHOD_DEF;
2303                 /*g_print ("got token 0x%08x for %s\n", token, mono_string_to_utf8 (mb->name));*/
2304                 return token;
2305         }
2306         if (strcmp (klass->name, "FieldBuilder") == 0) {
2307                 MonoReflectionFieldBuilder *mb = (MonoReflectionFieldBuilder *)obj;
2308                 return mb->table_idx | MONO_TOKEN_FIELD_DEF;
2309         }
2310         if (strcmp (klass->name, "TypeBuilder") == 0) {
2311                 MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder *)obj;
2312                 return tb->table_idx | MONO_TOKEN_TYPE_DEF;
2313         }
2314         if (strcmp (klass->name, "MonoType") == 0) {
2315                 MonoReflectionType *tb = (MonoReflectionType *)obj;
2316                 return mono_metadata_token_from_dor (
2317                         mono_image_typedef_or_ref (assembly, tb->type));
2318         }
2319         if (strcmp (klass->name, "MonoCMethod") == 0 ||
2320                         strcmp (klass->name, "MonoMethod") == 0) {
2321                 MonoReflectionMethod *m = (MonoReflectionMethod *)obj;
2322                 token = mono_image_get_methodref_token (assembly, m->method);
2323                 /*g_print ("got token 0x%08x for %s\n", token, m->method->name);*/
2324                 return token;
2325         }
2326         if (strcmp (klass->name, "MonoField") == 0) {
2327                 MonoReflectionField *f = (MonoReflectionField *)obj;
2328                 token = mono_image_get_fieldref_token (assembly, f->field, f->klass);
2329                 /*g_print ("got token 0x%08x for %s\n", token, f->field->name);*/
2330                 return token;
2331         }
2332         if (strcmp (klass->name, "MonoArrayMethod") == 0) {
2333                 MonoReflectionArrayMethod *m = (MonoReflectionArrayMethod *)obj;
2334                 token = mono_image_get_array_token (assembly, m);
2335                 return token;
2336         }
2337         g_print ("requested token for %s\n", klass->name);
2338         return 0;
2339 }
2340
2341 typedef struct {
2342         guint32 import_lookup_table;
2343         guint32 timestamp;
2344         guint32 forwarder;
2345         guint32 name_rva;
2346         guint32 import_address_table_rva;
2347 } MonoIDT;
2348
2349 typedef struct {
2350         guint32 name_rva;
2351         guint32 flags;
2352 } MonoILT;
2353
2354 /*
2355  * mono_image_basic_ini:
2356  * @assembly: an assembly builder object
2357  *
2358  * Create the MonoImage that represents the assembly builder and setup some
2359  * of the helper hash table and the basic metadata streams.
2360  */
2361 void
2362 mono_image_basic_init (MonoReflectionAssemblyBuilder *assemblyb)
2363 {
2364         static const guchar entrycode [16] = {0xff, 0x25, 0};
2365         MonoDynamicAssembly *assembly;
2366         MonoImage *image;
2367         int i;
2368         
2369         if (assemblyb->dynamic_assembly)
2370                 return;
2371
2372 #if HAVE_BOEHM_GC
2373         assembly = assemblyb->dynamic_assembly = GC_malloc (sizeof (MonoDynamicAssembly));
2374 #else
2375         assembly = assemblyb->dynamic_assembly = g_new0 (MonoDynamicAssembly, 1);
2376 #endif
2377
2378         assemblyb->assembly.assembly = (MonoAssembly*)assembly;
2379         assembly->token_fixups = mono_g_hash_table_new (g_direct_hash, g_direct_equal);
2380         assembly->handleref = g_hash_table_new (g_direct_hash, g_direct_equal);
2381         assembly->typeref = g_hash_table_new ((GHashFunc)mono_metadata_type_hash, (GCompareFunc)mono_metadata_type_equal);
2382
2383         string_heap_init (&assembly->sheap);
2384         mono_image_add_stream_data (&assembly->us, "", 1);
2385         mono_image_add_stream_data (&assembly->blob, "", 1);
2386         /* import tables... */
2387         mono_image_add_stream_data (&assembly->code, entrycode, sizeof (entrycode));
2388         assembly->iat_offset = mono_image_add_stream_zero (&assembly->code, 8); /* two IAT entries */
2389         assembly->idt_offset = mono_image_add_stream_zero (&assembly->code, 2 * sizeof (MonoIDT)); /* two IDT entries */
2390         mono_image_add_stream_zero (&assembly->code, 2); /* flags for name entry */
2391         assembly->imp_names_offset = mono_image_add_stream_data (&assembly->code, "_CorExeMain", 12);
2392         mono_image_add_stream_data (&assembly->code, "mscoree.dll", 12);
2393         assembly->ilt_offset = mono_image_add_stream_zero (&assembly->code, 8); /* two ILT entries */
2394         stream_data_align (&assembly->code);
2395
2396         assembly->cli_header_offset = mono_image_add_stream_zero (&assembly->code, sizeof (MonoCLIHeader));
2397
2398         for (i=0; i < 64; ++i) {
2399                 assembly->tables [i].next_idx = 1;
2400                 assembly->tables [i].columns = table_sizes [i];
2401         }
2402
2403         image = g_new0 (MonoImage, 1);
2404         
2405         /* keep in sync with image.c */
2406         assembly->assembly.aname.name = image->name = mono_string_to_utf8 (assemblyb->name);
2407         image->assembly_name = image->name; /* they may be different */
2408
2409         image->method_cache = g_hash_table_new (g_direct_hash, g_direct_equal);
2410         image->class_cache = g_hash_table_new (g_direct_hash, g_direct_equal);
2411         image->name_cache = g_hash_table_new (g_str_hash, g_str_equal);
2412         image->array_cache = g_hash_table_new (g_direct_hash, g_direct_equal);
2413
2414         image->delegate_begin_invoke_cache = 
2415                 g_hash_table_new ((GHashFunc)mono_signature_hash, 
2416                                   (GCompareFunc)mono_metadata_signature_equal);
2417         image->delegate_end_invoke_cache = 
2418                 g_hash_table_new ((GHashFunc)mono_signature_hash, 
2419                                   (GCompareFunc)mono_metadata_signature_equal);
2420         image->delegate_invoke_cache = 
2421                 g_hash_table_new ((GHashFunc)mono_signature_hash, 
2422                                   (GCompareFunc)mono_metadata_signature_equal);
2423
2424         image->runtime_invoke_cache = g_hash_table_new (g_direct_hash, g_direct_equal);
2425         image->managed_wrapper_cache = g_hash_table_new (g_direct_hash, g_direct_equal);
2426         image->native_wrapper_cache = g_hash_table_new (g_direct_hash, g_direct_equal);
2427         image->remoting_invoke_cache = g_hash_table_new (g_direct_hash, g_direct_equal);
2428         assembly->assembly.image = image;
2429         
2430 }
2431
2432 static int
2433 calc_section_size (MonoDynamicAssembly *assembly)
2434 {
2435         int nsections = 0;
2436
2437         /* alignment constraints */
2438         assembly->code.index += 3;
2439         assembly->code.index &= ~3;
2440         assembly->meta_size += 3;
2441         assembly->meta_size &= ~3;
2442         assembly->resources.index += 3;
2443         assembly->resources.index &= ~3;
2444
2445         assembly->sections [MONO_SECTION_TEXT].size = assembly->meta_size + assembly->code.index + assembly->resources.index + assembly->strong_name_size;
2446         assembly->sections [MONO_SECTION_TEXT].attrs = SECT_FLAGS_HAS_CODE | SECT_FLAGS_MEM_EXECUTE | SECT_FLAGS_MEM_READ;
2447         nsections++;
2448
2449         assembly->sections [MONO_SECTION_RELOC].size = 12;
2450         assembly->sections [MONO_SECTION_RELOC].attrs = SECT_FLAGS_MEM_READ | SECT_FLAGS_MEM_DISCARDABLE | SECT_FLAGS_HAS_INITIALIZED_DATA;
2451         nsections++;
2452
2453         return nsections;
2454 }
2455
2456 /*
2457  * mono_image_create_pefile:
2458  * @assemblyb: an assembly builder object
2459  * 
2460  * When we need to save an assembly, we first call this function that ensures the metadata 
2461  * tables are built for all the modules in the assembly. This function creates the PE-COFF
2462  * header, the image sections, the CLI header etc. all the data is written in
2463  * assembly->pefile where it can be easily retrieved later in chunks.
2464  */
2465 void
2466 mono_image_create_pefile (MonoReflectionAssemblyBuilder *assemblyb) {
2467         MonoMSDOSHeader *msdos;
2468         MonoDotNetHeader *header;
2469         MonoSectionTable *section;
2470         MonoCLIHeader *cli_header;
2471         guint32 size, image_size, virtual_base, text_offset;
2472         guint32 header_start, section_start, file_offset, virtual_offset;
2473         MonoDynamicAssembly *assembly;
2474         MonoDynamicStream *pefile;
2475         int i, nsections;
2476         guint32 *rva, value;
2477         guint16 *data16;
2478         guchar *p;
2479         static const unsigned char msheader[] = {
2480                 0x4d, 0x5a, 0x90, 0x00, 0x03, 0x00, 0x00, 0x00,  0x04, 0x00, 0x00, 0x00, 0xff, 0xff, 0x00, 0x00,
2481                 0xb8, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,  0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
2482                 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
2483                 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,  0x00, 0x00, 0x00, 0x00, 0x80, 0x00, 0x00, 0x00,
2484                 0x0e, 0x1f, 0xba, 0x0e, 0x00, 0xb4, 0x09, 0xcd,  0x21, 0xb8, 0x01, 0x4c, 0xcd, 0x21, 0x54, 0x68,
2485                 0x69, 0x73, 0x20, 0x70, 0x72, 0x6f, 0x67, 0x72,  0x61, 0x6d, 0x20, 0x63, 0x61, 0x6e, 0x6e, 0x6f,
2486                 0x74, 0x20, 0x62, 0x65, 0x20, 0x72, 0x75, 0x6e,  0x20, 0x69, 0x6e, 0x20, 0x44, 0x4f, 0x53, 0x20,
2487                 0x6d, 0x6f, 0x64, 0x65, 0x2e, 0x0d, 0x0d, 0x0a,  0x24, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
2488         };
2489
2490         mono_image_basic_init (assemblyb);
2491         assembly = assemblyb->dynamic_assembly;
2492
2493         /* already created */
2494         if (assembly->pefile.index)
2495                 return;
2496         
2497         mono_image_build_metadata (assemblyb);
2498         nsections = calc_section_size (assembly);
2499
2500         pefile = &assembly->pefile;
2501
2502         /* The DOS header and stub */
2503         g_assert (sizeof (MonoMSDOSHeader) == sizeof (msheader));
2504         mono_image_add_stream_data (pefile, msheader, sizeof (msheader));
2505
2506         /* the dotnet header */
2507         header_start = mono_image_add_stream_zero (pefile, sizeof (MonoDotNetHeader));
2508
2509         /* the section tables */
2510         section_start = mono_image_add_stream_zero (pefile, sizeof (MonoSectionTable) * nsections);
2511
2512         file_offset = section_start + sizeof (MonoSectionTable) * nsections;
2513         virtual_offset = VIRT_ALIGN;
2514         image_size = 0;
2515
2516         for (i = 0; i < MONO_SECTION_MAX; ++i) {
2517                 if (!assembly->sections [i].size)
2518                         continue;
2519                 /* align offsets */
2520                 file_offset += FILE_ALIGN - 1;
2521                 file_offset &= ~(FILE_ALIGN - 1);
2522                 virtual_offset += VIRT_ALIGN - 1;
2523                 virtual_offset &= ~(VIRT_ALIGN - 1);
2524
2525                 assembly->sections [i].offset = file_offset;
2526                 assembly->sections [i].rva = virtual_offset;
2527
2528                 file_offset += assembly->sections [i].size;
2529                 virtual_offset += assembly->sections [i].size;
2530                 image_size += (assembly->sections [i].size + VIRT_ALIGN - 1) & ~(VIRT_ALIGN - 1);
2531         }
2532
2533         file_offset += FILE_ALIGN - 1;
2534         file_offset &= ~(FILE_ALIGN - 1);
2535         mono_image_add_stream_zero (pefile, file_offset - pefile->index);
2536
2537         image_size += section_start + sizeof (MonoSectionTable) * nsections;
2538
2539         /* back-patch info */
2540         msdos = (MonoMSDOSHeader*)pefile->data;
2541         msdos->nlast_page = GUINT16_FROM_LE (file_offset & (512 - 1));
2542         msdos->npages = GUINT16_FROM_LE ((file_offset + (512 - 1)) / 512);
2543         msdos->pe_offset = GUINT32_FROM_LE (sizeof (MonoMSDOSHeader));
2544
2545         header = (MonoDotNetHeader*)(pefile->data + header_start);
2546         header->pesig [0] = 'P';
2547         header->pesig [1] = 'E';
2548         
2549         header->coff.coff_machine = GUINT16_FROM_LE (0x14c);
2550         header->coff.coff_sections = GUINT16_FROM_LE (nsections);
2551         header->coff.coff_time = GUINT32_FROM_LE (time (NULL));
2552         header->coff.coff_opt_header_size = GUINT16_FROM_LE (sizeof (MonoDotNetHeader) - sizeof (MonoCOFFHeader) - 4);
2553         if (assemblyb->pekind == 1) {
2554                 /* it's a dll */
2555                 header->coff.coff_attributes = GUINT16_FROM_LE (0x210e);
2556         } else {
2557                 /* it's an exe */
2558                 header->coff.coff_attributes = GUINT16_FROM_LE (0x010e);
2559         }
2560
2561         virtual_base = 0x400000; /* FIXME: 0x10000000 if a DLL */
2562
2563         header->pe.pe_magic = GUINT16_FROM_LE (0x10B);
2564         header->pe.pe_major = 6;
2565         header->pe.pe_minor = 0;
2566         size = assembly->sections [MONO_SECTION_TEXT].size;
2567         size += FILE_ALIGN - 1;
2568         size &= ~(FILE_ALIGN - 1);
2569         header->pe.pe_code_size = size;
2570         size = assembly->sections [MONO_SECTION_RSRC].size;
2571         size += FILE_ALIGN - 1;
2572         size &= ~(FILE_ALIGN - 1);
2573         header->pe.pe_data_size = size;
2574         g_assert (START_TEXT_RVA == assembly->sections [MONO_SECTION_TEXT].rva);
2575         header->pe.pe_rva_code_base = assembly->sections [MONO_SECTION_TEXT].rva;
2576         header->pe.pe_rva_data_base = assembly->sections [MONO_SECTION_RSRC].rva;
2577         /* pe_rva_entry_point always at the beginning of the text section */
2578         header->pe.pe_rva_entry_point = assembly->sections [MONO_SECTION_TEXT].rva;
2579
2580         header->nt.pe_image_base = GUINT32_FROM_LE (virtual_base);
2581         header->nt.pe_section_align = GUINT32_FROM_LE (VIRT_ALIGN);
2582         header->nt.pe_file_alignment = GUINT32_FROM_LE (FILE_ALIGN);
2583         header->nt.pe_os_major = GUINT16_FROM_LE (4);
2584         header->nt.pe_os_minor = GUINT16_FROM_LE (0);
2585         header->nt.pe_subsys_major = GUINT16_FROM_LE (4);
2586         size = section_start;
2587         size += FILE_ALIGN - 1;
2588         size &= ~(FILE_ALIGN - 1);
2589         header->nt.pe_header_size = GUINT32_FROM_LE (size);
2590         size = image_size;
2591         size += VIRT_ALIGN - 1;
2592         size &= ~(VIRT_ALIGN - 1);
2593         header->nt.pe_image_size = GUINT32_FROM_LE (size);
2594         header->nt.pe_subsys_required = GUINT16_FROM_LE (assemblyb->pekind); /* 3 -> cmdline app, 2 -> GUI app */
2595         header->nt.pe_stack_reserve = GUINT32_FROM_LE (0x00100000);
2596         header->nt.pe_stack_commit = GUINT32_FROM_LE (0x00001000);
2597         header->nt.pe_heap_reserve = GUINT32_FROM_LE (0x00100000);
2598         header->nt.pe_heap_commit = GUINT32_FROM_LE (0x00001000);
2599         header->nt.pe_loader_flags = GUINT32_FROM_LE (0);
2600         header->nt.pe_data_dir_count = GUINT32_FROM_LE (16);
2601
2602         /* fill data directory entries */
2603
2604         header->datadir.pe_resource_table.size = GUINT32_FROM_LE (assembly->sections [MONO_SECTION_RSRC].size);
2605         header->datadir.pe_resource_table.rva = GUINT32_FROM_LE (assembly->sections [MONO_SECTION_RSRC].rva);
2606
2607         header->datadir.pe_reloc_table.size = GUINT32_FROM_LE (assembly->sections [MONO_SECTION_RELOC].size);
2608         header->datadir.pe_reloc_table.rva = GUINT32_FROM_LE (assembly->sections [MONO_SECTION_RELOC].rva);
2609
2610         header->datadir.pe_cli_header.size = GUINT32_FROM_LE (72);
2611         header->datadir.pe_cli_header.rva = GUINT32_FROM_LE (assembly->text_rva + assembly->cli_header_offset);
2612         header->datadir.pe_iat.size = GUINT32_FROM_LE (8);
2613         header->datadir.pe_iat.rva = GUINT32_FROM_LE (assembly->text_rva + assembly->iat_offset);
2614         /* patch imported function RVA name */
2615         rva = (guint32*)(assembly->code.data + assembly->iat_offset);
2616         *rva = GUINT32_FROM_LE (assembly->text_rva + assembly->imp_names_offset);
2617
2618         /* the import table */
2619         header->datadir.pe_import_table.size = GUINT32_FROM_LE (79); /* FIXME: magic number? */
2620         header->datadir.pe_import_table.rva = GUINT32_FROM_LE (assembly->text_rva + assembly->idt_offset);
2621         /* patch imported dll RVA name and other entries in the dir */
2622         rva = (guint32*)(assembly->code.data + assembly->idt_offset + G_STRUCT_OFFSET (MonoIDT, name_rva));
2623         *rva = GUINT32_FROM_LE (assembly->text_rva + assembly->imp_names_offset + 12); /* 12 is strlen+1 of func name */
2624         rva = (guint32*)(assembly->code.data + assembly->idt_offset + G_STRUCT_OFFSET (MonoIDT, import_address_table_rva));
2625         *rva = GUINT32_FROM_LE (assembly->text_rva + assembly->iat_offset);
2626         rva = (guint32*)(assembly->code.data + assembly->idt_offset + G_STRUCT_OFFSET (MonoIDT, import_lookup_table));
2627         *rva = GUINT32_FROM_LE (assembly->text_rva + assembly->ilt_offset);
2628
2629         p = (assembly->code.data + assembly->ilt_offset);
2630         value = (assembly->text_rva + assembly->imp_names_offset - 2);
2631         *p++ = (value) & 0xff;
2632         *p++ = (value >> 8) & (0xff);
2633         *p++ = (value >> 16) & (0xff);
2634         *p++ = (value >> 24) & (0xff);
2635
2636         /* the CLI header info */
2637         cli_header = (MonoCLIHeader*)(assembly->code.data + assembly->cli_header_offset);
2638         cli_header->ch_size = GUINT32_FROM_LE (72);
2639         cli_header->ch_runtime_major = GUINT16_FROM_LE (2);
2640         cli_header->ch_flags = GUINT32_FROM_LE (CLI_FLAGS_ILONLY);
2641         if (assemblyb->entry_point) 
2642                 cli_header->ch_entry_point = GUINT32_FROM_LE (assemblyb->entry_point->table_idx | MONO_TOKEN_METHOD_DEF);
2643         else
2644                 cli_header->ch_entry_point = GUINT32_FROM_LE (0);
2645         /* The embedded managed resources */
2646         text_offset = assembly->text_rva + assembly->code.index;
2647         cli_header->ch_resources.rva = GUINT32_FROM_LE (text_offset);
2648         cli_header->ch_resources.size = GUINT32_FROM_LE (assembly->resources.index);
2649         text_offset += assembly->resources.index;
2650         cli_header->ch_metadata.rva = GUINT32_FROM_LE (text_offset);
2651         cli_header->ch_metadata.size = GUINT32_FROM_LE (assembly->meta_size);
2652         text_offset += assembly->meta_size;
2653         if (assembly->strong_name_size) {
2654                 cli_header->ch_strong_name.rva = GUINT32_FROM_LE (text_offset);
2655                 cli_header->ch_strong_name.size = GUINT32_FROM_LE (assembly->strong_name_size);
2656                 text_offset += assembly->strong_name_size;
2657         }
2658
2659         /* write the section tables and section content */
2660         section = (MonoSectionTable*)(pefile->data + section_start);
2661         for (i = 0; i < MONO_SECTION_MAX; ++i) {
2662                 static const char *section_names [] = {
2663                         ".text", ".rsrc", ".reloc"
2664                 };
2665                 if (!assembly->sections [i].size)
2666                         continue;
2667                 strcpy (section->st_name, section_names [i]);
2668                 /*g_print ("output section %s (%d), size: %d\n", section->st_name, i, assembly->sections [i].size);*/
2669                 section->st_virtual_address = GUINT32_FROM_LE (assembly->sections [i].rva);
2670                 section->st_virtual_size = GUINT32_FROM_LE (assembly->sections [i].size);
2671                 section->st_raw_data_size = GUINT32_FROM_LE (GUINT32_TO_LE (section->st_virtual_size) + (FILE_ALIGN - 1));
2672                 section->st_raw_data_size &= GUINT32_FROM_LE (~(FILE_ALIGN - 1));
2673                 section->st_raw_data_ptr = GUINT32_FROM_LE (assembly->sections [i].offset);
2674                 section->st_flags = GUINT32_FROM_LE (assembly->sections [i].attrs);
2675                 switch (i) {
2676                 case MONO_SECTION_TEXT:
2677                         /* patch entry point */
2678                         p = (assembly->code.data + 2);
2679                         value = (virtual_base + assembly->text_rva + assembly->iat_offset);
2680                         *p++ = (value) & 0xff;
2681                         *p++ = (value >> 8) & 0xff;
2682                         *p++ = (value >> 16) & 0xff;
2683                         *p++ = (value >> 24) & 0xff;
2684
2685                         text_offset = assembly->sections [i].offset;
2686                         memcpy (pefile->data + text_offset, assembly->code.data, assembly->code.index);
2687                         text_offset += assembly->code.index;
2688                         memcpy (pefile->data + text_offset, assembly->resources.data, assembly->resources.index);
2689                         text_offset += assembly->resources.index;
2690                         memcpy (pefile->data + text_offset, assembly->assembly.image->raw_metadata, assembly->meta_size);
2691                         text_offset += assembly->meta_size;
2692                         memcpy (pefile->data + text_offset, assembly->strong_name, assembly->strong_name_size);
2693                         break;
2694                 case MONO_SECTION_RELOC:
2695                         rva = (guint32*)(pefile->data + assembly->sections [i].offset);
2696                         *rva = GUINT32_FROM_LE (assembly->text_rva);
2697                         ++rva;
2698                         *rva = GUINT32_FROM_LE (12);
2699                         ++rva;
2700                         data16 = (guint16*)rva;
2701                         /* 
2702                          * the entrypoint is always at the start of the text section 
2703                          * 3 is IMAGE_REL_BASED_HIGHLOW
2704                          * 2 is patch_size_rva - text_rva
2705                          */
2706                         *data16 = GUINT16_FROM_LE ((3 << 12) + (2));
2707                         data16++;
2708                         *data16 = 0; /* terminate */
2709                         break;
2710                 case MONO_SECTION_RSRC:
2711                 default:
2712                         g_assert_not_reached ();
2713                 }
2714                 section++;
2715         }
2716         
2717         /* check that the file is properly padded */
2718 #if 0
2719         {
2720                 FILE *f = fopen ("mypetest.exe", "w");
2721                 fwrite (pefile->data, pefile->index, 1, f);
2722                 fclose (f);
2723         }
2724 #endif
2725 }
2726
2727 /*
2728  * We need to return always the same object for MethodInfo, FieldInfo etc..
2729  * but we need to consider the reflected type.
2730  * type uses a different hash, since it uses custom hash/equal functions.
2731  */
2732
2733 typedef struct {
2734         gpointer item;
2735         MonoClass *refclass;
2736 } ReflectedEntry;
2737
2738 static gboolean
2739 reflected_equal (gconstpointer a, gconstpointer b) {
2740         const ReflectedEntry *ea = a;
2741         const ReflectedEntry *eb = b;
2742
2743         return (ea->item == eb->item) && (ea->refclass == eb->refclass);
2744 }
2745
2746 static guint
2747 reflected_hash (gconstpointer a) {
2748         const ReflectedEntry *ea = a;
2749         return GPOINTER_TO_UINT (ea->item);
2750 }
2751
2752 #define CHECK_OBJECT(t,p,k)     \
2753         do {    \
2754                 t _obj; \
2755                 ReflectedEntry e;       \
2756                 e.item = (p);   \
2757                 e.refclass = (k);       \
2758                 mono_domain_lock (domain);      \
2759                 if (!domain->refobject_hash)    \
2760                         domain->refobject_hash = mono_g_hash_table_new (reflected_hash, reflected_equal);       \
2761                 if ((_obj = mono_g_hash_table_lookup (domain->refobject_hash, &e))) {   \
2762                         mono_domain_unlock (domain);    \
2763                         return _obj;    \
2764                 }       \
2765         } while (0)
2766
2767 #define CACHE_OBJECT(p,o,k)     \
2768         do {    \
2769                 ReflectedEntry *e = mono_mempool_alloc (domain->mp, sizeof (ReflectedEntry));   \
2770                 e->item = (p);  \
2771                 e->refclass = (k);      \
2772                 mono_g_hash_table_insert (domain->refobject_hash, e,o); \
2773                 mono_domain_unlock (domain);    \
2774         } while (0)
2775
2776 /*
2777  * mono_assembly_get_object:
2778  * @domain: an app domain
2779  * @assembly: an assembly
2780  *
2781  * Return an System.Reflection.Assembly object representing the MonoAssembly @assembly.
2782  */
2783 MonoReflectionAssembly*
2784 mono_assembly_get_object (MonoDomain *domain, MonoAssembly *assembly)
2785 {
2786         static MonoClass *System_Reflection_Assembly;
2787         MonoReflectionAssembly *res;
2788         
2789         CHECK_OBJECT (MonoReflectionAssembly *, assembly, NULL);
2790         if (!System_Reflection_Assembly)
2791                 System_Reflection_Assembly = mono_class_from_name (
2792                         mono_defaults.corlib, "System.Reflection", "Assembly");
2793         res = (MonoReflectionAssembly *)mono_object_new (domain, System_Reflection_Assembly);
2794         res->assembly = assembly;
2795         CACHE_OBJECT (assembly, res, NULL);
2796         return res;
2797 }
2798
2799
2800 MonoReflectionModule*   
2801 mono_module_get_object   (MonoDomain *domain, MonoImage *image)
2802 {
2803         static MonoClass *System_Reflection_Module;
2804         MonoReflectionModule *res;
2805         
2806         CHECK_OBJECT (MonoReflectionModule *, image, NULL);
2807         if (!System_Reflection_Module)
2808                 System_Reflection_Module = mono_class_from_name (
2809                         mono_defaults.corlib, "System.Reflection", "Module");
2810         res = (MonoReflectionModule *)mono_object_new (domain, System_Reflection_Module);
2811
2812         res->image = image;
2813         res->assembly = (MonoReflectionAssembly *) mono_assembly_get_object(domain, image->assembly);
2814
2815         res->fqname    = mono_string_new (domain, image->name);
2816         res->name      = mono_string_new (domain, image->name);
2817         res->scopename = mono_string_new (domain, image->module_name);
2818
2819         CACHE_OBJECT (image, res, NULL);
2820         return res;
2821 }
2822
2823
2824 static gboolean
2825 mymono_metadata_type_equal (MonoType *t1, MonoType *t2)
2826 {
2827         if ((t1->type != t2->type) ||
2828             (t1->byref != t2->byref))
2829                 return FALSE;
2830
2831         switch (t1->type) {
2832         case MONO_TYPE_VOID:
2833         case MONO_TYPE_BOOLEAN:
2834         case MONO_TYPE_CHAR:
2835         case MONO_TYPE_I1:
2836         case MONO_TYPE_U1:
2837         case MONO_TYPE_I2:
2838         case MONO_TYPE_U2:
2839         case MONO_TYPE_I4:
2840         case MONO_TYPE_U4:
2841         case MONO_TYPE_I8:
2842         case MONO_TYPE_U8:
2843         case MONO_TYPE_R4:
2844         case MONO_TYPE_R8:
2845         case MONO_TYPE_STRING:
2846         case MONO_TYPE_I:
2847         case MONO_TYPE_U:
2848         case MONO_TYPE_OBJECT:
2849                 return TRUE;
2850         case MONO_TYPE_VALUETYPE:
2851         case MONO_TYPE_CLASS:
2852                 return t1->data.klass == t2->data.klass;
2853         case MONO_TYPE_PTR:
2854         case MONO_TYPE_SZARRAY:
2855                 return mymono_metadata_type_equal (t1->data.type, t2->data.type);
2856         case MONO_TYPE_ARRAY:
2857                 if (t1->data.array->rank != t2->data.array->rank)
2858                         return FALSE;
2859                 return mymono_metadata_type_equal (t1->data.array->type, t2->data.array->type);
2860         default:
2861                 g_error ("implement type compare for %0x!", t1->type);
2862                 return FALSE;
2863         }
2864
2865         return FALSE;
2866 }
2867
2868 static guint
2869 mymono_metadata_type_hash (MonoType *t1)
2870 {
2871         guint hash;
2872
2873         hash = t1->type;
2874
2875         hash |= t1->byref << 6; /* do not collide with t1->type values */
2876         switch (t1->type) {
2877         case MONO_TYPE_VALUETYPE:
2878         case MONO_TYPE_CLASS:
2879                 /* check if the distribution is good enough */
2880                 return hash << 7 | g_str_hash (t1->data.klass->name);
2881         case MONO_TYPE_PTR:
2882         case MONO_TYPE_SZARRAY:
2883                 return hash << 7 | mymono_metadata_type_hash (t1->data.type);
2884         }
2885         return hash;
2886 }
2887
2888 /*
2889  * mono_type_get_object:
2890  * @domain: an app domain
2891  * @type: a type
2892  *
2893  * Return an System.MonoType object representing the type @type.
2894  */
2895 MonoReflectionType*
2896 mono_type_get_object (MonoDomain *domain, MonoType *type)
2897 {
2898         MonoReflectionType *res;
2899         MonoClass *klass = mono_class_from_mono_type (type);
2900
2901         mono_domain_lock (domain);
2902         if (!domain->type_hash)
2903                 domain->type_hash = mono_g_hash_table_new ((GHashFunc)mymono_metadata_type_hash, 
2904                                 (GCompareFunc)mymono_metadata_type_equal);
2905         if ((res = mono_g_hash_table_lookup (domain->type_hash, type))) {
2906                 mono_domain_unlock (domain);
2907                 return res;
2908         }
2909         if (klass->reflection_info && !klass->wastypebuilder) {
2910                 //g_assert_not_reached ();
2911                 /* should this be considered an error condition? */
2912                 if (!type->byref) {
2913                         mono_domain_unlock (domain);
2914                         return klass->reflection_info;
2915                 }
2916         }
2917         mono_class_init (klass);
2918         res = (MonoReflectionType *)mono_object_new (domain, mono_defaults.monotype_class);
2919         res->type = type;
2920         mono_g_hash_table_insert (domain->type_hash, type, res);
2921         mono_domain_unlock (domain);
2922         return res;
2923 }
2924
2925 /*
2926  * mono_method_get_object:
2927  * @domain: an app domain
2928  * @method: a method
2929  * @refclass: the reflected type (can be NULL)
2930  *
2931  * Return an System.Reflection.MonoMethod object representing the method @method.
2932  */
2933 MonoReflectionMethod*
2934 mono_method_get_object (MonoDomain *domain, MonoMethod *method, MonoClass *refclass)
2935 {
2936         /*
2937          * We use the same C representation for methods and constructors, but the type 
2938          * name in C# is different.
2939          */
2940         const char *cname;
2941         MonoClass *klass;
2942         MonoReflectionMethod *ret;
2943
2944         if (!refclass)
2945                 refclass = method->klass;
2946
2947         CHECK_OBJECT (MonoReflectionMethod *, method, refclass);
2948         if (*method->name == '.' && (strcmp (method->name, ".ctor") == 0 || strcmp (method->name, ".cctor") == 0))
2949                 cname = "MonoCMethod";
2950         else
2951                 cname = "MonoMethod";
2952         klass = mono_class_from_name (mono_defaults.corlib, "System.Reflection", cname);
2953
2954         ret = (MonoReflectionMethod*)mono_object_new (domain, klass);
2955         ret->method = method;
2956         ret->name = mono_string_new (domain, method->name);
2957         ret->reftype = mono_type_get_object (domain, &refclass->byval_arg);
2958         CACHE_OBJECT (method, ret, refclass);
2959         return ret;
2960 }
2961
2962 /*
2963  * mono_field_get_object:
2964  * @domain: an app domain
2965  * @klass: a type
2966  * @field: a field
2967  *
2968  * Return an System.Reflection.MonoField object representing the field @field
2969  * in class @klass.
2970  */
2971 MonoReflectionField*
2972 mono_field_get_object (MonoDomain *domain, MonoClass *klass, MonoClassField *field)
2973 {
2974         MonoReflectionField *res;
2975         MonoClass *oklass;
2976
2977         CHECK_OBJECT (MonoReflectionField *, field, klass);
2978         oklass = mono_class_from_name (mono_defaults.corlib, "System.Reflection", "MonoField");
2979         res = (MonoReflectionField *)mono_object_new (domain, oklass);
2980         res->klass = klass;
2981         res->field = field;
2982         CACHE_OBJECT (field, res, klass);
2983         return res;
2984 }
2985
2986 /*
2987  * mono_property_get_object:
2988  * @domain: an app domain
2989  * @klass: a type
2990  * @property: a property
2991  *
2992  * Return an System.Reflection.MonoProperty object representing the property @property
2993  * in class @klass.
2994  */
2995 MonoReflectionProperty*
2996 mono_property_get_object (MonoDomain *domain, MonoClass *klass, MonoProperty *property)
2997 {
2998         MonoReflectionProperty *res;
2999         MonoClass *oklass;
3000
3001         CHECK_OBJECT (MonoReflectionProperty *, property, klass);
3002         oklass = mono_class_from_name (mono_defaults.corlib, "System.Reflection", "MonoProperty");
3003         res = (MonoReflectionProperty *)mono_object_new (domain, oklass);
3004         res->klass = klass;
3005         res->property = property;
3006         CACHE_OBJECT (property, res, klass);
3007         return res;
3008 }
3009
3010 /*
3011  * mono_event_get_object:
3012  * @domain: an app domain
3013  * @klass: a type
3014  * @event: a event
3015  *
3016  * Return an System.Reflection.MonoEvent object representing the event @event
3017  * in class @klass.
3018  */
3019 MonoReflectionEvent*
3020 mono_event_get_object (MonoDomain *domain, MonoClass *klass, MonoEvent *event)
3021 {
3022         MonoReflectionEvent *res;
3023         MonoClass *oklass;
3024
3025         CHECK_OBJECT (MonoReflectionEvent *, event, klass);
3026         oklass = mono_class_from_name (mono_defaults.corlib, "System.Reflection", "MonoEvent");
3027         res = (MonoReflectionEvent *)mono_object_new (domain, oklass);
3028         res->klass = klass;
3029         res->event = event;
3030         CACHE_OBJECT (event, res, klass);
3031         return res;
3032 }
3033
3034 /*
3035  * mono_param_get_objects:
3036  * @domain: an app domain
3037  * @method: a method
3038  *
3039  * Return an System.Reflection.ParameterInfo array object representing the parameters
3040  * in the method @method.
3041  */
3042 MonoReflectionParameter**
3043 mono_param_get_objects (MonoDomain *domain, MonoMethod *method)
3044 {
3045         MonoReflectionParameter **res;
3046         MonoReflectionMethod *member;
3047         MonoClass *oklass;
3048         char **names;
3049         int i;
3050
3051         if (!method->signature->param_count)
3052                 return NULL;
3053
3054         member = mono_method_get_object (domain, method, NULL);
3055         names = g_new (char *, method->signature->param_count);
3056         mono_method_get_param_names (method, (const char **) names);
3057         
3058         /* Note: the cache is based on the address of the signature into the method
3059          * since we already cache MethodInfos with the method as keys.
3060          */
3061         CHECK_OBJECT (MonoReflectionParameter**, &(method->signature), NULL);
3062         oklass = mono_class_from_name (mono_defaults.corlib, "System.Reflection", "ParameterInfo");
3063 #if HAVE_BOEHM_GC
3064         res = GC_malloc (sizeof (MonoReflectionParameter*) * method->signature->param_count);
3065 #else
3066         res = g_new0 (MonoReflectionParameter*, method->signature->param_count);
3067 #endif
3068         for (i = 0; i < method->signature->param_count; ++i) {
3069                 res [i] = (MonoReflectionParameter *)mono_object_new (domain, oklass);
3070                 res [i]->ClassImpl = mono_type_get_object (domain, method->signature->params [i]);
3071                 res [i]->DefaultValueImpl = NULL; /* FIXME */
3072                 res [i]->MemberImpl = (MonoObject*)member;
3073                 res [i]->NameImpl = mono_string_new (domain, names [i]);
3074                 res [i]->PositionImpl = i + 1;
3075                 res [i]->AttrsImpl = method->signature->params [i]->attrs;
3076         }
3077         g_free (names);
3078         CACHE_OBJECT (&(method->signature), res, NULL);
3079         return res;
3080 }
3081
3082 static int
3083 assembly_name_to_aname (MonoAssemblyName *assembly, char *p) {
3084         int found_sep;
3085         char *s;
3086
3087         memset (assembly, 0, sizeof (MonoAssemblyName));
3088         assembly->name = p;
3089         assembly->culture = "";
3090         
3091         while (*p && (isalnum (*p) || *p == '.'))
3092                 p++;
3093         found_sep = 0;
3094         while (*p == ' ' || *p == ',') {
3095                 *p++ = 0;
3096                 found_sep = 1;
3097                 continue;
3098         }
3099         /* failed */
3100         if (!found_sep)
3101                 return 1;
3102         while (*p) {
3103                 if (*p == 'V' && strncmp (p, "Version=", 8) == 0) {
3104                         p += 8;
3105                         assembly->major = strtoul (p, &s, 10);
3106                         if (s == p || *s != '.')
3107                                 return 1;
3108                         p = ++s;
3109                         assembly->minor = strtoul (p, &s, 10);
3110                         if (s == p || *s != '.')
3111                                 return 1;
3112                         p = ++s;
3113                         assembly->build = strtoul (p, &s, 10);
3114                         if (s == p || *s != '.')
3115                                 return 1;
3116                         p = ++s;
3117                         assembly->revision = strtoul (p, &s, 10);
3118                         if (s == p)
3119                                 return 1;
3120                 } else if (*p == 'C' && strncmp (p, "Culture=", 8) == 0) {
3121                         p += 8;
3122                         if (strncmp (p, "neutral", 7) == 0) {
3123                                 assembly->culture = "";
3124                                 p += 7;
3125                         } else {
3126                                 assembly->culture = p;
3127                                 while (*p && *p != ',') {
3128                                         p++;
3129                                 }
3130                         }
3131                 } else if (*p == 'P' && strncmp (p, "PublicKeyToken=", 15) == 0) {
3132                         p += 15;
3133                         s = p;
3134                         while (*s && isxdigit (*s)) {
3135                                 *s = tolower (*s);
3136                                 s++;
3137                         }
3138                         assembly->hash_len = s - p;
3139                         if (!(s-p) || ((s-p) & 1))
3140                                 return 1;
3141                         assembly->hash_value = s = p;
3142                         while (*s && isxdigit (*s)) {
3143                                 int val;
3144                                 val = *s >= '0' && *s <= '9'? *s - '0': *s - 'a' + 10;
3145                                 s++;
3146                                 *p = val << 4;
3147                                 *p |= *s >= '0' && *s <= '9'? *s - '0': *s - 'a' + 10;
3148                                 p++;
3149                         }
3150                         p = s;
3151                 } else {
3152                         return 1;
3153                 }
3154                 found_sep = 0;
3155                 while (*p == ' ' || *p == ',') {
3156                         *p++ = 0;
3157                         found_sep = 1;
3158                         continue;
3159                 }
3160                 /* failed */
3161                 if (!found_sep)
3162                         return 1;
3163         }
3164
3165         return 0;
3166 }
3167
3168 /*
3169  * mono_reflection_parse_type:
3170  * @name: type name
3171  *
3172  * Parse a type name as accepted by the GetType () method and output the info
3173  * extracted in the info structure.
3174  * the name param will be mangled, so, make a copy before passing it to this function.
3175  * The fields in info will be valid until the memory pointed to by name is valid.
3176  * Returns 0 on parse error.
3177  * See also mono_type_get_name () below.
3178  */
3179 int
3180 mono_reflection_parse_type (char *name, MonoTypeNameParse *info) {
3181
3182         char *start, *p, *w, *last_point, *startn;
3183         int in_modifiers = 0;
3184         int isbyref = 0, rank;
3185
3186         start = p = w = name;
3187
3188         memset (&info->assembly, 0, sizeof (MonoAssemblyName));
3189         info->name = info->name_space = NULL;
3190         info->nested = NULL;
3191         info->modifiers = NULL;
3192
3193         /* last_point separates the namespace from the name */
3194         last_point = NULL;
3195
3196         while (*p) {
3197                 switch (*p) {
3198                 case '+':
3199                         *p = 0; /* NULL terminate the name */
3200                         startn = p + 1;
3201                         /* we have parsed the nesting namespace + name */
3202                         if (info->name) {
3203                                 info->nested = g_list_append (info->nested, startn);
3204                                 break;
3205                         }
3206                         if (last_point) {
3207                                 info->name_space = start;
3208                                 *last_point = 0;
3209                                 info->name = last_point + 1;
3210                         } else {
3211                                 info->name_space = (char *)"";
3212                                 info->name = start;
3213                         }
3214                         break;
3215                 case '.':
3216                         last_point = w;
3217                         break;
3218                 case '\\':
3219                         ++p;
3220                         break;
3221                 case '&':
3222                 case '*':
3223                 case '[':
3224                 case ',':
3225                         in_modifiers = 1;
3226                         break;
3227                 default:
3228                         break;
3229                 }
3230                 if (in_modifiers)
3231                         break;
3232                 *w++ = *p++;
3233         }
3234         
3235         if (info->name) {
3236                 info->nested = g_list_append (info->nested, startn);
3237         } else {
3238                 if (last_point) {
3239                         info->name_space = start;
3240                         *last_point = 0;
3241                         info->name = last_point + 1;
3242                 } else {
3243                         info->name_space = (char *)"";
3244                         info->name = start;
3245                 }
3246         }
3247         while (*p) {
3248                 switch (*p) {
3249                 case '&':
3250                         if (isbyref) /* only one level allowed by the spec */
3251                                 return 0;
3252                         isbyref = 1;
3253                         info->modifiers = g_list_append (info->modifiers, GUINT_TO_POINTER (0));
3254                         *p++ = 0;
3255                         break;
3256                 case '*':
3257                         info->modifiers = g_list_append (info->modifiers, GUINT_TO_POINTER (-1));
3258                         *p++ = 0;
3259                         break;
3260                 case '[':
3261                         rank = 1;
3262                         *p++ = 0;
3263                         while (*p) {
3264                                 if (*p == ']')
3265                                         break;
3266                                 if (*p == ',')
3267                                         rank++;
3268                                 else if (*p != '*') /* '*' means unknown lower bound */
3269                                         return 0;
3270                                 ++p;
3271                         }
3272                         if (*p++ != ']')
3273                                 return 0;
3274                         info->modifiers = g_list_append (info->modifiers, GUINT_TO_POINTER (rank));
3275                         break;
3276                 case ',':
3277                         *p++ = 0;
3278                         while (*p) {
3279                                 if (*p == ' ') {
3280                                         ++p;
3281                                         continue;
3282                                 }
3283                                 break;
3284                         }
3285                         if (!*p)
3286                                 return 0; /* missing assembly name */
3287                         if (!assembly_name_to_aname (&info->assembly, p))
3288                                 return 0;
3289                         break;
3290                 default:
3291                         break;
3292                 }
3293                 if (info->assembly.name)
3294                         break;
3295         }
3296         *w = 0; /* terminate class name */
3297         if (!info->name || !*info->name)
3298                 return 0;
3299         /* add other consistency checks */
3300         return 1;
3301 }
3302
3303 static void
3304 mono_type_get_name_recurse (MonoType *type, GString *str)
3305 {
3306         MonoClass *klass;
3307         
3308         switch (type->type) {
3309         case MONO_TYPE_ARRAY: {
3310                 int i, rank = type->data.array->rank;
3311
3312                 mono_type_get_name_recurse (type->data.array->type, str);
3313                 g_string_append_c (str, '[');
3314                 for (i = 1; i < rank; i++)
3315                         g_string_append_c (str, ',');
3316                 g_string_append_c (str, ']');
3317                 break;
3318         }
3319         case MONO_TYPE_SZARRAY:
3320                 mono_type_get_name_recurse (type->data.type, str);
3321                 g_string_append (str, "[]");
3322                 break;
3323         case MONO_TYPE_PTR:
3324                 mono_type_get_name_recurse (type->data.type, str);
3325                 g_string_append_c (str, '*');
3326                 break;
3327         default:
3328                 klass = mono_class_from_mono_type (type);
3329                 if (klass->nested_in) {
3330                         mono_type_get_name_recurse (&klass->nested_in->byval_arg, str);
3331                         g_string_append_c (str, '+');
3332                 }
3333                 if (*klass->name_space) {
3334                         g_string_append (str, klass->name_space);
3335                         g_string_append_c (str, '.');
3336                 }
3337                 g_string_append (str, klass->name);
3338                 break;
3339         }
3340 }
3341
3342 /*
3343  * mono_type_get_name:
3344  * @type: a type
3345  *
3346  * Returns the string representation for type as required by System.Reflection.
3347  * The inverse of mono_reflection_parse_type ().
3348  */
3349 char*
3350 mono_type_get_name (MonoType *type)
3351 {
3352         GString* result = g_string_new ("");
3353         mono_type_get_name_recurse (type, result);
3354
3355         if (type->byref)
3356                 g_string_append_c (result, '&');
3357
3358         return g_string_free (result, FALSE);
3359 }
3360
3361 /*
3362  * mono_reflection_get_type:
3363  * @image: a metadata context
3364  * @info: type description structure
3365  * @ignorecase: flag for case-insensitive string compares
3366  *
3367  * Build a MonoType from the type description in @info.
3368  * 
3369  */
3370 MonoType*
3371 mono_reflection_get_type (MonoImage* image, MonoTypeNameParse *info, gboolean ignorecase)
3372 {
3373         MonoClass *klass;
3374         GList *mod;
3375         int modval;
3376         
3377         if (!image)
3378                 image = mono_defaults.corlib;
3379
3380         if (ignorecase)
3381                 klass = mono_class_from_name_case (image, info->name_space, info->name);
3382         else
3383                 klass = mono_class_from_name (image, info->name_space, info->name);
3384         if (!klass)
3385                 return NULL;
3386         for (mod = info->nested; mod; mod = mod->next) {
3387                 GList *nested;
3388
3389                 mono_class_init (klass);
3390                 nested = klass->nested_classes;
3391                 klass = NULL;
3392                 while (nested) {
3393                         klass = nested->data;
3394                         if (ignorecase) {
3395                                 if (g_strcasecmp (klass->name, mod->data) == 0)
3396                                         break;
3397                         } else {
3398                                 if (strcmp (klass->name, mod->data) == 0)
3399                                         break;
3400                         }
3401                         klass = NULL;
3402                         nested = nested->next;
3403                 }
3404                 if (!klass)
3405                         break;
3406         }
3407         if (!klass)
3408                 return NULL;
3409         mono_class_init (klass);
3410         for (mod = info->modifiers; mod; mod = mod->next) {
3411                 modval = GPOINTER_TO_UINT (mod->data);
3412                 if (!modval) { /* byref: must be last modifier */
3413                         return &klass->this_arg;
3414                 } else if (modval == -1) {
3415                         klass = mono_ptr_class_get (&klass->byval_arg);
3416                 } else { /* array rank */
3417                         klass = mono_array_class_get (&klass->byval_arg, modval);
3418                 }
3419                 mono_class_init (klass);
3420         }
3421         return &klass->byval_arg;
3422 }
3423
3424 /*
3425  * mono_reflection_type_from_name:
3426  * @name: type name.
3427  * @image: a metadata context (can be NULL).
3428  *
3429  * Retrieves a MonoType from its @name. If the name is not fully qualified,
3430  * it defaults to get the type from @image or, if @image is NULL or loading
3431  * from it fails, uses corlib.
3432  * 
3433  */
3434 MonoType*
3435 mono_reflection_type_from_name (char *name, MonoImage *image)
3436 {
3437         MonoType *type;
3438         MonoTypeNameParse info;
3439         
3440         /*g_print ("requested type %s\n", str);*/
3441         if (!mono_reflection_parse_type (name, &info)) {
3442                 g_list_free (info.modifiers);
3443                 g_list_free (info.nested);
3444                 return NULL;
3445         }
3446
3447         if (info.assembly.name) {
3448                 image = mono_image_loaded (info.assembly.name);
3449                 /* do we need to load if it's not already loaded? */
3450                 if (!image) {
3451                         g_list_free (info.modifiers);
3452                         g_list_free (info.nested);
3453                         return NULL;
3454                 }
3455         } else if (image == NULL) {
3456                 image = mono_defaults.corlib;
3457         }
3458
3459         type = mono_reflection_get_type (image, &info, FALSE);
3460         if (type == NULL && !info.assembly.name && image != mono_defaults.corlib) {
3461                 image = mono_defaults.corlib;
3462                 type = mono_reflection_get_type (image, &info, FALSE);
3463         }
3464         
3465         g_list_free (info.modifiers);
3466         g_list_free (info.nested);
3467         return type;
3468 }
3469
3470 static void*
3471 load_cattr_value (MonoImage *image, MonoType *t, const char *p, const char **end)
3472 {
3473         int slen, type = t->type;
3474 handle_enum:
3475         switch (type) {
3476         case MONO_TYPE_U1:
3477         case MONO_TYPE_I1:
3478         case MONO_TYPE_BOOLEAN: {
3479                 MonoBoolean *bval = g_malloc (sizeof (MonoBoolean));
3480                 *bval = *p;
3481                 *end = p + 1;
3482                 return bval;
3483         }
3484         case MONO_TYPE_CHAR:
3485         case MONO_TYPE_U2:
3486         case MONO_TYPE_I2: {
3487                 guint16 *val = g_malloc (sizeof (guint16));
3488                 *val = read16 (p);
3489                 *end = p + 2;
3490                 return val;
3491         }
3492 #if SIZEOF_VOID_P == 4
3493         case MONO_TYPE_U:
3494         case MONO_TYPE_I:
3495 #endif
3496         case MONO_TYPE_R4:
3497         case MONO_TYPE_U4:
3498         case MONO_TYPE_I4: {
3499                 guint32 *val = g_malloc (sizeof (guint32));
3500                 *val = read32 (p);
3501                 *end = p + 4;
3502                 return val;
3503         }
3504 #if SIZEOF_VOID_P == 8
3505         case MONO_TYPE_U: /* error out instead? this should probably not happen */
3506         case MONO_TYPE_I:
3507 #endif
3508         case MONO_TYPE_R8:
3509         case MONO_TYPE_U8:
3510         case MONO_TYPE_I8: {
3511                 guint64 *val = g_malloc (sizeof (guint64));
3512                 *val = read64 (p);
3513                 *end = p + 8;
3514                 return val;
3515         }
3516         case MONO_TYPE_VALUETYPE:
3517                 if (t->data.klass->enumtype) {
3518                         type = t->data.klass->enum_basetype->type;
3519                         goto handle_enum;
3520                 } else {
3521                         g_error ("generic valutype %s not handled in custom attr value decoding", t->data.klass->name);
3522                 }
3523                 break;
3524         case MONO_TYPE_STRING:
3525                 if (*p == (char)0xFF) {
3526                         *end = p + 1;
3527                         return NULL;
3528                 }
3529                 slen = mono_metadata_decode_value (p, &p);
3530                 *end = p + slen;
3531                 return mono_string_new_len (mono_domain_get (), p, slen);
3532         case MONO_TYPE_CLASS: {
3533                 char *n;
3534                 MonoType *t;
3535 handle_type:
3536                 slen = mono_metadata_decode_value (p, &p);
3537                 n = g_memdup (p, slen + 1);
3538                 n [slen] = 0;
3539                 t = mono_reflection_type_from_name (n, image);
3540                 if (!t)
3541                         g_warning ("Cannot load type '%s'", n);
3542                 g_free (n);
3543                 *end = p + slen;
3544                 return mono_type_get_object (mono_domain_get (), t);
3545         }
3546         case MONO_TYPE_OBJECT: {
3547                 char subt = *p++;
3548                 MonoObject *obj;
3549                 MonoClass *subc;
3550                 void *val;
3551
3552                 if (subt == 0x50) {
3553                         goto handle_type;
3554                 } else if (subt == 0x55) {
3555                         char *n;
3556                         MonoType *t;
3557                         slen = mono_metadata_decode_value (p, &p);
3558                         n = g_memdup (p, slen + 1);
3559                         n [slen] = 0;
3560                         t = mono_reflection_type_from_name (n, image);
3561                         if (!t)
3562                                 g_warning ("Cannot load type '%s'", n);
3563                         g_free (n);
3564                         p += slen;
3565                         subc = mono_class_from_mono_type (t);
3566                 } else if (subt >= MONO_TYPE_BOOLEAN && subt <= MONO_TYPE_R8) {
3567                         MonoType simple_type = {{0}};
3568                         simple_type.type = subt;
3569                         subc = mono_class_from_mono_type (&simple_type);
3570                 } else {
3571                         g_error ("Unknown type 0x%02x for object type encoding in custom attr", subt);
3572                 }
3573                 val = load_cattr_value (image, &subc->byval_arg, p, end);
3574                 obj = mono_object_new (mono_domain_get (), subc);
3575                 memcpy ((char*)obj + sizeof (MonoObject), val, mono_class_value_size (subc, NULL));
3576                 g_free (val);
3577                 return obj;
3578         }
3579         default:
3580                 g_error ("Type 0x%02x not handled in custom attr value decoding", type);
3581         }
3582         return NULL;
3583 }
3584
3585 /*
3586  * Optimization we could avoid mallocing() an little-endian archs that
3587  * don't crash with unaligned accesses.
3588  */
3589 static const char*
3590 fill_param_data (MonoImage *image, MonoMethodSignature *sig, guint32 blobidx, void **params) {
3591         int len, i;
3592         const char *p = mono_metadata_blob_heap (image, blobidx);
3593
3594         len = mono_metadata_decode_value (p, &p);
3595         if (len < 2 || read16 (p) != 0x0001) /* Prolog */
3596                 return NULL;
3597
3598         /* skip prolog */
3599         p += 2;
3600         for (i = 0; i < sig->param_count; ++i) {
3601                 params [i] = load_cattr_value (image, sig->params [i], p, &p);
3602         }
3603         return p;
3604 }
3605
3606 static gboolean
3607 type_is_reference (MonoType *type)
3608 {
3609         switch (type->type) {
3610         case MONO_TYPE_BOOLEAN:
3611         case MONO_TYPE_CHAR:
3612         case MONO_TYPE_U:
3613         case MONO_TYPE_I:
3614         case MONO_TYPE_U1:
3615         case MONO_TYPE_I1:
3616         case MONO_TYPE_U2:
3617         case MONO_TYPE_I2:
3618         case MONO_TYPE_U4:
3619         case MONO_TYPE_I4:
3620         case MONO_TYPE_U8:
3621         case MONO_TYPE_I8:
3622         case MONO_TYPE_R8:
3623         case MONO_TYPE_R4:
3624         case MONO_TYPE_VALUETYPE:
3625                 return FALSE;
3626         default:
3627                 return TRUE;
3628         }
3629 }
3630
3631 static void
3632 free_param_data (MonoMethodSignature *sig, void **params) {
3633         int i;
3634         for (i = 0; i < sig->param_count; ++i) {
3635                 if (!type_is_reference (sig->params [i]))
3636                         g_free (params [i]);
3637         }
3638 }
3639
3640 /*
3641  * Find the method index in the metadata methodDef table.
3642  * Later put these three helper methods in metadata and export them.
3643  */
3644 static guint32
3645 find_method_index (MonoMethod *method) {
3646         MonoClass *klass = method->klass;
3647         int i;
3648
3649         for (i = 0; i < klass->method.count; ++i) {
3650                 if (method == klass->methods [i])
3651                         return klass->method.first + 1 + i;
3652         }
3653         return 0;
3654 }
3655
3656 /*
3657  * Find the field index in the metadata FieldDef table.
3658  */
3659 static guint32
3660 find_field_index (MonoClass *klass, MonoClassField *field) {
3661         int i;
3662
3663         for (i = 0; i < klass->field.count; ++i) {
3664                 if (field == &klass->fields [i])
3665                         return klass->field.first + 1 + i;
3666         }
3667         return 0;
3668 }
3669
3670 /*
3671  * Find the property index in the metadata Property table.
3672  */
3673 static guint32
3674 find_property_index (MonoClass *klass, MonoProperty *property) {
3675         int i;
3676
3677         for (i = 0; i < klass->property.count; ++i) {
3678                 if (property == &klass->properties [i])
3679                         return klass->property.first + 1 + i;
3680         }
3681         return 0;
3682 }
3683
3684 /*
3685  * Find the event index in the metadata Event table.
3686  */
3687 static guint32
3688 find_event_index (MonoClass *klass, MonoEvent *event) {
3689         int i;
3690
3691         for (i = 0; i < klass->event.count; ++i) {
3692                 if (event == &klass->events [i])
3693                         return klass->event.first + 1 + i;
3694         }
3695         return 0;
3696 }
3697
3698 /*
3699  * mono_reflection_get_custom_attrs:
3700  * @obj: a reflection object handle
3701  *
3702  * Return an array with all the custom attributes defined of the
3703  * reflection handle @obj. The objects are fully build.
3704  */
3705 MonoArray*
3706 mono_reflection_get_custom_attrs (MonoObject *obj)
3707 {
3708         guint32 idx, mtoken, i, len;
3709         guint32 cols [MONO_CUSTOM_ATTR_SIZE];
3710         MonoClass *klass;
3711         MonoImage *image;
3712         MonoTableInfo *ca;
3713         MonoMethod *method;
3714         MonoObject *attr;
3715         MonoArray *result;
3716         GList *list = NULL;
3717         void **params;
3718         
3719         klass = obj->vtable->klass;
3720         /* FIXME: need to handle: Module */
3721         if (klass == mono_defaults.monotype_class) {
3722                 MonoReflectionType *rtype = (MonoReflectionType*)obj;
3723                 klass = mono_class_from_mono_type (rtype->type);
3724                 idx = mono_metadata_token_index (klass->type_token);
3725                 idx <<= CUSTOM_ATTR_BITS;
3726                 idx |= CUSTOM_ATTR_TYPEDEF;
3727                 image = klass->image;
3728         } else if (strcmp ("Assembly", klass->name) == 0) {
3729                 MonoReflectionAssembly *rassembly = (MonoReflectionAssembly*)obj;
3730                 idx = 1; /* there is only one assembly */
3731                 idx <<= CUSTOM_ATTR_BITS;
3732                 idx |= CUSTOM_ATTR_ASSEMBLY;
3733                 image = rassembly->assembly->image;
3734         } else if (strcmp ("MonoProperty", klass->name) == 0) {
3735                 MonoReflectionProperty *rprop = (MonoReflectionProperty*)obj;
3736                 idx = find_property_index (rprop->klass, rprop->property);
3737                 idx <<= CUSTOM_ATTR_BITS;
3738                 idx |= CUSTOM_ATTR_PROPERTY;
3739                 image = rprop->klass->image;
3740         } else if (strcmp ("MonoEvent", klass->name) == 0) {
3741                 MonoReflectionEvent *revent = (MonoReflectionEvent*)obj;
3742                 idx = find_event_index (revent->klass, revent->event);
3743                 idx <<= CUSTOM_ATTR_BITS;
3744                 idx |= CUSTOM_ATTR_EVENT;
3745                 image = revent->klass->image;
3746         } else if (strcmp ("MonoField", klass->name) == 0) {
3747                 MonoReflectionField *rfield = (MonoReflectionField*)obj;
3748                 idx = find_field_index (rfield->klass, rfield->field);
3749                 idx <<= CUSTOM_ATTR_BITS;
3750                 idx |= CUSTOM_ATTR_FIELDDEF;
3751                 image = rfield->klass->image;
3752         } else if ((strcmp ("MonoMethod", klass->name) == 0) || (strcmp ("MonoCMethod", klass->name) == 0)) {
3753                 MonoReflectionMethod *rmethod = (MonoReflectionMethod*)obj;
3754                 idx = find_method_index (rmethod->method);
3755                 idx <<= CUSTOM_ATTR_BITS;
3756                 idx |= CUSTOM_ATTR_METHODDEF;
3757                 image = rmethod->method->klass->image;
3758         } else if (strcmp ("ParameterInfo", klass->name) == 0) {
3759                 MonoReflectionParameter *param = (MonoReflectionParameter*)obj;
3760                 MonoReflectionMethod *rmethod = (MonoReflectionMethod*)param->MemberImpl;
3761                 guint32 method_index = find_method_index (rmethod->method);
3762                 guint32 param_list, param_last, param_pos, found;
3763
3764                 image = rmethod->method->klass->image;
3765                 ca = &image->tables [MONO_TABLE_METHOD];
3766
3767                 param_list = mono_metadata_decode_row_col (ca, method_index - 1, MONO_METHOD_PARAMLIST);
3768                 if (method_index == ca->rows) {
3769                         ca = &image->tables [MONO_TABLE_PARAM];
3770                         param_last = ca->rows + 1;
3771                 } else {
3772                         param_last = mono_metadata_decode_row_col (ca, method_index, MONO_METHOD_PARAMLIST);
3773                         ca = &image->tables [MONO_TABLE_PARAM];
3774                 }
3775                 found = 0;
3776                 for (i = param_list; i < param_last; ++i) {
3777                         param_pos = mono_metadata_decode_row_col (ca, i - 1, MONO_PARAM_SEQUENCE);
3778                         if (param_pos == param->PositionImpl) {
3779                                 found = 1;
3780                                 break;
3781                         }
3782                 }
3783                 if (!found)
3784                         return mono_array_new (mono_domain_get (), mono_defaults.object_class, 0);
3785                 idx = i;
3786                 idx <<= CUSTOM_ATTR_BITS;
3787                 idx |= CUSTOM_ATTR_PARAMDEF;
3788         } else { /* handle other types here... */
3789                 g_error ("get custom attrs not yet supported for %s", klass->name);
3790         }
3791
3792         /* at this point image and index are set correctly for searching the custom attr */
3793         ca = &image->tables [MONO_TABLE_CUSTOMATTRIBUTE];
3794         /* the table is not sorted */
3795         for (i = 0; i < ca->rows; ++i) {
3796                 const char *named;
3797                 gint j, num_named;
3798                 mono_metadata_decode_row (ca, i, cols, MONO_CUSTOM_ATTR_SIZE);
3799                 if (cols [MONO_CUSTOM_ATTR_PARENT] != idx)
3800                         continue;
3801                 mtoken = cols [MONO_CUSTOM_ATTR_TYPE] >> CUSTOM_ATTR_TYPE_BITS;
3802                 switch (cols [MONO_CUSTOM_ATTR_TYPE] & CUSTOM_ATTR_TYPE_MASK) {
3803                 case CUSTOM_ATTR_TYPE_METHODDEF:
3804                         mtoken |= MONO_TOKEN_METHOD_DEF;
3805                         break;
3806                 case CUSTOM_ATTR_TYPE_MEMBERREF:
3807                         mtoken |= MONO_TOKEN_MEMBER_REF;
3808                         break;
3809                 default:
3810                         g_error ("Unknown table for custom attr type %08x", cols [MONO_CUSTOM_ATTR_TYPE]);
3811                         break;
3812                 }
3813                 method = mono_get_method (image, mtoken, NULL);
3814                 if (!method)
3815                         g_error ("Can't find custom attr constructor image: %s mtoken: 0x%08x", image->name, mtoken);
3816                 mono_class_init (method->klass);
3817                 /*g_print ("got attr %s\n", method->klass->name);*/
3818                 params = g_new (void*, method->signature->param_count);
3819                 named = fill_param_data (image, method->signature, cols [MONO_CUSTOM_ATTR_VALUE], params);
3820                 attr = mono_object_new (mono_domain_get (), method->klass);
3821                 mono_runtime_invoke (method, attr, params, NULL);
3822                 free_param_data (method->signature, params);
3823                 g_free (params);
3824                 num_named = read16 (named);
3825                 named += 2;
3826                 for (j = 0; j < num_named; j++) {
3827                         gint name_len;
3828                         char *name, named_type;
3829                         named_type = *named++;
3830                         named++; /* type of data */
3831                         name_len = mono_metadata_decode_blob_size (named, &named);
3832                         name = g_malloc (name_len + 1);
3833                         memcpy (name, named, name_len);
3834                         name [name_len] = 0;
3835                         named += name_len;
3836                         if (named_type == 0x53) {
3837                                 MonoClassField *field = mono_class_get_field_from_name (mono_object_class (attr), name);
3838                                 void *val = load_cattr_value (image, field->type, named, &named);
3839                                 mono_field_set_value (attr, field, val);
3840                                 if (!type_is_reference (field->type))
3841                                         g_free (val);
3842                         } else if (named_type == 0x54) {
3843                                 MonoProperty *prop = mono_class_get_property_from_name (mono_object_class (attr), name);
3844                                 void *pparams [1];
3845                                 MonoType *prop_type;
3846                                 /* can we have more that 1 arg in a custom attr named property? */
3847                                 prop_type = prop->get? prop->get->signature->ret: prop->set->signature->params [prop->set->signature->param_count - 1];
3848                                 pparams [0] = load_cattr_value (image, prop_type, named, &named);
3849                                 mono_property_set_value (prop, attr, pparams, NULL);
3850                                 if (!type_is_reference (prop_type))
3851                                         g_free (pparams [0]);
3852                         }
3853                         g_free (name);
3854                 }
3855                 list = g_list_prepend (list, attr);
3856         }
3857
3858         len = g_list_length (list);
3859         /*
3860          * The return type is really object[], but System/Attribute.cs does a cast
3861          * to (Attribute []) and that is not allowed: I'm lazy for now, but we should
3862          * probably fix that.
3863          */
3864         klass = mono_class_from_name (mono_defaults.corlib, "System", "Attribute");
3865         result = mono_array_new (mono_domain_get (), klass, len);
3866         for (i = 0; i < len; ++i) {
3867                 mono_array_set (result, gpointer, i, list->data);
3868                 list = list->next;
3869         }
3870         g_list_free (g_list_first (list));
3871
3872         return result;
3873 }
3874
3875 static MonoMethodSignature*
3876 parameters_to_signature (MonoArray *parameters) {
3877         MonoMethodSignature *sig;
3878         int count, i;
3879
3880         count = parameters? mono_array_length (parameters): 0;
3881
3882         sig = g_malloc0 (sizeof (MonoMethodSignature) + sizeof (MonoType*) * count);
3883         sig->param_count = count;
3884         sig->sentinelpos = -1; /* FIXME */
3885         for (i = 0; i < count; ++i) {
3886                 MonoReflectionType *pt = mono_array_get (parameters, MonoReflectionType*, i);
3887                 sig->params [i] = pt->type;
3888         }
3889         return sig;
3890 }
3891
3892 static MonoMethodSignature*
3893 ctor_builder_to_signature (MonoReflectionCtorBuilder *ctor) {
3894         MonoMethodSignature *sig;
3895
3896         sig = parameters_to_signature (ctor->parameters);
3897         sig->hasthis = ctor->attrs & METHOD_ATTRIBUTE_STATIC? 0: 1;
3898         sig->ret = &mono_defaults.void_class->byval_arg;
3899         return sig;
3900 }
3901
3902 static MonoMethodSignature*
3903 method_builder_to_signature (MonoReflectionMethodBuilder *method) {
3904         MonoMethodSignature *sig;
3905
3906         sig = parameters_to_signature (method->parameters);
3907         sig->hasthis = method->attrs & METHOD_ATTRIBUTE_STATIC? 0: 1;
3908         sig->ret = method->rtype? method->rtype->type: &mono_defaults.void_class->byval_arg;
3909         return sig;
3910 }
3911
3912 static void
3913 get_prop_name_and_type (MonoObject *prop, char **name, MonoType **type)
3914 {
3915         MonoClass *klass = mono_object_class (prop);
3916         if (strcmp (klass->name, "PropertyBuilder") == 0) {
3917                 MonoReflectionPropertyBuilder *pb = (MonoReflectionPropertyBuilder *)prop;
3918                 *name = mono_string_to_utf8 (pb->name);
3919                 *type = pb->type->type;
3920         } else {
3921                 MonoReflectionProperty *p = (MonoReflectionProperty *)prop;
3922                 *name = g_strdup (p->property->name);
3923                 if (p->property->get)
3924                         *type = p->property->get->signature->ret;
3925                 else
3926                         *type = p->property->set->signature->params [p->property->set->signature->param_count - 1];
3927         }
3928 }
3929
3930 static void
3931 get_field_name_and_type (MonoObject *field, char **name, MonoType **type)
3932 {
3933         MonoClass *klass = mono_object_class (field);
3934         if (strcmp (klass->name, "FieldBuilder") == 0) {
3935                 MonoReflectionFieldBuilder *fb = (MonoReflectionFieldBuilder *)field;
3936                 *name = mono_string_to_utf8 (fb->name);
3937                 *type = fb->type->type;
3938         } else {
3939                 MonoReflectionField *f = (MonoReflectionField *)field;
3940                 *name = g_strdup (f->field->name);
3941                 *type = f->field->type;
3942         }
3943 }
3944
3945 static char*
3946 type_get_qualified_name (MonoType *type, MonoAssembly *ass) {
3947         char *name, *result;
3948         MonoClass *klass;
3949         MonoAssembly *ta;
3950
3951         name = mono_type_get_name (type);
3952         klass = my_mono_class_from_mono_type (type);
3953         ta = klass->image->assembly;
3954         if (ta == ass || klass->image == mono_defaults.corlib)
3955                 return name;
3956
3957         /* missing public key */
3958         result = g_strdup_printf ("%s, %s, Version=%d.%d.%d.%d, Culture=%s",
3959                 name, ta->aname.name,
3960                 ta->aname.major, ta->aname.minor, ta->aname.build, ta->aname.revision,
3961                 ta->aname.culture && *ta->aname.culture? ta->aname.culture: "neutral");
3962         g_free (name);
3963         return result;
3964 }
3965
3966 static void
3967 encode_cattr_value (char *buffer, char *p, char **retbuffer, char **retp, guint32 *buflen, MonoType *type, MonoObject *arg)
3968 {
3969         char *argval;
3970         MonoTypeEnum simple_type;
3971         
3972         if ((p-buffer) + 10 >= *buflen) {
3973                 char *newbuf;
3974                 *buflen *= 2;
3975                 newbuf = g_realloc (buffer, *buflen);
3976                 p = newbuf + (p-buffer);
3977                 buffer = newbuf;
3978         }
3979         argval = ((char*)arg + sizeof (MonoObject));
3980         simple_type = type->type;
3981 handle_enum:
3982         switch (simple_type) {
3983         case MONO_TYPE_BOOLEAN:
3984         case MONO_TYPE_U1:
3985         case MONO_TYPE_I1:
3986                 *p++ = *argval;
3987                 break;
3988         case MONO_TYPE_CHAR:
3989         case MONO_TYPE_U2:
3990         case MONO_TYPE_I2:
3991                 swap_with_size (p, argval, 2, 1);
3992                 p += 2;
3993                 break;
3994         case MONO_TYPE_U4:
3995         case MONO_TYPE_I4:
3996         case MONO_TYPE_R4:
3997                 swap_with_size (p, argval, 4, 1);
3998                 p += 4;
3999                 break;
4000         case MONO_TYPE_U8:
4001         case MONO_TYPE_I8:
4002         case MONO_TYPE_R8:
4003                 swap_with_size (p, argval, 8, 1);
4004                 p += 8;
4005                 break;
4006         case MONO_TYPE_VALUETYPE:
4007                 if (type->data.klass->enumtype) {
4008                         simple_type = type->data.klass->enum_basetype->type;
4009                         goto handle_enum;
4010                 } else {
4011                         g_warning ("generic valutype %s not handled in custom attr value decoding", type->data.klass->name);
4012                 }
4013                 break;
4014         case MONO_TYPE_STRING: {
4015                 char *str;
4016                 guint32 slen;
4017                 if (!arg) {
4018                         *p++ = 0xFF;
4019                         break;
4020                 }
4021                 str = mono_string_to_utf8 ((MonoString*)arg);
4022                 slen = strlen (str);
4023                 if ((p-buffer) + 10 + slen >= *buflen) {
4024                         char *newbuf;
4025                         *buflen *= 2;
4026                         *buflen += slen;
4027                         newbuf = g_realloc (buffer, *buflen);
4028                         p = newbuf + (p-buffer);
4029                         buffer = newbuf;
4030                 }
4031                 mono_metadata_encode_value (slen, p, &p);
4032                 memcpy (p, str, slen);
4033                 p += slen;
4034                 g_free (str);
4035                 break;
4036         }
4037         case MONO_TYPE_CLASS: {
4038                 char *str;
4039                 guint32 slen;
4040                 MonoClass *k = mono_object_class (arg);
4041                 if (!mono_object_isinst (arg, mono_defaults.monotype_class) &&
4042                                 (strcmp (k->name, "TypeBuilder") || strcmp (k->name_space, "System.Reflection.Emit")))
4043                         g_error ("only types allowed, not %s.%s", k->name_space, k->name);
4044 handle_type:
4045                 str = type_get_qualified_name (((MonoReflectionType*)arg)->type, NULL);
4046                 slen = strlen (str);
4047                 if ((p-buffer) + 10 + slen >= *buflen) {
4048                         char *newbuf;
4049                         *buflen *= 2;
4050                         *buflen += slen;
4051                         newbuf = g_realloc (buffer, *buflen);
4052                         p = newbuf + (p-buffer);
4053                         buffer = newbuf;
4054                 }
4055                 mono_metadata_encode_value (slen, p, &p);
4056                 memcpy (p, str, slen);
4057                 p += slen;
4058                 g_free (str);
4059                 break;
4060         }
4061         /* it may be a boxed value or a Type */
4062         case MONO_TYPE_OBJECT: {
4063                 MonoClass *klass = mono_object_class (arg);
4064                 char *str;
4065                 guint32 slen;
4066                 
4067                 if (mono_object_isinst (arg, mono_defaults.monotype_class)) {
4068                         *p++ = 0x50;
4069                         goto handle_type;
4070                 } else if (klass->enumtype) {
4071                         *p++ = 0x55;
4072                 } else if (klass->byval_arg.type >= MONO_TYPE_BOOLEAN && klass->byval_arg.type <= MONO_TYPE_R8) {
4073                         *p++ = simple_type = klass->byval_arg.type;
4074                         goto handle_enum;
4075                 } else {
4076                         g_error ("unhandled type in custom attr");
4077                 }
4078                 str = type_get_qualified_name (klass->enum_basetype, NULL);
4079                 slen = strlen (str);
4080                 if ((p-buffer) + 10 + slen >= *buflen) {
4081                         char *newbuf;
4082                         *buflen *= 2;
4083                         *buflen += slen;
4084                         newbuf = g_realloc (buffer, *buflen);
4085                         p = newbuf + (p-buffer);
4086                         buffer = newbuf;
4087                 }
4088                 mono_metadata_encode_value (slen, p, &p);
4089                 memcpy (p, str, slen);
4090                 p += slen;
4091                 g_free (str);
4092                 simple_type = klass->enum_basetype->type;
4093                 goto handle_enum;
4094         }
4095         default:
4096                 g_error ("type 0x%02x not yet supported in custom attr encoder", simple_type);
4097         }
4098         *retp = p;
4099         *retbuffer = buffer;
4100 }
4101
4102 /*
4103  * mono_reflection_get_custom_attrs_blob:
4104  * @ctor: custom attribute constructor
4105  * @ctorArgs: arguments o the constructor
4106  * @properties:
4107  * @propValues:
4108  * @fields:
4109  * @fieldValues:
4110  * 
4111  * Creates the blob of data that needs to be saved in the metadata and that represents
4112  * the custom attributed described by @ctor, @ctorArgs etc.
4113  * Returns: a Byte array representing the blob of data.
4114  */
4115 MonoArray*
4116 mono_reflection_get_custom_attrs_blob (MonoObject *ctor, MonoArray *ctorArgs, MonoArray *properties, MonoArray *propValues, MonoArray *fields, MonoArray* fieldValues) {
4117         MonoArray *result;
4118         MonoMethodSignature *sig;
4119         MonoObject *arg;
4120         char *buffer, *p;
4121         guint32 buflen, i;
4122
4123         if (strcmp (ctor->vtable->klass->name, "MonoCMethod")) {
4124                 sig = ctor_builder_to_signature ((MonoReflectionCtorBuilder*)ctor);
4125         } else {
4126                 sig = ((MonoReflectionMethod*)ctor)->method->signature;
4127         }
4128         buflen = 256;
4129         p = buffer = g_malloc (buflen);
4130         /* write the prolog */
4131         *p++ = 1;
4132         *p++ = 0;
4133         for (i = 0; i < sig->param_count; ++i) {
4134                 arg = (MonoObject*)mono_array_get (ctorArgs, gpointer, i);
4135                 encode_cattr_value (buffer, p, &buffer, &p, &buflen, sig->params [i], arg);
4136         }
4137         i = 0;
4138         if (properties)
4139                 i += mono_array_length (properties);
4140         if (fields)
4141                 i += mono_array_length (fields);
4142         *p++ = i & 0xff;
4143         *p++ = (i >> 8) & 0xff;
4144         if (properties) {
4145                 MonoObject *prop;
4146                 for (i = 0; i < mono_array_length (properties); ++i) {
4147                         MonoType *ptype;
4148                         char *pname;
4149                         int len;
4150                         
4151                         prop = mono_array_get (properties, gpointer, i);
4152                         get_prop_name_and_type (prop, &pname, &ptype);
4153                         *p++ = 0x54; /* PROPERTY signature */
4154                         mono_metadata_encode_value (ptype->type, p, &p);
4155                         len = strlen (pname);
4156                         mono_metadata_encode_value (len, p, &p);
4157                         memcpy (p, pname, len);
4158                         p += len;
4159                         encode_cattr_value (buffer, p, &buffer, &p, &buflen, ptype, (MonoObject*)mono_array_get (propValues, gpointer, i));
4160                         g_free (pname);
4161                 }
4162         }
4163
4164         if (fields) {
4165                 MonoObject *field;
4166                 for (i = 0; i < mono_array_length (fields); ++i) {
4167                         MonoType *ftype;
4168                         char *fname;
4169                         int len;
4170                         
4171                         field = mono_array_get (fields, gpointer, i);
4172                         get_field_name_and_type (field, &fname, &ftype);
4173                         *p++ = 0x53; /* FIELD signature */
4174                         mono_metadata_encode_value (ftype->type, p, &p);
4175                         len = strlen (fname);
4176                         mono_metadata_encode_value (len, p, &p);
4177                         memcpy (p, fname, len);
4178                         p += len;
4179                         encode_cattr_value (buffer, p, &buffer, &p, &buflen, ftype, (MonoObject*)mono_array_get (fieldValues, gpointer, i));
4180                         g_free (fname);
4181                 }
4182         }
4183
4184         g_assert (p - buffer <= buflen);
4185         buflen = p - buffer;
4186         result = mono_array_new (mono_domain_get (), mono_defaults.byte_class, buflen);
4187         p = mono_array_addr (result, char, 0);
4188         memcpy (p, buffer, buflen);
4189         g_free (buffer);
4190         if (strcmp (ctor->vtable->klass->name, "MonoCMethod"))
4191                 g_free (sig);
4192         return result;
4193 }
4194
4195 /*
4196  * mono_reflection_setup_internal_class:
4197  * @tb: a TypeBuilder object
4198  *
4199  * Creates a MonoClass that represents the TypeBuilder.
4200  * This is a trick that lets us simplify a lot of reflection code
4201  * (and will allow us to support Build and Run assemblies easier).
4202  */
4203 void
4204 mono_reflection_setup_internal_class (MonoReflectionTypeBuilder *tb)
4205 {
4206         MonoClass *klass, *parent;
4207
4208         klass = g_new0 (MonoClass, 1);
4209
4210         klass->image = tb->module->assemblyb->dynamic_assembly->assembly.image;
4211
4212         if (tb->parent) {
4213                 /* check so we can compile corlib correctly */
4214                 if (strcmp (mono_object_class (tb->parent)->name, "TypeBuilder") == 0) {
4215                         /* mono_class_setup_mono_type () guaranteess type->data.klass is valid */
4216                         parent = tb->parent->type->data.klass;
4217                 } else 
4218                         parent = my_mono_class_from_mono_type (tb->parent->type);
4219         } else
4220                 parent = NULL;
4221         
4222         klass->inited = 1; /* we lie to the runtime */
4223         klass->name = mono_string_to_utf8 (tb->name);
4224         klass->name_space = mono_string_to_utf8 (tb->nspace);
4225         klass->type_token = MONO_TOKEN_TYPE_DEF | tb->table_idx;
4226         klass->flags = tb->attrs;
4227
4228         klass->element_class = klass;
4229         klass->reflection_info = tb; /* need to pin. */
4230
4231         if (parent != NULL)
4232                 mono_class_setup_parent (klass, parent);
4233         else if (strcmp (klass->name, "Object") == 0 && strcmp (klass->name_space, "System") == 0) {
4234                 const char *old_n = klass->name;
4235                 /* trick to get relative numbering right when compiling corlib */
4236                 klass->name = "BuildingObject";
4237                 mono_class_setup_parent (klass, mono_defaults.object_class);
4238                 klass->name = old_n;
4239         }
4240         mono_class_setup_mono_type (klass);
4241
4242         /*
4243          * FIXME: handle interfaces.
4244          */
4245
4246         tb->type.type = &klass->byval_arg;
4247
4248         /*g_print ("setup %s as %s (%p)\n", klass->name, ((MonoObject*)tb)->vtable->klass->name, tb);*/
4249 }
4250
4251 /*
4252  * mono_reflection_create_internal_class:
4253  * @tb: a TypeBuilder object
4254  *
4255  * Actually create the MonoClass that is associated with the TypeBuilder.
4256  */
4257 void
4258 mono_reflection_create_internal_class (MonoReflectionTypeBuilder *tb)
4259 {
4260         MonoClass *klass;
4261
4262         klass = my_mono_class_from_mono_type (tb->type.type);
4263
4264         if (klass->enumtype && klass->enum_basetype == NULL) {
4265                 MonoReflectionFieldBuilder *fb;
4266
4267                 g_assert (tb->fields != NULL);
4268                 g_assert (mono_array_length (tb->fields) >= 1);
4269
4270                 fb = mono_array_get (tb->fields, MonoReflectionFieldBuilder*, 0);
4271
4272                 klass->enum_basetype = fb->type->type;
4273                 klass->element_class = my_mono_class_from_mono_type (klass->enum_basetype);
4274                 if (!klass->element_class)
4275                         klass->element_class = mono_class_from_mono_type (klass->enum_basetype);
4276                 klass->instance_size = klass->element_class->instance_size;
4277                 klass->size_inited = 1;
4278                 /* 
4279                  * this is almost safe to do with enums and it's needed to be able
4280                  * to create objects of the enum type (for use in SetConstant).
4281                  */
4282                 mono_class_setup_vtable (klass);
4283         }
4284 }
4285
4286 static MonoMethod*
4287 ctorbuilder_to_mono_method (MonoClass *klass, MonoReflectionCtorBuilder* mb) {
4288         MonoMethod *m;
4289         MonoMethodNormal *pm;
4290         pm = g_new0 (MonoMethodNormal, 1);
4291         m = (MonoMethod*)pm;
4292
4293         m->flags = mb->attrs;
4294         m->iflags = mb->iattrs;
4295         m->name = mb->attrs & METHOD_ATTRIBUTE_STATIC? ".cctor": ".ctor";
4296         m->klass = klass;
4297         m->signature = ctor_builder_to_signature (mb);
4298         /* FIXME: create header */
4299         mb->mhandle = m;
4300         return m;
4301 }
4302
4303 static MonoMethod*
4304 methodbuilder_to_mono_method (MonoClass *klass, MonoReflectionMethodBuilder* mb) {
4305         MonoMethod *m;
4306
4307         if (mb->dll) {
4308                 MonoMethodPInvoke *pm;
4309                 pm = g_new0 (MonoMethodPInvoke, 1);
4310                 m = (MonoMethod*)pm;
4311         } else {
4312                 MonoMethodNormal *pm;
4313                 pm = g_new0 (MonoMethodNormal, 1);
4314                 m = (MonoMethod*)pm;
4315         }
4316         m->flags = mb->attrs;
4317         m->iflags = mb->iattrs;
4318         m->name = mono_string_to_utf8 (mb->name);
4319         m->klass = klass;
4320         m->signature = method_builder_to_signature (mb);
4321         /* FIXME: create header */
4322         mb->mhandle = m;
4323         return m;
4324 }
4325
4326 static void
4327 ensure_runtime_vtable (MonoClass *klass)
4328 {
4329         MonoReflectionTypeBuilder *tb = klass->reflection_info;
4330         int i, num, j;
4331
4332         if (!tb || klass->wastypebuilder)
4333                 return;
4334         if (klass->parent)
4335                 ensure_runtime_vtable (klass->parent);
4336
4337         num = tb->ctors? mono_array_length (tb->ctors): 0;
4338         num += tb->methods? mono_array_length (tb->methods): 0;
4339         klass->method.count = num;
4340         klass->methods = g_new (MonoMethod*, num);
4341         num = tb->ctors? mono_array_length (tb->ctors): 0;
4342         for (i = 0; i < num; ++i)
4343                 klass->methods [i] = ctorbuilder_to_mono_method (klass, mono_array_get (tb->ctors, MonoReflectionCtorBuilder*, i));
4344         num = tb->methods? mono_array_length (tb->methods): 0;
4345         j = i;
4346         for (i = 0; i < num; ++i)
4347                 klass->methods [j++] = methodbuilder_to_mono_method (klass, mono_array_get (tb->methods, MonoReflectionMethodBuilder*, i));
4348
4349         klass->wastypebuilder = TRUE;
4350         if (tb->interfaces) {
4351                 klass->interface_count = mono_array_length (tb->interfaces);
4352                 klass->interfaces = g_new (MonoClass*, klass->interface_count);
4353                 for (i = 0; i < klass->interface_count; ++i) {
4354                         MonoReflectionType *iface = mono_array_get (tb->interfaces, gpointer, i);
4355                         klass->interfaces [i] = mono_class_from_mono_type (iface->type);
4356                 }
4357         }
4358         mono_class_setup_vtable (klass);
4359 }
4360
4361 static void
4362 typebuilder_setup_fields (MonoClass *klass)
4363 {
4364         MonoReflectionTypeBuilder *tb = klass->reflection_info;
4365         MonoReflectionFieldBuilder *fb;
4366         MonoClassField *field;
4367         int i;
4368
4369         klass->field.count = tb->fields? mono_array_length (tb->fields): 0;
4370
4371         if (klass->field.count || klass->fields)
4372                 return;
4373         
4374         klass->fields = g_new0 (MonoClassField, klass->field.count);
4375
4376         for (i = 0; i < klass->field.count; ++i) {
4377                 fb = mono_array_get (tb->fields, gpointer, i);
4378                 field = &klass->fields [i];
4379                 field->name = mono_string_to_utf8 (fb->name);
4380                 if (fb->attrs) {
4381                         /* FIXME: handle type modifiers */
4382                         field->type = g_memdup (fb->type->type, sizeof (MonoType));
4383                         field->type->attrs = fb->attrs;
4384                 } else {
4385                         field->type = fb->type->type;
4386                 }
4387                 if ((fb->attrs & FIELD_ATTRIBUTE_HAS_FIELD_RVA) && fb->rva_data)
4388                         field->data = mono_array_addr (fb->rva_data, char, 0);
4389                 if (fb->offset != -1)
4390                         field->offset = fb->offset;
4391         }
4392         mono_class_layout_fields (klass);
4393 }
4394
4395 MonoReflectionType*
4396 mono_reflection_create_runtime_class (MonoReflectionTypeBuilder *tb)
4397 {
4398         MonoClass *klass;
4399         MonoReflectionType* res;
4400
4401         klass = my_mono_class_from_mono_type (tb->type.type);
4402
4403         /*
4404          * Fields to set in klass:
4405          * the various flags: delegate/unicode/contextbound etc.
4406          * nested_in
4407          * nested_classes
4408          * properties
4409          * events
4410          */
4411         klass->flags = tb->attrs;
4412         klass->element_class = klass;
4413
4414         /* enums are done right away */
4415         if (!klass->enumtype)
4416                 ensure_runtime_vtable (klass);
4417
4418         /* fields and object layout */
4419         if (klass->parent) {
4420                 if (!klass->parent->size_inited)
4421                         mono_class_init (klass->parent);
4422                 klass->instance_size += klass->parent->instance_size;
4423                 klass->class_size += klass->parent->class_size;
4424                 klass->min_align = klass->parent->min_align;
4425         } else {
4426                 klass->instance_size = sizeof (MonoObject);
4427                 klass->min_align = 1;
4428         }
4429         /* FIXME: handle packing_size and instance_size */
4430         typebuilder_setup_fields (klass);
4431
4432         res = mono_type_get_object (mono_object_domain (tb), &klass->byval_arg);
4433         /* with enums res == tb: need to fix that. */
4434         if (!klass->enumtype)
4435                 g_assert (res != tb);
4436         return res;
4437 }
4438
4439 MonoArray *
4440 mono_reflection_sighelper_get_signature_local (MonoReflectionSigHelper *sig)
4441 {
4442         MonoDynamicAssembly *assembly = sig->module->assemblyb->dynamic_assembly;
4443         guint32 na = mono_array_length (sig->arguments);
4444         guint32 buflen, i;
4445         MonoArray *result;
4446         char *buf, *p;
4447
4448         p = buf = g_malloc (10 + na * 10);
4449
4450         mono_metadata_encode_value (0x07, p, &p);
4451         mono_metadata_encode_value (na, p, &p);
4452         for (i = 0; i < na; ++i) {
4453                 MonoReflectionType *type = mono_array_get (sig->arguments, MonoReflectionType *, i);
4454                 encode_reflection_type (assembly, type, p, &p);
4455         }
4456
4457         buflen = p - buf;
4458         result = mono_array_new (mono_domain_get (), mono_defaults.byte_class, buflen);
4459         p = mono_array_addr (result, char, 0);
4460         memcpy (p, buf, buflen);
4461         g_free (buf);
4462
4463         return result;
4464 }
4465
4466 MonoArray *
4467 mono_reflection_sighelper_get_signature_field (MonoReflectionSigHelper *sig)
4468 {
4469         MonoDynamicAssembly *assembly = sig->module->assemblyb->dynamic_assembly;
4470         guint32 na = mono_array_length (sig->arguments);
4471         guint32 buflen, i;
4472         MonoArray *result;
4473         char *buf, *p;
4474
4475         p = buf = g_malloc (10 + na * 10);
4476
4477         mono_metadata_encode_value (0x06, p, &p);
4478         for (i = 0; i < na; ++i) {
4479                 MonoReflectionType *type = mono_array_get (sig->arguments, MonoReflectionType *, i);
4480                 encode_reflection_type (assembly, type, p, &p);
4481         }
4482
4483         buflen = p - buf;
4484         result = mono_array_new (mono_domain_get (), mono_defaults.byte_class, buflen);
4485         p = mono_array_addr (result, char, 0);
4486         memcpy (p, buf, buflen);
4487         g_free (buf);
4488
4489         return result;
4490 }
4491