Thu Feb 21 16:45:34 CET 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/metadata/reflection.h"
13 #include "mono/metadata/tabledefs.h"
14 #include "mono/metadata/tokentype.h"
15 #include "mono/metadata/appdomain.h"
16 #include <stdio.h>
17 #include <glib.h>
18 #include <errno.h>
19 #include <time.h>
20 #include <string.h>
21 #include "image.h"
22 #include "cil-coff.h"
23 #include "rawbuffer.h"
24 #include "mono-endian.h"
25 #include "private.h"
26
27 #define TEXT_OFFSET 512
28 #define CLI_H_SIZE 136
29 #define FILE_ALIGN 512
30 #define START_TEXT_RVA  0x00002000
31
32 typedef struct {
33         MonoReflectionILGen *ilgen;
34         MonoReflectionType *rtype;
35         MonoArray *parameters;
36         MonoArray *pinfo;
37         guint32 attrs;
38         guint32 iattrs;
39         guint32 call_conv;
40         guint32 *table_idx; /* note: it's a pointer */
41         MonoArray *code;
42         MonoObject *type;
43         MonoString *name;
44 } ReflectionMethodBuilder;
45
46 const unsigned char table_sizes [64] = {
47         MONO_MODULE_SIZE,
48         MONO_TYPEREF_SIZE,
49         MONO_TYPEDEF_SIZE,
50         0,
51         MONO_FIELD_SIZE,
52         0,
53         MONO_METHOD_SIZE,
54         0,
55         MONO_PARAM_SIZE,
56         MONO_INTERFACEIMPL_SIZE,
57         MONO_MEMBERREF_SIZE,    /* 0x0A */
58         MONO_CONSTANT_SIZE,
59         MONO_CUSTOM_ATTR_SIZE,
60         MONO_FIELD_MARSHAL_SIZE,
61         MONO_DECL_SECURITY_SIZE,
62         MONO_CLASS_LAYOUT_SIZE,
63         MONO_FIELD_LAYOUT_SIZE, /* 0x10 */
64         MONO_STAND_ALONE_SIGNATURE_SIZE,
65         MONO_EVENT_MAP_SIZE,
66         0,
67         MONO_EVENT_SIZE,
68         MONO_PROPERTY_MAP_SIZE,
69         0,
70         MONO_PROPERTY_SIZE,
71         MONO_METHOD_SEMA_SIZE,
72         MONO_MTHODIMPL_SIZE,
73         MONO_MODULEREF_SIZE,    /* 0x1A */
74         MONO_TYPESPEC_SIZE,
75         MONO_IMPLMAP_SIZE,      
76         MONO_FIELD_RVA_SIZE,
77         0,
78         0,
79         MONO_ASSEMBLY_SIZE,     /* 0x20 */
80         MONO_ASSEMBLY_PROCESSOR_SIZE,
81         MONO_ASSEMBLYOS_SIZE,
82         MONO_ASSEMBLYREF_SIZE,
83         MONO_ASSEMBLYREFPROC_SIZE,
84         MONO_ASSEMBLYREFOS_SIZE,
85         MONO_FILE_SIZE,
86         MONO_EXP_TYPE_SIZE,
87         MONO_MANIFEST_SIZE,
88         MONO_NESTED_CLASS_SIZE,
89         0       /* 0x2A */
90 };
91
92 static guint32 mono_image_typedef_or_ref (MonoDynamicAssembly *assembly, MonoType *type);
93 static guint32 mono_image_get_methodref_token (MonoDynamicAssembly *assembly, MonoMethod *method);
94
95 static void
96 alloc_table (MonoDynamicTable *table, guint nrows)
97 {
98         table->rows = nrows;
99         g_assert (table->columns);
100         table->values = g_realloc (table->values, (1 + table->rows) * table->columns * sizeof (guint32));
101 }
102
103 static guint32
104 string_heap_insert (MonoStringHeap *sh, const char *str)
105 {
106         guint32 idx;
107         guint32 len;
108         gpointer oldkey, oldval;
109
110         if (g_hash_table_lookup_extended (sh->hash, str, &oldkey, &oldval))
111                 return GPOINTER_TO_UINT (oldval);
112
113         len = strlen (str) + 1;
114         idx = sh->index;
115         if (idx + len > sh->alloc_size) {
116                 sh->alloc_size += len + 4096;
117                 sh->data = g_realloc (sh->data, sh->alloc_size);
118         }
119         /*
120          * We strdup the string even if we already copy them in sh->data
121          * so that the string pointers in the hash remain valid even if
122          * we need to realloc sh->data. We may want to avoid that later.
123          */
124         g_hash_table_insert (sh->hash, g_strdup (str), GUINT_TO_POINTER (idx));
125         memcpy (sh->data + idx, str, len);
126         sh->index += len;
127         return idx;
128 }
129
130 static void
131 string_heap_init (MonoStringHeap *sh)
132 {
133         sh->index = 0;
134         sh->alloc_size = 4096;
135         sh->data = g_malloc (4096);
136         sh->hash = g_hash_table_new (g_str_hash, g_str_equal);
137         string_heap_insert (sh, "");
138 }
139
140 static void
141 string_heap_free (MonoStringHeap *sh)
142 {
143         g_free (sh->data);
144         g_hash_table_foreach (sh->hash, (GHFunc)g_free, NULL);
145         g_hash_table_destroy (sh->hash);
146 }
147
148 static guint32
149 mono_image_add_stream_data (MonoDynamicStream *stream, char *data, guint32 len)
150 {
151         guint32 idx;
152         if (stream->alloc_size < stream->index + len) {
153                 stream->alloc_size += len + 4096;
154                 stream->data = g_realloc (stream->data, stream->alloc_size);
155         }
156         memcpy (stream->data + stream->index, data, len);
157         idx = stream->index;
158         stream->index += len;
159         /* 
160          * align index? Not without adding an additional param that controls it since
161          * we may store a blob value in pieces.
162          */
163         return idx;
164 }
165
166 static void
167 stream_data_align (MonoDynamicStream *stream)
168 {
169         char buf [4] = {0};
170         guint32 count = stream->index % 4;
171
172         /* we assume the stream data will be aligned */
173         if (count)
174                 mono_image_add_stream_data (stream, buf, 4 - count);
175 }
176
177 static void
178 encode_type (MonoDynamicAssembly *assembly, MonoType *type, char *p, char **endbuf)
179 {
180         if (!type) {
181                 g_assert_not_reached ();
182                 return;
183         }
184                 
185         if (type->byref)
186                 mono_metadata_encode_value (MONO_TYPE_BYREF, p, &p);
187
188         switch (type->type){
189         case MONO_TYPE_VOID:
190         case MONO_TYPE_BOOLEAN:
191         case MONO_TYPE_CHAR:
192         case MONO_TYPE_I1:
193         case MONO_TYPE_U1:
194         case MONO_TYPE_I2:
195         case MONO_TYPE_U2:
196         case MONO_TYPE_I4:
197         case MONO_TYPE_U4:
198         case MONO_TYPE_I8:
199         case MONO_TYPE_U8:
200         case MONO_TYPE_R4:
201         case MONO_TYPE_R8:
202         case MONO_TYPE_I:
203         case MONO_TYPE_U:
204         case MONO_TYPE_STRING:
205         case MONO_TYPE_OBJECT:
206         case MONO_TYPE_TYPEDBYREF:
207                 mono_metadata_encode_value (type->type, p, &p);
208                 break;
209         case MONO_TYPE_PTR:
210         case MONO_TYPE_SZARRAY:
211                 mono_metadata_encode_value (type->type, p, &p);
212                 encode_type (assembly, type->data.type, p, &p);
213                 break;
214         case MONO_TYPE_VALUETYPE:
215         case MONO_TYPE_CLASS:
216                 mono_metadata_encode_value (type->type, p, &p);
217                 mono_metadata_encode_value (mono_image_typedef_or_ref (assembly, type), p, &p);
218                 break;
219         default:
220                 g_error ("need to encode type %x", type->type);
221         }
222         *endbuf = p;
223 }
224
225 static void
226 encode_reflection_type (MonoDynamicAssembly *assembly, MonoReflectionType *type, char *p, char **endbuf)
227 {
228         MonoReflectionTypeBuilder *tb;
229         guint32 token;
230
231         if (!type) {
232                 mono_metadata_encode_value (MONO_TYPE_VOID, p, endbuf);
233                 return;
234         }
235         if (type->type) {
236                 encode_type (assembly, type->type, p, endbuf);
237                 return;
238         }
239
240         tb = (MonoReflectionTypeBuilder*) type;
241         token = TYPEDEFORREF_TYPEDEF | (tb->table_idx << TYPEDEFORREF_BITS); /* typedef */
242
243         /* FIXME: handle other base types (need to have also some hacks to compile corlib) ... */
244         /* FIXME: handle byref ... */
245         mono_metadata_encode_value (MONO_TYPE_CLASS, p, &p);
246         mono_metadata_encode_value (token, p, endbuf);
247         /*g_print ("encoding type %s to 0x%08x\n", mono_string_to_utf8 (tb->name), token);*/
248 }
249
250 static guint32
251 method_encode_signature (MonoDynamicAssembly *assembly, MonoMethodSignature *sig)
252 {
253         char *buf;
254         char *p;
255         int i;
256         guint32 nparams =  sig->param_count;
257         guint32 size = 10 + nparams * 10;
258         guint32 idx;
259         char blob_size [6];
260         char *b = blob_size;
261         
262         p = buf = g_malloc (size);
263         /*
264          * FIXME: vararg, explicit_this, differenc call_conv values...
265          */
266         *p = sig->call_convention;
267         if (sig->hasthis)
268                 *p |= 0x20; /* hasthis */
269         p++;
270         mono_metadata_encode_value (nparams, p, &p);
271         encode_type (assembly, sig->ret, p, &p);
272         for (i = 0; i < nparams; ++i)
273                 encode_type (assembly, sig->params [i], p, &p);
274         /* store length */
275         mono_metadata_encode_value (p-buf, b, &b);
276         idx = mono_image_add_stream_data (&assembly->blob, blob_size, b-blob_size);
277         mono_image_add_stream_data (&assembly->blob, buf, p-buf);
278         g_free (buf);
279         return idx;
280 }
281
282 static guint32
283 method_builder_encode_signature (MonoDynamicAssembly *assembly, ReflectionMethodBuilder *mb)
284 {
285         /*
286          * FIXME: reuse code from method_encode_signature().
287          */
288         char *buf;
289         char *p;
290         int i;
291         guint32 nparams =  mb->parameters ? mono_array_length (mb->parameters): 0;
292         guint32 size = 10 + nparams * 10;
293         guint32 idx;
294         char blob_size [6];
295         char *b = blob_size;
296         
297         p = buf = g_malloc (size);
298         /* LAMESPEC: all the call conv spec is foobared */
299         *p = mb->call_conv & 0x60; /* has-this, explicit-this */
300         if (mb->call_conv & 2)
301                 *p |= 0x5; /* vararg */
302         if (!(mb->attrs & METHOD_ATTRIBUTE_STATIC))
303                 *p |= 0x20; /* hasthis */
304         p++;
305         mono_metadata_encode_value (nparams, p, &p);
306         encode_reflection_type (assembly, mb->rtype, p, &p);
307         for (i = 0; i < nparams; ++i) {
308                 MonoReflectionType *pt = mono_array_get (mb->parameters, MonoReflectionType*, i);
309                 encode_reflection_type (assembly, pt, p, &p);
310         }
311         /* store length */
312         mono_metadata_encode_value (p-buf, b, &b);
313         idx = mono_image_add_stream_data (&assembly->blob, blob_size, b-blob_size);
314         mono_image_add_stream_data (&assembly->blob, buf, p-buf);
315         g_free (buf);
316         return idx;
317 }
318
319 static guint32
320 encode_locals (MonoDynamicAssembly *assembly, MonoReflectionILGen *ilgen)
321 {
322         MonoDynamicTable *table;
323         guint32 *values;
324         char *p;
325         guint32 idx, sig_idx;
326         guint nl = mono_array_length (ilgen->locals);
327         char *buf;
328         char blob_size [6];
329         char *b = blob_size;
330         int i;
331
332         p = buf = g_malloc (10 + nl * 10);
333         table = &assembly->tables [MONO_TABLE_STANDALONESIG];
334         idx = table->next_idx ++;
335         table->rows ++;
336         alloc_table (table, table->rows);
337         values = table->values + idx * MONO_STAND_ALONE_SIGNATURE_SIZE;
338
339         mono_metadata_encode_value (0x07, p, &p);
340         mono_metadata_encode_value (nl, p, &p);
341         for (i = 0; i < nl; ++i) {
342                 MonoReflectionLocalBuilder *lb = mono_array_get (ilgen->locals, MonoReflectionLocalBuilder*, i);
343                 encode_reflection_type (assembly, lb->type, p, &p);
344         }
345         mono_metadata_encode_value (p-buf, b, &b);
346         sig_idx = mono_image_add_stream_data (&assembly->blob, blob_size, b-blob_size);
347         mono_image_add_stream_data (&assembly->blob, buf, p-buf);
348         g_free (buf);
349
350         values [MONO_STAND_ALONE_SIGNATURE] = sig_idx;
351
352         return idx;
353 }
354
355 static guint32
356 method_encode_code (MonoDynamicAssembly *assembly, ReflectionMethodBuilder *mb)
357 {
358         /* we use only tiny formats now: need  to implement ILGenerator */
359         char flags = 0;
360         guint32 idx;
361         guint32 code_size;
362         gint32 max_stack, i;
363         gint32 num_locals = 0;
364         gint32 num_exception = 0;
365         gint maybe_small;
366         guint32 fat_flags;
367         char fat_header [12];
368         guint32 *intp;
369         guint16 *shortp;
370         guint32 local_sig = 0;
371         guint32 header_size = 12;
372         MonoArray *code;
373
374         if ((mb->attrs & METHOD_ATTRIBUTE_PINVOKE_IMPL) ||
375                         (mb->iattrs & METHOD_IMPL_ATTRIBUTE_INTERNAL_CALL) ||
376                         (mb->iattrs & METHOD_IMPL_ATTRIBUTE_RUNTIME) ||
377                         (mb->attrs & METHOD_ATTRIBUTE_ABSTRACT))
378                 return 0;
379
380         /*if (mb->name)
381                 g_print ("Encode method %s\n", mono_string_to_utf8 (mb->name));*/
382         if (mb->ilgen) {
383                 code = mb->ilgen->code;
384                 code_size = mb->ilgen->code_len;
385                 max_stack = mb->ilgen->max_stack;
386                 num_locals = mb->ilgen->locals ? mono_array_length (mb->ilgen->locals) : 0;
387                 if (mb->ilgen->ex_handlers) {
388                         MonoILExceptionInfo *ex_info;
389                         for (i = 0; i < mono_array_length (mb->ilgen->ex_handlers); ++i) {
390                                 ex_info = (MonoILExceptionInfo*)mono_array_addr (mb->ilgen->ex_handlers, MonoILExceptionInfo, i);
391                                 if (ex_info->handlers)
392                                         num_exception += mono_array_length (ex_info->handlers);
393                                 else
394                                         num_exception++;
395                         }
396                 }
397         } else {
398                 code = mb->code;
399                 code_size = mono_array_length (code);
400                 max_stack = 8; /* we probably need to run a verifier on the code... */
401         }
402
403         /* check for exceptions, maxstack, locals */
404         maybe_small = (max_stack <= 8) && (!num_locals) && (!num_exception);
405         if (maybe_small) {
406                 if (code_size < 64 && !(code_size & 1)) {
407                         flags = (code_size << 2) | 0x2;
408                 } else if (code_size < 32 && (code_size & 1)) {
409                         flags = (code_size << 2) | 0x6; /* LAMESPEC: see metadata.c */
410                 } else {
411                         goto fat_header;
412                 }
413                 idx = mono_image_add_stream_data (&assembly->code, &flags, 1);
414                 mono_image_add_stream_data (&assembly->code, mono_array_addr (code, char, 0), code_size);
415                 return assembly->text_rva + idx + CLI_H_SIZE;
416         } 
417 fat_header:
418         if (num_locals)
419                 local_sig = MONO_TOKEN_SIGNATURE | encode_locals (assembly, mb->ilgen);
420         /* 
421          * FIXME: need to set also the header size in fat_flags.
422          * (and more sects and init locals flags)
423          */
424         fat_flags =  0x03;
425         if (num_exception)
426                 fat_flags |= METHOD_HEADER_MORE_SECTS;
427         fat_header [0] = fat_flags;
428         fat_header [1] = (header_size / 4 ) << 4;
429         shortp = (guint16*)(fat_header + 2);
430         *shortp = max_stack;
431         intp = (guint32*)(fat_header + 4);
432         *intp = code_size;
433         intp = (guint32*)(fat_header + 8);
434         *intp = local_sig;
435         idx = mono_image_add_stream_data (&assembly->code, fat_header, 12);
436         mono_image_add_stream_data (&assembly->code, mono_array_addr (code, char, 0), code_size);
437         if (num_exception) {
438                 unsigned char sheader [4];
439                 MonoExceptionClause clause;
440                 MonoILExceptionInfo * ex_info;
441                 MonoILExceptionBlock * ex_block;
442                 int j;
443
444                 stream_data_align (&assembly->code);
445                 /* always use fat format for now */
446                 sheader [0] = METHOD_HEADER_SECTION_FAT_FORMAT | METHOD_HEADER_SECTION_EHTABLE;
447                 num_exception *= sizeof (MonoExceptionClause);
448                 sheader [1] = num_exception & 0xff;
449                 sheader [2] = (num_exception >> 8) & 0xff;
450                 sheader [3] = (num_exception >> 16) & 0xff;
451                 mono_image_add_stream_data (&assembly->code, sheader, 4);
452                 /* fat header, so we are already aligned */
453                 /* reverse order */
454                 for (i = mono_array_length (mb->ilgen->ex_handlers) - 1; i >= 0; --i) {
455                         ex_info = (MonoILExceptionInfo *)mono_array_addr (mb->ilgen->ex_handlers, MonoILExceptionInfo, i);
456                         if (ex_info->handlers) {
457                                 int finally_start = 0;
458                                 for (j = 0; j < mono_array_length (ex_info->handlers); ++j) {
459                                         ex_block = (MonoILExceptionBlock*)mono_array_addr (ex_info->handlers, MonoILExceptionBlock, j);
460                                         clause.flags = ex_block->type;
461                                         clause.try_offset = ex_info->start;
462                                         /* need fault, too, probably */
463                                         if (clause.flags == MONO_EXCEPTION_CLAUSE_FINALLY)
464                                                 clause.try_len = finally_start - ex_info->start;
465                                         else
466                                                 clause.try_len = ex_info->len;
467                                         clause.handler_offset = ex_block->start;
468                                         clause.handler_len = ex_block->len;
469                                         finally_start = clause.handler_offset + clause.handler_len;
470                                         clause.token_or_filter = ex_block->extype ? mono_metadata_token_from_dor (
471                                                         mono_image_typedef_or_ref (assembly, ex_block->extype->type)): 0;
472                                         /*g_print ("out clause %d: from %d len=%d, handler at %d, %d\n", 
473                                                         clause.flags, clause.try_offset, clause.try_len, clause.handler_offset, clause.handler_len);*/
474                                         /* FIXME: ENOENDIAN */
475                                         mono_image_add_stream_data (&assembly->code, (char*)&clause, sizeof (clause));
476                                 }
477                         } else {
478                                 g_error ("No clauses");
479                         }
480                 }
481         }
482         return assembly->text_rva + idx + CLI_H_SIZE;
483 }
484
485 static guint32
486 find_index_in_table (MonoDynamicAssembly *assembly, int table_idx, int col, guint32 index)
487 {
488         int i;
489         MonoDynamicTable *table;
490         guint32 *values;
491         
492         table = &assembly->tables [table_idx];
493
494         g_assert (col < table->columns);
495
496         values = table->values + table->columns;
497         for (i = 1; i <= table->rows; ++i) {
498                 if (values [col] == index)
499                         return i;
500         }
501         return 0;
502 }
503
504 /*
505  * index is the table index of the object
506  * type is one of CUSTOM_ATTR_*
507  */
508 static void
509 mono_image_add_cattrs (MonoDynamicAssembly *assembly, guint32 index, guint32 type, MonoArray *cattrs)
510 {
511         MonoDynamicTable *table;
512         MonoReflectionCustomAttr *cattr;
513         guint32 *values;
514         guint32 count, i, token;
515         char blob_size [6];
516         char *p = blob_size;
517         
518         /* it is legal to pass a NULL cattrs: we avoid to use the if in a lot of places */
519         if (!cattrs)
520                 return;
521         count = mono_array_length (cattrs);
522         table = &assembly->tables [MONO_TABLE_CUSTOMATTRIBUTE];
523         table->rows += count;
524         alloc_table (table, table->rows);
525         values = table->values + table->next_idx * MONO_CUSTOM_ATTR_SIZE;
526         index <<= CUSTOM_ATTR_BITS;
527         index |= type;
528         for (i = 0; i < count; ++i) {
529                 cattr = (MonoReflectionCustomAttr*)mono_array_get (cattrs, gpointer, i);
530                 values [MONO_CUSTOM_ATTR_PARENT] = index;
531                 token = mono_image_create_token (assembly, (MonoObject*)cattr->ctor);
532                 type = mono_metadata_token_index (token);
533                 type <<= CUSTOM_ATTR_TYPE_BITS;
534                 switch (mono_metadata_token_table (token)) {
535                 case MONO_TABLE_METHOD:
536                         type |= CUSTOM_ATTR_TYPE_METHODDEF;
537                         break;
538                 case MONO_TABLE_MEMBERREF:
539                         type |= CUSTOM_ATTR_TYPE_MEMBERREF;
540                         break;
541                 default:
542                         g_error ("got wrong token in custom attr");
543                 }
544                 values [MONO_CUSTOM_ATTR_TYPE] = type;
545                 p = blob_size;
546                 mono_metadata_encode_value (mono_array_length (cattr->data), p, &p);
547                 values [MONO_CUSTOM_ATTR_VALUE] = mono_image_add_stream_data (&assembly->blob, blob_size, p - blob_size);
548                 mono_image_add_stream_data (&assembly->blob,
549                         mono_array_addr (cattr->data, char, 0), mono_array_length (cattr->data));
550                 values += MONO_CUSTOM_ATTR_SIZE;
551                 ++table->next_idx;
552         }
553 }
554
555 static void
556 mono_image_basic_method (ReflectionMethodBuilder *mb, MonoDynamicAssembly *assembly)
557 {
558         MonoDynamicTable *table;
559         guint32 *values;
560         char *name;
561         guint i, count;
562
563         /* room in this table is already allocated */
564         table = &assembly->tables [MONO_TABLE_METHOD];
565         *mb->table_idx = table->next_idx ++;
566         values = table->values + *mb->table_idx * MONO_METHOD_SIZE;
567         if (mb->name) {
568                 name = mono_string_to_utf8 (mb->name);
569                 values [MONO_METHOD_NAME] = string_heap_insert (&assembly->sheap, name);
570                 g_free (name);
571         } else { /* a constructor */
572                 values [MONO_METHOD_NAME] = string_heap_insert (&assembly->sheap, mb->attrs & METHOD_ATTRIBUTE_STATIC? ".cctor": ".ctor");
573         }
574         values [MONO_METHOD_FLAGS] = mb->attrs;
575         values [MONO_METHOD_IMPLFLAGS] = mb->iattrs;
576         values [MONO_METHOD_SIGNATURE] = method_builder_encode_signature (assembly, mb);
577         values [MONO_METHOD_RVA] = method_encode_code (assembly, mb);
578         
579         table = &assembly->tables [MONO_TABLE_PARAM];
580         values [MONO_METHOD_PARAMLIST] = table->next_idx;
581
582         if (mb->pinfo) {
583                 count = 0;
584                 for (i = 0; i < mono_array_length (mb->pinfo); ++i) {
585                         if (mono_array_get (mb->pinfo, gpointer, i))
586                                 count++;
587                 }
588                 table->rows += count;
589                 alloc_table (table, table->rows);
590                 values = table->values + table->next_idx * MONO_PARAM_SIZE;
591                 for (i = 0; i < mono_array_length (mb->pinfo); ++i) {
592                         MonoReflectionParamBuilder *pb;
593                         if ((pb = mono_array_get (mb->pinfo, MonoReflectionParamBuilder*, i))) {
594                                 values [MONO_PARAM_FLAGS] = pb->attrs;
595                                 values [MONO_PARAM_SEQUENCE] = i;
596                                 name = mono_string_to_utf8 (pb->name);
597                                 values [MONO_PARAM_NAME] = string_heap_insert (&assembly->sheap, name);
598                                 g_free (name);
599                                 values += MONO_PARAM_SIZE;
600                                 table->next_idx++;
601                                 mono_image_add_cattrs (assembly, pb->table_idx, CUSTOM_ATTR_PARAMDEF, pb->cattrs);
602                         }
603                 }
604         }
605 }
606
607 static void
608 mono_image_get_method_info (MonoReflectionMethodBuilder *mb, MonoDynamicAssembly *assembly)
609 {
610         MonoDynamicTable *table;
611         guint32 *values;
612         char *name;
613         ReflectionMethodBuilder rmb;
614
615         rmb.ilgen = mb->ilgen;
616         rmb.rtype = mb->rtype;
617         rmb.parameters = mb->parameters;
618         rmb.pinfo = mb->pinfo;
619         rmb.attrs = mb->attrs;
620         rmb.iattrs = mb->iattrs;
621         rmb.call_conv = mb->call_conv;
622         rmb.code = mb->code;
623         rmb.type = mb->type;
624         rmb.name = mb->name;
625         rmb.table_idx = &mb->table_idx;
626
627         mono_image_basic_method (&rmb, assembly);
628
629         if (mb->dll) { /* It's a P/Invoke method */
630                 guint32 moduleref;
631                 table = &assembly->tables [MONO_TABLE_IMPLMAP];
632                 table->rows ++;
633                 alloc_table (table, table->rows);
634                 values = table->values + table->rows * MONO_IMPLMAP_SIZE;
635                 values [MONO_IMPLMAP_FLAGS] = (mb->native_cc << 8) | mb->charset;
636                 values [MONO_IMPLMAP_MEMBER] = (mb->table_idx << 1) | 1; /* memberforwarded: method */
637                 name = mono_string_to_utf8 (mb->dllentry);
638                 values [MONO_IMPLMAP_NAME] = string_heap_insert (&assembly->sheap, name);
639                 g_free (name);
640                 name = mono_string_to_utf8 (mb->dll);
641                 moduleref = string_heap_insert (&assembly->sheap, name);
642                 g_free (name);
643                 if (!(values [MONO_IMPLMAP_SCOPE] = find_index_in_table (assembly, MONO_TABLE_MODULEREF, MONO_MODULEREF_NAME, moduleref))) {
644                         table = &assembly->tables [MONO_TABLE_MODULEREF];
645                         table->rows ++;
646                         alloc_table (table, table->rows);
647                         table->values [table->rows * MONO_MODULEREF_SIZE + MONO_MODULEREF_NAME] = moduleref;
648                         values [MONO_IMPLMAP_SCOPE] = table->rows;
649                 }
650         }
651         if (mb->override_method) {
652                 MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder *)mb->type;
653                 table = &assembly->tables [MONO_TABLE_METHODIMPL];
654                 table->rows ++;
655                 alloc_table (table, table->rows);
656                 values = table->values + table->rows * MONO_MTHODIMPL_SIZE;
657                 values [MONO_MTHODIMPL_CLASS] = tb->table_idx;
658                 values [MONO_MTHODIMPL_BODY] = METHODDEFORREF_METHODDEF | (mb->table_idx << METHODDEFORREF_BITS);
659                 if (mb->override_method->method)
660                         values [MONO_MTHODIMPL_DECLARATION] = mono_image_get_methodref_token (assembly, mb->override_method->method);
661                 else {
662                         MonoReflectionMethodBuilder *omb = (MonoReflectionMethodBuilder*)mb->override_method;
663                         values [MONO_MTHODIMPL_DECLARATION] = METHODDEFORREF_METHODDEF | (omb->table_idx << METHODDEFORREF_BITS);
664                 }
665         }
666         mono_image_add_cattrs (assembly, mb->table_idx, CUSTOM_ATTR_METHODDEF, mb->cattrs);
667 }
668
669 static void
670 mono_image_get_ctor_info (MonoDomain *domain, MonoReflectionCtorBuilder *mb, MonoDynamicAssembly *assembly)
671 {
672         ReflectionMethodBuilder rmb;
673
674         rmb.ilgen = mb->ilgen;
675         rmb.rtype = mono_type_get_object (domain, &mono_defaults.void_class->byval_arg);
676         rmb.parameters = mb->parameters;
677         rmb.pinfo = mb->pinfo;
678         rmb.attrs = mb->attrs;
679         rmb.iattrs = mb->iattrs;
680         rmb.call_conv = mb->call_conv;
681         rmb.code = NULL;
682         rmb.type = mb->type;
683         rmb.name = NULL;
684         rmb.table_idx = &mb->table_idx;
685
686         mono_image_basic_method (&rmb, assembly);
687         mono_image_add_cattrs (assembly, mb->table_idx, CUSTOM_ATTR_METHODDEF, mb->cattrs);
688
689 }
690
691 static guint32
692 fieldref_encode_signature (MonoDynamicAssembly *assembly, MonoClassField *field)
693 {
694         char blob_size [64];
695         char *b = blob_size;
696         char *p;
697         char* buf;
698         guint32 idx;
699         
700         p = buf = g_malloc (64);
701         
702         /* No start code with field refs...
703          * mono_metadata_encode_value (0x06, p, &p);
704          */
705         /* encode custom attributes before the type */
706         encode_type (assembly, field->type, p, &p);
707         g_assert (p-buf < 64);
708         mono_metadata_encode_value (p-buf, b, &b);
709         idx = mono_image_add_stream_data (&assembly->blob, blob_size, b-blob_size);
710         mono_image_add_stream_data (&assembly->blob, buf, p-buf);
711         g_free (buf);
712         return idx;
713 }
714
715 static guint32
716 field_encode_signature (MonoDynamicAssembly *assembly, MonoReflectionFieldBuilder *fb)
717 {
718         char blob_size [64];
719         char *b = blob_size;
720         char *p;
721         char* buf;
722         guint32 idx;
723         
724         p = buf = g_malloc (64);
725         
726         mono_metadata_encode_value (0x06, p, &p);
727         /* encode custom attributes before the type */
728         encode_reflection_type (assembly, fb->type, p, &p);
729         g_assert (p-buf < 64);
730         mono_metadata_encode_value (p-buf, b, &b);
731         idx = mono_image_add_stream_data (&assembly->blob, blob_size, b-blob_size);
732         mono_image_add_stream_data (&assembly->blob, buf, p-buf);
733         g_free (buf);
734         return idx;
735 }
736
737 static guint32
738 encode_constant (MonoDynamicAssembly *assembly, MonoObject *val, guint32 *ret_type) {
739         char blob_size [64];
740         char *b = blob_size;
741         char *p, *box_val;
742         char* buf;
743         guint32 idx, len;
744         
745         p = buf = g_malloc (64);
746
747         box_val = ((char*)val) + sizeof (MonoObject);
748         *ret_type = val->vtable->klass->byval_arg.type;
749         switch (*ret_type) {
750         case MONO_TYPE_BOOLEAN:
751         case MONO_TYPE_U1:
752         case MONO_TYPE_I1:
753                 len = 1;
754                 break;
755         case MONO_TYPE_CHAR:
756         case MONO_TYPE_U2:
757         case MONO_TYPE_I2:
758                 len = 2;
759                 break;
760         case MONO_TYPE_U4:
761         case MONO_TYPE_I4:
762         case MONO_TYPE_R4:
763                 len = 4;
764                 break;
765         case MONO_TYPE_U8:
766         case MONO_TYPE_I8:
767         case MONO_TYPE_R8:
768                 len = 8;
769                 break;
770         case MONO_TYPE_STRING:
771         default:
772                 g_error ("we don't encode constant type 0x%02x yet", *ret_type);
773         }
774
775         /* there is no signature */
776         mono_metadata_encode_value (len, b, &b);
777         idx = mono_image_add_stream_data (&assembly->blob, blob_size, b-blob_size);
778         /* FIXME: ENOENDIAN */
779         mono_image_add_stream_data (&assembly->blob, box_val, len);
780
781         g_free (buf);
782         return idx;
783 }
784
785 static void
786 mono_image_get_field_info (MonoReflectionFieldBuilder *fb, MonoDynamicAssembly *assembly)
787 {
788         MonoDynamicTable *table;
789         guint32 *values;
790         char *name;
791
792         table = &assembly->tables [MONO_TABLE_FIELD];
793         fb->table_idx = table->next_idx ++;
794         values = table->values + fb->table_idx * MONO_FIELD_SIZE;
795         name = mono_string_to_utf8 (fb->name);
796         values [MONO_FIELD_NAME] = string_heap_insert (&assembly->sheap, name);
797         g_free (name);
798         values [MONO_FIELD_FLAGS] = fb->attrs;
799         values [MONO_FIELD_SIGNATURE] = field_encode_signature (assembly, fb);
800
801         if (fb->offset != -1) {
802                 table = &assembly->tables [MONO_TABLE_FIELDLAYOUT];
803                 table->rows ++;
804                 alloc_table (table, table->rows);
805                 values = table->values + table->rows * MONO_FIELD_LAYOUT_SIZE;
806                 values [MONO_FIELD_LAYOUT_FIELD] = fb->table_idx;
807                 values [MONO_FIELD_LAYOUT_OFFSET] = fb->offset;
808         }
809         if (fb->attrs & FIELD_ATTRIBUTE_LITERAL) {
810                 guint32 field_type = 0;
811                 table = &assembly->tables [MONO_TABLE_CONSTANT];
812                 table->rows ++;
813                 alloc_table (table, table->rows);
814                 values = table->values + table->rows * MONO_CONSTANT_SIZE;
815                 values [MONO_CONSTANT_PARENT] = HASCONSTANT_FIEDDEF | (fb->table_idx << HASCONSTANT_BITS);
816                 values [MONO_CONSTANT_VALUE] = encode_constant (assembly, fb->def_value, &field_type);
817                 values [MONO_CONSTANT_TYPE] = field_type;
818                 values [MONO_CONSTANT_PADDING] = 0;
819         }
820         if (fb->rva_data) {
821                 guint32 rva_idx;
822                 table = &assembly->tables [MONO_TABLE_FIELDRVA];
823                 table->rows ++;
824                 alloc_table (table, table->rows);
825                 values = table->values + table->rows * MONO_FIELD_RVA_SIZE;
826                 values [MONO_FIELD_RVA_FIELD] = fb->table_idx;
827                 /*
828                  * We store it in the code section because it's simpler for now.
829                  */
830                 rva_idx = mono_image_add_stream_data (&assembly->code, mono_array_addr (fb->rva_data, char, 0), mono_array_length (fb->rva_data));
831                 values [MONO_FIELD_RVA_RVA] = rva_idx + assembly->text_rva + CLI_H_SIZE;
832         }
833         mono_image_add_cattrs (assembly, fb->table_idx, CUSTOM_ATTR_FIELDDEF, fb->cattrs);
834 }
835
836 static guint32
837 property_encode_signature (MonoDynamicAssembly *assembly, MonoReflectionPropertyBuilder *fb)
838 {
839         char *buf, *p;
840         char blob_size [6];
841         char *b = blob_size;
842         guint32 nparams = 0;
843         MonoReflectionMethodBuilder *mb = fb->get_method;
844         guint32 idx, i;
845
846         if (mb && mb->parameters)
847                 nparams = mono_array_length (mb->parameters);
848         buf = p = g_malloc (24 + nparams * 10);
849         *p = 0x08;
850         p++;
851         mono_metadata_encode_value (nparams, p, &p);
852         if (mb) {
853                 encode_reflection_type (assembly, mb->rtype, p, &p);
854                 for (i = 0; i < nparams; ++i) {
855                         MonoReflectionType *pt = mono_array_get (mb->parameters, MonoReflectionType*, i);
856                         encode_reflection_type (assembly, pt, p, &p);
857                 }
858         } else {
859                 *p++ = 1; /* void: a property should probably not be allowed without a getter */
860         }
861         /* store length */
862         mono_metadata_encode_value (p-buf, b, &b);
863         idx = mono_image_add_stream_data (&assembly->blob, blob_size, b-blob_size);
864         mono_image_add_stream_data (&assembly->blob, buf, p-buf);
865         g_free (buf);
866         return idx;
867 }
868
869 static void
870 mono_image_get_property_info (MonoReflectionPropertyBuilder *pb, MonoDynamicAssembly *assembly)
871 {
872         MonoDynamicTable *table;
873         guint32 *values;
874         char *name;
875         guint num_methods = 0;
876         guint32 semaidx;
877
878         /* 
879          * we need to set things in the following tables:
880          * PROPERTYMAP (info already filled in _get_type_info ())
881          * PROPERTY    (rows already preallocated in _get_type_info ())
882          * METHOD      (method info already done with the generic method code)
883          * METHODSEMANTICS
884          */
885         table = &assembly->tables [MONO_TABLE_PROPERTY];
886         pb->table_idx = table->next_idx ++;
887         values = table->values + pb->table_idx * MONO_FIELD_SIZE;
888         name = mono_string_to_utf8 (pb->name);
889         values [MONO_PROPERTY_NAME] = string_heap_insert (&assembly->sheap, name);
890         g_free (name);
891         values [MONO_PROPERTY_FLAGS] = pb->attrs;
892         values [MONO_PROPERTY_TYPE] = property_encode_signature (assembly, pb);
893
894         /* FIXME: we still don't handle 'other' methods */
895         if (pb->get_method) num_methods ++;
896         if (pb->set_method) num_methods ++;
897
898         table = &assembly->tables [MONO_TABLE_METHODSEMANTICS];
899         table->rows += num_methods;
900         alloc_table (table, table->rows);
901
902         if (pb->get_method) {
903                 semaidx = table->next_idx ++;
904                 values = table->values + semaidx * MONO_METHOD_SEMA_SIZE;
905                 values [MONO_METHOD_SEMA_SEMANTICS] = METHOD_SEMANTIC_GETTER;
906                 values [MONO_METHOD_SEMA_METHOD] = pb->get_method->table_idx;
907                 values [MONO_METHOD_SEMA_ASSOCIATION] = (pb->table_idx << HAS_SEMANTICS_BITS) | HAS_SEMANTICS_PROPERTY;
908         }
909         if (pb->set_method) {
910                 semaidx = table->next_idx ++;
911                 values = table->values + semaidx * MONO_METHOD_SEMA_SIZE;
912                 values [MONO_METHOD_SEMA_SEMANTICS] = METHOD_SEMANTIC_SETTER;
913                 values [MONO_METHOD_SEMA_METHOD] = pb->set_method->table_idx;
914                 values [MONO_METHOD_SEMA_ASSOCIATION] = (pb->table_idx << HAS_SEMANTICS_BITS) | HAS_SEMANTICS_PROPERTY;
915         }
916         mono_image_add_cattrs (assembly, pb->table_idx, CUSTOM_ATTR_PROPERTY, pb->cattrs);
917 }
918
919 static guint32
920 resolution_scope_from_image (MonoDynamicAssembly *assembly, MonoImage *image)
921 {
922         if (image != mono_defaults.corlib)
923                 g_error ("multiple assemblyref not yet supported");
924         /* first row in assemblyref */
925         return (1 << RESOLTION_SCOPE_BITS) | RESOLTION_SCOPE_ASSEMBLYREF;
926 }
927
928 static guint32
929 mono_image_typedef_or_ref (MonoDynamicAssembly *assembly, MonoType *type)
930 {
931         MonoDynamicTable *table;
932         guint32 *values;
933         guint32 token;
934         MonoClass *klass;
935
936         if (!assembly->typeref)
937                 assembly->typeref = g_hash_table_new (g_direct_hash, g_direct_equal);
938         
939         token = GPOINTER_TO_UINT (g_hash_table_lookup (assembly->typeref, type));
940         if (token)
941                 return token;
942         klass = type->data.klass;
943         /*
944          * If it's in the same module:
945          * return TYPEDEFORREF_TYPEDEF | ((klass->token & 0xffffff) << TYPEDEFORREF_BITS)
946          */
947
948         table = &assembly->tables [MONO_TABLE_TYPEREF];
949         alloc_table (table, table->rows + 1);
950         values = table->values + table->next_idx * MONO_TYPEREF_SIZE;
951         values [MONO_TYPEREF_SCOPE] = resolution_scope_from_image (assembly, klass->image);
952         values [MONO_TYPEREF_NAME] = string_heap_insert (&assembly->sheap, klass->name);
953         values [MONO_TYPEREF_NAMESPACE] = string_heap_insert (&assembly->sheap, klass->name_space);
954         token = TYPEDEFORREF_TYPEREF | (table->next_idx << TYPEDEFORREF_BITS); /* typeref */
955         g_hash_table_insert (assembly->typeref, type, GUINT_TO_POINTER(token));
956         table->next_idx ++;
957         return token;
958 }
959
960 static guint32
961 mono_image_get_memberref_token (MonoDynamicAssembly *assembly, MonoClass *klass, const char *name, guint32 sig)
962 {
963         MonoDynamicTable *table;
964         guint32 *values;
965         guint32 token, pclass;
966         guint32 parent;
967
968         parent = mono_image_typedef_or_ref (assembly, &klass->byval_arg);
969         switch (parent & TYPEDEFORREF_MASK) {
970         case TYPEDEFORREF_TYPEREF:
971                 pclass = MEMBERREF_PARENT_TYPEREF;
972                 break;
973         case TYPEDEFORREF_TYPESPEC:
974                 pclass = MEMBERREF_PARENT_TYPESPEC;
975                 break;
976         case TYPEDEFORREF_TYPEDEF:
977                 /* should never get here */
978         default:
979                 g_error ("unknow typeref or def token");
980         }
981         /* extract the index */
982         parent >>= TYPEDEFORREF_BITS;
983
984         table = &assembly->tables [MONO_TABLE_MEMBERREF];
985         alloc_table (table, table->rows + 1);
986         values = table->values + table->next_idx * MONO_MEMBERREF_SIZE;
987         values [MONO_MEMBERREF_CLASS] = pclass | (parent << MEMBERREF_PARENT_BITS);
988         values [MONO_MEMBERREF_NAME] = string_heap_insert (&assembly->sheap, name);
989         values [MONO_MEMBERREF_SIGNATURE] = sig;
990         token = MONO_TOKEN_MEMBER_REF | table->next_idx;
991         table->next_idx ++;
992
993         return token;
994 }
995
996 static guint32
997 mono_image_get_methodref_token (MonoDynamicAssembly *assembly, MonoMethod *method)
998 {
999         guint32 token;
1000         if (!assembly->typeref)
1001                 assembly->typeref = g_hash_table_new (g_direct_hash, g_direct_equal);
1002         
1003         token = GPOINTER_TO_UINT (g_hash_table_lookup (assembly->typeref, method));
1004         if (token)
1005                 return token;
1006         token = mono_image_get_memberref_token (assembly, method->klass, 
1007                 method->name,  method_encode_signature (assembly, method->signature));
1008         g_hash_table_insert (assembly->typeref, method, GUINT_TO_POINTER(token));
1009         return token;
1010 }
1011
1012 static guint32
1013 mono_image_get_fieldref_token (MonoDynamicAssembly *assembly, MonoClassField *field, MonoClass *klass)
1014 {
1015         guint32 token;
1016         if (!assembly->typeref)
1017                 assembly->typeref = g_hash_table_new (g_direct_hash, g_direct_equal);
1018         
1019         token = GPOINTER_TO_UINT (g_hash_table_lookup (assembly->typeref, field));
1020         if (token)
1021                 return token;
1022         token = mono_image_get_memberref_token (assembly, klass, 
1023                 field->name,  fieldref_encode_signature (assembly, field));
1024         g_hash_table_insert (assembly->typeref, field, GUINT_TO_POINTER(token));
1025         return token;
1026 }
1027
1028 static void
1029 mono_image_get_type_info (MonoDomain *domain, MonoReflectionTypeBuilder *tb, MonoDynamicAssembly *assembly)
1030 {
1031         MonoDynamicTable *table;
1032         guint *values;
1033         int i;
1034         char *n;
1035
1036         table = &assembly->tables [MONO_TABLE_TYPEDEF];
1037         values = table->values + tb->table_idx * MONO_TYPEDEF_SIZE;
1038         values [MONO_TYPEDEF_FLAGS] = tb->attrs;
1039         if (tb->parent) { /* interfaces don't have a parent */
1040                 if (tb->parent->type)
1041                         values [MONO_TYPEDEF_EXTENDS] = mono_image_typedef_or_ref (assembly, tb->parent->type);
1042                 else {
1043                         MonoReflectionTypeBuilder *ptb = (MonoReflectionTypeBuilder *)tb->parent;
1044                         values [MONO_TYPEDEF_EXTENDS] = TYPEDEFORREF_TYPEDEF | (ptb->table_idx << TYPEDEFORREF_BITS);
1045                 }
1046         } else
1047                 values [MONO_TYPEDEF_EXTENDS] = 0;
1048         n = mono_string_to_utf8 (tb->name);
1049         values [MONO_TYPEDEF_NAME] = string_heap_insert (&assembly->sheap, n);
1050         g_free (n);
1051         n = mono_string_to_utf8 (tb->nspace);
1052         values [MONO_TYPEDEF_NAMESPACE] = string_heap_insert (&assembly->sheap, n);
1053         g_free (n);
1054         values [MONO_TYPEDEF_FIELD_LIST] = assembly->tables [MONO_TABLE_FIELD].next_idx;
1055         values [MONO_TYPEDEF_METHOD_LIST] = assembly->tables [MONO_TABLE_METHOD].next_idx;
1056
1057         /*
1058          * if we have explicitlayout or sequentiallayouts, output data in the
1059          * ClassLayout table.
1060          */
1061         if ((tb->attrs & TYPE_ATTRIBUTE_LAYOUT_MASK) != TYPE_ATTRIBUTE_AUTO_LAYOUT) {
1062                 table = &assembly->tables [MONO_TABLE_CLASSLAYOUT];
1063                 table->rows++;
1064                 alloc_table (table, table->rows);
1065                 values = table->values + table->rows * MONO_CLASS_LAYOUT_SIZE;
1066                 values [MONO_CLASS_LAYOUT_PARENT] = tb->table_idx;
1067                 values [MONO_CLASS_LAYOUT_CLASS_SIZE] = tb->class_size;
1068                 values [MONO_CLASS_LAYOUT_PACKING_SIZE] = tb->packing_size;
1069         }
1070
1071         /*
1072          * FIXME: constructors and methods need to be output in the same order
1073          * as they are defined (according to table_idx).
1074          */
1075
1076         /* handle constructors */
1077         if (tb->ctors) {
1078                 table = &assembly->tables [MONO_TABLE_METHOD];
1079                 table->rows += mono_array_length (tb->ctors);
1080                 alloc_table (table, table->rows);
1081                 for (i = 0; i < mono_array_length (tb->ctors); ++i)
1082                         mono_image_get_ctor_info (domain,
1083                                 mono_array_get (tb->ctors, MonoReflectionCtorBuilder*, i), assembly);
1084         }
1085
1086         /* handle methods */
1087         if (tb->methods) {
1088                 table = &assembly->tables [MONO_TABLE_METHOD];
1089                 table->rows += mono_array_length (tb->methods);
1090                 alloc_table (table, table->rows);
1091                 for (i = 0; i < mono_array_length (tb->methods); ++i)
1092                         mono_image_get_method_info (
1093                                 mono_array_get (tb->methods, MonoReflectionMethodBuilder*, i), assembly);
1094         }
1095
1096         /* handle fields */
1097         if (tb->fields) {
1098                 table = &assembly->tables [MONO_TABLE_FIELD];
1099                 table->rows += mono_array_length (tb->fields);
1100                 alloc_table (table, table->rows);
1101                 for (i = 0; i < mono_array_length (tb->fields); ++i)
1102                         mono_image_get_field_info (
1103                                 mono_array_get (tb->fields, MonoReflectionFieldBuilder*, i), assembly);
1104         }
1105
1106         /* Do the same with properties etc.. */
1107         if (tb->properties && mono_array_length (tb->properties)) {
1108                 table = &assembly->tables [MONO_TABLE_PROPERTY];
1109                 table->rows += mono_array_length (tb->properties);
1110                 alloc_table (table, table->rows);
1111                 table = &assembly->tables [MONO_TABLE_PROPERTYMAP];
1112                 table->rows ++;
1113                 alloc_table (table, table->rows);
1114                 values = table->values + table->rows * MONO_PROPERTY_MAP_SIZE;
1115                 values [MONO_PROPERTY_MAP_PARENT] = tb->table_idx;
1116                 values [MONO_PROPERTY_MAP_PROPERTY_LIST] = assembly->tables [MONO_TABLE_PROPERTY].next_idx;
1117                 for (i = 0; i < mono_array_length (tb->properties); ++i)
1118                         mono_image_get_property_info (
1119                                 mono_array_get (tb->properties, MonoReflectionPropertyBuilder*, i), assembly);
1120         }
1121         if (tb->subtypes) {
1122                 MonoDynamicTable *ntable;
1123                 
1124                 table = &assembly->tables [MONO_TABLE_TYPEDEF];
1125                 table->rows += mono_array_length (tb->subtypes);
1126                 alloc_table (table, table->rows);
1127
1128                 ntable = &assembly->tables [MONO_TABLE_NESTEDCLASS];
1129                 ntable->rows += mono_array_length (tb->subtypes);
1130                 alloc_table (ntable, ntable->rows);
1131                 values = ntable->values + ntable->next_idx * MONO_NESTED_CLASS_SIZE;
1132
1133                 for (i = 0; i < mono_array_length (tb->subtypes); ++i) {
1134                         MonoReflectionTypeBuilder *subtype = mono_array_get (tb->subtypes, MonoReflectionTypeBuilder*, i);
1135
1136                         mono_image_get_type_info (domain, subtype, assembly);
1137                         values [MONO_NESTED_CLASS_NESTED] = subtype->table_idx;
1138                         values [MONO_NESTED_CLASS_ENCLOSING] = tb->table_idx;
1139                         /*g_print ("nesting %s (%d) in %s (%d) (rows %d/%d)\n",
1140                                 mono_string_to_utf8 (subtype->name), subtype->table_idx,
1141                                 mono_string_to_utf8 (tb->name), tb->table_idx,
1142                                 ntable->next_idx, ntable->rows);*/
1143                         values += MONO_NESTED_CLASS_SIZE;
1144                         ntable->next_idx++;
1145                 }
1146         }
1147         mono_image_add_cattrs (assembly, tb->table_idx, CUSTOM_ATTR_TYPEDEF, tb->cattrs);
1148 }
1149
1150 static void
1151 mono_image_fill_module_table (MonoDomain *domain, MonoReflectionModuleBuilder *mb, MonoDynamicAssembly *assembly)
1152 {
1153         MonoDynamicTable *table;
1154         int i;
1155         char *name;
1156
1157         table = &assembly->tables [MONO_TABLE_MODULE];
1158         mb->table_idx = table->next_idx ++;
1159         name = mono_string_to_utf8 (mb->module.name);
1160         table->values [mb->table_idx * MONO_MODULE_SIZE + MONO_MODULE_NAME] = string_heap_insert (&assembly->sheap, name);
1161         g_free (name);
1162         /* need to set mvid? */
1163
1164         mono_image_add_cattrs (assembly, mb->table_idx, CUSTOM_ATTR_MODULE, mb->cattrs);
1165         /*
1166          * fill-in info in other tables as well.
1167          */
1168         table = &assembly->tables [MONO_TABLE_TYPEDEF];
1169         table->rows += mono_array_length (mb->types);
1170         alloc_table (table, table->rows);
1171         /*
1172          * We assign here the typedef indexes to avoid mismatches if a type that
1173          * has not yet been stored in the tables is referenced by another type.
1174          */
1175         for (i = 0; i < mono_array_length (mb->types); ++i) {
1176                 int j;
1177                 MonoReflectionTypeBuilder *type = mono_array_get (mb->types, MonoReflectionTypeBuilder*, i);
1178                 type->table_idx = table->next_idx ++;
1179                 if (!type->subtypes)
1180                         continue;
1181                 for (j = 0; j < mono_array_length (type->subtypes); ++j) {
1182                         MonoReflectionTypeBuilder *subtype = mono_array_get (type->subtypes, MonoReflectionTypeBuilder*, j);
1183                         subtype->table_idx = table->next_idx ++;
1184                 }
1185         }
1186         for (i = 0; i < mono_array_length (mb->types); ++i)
1187                 mono_image_get_type_info (domain, mono_array_get (mb->types, MonoReflectionTypeBuilder*, i), assembly);
1188 }
1189
1190 #define align_pointer(base,p)\
1191         do {\
1192                 guint32 __diff = (unsigned char*)(p)-(unsigned char*)(base);\
1193                 if (__diff & 3)\
1194                         (p) += 4 - (__diff & 3);\
1195         } while (0)
1196
1197 static void
1198 build_compressed_metadata (MonoDynamicAssembly *assembly)
1199 {
1200         int i;
1201         guint64 valid_mask = 0;
1202         guint32 heapt_size = 0;
1203         guint32 meta_size = 256; /* allow for header and other stuff */
1204         guint32 table_offset;
1205         guint32 ntables = 0;
1206         guint64 *int64val;
1207         guint32 *int32val;
1208         guint16 *int16val;
1209         MonoImage *meta;
1210         unsigned char *p;
1211         char *version = "mono" VERSION;
1212         
1213         /* Compute table sizes */
1214         meta = assembly->assembly.image = g_new0 (MonoImage, 1);
1215         
1216         /* Setup the info used by compute_sizes () */
1217         meta->idx_blob_wide = assembly->blob.index >= 65536 ? 1 : 0;
1218         meta->idx_guid_wide = assembly->guid.index >= 65536 ? 1 : 0;
1219         meta->idx_string_wide = assembly->sheap.index >= 65536 ? 1 : 0;
1220
1221         meta_size += assembly->blob.index;
1222         meta_size += assembly->guid.index;
1223         meta_size += assembly->sheap.index;
1224         meta_size += assembly->us.index;
1225
1226         for (i=0; i < 64; ++i)
1227                 meta->tables [i].rows = assembly->tables [i].rows;
1228         
1229         for (i = 0; i < 64; i++){
1230                 if (meta->tables [i].rows == 0)
1231                         continue;
1232                 valid_mask |= (guint64)1 << i;
1233                 ntables ++;
1234                 meta->tables [i].row_size = mono_metadata_compute_size (
1235                         meta, i, &meta->tables [i].size_bitfield);
1236                 heapt_size += meta->tables [i].row_size * meta->tables [i].rows;
1237         }
1238         heapt_size += 24; /* #~ header size */
1239         heapt_size += ntables * 4;
1240         meta_size += heapt_size;
1241         meta->raw_metadata = g_malloc0 (meta_size);
1242         p = meta->raw_metadata;
1243         /* the metadata signature */
1244         *p++ = 'B'; *p++ = 'S'; *p++ = 'J'; *p++ = 'B';
1245         /* version numbers and 4 bytes reserved */
1246         int16val = (guint16*)p;
1247         *int16val++ = 1;
1248         *int16val = 1;
1249         p += 8;
1250         /* version string */
1251         int32val = (guint32*)p;
1252         *int32val = strlen (version);
1253         p += 4;
1254         memcpy (p, version, *int32val);
1255         p += *int32val;
1256         align_pointer (meta->raw_metadata, p);
1257         int16val = (guint16*)p;
1258         *int16val++ = 0; /* flags must be 0 */
1259         *int16val = 5; /* number of streams */
1260         p += 4;
1261
1262         /*
1263          * write the stream info.
1264          */
1265         table_offset = (p - (unsigned char*)meta->raw_metadata) + 5 * 8 + 40; /* room needed for stream headers */
1266         table_offset += 3; table_offset &= ~3;
1267         
1268         int32val = (guint32*)p;
1269         *int32val++ = assembly->tstream.offset = table_offset;
1270         *int32val = heapt_size;
1271         table_offset += *int32val;
1272         table_offset += 3; table_offset &= ~3;
1273         p += 8;
1274         strcpy (p, "#~");
1275         p += 3;
1276         align_pointer (meta->raw_metadata, p);
1277
1278         int32val = (guint32*)p;
1279         *int32val++ = assembly->sheap.offset = table_offset;
1280         *int32val = assembly->sheap.index;
1281         table_offset += *int32val;
1282         table_offset += 3; table_offset &= ~3;
1283         p += 8;
1284         strcpy (p, "#Strings");
1285         p += 9;
1286         align_pointer (meta->raw_metadata, p);
1287
1288         int32val = (guint32*)p;
1289         *int32val++ = assembly->us.offset = table_offset;
1290         *int32val = assembly->us.index;
1291         table_offset += *int32val;
1292         table_offset += 3; table_offset &= ~3;
1293         p += 8;
1294         strcpy (p, "#US");
1295         p += 4;
1296         align_pointer (meta->raw_metadata, p);
1297
1298         int32val = (guint32*)p;
1299         *int32val++ = assembly->blob.offset = table_offset;
1300         *int32val = assembly->blob.index;
1301         table_offset += *int32val;
1302         table_offset += 3; table_offset &= ~3;
1303         p += 8;
1304         strcpy (p, "#Blob");
1305         p += 6;
1306         align_pointer (meta->raw_metadata, p);
1307
1308         int32val = (guint32*)p;
1309         *int32val++ = assembly->guid.offset = table_offset;
1310         *int32val = assembly->guid.index;
1311         table_offset += *int32val;
1312         table_offset += 3; table_offset &= ~3;
1313         p += 8;
1314         strcpy (p, "#GUID");
1315         p += 6;
1316         align_pointer (meta->raw_metadata, p);
1317
1318         /* 
1319          * now copy the data, the table stream header and contents goes first.
1320          */
1321         g_assert ((p - (unsigned char*)meta->raw_metadata) < assembly->tstream.offset);
1322         p = meta->raw_metadata + assembly->tstream.offset;
1323         int32val = (guint32*)p;
1324         *int32val = 0; /* reserved */
1325         p += 4;
1326         *p++ = 1; /* version */
1327         *p++ = 0;
1328         if (meta->idx_string_wide)
1329                 *p |= 0x01;
1330         if (meta->idx_guid_wide)
1331                 *p |= 0x02;
1332         if (meta->idx_blob_wide)
1333                 *p |= 0x04;
1334         ++p;
1335         *p++ = 0; /* reserved */
1336         int64val = (guint64*)p;
1337         *int64val++ = valid_mask;
1338         *int64val++ = 0; /* bitvector of sorted tables, set to 0 for now  */
1339         p += 16;
1340         int32val = (guint32*)p;
1341         for (i = 0; i < 64; i++){
1342                 if (meta->tables [i].rows == 0)
1343                         continue;
1344                 *int32val++ = meta->tables [i].rows;
1345         }
1346         p = (unsigned char*)int32val;
1347         /* compress the tables */
1348         for (i = 0; i < 64; i++){
1349                 int row, col;
1350                 guint32 *values;
1351                 guint32 bitfield = meta->tables [i].size_bitfield;
1352                 if (!meta->tables [i].rows)
1353                         continue;
1354                 if (assembly->tables [i].columns != mono_metadata_table_count (bitfield))
1355                         g_error ("col count mismatch in %d: %d %d", i, assembly->tables [i].columns, mono_metadata_table_count (bitfield));
1356                 meta->tables [i].base = p;
1357                 for (row = 1; row <= meta->tables [i].rows; ++row) {
1358                         values = assembly->tables [i].values + row * assembly->tables [i].columns;
1359                         for (col = 0; col < assembly->tables [i].columns; ++col) {
1360                                 switch (mono_metadata_table_size (bitfield, col)) {
1361                                 case 1:
1362                                         *p++ = values [col];
1363                                         break;
1364                                 case 2:
1365                                         int16val = (guint16*)p;
1366                                         *int16val = values [col];
1367                                         p += 2;
1368                                         break;
1369                                 case 4:
1370                                         int32val = (guint32*)p;
1371                                         *int32val = values [col];
1372                                         p += 4;
1373                                         break;
1374                                 default:
1375                                         g_assert_not_reached ();
1376                                 }
1377                         }
1378                 }
1379                 g_assert ((p - (unsigned char*)meta->tables [i].base) == (meta->tables [i].rows * meta->tables [i].row_size));
1380         }
1381         
1382         g_assert (assembly->guid.offset + assembly->guid.index < meta_size);
1383         memcpy (meta->raw_metadata + assembly->sheap.offset, assembly->sheap.data, assembly->sheap.index);
1384         memcpy (meta->raw_metadata + assembly->us.offset, assembly->us.data, assembly->us.index);
1385         memcpy (meta->raw_metadata + assembly->blob.offset, assembly->blob.data, assembly->blob.index);
1386         memcpy (meta->raw_metadata + assembly->guid.offset, assembly->guid.data, assembly->guid.index);
1387
1388         assembly->meta_size = assembly->guid.offset + assembly->guid.index;
1389 }
1390
1391 static void
1392 mono_image_build_metadata (MonoReflectionAssemblyBuilder *assemblyb)
1393 {
1394         MonoDynamicTable *table;
1395         MonoDynamicAssembly *assembly = assemblyb->dynamic_assembly;
1396         MonoDomain *domain = ((MonoObject *)assemblyb)->vtable->domain;
1397         guint32 len;
1398         guint32 *values;
1399         char *name;
1400         int i;
1401         
1402         assembly->text_rva = START_TEXT_RVA;
1403
1404         table = &assembly->tables [MONO_TABLE_ASSEMBLY];
1405         alloc_table (table, 1);
1406         values = table->values + MONO_ASSEMBLY_SIZE;
1407         values [MONO_ASSEMBLY_HASH_ALG] = 0x8004;
1408         name = mono_string_to_utf8 (assemblyb->name);
1409         values [MONO_ASSEMBLY_NAME] = string_heap_insert (&assembly->sheap, name);
1410         g_free (name);
1411         values [MONO_ASSEMBLY_CULTURE] = string_heap_insert (&assembly->sheap, "");
1412         values [MONO_ASSEMBLY_PUBLIC_KEY] = 0;
1413         values [MONO_ASSEMBLY_MAJOR_VERSION] = 0;
1414         values [MONO_ASSEMBLY_MINOR_VERSION] = 0;
1415         values [MONO_ASSEMBLY_REV_NUMBER] = 0;
1416         values [MONO_ASSEMBLY_BUILD_NUMBER] = 0;
1417
1418         mono_image_add_cattrs (assembly, 1, CUSTOM_ATTR_ASSEMBLY, assemblyb->cattrs);
1419
1420         assembly->tables [MONO_TABLE_TYPEDEF].rows = 1; /* .<Module> */
1421         assembly->tables [MONO_TABLE_TYPEDEF].next_idx++;
1422
1423         len = mono_array_length (assemblyb->modules);
1424         table = &assembly->tables [MONO_TABLE_MODULE];
1425         alloc_table (table, len);
1426         for (i = 0; i < len; ++i)
1427                 mono_image_fill_module_table (domain, mono_array_get (assemblyb->modules, MonoReflectionModuleBuilder*, i), assembly);
1428
1429         table = &assembly->tables [MONO_TABLE_TYPEDEF];
1430         /* 
1431          * table->rows is already set above and in mono_image_fill_module_table.
1432          */
1433         alloc_table (table, table->rows);
1434         /*
1435          * Set the first entry.
1436          */
1437         values = table->values + table->columns;
1438         values [MONO_TYPEDEF_FLAGS] = 0;
1439         values [MONO_TYPEDEF_NAME] = string_heap_insert (&assembly->sheap, "<Module>") ;
1440         values [MONO_TYPEDEF_NAMESPACE] = string_heap_insert (&assembly->sheap, "") ;
1441         values [MONO_TYPEDEF_EXTENDS] = 0;
1442         values [MONO_TYPEDEF_FIELD_LIST] = 1;
1443         values [MONO_TYPEDEF_METHOD_LIST] = 1;
1444
1445         /* later include all the assemblies referenced */
1446         table = &assembly->tables [MONO_TABLE_ASSEMBLYREF];
1447         alloc_table (table, 1);
1448         values = table->values + table->columns;
1449         values [MONO_ASSEMBLYREF_NAME] = string_heap_insert (&assembly->sheap, "corlib");
1450         values [MONO_ASSEMBLYREF_MAJOR_VERSION] = 0;
1451         values [MONO_ASSEMBLYREF_MINOR_VERSION] = 0;
1452         values [MONO_ASSEMBLYREF_BUILD_NUMBER] = 0;
1453         values [MONO_ASSEMBLYREF_REV_NUMBER] = 0;
1454         values [MONO_ASSEMBLYREF_FLAGS] = 0;
1455         values [MONO_ASSEMBLYREF_PUBLIC_KEY] = 0;
1456         values [MONO_ASSEMBLYREF_CULTURE] = 0;
1457         values [MONO_ASSEMBLYREF_HASH_VALUE] = 0;
1458
1459         build_compressed_metadata (assembly);
1460 }
1461
1462 guint32
1463 mono_image_insert_string (MonoReflectionAssemblyBuilder *assembly, MonoString *str)
1464 {
1465         guint32 index;
1466         char buf [16];
1467         char *b = buf;
1468         
1469         if (!assembly->dynamic_assembly)
1470                 mono_image_basic_init (assembly);
1471         mono_metadata_encode_value (1 | (str->length * 2), b, &b);
1472         index = mono_image_add_stream_data (&assembly->dynamic_assembly->us, buf, b-buf);
1473         /* FIXME: ENOENDIAN */
1474         mono_image_add_stream_data (&assembly->dynamic_assembly->us, (char*)mono_string_chars (str), str->length * 2);
1475         mono_image_add_stream_data (&assembly->dynamic_assembly->us, "", 1);
1476         return MONO_TOKEN_STRING | index;
1477 }
1478
1479 /*
1480  * Get a token to insert in the IL code stream for the given MemberInfo.
1481  * obj can be:
1482  *      ConstructorBuilder
1483  *      MethodBuilder
1484  *      FieldBuilder
1485  *      MonoCMethod
1486  *      MonoMethod
1487  *      MonoField
1488  *      MonoType
1489  *      TypeBuilder
1490  */
1491 guint32
1492 mono_image_create_token (MonoDynamicAssembly *assembly, MonoObject *obj)
1493 {
1494         MonoClass *klass = obj->vtable->klass;
1495         guint32 token;
1496
1497         if (strcmp (klass->name, "MethodBuilder") == 0) {
1498                 MonoReflectionMethodBuilder *mb = (MonoReflectionMethodBuilder *)obj;
1499                 token = mb->table_idx | MONO_TOKEN_METHOD_DEF;
1500                 /*g_print ("got token 0x%08x for %s\n", token, mono_string_to_utf8 (mb->name));*/
1501                 return token;
1502         }
1503         if (strcmp (klass->name, "ConstructorBuilder") == 0) {
1504                 MonoReflectionCtorBuilder *mb = (MonoReflectionCtorBuilder *)obj;
1505                 token = mb->table_idx | MONO_TOKEN_METHOD_DEF;
1506                 /*g_print ("got token 0x%08x for %s\n", token, mono_string_to_utf8 (mb->name));*/
1507                 return token;
1508         }
1509         if (strcmp (klass->name, "FieldBuilder") == 0) {
1510                 MonoReflectionFieldBuilder *mb = (MonoReflectionFieldBuilder *)obj;
1511                 return mb->table_idx | MONO_TOKEN_FIELD_DEF;
1512         }
1513         if (strcmp (klass->name, "TypeBuilder") == 0) {
1514                 MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder *)obj;
1515                 return tb->table_idx | MONO_TOKEN_TYPE_DEF;
1516         }
1517         if (strcmp (klass->name, "MonoType") == 0) {
1518                 MonoReflectionType *tb = (MonoReflectionType *)obj;
1519                 return mono_metadata_token_from_dor (
1520                         mono_image_typedef_or_ref (assembly, tb->type));
1521         }
1522         if (strcmp (klass->name, "MonoCMethod") == 0 ||
1523                         strcmp (klass->name, "MonoMethod") == 0) {
1524                 MonoReflectionMethod *m = (MonoReflectionMethod *)obj;
1525                 token = mono_image_get_methodref_token (assembly, m->method);
1526                 /*g_print ("got token 0x%08x for %s\n", token, m->method->name);*/
1527                 return token;
1528         }
1529         if (strcmp (klass->name, "MonoField") == 0) {
1530                 MonoReflectionField *f = (MonoReflectionField *)obj;
1531                 token = mono_image_get_fieldref_token (assembly, f->field, f->klass);
1532                 /*g_print ("got token 0x%08x for %s\n", token, f->field->name);*/
1533                 return token;
1534         }
1535         g_print ("requested token for %s\n", klass->name);
1536         return 0;
1537 }
1538
1539 void
1540 mono_image_basic_init (MonoReflectionAssemblyBuilder *assemblyb)
1541 {
1542         MonoDynamicAssembly *assembly;
1543         int i;
1544         
1545         if (assemblyb->dynamic_assembly)
1546                 return;
1547
1548         assembly = assemblyb->dynamic_assembly = g_new0 (MonoDynamicAssembly, 1);
1549
1550         string_heap_init (&assembly->sheap);
1551         mono_image_add_stream_data (&assembly->us, "", 1);
1552         mono_image_add_stream_data (&assembly->blob, "", 1);
1553
1554         for (i=0; i < 64; ++i) {
1555                 assembly->tables [i].next_idx = 1;
1556                 assembly->tables [i].columns = table_sizes [i];
1557         }
1558         
1559 }
1560
1561 int
1562 mono_image_get_header (MonoReflectionAssemblyBuilder *assemblyb, char *buffer, int maxsize)
1563 {
1564         MonoMSDOSHeader *msdos;
1565         MonoDotNetHeader *header;
1566         MonoSectionTable *section;
1567         MonoCLIHeader *cli_header;
1568         guint32 header_size =  TEXT_OFFSET + CLI_H_SIZE;
1569         MonoDynamicAssembly *assembly;
1570
1571         static const unsigned char msheader[] = {
1572                 0x4d, 0x5a, 0x90, 0x00, 0x03, 0x00, 0x00, 0x00,  0x04, 0x00, 0x00, 0x00, 0xff, 0xff, 0x00, 0x00,
1573                 0xb8, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,  0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1574                 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1575                 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,  0x00, 0x00, 0x00, 0x00, 0x80, 0x00, 0x00, 0x00,
1576                 0x0e, 0x1f, 0xba, 0x0e, 0x00, 0xb4, 0x09, 0xcd,  0x21, 0xb8, 0x01, 0x4c, 0xcd, 0x21, 0x54, 0x68,
1577                 0x69, 0x73, 0x20, 0x70, 0x72, 0x6f, 0x67, 0x72,  0x61, 0x6d, 0x20, 0x63, 0x61, 0x6e, 0x6e, 0x6f,
1578                 0x74, 0x20, 0x62, 0x65, 0x20, 0x72, 0x75, 0x6e,  0x20, 0x69, 0x6e, 0x20, 0x44, 0x4f, 0x53, 0x20,
1579                 0x6d, 0x6f, 0x64, 0x65, 0x2e, 0x0d, 0x0d, 0x0a,  0x24, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
1580         };
1581
1582         if (maxsize < header_size)
1583                 return -1;
1584
1585         mono_image_basic_init (assemblyb);
1586         assembly = assemblyb->dynamic_assembly;
1587
1588         mono_image_build_metadata (assemblyb);
1589
1590         memset (buffer, 0, header_size);
1591         memcpy (buffer, msheader, sizeof (MonoMSDOSHeader));
1592
1593         msdos = (MonoMSDOSHeader *)buffer;
1594         header = (MonoDotNetHeader *)(buffer + sizeof (MonoMSDOSHeader));
1595         section = (MonoSectionTable*) (buffer + sizeof (MonoMSDOSHeader) + sizeof (MonoDotNetHeader));
1596
1597         /* FIXME: ENDIAN problem: byteswap as needed */
1598         msdos->pe_offset = sizeof (MonoMSDOSHeader);
1599
1600         header->pesig [0] = 'P';
1601         header->pesig [1] = 'E';
1602         header->pesig [2] = header->pesig [3] = 0;
1603
1604         header->coff.coff_machine = 0x14c;
1605         header->coff.coff_sections = 1; /* only .text supported now */
1606         header->coff.coff_time = time (NULL);
1607         header->coff.coff_opt_header_size = sizeof (MonoDotNetHeader) - sizeof (MonoCOFFHeader) - 4;
1608         /* it's an exe */
1609         header->coff.coff_attributes = 0x010e;
1610         /* it's a dll */
1611         //header->coff.coff_attributes = 0x210e;
1612         header->pe.pe_magic = 0x10B;
1613         header->pe.pe_major = 6;
1614         header->pe.pe_minor = 0;
1615         /* need to set: pe_code_size pe_data_size pe_rva_entry_point pe_rva_code_base pe_rva_data_base */
1616
1617         header->nt.pe_image_base = 0x400000;
1618         header->nt.pe_section_align = 8192;
1619         header->nt.pe_file_alignment = FILE_ALIGN;
1620         header->nt.pe_os_major = 4;
1621         header->nt.pe_os_minor = 0;
1622         header->nt.pe_subsys_major = 4;
1623         /* need to set pe_image_size, pe_header_size */
1624         header->nt.pe_subsys_required = 3; /* 3 -> cmdline app, 2 -> GUI app */
1625         header->nt.pe_stack_reserve = 0x00100000;
1626         header->nt.pe_stack_commit = 0x00001000;
1627         header->nt.pe_heap_reserve = 0x00100000;
1628         header->nt.pe_heap_commit = 0x00001000;
1629         header->nt.pe_loader_flags = 1;
1630         header->nt.pe_data_dir_count = 16;
1631
1632 #if 0
1633         /* set: */
1634         header->datadir.pe_import_table
1635         pe_resource_table
1636         pe_reloc_table
1637         pe_iat  
1638 #endif
1639         header->datadir.pe_cli_header.size = CLI_H_SIZE;
1640         header->datadir.pe_cli_header.rva = assembly->text_rva; /* we put it always at the beginning */
1641
1642         /* Write section tables */
1643         strcpy (section->st_name, ".text");
1644         section->st_virtual_size = 1024; /* FIXME */
1645         section->st_virtual_address = START_TEXT_RVA;
1646         section->st_raw_data_size = 1024; /* FIXME */
1647         section->st_raw_data_ptr = TEXT_OFFSET;
1648         section->st_flags = SECT_FLAGS_HAS_CODE | SECT_FLAGS_MEM_EXECUTE | SECT_FLAGS_MEM_READ;
1649
1650         /* 
1651          * align: build_compressed_metadata () assumes metadata is aligned 
1652          * see below:
1653          * cli_header->ch_metadata.rva = assembly->text_rva + assembly->code.index + CLI_H_SIZE;
1654          */
1655         assembly->code.index += 3;
1656         assembly->code.index &= ~3;
1657
1658         /*
1659          * Write the MonoCLIHeader header 
1660          */
1661         cli_header = (MonoCLIHeader*)(buffer + TEXT_OFFSET);
1662         cli_header->ch_size = CLI_H_SIZE;
1663         cli_header->ch_runtime_major = 2;
1664         cli_header->ch_flags = CLI_FLAGS_ILONLY;
1665         if (assemblyb->entry_point) 
1666                 cli_header->ch_entry_point = assemblyb->entry_point->table_idx | MONO_TOKEN_METHOD_DEF;
1667         else
1668                 cli_header->ch_entry_point = 0;
1669         cli_header->ch_metadata.rva = assembly->text_rva + assembly->code.index + CLI_H_SIZE;
1670         cli_header->ch_metadata.size = assembly->meta_size;
1671         
1672         return header_size;
1673 }
1674
1675 /*
1676  * We need to return always the same object for Type, MethodInfo, FieldInfo etc..
1677  */
1678 static GHashTable *object_cache = NULL;
1679
1680 #define CHECK_OBJECT(t,p)       \
1681         do {    \
1682                 t _obj; \
1683                 if (!object_cache)      \
1684                         object_cache = g_hash_table_new (g_direct_hash, g_direct_equal);        \
1685                 if ((_obj = g_hash_table_lookup (object_cache, (p))))   \
1686                         return _obj;    \
1687         } while (0)
1688
1689 #define CACHE_OBJECT(p,o)       \
1690         do {    \
1691                 g_hash_table_insert (object_cache, p,o);        \
1692         } while (0)
1693         
1694 MonoReflectionAssembly*
1695 mono_assembly_get_object (MonoDomain *domain, MonoAssembly *assembly)
1696 {
1697         static MonoClass *System_Reflection_Assembly;
1698         MonoReflectionAssembly *res;
1699         
1700         CHECK_OBJECT (MonoReflectionAssembly *, assembly);
1701         if (!System_Reflection_Assembly)
1702                 System_Reflection_Assembly = mono_class_from_name (
1703                         mono_defaults.corlib, "System.Reflection", "Assembly");
1704         res = (MonoReflectionAssembly *)mono_object_new (domain, System_Reflection_Assembly);
1705         res->assembly = assembly;
1706         CACHE_OBJECT (assembly, res);
1707         return res;
1708 }
1709
1710 MonoReflectionType*
1711 mono_type_get_object (MonoDomain *domain, MonoType *type)
1712 {
1713         MonoReflectionType *res;
1714         MonoClass *klass;
1715
1716         /* 
1717          * FIXME: type may come from the cache in metadata.c, we hand out only
1718          * the types from a MonoClass structure: the long term fix is to just
1719          * load corlib always and remove the cache in metadata.c altogether.
1720          * Or we may still handle it this way so we can store in MonoType additional info
1721          * as we do now.
1722          */
1723         klass = mono_class_from_mono_type (type);
1724         if ((type != &klass->byval_arg) && (type != &klass->this_arg)) {
1725                 if (type->byref)
1726                         type = &klass->this_arg;
1727                 else
1728                         type = &klass->byval_arg;
1729         }
1730         CHECK_OBJECT (MonoReflectionType *, type);
1731         res = (MonoReflectionType *)mono_object_new (domain, mono_defaults.monotype_class);
1732         res->type = type;
1733         CACHE_OBJECT (type, res);
1734         return res;
1735 }
1736
1737 MonoReflectionMethod*
1738 mono_method_get_object (MonoDomain *domain, MonoMethod *method)
1739 {
1740         /*
1741          * We use the same C representation for methods and constructors, but the type 
1742          * name in C# is different.
1743          */
1744         char *cname;
1745         MonoClass *klass;
1746         MonoReflectionMethod *ret;
1747
1748         CHECK_OBJECT (MonoReflectionMethod *, method);
1749         if (*method->name == '.' && (strcmp (method->name, ".ctor") == 0 || strcmp (method->name, ".cctor") == 0))
1750                 cname = "MonoCMethod";
1751         else
1752                 cname = "MonoMethod";
1753         klass = mono_class_from_name (mono_defaults.corlib, "System.Reflection", cname);
1754
1755         ret = (MonoReflectionMethod*)mono_object_new (domain, klass);
1756         ret->method = method;
1757         CACHE_OBJECT (method, ret);
1758         return ret;
1759 }
1760
1761 MonoReflectionField*
1762 mono_field_get_object (MonoDomain *domain, MonoClass *klass, MonoClassField *field)
1763 {
1764         MonoReflectionField *res;
1765         MonoClass *oklass;
1766
1767         CHECK_OBJECT (MonoReflectionField *, field);
1768         oklass = mono_class_from_name (mono_defaults.corlib, "System.Reflection", "MonoField");
1769         res = (MonoReflectionField *)mono_object_new (domain, oklass);
1770         res->klass = klass;
1771         res->field = field;
1772         CACHE_OBJECT (field, res);
1773         return res;
1774 }
1775
1776 MonoReflectionProperty*
1777 mono_property_get_object (MonoDomain *domain, MonoClass *klass, MonoProperty *property)
1778 {
1779         MonoReflectionProperty *res;
1780         MonoClass *oklass;
1781
1782         CHECK_OBJECT (MonoReflectionProperty *, property);
1783         oklass = mono_class_from_name (mono_defaults.corlib, "System.Reflection", "MonoProperty");
1784         res = (MonoReflectionProperty *)mono_object_new (domain, oklass);
1785         res->klass = klass;
1786         res->property = property;
1787         CACHE_OBJECT (property, res);
1788         return res;
1789 }
1790
1791 MonoReflectionParameter**
1792 mono_param_get_objects (MonoDomain *domain, MonoMethod *method)
1793 {
1794         MonoReflectionParameter **res;
1795         MonoReflectionMethod *member;
1796         MonoClass *oklass;
1797         char **names;
1798         int i;
1799
1800         if (!method->signature->param_count)
1801                 return NULL;
1802
1803         member = mono_method_get_object (domain, method);
1804         names = g_new (char *, method->signature->param_count);
1805         mono_method_get_param_names (method, (const char **) names);
1806         
1807         /* Note: the cache is based on the address of the signature into the method
1808          * since we already cache MethodInfos with the method as keys.
1809          */
1810         CHECK_OBJECT (MonoReflectionParameter**, &(method->signature));
1811         oklass = mono_class_from_name (mono_defaults.corlib, "System.Reflection", "ParameterInfo");
1812         res = g_new0 (MonoReflectionParameter*, method->signature->param_count);
1813         for (i = 0; i < method->signature->param_count; ++i) {
1814                 res [i] = (MonoReflectionParameter *)mono_object_new (domain, oklass);
1815                 res [i]->ClassImpl = mono_type_get_object (domain, method->signature->params [i]);
1816                 res [i]->DefaultValueImpl = NULL; /* FIXME */
1817                 res [i]->MemberImpl = (MonoObject*)member;
1818                 res [i]->NameImpl = mono_string_new (domain, names [i]);
1819                 res [i]->PositionImpl = i + 1;
1820                 res [i]->AttrsImpl = method->signature->params [i]->attrs;
1821         }
1822         g_free (names);
1823         CACHE_OBJECT (&(method->signature), res);
1824         return res;
1825 }
1826
1827 /*
1828  * Parse a type name as accepted by the GetType () method and output the info
1829  * extracted in the info structure.
1830  * the name param will be mangled, so, make a copy before passing it to this function.
1831  * The fields in info will be valid until the memory pointed to by name is valid.
1832  * Returns 0 on parse error.
1833  */
1834 int
1835 mono_reflection_parse_type (char *name, MonoTypeNameParse *info) {
1836
1837         char *start, *p, *w, *last_point;
1838         int in_modifiers = 0;
1839
1840         start = p = w = name;
1841
1842         info->name = info->name_space = info->assembly = NULL;
1843         info->nest_name = info->nest_name_space = NULL;
1844         info->rank = info->isbyref = info->ispointer = 0;
1845
1846         last_point = NULL;
1847
1848         while (*p) {
1849                 switch (*p) {
1850                 case '+':
1851                         /* we have parsed the nesting namespace + name */
1852                         if (last_point) {
1853                                 info->nest_name_space = start;
1854                                 *last_point = 0;
1855                                 info->nest_name = last_point + 1;
1856                         } else {
1857                                 info->nest_name_space = "";
1858                                 info->nest_name = start;
1859                         }
1860                         *p = 0; /* NULL terminate */
1861                         last_point = NULL;
1862                         start = p + 1;
1863                         break;
1864                 case '.':
1865                         last_point = w;
1866                         break;
1867                 case '\\':
1868                         ++p;
1869                         break;
1870                 case '&':
1871                 case '*':
1872                 case '[':
1873                 case ',':
1874                         in_modifiers = 1;
1875                         break;
1876                 default:
1877                         break;
1878                 }
1879                 if (in_modifiers)
1880                         break;
1881                 *w++ = *p++;
1882         }
1883         
1884         if (last_point) {
1885                 info->name_space = start;
1886                 *last_point = 0;
1887                 info->name = last_point + 1;
1888         } else {
1889                 info->name_space = "";
1890                 info->name = start;
1891         }
1892         /* FIXME: we don't mainatin an order for byref, pointer and array... */
1893         while (*p) {
1894                 switch (*p) {
1895                 case '&':
1896                         info->isbyref = 1;
1897                         *p++ = 0;
1898                         break;
1899                 case '*':
1900                         info->ispointer = 1;
1901                         *p++ = 0;
1902                         break;
1903                 case '[':
1904                         info->rank = 1;
1905                         *p++ = 0;
1906                         while (*p) {
1907                                 if (*p == ',')
1908                                         info->rank++;
1909                                 if (*p == ']')
1910                                         break;
1911                                 ++p;
1912                         }
1913                         if (*p++ != ']')
1914                                 return 0;
1915                         break;
1916                 case ',':
1917                         *p++ = 0;
1918                         while (*p) {
1919                                 if (*p == ' ') {
1920                                         ++p;
1921                                         continue;
1922                                 }
1923                                 break;
1924                         }
1925                         if (!*p)
1926                                 return 0; /* missing assembly name */
1927                         info->assembly = p;
1928                         break;
1929                 default:
1930                         break;
1931                 }
1932         }
1933         *w = 0; /* terminate class name */
1934         if (!info->name || !*info->name)
1935                 return 0;
1936         if (info->nest_name && !*info->nest_name)
1937                 return 0;
1938         /* add other consistency checks */
1939         return 1;
1940 }
1941
1942 static MonoObject*
1943 dummy_runtime_invoke (MonoMethod *method, void *obj, void **params)
1944 {
1945         g_error ("runtime invoke called on uninitialized runtime");
1946         return NULL;
1947 }
1948
1949 MonoInvokeFunc mono_default_runtime_invoke = dummy_runtime_invoke;
1950
1951 void
1952 mono_install_runtime_invoke (MonoInvokeFunc func) {
1953         if (func)
1954                 mono_default_runtime_invoke = func;
1955         else
1956                 mono_default_runtime_invoke = dummy_runtime_invoke;
1957 }
1958
1959 MonoObject*
1960 mono_runtime_invoke (MonoMethod *method, void *obj, void **params)
1961 {
1962         return mono_default_runtime_invoke (method, obj, params);;
1963 }
1964
1965 /*
1966  * Optimization we could avoid mallocing() an little-endian archs that
1967  * don't crash with unaligned accesses.
1968  */
1969 static void
1970 fill_param_data (MonoImage *image, MonoMethodSignature *sig, guint32 blobidx, void **params) {
1971         int len, i, slen, type;
1972         const char *p = mono_metadata_blob_heap (image, blobidx);
1973
1974         len = mono_metadata_decode_value (p, &p);
1975         if (len < 2 || read16 (p) != 0x0001) /* Prolog */
1976                 return;
1977
1978         /* skip prolog */
1979         p += 2;
1980         for (i = 0; i < sig->param_count; ++i) {
1981                 type = sig->params [i]->type;
1982 handle_enum:
1983                 switch (type) {
1984                 case MONO_TYPE_U1:
1985                 case MONO_TYPE_I1:
1986                 case MONO_TYPE_BOOLEAN: {
1987                         MonoBoolean *bval = params [i] = g_malloc (sizeof (MonoBoolean));
1988                         *bval = *p;
1989                         ++p;
1990                         break;
1991                 }
1992                 case MONO_TYPE_CHAR:
1993                 case MONO_TYPE_U2:
1994                 case MONO_TYPE_I2: {
1995                         guint16 *val = params [i] = g_malloc (sizeof (guint16));
1996                         *val = read16 (p);
1997                         p += 2;
1998                         break;
1999                 }
2000 #if SIZEOF_VOID_P == 4
2001                 case MONO_TYPE_U:
2002                 case MONO_TYPE_I:
2003 #endif
2004                 case MONO_TYPE_R4:
2005                 case MONO_TYPE_U4:
2006                 case MONO_TYPE_I4: {
2007                         guint32 *val = params [i] = g_malloc (sizeof (guint32));
2008                         *val = read32 (p);
2009                         p += 4;
2010                         break;
2011                 }
2012 #if SIZEOF_VOID_P == 8
2013                 case MONO_TYPE_U: /* error out instead? this should probably not happen */
2014                 case MONO_TYPE_I:
2015 #endif
2016                 case MONO_TYPE_R8:
2017                 case MONO_TYPE_U8:
2018                 case MONO_TYPE_I8: {
2019                         guint64 *val = params [i] = g_malloc (sizeof (guint64));
2020                         *val = read64 (p);
2021                         p += 8;
2022                         break;
2023                 }
2024                 case MONO_TYPE_VALUETYPE:
2025                         if (sig->params [i]->data.klass->enumtype) {
2026                                 type = sig->params [i]->data.klass->enum_basetype->type;
2027                                 goto handle_enum;
2028                         } else {
2029                                 g_warning ("generic valutype not handled in custom attr value decoding");
2030                         }
2031                         break;
2032                 case MONO_TYPE_STRING: {
2033                         slen = mono_metadata_decode_value (p, &p);
2034                         params [i] = mono_string_new_len (mono_domain_get (), p, slen);
2035                         p += slen;
2036                         break;
2037                 }
2038                 default:
2039                         g_warning ("Type %02x not handled in custom attr value decoding", sig->params [i]->type);
2040                         break;
2041                 }
2042         }
2043 }
2044
2045 static void
2046 free_param_data (MonoMethodSignature *sig, void **params) {
2047         int i;
2048         for (i = 0; i < sig->param_count; ++i) {
2049                 switch (sig->params [i]->type) {
2050                 case MONO_TYPE_BOOLEAN:
2051                 case MONO_TYPE_CHAR:
2052                 case MONO_TYPE_U:
2053                 case MONO_TYPE_I:
2054                 case MONO_TYPE_U1:
2055                 case MONO_TYPE_I1:
2056                 case MONO_TYPE_U2:
2057                 case MONO_TYPE_I2:
2058                 case MONO_TYPE_U4:
2059                 case MONO_TYPE_I4:
2060                 case MONO_TYPE_U8:
2061                 case MONO_TYPE_I8:
2062                 case MONO_TYPE_R8:
2063                 case MONO_TYPE_R4:
2064                 case MONO_TYPE_VALUETYPE:
2065                         g_free (params [i]);
2066                         break;
2067                 default:
2068                         break;
2069                 }
2070         }
2071 }
2072
2073 /*
2074  * Find the method index in the metadata methodDef table.
2075  * Later put these three helper methods in metadata and export them.
2076  */
2077 static guint32
2078 find_method_index (MonoMethod *method) {
2079         MonoClass *klass = method->klass;
2080         int i;
2081
2082         for (i = 0; i < klass->method.count; ++i) {
2083                 if (method == klass->methods [i])
2084                         return klass->method.first + 1 + i;
2085         }
2086         return 0;
2087 }
2088
2089 /*
2090  * Find the field index in the metadata FieldDef table.
2091  */
2092 static guint32
2093 find_field_index (MonoClass *klass, MonoClassField *field) {
2094         int i;
2095
2096         for (i = 0; i < klass->field.count; ++i) {
2097                 if (field == &klass->fields [i])
2098                         return klass->field.first + 1 + i;
2099         }
2100         return 0;
2101 }
2102
2103 /*
2104  * Find the property index in the metadata FieldDef table.
2105  */
2106 static guint32
2107 find_property_index (MonoClass *klass, MonoProperty *property) {
2108         int i;
2109
2110         for (i = 0; i < klass->property.count; ++i) {
2111                 if (property == &klass->properties [i])
2112                         return klass->property.first + 1 + i;
2113         }
2114         return 0;
2115 }
2116
2117 MonoArray*
2118 mono_reflection_get_custom_attrs (MonoObject *obj)
2119 {
2120         guint32 index, mtoken, i;
2121         guint32 cols [MONO_CUSTOM_ATTR_SIZE];
2122         MonoClass *klass;
2123         MonoImage *image;
2124         MonoTableInfo *ca;
2125         MonoMethod *method;
2126         MonoObject *attr;
2127         MonoArray *result;
2128         GList *list = NULL;
2129         void **params;
2130         
2131         klass = obj->vtable->klass;
2132         /* FIXME: need to handle: Module, MonoProperty */
2133         if (klass == mono_defaults.monotype_class) {
2134                 MonoReflectionType *rtype = (MonoReflectionType*)obj;
2135                 klass = mono_class_from_mono_type (rtype->type);
2136                 index = mono_metadata_token_index (klass->type_token);
2137                 index <<= CUSTOM_ATTR_BITS;
2138                 index |= CUSTOM_ATTR_TYPEDEF;
2139                 image = klass->image;
2140         } else if (strcmp ("Assembly", klass->name) == 0) {
2141                 MonoReflectionAssembly *rassembly = (MonoReflectionAssembly*)obj;
2142                 index = 1; /* there is only one assembly */
2143                 index <<= CUSTOM_ATTR_BITS;
2144                 index |= CUSTOM_ATTR_ASSEMBLY;
2145                 image = rassembly->assembly->image;
2146         } else if (strcmp ("MonoProperty", klass->name) == 0) {
2147                 MonoReflectionProperty *rprop = (MonoReflectionProperty*)obj;
2148                 index = find_property_index (rprop->klass, rprop->property);
2149                 index <<= CUSTOM_ATTR_BITS;
2150                 index |= CUSTOM_ATTR_PROPERTY;
2151                 image = rprop->klass->image;
2152         } else if (strcmp ("MonoField", klass->name) == 0) {
2153                 MonoReflectionField *rfield = (MonoReflectionField*)obj;
2154                 index = find_field_index (rfield->klass, rfield->field);
2155                 index <<= CUSTOM_ATTR_BITS;
2156                 index |= CUSTOM_ATTR_FIELDDEF;
2157                 image = rfield->klass->image;
2158         } else if ((strcmp ("MonoMethod", klass->name) == 0) || (strcmp ("MonoCMethod", klass->name) == 0)) {
2159                 MonoReflectionMethod *rmethod = (MonoReflectionMethod*)obj;
2160                 index = find_method_index (rmethod->method);
2161                 index <<= CUSTOM_ATTR_BITS;
2162                 index |= CUSTOM_ATTR_METHODDEF;
2163                 image = method->klass->image;
2164         } else if (strcmp ("ParameterInfo", klass->name) == 0) {
2165                 MonoReflectionParameter *param = (MonoReflectionParameter*)obj;
2166                 MonoReflectionMethod *rmethod = (MonoReflectionMethod*)param->MemberImpl;
2167                 guint32 method_index = find_method_index (rmethod->method);
2168                 guint32 param_list, param_last, param_pos, found;
2169
2170                 image = rmethod->method->klass->image;
2171                 ca = &image->tables [MONO_TABLE_METHOD];
2172
2173                 param_list = mono_metadata_decode_row_col (ca, method_index - 1, MONO_METHOD_PARAMLIST);
2174                 if (method_index == ca->rows) {
2175                         ca = &image->tables [MONO_TABLE_PARAM];
2176                         param_last = ca->rows + 1;
2177                 } else {
2178                         param_last = mono_metadata_decode_row_col (ca, method_index, MONO_METHOD_PARAMLIST);
2179                         ca = &image->tables [MONO_TABLE_PARAM];
2180                 }
2181                 found = 0;
2182                 for (i = param_list; i < param_list; ++i) {
2183                         param_pos = mono_metadata_decode_row_col (ca, i - 1, MONO_PARAM_SEQUENCE);
2184                         if (param_pos == param->PositionImpl) {
2185                                 found = 1;
2186                                 break;
2187                         }
2188                 }
2189                 if (!found)
2190                         return mono_array_new (mono_domain_get (), mono_defaults.object_class, 0);
2191                 index = i;
2192                 index <<= CUSTOM_ATTR_BITS;
2193                 index |= CUSTOM_ATTR_PARAMDEF;
2194         } else { /* handle other types here... */
2195                 g_error ("get custom attrs not yet supported for %s", klass->name);
2196         }
2197
2198         /* at this point image and index are set correctly for searching the custom attr */
2199         ca = &image->tables [MONO_TABLE_CUSTOMATTRIBUTE];
2200         /* the table is not sorted */
2201         for (i = 0; i < ca->rows; ++i) {
2202                 mono_metadata_decode_row (ca, i, cols, MONO_CUSTOM_ATTR_SIZE);
2203                 if (cols [MONO_CUSTOM_ATTR_PARENT] != index)
2204                         continue;
2205                 mtoken = cols [MONO_CUSTOM_ATTR_TYPE] >> CUSTOM_ATTR_TYPE_BITS;
2206                 switch (cols [MONO_CUSTOM_ATTR_TYPE] & CUSTOM_ATTR_TYPE_MASK) {
2207                 case CUSTOM_ATTR_TYPE_METHODDEF:
2208                         mtoken |= MONO_TOKEN_METHOD_DEF;
2209                         break;
2210                 case CUSTOM_ATTR_TYPE_MEMBERREF:
2211                         mtoken |= MONO_TOKEN_MEMBER_REF;
2212                         break;
2213                 default:
2214                         g_error ("Unknown table for custom attr type %08x", cols [MONO_CUSTOM_ATTR_TYPE]);
2215                         break;
2216                 }
2217                 method = mono_get_method (image, mtoken, NULL);
2218                 if (!method)
2219                         g_error ("Can't find custom attr constructor");
2220                 mono_class_init (method->klass);
2221                 /*g_print ("got attr %s\n", method->klass->name);*/
2222                 params = g_new (void*, method->signature->param_count);
2223                 fill_param_data (image, method->signature, cols [MONO_CUSTOM_ATTR_VALUE], params);
2224                 attr = mono_object_new (mono_domain_get (), method->klass);
2225                 mono_runtime_invoke (method, attr, params);
2226                 list = g_list_prepend (list, attr);
2227                 free_param_data (method->signature, params);
2228                 g_free (params);
2229         }
2230
2231         index = g_list_length (list);
2232         /*
2233          * The return type is really object[], but System/Attribute.cs does a cast
2234          * to (Attribute []) and that is not allowed: I'm lazy for now, but we should
2235          * probably fix that.
2236          */
2237         klass = mono_class_from_name (mono_defaults.corlib, "System", "Attribute");
2238         result = mono_array_new (mono_domain_get (), klass, index);
2239         for (i = 0; i < index; ++i) {
2240                 mono_array_set (result, gpointer, i, list->data);
2241                 list = list->next;
2242         }
2243         g_list_free (g_list_first (list));
2244
2245         return result;
2246 }
2247
2248 MonoArray*
2249 mono_reflection_get_custom_attrs_blob (MonoObject *ctor, MonoArray *ctorArgs, MonoArray *properties, MonoArray *porpValues, MonoArray *fields, MonoArray* fieldValues) {
2250         MonoArray *result;
2251         MonoMethodSignature *sig;
2252         MonoObject *arg;
2253         char *buffer, *p, *argval;
2254         guint32 buflen, i, type;
2255
2256         if (strcmp (ctor->vtable->klass->name, "MonoCMethod")) {
2257                 g_warning ("ConstructorBuilder Custom attribute not yet supported");
2258                 /* 
2259                  * maybe we should have a param array to method signature function and
2260                  * continue with the normal codepath.
2261                  */
2262                 result = mono_array_new (mono_domain_get (), mono_defaults.byte_class, 4);
2263                 mono_array_set (result, char, 0, 1);
2264                 return result;
2265         }
2266         buflen = 256;
2267         p = buffer = g_malloc (buflen);
2268         /* write the prolog */
2269         *p++ = 1;
2270         *p++ = 0;
2271         sig = ((MonoReflectionMethod*)ctor)->method->signature;
2272         /* FIXME: ENOENDIAN */
2273         for (i = 0; i < sig->param_count; ++i) {
2274                 if ((p-buffer) + 10 >= buflen) {
2275                         char *newbuf;
2276                         buflen *= 2;
2277                         newbuf = g_realloc (buffer, buflen);
2278                         p = newbuf + (p-buffer);
2279                         buffer = newbuf;
2280                 }
2281                 arg = (MonoObject*)mono_array_get (ctorArgs, gpointer, i);
2282                 argval = ((char*)arg + sizeof (MonoObject));
2283                 type = sig->params [i]->type;
2284 handle_enum:
2285                 switch (type) {
2286                 case MONO_TYPE_BOOLEAN:
2287                 case MONO_TYPE_U1:
2288                 case MONO_TYPE_I1:
2289                         *p++ = *argval;
2290                         break;
2291                 case MONO_TYPE_CHAR:
2292                 case MONO_TYPE_U2:
2293                 case MONO_TYPE_I2: {
2294                         guint16 *val = (guint16*)p;
2295                         *val = *(guint16*)argval;
2296                         p += 2;
2297                         break;
2298                 }
2299                 case MONO_TYPE_U4:
2300                 case MONO_TYPE_I4:
2301                 case MONO_TYPE_R4: {
2302                         guint32 *val = (guint32*)p;
2303                         *val = *(guint32*)argval;
2304                         p += 4;
2305                         break;
2306                 }
2307                 case MONO_TYPE_U8:
2308                 case MONO_TYPE_I8:
2309                 case MONO_TYPE_R8: {
2310                         guint64 *val = (guint64*)p;
2311                         *val = *(guint64*)argval;
2312                         p += 8;
2313                         break;
2314                 }
2315                 case MONO_TYPE_VALUETYPE:
2316                         if (sig->params [i]->data.klass->enumtype) {
2317                                 type = sig->params [i]->data.klass->enum_basetype->type;
2318                                 goto handle_enum;
2319                         } else {
2320                                 g_warning ("generic valutype not handled in custom attr value decoding");
2321                         }
2322                         break;
2323                 case MONO_TYPE_STRING: {
2324                         char *str = mono_string_to_utf8 ((MonoString*)arg);
2325                         guint32 slen = strlen (str);
2326                         if ((p-buffer) + 10 + slen >= buflen) {
2327                                 char *newbuf;
2328                                 buflen *= 2;
2329                                 buflen += slen;
2330                                 newbuf = g_realloc (buffer, buflen);
2331                                 p = newbuf + (p-buffer);
2332                                 buffer = newbuf;
2333                         }
2334                         mono_metadata_encode_value (slen, p, &p);
2335                         memcpy (p, str, slen);
2336                         p += slen;
2337                         g_free (str);
2338                         break;
2339                 }
2340                 default:
2341                         g_error ("type 0x%02x not yet supported in custom attr encoder", type);
2342                 }
2343         }
2344         /* 
2345          * we don't support properties and fields, yet, set to 0.
2346          */
2347         *p++ = 0;
2348         *p++ = 0;
2349         buflen = p - buffer;
2350         result = mono_array_new (mono_domain_get (), mono_defaults.byte_class, buflen);
2351         p = mono_array_addr (result, char, 0);
2352         memcpy (p, buffer, buflen);
2353         g_free (buffer);
2354         return result;
2355 }
2356