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