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