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