2003-02-17 Gonzalo Paniagua Javier <gonzalo@ximian.com>
[mono.git] / mono / metadata / reflection.c
1
2 /*
3  * reflection.c: Routines for creating an image at runtime.
4  * 
5  * Author:
6  *   Paolo Molaro (lupus@ximian.com)
7  *
8  * (C) 2001, 2002 Ximian, Inc.  http://www.ximian.com
9  *
10  */
11 #include <config.h>
12 #include "mono/utils/mono-digest.h"
13 #include "mono/metadata/reflection.h"
14 #include "mono/metadata/tabledefs.h"
15 #include "mono/metadata/tokentype.h"
16 #include "mono/metadata/appdomain.h"
17 #include "mono/metadata/opcodes.h"
18 #include "mono/metadata/assembly.h"
19 #include <mono/metadata/exception.h>
20 #include <stdio.h>
21 #include <glib.h>
22 #include <errno.h>
23 #include <time.h>
24 #include <string.h>
25 #include <ctype.h>
26 #include "image.h"
27 #include "cil-coff.h"
28 #include "rawbuffer.h"
29 #include "mono-endian.h"
30 #include "private.h"
31 #include <mono/os/gc_wrapper.h>
32
33 #define TEXT_OFFSET 512
34 #define CLI_H_SIZE 136
35 #define FILE_ALIGN 512
36 #define VIRT_ALIGN 8192
37 #define START_TEXT_RVA  0x00002000
38
39 typedef struct {
40         MonoReflectionILGen *ilgen;
41         MonoReflectionType *rtype;
42         MonoArray *parameters;
43         MonoArray *pinfo;
44         guint32 attrs;
45         guint32 iattrs;
46         guint32 call_conv;
47         guint32 *table_idx; /* note: it's a pointer */
48         MonoArray *code;
49         MonoObject *type;
50         MonoString *name;
51         MonoBoolean init_locals;
52 } ReflectionMethodBuilder;
53
54 const unsigned char table_sizes [64] = {
55         MONO_MODULE_SIZE,
56         MONO_TYPEREF_SIZE,
57         MONO_TYPEDEF_SIZE,
58         0,
59         MONO_FIELD_SIZE,
60         0,
61         MONO_METHOD_SIZE,
62         0,
63         MONO_PARAM_SIZE,
64         MONO_INTERFACEIMPL_SIZE,
65         MONO_MEMBERREF_SIZE,    /* 0x0A */
66         MONO_CONSTANT_SIZE,
67         MONO_CUSTOM_ATTR_SIZE,
68         MONO_FIELD_MARSHAL_SIZE,
69         MONO_DECL_SECURITY_SIZE,
70         MONO_CLASS_LAYOUT_SIZE,
71         MONO_FIELD_LAYOUT_SIZE, /* 0x10 */
72         MONO_STAND_ALONE_SIGNATURE_SIZE,
73         MONO_EVENT_MAP_SIZE,
74         0,
75         MONO_EVENT_SIZE,
76         MONO_PROPERTY_MAP_SIZE,
77         0,
78         MONO_PROPERTY_SIZE,
79         MONO_METHOD_SEMA_SIZE,
80         MONO_METHODIMPL_SIZE,
81         MONO_MODULEREF_SIZE,    /* 0x1A */
82         MONO_TYPESPEC_SIZE,
83         MONO_IMPLMAP_SIZE,      
84         MONO_FIELD_RVA_SIZE,
85         0,
86         0,
87         MONO_ASSEMBLY_SIZE,     /* 0x20 */
88         MONO_ASSEMBLY_PROCESSOR_SIZE,
89         MONO_ASSEMBLYOS_SIZE,
90         MONO_ASSEMBLYREF_SIZE,
91         MONO_ASSEMBLYREFPROC_SIZE,
92         MONO_ASSEMBLYREFOS_SIZE,
93         MONO_FILE_SIZE,
94         MONO_EXP_TYPE_SIZE,
95         MONO_MANIFEST_SIZE,
96         MONO_NESTED_CLASS_SIZE,
97         0       /* 0x2A */
98 };
99
100 static guint32 mono_image_typedef_or_ref (MonoDynamicAssembly *assembly, MonoType *type);
101 static guint32 mono_image_get_methodref_token (MonoDynamicAssembly *assembly, MonoMethod *method);
102 static guint32 mono_image_get_sighelper_token (MonoDynamicAssembly *assembly, MonoReflectionSigHelper *helper);
103 static guint32 encode_marshal_blob (MonoDynamicAssembly *assembly, MonoReflectionMarshal *minfo);
104
105 static void
106 alloc_table (MonoDynamicTable *table, guint nrows)
107 {
108         table->rows = nrows;
109         g_assert (table->columns);
110         table->values = g_realloc (table->values, (1 + table->rows) * table->columns * sizeof (guint32));
111 }
112
113 static guint32
114 string_heap_insert (MonoDynamicStream *sh, const char *str)
115 {
116         guint32 idx;
117         guint32 len;
118         gpointer oldkey, oldval;
119
120         if (g_hash_table_lookup_extended (sh->hash, str, &oldkey, &oldval))
121                 return GPOINTER_TO_UINT (oldval);
122
123         len = strlen (str) + 1;
124         idx = sh->index;
125         if (idx + len > sh->alloc_size) {
126                 sh->alloc_size += len + 4096;
127                 sh->data = g_realloc (sh->data, sh->alloc_size);
128         }
129         /*
130          * We strdup the string even if we already copy them in sh->data
131          * so that the string pointers in the hash remain valid even if
132          * we need to realloc sh->data. We may want to avoid that later.
133          */
134         g_hash_table_insert (sh->hash, g_strdup (str), GUINT_TO_POINTER (idx));
135         memcpy (sh->data + idx, str, len);
136         sh->index += len;
137         return idx;
138 }
139
140 static void
141 string_heap_init (MonoDynamicStream *sh)
142 {
143         sh->index = 0;
144         sh->alloc_size = 4096;
145         sh->data = g_malloc (4096);
146         sh->hash = g_hash_table_new (g_str_hash, g_str_equal);
147         string_heap_insert (sh, "");
148 }
149
150 #if 0 /* never used */
151 static void
152 string_heap_free (MonoDynamicStream *sh)
153 {
154         g_free (sh->data);
155         g_hash_table_foreach (sh->hash, (GHFunc)g_free, NULL);
156         g_hash_table_destroy (sh->hash);
157 }
158 #endif
159
160 static guint32
161 mono_image_add_stream_data (MonoDynamicStream *stream, const char *data, guint32 len)
162 {
163         guint32 idx;
164         if (stream->alloc_size < stream->index + len) {
165                 stream->alloc_size += len + 4096;
166                 stream->data = g_realloc (stream->data, stream->alloc_size);
167         }
168         memcpy (stream->data + stream->index, data, len);
169         idx = stream->index;
170         stream->index += len;
171         /* 
172          * align index? Not without adding an additional param that controls it since
173          * we may store a blob value in pieces.
174          */
175         return idx;
176 }
177
178 static guint32
179 mono_image_add_stream_zero (MonoDynamicStream *stream, guint32 len)
180 {
181         guint32 idx;
182         if (stream->alloc_size < stream->index + len) {
183                 stream->alloc_size += len + 4096;
184                 stream->data = g_realloc (stream->data, stream->alloc_size);
185         }
186         memset (stream->data + stream->index, 0, len);
187         idx = stream->index;
188         stream->index += len;
189         return idx;
190 }
191
192 static void
193 stream_data_align (MonoDynamicStream *stream)
194 {
195         char buf [4] = {0};
196         guint32 count = stream->index % 4;
197
198         /* we assume the stream data will be aligned */
199         if (count)
200                 mono_image_add_stream_data (stream, buf, 4 - count);
201 }
202
203 static int
204 mono_blob_entry_hash (const char* str)
205 {
206         guint len, h;
207         const char *end;
208         len = mono_metadata_decode_blob_size (str, &str);
209         end = str + len;
210         h = *str;
211         for (str += 1; str < end; str++)
212                 h = (h << 5) - h + *str;
213         return h;
214 }
215
216 static gboolean
217 mono_blob_entry_equal (const char *str1, const char *str2) {
218         int len, len2;
219         const char *end1;
220         const char *end2;
221         len = mono_metadata_decode_blob_size (str1, &end1);
222         len2 = mono_metadata_decode_blob_size (str2, &end2);
223         if (len != len2)
224                 return 0;
225         return memcmp (end1, end2, len) == 0;
226 }
227
228 static guint32
229 add_to_blob_cached (MonoDynamicAssembly *assembly, char *b1, int s1, char *b2, int s2)
230 {
231         guint32 idx;
232         char *copy;
233         gpointer oldkey, oldval;
234         
235         copy = g_malloc (s1+s2);
236         memcpy (copy, b1, s1);
237         memcpy (copy + s1, b2, s2);
238         if (g_hash_table_lookup_extended (assembly->blob_cache, copy, &oldkey, &oldval)) {
239                 g_free (copy);
240                 idx = GPOINTER_TO_UINT (oldval);
241         } else {
242                 idx = mono_image_add_stream_data (&assembly->blob, b1, s1);
243                 mono_image_add_stream_data (&assembly->blob, b2, s2);
244                 g_hash_table_insert (assembly->blob_cache, copy, GUINT_TO_POINTER (idx));
245         }
246         return idx;
247 }
248
249 /* modified version needed to handle building corlib */
250 static MonoClass*
251 my_mono_class_from_mono_type (MonoType *type) {
252         switch (type->type) {
253         case MONO_TYPE_ARRAY:
254         case MONO_TYPE_PTR:
255         case MONO_TYPE_SZARRAY:
256                 return mono_class_from_mono_type (type);
257         default:
258                 /* should be always valid when we reach this case... */
259                 return type->data.klass;
260         }
261 }
262
263 static void
264 encode_type (MonoDynamicAssembly *assembly, MonoType *type, char *p, char **endbuf)
265 {
266         if (!type) {
267                 g_assert_not_reached ();
268                 return;
269         }
270                 
271         if (type->byref)
272                 mono_metadata_encode_value (MONO_TYPE_BYREF, p, &p);
273
274         switch (type->type){
275         case MONO_TYPE_VOID:
276         case MONO_TYPE_BOOLEAN:
277         case MONO_TYPE_CHAR:
278         case MONO_TYPE_I1:
279         case MONO_TYPE_U1:
280         case MONO_TYPE_I2:
281         case MONO_TYPE_U2:
282         case MONO_TYPE_I4:
283         case MONO_TYPE_U4:
284         case MONO_TYPE_I8:
285         case MONO_TYPE_U8:
286         case MONO_TYPE_R4:
287         case MONO_TYPE_R8:
288         case MONO_TYPE_I:
289         case MONO_TYPE_U:
290         case MONO_TYPE_STRING:
291         case MONO_TYPE_OBJECT:
292         case MONO_TYPE_TYPEDBYREF:
293                 mono_metadata_encode_value (type->type, p, &p);
294                 break;
295         case MONO_TYPE_PTR:
296         case MONO_TYPE_SZARRAY:
297                 mono_metadata_encode_value (type->type, p, &p);
298                 encode_type (assembly, type->data.type, p, &p);
299                 break;
300         case MONO_TYPE_VALUETYPE:
301         case MONO_TYPE_CLASS:
302                 mono_metadata_encode_value (type->type, p, &p);
303                 mono_metadata_encode_value (mono_image_typedef_or_ref (assembly, type), p, &p);
304                 break;
305 #if 0
306         case MONO_TYPE_VALUETYPE:
307         case MONO_TYPE_CLASS: {
308                 MonoClass *k = mono_class_from_mono_type (type);
309                 mono_metadata_encode_value (type->type, p, &p);
310                 /* ensure only non-byref gets passed to mono_image_typedef_or_ref() */
311                 mono_metadata_encode_value (mono_image_typedef_or_ref (assembly, &k->byval_arg), p, &p);
312                 break;
313         }
314 #endif
315         case MONO_TYPE_ARRAY:
316                 mono_metadata_encode_value (type->type, p, &p);
317                 encode_type (assembly, type->data.array->type, p, &p);
318                 mono_metadata_encode_value (type->data.array->rank, p, &p);
319                 mono_metadata_encode_value (0, p, &p); /* FIXME: set to 0 for now */
320                 mono_metadata_encode_value (0, p, &p);
321                 break;
322         default:
323                 g_error ("need to encode type %x", type->type);
324         }
325         *endbuf = p;
326 }
327
328 static void
329 encode_reflection_type (MonoDynamicAssembly *assembly, MonoReflectionType *type, char *p, char **endbuf)
330 {
331         if (!type) {
332                 mono_metadata_encode_value (MONO_TYPE_VOID, p, endbuf);
333                 return;
334         }
335         if (type->type) {
336                 encode_type (assembly, type->type, p, endbuf);
337                 return;
338         }
339
340         g_assert_not_reached ();
341
342 }
343
344 static guint32
345 method_encode_signature (MonoDynamicAssembly *assembly, MonoMethodSignature *sig)
346 {
347         char *buf;
348         char *p;
349         int i;
350         guint32 nparams =  sig->param_count;
351         guint32 size = 10 + nparams * 10;
352         guint32 idx;
353         char blob_size [6];
354         char *b = blob_size;
355         
356         p = buf = g_malloc (size);
357         /*
358          * FIXME: vararg, explicit_this, differenc call_conv values...
359          */
360         *p = sig->call_convention;
361         if (sig->hasthis)
362                 *p |= 0x20; /* hasthis */
363         p++;
364         mono_metadata_encode_value (nparams, p, &p);
365         encode_type (assembly, sig->ret, p, &p);
366         for (i = 0; i < nparams; ++i)
367                 encode_type (assembly, sig->params [i], p, &p);
368         /* store length */
369         g_assert (p - buf < size);
370         mono_metadata_encode_value (p-buf, b, &b);
371         idx = add_to_blob_cached (assembly, blob_size, b-blob_size, buf, p-buf);
372         g_free (buf);
373         return idx;
374 }
375
376 static guint32
377 method_builder_encode_signature (MonoDynamicAssembly *assembly, ReflectionMethodBuilder *mb)
378 {
379         /*
380          * FIXME: reuse code from method_encode_signature().
381          */
382         char *buf;
383         char *p;
384         int i;
385         guint32 nparams =  mb->parameters ? mono_array_length (mb->parameters): 0;
386         guint32 size = 10 + nparams * 10;
387         guint32 idx;
388         char blob_size [6];
389         char *b = blob_size;
390         
391         p = buf = g_malloc (size);
392         /* LAMESPEC: all the call conv spec is foobared */
393         *p = mb->call_conv & 0x60; /* has-this, explicit-this */
394         if (mb->call_conv & 2)
395                 *p |= 0x5; /* vararg */
396         if (!(mb->attrs & METHOD_ATTRIBUTE_STATIC))
397                 *p |= 0x20; /* hasthis */
398         p++;
399         mono_metadata_encode_value (nparams, p, &p);
400         encode_reflection_type (assembly, mb->rtype, p, &p);
401         for (i = 0; i < nparams; ++i) {
402                 MonoReflectionType *pt = mono_array_get (mb->parameters, MonoReflectionType*, i);
403                 encode_reflection_type (assembly, pt, p, &p);
404         }
405         /* store length */
406         g_assert (p - buf < size);
407         mono_metadata_encode_value (p-buf, b, &b);
408         idx = add_to_blob_cached (assembly, blob_size, b-blob_size, buf, p-buf);
409         g_free (buf);
410         return idx;
411 }
412
413 static guint32
414 encode_locals (MonoDynamicAssembly *assembly, MonoReflectionILGen *ilgen)
415 {
416         MonoDynamicTable *table;
417         guint32 *values;
418         char *p;
419         guint32 idx, sig_idx, size;
420         guint nl = mono_array_length (ilgen->locals);
421         char *buf;
422         char blob_size [6];
423         char *b = blob_size;
424         int i;
425
426         size = 10 + nl * 10;
427         p = buf = g_malloc (size);
428         table = &assembly->tables [MONO_TABLE_STANDALONESIG];
429         idx = table->next_idx ++;
430         table->rows ++;
431         alloc_table (table, table->rows);
432         values = table->values + idx * MONO_STAND_ALONE_SIGNATURE_SIZE;
433
434         mono_metadata_encode_value (0x07, p, &p);
435         mono_metadata_encode_value (nl, p, &p);
436         for (i = 0; i < nl; ++i) {
437                 MonoReflectionLocalBuilder *lb = mono_array_get (ilgen->locals, MonoReflectionLocalBuilder*, i);
438                 encode_reflection_type (assembly, lb->type, p, &p);
439         }
440         g_assert (p - buf < size);
441         mono_metadata_encode_value (p-buf, b, &b);
442         sig_idx = add_to_blob_cached (assembly, blob_size, b-blob_size, buf, p-buf);
443         g_free (buf);
444
445         values [MONO_STAND_ALONE_SIGNATURE] = sig_idx;
446
447         return idx;
448 }
449
450 static guint32
451 method_count_clauses (MonoReflectionILGen *ilgen)
452 {
453         guint32 num_clauses = 0;
454         int i;
455
456         MonoILExceptionInfo *ex_info;
457         for (i = 0; i < mono_array_length (ilgen->ex_handlers); ++i) {
458                 ex_info = (MonoILExceptionInfo*)mono_array_addr (ilgen->ex_handlers, MonoILExceptionInfo, i);
459                 if (ex_info->handlers)
460                         num_clauses += mono_array_length (ex_info->handlers);
461                 else
462                         num_clauses++;
463         }
464
465         return num_clauses;
466 }
467
468 static MonoExceptionClause*
469 method_encode_clauses (MonoDynamicAssembly *assembly,
470                                            MonoReflectionILGen *ilgen, guint32 num_clauses)
471 {
472         MonoExceptionClause *clauses;
473         MonoExceptionClause *clause;
474         MonoILExceptionInfo *ex_info;
475         MonoILExceptionBlock *ex_block;
476         guint32 finally_start;
477         int i, j, clause_index;;
478
479         clauses = g_new0 (MonoExceptionClause, num_clauses);
480
481         clause_index = 0;
482         for (i = 0; i < mono_array_length (ilgen->ex_handlers); ++i) {
483                 ex_info = (MonoILExceptionInfo*)mono_array_addr (ilgen->ex_handlers, MonoILExceptionInfo, i);
484                 finally_start = ex_info->start + ex_info->len;
485                 g_assert (ex_info->handlers);
486                 for (j = 0; j < mono_array_length (ex_info->handlers); ++j) {
487                         ex_block = (MonoILExceptionBlock*)mono_array_addr (ex_info->handlers, MonoILExceptionBlock, j);
488                         clause = &(clauses [clause_index]);
489
490                         clause->flags = ex_block->type;
491                         clause->try_offset = ex_info->start;
492
493                         if (ex_block->type == MONO_EXCEPTION_CLAUSE_FINALLY)
494                                 clause->try_len = finally_start - ex_info->start;
495                         else
496                                 clause->try_len = ex_info->len;
497                         clause->handler_offset = ex_block->start;
498                         clause->handler_len = ex_block->len;
499                         clause->token_or_filter = ex_block->extype ? mono_metadata_token_from_dor (
500                                 mono_image_typedef_or_ref (assembly, ex_block->extype->type)): 0;
501                         if (ex_block->extype) {
502                                 mono_g_hash_table_insert (assembly->tokens,
503                                                                                   GUINT_TO_POINTER (clause->token_or_filter),
504                                                                                   ex_block->extype);
505                         }
506                         finally_start = ex_block->start + ex_block->len;
507
508                         clause_index ++;
509                 }
510         }
511
512         return clauses;
513 }
514
515 static guint32
516 method_encode_code (MonoDynamicAssembly *assembly, ReflectionMethodBuilder *mb)
517 {
518         char flags = 0;
519         guint32 idx;
520         guint32 code_size;
521         gint32 max_stack, i;
522         gint32 num_locals = 0;
523         gint32 num_exception = 0;
524         gint maybe_small;
525         guint32 fat_flags;
526         char fat_header [12];
527         guint32 *intp;
528         guint16 *shortp;
529         guint32 local_sig = 0;
530         guint32 header_size = 12;
531         MonoArray *code;
532
533         if ((mb->attrs & METHOD_ATTRIBUTE_PINVOKE_IMPL) ||
534                         (mb->iattrs & METHOD_IMPL_ATTRIBUTE_INTERNAL_CALL) ||
535                         (mb->iattrs & METHOD_IMPL_ATTRIBUTE_RUNTIME) ||
536                         (mb->attrs & METHOD_ATTRIBUTE_ABSTRACT))
537                 return 0;
538
539         /*if (mb->name)
540                 g_print ("Encode method %s\n", mono_string_to_utf8 (mb->name));*/
541         if (mb->ilgen) {
542                 code = mb->ilgen->code;
543                 code_size = mb->ilgen->code_len;
544                 max_stack = mb->ilgen->max_stack;
545                 num_locals = mb->ilgen->locals ? mono_array_length (mb->ilgen->locals) : 0;
546                 if (mb->ilgen->ex_handlers)
547                         num_exception = method_count_clauses (mb->ilgen);
548         } else {
549                 code = mb->code;
550                 code_size = mono_array_length (code);
551                 max_stack = 8; /* we probably need to run a verifier on the code... */
552         }
553
554         /* check for exceptions, maxstack, locals */
555         maybe_small = (max_stack <= 8) && (!num_locals) && (!num_exception);
556         if (maybe_small) {
557                 if (code_size < 64 && !(code_size & 1)) {
558                         flags = (code_size << 2) | 0x2;
559                 } else if (code_size < 32 && (code_size & 1)) {
560                         flags = (code_size << 2) | 0x6; /* LAMESPEC: see metadata.c */
561                 } else {
562                         goto fat_header;
563                 }
564                 idx = mono_image_add_stream_data (&assembly->code, &flags, 1);
565                 /* add to the fixup todo list */
566                 if (mb->ilgen && mb->ilgen->num_token_fixups)
567                         mono_g_hash_table_insert (assembly->token_fixups, mb->ilgen, GUINT_TO_POINTER (idx + 1));
568                 mono_image_add_stream_data (&assembly->code, mono_array_addr (code, char, 0), code_size);
569                 return assembly->text_rva + idx;
570         } 
571 fat_header:
572         if (num_locals)
573                 local_sig = MONO_TOKEN_SIGNATURE | encode_locals (assembly, mb->ilgen);
574         /* 
575          * FIXME: need to set also the header size in fat_flags.
576          * (and more sects and init locals flags)
577          */
578         fat_flags =  0x03;
579         if (num_exception)
580                 fat_flags |= METHOD_HEADER_MORE_SECTS;
581         if (mb->init_locals)
582                 fat_flags |= METHOD_HEADER_INIT_LOCALS;
583         fat_header [0] = fat_flags;
584         fat_header [1] = (header_size / 4 ) << 4;
585         shortp = (guint16*)(fat_header + 2);
586         *shortp = GUINT16_TO_LE (max_stack);
587         intp = (guint32*)(fat_header + 4);
588         *intp = GUINT32_TO_LE (code_size);
589         intp = (guint32*)(fat_header + 8);
590         *intp = GUINT32_TO_LE (local_sig);
591         idx = mono_image_add_stream_data (&assembly->code, fat_header, 12);
592         /* add to the fixup todo list */
593         if (mb->ilgen && mb->ilgen->num_token_fixups)
594                 mono_g_hash_table_insert (assembly->token_fixups, mb->ilgen, GUINT_TO_POINTER (idx + 12));
595         
596         mono_image_add_stream_data (&assembly->code, mono_array_addr (code, char, 0), code_size);
597         if (num_exception) {
598                 unsigned char sheader [4];
599                 MonoExceptionClause clause;
600                 MonoILExceptionInfo * ex_info;
601                 MonoILExceptionBlock * ex_block;
602                 int j;
603
604                 stream_data_align (&assembly->code);
605                 /* always use fat format for now */
606                 sheader [0] = METHOD_HEADER_SECTION_FAT_FORMAT | METHOD_HEADER_SECTION_EHTABLE;
607                 num_exception *= sizeof (MonoExceptionClause);
608                 num_exception += 4; /* include the size of the header */
609                 sheader [1] = num_exception & 0xff;
610                 sheader [2] = (num_exception >> 8) & 0xff;
611                 sheader [3] = (num_exception >> 16) & 0xff;
612                 mono_image_add_stream_data (&assembly->code, sheader, 4);
613                 /* fat header, so we are already aligned */
614                 /* reverse order */
615                 for (i = mono_array_length (mb->ilgen->ex_handlers) - 1; i >= 0; --i) {
616                         ex_info = (MonoILExceptionInfo *)mono_array_addr (mb->ilgen->ex_handlers, MonoILExceptionInfo, i);
617                         if (ex_info->handlers) {
618                                 int finally_start = ex_info->start + ex_info->len;
619                                 for (j = 0; j < mono_array_length (ex_info->handlers); ++j) {
620                                         ex_block = (MonoILExceptionBlock*)mono_array_addr (ex_info->handlers, MonoILExceptionBlock, j);
621                                         clause.flags = GUINT32_TO_LE (ex_block->type);
622                                         clause.try_offset = GUINT32_TO_LE (ex_info->start);
623                                         /* need fault, too, probably */
624                                         if (ex_block->type == MONO_EXCEPTION_CLAUSE_FINALLY)
625                                                 clause.try_len = GUINT32_TO_LE (finally_start - ex_info->start);
626                                         else
627                                                 clause.try_len = GUINT32_TO_LE (ex_info->len);
628                                         clause.handler_offset = GUINT32_TO_LE (ex_block->start);
629                                         clause.handler_len = GUINT32_TO_LE (ex_block->len);
630                                         finally_start = ex_block->start + ex_block->len;
631                                         clause.token_or_filter = ex_block->extype ? mono_metadata_token_from_dor (
632                                                         mono_image_typedef_or_ref (assembly, ex_block->extype->type)): 0;
633                                         clause.token_or_filter = GUINT32_TO_LE (clause.token_or_filter);
634                                         /*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", 
635                                                         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);*/
636                                         mono_image_add_stream_data (&assembly->code, (char*)&clause, sizeof (clause));
637                                 }
638                         } else {
639                                 g_error ("No clauses for ex info block %d", i);
640                         }
641                 }
642         }
643         return assembly->text_rva + idx;
644 }
645
646 static guint32
647 find_index_in_table (MonoDynamicAssembly *assembly, int table_idx, int col, guint32 token)
648 {
649         int i;
650         MonoDynamicTable *table;
651         guint32 *values;
652         
653         table = &assembly->tables [table_idx];
654
655         g_assert (col < table->columns);
656
657         values = table->values + table->columns;
658         for (i = 1; i <= table->rows; ++i) {
659                 if (values [col] == token)
660                         return i;
661                 values += table->columns;
662         }
663         return 0;
664 }
665
666 /*
667  * idx is the table index of the object
668  * type is one of CUSTOM_ATTR_*
669  */
670 static void
671 mono_image_add_cattrs (MonoDynamicAssembly *assembly, guint32 idx, guint32 type, MonoArray *cattrs)
672 {
673         MonoDynamicTable *table;
674         MonoReflectionCustomAttr *cattr;
675         guint32 *values;
676         guint32 count, i, token;
677         char blob_size [6];
678         char *p = blob_size;
679         
680         /* it is legal to pass a NULL cattrs: we avoid to use the if in a lot of places */
681         if (!cattrs)
682                 return;
683         count = mono_array_length (cattrs);
684         table = &assembly->tables [MONO_TABLE_CUSTOMATTRIBUTE];
685         table->rows += count;
686         alloc_table (table, table->rows);
687         values = table->values + table->next_idx * MONO_CUSTOM_ATTR_SIZE;
688         idx <<= CUSTOM_ATTR_BITS;
689         idx |= type;
690         for (i = 0; i < count; ++i) {
691                 cattr = (MonoReflectionCustomAttr*)mono_array_get (cattrs, gpointer, i);
692                 values [MONO_CUSTOM_ATTR_PARENT] = idx;
693                 token = mono_image_create_token (assembly, (MonoObject*)cattr->ctor);
694                 type = mono_metadata_token_index (token);
695                 type <<= CUSTOM_ATTR_TYPE_BITS;
696                 switch (mono_metadata_token_table (token)) {
697                 case MONO_TABLE_METHOD:
698                         type |= CUSTOM_ATTR_TYPE_METHODDEF;
699                         break;
700                 case MONO_TABLE_MEMBERREF:
701                         type |= CUSTOM_ATTR_TYPE_MEMBERREF;
702                         break;
703                 default:
704                         g_warning ("got wrong token in custom attr");
705                         continue;
706                 }
707                 values [MONO_CUSTOM_ATTR_TYPE] = type;
708                 p = blob_size;
709                 mono_metadata_encode_value (mono_array_length (cattr->data), p, &p);
710                 values [MONO_CUSTOM_ATTR_VALUE] = add_to_blob_cached (assembly, blob_size, p - blob_size,
711                         mono_array_addr (cattr->data, char, 0), mono_array_length (cattr->data));
712                 values += MONO_CUSTOM_ATTR_SIZE;
713                 ++table->next_idx;
714         }
715 }
716
717 /*
718  * Fill in the MethodDef and ParamDef tables for a method.
719  * This is used for both normal methods and constructors.
720  */
721 static void
722 mono_image_basic_method (ReflectionMethodBuilder *mb, MonoDynamicAssembly *assembly)
723 {
724         MonoDynamicTable *table;
725         guint32 *values;
726         char *name;
727         guint i, count;
728
729         /* room in this table is already allocated */
730         table = &assembly->tables [MONO_TABLE_METHOD];
731         *mb->table_idx = table->next_idx ++;
732         values = table->values + *mb->table_idx * MONO_METHOD_SIZE;
733         if (mb->name) {
734                 name = mono_string_to_utf8 (mb->name);
735                 values [MONO_METHOD_NAME] = string_heap_insert (&assembly->sheap, name);
736                 g_free (name);
737         } else { /* a constructor */
738                 values [MONO_METHOD_NAME] = string_heap_insert (&assembly->sheap, mb->attrs & METHOD_ATTRIBUTE_STATIC? ".cctor": ".ctor");
739         }
740         values [MONO_METHOD_FLAGS] = mb->attrs;
741         values [MONO_METHOD_IMPLFLAGS] = mb->iattrs;
742         values [MONO_METHOD_SIGNATURE] = method_builder_encode_signature (assembly, mb);
743         values [MONO_METHOD_RVA] = method_encode_code (assembly, mb);
744         
745         table = &assembly->tables [MONO_TABLE_PARAM];
746         values [MONO_METHOD_PARAMLIST] = table->next_idx;
747
748         if (mb->pinfo) {
749                 MonoDynamicTable *mtable;
750                 guint32 *mvalues;
751                 
752                 mtable = &assembly->tables [MONO_TABLE_FIELDMARSHAL];
753                 mvalues = mtable->values + mtable->next_idx * MONO_FIELD_MARSHAL_SIZE;
754                 
755                 count = 0;
756                 for (i = 0; i < mono_array_length (mb->pinfo); ++i) {
757                         if (mono_array_get (mb->pinfo, gpointer, i))
758                                 count++;
759                 }
760                 table->rows += count;
761                 alloc_table (table, table->rows);
762                 values = table->values + table->next_idx * MONO_PARAM_SIZE;
763                 for (i = 0; i < mono_array_length (mb->pinfo); ++i) {
764                         MonoReflectionParamBuilder *pb;
765                         if ((pb = mono_array_get (mb->pinfo, MonoReflectionParamBuilder*, i))) {
766                                 values [MONO_PARAM_FLAGS] = pb->attrs;
767                                 values [MONO_PARAM_SEQUENCE] = i;
768                                 if (pb->name != NULL) {
769                                         name = mono_string_to_utf8 (pb->name);
770                                         values [MONO_PARAM_NAME] = string_heap_insert (&assembly->sheap, name);
771                                         g_free (name);
772                                 }
773                                 else
774                                         values [MONO_PARAM_NAME] = 0;
775                                 values += MONO_PARAM_SIZE;
776                                 if (pb->marshal_info) {
777                                         mtable->rows++;
778                                         alloc_table (mtable, mtable->rows);
779                                         mvalues = mtable->values + mtable->rows * MONO_FIELD_MARSHAL_SIZE;
780                                         mvalues [MONO_FIELD_MARSHAL_PARENT] = (table->next_idx << HAS_FIELD_MARSHAL_BITS) | HAS_FIELD_MARSHAL_PARAMDEF;
781                                         mvalues [MONO_FIELD_MARSHAL_NATIVE_TYPE] = encode_marshal_blob (assembly, pb->marshal_info);
782                                 }
783                                 pb->table_idx = table->next_idx++;
784                         }
785                 }
786         }
787 }
788
789 static void
790 mono_image_get_method_info (MonoReflectionMethodBuilder *mb, MonoDynamicAssembly *assembly)
791 {
792         MonoDynamicTable *table;
793         guint32 *values;
794         char *name;
795         ReflectionMethodBuilder rmb;
796
797         rmb.ilgen = mb->ilgen;
798         rmb.rtype = mb->rtype;
799         rmb.parameters = mb->parameters;
800         rmb.pinfo = mb->pinfo;
801         rmb.attrs = mb->attrs;
802         rmb.iattrs = mb->iattrs;
803         rmb.call_conv = mb->call_conv;
804         rmb.code = mb->code;
805         rmb.type = mb->type;
806         rmb.name = mb->name;
807         rmb.table_idx = &mb->table_idx;
808         rmb.init_locals = mb->init_locals;
809
810         mono_image_basic_method (&rmb, assembly);
811
812         if (mb->dll) { /* It's a P/Invoke method */
813                 guint32 moduleref;
814                 table = &assembly->tables [MONO_TABLE_IMPLMAP];
815                 table->rows ++;
816                 alloc_table (table, table->rows);
817                 values = table->values + table->rows * MONO_IMPLMAP_SIZE;
818                 values [MONO_IMPLMAP_FLAGS] = (mb->native_cc << 8) | mb->charset;
819                 values [MONO_IMPLMAP_MEMBER] = (mb->table_idx << 1) | 1; /* memberforwarded: method */
820                 name = mono_string_to_utf8 (mb->dllentry);
821                 values [MONO_IMPLMAP_NAME] = string_heap_insert (&assembly->sheap, name);
822                 g_free (name);
823                 name = mono_string_to_utf8 (mb->dll);
824                 moduleref = string_heap_insert (&assembly->sheap, name);
825                 g_free (name);
826                 if (!(values [MONO_IMPLMAP_SCOPE] = find_index_in_table (assembly, MONO_TABLE_MODULEREF, MONO_MODULEREF_NAME, moduleref))) {
827                         table = &assembly->tables [MONO_TABLE_MODULEREF];
828                         table->rows ++;
829                         alloc_table (table, table->rows);
830                         table->values [table->rows * MONO_MODULEREF_SIZE + MONO_MODULEREF_NAME] = moduleref;
831                         values [MONO_IMPLMAP_SCOPE] = table->rows;
832                 }
833         }
834         if (mb->override_method) {
835                 MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder *)mb->type;
836                 guint32 tok;
837                 table = &assembly->tables [MONO_TABLE_METHODIMPL];
838                 table->rows ++;
839                 alloc_table (table, table->rows);
840                 values = table->values + table->rows * MONO_METHODIMPL_SIZE;
841                 values [MONO_METHODIMPL_CLASS] = tb->table_idx;
842                 values [MONO_METHODIMPL_BODY] = METHODDEFORREF_METHODDEF | (mb->table_idx << METHODDEFORREF_BITS);
843                 tok = mono_image_create_token (assembly, (MonoObject*)mb->override_method);
844                 switch (mono_metadata_token_table (tok)) {
845                 case MONO_TABLE_MEMBERREF:
846                         tok = (mono_metadata_token_index (tok) << METHODDEFORREF_BITS ) | METHODDEFORREF_METHODREF;
847                         break;
848                 case MONO_TABLE_METHOD:
849                         tok = (mono_metadata_token_index (tok) << METHODDEFORREF_BITS ) | METHODDEFORREF_METHODDEF;
850                         break;
851                 default:
852                         g_assert_not_reached ();
853                 }
854                 values [MONO_METHODIMPL_DECLARATION] = tok;
855         }
856 }
857
858 static void
859 mono_image_get_ctor_info (MonoDomain *domain, MonoReflectionCtorBuilder *mb, MonoDynamicAssembly *assembly)
860 {
861         ReflectionMethodBuilder rmb;
862
863         rmb.ilgen = mb->ilgen;
864         rmb.rtype = mono_type_get_object (domain, &mono_defaults.void_class->byval_arg);
865         rmb.parameters = mb->parameters;
866         rmb.pinfo = mb->pinfo;
867         rmb.attrs = mb->attrs;
868         rmb.iattrs = mb->iattrs;
869         rmb.call_conv = mb->call_conv;
870         rmb.code = NULL;
871         rmb.type = mb->type;
872         rmb.name = NULL;
873         rmb.table_idx = &mb->table_idx;
874         rmb.init_locals = mb->init_locals;
875
876         mono_image_basic_method (&rmb, assembly);
877
878 }
879
880 static guint32
881 fieldref_encode_signature (MonoDynamicAssembly *assembly, MonoClassField *field)
882 {
883         char blob_size [64];
884         char *b = blob_size;
885         char *p;
886         char* buf;
887         guint32 idx;
888         
889         p = buf = g_malloc (64);
890         
891         mono_metadata_encode_value (0x06, p, &p);
892         /* encode custom attributes before the type */
893         encode_type (assembly, field->type, p, &p);
894         g_assert (p-buf < 64);
895         mono_metadata_encode_value (p-buf, b, &b);
896         idx = add_to_blob_cached (assembly, blob_size, b-blob_size, buf, p-buf);
897         g_free (buf);
898         return idx;
899 }
900
901 static guint32
902 field_encode_signature (MonoDynamicAssembly *assembly, MonoReflectionFieldBuilder *fb)
903 {
904         char blob_size [64];
905         char *b = blob_size;
906         char *p;
907         char* buf;
908         guint32 idx;
909         
910         p = buf = g_malloc (64);
911         
912         mono_metadata_encode_value (0x06, p, &p);
913         /* encode custom attributes before the type */
914         encode_reflection_type (assembly, fb->type, p, &p);
915         g_assert (p-buf < 64);
916         mono_metadata_encode_value (p-buf, b, &b);
917         idx = add_to_blob_cached (assembly, blob_size, b-blob_size, buf, p-buf);
918         g_free (buf);
919         return idx;
920 }
921
922 /*
923  * Copy len * nelem bytes from val to dest, swapping bytes to LE if necessary.
924  * dest may be misaligned.
925  */
926 static void
927 swap_with_size (char *dest, const char* val, int len, int nelem) {
928 #if G_BYTE_ORDER != G_LITTLE_ENDIAN
929         int elem;
930
931         for (elem = 0; elem < nelem; ++elem) {
932                 switch (len) {
933                 case 1:
934                         *dest = *val;
935                         break;
936                 case 2:
937                         dest [0] = val [1];
938                         dest [1] = val [0];
939                         break;
940                 case 4:
941                         dest [0] = val [3];
942                         dest [1] = val [2];
943                         dest [2] = val [1];
944                         dest [3] = val [0];
945                         break;
946                 case 8:
947                         dest [0] = val [7];
948                         dest [1] = val [6];
949                         dest [2] = val [5];
950                         dest [3] = val [4];
951                         dest [4] = val [3];
952                         dest [5] = val [2];
953                         dest [6] = val [1];
954                         dest [7] = val [0];
955                         break;
956                 default:
957                         g_assert_not_reached ();
958                 }
959                 dest += len;
960                 val += len;
961         }
962 #else
963         memcpy (dest, val, len * nelem);
964 #endif
965 }
966
967 static guint32
968 encode_constant (MonoDynamicAssembly *assembly, MonoObject *val, guint32 *ret_type) {
969         char blob_size [64];
970         char *b = blob_size;
971         char *p, *box_val;
972         char* buf;
973         guint32 idx, len, dummy = 0;
974         
975         p = buf = g_malloc (64);
976         if (!val) {
977                 *ret_type = MONO_TYPE_CLASS;
978                 len = 4;
979                 box_val = (char*)&dummy;
980         } else {
981                 box_val = ((char*)val) + sizeof (MonoObject);
982                 *ret_type = val->vtable->klass->byval_arg.type;
983         }
984 handle_enum:
985         switch (*ret_type) {
986         case MONO_TYPE_BOOLEAN:
987         case MONO_TYPE_U1:
988         case MONO_TYPE_I1:
989                 len = 1;
990                 break;
991         case MONO_TYPE_CHAR:
992         case MONO_TYPE_U2:
993         case MONO_TYPE_I2:
994                 len = 2;
995                 break;
996         case MONO_TYPE_U4:
997         case MONO_TYPE_I4:
998         case MONO_TYPE_R4:
999                 len = 4;
1000                 break;
1001         case MONO_TYPE_U8:
1002         case MONO_TYPE_I8:
1003         case MONO_TYPE_R8:
1004                 len = 8;
1005                 break;
1006         case MONO_TYPE_VALUETYPE:
1007                 if (val->vtable->klass->enumtype) {
1008                         *ret_type = val->vtable->klass->enum_basetype->type;
1009                         goto handle_enum;
1010                 } else
1011                         g_error ("we can't encode valuetypes");
1012         case MONO_TYPE_CLASS:
1013                 break;
1014         case MONO_TYPE_STRING: {
1015                 MonoString *str = (MonoString*)val;
1016                 /* there is no signature */
1017                 len = str->length * 2;
1018                 mono_metadata_encode_value (len, b, &b);
1019 #if G_BYTE_ORDER != G_LITTLE_ENDIAN
1020                 {
1021                         char *swapped = g_malloc (2 * mono_string_length (str));
1022                         const char *p = (const char*)mono_string_chars (str);
1023
1024                         swap_with_size (swapped, p, 2, mono_string_length (str));
1025                         idx = add_to_blob_cached (assembly, blob_size, b-blob_size, swapped, len);
1026                         g_free (swapped);
1027                 }
1028 #else
1029                 idx = add_to_blob_cached (assembly, blob_size, b-blob_size, (char*)mono_string_chars (str), len);
1030 #endif
1031
1032                 g_free (buf);
1033                 return idx;
1034         }
1035         default:
1036                 g_error ("we don't encode constant type 0x%02x yet", *ret_type);
1037         }
1038
1039         /* there is no signature */
1040         mono_metadata_encode_value (len, b, &b);
1041 #if G_BYTE_ORDER != G_LITTLE_ENDIAN
1042         idx = mono_image_add_stream_data (&assembly->blob, blob_size, b-blob_size);
1043         swap_with_size (blob_size, box_val, len, 1);
1044         mono_image_add_stream_data (&assembly->blob, blob_size, len);
1045 #else
1046         idx = add_to_blob_cached (assembly, blob_size, b-blob_size, box_val, len);
1047 #endif
1048
1049         g_free (buf);
1050         return idx;
1051 }
1052
1053 static guint32
1054 encode_marshal_blob (MonoDynamicAssembly *assembly, MonoReflectionMarshal *minfo) {
1055         char blob_size [64];
1056         char *b = blob_size;
1057         char *p, *buf;
1058         guint32 idx, len;
1059         
1060         p = buf = g_malloc (256);
1061
1062         switch (minfo->type) {
1063         case MONO_NATIVE_BYVALTSTR:
1064         case MONO_NATIVE_BYVALARRAY:
1065                 mono_metadata_encode_value (minfo->type, p, &p);
1066                 mono_metadata_encode_value (minfo->count, p, &p);
1067                 break;
1068                 /* FIXME: handle ARRAY and other unmanaged types that need extra info */
1069         default:
1070                 mono_metadata_encode_value (minfo->type, p, &p);
1071                 break;
1072         }
1073         len = p-buf;
1074         mono_metadata_encode_value (len, b, &b);
1075         idx = add_to_blob_cached (assembly, blob_size, b-blob_size, buf, len);
1076         g_free (buf);
1077         return idx;
1078 }
1079
1080 static void
1081 mono_image_get_field_info (MonoReflectionFieldBuilder *fb, MonoDynamicAssembly *assembly)
1082 {
1083         MonoDynamicTable *table;
1084         guint32 *values;
1085         char *name;
1086
1087         /* maybe this fixup should be done in the C# code */
1088         if (fb->attrs & FIELD_ATTRIBUTE_LITERAL)
1089                 fb->attrs |= FIELD_ATTRIBUTE_HAS_DEFAULT;
1090         table = &assembly->tables [MONO_TABLE_FIELD];
1091         fb->table_idx = table->next_idx ++;
1092         values = table->values + fb->table_idx * MONO_FIELD_SIZE;
1093         name = mono_string_to_utf8 (fb->name);
1094         values [MONO_FIELD_NAME] = string_heap_insert (&assembly->sheap, name);
1095         g_free (name);
1096         values [MONO_FIELD_FLAGS] = fb->attrs;
1097         values [MONO_FIELD_SIGNATURE] = field_encode_signature (assembly, fb);
1098
1099         if (fb->offset != -1) {
1100                 table = &assembly->tables [MONO_TABLE_FIELDLAYOUT];
1101                 table->rows ++;
1102                 alloc_table (table, table->rows);
1103                 values = table->values + table->rows * MONO_FIELD_LAYOUT_SIZE;
1104                 values [MONO_FIELD_LAYOUT_FIELD] = fb->table_idx;
1105                 values [MONO_FIELD_LAYOUT_OFFSET] = fb->offset;
1106         }
1107         if (fb->attrs & FIELD_ATTRIBUTE_LITERAL) {
1108                 guint32 field_type = 0;
1109                 table = &assembly->tables [MONO_TABLE_CONSTANT];
1110                 table->rows ++;
1111                 alloc_table (table, table->rows);
1112                 values = table->values + table->rows * MONO_CONSTANT_SIZE;
1113                 values [MONO_CONSTANT_PARENT] = HASCONSTANT_FIEDDEF | (fb->table_idx << HASCONSTANT_BITS);
1114                 values [MONO_CONSTANT_VALUE] = encode_constant (assembly, fb->def_value, &field_type);
1115                 values [MONO_CONSTANT_TYPE] = field_type;
1116                 values [MONO_CONSTANT_PADDING] = 0;
1117         }
1118         if (fb->rva_data) {
1119                 guint32 rva_idx;
1120                 table = &assembly->tables [MONO_TABLE_FIELDRVA];
1121                 table->rows ++;
1122                 alloc_table (table, table->rows);
1123                 values = table->values + table->rows * MONO_FIELD_RVA_SIZE;
1124                 values [MONO_FIELD_RVA_FIELD] = fb->table_idx;
1125                 /*
1126                  * We store it in the code section because it's simpler for now.
1127                  */
1128                 rva_idx = mono_image_add_stream_data (&assembly->code, mono_array_addr (fb->rva_data, char, 0), mono_array_length (fb->rva_data));
1129                 values [MONO_FIELD_RVA_RVA] = rva_idx + assembly->text_rva;
1130         }
1131         if (fb->marshal_info) {
1132                 table = &assembly->tables [MONO_TABLE_FIELDMARSHAL];
1133                 table->rows ++;
1134                 alloc_table (table, table->rows);
1135                 values = table->values + table->rows * MONO_FIELD_MARSHAL_SIZE;
1136                 values [MONO_FIELD_MARSHAL_PARENT] = (fb->table_idx << HAS_FIELD_MARSHAL_BITS) | HAS_FIELD_MARSHAL_FIELDSREF;
1137                 values [MONO_FIELD_MARSHAL_NATIVE_TYPE] = encode_marshal_blob (assembly, fb->marshal_info);
1138         }
1139 }
1140
1141 static guint32
1142 property_encode_signature (MonoDynamicAssembly *assembly, MonoReflectionPropertyBuilder *fb)
1143 {
1144         char *buf, *p;
1145         char blob_size [6];
1146         char *b = blob_size;
1147         guint32 nparams = 0;
1148         MonoReflectionMethodBuilder *mb = fb->get_method;
1149         MonoReflectionMethodBuilder *smb = fb->set_method;
1150         guint32 idx, i, size;
1151
1152         if (mb && mb->parameters)
1153                 nparams = mono_array_length (mb->parameters);
1154         if (!mb && smb && smb->parameters)
1155                 nparams = mono_array_length (smb->parameters) - 1;
1156         size = 24 + nparams * 10;
1157         buf = p = g_malloc (size);
1158         *p = 0x08;
1159         p++;
1160         mono_metadata_encode_value (nparams, p, &p);
1161         if (mb) {
1162                 encode_reflection_type (assembly, mb->rtype, p, &p);
1163                 for (i = 0; i < nparams; ++i) {
1164                         MonoReflectionType *pt = mono_array_get (mb->parameters, MonoReflectionType*, i);
1165                         encode_reflection_type (assembly, pt, p, &p);
1166                 }
1167         } else {
1168                 /* the property type is the last param */
1169                 encode_reflection_type (assembly, mono_array_get (smb->parameters, MonoReflectionType*, nparams), p, &p);
1170                 for (i = 0; i < nparams; ++i) {
1171                         MonoReflectionType *pt = mono_array_get (smb->parameters, MonoReflectionType*, i);
1172                         encode_reflection_type (assembly, pt, p, &p);
1173                 }
1174         }
1175         /* store length */
1176         g_assert (p - buf < size);
1177         mono_metadata_encode_value (p-buf, b, &b);
1178         idx = add_to_blob_cached (assembly, blob_size, b-blob_size, buf, p-buf);
1179         g_free (buf);
1180         return idx;
1181 }
1182
1183 static void
1184 mono_image_get_property_info (MonoReflectionPropertyBuilder *pb, MonoDynamicAssembly *assembly)
1185 {
1186         MonoDynamicTable *table;
1187         guint32 *values;
1188         char *name;
1189         guint num_methods = 0;
1190         guint32 semaidx;
1191
1192         /* 
1193          * we need to set things in the following tables:
1194          * PROPERTYMAP (info already filled in _get_type_info ())
1195          * PROPERTY    (rows already preallocated in _get_type_info ())
1196          * METHOD      (method info already done with the generic method code)
1197          * METHODSEMANTICS
1198          */
1199         table = &assembly->tables [MONO_TABLE_PROPERTY];
1200         pb->table_idx = table->next_idx ++;
1201         values = table->values + pb->table_idx * MONO_PROPERTY_SIZE;
1202         name = mono_string_to_utf8 (pb->name);
1203         values [MONO_PROPERTY_NAME] = string_heap_insert (&assembly->sheap, name);
1204         g_free (name);
1205         values [MONO_PROPERTY_FLAGS] = pb->attrs;
1206         values [MONO_PROPERTY_TYPE] = property_encode_signature (assembly, pb);
1207
1208         /* FIXME: we still don't handle 'other' methods */
1209         if (pb->get_method) num_methods ++;
1210         if (pb->set_method) num_methods ++;
1211
1212         table = &assembly->tables [MONO_TABLE_METHODSEMANTICS];
1213         table->rows += num_methods;
1214         alloc_table (table, table->rows);
1215
1216         if (pb->get_method) {
1217                 semaidx = table->next_idx ++;
1218                 values = table->values + semaidx * MONO_METHOD_SEMA_SIZE;
1219                 values [MONO_METHOD_SEMA_SEMANTICS] = METHOD_SEMANTIC_GETTER;
1220                 values [MONO_METHOD_SEMA_METHOD] = pb->get_method->table_idx;
1221                 values [MONO_METHOD_SEMA_ASSOCIATION] = (pb->table_idx << HAS_SEMANTICS_BITS) | HAS_SEMANTICS_PROPERTY;
1222         }
1223         if (pb->set_method) {
1224                 semaidx = table->next_idx ++;
1225                 values = table->values + semaidx * MONO_METHOD_SEMA_SIZE;
1226                 values [MONO_METHOD_SEMA_SEMANTICS] = METHOD_SEMANTIC_SETTER;
1227                 values [MONO_METHOD_SEMA_METHOD] = pb->set_method->table_idx;
1228                 values [MONO_METHOD_SEMA_ASSOCIATION] = (pb->table_idx << HAS_SEMANTICS_BITS) | HAS_SEMANTICS_PROPERTY;
1229         }
1230 }
1231
1232 static void
1233 mono_image_get_event_info (MonoReflectionEventBuilder *eb, MonoDynamicAssembly *assembly)
1234 {
1235         MonoDynamicTable *table;
1236         guint32 *values;
1237         char *name;
1238         guint num_methods = 0;
1239         guint32 semaidx;
1240
1241         /* 
1242          * we need to set things in the following tables:
1243          * EVENTMAP (info already filled in _get_type_info ())
1244          * EVENT    (rows already preallocated in _get_type_info ())
1245          * METHOD      (method info already done with the generic method code)
1246          * METHODSEMANTICS
1247          */
1248         table = &assembly->tables [MONO_TABLE_EVENT];
1249         eb->table_idx = table->next_idx ++;
1250         values = table->values + eb->table_idx * MONO_EVENT_SIZE;
1251         name = mono_string_to_utf8 (eb->name);
1252         values [MONO_EVENT_NAME] = string_heap_insert (&assembly->sheap, name);
1253         g_free (name);
1254         values [MONO_EVENT_FLAGS] = eb->attrs;
1255         values [MONO_EVENT_TYPE] = mono_image_typedef_or_ref (assembly, eb->type->type);
1256
1257         /*
1258          * FIXME: we still don't handle 'other' methods 
1259          */
1260         if (eb->add_method) num_methods ++;
1261         if (eb->remove_method) num_methods ++;
1262         if (eb->raise_method) num_methods ++;
1263
1264         table = &assembly->tables [MONO_TABLE_METHODSEMANTICS];
1265         table->rows += num_methods;
1266         alloc_table (table, table->rows);
1267
1268         if (eb->add_method) {
1269                 semaidx = table->next_idx ++;
1270                 values = table->values + semaidx * MONO_METHOD_SEMA_SIZE;
1271                 values [MONO_METHOD_SEMA_SEMANTICS] = METHOD_SEMANTIC_ADD_ON;
1272                 values [MONO_METHOD_SEMA_METHOD] = eb->add_method->table_idx;
1273                 values [MONO_METHOD_SEMA_ASSOCIATION] = (eb->table_idx << HAS_SEMANTICS_BITS) | HAS_SEMANTICS_EVENT;
1274         }
1275         if (eb->remove_method) {
1276                 semaidx = table->next_idx ++;
1277                 values = table->values + semaidx * MONO_METHOD_SEMA_SIZE;
1278                 values [MONO_METHOD_SEMA_SEMANTICS] = METHOD_SEMANTIC_REMOVE_ON;
1279                 values [MONO_METHOD_SEMA_METHOD] = eb->remove_method->table_idx;
1280                 values [MONO_METHOD_SEMA_ASSOCIATION] = (eb->table_idx << HAS_SEMANTICS_BITS) | HAS_SEMANTICS_EVENT;
1281         }
1282         if (eb->raise_method) {
1283                 semaidx = table->next_idx ++;
1284                 values = table->values + semaidx * MONO_METHOD_SEMA_SIZE;
1285                 values [MONO_METHOD_SEMA_SEMANTICS] = METHOD_SEMANTIC_FIRE;
1286                 values [MONO_METHOD_SEMA_METHOD] = eb->raise_method->table_idx;
1287                 values [MONO_METHOD_SEMA_ASSOCIATION] = (eb->table_idx << HAS_SEMANTICS_BITS) | HAS_SEMANTICS_EVENT;
1288         }
1289 }
1290
1291 static guint32
1292 resolution_scope_from_image (MonoDynamicAssembly *assembly, MonoImage *image)
1293 {
1294         MonoDynamicTable *table;
1295         guint32 token;
1296         guint32 *values;
1297         guint32 cols [MONO_ASSEMBLY_SIZE];
1298         const char *pubkey;
1299         guint32 publen;
1300
1301         if ((token = GPOINTER_TO_UINT (g_hash_table_lookup (assembly->handleref, image))))
1302                 return token;
1303
1304         if (image->assembly->dynamic)
1305                 /* FIXME: */
1306                 memset (cols, 0, sizeof (cols));
1307         else
1308                 mono_metadata_decode_row (&image->tables [MONO_TABLE_ASSEMBLY], 0, cols, MONO_ASSEMBLY_SIZE);
1309
1310         table = &assembly->tables [MONO_TABLE_ASSEMBLYREF];
1311         token = table->next_idx ++;
1312         table->rows ++;
1313         alloc_table (table, table->rows);
1314         values = table->values + token * MONO_ASSEMBLYREF_SIZE;
1315         if (strcmp ("corlib", image->assembly_name) == 0)
1316                 values [MONO_ASSEMBLYREF_NAME] = string_heap_insert (&assembly->sheap, "mscorlib");
1317         else
1318                 values [MONO_ASSEMBLYREF_NAME] = string_heap_insert (&assembly->sheap, image->assembly_name);
1319         values [MONO_ASSEMBLYREF_MAJOR_VERSION] = cols [MONO_ASSEMBLY_MAJOR_VERSION];
1320         values [MONO_ASSEMBLYREF_MINOR_VERSION] = cols [MONO_ASSEMBLY_MINOR_VERSION];
1321         values [MONO_ASSEMBLYREF_BUILD_NUMBER] = cols [MONO_ASSEMBLY_BUILD_NUMBER];
1322         values [MONO_ASSEMBLYREF_REV_NUMBER] = cols [MONO_ASSEMBLY_REV_NUMBER];
1323         values [MONO_ASSEMBLYREF_FLAGS] = 0;
1324         values [MONO_ASSEMBLYREF_CULTURE] = 0;
1325         values [MONO_ASSEMBLYREF_HASH_VALUE] = 0;
1326
1327         if ((pubkey = mono_image_get_public_key (image, &publen))) {
1328                 guchar pubtoken [9];
1329                 pubtoken [0] = 8;
1330                 mono_digest_get_public_token (pubtoken + 1, pubkey, publen);
1331                 values [MONO_ASSEMBLYREF_PUBLIC_KEY] = mono_image_add_stream_data (&assembly->blob, pubtoken, 9);
1332         } else {
1333                 /* 
1334                  * We add the pubtoken from ms, so that the ms runtime can handle our binaries.
1335                  * This is currently only a problem with references to System.Xml (see bug#27706),
1336                  * but there may be other cases that makes this necessary. Note, we need to set 
1337                  * the version as well. When/if we sign our assemblies, we'd need to get our pubtoken 
1338                  * recognized by ms, yuck!
1339                  * FIXME: need to add more assembly names, as needed.
1340                  */
1341                 if (strcmp (image->assembly_name, "corlib") == 0 ||
1342                                 strcmp (image->assembly_name, "mscorlib") == 0 ||
1343                                 strcmp (image->assembly_name, "System") == 0 ||
1344                                 strcmp (image->assembly_name, "System.Xml") == 0 ||
1345                                 strcmp (image->assembly_name, "System.Data") == 0 ||
1346                                 strcmp (image->assembly_name, "System.Drawing") == 0 ||
1347                                 strcmp (image->assembly_name, "System.Web") == 0) {
1348                         static const guchar ptoken [9] = {8, '\xB7', '\x7A', '\x5C', '\x56', '\x19', '\x34', '\xE0', '\x89'};
1349                         values [MONO_ASSEMBLYREF_PUBLIC_KEY] = mono_image_add_stream_data (&assembly->blob, ptoken, 9);
1350                         values [MONO_ASSEMBLYREF_MAJOR_VERSION] = 1;
1351                         values [MONO_ASSEMBLYREF_BUILD_NUMBER] = 3300;
1352                 } else {
1353                         values [MONO_ASSEMBLYREF_PUBLIC_KEY] = 0;
1354                 }
1355         }
1356         token <<= RESOLTION_SCOPE_BITS;
1357         token |= RESOLTION_SCOPE_ASSEMBLYREF;
1358         g_hash_table_insert (assembly->handleref, image, GUINT_TO_POINTER (token));
1359         mono_g_hash_table_insert (assembly->tokens, GUINT_TO_POINTER (token), image);
1360         return token;
1361 }
1362
1363 static guint32
1364 create_typespec (MonoDynamicAssembly *assembly, MonoType *type)
1365 {
1366         MonoDynamicTable *table;
1367         guint32 *values;
1368         guint32 token;
1369         char sig [128];
1370         char *p = sig;
1371         char blob_size [6];
1372         char *b = blob_size;
1373
1374         switch (type->type) {
1375         case MONO_TYPE_FNPTR:
1376         case MONO_TYPE_PTR:
1377         case MONO_TYPE_SZARRAY:
1378         case MONO_TYPE_ARRAY:
1379                 encode_type (assembly, type, p, &p);
1380                 break;
1381         default:
1382                 return 0;
1383         }
1384         
1385         g_assert (p-sig < 128);
1386         mono_metadata_encode_value (p-sig, b, &b);
1387         token = add_to_blob_cached (assembly, blob_size, b-blob_size, sig, p-sig);
1388
1389         table = &assembly->tables [MONO_TABLE_TYPESPEC];
1390         alloc_table (table, table->rows + 1);
1391         values = table->values + table->next_idx * MONO_TYPESPEC_SIZE;
1392         values [MONO_TYPESPEC_SIGNATURE] = token;
1393
1394         token = TYPEDEFORREF_TYPESPEC | (table->next_idx << TYPEDEFORREF_BITS);
1395         g_hash_table_insert (assembly->typeref, type, GUINT_TO_POINTER(token));
1396         table->next_idx ++;
1397         return token;
1398 }
1399
1400 /*
1401  * Despite the name, we handle also TypeSpec (with the above helper).
1402  */
1403 static guint32
1404 mono_image_typedef_or_ref_aux (MonoDynamicAssembly *assembly, MonoType *type,
1405                                                            gboolean force_ref)
1406 {
1407         MonoDynamicTable *table;
1408         guint32 *values;
1409         guint32 token, scope, enclosing;
1410         MonoClass *klass;
1411
1412 #define COMPILE_CORLIB 0
1413 #if COMPILE_CORLIB
1414         /* nasty hack, need to find the proper solution */
1415         if (type->type == MONO_TYPE_OBJECT)
1416                 return TYPEDEFORREF_TYPEDEF | (2 << TYPEDEFORREF_BITS);
1417 #endif
1418         token = GPOINTER_TO_UINT (g_hash_table_lookup (assembly->typeref, type));
1419         if (token)
1420                 return token;
1421         token = create_typespec (assembly, type);
1422         if (token)
1423                 return token;
1424         klass = my_mono_class_from_mono_type (type);
1425         if (!klass)
1426                 klass = mono_class_from_mono_type (type);
1427         /*
1428          * If it's in the same module:
1429          */
1430         if (!force_ref && (klass->image == assembly->assembly.image)) {
1431                 MonoReflectionTypeBuilder *tb = klass->reflection_info;
1432                 token = TYPEDEFORREF_TYPEDEF | (tb->table_idx << TYPEDEFORREF_BITS);
1433                 mono_g_hash_table_insert (assembly->tokens, GUINT_TO_POINTER (token), klass);
1434                 return token;
1435         }
1436
1437         if (klass->nested_in) {
1438                 enclosing = mono_image_typedef_or_ref (assembly, &klass->nested_in->byval_arg);
1439                 /* get the typeref idx of the enclosing type */
1440                 enclosing >>= TYPEDEFORREF_BITS;
1441                 scope = (enclosing << RESOLTION_SCOPE_BITS) | RESOLTION_SCOPE_TYPEREF;
1442         } else {
1443                 scope = resolution_scope_from_image (assembly, klass->image);
1444         }
1445         table = &assembly->tables [MONO_TABLE_TYPEREF];
1446         alloc_table (table, table->rows + 1);
1447         values = table->values + table->next_idx * MONO_TYPEREF_SIZE;
1448         values [MONO_TYPEREF_SCOPE] = scope;
1449         values [MONO_TYPEREF_NAME] = string_heap_insert (&assembly->sheap, klass->name);
1450         values [MONO_TYPEREF_NAMESPACE] = string_heap_insert (&assembly->sheap, klass->name_space);
1451         token = TYPEDEFORREF_TYPEREF | (table->next_idx << TYPEDEFORREF_BITS); /* typeref */
1452         g_hash_table_insert (assembly->typeref, type, GUINT_TO_POINTER(token));
1453         table->next_idx ++;
1454         mono_g_hash_table_insert (assembly->tokens, GUINT_TO_POINTER (token), klass);
1455         return token;
1456 }
1457
1458 static guint32
1459 mono_image_typedef_or_ref (MonoDynamicAssembly *assembly, MonoType *type)
1460 {
1461         return mono_image_typedef_or_ref_aux (assembly, type, FALSE);
1462 }
1463
1464 /*
1465  * Insert a memberef row into the metadata: the token that point to the memberref
1466  * is returned. Caching is done in the caller (mono_image_get_methodref_token() or
1467  * mono_image_get_fieldref_token()).
1468  * The sig param is an index to an already built signature.
1469  */
1470 static guint32
1471 mono_image_get_memberref_token (MonoDynamicAssembly *assembly, MonoType *type, const char *name, guint32 sig)
1472 {
1473         MonoDynamicTable *table;
1474         guint32 *values;
1475         guint32 token, pclass;
1476         guint32 parent;
1477
1478         parent = mono_image_typedef_or_ref_aux (assembly, type, TRUE);
1479         switch (parent & TYPEDEFORREF_MASK) {
1480         case TYPEDEFORREF_TYPEREF:
1481                 pclass = MEMBERREF_PARENT_TYPEREF;
1482                 break;
1483         case TYPEDEFORREF_TYPESPEC:
1484                 pclass = MEMBERREF_PARENT_TYPESPEC;
1485                 break;
1486         case TYPEDEFORREF_TYPEDEF:
1487                 /* should never get here */
1488         default:
1489                 g_warning ("unknown typeref or def token 0x%08x for %s", parent, name);
1490                 return 0;
1491         }
1492         /* extract the index */
1493         parent >>= TYPEDEFORREF_BITS;
1494
1495         table = &assembly->tables [MONO_TABLE_MEMBERREF];
1496         alloc_table (table, table->rows + 1);
1497         values = table->values + table->next_idx * MONO_MEMBERREF_SIZE;
1498         values [MONO_MEMBERREF_CLASS] = pclass | (parent << MEMBERREF_PARENT_BITS);
1499         values [MONO_MEMBERREF_NAME] = string_heap_insert (&assembly->sheap, name);
1500         values [MONO_MEMBERREF_SIGNATURE] = sig;
1501         token = MONO_TOKEN_MEMBER_REF | table->next_idx;
1502         table->next_idx ++;
1503
1504         return token;
1505 }
1506
1507 static guint32
1508 mono_image_get_methodref_token (MonoDynamicAssembly *assembly, MonoMethod *method)
1509 {
1510         guint32 token;
1511         
1512         token = GPOINTER_TO_UINT (g_hash_table_lookup (assembly->handleref, method));
1513         if (token)
1514                 return token;
1515         token = mono_image_get_memberref_token (assembly, &method->klass->byval_arg,
1516                 method->name,  method_encode_signature (assembly, method->signature));
1517         g_hash_table_insert (assembly->handleref, method, GUINT_TO_POINTER(token));
1518         return token;
1519 }
1520
1521 static guint32
1522 mono_image_get_fieldref_token (MonoDynamicAssembly *assembly, MonoClassField *field, MonoClass *klass)
1523 {
1524         guint32 token;
1525         
1526         token = GPOINTER_TO_UINT (g_hash_table_lookup (assembly->handleref, field));
1527         if (token)
1528                 return token;
1529         field->parent = klass;
1530         token = mono_image_get_memberref_token (assembly, &klass->byval_arg, 
1531                 field->name,  fieldref_encode_signature (assembly, field));
1532         g_hash_table_insert (assembly->handleref, field, GUINT_TO_POINTER(token));
1533         return token;
1534 }
1535
1536 static guint32
1537 mono_reflection_encode_sighelper (MonoDynamicAssembly *assembly, MonoReflectionSigHelper *helper)
1538 {
1539         char *buf;
1540         char *p;
1541         guint32 nargs;
1542         guint32 size;
1543         guint32 i, idx;
1544         char blob_size [6];
1545         char *b = blob_size;
1546
1547         /* FIXME: */
1548         g_assert (helper->type == 2);
1549
1550         if (helper->arguments)
1551                 nargs = mono_array_length (helper->arguments);
1552         else
1553                 nargs = 0;
1554
1555         size = 10 + (nargs * 10);
1556         
1557         p = buf = g_malloc (size);
1558
1559         /* Encode calling convention */
1560         /* Change Any to Standard */
1561         if ((helper->call_conv & 0x03) == 0x03)
1562                 helper->call_conv = 0x01;
1563         /* explicit_this implies has_this */
1564         if (helper->call_conv & 0x40)
1565                 helper->call_conv &= 0x20;
1566
1567         if (helper->call_conv == 0) /* Unmanaged */
1568                 *p = helper->unmanaged_call_conv - 1;
1569         else {
1570                 /* Managed */
1571                 *p = helper->call_conv & 0x60; /* has_this + explicit_this */
1572                 if (helper->call_conv & 0x02) /* varargs */
1573                         *p += 0x05;
1574         }
1575
1576         p++;
1577         mono_metadata_encode_value (nargs, p, &p);
1578         encode_reflection_type (assembly, helper->return_type, p, &p);
1579         for (i = 0; i < nargs; ++i) {
1580                 MonoReflectionType *pt = mono_array_get (helper->arguments, MonoReflectionType*, i);
1581                 encode_reflection_type (assembly, pt, p, &p);
1582         }
1583         /* store length */
1584         g_assert (p - buf < size);
1585         mono_metadata_encode_value (p-buf, b, &b);
1586         idx = add_to_blob_cached (assembly, blob_size, b-blob_size, buf, p-buf);
1587         g_free (buf);
1588
1589         return idx;
1590 }
1591         
1592 static guint32 
1593 mono_image_get_sighelper_token (MonoDynamicAssembly *assembly, MonoReflectionSigHelper *helper)
1594 {
1595         guint32 idx;
1596         MonoDynamicTable *table;
1597         guint32 *values;
1598
1599         table = &assembly->tables [MONO_TABLE_STANDALONESIG];
1600         idx = table->next_idx ++;
1601         table->rows ++;
1602         alloc_table (table, table->rows);
1603         values = table->values + idx * MONO_STAND_ALONE_SIGNATURE_SIZE;
1604
1605         values [MONO_STAND_ALONE_SIGNATURE] =
1606                 mono_reflection_encode_sighelper (assembly, helper);
1607
1608         return idx;
1609 }
1610
1611 static int
1612 reflection_cc_to_file (int call_conv) {
1613         switch (call_conv & 0x3) {
1614         case 0:
1615         case 1: return MONO_CALL_DEFAULT;
1616         case 2: return MONO_CALL_VARARG;
1617         default:
1618                 g_assert_not_reached ();
1619         }
1620         return 0;
1621 }
1622
1623 typedef struct {
1624         MonoType *parent;
1625         MonoMethodSignature *sig;
1626         char *name;
1627         guint32 token;
1628 } ArrayMethod;
1629
1630 static guint32
1631 mono_image_get_array_token (MonoDynamicAssembly *assembly, MonoReflectionArrayMethod *m)
1632 {
1633         guint32 nparams, i;
1634         GList *tmp;
1635         char *name;
1636         MonoMethodSignature *sig;
1637         ArrayMethod *am;
1638         
1639         name = mono_string_to_utf8 (m->name);
1640         nparams = mono_array_length (m->parameters);
1641         sig = g_malloc0 (sizeof (MonoMethodSignature) + sizeof (MonoType*) * nparams);
1642         sig->hasthis = 1;
1643         sig->call_convention = reflection_cc_to_file (m->call_conv);
1644         sig->param_count = nparams;
1645         sig->ret = m->ret? m->ret->type: &mono_defaults.void_class->byval_arg;
1646         for (i = 0; i < nparams; ++i) {
1647                 MonoReflectionType *t = mono_array_get (m->parameters, gpointer, i);
1648                 sig->params [i] = t->type;
1649         }
1650
1651         for (tmp = assembly->array_methods; tmp; tmp = tmp->next) {
1652                 am = tmp->data;
1653                 if (strcmp (name, am->name) == 0 && 
1654                                 mono_metadata_type_equal (am->parent, m->parent->type) &&
1655                                 mono_metadata_signature_equal (am->sig, sig)) {
1656                         g_free (name);
1657                         g_free (sig);
1658                         return am->token;
1659                 }
1660         }
1661         am = g_new0 (ArrayMethod, 1);
1662         am->name = name;
1663         am->sig = sig;
1664         am->parent = m->parent->type;
1665         am->token = mono_image_get_memberref_token (assembly, am->parent,
1666                 name,  method_encode_signature (assembly, sig));
1667         assembly->array_methods = g_list_prepend (assembly->array_methods, am);
1668         m->table_idx = am->token & 0xffffff;
1669         return am->token;
1670 }
1671
1672 /*
1673  * Insert into the metadata tables all the info about the TypeBuilder tb.
1674  * Data in the tables is inserted in a predefined order, since some tables need to be sorted.
1675  */
1676 static void
1677 mono_image_get_type_info (MonoDomain *domain, MonoReflectionTypeBuilder *tb, MonoDynamicAssembly *assembly)
1678 {
1679         MonoDynamicTable *table;
1680         guint *values;
1681         int i, is_object = 0, is_system = 0;
1682         char *n;
1683
1684         table = &assembly->tables [MONO_TABLE_TYPEDEF];
1685         values = table->values + tb->table_idx * MONO_TYPEDEF_SIZE;
1686         values [MONO_TYPEDEF_FLAGS] = tb->attrs;
1687         n = mono_string_to_utf8 (tb->name);
1688         if (strcmp (n, "Object") == 0)
1689                 is_object++;
1690         values [MONO_TYPEDEF_NAME] = string_heap_insert (&assembly->sheap, n);
1691         g_free (n);
1692         n = mono_string_to_utf8 (tb->nspace);
1693         if (strcmp (n, "System") == 0)
1694                 is_system++;
1695         values [MONO_TYPEDEF_NAMESPACE] = string_heap_insert (&assembly->sheap, n);
1696         g_free (n);
1697         if (tb->parent && !(is_system && is_object) && 
1698                 !(tb->attrs & TYPE_ATTRIBUTE_INTERFACE)) { /* interfaces don't have a parent */
1699                 values [MONO_TYPEDEF_EXTENDS] = mono_image_typedef_or_ref (assembly, tb->parent->type);
1700         } else
1701                 values [MONO_TYPEDEF_EXTENDS] = 0;
1702         values [MONO_TYPEDEF_FIELD_LIST] = assembly->tables [MONO_TABLE_FIELD].next_idx;
1703         values [MONO_TYPEDEF_METHOD_LIST] = assembly->tables [MONO_TABLE_METHOD].next_idx;
1704
1705         /*
1706          * if we have explicitlayout or sequentiallayouts, output data in the
1707          * ClassLayout table.
1708          */
1709         if (((tb->attrs & TYPE_ATTRIBUTE_LAYOUT_MASK) != TYPE_ATTRIBUTE_AUTO_LAYOUT) && (tb->class_size != -1)) {
1710                 table = &assembly->tables [MONO_TABLE_CLASSLAYOUT];
1711                 table->rows++;
1712                 alloc_table (table, table->rows);
1713                 values = table->values + table->rows * MONO_CLASS_LAYOUT_SIZE;
1714                 values [MONO_CLASS_LAYOUT_PARENT] = tb->table_idx;
1715                 values [MONO_CLASS_LAYOUT_CLASS_SIZE] = tb->class_size;
1716                 values [MONO_CLASS_LAYOUT_PACKING_SIZE] = tb->packing_size;
1717         }
1718
1719         /* handle interfaces */
1720         if (tb->interfaces) {
1721                 table = &assembly->tables [MONO_TABLE_INTERFACEIMPL];
1722                 i = table->rows;
1723                 table->rows += mono_array_length (tb->interfaces);
1724                 alloc_table (table, table->rows);
1725                 values = table->values + (i + 1) * MONO_INTERFACEIMPL_SIZE;
1726                 for (i = 0; i < mono_array_length (tb->interfaces); ++i) {
1727                         MonoReflectionType* iface = (MonoReflectionType*) mono_array_get (tb->interfaces, gpointer, i);
1728                         values [MONO_INTERFACEIMPL_CLASS] = tb->table_idx;
1729                         values [MONO_INTERFACEIMPL_INTERFACE] = mono_image_typedef_or_ref (assembly, iface->type);
1730                         values += MONO_INTERFACEIMPL_SIZE;
1731                 }
1732         }
1733
1734         /* handle fields */
1735         if (tb->fields) {
1736                 table = &assembly->tables [MONO_TABLE_FIELD];
1737                 table->rows += mono_array_length (tb->fields);
1738                 alloc_table (table, table->rows);
1739                 for (i = 0; i < mono_array_length (tb->fields); ++i)
1740                         mono_image_get_field_info (
1741                                 mono_array_get (tb->fields, MonoReflectionFieldBuilder*, i), assembly);
1742         }
1743
1744         /* handle constructors */
1745         if (tb->ctors) {
1746                 table = &assembly->tables [MONO_TABLE_METHOD];
1747                 table->rows += mono_array_length (tb->ctors);
1748                 alloc_table (table, table->rows);
1749                 for (i = 0; i < mono_array_length (tb->ctors); ++i)
1750                         mono_image_get_ctor_info (domain,
1751                                 mono_array_get (tb->ctors, MonoReflectionCtorBuilder*, i), assembly);
1752         }
1753
1754         /* handle methods */
1755         if (tb->methods) {
1756                 table = &assembly->tables [MONO_TABLE_METHOD];
1757                 table->rows += mono_array_length (tb->methods);
1758                 alloc_table (table, table->rows);
1759                 for (i = 0; i < mono_array_length (tb->methods); ++i)
1760                         mono_image_get_method_info (
1761                                 mono_array_get (tb->methods, MonoReflectionMethodBuilder*, i), assembly);
1762         }
1763
1764         /* Do the same with properties etc.. */
1765         if (tb->events && mono_array_length (tb->events)) {
1766                 table = &assembly->tables [MONO_TABLE_EVENT];
1767                 table->rows += mono_array_length (tb->events);
1768                 alloc_table (table, table->rows);
1769                 table = &assembly->tables [MONO_TABLE_EVENTMAP];
1770                 table->rows ++;
1771                 alloc_table (table, table->rows);
1772                 values = table->values + table->rows * MONO_EVENT_MAP_SIZE;
1773                 values [MONO_EVENT_MAP_PARENT] = tb->table_idx;
1774                 values [MONO_EVENT_MAP_EVENTLIST] = assembly->tables [MONO_TABLE_EVENT].next_idx;
1775                 for (i = 0; i < mono_array_length (tb->events); ++i)
1776                         mono_image_get_event_info (
1777                                 mono_array_get (tb->events, MonoReflectionEventBuilder*, i), assembly);
1778         }
1779         if (tb->properties && mono_array_length (tb->properties)) {
1780                 table = &assembly->tables [MONO_TABLE_PROPERTY];
1781                 table->rows += mono_array_length (tb->properties);
1782                 alloc_table (table, table->rows);
1783                 table = &assembly->tables [MONO_TABLE_PROPERTYMAP];
1784                 table->rows ++;
1785                 alloc_table (table, table->rows);
1786                 values = table->values + table->rows * MONO_PROPERTY_MAP_SIZE;
1787                 values [MONO_PROPERTY_MAP_PARENT] = tb->table_idx;
1788                 values [MONO_PROPERTY_MAP_PROPERTY_LIST] = assembly->tables [MONO_TABLE_PROPERTY].next_idx;
1789                 for (i = 0; i < mono_array_length (tb->properties); ++i)
1790                         mono_image_get_property_info (
1791                                 mono_array_get (tb->properties, MonoReflectionPropertyBuilder*, i), assembly);
1792         }
1793         if (tb->subtypes) {
1794                 MonoDynamicTable *ntable;
1795                 
1796                 table = &assembly->tables [MONO_TABLE_TYPEDEF];
1797                 table->rows += mono_array_length (tb->subtypes);
1798                 alloc_table (table, table->rows);
1799
1800                 ntable = &assembly->tables [MONO_TABLE_NESTEDCLASS];
1801                 ntable->rows += mono_array_length (tb->subtypes);
1802                 alloc_table (ntable, ntable->rows);
1803                 values = ntable->values + ntable->next_idx * MONO_NESTED_CLASS_SIZE;
1804
1805                 for (i = 0; i < mono_array_length (tb->subtypes); ++i) {
1806                         MonoReflectionTypeBuilder *subtype = mono_array_get (tb->subtypes, MonoReflectionTypeBuilder*, i);
1807
1808                         values [MONO_NESTED_CLASS_NESTED] = subtype->table_idx;
1809                         values [MONO_NESTED_CLASS_ENCLOSING] = tb->table_idx;
1810                         /*g_print ("nesting %s (%d) in %s (%d) (rows %d/%d)\n",
1811                                 mono_string_to_utf8 (subtype->name), subtype->table_idx,
1812                                 mono_string_to_utf8 (tb->name), tb->table_idx,
1813                                 ntable->next_idx, ntable->rows);*/
1814                         values += MONO_NESTED_CLASS_SIZE;
1815                         ntable->next_idx++;
1816                 }
1817                 for (i = 0; i < mono_array_length (tb->subtypes); ++i) {
1818                         MonoReflectionTypeBuilder *subtype = mono_array_get (tb->subtypes, MonoReflectionTypeBuilder*, i);
1819
1820                         mono_image_get_type_info (domain, subtype, assembly);
1821                 }
1822         }
1823 }
1824
1825 static void
1826 assign_type_idx (MonoReflectionTypeBuilder *type, MonoDynamicTable *table)
1827 {
1828         int j;
1829
1830         type->table_idx = table->next_idx ++;
1831         if (!type->subtypes)
1832                 return;
1833         for (j = 0; j < mono_array_length (type->subtypes); ++j) {
1834                 MonoReflectionTypeBuilder *subtype = mono_array_get (type->subtypes, MonoReflectionTypeBuilder*, j);
1835                 assign_type_idx (subtype, table);
1836         }
1837 }
1838
1839 static void
1840 params_add_cattrs (MonoDynamicAssembly *assembly, MonoArray *pinfo) {
1841         int i;
1842
1843         if (!pinfo)
1844                 return;
1845         for (i = 0; i < mono_array_length (pinfo); ++i) {
1846                 MonoReflectionParamBuilder *pb;
1847                 pb = mono_array_get (pinfo, MonoReflectionParamBuilder *, i);
1848                 if (!pb)
1849                         continue;
1850                 mono_image_add_cattrs (assembly, pb->table_idx, CUSTOM_ATTR_PARAMDEF, pb->cattrs);
1851         }
1852 }
1853
1854 static void
1855 type_add_cattrs (MonoDynamicAssembly *assembly, MonoReflectionTypeBuilder *tb) {
1856         int i;
1857         
1858         mono_image_add_cattrs (assembly, tb->table_idx, CUSTOM_ATTR_TYPEDEF, tb->cattrs);
1859         if (tb->fields) {
1860                 for (i = 0; i < mono_array_length (tb->fields); ++i) {
1861                         MonoReflectionFieldBuilder* fb;
1862                         fb = mono_array_get (tb->fields, MonoReflectionFieldBuilder*, i);
1863                         mono_image_add_cattrs (assembly, fb->table_idx, CUSTOM_ATTR_FIELDDEF, fb->cattrs);
1864                 }
1865         }
1866         if (tb->events) {
1867                 for (i = 0; i < mono_array_length (tb->events); ++i) {
1868                         MonoReflectionEventBuilder* eb;
1869                         eb = mono_array_get (tb->events, MonoReflectionEventBuilder*, i);
1870                         mono_image_add_cattrs (assembly, eb->table_idx, CUSTOM_ATTR_EVENT, eb->cattrs);
1871                 }
1872         }
1873         if (tb->properties) {
1874                 for (i = 0; i < mono_array_length (tb->properties); ++i) {
1875                         MonoReflectionPropertyBuilder* pb;
1876                         pb = mono_array_get (tb->properties, MonoReflectionPropertyBuilder*, i);
1877                         mono_image_add_cattrs (assembly, pb->table_idx, CUSTOM_ATTR_PROPERTY, pb->cattrs);
1878                 }
1879         }
1880         if (tb->ctors) {
1881                 for (i = 0; i < mono_array_length (tb->ctors); ++i) {
1882                         MonoReflectionCtorBuilder* cb;
1883                         cb = mono_array_get (tb->ctors, MonoReflectionCtorBuilder*, i);
1884                         mono_image_add_cattrs (assembly, cb->table_idx, CUSTOM_ATTR_METHODDEF, cb->cattrs);
1885                         params_add_cattrs (assembly, cb->pinfo);
1886                 }
1887         }
1888
1889         if (tb->methods) {
1890                 for (i = 0; i < mono_array_length (tb->methods); ++i) {
1891                         MonoReflectionMethodBuilder* mb;
1892                         mb = mono_array_get (tb->methods, MonoReflectionMethodBuilder*, i);
1893                         mono_image_add_cattrs (assembly, mb->table_idx, CUSTOM_ATTR_METHODDEF, mb->cattrs);
1894                         params_add_cattrs (assembly, mb->pinfo);
1895                 }
1896         }
1897
1898         if (tb->subtypes) {
1899                 for (i = 0; i < mono_array_length (tb->subtypes); ++i)
1900                         type_add_cattrs (assembly, mono_array_get (tb->subtypes, MonoReflectionTypeBuilder*, i));
1901         }
1902 }
1903
1904 static void
1905 module_add_cattrs (MonoDynamicAssembly *assembly, MonoReflectionModuleBuilder *mb) {
1906         int i;
1907         
1908         mono_image_add_cattrs (assembly, mb->table_idx, CUSTOM_ATTR_MODULE, mb->cattrs);
1909         
1910         /* no types in the module */
1911         if (!mb->types)
1912                 return;
1913         
1914         for (i = 0; i < mono_array_length (mb->types); ++i)
1915                 type_add_cattrs (assembly, mono_array_get (mb->types, MonoReflectionTypeBuilder*, i));
1916 }
1917
1918 static void
1919 mono_image_fill_module_table (MonoDomain *domain, MonoReflectionModuleBuilder *mb, MonoDynamicAssembly *assembly)
1920 {
1921         MonoDynamicTable *table;
1922         int i;
1923         char *name;
1924
1925         table = &assembly->tables [MONO_TABLE_MODULE];
1926         mb->table_idx = table->next_idx ++;
1927         name = mono_string_to_utf8 (mb->module.name);
1928         table->values [mb->table_idx * MONO_MODULE_SIZE + MONO_MODULE_NAME] = string_heap_insert (&assembly->sheap, name);
1929         g_free (name);
1930         i = mono_image_add_stream_data (&assembly->guid, mono_array_addr (mb->guid, char, 0), 16);
1931         i /= 16;
1932         ++i;
1933         table->values [mb->table_idx * MONO_MODULE_SIZE + MONO_MODULE_MVID] = i;
1934         table->values [mb->table_idx * MONO_MODULE_SIZE + MONO_MODULE_ENC] = 0;
1935         table->values [mb->table_idx * MONO_MODULE_SIZE + MONO_MODULE_ENCBASE] = 0;
1936
1937         /* no types in the module */
1938         if (!mb->types)
1939                 return;
1940         
1941         /*
1942          * fill-in info in other tables as well.
1943          */
1944         table = &assembly->tables [MONO_TABLE_TYPEDEF];
1945         table->rows += mono_array_length (mb->types);
1946         alloc_table (table, table->rows);
1947         /*
1948          * We assign here the typedef indexes to avoid mismatches if a type that
1949          * has not yet been stored in the tables is referenced by another type.
1950          */
1951         for (i = 0; i < mono_array_length (mb->types); ++i) {
1952                 MonoReflectionTypeBuilder *type = mono_array_get (mb->types, MonoReflectionTypeBuilder*, i);
1953                 assign_type_idx (type, table);
1954         }
1955         for (i = 0; i < mono_array_length (mb->types); ++i)
1956                 mono_image_get_type_info (domain, mono_array_get (mb->types, MonoReflectionTypeBuilder*, i), assembly);
1957 }
1958
1959 #define align_pointer(base,p)\
1960         do {\
1961                 guint32 __diff = (unsigned char*)(p)-(unsigned char*)(base);\
1962                 if (__diff & 3)\
1963                         (p) += 4 - (__diff & 3);\
1964         } while (0)
1965
1966 static int
1967 compare_semantics (const void *a, const void *b)
1968 {
1969         const guint32 *a_values = a;
1970         const guint32 *b_values = b;
1971         int assoc = a_values [MONO_METHOD_SEMA_ASSOCIATION] - b_values [MONO_METHOD_SEMA_ASSOCIATION];
1972         if (assoc)
1973                 return assoc;
1974         return a_values [MONO_METHOD_SEMA_SEMANTICS] - b_values [MONO_METHOD_SEMA_SEMANTICS];
1975 }
1976
1977 static int
1978 compare_custom_attrs (const void *a, const void *b)
1979 {
1980         const guint32 *a_values = a;
1981         const guint32 *b_values = b;
1982
1983         return a_values [MONO_CUSTOM_ATTR_PARENT] - b_values [MONO_CUSTOM_ATTR_PARENT];
1984 }
1985
1986 static int
1987 compare_field_marshal (const void *a, const void *b)
1988 {
1989         const guint32 *a_values = a;
1990         const guint32 *b_values = b;
1991
1992         return a_values [MONO_FIELD_MARSHAL_PARENT] - b_values [MONO_FIELD_MARSHAL_PARENT];
1993 }
1994
1995 static int
1996 compare_nested (const void *a, const void *b)
1997 {
1998         const guint32 *a_values = a;
1999         const guint32 *b_values = b;
2000
2001         return a_values [MONO_NESTED_CLASS_NESTED] - b_values [MONO_NESTED_CLASS_NESTED];
2002 }
2003
2004 /*
2005  * build_compressed_metadata() fills in the blob of data that represents the 
2006  * raw metadata as it will be saved in the PE file. The five streams are output 
2007  * and the metadata tables are comnpressed from the guint32 array representation, 
2008  * to the compressed on-disk format.
2009  */
2010 static void
2011 build_compressed_metadata (MonoDynamicAssembly *assembly)
2012 {
2013         MonoDynamicTable *table;
2014         int i;
2015         guint64 valid_mask = 0;
2016         guint64 sorted_mask;
2017         guint32 heapt_size = 0;
2018         guint32 meta_size = 256; /* allow for header and other stuff */
2019         guint32 table_offset;
2020         guint32 ntables = 0;
2021         guint64 *int64val;
2022         guint32 *int32val;
2023         guint16 *int16val;
2024         MonoImage *meta;
2025         unsigned char *p;
2026         /*
2027          * We need to use the current ms version or the ms runtime it won't find
2028          * the support dlls. D'oh!
2029          * const char *version = "mono-" VERSION;
2030          */
2031         const char *version = "v1.0.3705";
2032         struct StreamDesc {
2033                 const char *name;
2034                 MonoDynamicStream *stream;
2035         } stream_desc [] = {
2036                 {"#~", &assembly->tstream},
2037                 {"#Strings", &assembly->sheap},
2038                 {"#US", &assembly->us},
2039                 {"#Blob", &assembly->blob},
2040                 {"#GUID", &assembly->guid}
2041         };
2042         
2043         /* tables that are sorted */
2044         sorted_mask = ((guint64)1 << MONO_TABLE_CONSTANT) | ((guint64)1 << MONO_TABLE_FIELDMARSHAL)
2045                 | ((guint64)1 << MONO_TABLE_METHODSEMANTICS) | ((guint64)1 << MONO_TABLE_CLASSLAYOUT)
2046                 | ((guint64)1 << MONO_TABLE_FIELDLAYOUT) | ((guint64)1 << MONO_TABLE_FIELDRVA)
2047                 | ((guint64)1 << MONO_TABLE_IMPLMAP) | ((guint64)1 << MONO_TABLE_NESTEDCLASS)
2048                 | ((guint64)1 << MONO_TABLE_METHODIMPL) | ((guint64)1 << MONO_TABLE_CUSTOMATTRIBUTE)
2049                 | ((guint64)1 << MONO_TABLE_DECLSECURITY);
2050         
2051         /* Compute table sizes */
2052         /* the MonoImage has already been created in mono_image_basic_init() */
2053         meta = assembly->assembly.image;
2054         
2055         /* Setup the info used by compute_sizes () */
2056         meta->idx_blob_wide = assembly->blob.index >= 65536 ? 1 : 0;
2057         meta->idx_guid_wide = assembly->guid.index >= 65536 ? 1 : 0;
2058         meta->idx_string_wide = assembly->sheap.index >= 65536 ? 1 : 0;
2059
2060         meta_size += assembly->blob.index;
2061         meta_size += assembly->guid.index;
2062         meta_size += assembly->sheap.index;
2063         meta_size += assembly->us.index;
2064
2065         for (i=0; i < 64; ++i)
2066                 meta->tables [i].rows = assembly->tables [i].rows;
2067         
2068         for (i = 0; i < 64; i++){
2069                 if (meta->tables [i].rows == 0)
2070                         continue;
2071                 valid_mask |= (guint64)1 << i;
2072                 ntables ++;
2073                 meta->tables [i].row_size = mono_metadata_compute_size (
2074                         meta, i, &meta->tables [i].size_bitfield);
2075                 heapt_size += meta->tables [i].row_size * meta->tables [i].rows;
2076         }
2077         heapt_size += 24; /* #~ header size */
2078         heapt_size += ntables * 4;
2079         meta_size += heapt_size;
2080         meta->raw_metadata = g_malloc0 (meta_size);
2081         p = meta->raw_metadata;
2082         /* the metadata signature */
2083         *p++ = 'B'; *p++ = 'S'; *p++ = 'J'; *p++ = 'B';
2084         /* version numbers and 4 bytes reserved */
2085         int16val = (guint16*)p;
2086         *int16val++ = GUINT16_TO_LE (1);
2087         *int16val = GUINT16_TO_LE (1);
2088         p += 8;
2089         /* version string */
2090         int32val = (guint32*)p;
2091         *int32val = GUINT32_TO_LE ((strlen (version) + 3) & (~3)); /* needs to be multiple of 4 */
2092         p += 4;
2093         memcpy (p, version, GUINT32_FROM_LE (*int32val));
2094         p += GUINT32_FROM_LE (*int32val);
2095         align_pointer (meta->raw_metadata, p);
2096         int16val = (guint16*)p;
2097         *int16val++ = GUINT16_TO_LE (0); /* flags must be 0 */
2098         *int16val = GUINT16_TO_LE (5); /* number of streams */
2099         p += 4;
2100
2101         /*
2102          * write the stream info.
2103          */
2104         table_offset = (p - (unsigned char*)meta->raw_metadata) + 5 * 8 + 40; /* room needed for stream headers */
2105         table_offset += 3; table_offset &= ~3;
2106
2107         assembly->tstream.index = heapt_size;
2108         for (i = 0; i < 5; ++i) {
2109                 int32val = (guint32*)p;
2110                 stream_desc [i].stream->offset = table_offset;
2111                 *int32val++ = GUINT32_TO_LE (table_offset);
2112                 *int32val = GUINT32_TO_LE (stream_desc [i].stream->index);
2113                 table_offset += GUINT32_FROM_LE (*int32val);
2114                 table_offset += 3; table_offset &= ~3;
2115                 p += 8;
2116                 strcpy (p, stream_desc [i].name);
2117                 p += strlen (stream_desc [i].name) + 1;
2118                 align_pointer (meta->raw_metadata, p);
2119         }
2120         /* 
2121          * now copy the data, the table stream header and contents goes first.
2122          */
2123         g_assert ((p - (unsigned char*)meta->raw_metadata) < assembly->tstream.offset);
2124         p = meta->raw_metadata + assembly->tstream.offset;
2125         int32val = (guint32*)p;
2126         *int32val = GUINT32_TO_LE (0); /* reserved */
2127         p += 4;
2128         *p++ = 1; /* version */
2129         *p++ = 0;
2130         if (meta->idx_string_wide)
2131                 *p |= 0x01;
2132         if (meta->idx_guid_wide)
2133                 *p |= 0x02;
2134         if (meta->idx_blob_wide)
2135                 *p |= 0x04;
2136         ++p;
2137         *p++ = 0; /* reserved */
2138         int64val = (guint64*)p;
2139         *int64val++ = GUINT64_TO_LE (valid_mask);
2140         *int64val++ = GUINT64_TO_LE (valid_mask & sorted_mask); /* bitvector of sorted tables  */
2141         p += 16;
2142         int32val = (guint32*)p;
2143         for (i = 0; i < 64; i++){
2144                 if (meta->tables [i].rows == 0)
2145                         continue;
2146                 *int32val++ = GUINT32_TO_LE (meta->tables [i].rows);
2147         }
2148         p = (unsigned char*)int32val;
2149
2150         /* sort the tables that still need sorting */
2151         table = &assembly->tables [MONO_TABLE_METHODSEMANTICS];
2152         if (table->rows)
2153                 qsort (table->values + MONO_METHOD_SEMA_SIZE, table->rows, sizeof (guint32) * MONO_METHOD_SEMA_SIZE, compare_semantics);
2154         table = &assembly->tables [MONO_TABLE_CUSTOMATTRIBUTE];
2155         if (table->rows)
2156                 qsort (table->values + MONO_CUSTOM_ATTR_SIZE, table->rows, sizeof (guint32) * MONO_CUSTOM_ATTR_SIZE, compare_custom_attrs);
2157         table = &assembly->tables [MONO_TABLE_FIELDMARSHAL];
2158         if (table->rows)
2159                 qsort (table->values + MONO_FIELD_MARSHAL_SIZE, table->rows, sizeof (guint32) * MONO_FIELD_MARSHAL_SIZE, compare_field_marshal);
2160         table = &assembly->tables [MONO_TABLE_NESTEDCLASS];
2161         if (table->rows)
2162                 qsort (table->values + MONO_NESTED_CLASS_SIZE, table->rows, sizeof (guint32) * MONO_NESTED_CLASS_SIZE, compare_nested);
2163
2164         /* compress the tables */
2165         for (i = 0; i < 64; i++){
2166                 int row, col;
2167                 guint32 *values;
2168                 guint32 bitfield = meta->tables [i].size_bitfield;
2169                 if (!meta->tables [i].rows)
2170                         continue;
2171                 if (assembly->tables [i].columns != mono_metadata_table_count (bitfield))
2172                         g_error ("col count mismatch in %d: %d %d", i, assembly->tables [i].columns, mono_metadata_table_count (bitfield));
2173                 meta->tables [i].base = p;
2174                 for (row = 1; row <= meta->tables [i].rows; ++row) {
2175                         values = assembly->tables [i].values + row * assembly->tables [i].columns;
2176                         for (col = 0; col < assembly->tables [i].columns; ++col) {
2177                                 switch (mono_metadata_table_size (bitfield, col)) {
2178                                 case 1:
2179                                         *p++ = values [col];
2180                                         break;
2181                                 case 2:
2182                                         *p++ = values [col] & 0xff;
2183                                         *p++ = (values [col] >> 8) & 0xff;
2184                                         break;
2185                                 case 4:
2186                                         *p++ = values [col] & 0xff;
2187                                         *p++ = (values [col] >> 8) & 0xff;
2188                                         *p++ = (values [col] >> 16) & 0xff;
2189                                         *p++ = (values [col] >> 24) & 0xff;
2190                                         break;
2191                                 default:
2192                                         g_assert_not_reached ();
2193                                 }
2194                         }
2195                 }
2196                 g_assert ((p - (const unsigned char*)meta->tables [i].base) == (meta->tables [i].rows * meta->tables [i].row_size));
2197         }
2198         
2199         g_assert (assembly->guid.offset + assembly->guid.index < meta_size);
2200         memcpy (meta->raw_metadata + assembly->sheap.offset, assembly->sheap.data, assembly->sheap.index);
2201         memcpy (meta->raw_metadata + assembly->us.offset, assembly->us.data, assembly->us.index);
2202         memcpy (meta->raw_metadata + assembly->blob.offset, assembly->blob.data, assembly->blob.index);
2203         memcpy (meta->raw_metadata + assembly->guid.offset, assembly->guid.data, assembly->guid.index);
2204
2205         assembly->meta_size = assembly->guid.offset + assembly->guid.index;
2206 }
2207
2208 /*
2209  * Some tables in metadata need to be sorted according to some criteria, but
2210  * when methods and fields are first created with reflection, they may be assigned a token
2211  * that doesn't correspond to the final token they will get assigned after the sorting.
2212  * ILGenerator.cs keeps a fixup table that maps the position of tokens in the IL code stream
2213  * with the reflection objects that represent them. Once all the tables are set up, the 
2214  * reflection objects will contains the correct table index. fixup_method() will fixup the
2215  * tokens for the method with ILGenerator @ilgen.
2216  */
2217 static void
2218 fixup_method (MonoReflectionILGen *ilgen, gpointer value, MonoDynamicAssembly *assembly) {
2219         guint32 code_idx = GPOINTER_TO_UINT (value);
2220         MonoReflectionILTokenInfo *iltoken;
2221         MonoReflectionFieldBuilder *field;
2222         MonoReflectionCtorBuilder *ctor;
2223         MonoReflectionMethodBuilder *method;
2224         MonoReflectionTypeBuilder *tb;
2225         guint32 i, idx;
2226         unsigned char *target;
2227
2228         for (i = 0; i < ilgen->num_token_fixups; ++i) {
2229                 iltoken = (MonoReflectionILTokenInfo *)mono_array_addr_with_size (ilgen->token_fixups, sizeof (MonoReflectionILTokenInfo), i);
2230                 target = assembly->code.data + code_idx + iltoken->code_pos;
2231                 switch (target [3]) {
2232                 case MONO_TABLE_FIELD:
2233                         if (strcmp (iltoken->member->vtable->klass->name, "FieldBuilder"))
2234                                 g_assert_not_reached ();
2235                         field = (MonoReflectionFieldBuilder *)iltoken->member;
2236                         idx = field->table_idx;
2237                         break;
2238                 case MONO_TABLE_METHOD:
2239                         if (!strcmp (iltoken->member->vtable->klass->name, "MethodBuilder")) {
2240                                 method = (MonoReflectionMethodBuilder *)iltoken->member;
2241                                 idx = method->table_idx;
2242                         } else if (!strcmp (iltoken->member->vtable->klass->name, "ConstructorBuilder")) {
2243                                 ctor = (MonoReflectionCtorBuilder *)iltoken->member;
2244                                 idx = ctor->table_idx;
2245                         } else {
2246                                 g_assert_not_reached ();
2247                         }
2248                         break;
2249                 case MONO_TABLE_TYPEDEF:
2250                         if (strcmp (iltoken->member->vtable->klass->name, "TypeBuilder"))
2251                                 g_assert_not_reached ();
2252                         tb = (MonoReflectionTypeBuilder *)iltoken->member;
2253                         idx = tb->table_idx;
2254                         break;
2255                 default:
2256                         g_error ("got unexpected table 0x%02x in fixup", target [3]);
2257                 }
2258                 target [0] = idx & 0xff;
2259                 target [1] = (idx >> 8) & 0xff;
2260                 target [2] = (idx >> 16) & 0xff;
2261         }
2262 }
2263
2264 static void
2265 assembly_add_resource (MonoDynamicAssembly *assembly, MonoReflectionResource *rsrc)
2266 {
2267         MonoDynamicTable *table;
2268         guint32 *values;
2269         char blob_size [6];
2270         guchar hash [20];
2271         char *b = blob_size;
2272         char *name, *sname;
2273         guint32 idx, offset;
2274
2275         if (rsrc->filename) {
2276                 name = mono_string_to_utf8 (rsrc->filename);
2277                 sname = g_path_get_basename (name);
2278         
2279                 table = &assembly->tables [MONO_TABLE_FILE];
2280                 table->rows++;
2281                 alloc_table (table, table->rows);
2282                 values = table->values + table->next_idx * MONO_FILE_SIZE;
2283                 values [MONO_FILE_FLAGS] = FILE_CONTAINS_NO_METADATA;
2284                 values [MONO_FILE_NAME] = string_heap_insert (&assembly->sheap, sname);
2285                 g_free (sname);
2286
2287                 mono_sha1_get_digest_from_file (name, hash);
2288                 mono_metadata_encode_value (20, b, &b);
2289                 values [MONO_FILE_HASH_VALUE] = mono_image_add_stream_data (&assembly->blob, blob_size, b-blob_size);
2290                 mono_image_add_stream_data (&assembly->blob, hash, 20);
2291                 g_free (name);
2292                 idx = table->next_idx++;
2293                 idx = IMPLEMENTATION_FILE | (idx << IMPLEMENTATION_BITS);
2294                 offset = 0;
2295         } else {
2296                 char sizebuf [4];
2297                 offset = mono_array_length (rsrc->data);
2298                 sizebuf [0] = offset; sizebuf [1] = offset >> 8;
2299                 sizebuf [2] = offset >> 16; sizebuf [3] = offset >> 24;
2300                 offset = mono_image_add_stream_data (&assembly->resources, sizebuf, 4);
2301                 mono_image_add_stream_data (&assembly->resources, mono_array_addr (rsrc->data, char, 0), mono_array_length (rsrc->data));
2302                 idx = 0;
2303         }
2304
2305         table = &assembly->tables [MONO_TABLE_MANIFESTRESOURCE];
2306         table->rows++;
2307         alloc_table (table, table->rows);
2308         values = table->values + table->next_idx * MONO_MANIFEST_SIZE;
2309         values [MONO_MANIFEST_OFFSET] = offset;
2310         values [MONO_MANIFEST_FLAGS] = rsrc->attrs;
2311         name = mono_string_to_utf8 (rsrc->name);
2312         values [MONO_MANIFEST_NAME] = string_heap_insert (&assembly->sheap, name);
2313         g_free (name);
2314         values [MONO_MANIFEST_IMPLEMENTATION] = idx;
2315         table->next_idx++;
2316 }
2317
2318 static void
2319 set_version_from_string (MonoString *version, guint32 *values)
2320 {
2321         gchar *ver, *p, *str;
2322         guint32 i;
2323         
2324         values [MONO_ASSEMBLY_MAJOR_VERSION] = 0;
2325         values [MONO_ASSEMBLY_MINOR_VERSION] = 0;
2326         values [MONO_ASSEMBLY_REV_NUMBER] = 0;
2327         values [MONO_ASSEMBLY_BUILD_NUMBER] = 0;
2328         if (!version)
2329                 return;
2330         ver = str = mono_string_to_utf8 (version);
2331         for (i = 0; i < 4; ++i) {
2332                 values [MONO_ASSEMBLY_MAJOR_VERSION + i] = strtol (ver, &p, 10);
2333                 switch (*p) {
2334                 case '.':
2335                         p++;
2336                         break;
2337                 case '*':
2338                         /* handle Revision and Build */
2339                         p++;
2340                         break;
2341                 }
2342                 ver = p;
2343         }
2344         g_free (str);
2345 }
2346
2347 static guint32
2348 load_public_key (MonoString *fname, MonoDynamicAssembly *assembly) {
2349         char *name, *content;
2350         gsize len;
2351         guint32 token = 0;
2352
2353         if (!fname)
2354                 return token;
2355         name = mono_string_to_utf8 (fname);
2356         if (g_file_get_contents (name, &content, &len, NULL)) {
2357                 char blob_size [6];
2358                 char *b = blob_size;
2359                 /* check it's a public key or keypair */
2360                 mono_metadata_encode_value (len, b, &b);
2361                 token = mono_image_add_stream_data (&assembly->blob, blob_size, b - blob_size);
2362                 mono_image_add_stream_data (&assembly->blob, content, len);
2363                 g_free (content);
2364                 /* need to get the actual value from the key type... */
2365                 assembly->strong_name_size = 128;
2366                 assembly->strong_name = g_malloc0 (assembly->strong_name_size);
2367         }
2368         /* FIXME: how do we tell mcs if loading fails? */
2369         g_free (name);
2370         return token;
2371 }
2372
2373 /*
2374  * mono_image_build_metadata() will fill the info in all the needed metadata tables
2375  * for the AssemblyBuilder @assemblyb: it iterates over the assembly modules
2376  * and recursively outputs the info for a module. Each module will output all the info
2377  * about it's types etc.
2378  * At the end of the process, method and field tokens are fixed up and the on-disk
2379  * compressed metadata representation is created.
2380  */
2381 void
2382 mono_image_build_metadata (MonoReflectionAssemblyBuilder *assemblyb)
2383 {
2384         MonoDynamicTable *table;
2385         MonoDynamicAssembly *assembly = assemblyb->dynamic_assembly;
2386         MonoDomain *domain = mono_object_domain (assemblyb);
2387         guint32 len;
2388         guint32 *values;
2389         char *name;
2390         int i;
2391
2392         if (assembly->text_rva)
2393                 return;
2394
2395         assembly->text_rva = START_TEXT_RVA;
2396
2397         table = &assembly->tables [MONO_TABLE_ASSEMBLY];
2398         alloc_table (table, 1);
2399         values = table->values + MONO_ASSEMBLY_SIZE;
2400         values [MONO_ASSEMBLY_HASH_ALG] = assemblyb->algid? assemblyb->algid: ASSEMBLY_HASH_SHA1;
2401         name = mono_string_to_utf8 (assemblyb->name);
2402         values [MONO_ASSEMBLY_NAME] = string_heap_insert (&assembly->sheap, name);
2403         g_free (name);
2404         if (assemblyb->culture) {
2405                 name = mono_string_to_utf8 (assemblyb->culture);
2406                 values [MONO_ASSEMBLY_CULTURE] = string_heap_insert (&assembly->sheap, name);
2407                 g_free (name);
2408         } else {
2409                 values [MONO_ASSEMBLY_CULTURE] = string_heap_insert (&assembly->sheap, "");
2410         }
2411         values [MONO_ASSEMBLY_PUBLIC_KEY] = load_public_key (assemblyb->keyfile, assembly);
2412         values [MONO_ASSEMBLY_FLAGS] = assemblyb->flags;
2413         set_version_from_string (assemblyb->version, values);
2414
2415         table = &assembly->tables [MONO_TABLE_TYPEDEF];
2416         table->rows = 1; /* .<Module> */
2417         table->next_idx++;
2418         alloc_table (table, table->rows);
2419         /*
2420          * Set the first entry.
2421          */
2422         values = table->values + table->columns;
2423         values [MONO_TYPEDEF_FLAGS] = 0;
2424         values [MONO_TYPEDEF_NAME] = string_heap_insert (&assembly->sheap, "<Module>") ;
2425         values [MONO_TYPEDEF_NAMESPACE] = string_heap_insert (&assembly->sheap, "") ;
2426         values [MONO_TYPEDEF_EXTENDS] = 0;
2427         values [MONO_TYPEDEF_FIELD_LIST] = 1;
2428         values [MONO_TYPEDEF_METHOD_LIST] = 1;
2429
2430         /* 
2431          * handle global methods 
2432          * FIXME: test what to do when global methods are defined in multiple modules.
2433          */
2434         if (assemblyb->modules) {
2435                 MonoReflectionModuleBuilder *mod = mono_array_get (assemblyb->modules, MonoReflectionModuleBuilder*, 0);
2436                 if (mod->global_methods) {
2437                         table = &assembly->tables [MONO_TABLE_METHOD];
2438                         table->rows += mono_array_length (mod->global_methods);
2439                         alloc_table (table, table->rows);
2440                         for (i = 0; i < mono_array_length (mod->global_methods); ++i)
2441                                 mono_image_get_method_info (
2442                                         mono_array_get (mod->global_methods, MonoReflectionMethodBuilder*, i), assembly);
2443                 }
2444         }
2445
2446         if (assemblyb->modules) {
2447                 len = mono_array_length (assemblyb->modules);
2448                 table = &assembly->tables [MONO_TABLE_MODULE];
2449                 alloc_table (table, len);
2450                 for (i = 0; i < len; ++i)
2451                         mono_image_fill_module_table (domain, mono_array_get (assemblyb->modules, MonoReflectionModuleBuilder*, i), assembly);
2452         } else {
2453                 table = &assembly->tables [MONO_TABLE_MODULE];
2454                 table->rows++;
2455                 alloc_table (table, table->rows);
2456                 table->values [table->next_idx * MONO_MODULE_SIZE + MONO_MODULE_NAME] = string_heap_insert (&assembly->sheap, "RefEmit_YouForgotToDefineAModule");
2457                 table->next_idx ++;
2458         }
2459
2460         /* 
2461          * table->rows is already set above and in mono_image_fill_module_table.
2462          */
2463         /* add all the custom attributes at the end, once all the indexes are stable */
2464         mono_image_add_cattrs (assembly, 1, CUSTOM_ATTR_ASSEMBLY, assemblyb->cattrs);
2465
2466         if (assemblyb->modules) {
2467                 len = mono_array_length (assemblyb->modules);
2468                 for (i = 0; i < len; ++i)
2469                         module_add_cattrs (assembly, mono_array_get (assemblyb->modules, MonoReflectionModuleBuilder*, i));
2470         }
2471
2472         /* fixup tokens */
2473         mono_g_hash_table_foreach (assembly->token_fixups, (GHFunc)fixup_method, assembly);
2474 }
2475
2476 /*
2477  * mono_image_insert_string:
2478  * @assembly: assembly builder object
2479  * @str: a string
2480  *
2481  * Insert @str into the user string stream of @assembly.
2482  */
2483 guint32
2484 mono_image_insert_string (MonoReflectionAssemblyBuilder *assembly, MonoString *str)
2485 {
2486         guint32 idx;
2487         char buf [16];
2488         char *b = buf;
2489         
2490         MONO_ARCH_SAVE_REGS;
2491
2492         if (!assembly->dynamic_assembly)
2493                 mono_image_basic_init (assembly);
2494         mono_metadata_encode_value (1 | (str->length * 2), b, &b);
2495         idx = mono_image_add_stream_data (&assembly->dynamic_assembly->us, buf, b-buf);
2496 #if G_BYTE_ORDER != G_LITTLE_ENDIAN
2497         {
2498                 char *swapped = g_malloc (2 * mono_string_length (str));
2499                 const char *p = (const char*)mono_string_chars (str);
2500
2501                 swap_with_size (swapped, p, 2, mono_string_length (str));
2502                 mono_image_add_stream_data (&assembly->dynamic_assembly->us, swapped, str->length * 2);
2503                 g_free (swapped);
2504         }
2505 #else
2506         mono_image_add_stream_data (&assembly->dynamic_assembly->us, (const char*)mono_string_chars (str), str->length * 2);
2507 #endif
2508         mono_image_add_stream_data (&assembly->dynamic_assembly->us, "", 1);
2509
2510         mono_g_hash_table_insert (assembly->dynamic_assembly->tokens, 
2511                                                           GUINT_TO_POINTER (MONO_TOKEN_STRING | idx), str);
2512
2513         return MONO_TOKEN_STRING | idx;
2514 }
2515
2516 /*
2517  * mono_image_create_token:
2518  * @assembly: a dynamic assembly
2519  * @obj:
2520  *
2521  * Get a token to insert in the IL code stream for the given MemberInfo.
2522  * @obj can be one of:
2523  *      ConstructorBuilder
2524  *      MethodBuilder
2525  *      FieldBuilder
2526  *      MonoCMethod
2527  *      MonoMethod
2528  *      MonoField
2529  *      MonoType
2530  *      TypeBuilder
2531  */
2532 guint32
2533 mono_image_create_token (MonoDynamicAssembly *assembly, MonoObject *obj)
2534 {
2535         MonoClass *klass;
2536         guint32 token;
2537
2538         if (!obj)
2539                 g_error ("System.Array methods not yet supported");
2540         
2541         klass = obj->vtable->klass;
2542         if (strcmp (klass->name, "MethodBuilder") == 0) {
2543                 MonoReflectionMethodBuilder *mb = (MonoReflectionMethodBuilder *)obj;
2544                 token = mb->table_idx | MONO_TOKEN_METHOD_DEF;
2545                 /*g_print ("got token 0x%08x for %s\n", token, mono_string_to_utf8 (mb->name));*/
2546         }
2547         else if (strcmp (klass->name, "ConstructorBuilder") == 0) {
2548                 MonoReflectionCtorBuilder *mb = (MonoReflectionCtorBuilder *)obj;
2549                 token = mb->table_idx | MONO_TOKEN_METHOD_DEF;
2550                 /*g_print ("got token 0x%08x for %s\n", token, mono_string_to_utf8 (mb->name));*/
2551         }
2552         else if (strcmp (klass->name, "FieldBuilder") == 0) {
2553                 MonoReflectionFieldBuilder *mb = (MonoReflectionFieldBuilder *)obj;
2554                 token = mb->table_idx | MONO_TOKEN_FIELD_DEF;
2555         }
2556         else if (strcmp (klass->name, "TypeBuilder") == 0) {
2557                 MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder *)obj;
2558                 token = tb->table_idx | MONO_TOKEN_TYPE_DEF;
2559         }
2560         else if (strcmp (klass->name, "MonoType") == 0) {
2561                 MonoReflectionType *tb = (MonoReflectionType *)obj;
2562                 token = mono_metadata_token_from_dor (
2563                         mono_image_typedef_or_ref (assembly, tb->type));
2564         }
2565         else if (strcmp (klass->name, "MonoCMethod") == 0 ||
2566                         strcmp (klass->name, "MonoMethod") == 0) {
2567                 MonoReflectionMethod *m = (MonoReflectionMethod *)obj;
2568                 token = mono_image_get_methodref_token (assembly, m->method);
2569                 /*g_print ("got token 0x%08x for %s\n", token, m->method->name);*/
2570         }
2571         else if (strcmp (klass->name, "MonoField") == 0) {
2572                 MonoReflectionField *f = (MonoReflectionField *)obj;
2573                 token = mono_image_get_fieldref_token (assembly, f->field, f->klass);
2574                 /*g_print ("got token 0x%08x for %s\n", token, f->field->name);*/
2575         }
2576         else if (strcmp (klass->name, "MonoArrayMethod") == 0) {
2577                 MonoReflectionArrayMethod *m = (MonoReflectionArrayMethod *)obj;
2578                 token = mono_image_get_array_token (assembly, m);
2579         }
2580         else if (strcmp (klass->name, "SignatureHelper") == 0) {
2581                 MonoReflectionSigHelper *s = (MonoReflectionSigHelper*)obj;
2582                 token = MONO_TOKEN_SIGNATURE | mono_image_get_sighelper_token (assembly, s);
2583         }
2584         else
2585                 g_error ("requested token for %s\n", klass->name);
2586
2587         mono_g_hash_table_insert (assembly->tokens, GUINT_TO_POINTER (token),
2588                                                           obj);
2589
2590         return token;
2591 }
2592
2593 typedef struct {
2594         guint32 import_lookup_table;
2595         guint32 timestamp;
2596         guint32 forwarder;
2597         guint32 name_rva;
2598         guint32 import_address_table_rva;
2599 } MonoIDT;
2600
2601 typedef struct {
2602         guint32 name_rva;
2603         guint32 flags;
2604 } MonoILT;
2605
2606 static void register_assembly (MonoDomain *domain, MonoReflectionAssembly *res, MonoAssembly *assembly);
2607
2608 static MonoImage*
2609 create_dynamic_mono_image (char *assembly_name, char *module_name)
2610 {
2611         MonoImage *image;
2612
2613         image = g_new0 (MonoImage, 1);
2614         
2615         /* keep in sync with image.c */
2616         image->name = assembly_name;
2617         image->assembly_name = image->name; /* they may be different */
2618         image->module_name = module_name;
2619         image->references = g_new0 (MonoAssembly*, 1);
2620         image->references [0] = NULL;
2621
2622         image->method_cache = g_hash_table_new (g_direct_hash, g_direct_equal);
2623         image->class_cache = g_hash_table_new (g_direct_hash, g_direct_equal);
2624         image->name_cache = g_hash_table_new (g_str_hash, g_str_equal);
2625         image->array_cache = g_hash_table_new (g_direct_hash, g_direct_equal);
2626
2627         image->delegate_begin_invoke_cache = 
2628                 g_hash_table_new ((GHashFunc)mono_signature_hash, 
2629                                   (GCompareFunc)mono_metadata_signature_equal);
2630         image->delegate_end_invoke_cache = 
2631                 g_hash_table_new ((GHashFunc)mono_signature_hash, 
2632                                   (GCompareFunc)mono_metadata_signature_equal);
2633         image->delegate_invoke_cache = 
2634                 g_hash_table_new ((GHashFunc)mono_signature_hash, 
2635                                   (GCompareFunc)mono_metadata_signature_equal);
2636
2637         image->runtime_invoke_cache = g_hash_table_new (g_direct_hash, g_direct_equal);
2638         image->managed_wrapper_cache = g_hash_table_new (g_direct_hash, g_direct_equal);
2639         image->native_wrapper_cache = g_hash_table_new (g_direct_hash, g_direct_equal);
2640         image->remoting_invoke_cache = g_hash_table_new (g_direct_hash, g_direct_equal);
2641
2642         return image;
2643 }
2644
2645 /*
2646  * mono_image_basic_init:
2647  * @assembly: an assembly builder object
2648  *
2649  * Create the MonoImage that represents the assembly builder and setup some
2650  * of the helper hash table and the basic metadata streams.
2651  */
2652 void
2653 mono_image_basic_init (MonoReflectionAssemblyBuilder *assemblyb)
2654 {
2655         static const guchar entrycode [16] = {0xff, 0x25, 0};
2656         MonoDynamicAssembly *assembly;
2657         MonoImage *image;
2658         int i;
2659         
2660         MONO_ARCH_SAVE_REGS;
2661
2662         if (assemblyb->dynamic_assembly)
2663                 return;
2664
2665 #if HAVE_BOEHM_GC
2666         assembly = assemblyb->dynamic_assembly = GC_MALLOC (sizeof (MonoDynamicAssembly));
2667 #else
2668         assembly = assemblyb->dynamic_assembly = g_new0 (MonoDynamicAssembly, 1);
2669 #endif
2670
2671         assembly->assembly.dynamic = assembly;
2672         assemblyb->assembly.assembly = (MonoAssembly*)assembly;
2673         assembly->token_fixups = mono_g_hash_table_new (g_direct_hash, g_direct_equal);
2674         assembly->handleref = g_hash_table_new (g_direct_hash, g_direct_equal);
2675         assembly->tokens = mono_g_hash_table_new (g_direct_hash, g_direct_equal);
2676         assembly->typeref = g_hash_table_new ((GHashFunc)mono_metadata_type_hash, (GCompareFunc)mono_metadata_type_equal);
2677         assembly->blob_cache = g_hash_table_new ((GHashFunc)mono_blob_entry_hash, (GCompareFunc)mono_blob_entry_equal);
2678
2679         string_heap_init (&assembly->sheap);
2680         mono_image_add_stream_data (&assembly->us, "", 1);
2681         add_to_blob_cached (assembly, (char*) "", 1, NULL, 0);
2682         /* import tables... */
2683         mono_image_add_stream_data (&assembly->code, entrycode, sizeof (entrycode));
2684         assembly->iat_offset = mono_image_add_stream_zero (&assembly->code, 8); /* two IAT entries */
2685         assembly->idt_offset = mono_image_add_stream_zero (&assembly->code, 2 * sizeof (MonoIDT)); /* two IDT entries */
2686         mono_image_add_stream_zero (&assembly->code, 2); /* flags for name entry */
2687         assembly->imp_names_offset = mono_image_add_stream_data (&assembly->code, "_CorExeMain", 12);
2688         mono_image_add_stream_data (&assembly->code, "mscoree.dll", 12);
2689         assembly->ilt_offset = mono_image_add_stream_zero (&assembly->code, 8); /* two ILT entries */
2690         stream_data_align (&assembly->code);
2691
2692         assembly->cli_header_offset = mono_image_add_stream_zero (&assembly->code, sizeof (MonoCLIHeader));
2693
2694         for (i=0; i < 64; ++i) {
2695                 assembly->tables [i].next_idx = 1;
2696                 assembly->tables [i].columns = table_sizes [i];
2697         }
2698
2699         image = create_dynamic_mono_image (mono_string_to_utf8 (assemblyb->name), g_strdup ("RefEmit_YouForgotToDefineAModule"));
2700         assembly->assembly.aname.name = image->name;
2701         image->assembly = (MonoAssembly*)assembly;
2702         assembly->assembly.image = image;
2703
2704         register_assembly (mono_object_domain (assemblyb), &assemblyb->assembly, &assembly->assembly);
2705         mono_assembly_invoke_load_hook ((MonoAssembly*)assembly);
2706 }
2707
2708 static int
2709 calc_section_size (MonoDynamicAssembly *assembly)
2710 {
2711         int nsections = 0;
2712
2713         /* alignment constraints */
2714         assembly->code.index += 3;
2715         assembly->code.index &= ~3;
2716         assembly->meta_size += 3;
2717         assembly->meta_size &= ~3;
2718         assembly->resources.index += 3;
2719         assembly->resources.index &= ~3;
2720
2721         assembly->sections [MONO_SECTION_TEXT].size = assembly->meta_size + assembly->code.index + assembly->resources.index + assembly->strong_name_size;
2722         assembly->sections [MONO_SECTION_TEXT].attrs = SECT_FLAGS_HAS_CODE | SECT_FLAGS_MEM_EXECUTE | SECT_FLAGS_MEM_READ;
2723         nsections++;
2724
2725         assembly->sections [MONO_SECTION_RELOC].size = 12;
2726         assembly->sections [MONO_SECTION_RELOC].attrs = SECT_FLAGS_MEM_READ | SECT_FLAGS_MEM_DISCARDABLE | SECT_FLAGS_HAS_INITIALIZED_DATA;
2727         nsections++;
2728
2729         return nsections;
2730 }
2731
2732 /*
2733  * mono_image_create_pefile:
2734  * @assemblyb: an assembly builder object
2735  * 
2736  * When we need to save an assembly, we first call this function that ensures the metadata 
2737  * tables are built for all the modules in the assembly. This function creates the PE-COFF
2738  * header, the image sections, the CLI header etc. all the data is written in
2739  * assembly->pefile where it can be easily retrieved later in chunks.
2740  */
2741 void
2742 mono_image_create_pefile (MonoReflectionAssemblyBuilder *assemblyb) {
2743         MonoMSDOSHeader *msdos;
2744         MonoDotNetHeader *header;
2745         MonoSectionTable *section;
2746         MonoCLIHeader *cli_header;
2747         guint32 size, image_size, virtual_base, text_offset;
2748         guint32 header_start, section_start, file_offset, virtual_offset;
2749         MonoDynamicAssembly *assembly;
2750         MonoDynamicStream *pefile;
2751         int i, nsections;
2752         guint32 *rva, value;
2753         guint16 *data16;
2754         guchar *p;
2755         static const unsigned char msheader[] = {
2756                 0x4d, 0x5a, 0x90, 0x00, 0x03, 0x00, 0x00, 0x00,  0x04, 0x00, 0x00, 0x00, 0xff, 0xff, 0x00, 0x00,
2757                 0xb8, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,  0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
2758                 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
2759                 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,  0x00, 0x00, 0x00, 0x00, 0x80, 0x00, 0x00, 0x00,
2760                 0x0e, 0x1f, 0xba, 0x0e, 0x00, 0xb4, 0x09, 0xcd,  0x21, 0xb8, 0x01, 0x4c, 0xcd, 0x21, 0x54, 0x68,
2761                 0x69, 0x73, 0x20, 0x70, 0x72, 0x6f, 0x67, 0x72,  0x61, 0x6d, 0x20, 0x63, 0x61, 0x6e, 0x6e, 0x6f,
2762                 0x74, 0x20, 0x62, 0x65, 0x20, 0x72, 0x75, 0x6e,  0x20, 0x69, 0x6e, 0x20, 0x44, 0x4f, 0x53, 0x20,
2763                 0x6d, 0x6f, 0x64, 0x65, 0x2e, 0x0d, 0x0d, 0x0a,  0x24, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
2764         };
2765
2766         mono_image_basic_init (assemblyb);
2767         assembly = assemblyb->dynamic_assembly;
2768
2769         /* already created */
2770         if (assembly->pefile.index)
2771                 return;
2772         
2773         mono_image_build_metadata (assemblyb);
2774
2775         if (assemblyb->resources) {
2776                 int len = mono_array_length (assemblyb->resources);
2777                 for (i = 0; i < len; ++i)
2778                         assembly_add_resource (assembly, (MonoReflectionResource*)mono_array_addr (assemblyb->resources, MonoReflectionResource, i));
2779         }
2780
2781         
2782         build_compressed_metadata (assembly);
2783
2784         nsections = calc_section_size (assembly);
2785
2786         pefile = &assembly->pefile;
2787
2788         /* The DOS header and stub */
2789         g_assert (sizeof (MonoMSDOSHeader) == sizeof (msheader));
2790         mono_image_add_stream_data (pefile, msheader, sizeof (msheader));
2791
2792         /* the dotnet header */
2793         header_start = mono_image_add_stream_zero (pefile, sizeof (MonoDotNetHeader));
2794
2795         /* the section tables */
2796         section_start = mono_image_add_stream_zero (pefile, sizeof (MonoSectionTable) * nsections);
2797
2798         file_offset = section_start + sizeof (MonoSectionTable) * nsections;
2799         virtual_offset = VIRT_ALIGN;
2800         image_size = 0;
2801
2802         for (i = 0; i < MONO_SECTION_MAX; ++i) {
2803                 if (!assembly->sections [i].size)
2804                         continue;
2805                 /* align offsets */
2806                 file_offset += FILE_ALIGN - 1;
2807                 file_offset &= ~(FILE_ALIGN - 1);
2808                 virtual_offset += VIRT_ALIGN - 1;
2809                 virtual_offset &= ~(VIRT_ALIGN - 1);
2810
2811                 assembly->sections [i].offset = file_offset;
2812                 assembly->sections [i].rva = virtual_offset;
2813
2814                 file_offset += assembly->sections [i].size;
2815                 virtual_offset += assembly->sections [i].size;
2816                 image_size += (assembly->sections [i].size + VIRT_ALIGN - 1) & ~(VIRT_ALIGN - 1);
2817         }
2818
2819         file_offset += FILE_ALIGN - 1;
2820         file_offset &= ~(FILE_ALIGN - 1);
2821         mono_image_add_stream_zero (pefile, file_offset - pefile->index);
2822
2823         image_size += section_start + sizeof (MonoSectionTable) * nsections;
2824
2825         /* back-patch info */
2826         msdos = (MonoMSDOSHeader*)pefile->data;
2827         msdos->nlast_page = GUINT16_FROM_LE (file_offset & (512 - 1));
2828         msdos->npages = GUINT16_FROM_LE ((file_offset + (512 - 1)) / 512);
2829         msdos->pe_offset = GUINT32_FROM_LE (sizeof (MonoMSDOSHeader));
2830
2831         header = (MonoDotNetHeader*)(pefile->data + header_start);
2832         header->pesig [0] = 'P';
2833         header->pesig [1] = 'E';
2834         
2835         header->coff.coff_machine = GUINT16_FROM_LE (0x14c);
2836         header->coff.coff_sections = GUINT16_FROM_LE (nsections);
2837         header->coff.coff_time = GUINT32_FROM_LE (time (NULL));
2838         header->coff.coff_opt_header_size = GUINT16_FROM_LE (sizeof (MonoDotNetHeader) - sizeof (MonoCOFFHeader) - 4);
2839         if (assemblyb->pekind == 1) {
2840                 /* it's a dll */
2841                 header->coff.coff_attributes = GUINT16_FROM_LE (0x210e);
2842         } else {
2843                 /* it's an exe */
2844                 header->coff.coff_attributes = GUINT16_FROM_LE (0x010e);
2845         }
2846
2847         virtual_base = 0x400000; /* FIXME: 0x10000000 if a DLL */
2848
2849         header->pe.pe_magic = GUINT16_FROM_LE (0x10B);
2850         header->pe.pe_major = 6;
2851         header->pe.pe_minor = 0;
2852         size = assembly->sections [MONO_SECTION_TEXT].size;
2853         size += FILE_ALIGN - 1;
2854         size &= ~(FILE_ALIGN - 1);
2855         header->pe.pe_code_size = size;
2856         size = assembly->sections [MONO_SECTION_RSRC].size;
2857         size += FILE_ALIGN - 1;
2858         size &= ~(FILE_ALIGN - 1);
2859         header->pe.pe_data_size = size;
2860         g_assert (START_TEXT_RVA == assembly->sections [MONO_SECTION_TEXT].rva);
2861         header->pe.pe_rva_code_base = assembly->sections [MONO_SECTION_TEXT].rva;
2862         header->pe.pe_rva_data_base = assembly->sections [MONO_SECTION_RSRC].rva;
2863         /* pe_rva_entry_point always at the beginning of the text section */
2864         header->pe.pe_rva_entry_point = assembly->sections [MONO_SECTION_TEXT].rva;
2865
2866         header->nt.pe_image_base = GUINT32_FROM_LE (virtual_base);
2867         header->nt.pe_section_align = GUINT32_FROM_LE (VIRT_ALIGN);
2868         header->nt.pe_file_alignment = GUINT32_FROM_LE (FILE_ALIGN);
2869         header->nt.pe_os_major = GUINT16_FROM_LE (4);
2870         header->nt.pe_os_minor = GUINT16_FROM_LE (0);
2871         header->nt.pe_subsys_major = GUINT16_FROM_LE (4);
2872         size = section_start;
2873         size += FILE_ALIGN - 1;
2874         size &= ~(FILE_ALIGN - 1);
2875         header->nt.pe_header_size = GUINT32_FROM_LE (size);
2876         size = image_size;
2877         size += VIRT_ALIGN - 1;
2878         size &= ~(VIRT_ALIGN - 1);
2879         header->nt.pe_image_size = GUINT32_FROM_LE (size);
2880
2881         //
2882         // Translate the PEFileKind value to the value expected by the Windows loader
2883         //
2884         {
2885                 short kind = assemblyb->pekind;
2886
2887                 //
2888                 // PEFileKinds.ConsoleApplication == 2
2889                 // PEFileKinds.WindowApplication == 3
2890                 //
2891                 // need to get:
2892                 //     IMAGE_SUBSYSTEM_WINDOWS_GUI 2 // Image runs in the Windows GUI subsystem.
2893                 //     IMAGE_SUBSYSTEM_WINDOWS_CUI 3 // Image runs in the Windows character subsystem.
2894                 if (kind == 2)
2895                         kind = 3;
2896                 else if (kind == 3)
2897                         kind = 2;
2898                 
2899                 header->nt.pe_subsys_required = GUINT16_FROM_LE (kind);
2900         }    
2901         header->nt.pe_stack_reserve = GUINT32_FROM_LE (0x00100000);
2902         header->nt.pe_stack_commit = GUINT32_FROM_LE (0x00001000);
2903         header->nt.pe_heap_reserve = GUINT32_FROM_LE (0x00100000);
2904         header->nt.pe_heap_commit = GUINT32_FROM_LE (0x00001000);
2905         header->nt.pe_loader_flags = GUINT32_FROM_LE (0);
2906         header->nt.pe_data_dir_count = GUINT32_FROM_LE (16);
2907
2908         /* fill data directory entries */
2909
2910         header->datadir.pe_resource_table.size = GUINT32_FROM_LE (assembly->sections [MONO_SECTION_RSRC].size);
2911         header->datadir.pe_resource_table.rva = GUINT32_FROM_LE (assembly->sections [MONO_SECTION_RSRC].rva);
2912
2913         header->datadir.pe_reloc_table.size = GUINT32_FROM_LE (assembly->sections [MONO_SECTION_RELOC].size);
2914         header->datadir.pe_reloc_table.rva = GUINT32_FROM_LE (assembly->sections [MONO_SECTION_RELOC].rva);
2915
2916         header->datadir.pe_cli_header.size = GUINT32_FROM_LE (72);
2917         header->datadir.pe_cli_header.rva = GUINT32_FROM_LE (assembly->text_rva + assembly->cli_header_offset);
2918         header->datadir.pe_iat.size = GUINT32_FROM_LE (8);
2919         header->datadir.pe_iat.rva = GUINT32_FROM_LE (assembly->text_rva + assembly->iat_offset);
2920         /* patch imported function RVA name */
2921         rva = (guint32*)(assembly->code.data + assembly->iat_offset);
2922         *rva = GUINT32_FROM_LE (assembly->text_rva + assembly->imp_names_offset);
2923
2924         /* the import table */
2925         header->datadir.pe_import_table.size = GUINT32_FROM_LE (79); /* FIXME: magic number? */
2926         header->datadir.pe_import_table.rva = GUINT32_FROM_LE (assembly->text_rva + assembly->idt_offset);
2927         /* patch imported dll RVA name and other entries in the dir */
2928         rva = (guint32*)(assembly->code.data + assembly->idt_offset + G_STRUCT_OFFSET (MonoIDT, name_rva));
2929         *rva = GUINT32_FROM_LE (assembly->text_rva + assembly->imp_names_offset + 12); /* 12 is strlen+1 of func name */
2930         rva = (guint32*)(assembly->code.data + assembly->idt_offset + G_STRUCT_OFFSET (MonoIDT, import_address_table_rva));
2931         *rva = GUINT32_FROM_LE (assembly->text_rva + assembly->iat_offset);
2932         rva = (guint32*)(assembly->code.data + assembly->idt_offset + G_STRUCT_OFFSET (MonoIDT, import_lookup_table));
2933         *rva = GUINT32_FROM_LE (assembly->text_rva + assembly->ilt_offset);
2934
2935         p = (assembly->code.data + assembly->ilt_offset);
2936         value = (assembly->text_rva + assembly->imp_names_offset - 2);
2937         *p++ = (value) & 0xff;
2938         *p++ = (value >> 8) & (0xff);
2939         *p++ = (value >> 16) & (0xff);
2940         *p++ = (value >> 24) & (0xff);
2941
2942         /* the CLI header info */
2943         cli_header = (MonoCLIHeader*)(assembly->code.data + assembly->cli_header_offset);
2944         cli_header->ch_size = GUINT32_FROM_LE (72);
2945         cli_header->ch_runtime_major = GUINT16_FROM_LE (2);
2946         cli_header->ch_flags = GUINT32_FROM_LE (CLI_FLAGS_ILONLY);
2947         if (assemblyb->entry_point) 
2948                 cli_header->ch_entry_point = GUINT32_FROM_LE (assemblyb->entry_point->table_idx | MONO_TOKEN_METHOD_DEF);
2949         else
2950                 cli_header->ch_entry_point = GUINT32_FROM_LE (0);
2951         /* The embedded managed resources */
2952         text_offset = assembly->text_rva + assembly->code.index;
2953         cli_header->ch_resources.rva = GUINT32_FROM_LE (text_offset);
2954         cli_header->ch_resources.size = GUINT32_FROM_LE (assembly->resources.index);
2955         text_offset += assembly->resources.index;
2956         cli_header->ch_metadata.rva = GUINT32_FROM_LE (text_offset);
2957         cli_header->ch_metadata.size = GUINT32_FROM_LE (assembly->meta_size);
2958         text_offset += assembly->meta_size;
2959         if (assembly->strong_name_size) {
2960                 cli_header->ch_strong_name.rva = GUINT32_FROM_LE (text_offset);
2961                 cli_header->ch_strong_name.size = GUINT32_FROM_LE (assembly->strong_name_size);
2962                 text_offset += assembly->strong_name_size;
2963         }
2964
2965         /* write the section tables and section content */
2966         section = (MonoSectionTable*)(pefile->data + section_start);
2967         for (i = 0; i < MONO_SECTION_MAX; ++i) {
2968                 static const char *section_names [] = {
2969                         ".text", ".rsrc", ".reloc"
2970                 };
2971                 if (!assembly->sections [i].size)
2972                         continue;
2973                 strcpy (section->st_name, section_names [i]);
2974                 /*g_print ("output section %s (%d), size: %d\n", section->st_name, i, assembly->sections [i].size);*/
2975                 section->st_virtual_address = GUINT32_FROM_LE (assembly->sections [i].rva);
2976                 section->st_virtual_size = GUINT32_FROM_LE (assembly->sections [i].size);
2977                 section->st_raw_data_size = GUINT32_FROM_LE (GUINT32_TO_LE (section->st_virtual_size) + (FILE_ALIGN - 1));
2978                 section->st_raw_data_size &= GUINT32_FROM_LE (~(FILE_ALIGN - 1));
2979                 section->st_raw_data_ptr = GUINT32_FROM_LE (assembly->sections [i].offset);
2980                 section->st_flags = GUINT32_FROM_LE (assembly->sections [i].attrs);
2981                 switch (i) {
2982                 case MONO_SECTION_TEXT:
2983                         /* patch entry point */
2984                         p = (assembly->code.data + 2);
2985                         value = (virtual_base + assembly->text_rva + assembly->iat_offset);
2986                         *p++ = (value) & 0xff;
2987                         *p++ = (value >> 8) & 0xff;
2988                         *p++ = (value >> 16) & 0xff;
2989                         *p++ = (value >> 24) & 0xff;
2990
2991                         text_offset = assembly->sections [i].offset;
2992                         memcpy (pefile->data + text_offset, assembly->code.data, assembly->code.index);
2993                         text_offset += assembly->code.index;
2994                         memcpy (pefile->data + text_offset, assembly->resources.data, assembly->resources.index);
2995                         text_offset += assembly->resources.index;
2996                         memcpy (pefile->data + text_offset, assembly->assembly.image->raw_metadata, assembly->meta_size);
2997                         text_offset += assembly->meta_size;
2998                         memcpy (pefile->data + text_offset, assembly->strong_name, assembly->strong_name_size);
2999                         break;
3000                 case MONO_SECTION_RELOC:
3001                         rva = (guint32*)(pefile->data + assembly->sections [i].offset);
3002                         *rva = GUINT32_FROM_LE (assembly->text_rva);
3003                         ++rva;
3004                         *rva = GUINT32_FROM_LE (12);
3005                         ++rva;
3006                         data16 = (guint16*)rva;
3007                         /* 
3008                          * the entrypoint is always at the start of the text section 
3009                          * 3 is IMAGE_REL_BASED_HIGHLOW
3010                          * 2 is patch_size_rva - text_rva
3011                          */
3012                         *data16 = GUINT16_FROM_LE ((3 << 12) + (2));
3013                         data16++;
3014                         *data16 = 0; /* terminate */
3015                         break;
3016                 case MONO_SECTION_RSRC:
3017                 default:
3018                         g_assert_not_reached ();
3019                 }
3020                 section++;
3021         }
3022         
3023         /* check that the file is properly padded */
3024 #if 0
3025         {
3026                 FILE *f = fopen ("mypetest.exe", "w");
3027                 fwrite (pefile->data, pefile->index, 1, f);
3028                 fclose (f);
3029         }
3030 #endif
3031 }
3032
3033 /*
3034  * We need to return always the same object for MethodInfo, FieldInfo etc..
3035  * but we need to consider the reflected type.
3036  * type uses a different hash, since it uses custom hash/equal functions.
3037  */
3038
3039 typedef struct {
3040         gpointer item;
3041         MonoClass *refclass;
3042 } ReflectedEntry;
3043
3044 static gboolean
3045 reflected_equal (gconstpointer a, gconstpointer b) {
3046         const ReflectedEntry *ea = a;
3047         const ReflectedEntry *eb = b;
3048
3049         return (ea->item == eb->item) && (ea->refclass == eb->refclass);
3050 }
3051
3052 static guint
3053 reflected_hash (gconstpointer a) {
3054         const ReflectedEntry *ea = a;
3055         return GPOINTER_TO_UINT (ea->item);
3056 }
3057
3058 #define CHECK_OBJECT(t,p,k)     \
3059         do {    \
3060                 t _obj; \
3061                 ReflectedEntry e;       \
3062                 e.item = (p);   \
3063                 e.refclass = (k);       \
3064                 mono_domain_lock (domain);      \
3065                 if (!domain->refobject_hash)    \
3066                         domain->refobject_hash = mono_g_hash_table_new (reflected_hash, reflected_equal);       \
3067                 if ((_obj = mono_g_hash_table_lookup (domain->refobject_hash, &e))) {   \
3068                         mono_domain_unlock (domain);    \
3069                         return _obj;    \
3070                 }       \
3071         } while (0)
3072
3073 #if HAVE_BOEHM_GC
3074 #define ALLOC_REFENTRY GC_MALLOC (sizeof (ReflectedEntry))
3075 #else
3076 #define ALLOC_REFENTRY mono_mempool_alloc (domain->mp, sizeof (ReflectedEntry))
3077 #endif
3078
3079 #define CACHE_OBJECT(p,o,k)     \
3080         do {    \
3081                 ReflectedEntry *e = ALLOC_REFENTRY;     \
3082                 e->item = (p);  \
3083                 e->refclass = (k);      \
3084                 mono_g_hash_table_insert (domain->refobject_hash, e,o); \
3085                 mono_domain_unlock (domain);    \
3086         } while (0)
3087
3088 static void 
3089 register_assembly (MonoDomain *domain, MonoReflectionAssembly *res, MonoAssembly *assembly)
3090 {
3091         /* this is done only once */
3092         mono_domain_lock (domain);
3093         CACHE_OBJECT (assembly, res, NULL);
3094 }
3095
3096 static void
3097 register_module (MonoDomain *domain, MonoReflectionModuleBuilder *res, MonoImage *module)
3098 {
3099         /* this is done only once */
3100         mono_domain_lock (domain);
3101         CACHE_OBJECT (module, res, NULL);
3102 }
3103
3104 void
3105 mono_image_module_basic_init (MonoReflectionModuleBuilder *moduleb)
3106 {
3107         MonoImage *image = moduleb->module.image;
3108         MonoReflectionAssemblyBuilder *ab = moduleb->assemblyb;
3109         if (!image) {
3110                 if (!ab->modules) {
3111                         /* a MonoImage was already created in mono_image_basic_init () */
3112                         image = ab->dynamic_assembly->assembly.image;
3113                 } else {
3114                         image = create_dynamic_mono_image (mono_string_to_utf8 (ab->name), mono_string_to_utf8 (moduleb->module.name));
3115                 }
3116                 moduleb->module.image = image;
3117                 register_module (mono_object_domain (moduleb), moduleb, image);
3118         }
3119 }
3120
3121 /*
3122  * mono_assembly_get_object:
3123  * @domain: an app domain
3124  * @assembly: an assembly
3125  *
3126  * Return an System.Reflection.Assembly object representing the MonoAssembly @assembly.
3127  */
3128 MonoReflectionAssembly*
3129 mono_assembly_get_object (MonoDomain *domain, MonoAssembly *assembly)
3130 {
3131         static MonoClass *System_Reflection_Assembly;
3132         MonoReflectionAssembly *res;
3133         
3134         CHECK_OBJECT (MonoReflectionAssembly *, assembly, NULL);
3135         if (!System_Reflection_Assembly)
3136                 System_Reflection_Assembly = mono_class_from_name (
3137                         mono_defaults.corlib, "System.Reflection", "Assembly");
3138         res = (MonoReflectionAssembly *)mono_object_new (domain, System_Reflection_Assembly);
3139         res->assembly = assembly;
3140         CACHE_OBJECT (assembly, res, NULL);
3141         return res;
3142 }
3143
3144
3145 MonoReflectionModule*   
3146 mono_module_get_object   (MonoDomain *domain, MonoImage *image)
3147 {
3148         static MonoClass *System_Reflection_Module;
3149         MonoReflectionModule *res;
3150         
3151         CHECK_OBJECT (MonoReflectionModule *, image, NULL);
3152         if (!System_Reflection_Module)
3153                 System_Reflection_Module = mono_class_from_name (
3154                         mono_defaults.corlib, "System.Reflection", "Module");
3155         res = (MonoReflectionModule *)mono_object_new (domain, System_Reflection_Module);
3156
3157         res->image = image;
3158         res->assembly = (MonoReflectionAssembly *) mono_assembly_get_object(domain, image->assembly);
3159
3160         res->fqname    = mono_string_new (domain, image->name);
3161         res->name      = mono_string_new (domain, image->name);
3162         res->scopename = mono_string_new (domain, image->module_name);
3163
3164         CACHE_OBJECT (image, res, NULL);
3165         return res;
3166 }
3167
3168
3169 static gboolean
3170 mymono_metadata_type_equal (MonoType *t1, MonoType *t2)
3171 {
3172         if ((t1->type != t2->type) ||
3173             (t1->byref != t2->byref))
3174                 return FALSE;
3175
3176         switch (t1->type) {
3177         case MONO_TYPE_VOID:
3178         case MONO_TYPE_BOOLEAN:
3179         case MONO_TYPE_CHAR:
3180         case MONO_TYPE_I1:
3181         case MONO_TYPE_U1:
3182         case MONO_TYPE_I2:
3183         case MONO_TYPE_U2:
3184         case MONO_TYPE_I4:
3185         case MONO_TYPE_U4:
3186         case MONO_TYPE_I8:
3187         case MONO_TYPE_U8:
3188         case MONO_TYPE_R4:
3189         case MONO_TYPE_R8:
3190         case MONO_TYPE_STRING:
3191         case MONO_TYPE_I:
3192         case MONO_TYPE_U:
3193         case MONO_TYPE_OBJECT:
3194         case MONO_TYPE_TYPEDBYREF:
3195                 return TRUE;
3196         case MONO_TYPE_VALUETYPE:
3197         case MONO_TYPE_CLASS:
3198                 return t1->data.klass == t2->data.klass;
3199         case MONO_TYPE_PTR:
3200                 return mymono_metadata_type_equal (t1->data.type, t2->data.type);
3201         case MONO_TYPE_SZARRAY:
3202 retry_sz:
3203                 if (t1->data.type->type != t2->data.type->type)
3204                         return FALSE;
3205                 if (t1->data.type->type == MONO_TYPE_CLASS || t1->data.type->type == MONO_TYPE_VALUETYPE)
3206                         return t1->data.type->data.klass == t2->data.type->data.klass;
3207                 if (t1->data.type->type == MONO_TYPE_SZARRAY) {
3208                         t1 = t1->data.type;
3209                         t2 = t2->data.type;
3210                         goto retry_sz;
3211                 }
3212                 return mymono_metadata_type_equal (t1->data.type, t2->data.type);
3213         case MONO_TYPE_ARRAY:
3214                 if (t1->data.array->rank != t2->data.array->rank)
3215                         return FALSE;
3216                 return mymono_metadata_type_equal (t1->data.array->type, t2->data.array->type);
3217         default:
3218                 g_error ("implement type compare for %0x!", t1->type);
3219                 return FALSE;
3220         }
3221
3222         return FALSE;
3223 }
3224
3225 static guint
3226 mymono_metadata_type_hash (MonoType *t1)
3227 {
3228         guint hash;
3229
3230         hash = t1->type;
3231
3232         hash |= t1->byref << 6; /* do not collide with t1->type values */
3233         switch (t1->type) {
3234         case MONO_TYPE_VALUETYPE:
3235         case MONO_TYPE_CLASS:
3236                 /* check if the distribution is good enough */
3237                 return ((hash << 5) - hash) ^ g_str_hash (t1->data.klass->name);
3238         case MONO_TYPE_PTR:
3239         case MONO_TYPE_SZARRAY:
3240                 return ((hash << 5) - hash) ^ mymono_metadata_type_hash (t1->data.type);
3241         }
3242         return hash;
3243 }
3244
3245 /*
3246  * mono_type_get_object:
3247  * @domain: an app domain
3248  * @type: a type
3249  *
3250  * Return an System.MonoType object representing the type @type.
3251  */
3252 MonoReflectionType*
3253 mono_type_get_object (MonoDomain *domain, MonoType *type)
3254 {
3255         MonoReflectionType *res;
3256         MonoClass *klass = mono_class_from_mono_type (type);
3257
3258         mono_domain_lock (domain);
3259         if (!domain->type_hash)
3260                 domain->type_hash = mono_g_hash_table_new ((GHashFunc)mymono_metadata_type_hash, 
3261                                 (GCompareFunc)mymono_metadata_type_equal);
3262         if ((res = mono_g_hash_table_lookup (domain->type_hash, type))) {
3263                 mono_domain_unlock (domain);
3264                 return res;
3265         }
3266         if (klass->reflection_info && !klass->wastypebuilder) {
3267                 //g_assert_not_reached ();
3268                 /* should this be considered an error condition? */
3269                 if (!type->byref) {
3270                         mono_domain_unlock (domain);
3271                         return klass->reflection_info;
3272                 }
3273         }
3274         mono_class_init (klass);
3275         res = (MonoReflectionType *)mono_object_new (domain, mono_defaults.monotype_class);
3276         res->type = type;
3277         mono_g_hash_table_insert (domain->type_hash, type, res);
3278         mono_domain_unlock (domain);
3279         return res;
3280 }
3281
3282 /*
3283  * mono_method_get_object:
3284  * @domain: an app domain
3285  * @method: a method
3286  * @refclass: the reflected type (can be NULL)
3287  *
3288  * Return an System.Reflection.MonoMethod object representing the method @method.
3289  */
3290 MonoReflectionMethod*
3291 mono_method_get_object (MonoDomain *domain, MonoMethod *method, MonoClass *refclass)
3292 {
3293         /*
3294          * We use the same C representation for methods and constructors, but the type 
3295          * name in C# is different.
3296          */
3297         const char *cname;
3298         MonoClass *klass;
3299         MonoReflectionMethod *ret;
3300
3301         if (!refclass)
3302                 refclass = method->klass;
3303
3304         CHECK_OBJECT (MonoReflectionMethod *, method, refclass);
3305         if (*method->name == '.' && (strcmp (method->name, ".ctor") == 0 || strcmp (method->name, ".cctor") == 0))
3306                 cname = "MonoCMethod";
3307         else
3308                 cname = "MonoMethod";
3309         klass = mono_class_from_name (mono_defaults.corlib, "System.Reflection", cname);
3310
3311         ret = (MonoReflectionMethod*)mono_object_new (domain, klass);
3312         ret->method = method;
3313         ret->name = mono_string_new (domain, method->name);
3314         ret->reftype = mono_type_get_object (domain, &refclass->byval_arg);
3315         CACHE_OBJECT (method, ret, refclass);
3316         return ret;
3317 }
3318
3319 /*
3320  * mono_field_get_object:
3321  * @domain: an app domain
3322  * @klass: a type
3323  * @field: a field
3324  *
3325  * Return an System.Reflection.MonoField object representing the field @field
3326  * in class @klass.
3327  */
3328 MonoReflectionField*
3329 mono_field_get_object (MonoDomain *domain, MonoClass *klass, MonoClassField *field)
3330 {
3331         MonoReflectionField *res;
3332         MonoClass *oklass;
3333
3334         CHECK_OBJECT (MonoReflectionField *, field, klass);
3335         oklass = mono_class_from_name (mono_defaults.corlib, "System.Reflection", "MonoField");
3336         res = (MonoReflectionField *)mono_object_new (domain, oklass);
3337         res->klass = klass;
3338         res->field = field;
3339         CACHE_OBJECT (field, res, klass);
3340         return res;
3341 }
3342
3343 /*
3344  * mono_property_get_object:
3345  * @domain: an app domain
3346  * @klass: a type
3347  * @property: a property
3348  *
3349  * Return an System.Reflection.MonoProperty object representing the property @property
3350  * in class @klass.
3351  */
3352 MonoReflectionProperty*
3353 mono_property_get_object (MonoDomain *domain, MonoClass *klass, MonoProperty *property)
3354 {
3355         MonoReflectionProperty *res;
3356         MonoClass *oklass;
3357
3358         CHECK_OBJECT (MonoReflectionProperty *, property, klass);
3359         oklass = mono_class_from_name (mono_defaults.corlib, "System.Reflection", "MonoProperty");
3360         res = (MonoReflectionProperty *)mono_object_new (domain, oklass);
3361         res->klass = klass;
3362         res->property = property;
3363         CACHE_OBJECT (property, res, klass);
3364         return res;
3365 }
3366
3367 /*
3368  * mono_event_get_object:
3369  * @domain: an app domain
3370  * @klass: a type
3371  * @event: a event
3372  *
3373  * Return an System.Reflection.MonoEvent object representing the event @event
3374  * in class @klass.
3375  */
3376 MonoReflectionEvent*
3377 mono_event_get_object (MonoDomain *domain, MonoClass *klass, MonoEvent *event)
3378 {
3379         MonoReflectionEvent *res;
3380         MonoClass *oklass;
3381
3382         CHECK_OBJECT (MonoReflectionEvent *, event, klass);
3383         oklass = mono_class_from_name (mono_defaults.corlib, "System.Reflection", "MonoEvent");
3384         res = (MonoReflectionEvent *)mono_object_new (domain, oklass);
3385         res->klass = klass;
3386         res->event = event;
3387         CACHE_OBJECT (event, res, klass);
3388         return res;
3389 }
3390
3391 /*
3392  * mono_param_get_objects:
3393  * @domain: an app domain
3394  * @method: a method
3395  *
3396  * Return an System.Reflection.ParameterInfo array object representing the parameters
3397  * in the method @method.
3398  */
3399 MonoReflectionParameter**
3400 mono_param_get_objects (MonoDomain *domain, MonoMethod *method)
3401 {
3402         MonoReflectionParameter **res;
3403         MonoReflectionMethod *member;
3404         MonoClass *oklass;
3405         char **names;
3406         int i;
3407
3408         if (!method->signature->param_count)
3409                 return NULL;
3410
3411         member = mono_method_get_object (domain, method, NULL);
3412         names = g_new (char *, method->signature->param_count);
3413         mono_method_get_param_names (method, (const char **) names);
3414         
3415         /* Note: the cache is based on the address of the signature into the method
3416          * since we already cache MethodInfos with the method as keys.
3417          */
3418         CHECK_OBJECT (MonoReflectionParameter**, &(method->signature), NULL);
3419         oklass = mono_class_from_name (mono_defaults.corlib, "System.Reflection", "ParameterInfo");
3420 #if HAVE_BOEHM_GC
3421         res = GC_MALLOC (sizeof (MonoReflectionParameter*) * method->signature->param_count);
3422 #else
3423         res = g_new0 (MonoReflectionParameter*, method->signature->param_count);
3424 #endif
3425         for (i = 0; i < method->signature->param_count; ++i) {
3426                 res [i] = (MonoReflectionParameter *)mono_object_new (domain, oklass);
3427                 res [i]->ClassImpl = mono_type_get_object (domain, method->signature->params [i]);
3428                 res [i]->DefaultValueImpl = NULL; /* FIXME */
3429                 res [i]->MemberImpl = (MonoObject*)member;
3430                 res [i]->NameImpl = mono_string_new (domain, names [i]);
3431                 res [i]->PositionImpl = i + 1;
3432                 res [i]->AttrsImpl = method->signature->params [i]->attrs;
3433         }
3434         g_free (names);
3435         CACHE_OBJECT (&(method->signature), res, NULL);
3436         return res;
3437 }
3438
3439 static int
3440 assembly_name_to_aname (MonoAssemblyName *assembly, char *p) {
3441         int found_sep;
3442         char *s;
3443
3444         memset (assembly, 0, sizeof (MonoAssemblyName));
3445         assembly->name = p;
3446         assembly->culture = "";
3447         
3448         while (*p && (isalnum (*p) || *p == '.'))
3449                 p++;
3450         found_sep = 0;
3451         while (*p == ' ' || *p == ',') {
3452                 *p++ = 0;
3453                 found_sep = 1;
3454                 continue;
3455         }
3456         /* failed */
3457         if (!found_sep)
3458                 return 1;
3459         while (*p) {
3460                 if (*p == 'V' && strncmp (p, "Version=", 8) == 0) {
3461                         p += 8;
3462                         assembly->major = strtoul (p, &s, 10);
3463                         if (s == p || *s != '.')
3464                                 return 1;
3465                         p = ++s;
3466                         assembly->minor = strtoul (p, &s, 10);
3467                         if (s == p || *s != '.')
3468                                 return 1;
3469                         p = ++s;
3470                         assembly->build = strtoul (p, &s, 10);
3471                         if (s == p || *s != '.')
3472                                 return 1;
3473                         p = ++s;
3474                         assembly->revision = strtoul (p, &s, 10);
3475                         if (s == p)
3476                                 return 1;
3477                 } else if (*p == 'C' && strncmp (p, "Culture=", 8) == 0) {
3478                         p += 8;
3479                         if (strncmp (p, "neutral", 7) == 0) {
3480                                 assembly->culture = "";
3481                                 p += 7;
3482                         } else {
3483                                 assembly->culture = p;
3484                                 while (*p && *p != ',') {
3485                                         p++;
3486                                 }
3487                         }
3488                 } else if (*p == 'P' && strncmp (p, "PublicKeyToken=", 15) == 0) {
3489                         p += 15;
3490                         s = p;
3491                         while (*s && isxdigit (*s)) {
3492                                 *s = tolower (*s);
3493                                 s++;
3494                         }
3495                         assembly->hash_len = s - p;
3496                         if (!(s-p) || ((s-p) & 1))
3497                                 return 1;
3498                         assembly->hash_value = s = p;
3499                         while (*s && isxdigit (*s)) {
3500                                 int val;
3501                                 val = *s >= '0' && *s <= '9'? *s - '0': *s - 'a' + 10;
3502                                 s++;
3503                                 *p = val << 4;
3504                                 *p |= *s >= '0' && *s <= '9'? *s - '0': *s - 'a' + 10;
3505                                 p++;
3506                         }
3507                         p = s;
3508                 } else {
3509                         while (*p && *p != ',')
3510                                 p++;
3511                 }
3512                 found_sep = 0;
3513                 while (*p == ' ' || *p == ',') {
3514                         *p++ = 0;
3515                         found_sep = 1;
3516                         continue;
3517                 }
3518                 /* failed */
3519                 if (!found_sep)
3520                         return 1;
3521         }
3522
3523         return 0;
3524 }
3525
3526 /*
3527  * mono_reflection_parse_type:
3528  * @name: type name
3529  *
3530  * Parse a type name as accepted by the GetType () method and output the info
3531  * extracted in the info structure.
3532  * the name param will be mangled, so, make a copy before passing it to this function.
3533  * The fields in info will be valid until the memory pointed to by name is valid.
3534  * Returns 0 on parse error.
3535  * See also mono_type_get_name () below.
3536  */
3537 int
3538 mono_reflection_parse_type (char *name, MonoTypeNameParse *info) {
3539
3540         char *start, *p, *w, *last_point, *startn;
3541         int in_modifiers = 0;
3542         int isbyref = 0, rank;
3543
3544         start = p = w = name;
3545
3546         memset (&info->assembly, 0, sizeof (MonoAssemblyName));
3547         info->name = info->name_space = NULL;
3548         info->nested = NULL;
3549         info->modifiers = NULL;
3550
3551         /* last_point separates the namespace from the name */
3552         last_point = NULL;
3553
3554         while (*p) {
3555                 switch (*p) {
3556                 case '+':
3557                         *p = 0; /* NULL terminate the name */
3558                         startn = p + 1;
3559                         /* we have parsed the nesting namespace + name */
3560                         if (info->name) {
3561                                 info->nested = g_list_append (info->nested, startn);
3562                                 break;
3563                         }
3564                         if (last_point) {
3565                                 info->name_space = start;
3566                                 *last_point = 0;
3567                                 info->name = last_point + 1;
3568                         } else {
3569                                 info->name_space = (char *)"";
3570                                 info->name = start;
3571                         }
3572                         break;
3573                 case '.':
3574                         last_point = w;
3575                         break;
3576                 case '\\':
3577                         ++p;
3578                         break;
3579                 case '&':
3580                 case '*':
3581                 case '[':
3582                 case ',':
3583                         in_modifiers = 1;
3584                         break;
3585                 default:
3586                         break;
3587                 }
3588                 if (in_modifiers)
3589                         break;
3590                 *w++ = *p++;
3591         }
3592         
3593         if (info->name) {
3594                 info->nested = g_list_append (info->nested, startn);
3595         } else {
3596                 if (last_point) {
3597                         info->name_space = start;
3598                         *last_point = 0;
3599                         info->name = last_point + 1;
3600                 } else {
3601                         info->name_space = (char *)"";
3602                         info->name = start;
3603                 }
3604         }
3605         while (*p) {
3606                 switch (*p) {
3607                 case '&':
3608                         if (isbyref) /* only one level allowed by the spec */
3609                                 return 0;
3610                         isbyref = 1;
3611                         info->modifiers = g_list_append (info->modifiers, GUINT_TO_POINTER (0));
3612                         *p++ = 0;
3613                         break;
3614                 case '*':
3615                         info->modifiers = g_list_append (info->modifiers, GUINT_TO_POINTER (-1));
3616                         *p++ = 0;
3617                         break;
3618                 case '[':
3619                         rank = 1;
3620                         *p++ = 0;
3621                         while (*p) {
3622                                 if (*p == ']')
3623                                         break;
3624                                 if (*p == ',')
3625                                         rank++;
3626                                 else if (*p != '*') /* '*' means unknown lower bound */
3627                                         return 0;
3628                                 ++p;
3629                         }
3630                         if (*p++ != ']')
3631                                 return 0;
3632                         info->modifiers = g_list_append (info->modifiers, GUINT_TO_POINTER (rank));
3633                         break;
3634                 case ',':
3635                         *p++ = 0;
3636                         while (*p) {
3637                                 if (*p == ' ') {
3638                                         ++p;
3639                                         continue;
3640                                 }
3641                                 break;
3642                         }
3643                         if (!*p)
3644                                 return 0; /* missing assembly name */
3645                         if (!assembly_name_to_aname (&info->assembly, p))
3646                                 return 0;
3647                         break;
3648                 default:
3649                         break;
3650                 }
3651                 if (info->assembly.name)
3652                         break;
3653         }
3654         *w = 0; /* terminate class name */
3655         if (!info->name || !*info->name)
3656                 return 0;
3657         /* add other consistency checks */
3658         return 1;
3659 }
3660
3661 static void
3662 mono_type_get_name_recurse (MonoType *type, GString *str)
3663 {
3664         MonoClass *klass;
3665         
3666         switch (type->type) {
3667         case MONO_TYPE_ARRAY: {
3668                 int i, rank = type->data.array->rank;
3669
3670                 mono_type_get_name_recurse (type->data.array->type, str);
3671                 g_string_append_c (str, '[');
3672                 for (i = 1; i < rank; i++)
3673                         g_string_append_c (str, ',');
3674                 g_string_append_c (str, ']');
3675                 break;
3676         }
3677         case MONO_TYPE_SZARRAY:
3678                 mono_type_get_name_recurse (type->data.type, str);
3679                 g_string_append (str, "[]");
3680                 break;
3681         case MONO_TYPE_PTR:
3682                 mono_type_get_name_recurse (type->data.type, str);
3683                 g_string_append_c (str, '*');
3684                 break;
3685         default:
3686                 klass = mono_class_from_mono_type (type);
3687                 if (klass->nested_in) {
3688                         mono_type_get_name_recurse (&klass->nested_in->byval_arg, str);
3689                         g_string_append_c (str, '+');
3690                 }
3691                 if (*klass->name_space) {
3692                         g_string_append (str, klass->name_space);
3693                         g_string_append_c (str, '.');
3694                 }
3695                 g_string_append (str, klass->name);
3696                 break;
3697         }
3698 }
3699
3700 /*
3701  * mono_type_get_name:
3702  * @type: a type
3703  *
3704  * Returns the string representation for type as required by System.Reflection.
3705  * The inverse of mono_reflection_parse_type ().
3706  */
3707 char*
3708 mono_type_get_name (MonoType *type)
3709 {
3710         GString* result = g_string_new ("");
3711         mono_type_get_name_recurse (type, result);
3712
3713         if (type->byref)
3714                 g_string_append_c (result, '&');
3715
3716         return g_string_free (result, FALSE);
3717 }
3718
3719 /*
3720  * mono_reflection_get_type:
3721  * @image: a metadata context
3722  * @info: type description structure
3723  * @ignorecase: flag for case-insensitive string compares
3724  *
3725  * Build a MonoType from the type description in @info.
3726  * 
3727  */
3728 MonoType*
3729 mono_reflection_get_type (MonoImage* image, MonoTypeNameParse *info, gboolean ignorecase)
3730 {
3731         MonoClass *klass;
3732         GList *mod;
3733         int modval;
3734         
3735         if (!image)
3736                 image = mono_defaults.corlib;
3737
3738         if (ignorecase)
3739                 klass = mono_class_from_name_case (image, info->name_space, info->name);
3740         else
3741                 klass = mono_class_from_name (image, info->name_space, info->name);
3742         if (!klass)
3743                 return NULL;
3744         for (mod = info->nested; mod; mod = mod->next) {
3745                 GList *nested;
3746
3747                 mono_class_init (klass);
3748                 nested = klass->nested_classes;
3749                 klass = NULL;
3750                 while (nested) {
3751                         klass = nested->data;
3752                         if (ignorecase) {
3753                                 if (g_strcasecmp (klass->name, mod->data) == 0)
3754                                         break;
3755                         } else {
3756                                 if (strcmp (klass->name, mod->data) == 0)
3757                                         break;
3758                         }
3759                         klass = NULL;
3760                         nested = nested->next;
3761                 }
3762                 if (!klass)
3763                         break;
3764         }
3765         if (!klass)
3766                 return NULL;
3767         mono_class_init (klass);
3768         for (mod = info->modifiers; mod; mod = mod->next) {
3769                 modval = GPOINTER_TO_UINT (mod->data);
3770                 if (!modval) { /* byref: must be last modifier */
3771                         return &klass->this_arg;
3772                 } else if (modval == -1) {
3773                         klass = mono_ptr_class_get (&klass->byval_arg);
3774                 } else { /* array rank */
3775                         klass = mono_array_class_get (&klass->byval_arg, modval);
3776                 }
3777                 mono_class_init (klass);
3778         }
3779         return &klass->byval_arg;
3780 }
3781
3782 /*
3783  * mono_reflection_type_from_name:
3784  * @name: type name.
3785  * @image: a metadata context (can be NULL).
3786  *
3787  * Retrieves a MonoType from its @name. If the name is not fully qualified,
3788  * it defaults to get the type from @image or, if @image is NULL or loading
3789  * from it fails, uses corlib.
3790  * 
3791  */
3792 MonoType*
3793 mono_reflection_type_from_name (char *name, MonoImage *image)
3794 {
3795         MonoType *type;
3796         MonoTypeNameParse info;
3797         
3798         /*g_print ("requested type %s\n", str);*/
3799         if (!mono_reflection_parse_type (name, &info)) {
3800                 g_list_free (info.modifiers);
3801                 g_list_free (info.nested);
3802                 return NULL;
3803         }
3804
3805         if (info.assembly.name) {
3806                 image = mono_image_loaded (info.assembly.name);
3807                 /* do we need to load if it's not already loaded? */
3808                 if (!image) {
3809                         g_list_free (info.modifiers);
3810                         g_list_free (info.nested);
3811                         return NULL;
3812                 }
3813         } else if (image == NULL) {
3814                 image = mono_defaults.corlib;
3815         }
3816
3817         type = mono_reflection_get_type (image, &info, FALSE);
3818         if (type == NULL && !info.assembly.name && image != mono_defaults.corlib) {
3819                 image = mono_defaults.corlib;
3820                 type = mono_reflection_get_type (image, &info, FALSE);
3821         }
3822         
3823         g_list_free (info.modifiers);
3824         g_list_free (info.nested);
3825         return type;
3826 }
3827
3828 static void*
3829 load_cattr_value (MonoImage *image, MonoType *t, const char *p, const char **end)
3830 {
3831         int slen, type = t->type;
3832 handle_enum:
3833         switch (type) {
3834         case MONO_TYPE_U1:
3835         case MONO_TYPE_I1:
3836         case MONO_TYPE_BOOLEAN: {
3837                 MonoBoolean *bval = g_malloc (sizeof (MonoBoolean));
3838                 *bval = *p;
3839                 *end = p + 1;
3840                 return bval;
3841         }
3842         case MONO_TYPE_CHAR:
3843         case MONO_TYPE_U2:
3844         case MONO_TYPE_I2: {
3845                 guint16 *val = g_malloc (sizeof (guint16));
3846                 *val = read16 (p);
3847                 *end = p + 2;
3848                 return val;
3849         }
3850 #if SIZEOF_VOID_P == 4
3851         case MONO_TYPE_U:
3852         case MONO_TYPE_I:
3853 #endif
3854         case MONO_TYPE_R4:
3855         case MONO_TYPE_U4:
3856         case MONO_TYPE_I4: {
3857                 guint32 *val = g_malloc (sizeof (guint32));
3858                 *val = read32 (p);
3859                 *end = p + 4;
3860                 return val;
3861         }
3862 #if SIZEOF_VOID_P == 8
3863         case MONO_TYPE_U: /* error out instead? this should probably not happen */
3864         case MONO_TYPE_I:
3865 #endif
3866         case MONO_TYPE_R8:
3867         case MONO_TYPE_U8:
3868         case MONO_TYPE_I8: {
3869                 guint64 *val = g_malloc (sizeof (guint64));
3870                 *val = read64 (p);
3871                 *end = p + 8;
3872                 return val;
3873         }
3874         case MONO_TYPE_VALUETYPE:
3875                 if (t->data.klass->enumtype) {
3876                         type = t->data.klass->enum_basetype->type;
3877                         goto handle_enum;
3878                 } else {
3879                         g_error ("generic valutype %s not handled in custom attr value decoding", t->data.klass->name);
3880                 }
3881                 break;
3882         case MONO_TYPE_STRING:
3883                 if (*p == (char)0xFF) {
3884                         *end = p + 1;
3885                         return NULL;
3886                 }
3887                 slen = mono_metadata_decode_value (p, &p);
3888                 *end = p + slen;
3889                 return mono_string_new_len (mono_domain_get (), p, slen);
3890         case MONO_TYPE_CLASS: {
3891                 char *n;
3892                 MonoType *t;
3893 handle_type:
3894                 slen = mono_metadata_decode_value (p, &p);
3895                 n = g_memdup (p, slen + 1);
3896                 n [slen] = 0;
3897                 t = mono_reflection_type_from_name (n, image);
3898                 if (!t)
3899                         g_warning ("Cannot load type '%s'", n);
3900                 g_free (n);
3901                 *end = p + slen;
3902                 return mono_type_get_object (mono_domain_get (), t);
3903         }
3904         case MONO_TYPE_OBJECT: {
3905                 char subt = *p++;
3906                 MonoObject *obj;
3907                 MonoClass *subc;
3908                 void *val;
3909
3910                 if (subt == 0x50) {
3911                         goto handle_type;
3912                 } else if (subt == 0x55) {
3913                         char *n;
3914                         MonoType *t;
3915                         slen = mono_metadata_decode_value (p, &p);
3916                         n = g_memdup (p, slen + 1);
3917                         n [slen] = 0;
3918                         t = mono_reflection_type_from_name (n, image);
3919                         if (!t)
3920                                 g_warning ("Cannot load type '%s'", n);
3921                         g_free (n);
3922                         p += slen;
3923                         subc = mono_class_from_mono_type (t);
3924                 } else if (subt >= MONO_TYPE_BOOLEAN && subt <= MONO_TYPE_R8) {
3925                         MonoType simple_type = {{0}};
3926                         simple_type.type = subt;
3927                         subc = mono_class_from_mono_type (&simple_type);
3928                 } else {
3929                         g_error ("Unknown type 0x%02x for object type encoding in custom attr", subt);
3930                 }
3931                 val = load_cattr_value (image, &subc->byval_arg, p, end);
3932                 obj = mono_object_new (mono_domain_get (), subc);
3933                 memcpy ((char*)obj + sizeof (MonoObject), val, mono_class_value_size (subc, NULL));
3934                 g_free (val);
3935                 return obj;
3936         }
3937         case MONO_TYPE_SZARRAY:
3938         {
3939                 MonoArray *arr;
3940                 guint32 i,alen;
3941                 alen=read32(p);
3942                 p+=4;
3943                 arr=mono_array_new(mono_domain_get(),mono_class_from_mono_type(t->data.type),alen);
3944                 switch (t->data.type->type)
3945                 {
3946                         case MONO_TYPE_U1:
3947                         case MONO_TYPE_I1:
3948                         case MONO_TYPE_BOOLEAN:
3949                                 for (i=0;i<alen;i++)
3950                                 {
3951                                         MonoBoolean val=*p++;
3952                                         mono_array_set(arr,MonoBoolean,i,val);
3953                                 }
3954                                 break;
3955                         case MONO_TYPE_CHAR:
3956                         case MONO_TYPE_U2:
3957                         case MONO_TYPE_I2:
3958                                 for (i=0;i<alen;i++)
3959                                 {
3960                                         guint16 val=read16(p);
3961                                         mono_array_set(arr,guint16,i,val);
3962                                         p+=2;
3963                                 }
3964                                 break;
3965                         case MONO_TYPE_R4:
3966                         case MONO_TYPE_U4:
3967                         case MONO_TYPE_I4:
3968                                 for (i=0;i<alen;i++)
3969                                 {
3970                                         guint32 val=read32(p);
3971                                         mono_array_set(arr,guint32,i,val);
3972                                         p+=4;
3973                                 }
3974                                 break;
3975                         case MONO_TYPE_R8:
3976                         case MONO_TYPE_U8:
3977                         case MONO_TYPE_I8:
3978                                 for (i=0;i<alen;i++)
3979                                 {
3980                                         guint64 val=read64(p);
3981                                         mono_array_set(arr,guint64,i,val);
3982                                         p+=8;
3983                                 }
3984                                 break;
3985                         case MONO_TYPE_STRING:
3986                                 for (i=0;i<alen;i++)
3987                                 {
3988                                         if (*p==(char)0xff)
3989                                         {
3990                                                 mono_array_set(arr,gpointer,i,NULL);
3991                                                 p++;
3992                                         }
3993                                         else
3994                                         {
3995                                                 slen=mono_metadata_decode_value(p,&p);
3996                                                 mono_array_set(arr,gpointer,i,mono_string_new_len(mono_domain_get(),p,slen));
3997                                                 p+=slen;
3998                                         }
3999                                 }
4000                                 break;
4001                         default:
4002                                 g_error("Type 0x%02x not handled in custom attr array decoding",t->data.type->type);
4003                 }
4004                 *end=p;
4005                 return arr;
4006         }
4007         default:
4008                 g_error ("Type 0x%02x not handled in custom attr value decoding", type);
4009         }
4010         return NULL;
4011 }
4012
4013 static gboolean
4014 type_is_reference (MonoType *type)
4015 {
4016         switch (type->type) {
4017         case MONO_TYPE_BOOLEAN:
4018         case MONO_TYPE_CHAR:
4019         case MONO_TYPE_U:
4020         case MONO_TYPE_I:
4021         case MONO_TYPE_U1:
4022         case MONO_TYPE_I1:
4023         case MONO_TYPE_U2:
4024         case MONO_TYPE_I2:
4025         case MONO_TYPE_U4:
4026         case MONO_TYPE_I4:
4027         case MONO_TYPE_U8:
4028         case MONO_TYPE_I8:
4029         case MONO_TYPE_R8:
4030         case MONO_TYPE_R4:
4031         case MONO_TYPE_VALUETYPE:
4032                 return FALSE;
4033         default:
4034                 return TRUE;
4035         }
4036 }
4037
4038 static void
4039 free_param_data (MonoMethodSignature *sig, void **params) {
4040         int i;
4041         for (i = 0; i < sig->param_count; ++i) {
4042                 if (!type_is_reference (sig->params [i]))
4043                         g_free (params [i]);
4044         }
4045 }
4046
4047 /*
4048  * Find the method index in the metadata methodDef table.
4049  * Later put these three helper methods in metadata and export them.
4050  */
4051 static guint32
4052 find_method_index (MonoMethod *method) {
4053         MonoClass *klass = method->klass;
4054         int i;
4055
4056         for (i = 0; i < klass->method.count; ++i) {
4057                 if (method == klass->methods [i])
4058                         return klass->method.first + 1 + i;
4059         }
4060         return 0;
4061 }
4062
4063 /*
4064  * Find the field index in the metadata FieldDef table.
4065  */
4066 static guint32
4067 find_field_index (MonoClass *klass, MonoClassField *field) {
4068         int i;
4069
4070         for (i = 0; i < klass->field.count; ++i) {
4071                 if (field == &klass->fields [i])
4072                         return klass->field.first + 1 + i;
4073         }
4074         return 0;
4075 }
4076
4077 /*
4078  * Find the property index in the metadata Property table.
4079  */
4080 static guint32
4081 find_property_index (MonoClass *klass, MonoProperty *property) {
4082         int i;
4083
4084         for (i = 0; i < klass->property.count; ++i) {
4085                 if (property == &klass->properties [i])
4086                         return klass->property.first + 1 + i;
4087         }
4088         return 0;
4089 }
4090
4091 /*
4092  * Find the event index in the metadata Event table.
4093  */
4094 static guint32
4095 find_event_index (MonoClass *klass, MonoEvent *event) {
4096         int i;
4097
4098         for (i = 0; i < klass->event.count; ++i) {
4099                 if (event == &klass->events [i])
4100                         return klass->event.first + 1 + i;
4101         }
4102         return 0;
4103 }
4104
4105 static MonoObject*
4106 create_custom_attr (MonoImage *image, MonoMethod *method, 
4107                                         const char *data, guint32 len)
4108 {
4109         const char *p = data;
4110         const char *named;
4111         guint32 i, j, num_named;
4112         MonoObject *attr;
4113         void **params;
4114
4115         if (len < 2 || read16 (p) != 0x0001) /* Prolog */
4116                 return NULL;
4117
4118         mono_class_init (method->klass);
4119         /*g_print ("got attr %s\n", method->klass->name);*/
4120         
4121         params = g_new (void*, method->signature->param_count);
4122
4123         /* skip prolog */
4124         p += 2;
4125         for (i = 0; i < method->signature->param_count; ++i) {
4126                 params [i] = load_cattr_value (image, method->signature->params [i], p, &p);
4127         }
4128
4129         named = p;
4130         attr = mono_object_new (mono_domain_get (), method->klass);
4131         mono_runtime_invoke (method, attr, params, NULL);
4132         free_param_data (method->signature, params);
4133         g_free (params);
4134         num_named = read16 (named);
4135         named += 2;
4136         for (j = 0; j < num_named; j++) {
4137                 gint name_len;
4138                 char *name, named_type;
4139                 named_type = *named++;
4140                 named++; /* type of data */
4141                 name_len = mono_metadata_decode_blob_size (named, &named);
4142                 name = g_malloc (name_len + 1);
4143                 memcpy (name, named, name_len);
4144                 name [name_len] = 0;
4145                 named += name_len;
4146                 if (named_type == 0x53) {
4147                         MonoClassField *field = mono_class_get_field_from_name (mono_object_class (attr), name);
4148                         void *val = load_cattr_value (image, field->type, named, &named);
4149                                 mono_field_set_value (attr, field, val);
4150                                 if (!type_is_reference (field->type))
4151                                         g_free (val);
4152                 } else if (named_type == 0x54) {
4153                         MonoProperty *prop = mono_class_get_property_from_name (mono_object_class (attr), name);
4154                         void *pparams [1];
4155                         MonoType *prop_type;
4156                         /* can we have more that 1 arg in a custom attr named property? */
4157                         prop_type = prop->get? prop->get->signature->ret: prop->set->signature->params [prop->set->signature->param_count - 1];
4158                         pparams [0] = load_cattr_value (image, prop_type, named, &named);
4159                         mono_property_set_value (prop, attr, pparams, NULL);
4160                         if (!type_is_reference (prop_type))
4161                                 g_free (pparams [0]);
4162                 }
4163                 g_free (name);
4164         }
4165
4166         return attr;
4167 }
4168
4169 /*
4170  * mono_reflection_get_custom_attrs:
4171  * @obj: a reflection object handle
4172  *
4173  * Return an array with all the custom attributes defined of the
4174  * reflection handle @obj. The objects are fully build.
4175  */
4176 MonoArray*
4177 mono_reflection_get_custom_attrs (MonoObject *obj)
4178 {
4179         guint32 idx, mtoken, i, len;
4180         guint32 cols [MONO_CUSTOM_ATTR_SIZE];
4181         MonoClass *klass;
4182         MonoImage *image;
4183         MonoTableInfo *ca;
4184         MonoMethod *method;
4185         MonoObject *attr;
4186         MonoArray *result;
4187         GList *list = NULL;
4188         MonoArray *dynamic_attrs = NULL;
4189         
4190         MONO_ARCH_SAVE_REGS;
4191         
4192         klass = obj->vtable->klass;
4193         /* FIXME: need to handle: Module */
4194         if (klass == mono_defaults.monotype_class) {
4195                 MonoReflectionType *rtype = (MonoReflectionType*)obj;
4196                 klass = mono_class_from_mono_type (rtype->type);
4197                 idx = mono_metadata_token_index (klass->type_token);
4198                 idx <<= CUSTOM_ATTR_BITS;
4199                 idx |= CUSTOM_ATTR_TYPEDEF;
4200                 image = klass->image;
4201         } else if (strcmp ("Assembly", klass->name) == 0) {
4202                 MonoReflectionAssembly *rassembly = (MonoReflectionAssembly*)obj;
4203                 idx = 1; /* there is only one assembly */
4204                 idx <<= CUSTOM_ATTR_BITS;
4205                 idx |= CUSTOM_ATTR_ASSEMBLY;
4206                 image = rassembly->assembly->image;
4207         } else if (strcmp ("MonoProperty", klass->name) == 0) {
4208                 MonoReflectionProperty *rprop = (MonoReflectionProperty*)obj;
4209                 idx = find_property_index (rprop->klass, rprop->property);
4210                 idx <<= CUSTOM_ATTR_BITS;
4211                 idx |= CUSTOM_ATTR_PROPERTY;
4212                 image = rprop->klass->image;
4213         } else if (strcmp ("MonoEvent", klass->name) == 0) {
4214                 MonoReflectionEvent *revent = (MonoReflectionEvent*)obj;
4215                 idx = find_event_index (revent->klass, revent->event);
4216                 idx <<= CUSTOM_ATTR_BITS;
4217                 idx |= CUSTOM_ATTR_EVENT;
4218                 image = revent->klass->image;
4219         } else if (strcmp ("MonoField", klass->name) == 0) {
4220                 MonoReflectionField *rfield = (MonoReflectionField*)obj;
4221                 idx = find_field_index (rfield->klass, rfield->field);
4222                 idx <<= CUSTOM_ATTR_BITS;
4223                 idx |= CUSTOM_ATTR_FIELDDEF;
4224                 image = rfield->klass->image;
4225         } else if ((strcmp ("MonoMethod", klass->name) == 0) || (strcmp ("MonoCMethod", klass->name) == 0)) {
4226                 MonoReflectionMethod *rmethod = (MonoReflectionMethod*)obj;
4227                 idx = find_method_index (rmethod->method);
4228                 idx <<= CUSTOM_ATTR_BITS;
4229                 idx |= CUSTOM_ATTR_METHODDEF;
4230                 image = rmethod->method->klass->image;
4231         } else if (strcmp ("ParameterInfo", klass->name) == 0) {
4232                 MonoReflectionParameter *param = (MonoReflectionParameter*)obj;
4233                 MonoReflectionMethod *rmethod = (MonoReflectionMethod*)param->MemberImpl;
4234                 guint32 method_index = find_method_index (rmethod->method);
4235                 guint32 param_list, param_last, param_pos, found;
4236
4237                 image = rmethod->method->klass->image;
4238                 ca = &image->tables [MONO_TABLE_METHOD];
4239
4240                 param_list = mono_metadata_decode_row_col (ca, method_index - 1, MONO_METHOD_PARAMLIST);
4241                 if (method_index == ca->rows) {
4242                         ca = &image->tables [MONO_TABLE_PARAM];
4243                         param_last = ca->rows + 1;
4244                 } else {
4245                         param_last = mono_metadata_decode_row_col (ca, method_index, MONO_METHOD_PARAMLIST);
4246                         ca = &image->tables [MONO_TABLE_PARAM];
4247                 }
4248                 found = 0;
4249                 for (i = param_list; i < param_last; ++i) {
4250                         param_pos = mono_metadata_decode_row_col (ca, i - 1, MONO_PARAM_SEQUENCE);
4251                         if (param_pos == param->PositionImpl) {
4252                                 found = 1;
4253                                 break;
4254                         }
4255                 }
4256                 if (!found)
4257                         return mono_array_new (mono_domain_get (), mono_defaults.object_class, 0);
4258                 idx = i;
4259                 idx <<= CUSTOM_ATTR_BITS;
4260                 idx |= CUSTOM_ATTR_PARAMDEF;
4261         } else if (strcmp ("AssemblyBuilder", klass->name) == 0) {
4262                 MonoReflectionAssemblyBuilder *assemblyb = (MonoReflectionAssemblyBuilder*)obj;
4263                 dynamic_attrs = assemblyb->cattrs;
4264                 if (!dynamic_attrs)
4265                         return mono_array_new (mono_domain_get (), mono_defaults.object_class, 0);
4266         } else { /* handle other types here... */
4267                 g_error ("get custom attrs not yet supported for %s", klass->name);
4268         }
4269
4270         if (dynamic_attrs) {
4271                 len = mono_array_length (dynamic_attrs);
4272                 for (i = 0; i < len; ++i) {
4273                         MonoReflectionCustomAttr *cattr = (MonoReflectionCustomAttr*)mono_array_get (dynamic_attrs, gpointer, i);                       
4274                         attr = create_custom_attr (image, cattr->ctor->method, mono_array_addr (cattr->data, int, 0), mono_array_length (cattr->data));
4275                         list = g_list_prepend (list, attr);
4276                 }               
4277         }
4278         else {
4279                 /* at this point image and index are set correctly for searching the custom attr */
4280                 ca = &image->tables [MONO_TABLE_CUSTOMATTRIBUTE];
4281                 /* the table is not sorted */
4282                 for (i = 0; i < ca->rows; ++i) {
4283                         mono_metadata_decode_row (ca, i, cols, MONO_CUSTOM_ATTR_SIZE);
4284                         if (cols [MONO_CUSTOM_ATTR_PARENT] != idx)
4285                                 continue;
4286                         mtoken = cols [MONO_CUSTOM_ATTR_TYPE] >> CUSTOM_ATTR_TYPE_BITS;
4287                         switch (cols [MONO_CUSTOM_ATTR_TYPE] & CUSTOM_ATTR_TYPE_MASK) {
4288                         case CUSTOM_ATTR_TYPE_METHODDEF:
4289                                 mtoken |= MONO_TOKEN_METHOD_DEF;
4290                                 break;
4291                         case CUSTOM_ATTR_TYPE_MEMBERREF:
4292                                 mtoken |= MONO_TOKEN_MEMBER_REF;
4293                                 break;
4294                         default:
4295                                 g_error ("Unknown table for custom attr type %08x", cols [MONO_CUSTOM_ATTR_TYPE]);
4296                                 break;
4297                         }
4298                         method = mono_get_method (image, mtoken, NULL);
4299                         if (!method)
4300                                 g_error ("Can't find custom attr constructor image: %s mtoken: 0x%08x", image->name, mtoken);
4301
4302                         {
4303                                 int data_len;
4304                                 const char *data = mono_metadata_blob_heap (image, cols [MONO_CUSTOM_ATTR_VALUE]);
4305                                 data_len = mono_metadata_decode_value (data, &data);
4306
4307                                 attr = create_custom_attr (image, method, data, data_len);
4308                         }
4309                         list = g_list_prepend (list, attr);
4310                 }
4311         }
4312
4313         len = g_list_length (list);
4314         /*
4315          * The return type is really object[], but System/Attribute.cs does a cast
4316          * to (Attribute []) and that is not allowed: I'm lazy for now, but we should
4317          * probably fix that.
4318          */
4319         klass = mono_class_from_name (mono_defaults.corlib, "System", "Attribute");
4320         result = mono_array_new (mono_domain_get (), klass, len);
4321         for (i = 0; i < len; ++i) {
4322                 mono_array_set (result, gpointer, i, list->data);
4323                 list = list->next;
4324         }
4325         g_list_free (g_list_first (list));
4326
4327         return result;
4328 }
4329
4330 static MonoMethodSignature*
4331 parameters_to_signature (MonoArray *parameters) {
4332         MonoMethodSignature *sig;
4333         int count, i;
4334
4335         count = parameters? mono_array_length (parameters): 0;
4336
4337         sig = g_malloc0 (sizeof (MonoMethodSignature) + sizeof (MonoType*) * count);
4338         sig->param_count = count;
4339         sig->sentinelpos = -1; /* FIXME */
4340         for (i = 0; i < count; ++i) {
4341                 MonoReflectionType *pt = mono_array_get (parameters, MonoReflectionType*, i);
4342                 sig->params [i] = pt->type;
4343         }
4344         return sig;
4345 }
4346
4347 static MonoMethodSignature*
4348 ctor_builder_to_signature (MonoReflectionCtorBuilder *ctor) {
4349         MonoMethodSignature *sig;
4350
4351         sig = parameters_to_signature (ctor->parameters);
4352         sig->hasthis = ctor->attrs & METHOD_ATTRIBUTE_STATIC? 0: 1;
4353         sig->ret = &mono_defaults.void_class->byval_arg;
4354         return sig;
4355 }
4356
4357 static MonoMethodSignature*
4358 method_builder_to_signature (MonoReflectionMethodBuilder *method) {
4359         MonoMethodSignature *sig;
4360
4361         sig = parameters_to_signature (method->parameters);
4362         sig->hasthis = method->attrs & METHOD_ATTRIBUTE_STATIC? 0: 1;
4363         sig->ret = method->rtype? method->rtype->type: &mono_defaults.void_class->byval_arg;
4364         return sig;
4365 }
4366
4367 static void
4368 get_prop_name_and_type (MonoObject *prop, char **name, MonoType **type)
4369 {
4370         MonoClass *klass = mono_object_class (prop);
4371         if (strcmp (klass->name, "PropertyBuilder") == 0) {
4372                 MonoReflectionPropertyBuilder *pb = (MonoReflectionPropertyBuilder *)prop;
4373                 *name = mono_string_to_utf8 (pb->name);
4374                 *type = pb->type->type;
4375         } else {
4376                 MonoReflectionProperty *p = (MonoReflectionProperty *)prop;
4377                 *name = g_strdup (p->property->name);
4378                 if (p->property->get)
4379                         *type = p->property->get->signature->ret;
4380                 else
4381                         *type = p->property->set->signature->params [p->property->set->signature->param_count - 1];
4382         }
4383 }
4384
4385 static void
4386 get_field_name_and_type (MonoObject *field, char **name, MonoType **type)
4387 {
4388         MonoClass *klass = mono_object_class (field);
4389         if (strcmp (klass->name, "FieldBuilder") == 0) {
4390                 MonoReflectionFieldBuilder *fb = (MonoReflectionFieldBuilder *)field;
4391                 *name = mono_string_to_utf8 (fb->name);
4392                 *type = fb->type->type;
4393         } else {
4394                 MonoReflectionField *f = (MonoReflectionField *)field;
4395                 *name = g_strdup (f->field->name);
4396                 *type = f->field->type;
4397         }
4398 }
4399
4400 static char*
4401 type_get_qualified_name (MonoType *type, MonoAssembly *ass) {
4402         char *name, *result;
4403         MonoClass *klass;
4404         MonoAssembly *ta;
4405
4406         name = mono_type_get_name (type);
4407         klass = my_mono_class_from_mono_type (type);
4408         ta = klass->image->assembly;
4409         if (ta == ass || klass->image == mono_defaults.corlib)
4410                 return name;
4411
4412         /* missing public key */
4413         result = g_strdup_printf ("%s, %s, Version=%d.%d.%d.%d, Culture=%s",
4414                 name, ta->aname.name,
4415                 ta->aname.major, ta->aname.minor, ta->aname.build, ta->aname.revision,
4416                 ta->aname.culture && *ta->aname.culture? ta->aname.culture: "neutral");
4417         g_free (name);
4418         return result;
4419 }
4420
4421 static void
4422 encode_cattr_value (char *buffer, char *p, char **retbuffer, char **retp, guint32 *buflen, MonoType *type, MonoObject *arg)
4423 {
4424         char *argval;
4425         MonoTypeEnum simple_type;
4426         
4427         if ((p-buffer) + 10 >= *buflen) {
4428                 char *newbuf;
4429                 *buflen *= 2;
4430                 newbuf = g_realloc (buffer, *buflen);
4431                 p = newbuf + (p-buffer);
4432                 buffer = newbuf;
4433         }
4434         argval = ((char*)arg + sizeof (MonoObject));
4435         simple_type = type->type;
4436 handle_enum:
4437         switch (simple_type) {
4438         case MONO_TYPE_BOOLEAN:
4439         case MONO_TYPE_U1:
4440         case MONO_TYPE_I1:
4441                 *p++ = *argval;
4442                 break;
4443         case MONO_TYPE_CHAR:
4444         case MONO_TYPE_U2:
4445         case MONO_TYPE_I2:
4446                 swap_with_size (p, argval, 2, 1);
4447                 p += 2;
4448                 break;
4449         case MONO_TYPE_U4:
4450         case MONO_TYPE_I4:
4451         case MONO_TYPE_R4:
4452                 swap_with_size (p, argval, 4, 1);
4453                 p += 4;
4454                 break;
4455         case MONO_TYPE_U8:
4456         case MONO_TYPE_I8:
4457         case MONO_TYPE_R8:
4458                 swap_with_size (p, argval, 8, 1);
4459                 p += 8;
4460                 break;
4461         case MONO_TYPE_VALUETYPE:
4462                 if (type->data.klass->enumtype) {
4463                         simple_type = type->data.klass->enum_basetype->type;
4464                         goto handle_enum;
4465                 } else {
4466                         g_warning ("generic valutype %s not handled in custom attr value decoding", type->data.klass->name);
4467                 }
4468                 break;
4469         case MONO_TYPE_STRING: {
4470                 char *str;
4471                 guint32 slen;
4472                 if (!arg) {
4473                         *p++ = 0xFF;
4474                         break;
4475                 }
4476                 str = mono_string_to_utf8 ((MonoString*)arg);
4477                 slen = strlen (str);
4478                 if ((p-buffer) + 10 + slen >= *buflen) {
4479                         char *newbuf;
4480                         *buflen *= 2;
4481                         *buflen += slen;
4482                         newbuf = g_realloc (buffer, *buflen);
4483                         p = newbuf + (p-buffer);
4484                         buffer = newbuf;
4485                 }
4486                 mono_metadata_encode_value (slen, p, &p);
4487                 memcpy (p, str, slen);
4488                 p += slen;
4489                 g_free (str);
4490                 break;
4491         }
4492         case MONO_TYPE_CLASS: {
4493                 char *str;
4494                 guint32 slen;
4495                 MonoClass *k = mono_object_class (arg);
4496                 if (!mono_object_isinst (arg, mono_defaults.monotype_class) &&
4497                                 (strcmp (k->name, "TypeBuilder") || strcmp (k->name_space, "System.Reflection.Emit")))
4498                         g_error ("only types allowed, not %s.%s", k->name_space, k->name);
4499 handle_type:
4500                 str = type_get_qualified_name (((MonoReflectionType*)arg)->type, NULL);
4501                 slen = strlen (str);
4502                 if ((p-buffer) + 10 + slen >= *buflen) {
4503                         char *newbuf;
4504                         *buflen *= 2;
4505                         *buflen += slen;
4506                         newbuf = g_realloc (buffer, *buflen);
4507                         p = newbuf + (p-buffer);
4508                         buffer = newbuf;
4509                 }
4510                 mono_metadata_encode_value (slen, p, &p);
4511                 memcpy (p, str, slen);
4512                 p += slen;
4513                 g_free (str);
4514                 break;
4515         }
4516         /* it may be a boxed value or a Type */
4517         case MONO_TYPE_OBJECT: {
4518                 MonoClass *klass = mono_object_class (arg);
4519                 char *str;
4520                 guint32 slen;
4521                 
4522                 if (mono_object_isinst (arg, mono_defaults.monotype_class)) {
4523                         *p++ = 0x50;
4524                         goto handle_type;
4525                 } else if (klass->enumtype) {
4526                         *p++ = 0x55;
4527                 } else if (klass->byval_arg.type >= MONO_TYPE_BOOLEAN && klass->byval_arg.type <= MONO_TYPE_R8) {
4528                         *p++ = simple_type = klass->byval_arg.type;
4529                         goto handle_enum;
4530                 } else {
4531                         g_error ("unhandled type in custom attr");
4532                 }
4533                 str = type_get_qualified_name (klass->enum_basetype, NULL);
4534                 slen = strlen (str);
4535                 if ((p-buffer) + 10 + slen >= *buflen) {
4536                         char *newbuf;
4537                         *buflen *= 2;
4538                         *buflen += slen;
4539                         newbuf = g_realloc (buffer, *buflen);
4540                         p = newbuf + (p-buffer);
4541                         buffer = newbuf;
4542                 }
4543                 mono_metadata_encode_value (slen, p, &p);
4544                 memcpy (p, str, slen);
4545                 p += slen;
4546                 g_free (str);
4547                 simple_type = klass->enum_basetype->type;
4548                 goto handle_enum;
4549         }
4550         default:
4551                 g_error ("type 0x%02x not yet supported in custom attr encoder", simple_type);
4552         }
4553         *retp = p;
4554         *retbuffer = buffer;
4555 }
4556
4557 /*
4558  * mono_reflection_get_custom_attrs_blob:
4559  * @ctor: custom attribute constructor
4560  * @ctorArgs: arguments o the constructor
4561  * @properties:
4562  * @propValues:
4563  * @fields:
4564  * @fieldValues:
4565  * 
4566  * Creates the blob of data that needs to be saved in the metadata and that represents
4567  * the custom attributed described by @ctor, @ctorArgs etc.
4568  * Returns: a Byte array representing the blob of data.
4569  */
4570 MonoArray*
4571 mono_reflection_get_custom_attrs_blob (MonoObject *ctor, MonoArray *ctorArgs, MonoArray *properties, MonoArray *propValues, MonoArray *fields, MonoArray* fieldValues) 
4572 {
4573         MonoArray *result;
4574         MonoMethodSignature *sig;
4575         MonoObject *arg;
4576         char *buffer, *p;
4577         guint32 buflen, i;
4578
4579         MONO_ARCH_SAVE_REGS;
4580
4581         if (strcmp (ctor->vtable->klass->name, "MonoCMethod")) {
4582                 sig = ctor_builder_to_signature ((MonoReflectionCtorBuilder*)ctor);
4583         } else {
4584                 sig = ((MonoReflectionMethod*)ctor)->method->signature;
4585         }
4586         buflen = 256;
4587         p = buffer = g_malloc (buflen);
4588         /* write the prolog */
4589         *p++ = 1;
4590         *p++ = 0;
4591         for (i = 0; i < sig->param_count; ++i) {
4592                 if (sig->params[i]->type==MONO_TYPE_SZARRAY)
4593                 {
4594                         guint32 alen=mono_array_length(ctorArgs) - i;
4595                         guint32 j;
4596                         if ((p-buffer) + 10 >= buflen) {
4597                                 char *newbuf;
4598                                 buflen *= 2;
4599                                 newbuf = g_realloc (buffer, buflen);
4600                                 p = newbuf + (p-buffer);
4601                                 buffer = newbuf;
4602                         }
4603                         *p++=alen&0xff;
4604                         *p++=(alen>>8)&0xff;
4605                         *p++=(alen>>16)&0xff;
4606                         *p++=(alen>>24)&0xff;
4607                         for (j=0;j<alen;j++)
4608                         {
4609                                 arg=(MonoObject*)mono_array_get(ctorArgs,gpointer,i+j);
4610                                 encode_cattr_value(buffer,p,&buffer,&p,&buflen,sig->params[i]->data.type,arg);
4611                         }
4612                 }
4613                 else
4614                 {
4615                         arg = (MonoObject*)mono_array_get (ctorArgs, gpointer, i);
4616                         encode_cattr_value (buffer, p, &buffer, &p, &buflen, sig->params [i], arg);
4617                 }
4618         }
4619         i = 0;
4620         if (properties)
4621                 i += mono_array_length (properties);
4622         if (fields)
4623                 i += mono_array_length (fields);
4624         *p++ = i & 0xff;
4625         *p++ = (i >> 8) & 0xff;
4626         if (properties) {
4627                 MonoObject *prop;
4628                 for (i = 0; i < mono_array_length (properties); ++i) {
4629                         MonoType *ptype;
4630                         char *pname;
4631                         int len;
4632                         
4633                         prop = mono_array_get (properties, gpointer, i);
4634                         get_prop_name_and_type (prop, &pname, &ptype);
4635                         *p++ = 0x54; /* PROPERTY signature */
4636                         mono_metadata_encode_value (ptype->type, p, &p);
4637                         len = strlen (pname);
4638                         mono_metadata_encode_value (len, p, &p);
4639                         memcpy (p, pname, len);
4640                         p += len;
4641                         encode_cattr_value (buffer, p, &buffer, &p, &buflen, ptype, (MonoObject*)mono_array_get (propValues, gpointer, i));
4642                         g_free (pname);
4643                 }
4644         }
4645
4646         if (fields) {
4647                 MonoObject *field;
4648                 for (i = 0; i < mono_array_length (fields); ++i) {
4649                         MonoType *ftype;
4650                         char *fname;
4651                         int len;
4652                         
4653                         field = mono_array_get (fields, gpointer, i);
4654                         get_field_name_and_type (field, &fname, &ftype);
4655                         *p++ = 0x53; /* FIELD signature */
4656                         mono_metadata_encode_value (ftype->type, p, &p);
4657                         len = strlen (fname);
4658                         mono_metadata_encode_value (len, p, &p);
4659                         memcpy (p, fname, len);
4660                         p += len;
4661                         encode_cattr_value (buffer, p, &buffer, &p, &buflen, ftype, (MonoObject*)mono_array_get (fieldValues, gpointer, i));
4662                         g_free (fname);
4663                 }
4664         }
4665
4666         g_assert (p - buffer <= buflen);
4667         buflen = p - buffer;
4668         result = mono_array_new (mono_domain_get (), mono_defaults.byte_class, buflen);
4669         p = mono_array_addr (result, char, 0);
4670         memcpy (p, buffer, buflen);
4671         g_free (buffer);
4672         if (strcmp (ctor->vtable->klass->name, "MonoCMethod"))
4673                 g_free (sig);
4674         return result;
4675 }
4676
4677 /*
4678  * mono_reflection_setup_internal_class:
4679  * @tb: a TypeBuilder object
4680  *
4681  * Creates a MonoClass that represents the TypeBuilder.
4682  * This is a trick that lets us simplify a lot of reflection code
4683  * (and will allow us to support Build and Run assemblies easier).
4684  */
4685 void
4686 mono_reflection_setup_internal_class (MonoReflectionTypeBuilder *tb)
4687 {
4688         MonoClass *klass, *parent;
4689
4690         MONO_ARCH_SAVE_REGS;
4691
4692         klass = g_new0 (MonoClass, 1);
4693
4694         klass->image = tb->module->assemblyb->dynamic_assembly->assembly.image;
4695
4696         if (tb->parent) {
4697                 /* check so we can compile corlib correctly */
4698                 if (strcmp (mono_object_class (tb->parent)->name, "TypeBuilder") == 0) {
4699                         /* mono_class_setup_mono_type () guaranteess type->data.klass is valid */
4700                         parent = tb->parent->type->data.klass;
4701                 } else 
4702                         parent = my_mono_class_from_mono_type (tb->parent->type);
4703         } else
4704                 parent = NULL;
4705         
4706         klass->inited = 1; /* we lie to the runtime */
4707         klass->name = mono_string_to_utf8 (tb->name);
4708         klass->name_space = mono_string_to_utf8 (tb->nspace);
4709         klass->type_token = MONO_TOKEN_TYPE_DEF | tb->table_idx;
4710         klass->flags = tb->attrs;
4711
4712         klass->element_class = klass;
4713         klass->reflection_info = tb; /* need to pin. */
4714
4715         /* Put into cache so mono_class_get () will find it */
4716         mono_image_add_to_name_cache (klass->image, klass->name_space, klass->name,
4717                                                                   tb->table_idx);
4718
4719         mono_g_hash_table_insert (tb->module->assemblyb->dynamic_assembly->tokens,
4720                                                           GUINT_TO_POINTER (MONO_TOKEN_TYPE_DEF | tb->table_idx),
4721                                                           tb);
4722
4723         if (parent != NULL)
4724                 mono_class_setup_parent (klass, parent);
4725         else if (strcmp (klass->name, "Object") == 0 && strcmp (klass->name_space, "System") == 0) {
4726                 const char *old_n = klass->name;
4727                 /* trick to get relative numbering right when compiling corlib */
4728                 klass->name = "BuildingObject";
4729                 mono_class_setup_parent (klass, mono_defaults.object_class);
4730                 klass->name = old_n;
4731         }
4732         mono_class_setup_mono_type (klass);
4733
4734         /*
4735          * FIXME: handle interfaces.
4736          */
4737
4738         tb->type.type = &klass->byval_arg;
4739
4740         /*g_print ("setup %s as %s (%p)\n", klass->name, ((MonoObject*)tb)->vtable->klass->name, tb);*/
4741 }
4742
4743 /*
4744  * mono_reflection_create_internal_class:
4745  * @tb: a TypeBuilder object
4746  *
4747  * Actually create the MonoClass that is associated with the TypeBuilder.
4748  */
4749 void
4750 mono_reflection_create_internal_class (MonoReflectionTypeBuilder *tb)
4751 {
4752         MonoClass *klass;
4753
4754         MONO_ARCH_SAVE_REGS;
4755
4756         klass = my_mono_class_from_mono_type (tb->type.type);
4757
4758         if (klass->enumtype && klass->enum_basetype == NULL) {
4759                 MonoReflectionFieldBuilder *fb;
4760
4761                 g_assert (tb->fields != NULL);
4762                 g_assert (mono_array_length (tb->fields) >= 1);
4763
4764                 fb = mono_array_get (tb->fields, MonoReflectionFieldBuilder*, 0);
4765
4766                 klass->enum_basetype = fb->type->type;
4767                 klass->element_class = my_mono_class_from_mono_type (klass->enum_basetype);
4768                 if (!klass->element_class)
4769                         klass->element_class = mono_class_from_mono_type (klass->enum_basetype);
4770                 klass->instance_size = klass->element_class->instance_size;
4771                 klass->size_inited = 1;
4772                 /* 
4773                  * this is almost safe to do with enums and it's needed to be able
4774                  * to create objects of the enum type (for use in SetConstant).
4775                  */
4776                 /* FIXME: Does this mean enums can't have method overrides ? */
4777                 mono_class_setup_vtable (klass, NULL, 0);
4778         }
4779 }
4780
4781 static MonoMethod*
4782 reflection_methodbuilder_to_mono_method (MonoClass *klass,
4783                                                                                  ReflectionMethodBuilder *rmb,
4784                                                                                  MonoMethodSignature *sig)
4785 {
4786         MonoMethod *m;
4787         MonoMethodNormal *pm;
4788
4789         if ((rmb->attrs & METHOD_ATTRIBUTE_PINVOKE_IMPL) ||
4790             (rmb->iattrs & METHOD_IMPL_ATTRIBUTE_INTERNAL_CALL))
4791                 m = (MonoMethod *)g_new0 (MonoMethodPInvoke, 1);
4792         else 
4793                 m = (MonoMethod *)g_new0 (MonoMethodNormal, 1);
4794
4795         pm = (MonoMethodNormal*)m;
4796
4797         m->slot = -1;
4798         m->flags = rmb->attrs;
4799         m->iflags = rmb->iattrs;
4800         m->name = mono_string_to_utf8 (rmb->name);
4801         m->klass = klass;
4802         m->signature = sig;
4803
4804         /* TODO: What about m->token ? */
4805         if (m->iflags & METHOD_IMPL_ATTRIBUTE_INTERNAL_CALL) {
4806                 if (klass == mono_defaults.string_class && !strcmp (m->name, ".ctor"))
4807                         m->string_ctor = 1;
4808
4809                 m->addr = mono_lookup_internal_call (m);
4810                 m->signature->pinvoke = 1;
4811         } else if (m->flags & METHOD_ATTRIBUTE_PINVOKE_IMPL) {
4812                 /* TODO */
4813                 m->signature->pinvoke = 1;
4814                 return m;
4815         } else if (!m->klass->dummy && 
4816                            !(m->flags & METHOD_ATTRIBUTE_ABSTRACT) &&
4817                            !(m->iflags & METHOD_IMPL_ATTRIBUTE_RUNTIME)) {
4818                 MonoMethodHeader *header;
4819                 guint32 code_size;
4820                 gint32 max_stack, i;
4821                 gint32 num_locals = 0;
4822                 gint32 num_clauses = 0;
4823                 guint8 *code;
4824
4825                 if (rmb->ilgen) {
4826                         code = mono_array_addr (rmb->ilgen->code, guint8, 0);
4827                         code_size = rmb->ilgen->code_len;
4828                         max_stack = rmb->ilgen->max_stack;
4829                         num_locals = rmb->ilgen->locals ? mono_array_length (rmb->ilgen->locals) : 0;
4830                         if (rmb->ilgen->ex_handlers)
4831                                 num_clauses = method_count_clauses (rmb->ilgen);
4832                 } else {
4833                         if (rmb->code) {
4834                                 code = mono_array_addr (rmb->code, guint8, 0);
4835                                 code_size = mono_array_length (rmb->code);
4836                                 /* we probably need to run a verifier on the code... */
4837                                 max_stack = 8; 
4838                         }
4839                         else {
4840                                 code = NULL;
4841                                 code_size = 0;
4842                                 max_stack = 8;
4843                         }
4844                 }
4845
4846                 header = g_malloc0 (sizeof (MonoMethodHeader) + 
4847                                                         (num_locals - MONO_ZERO_LEN_ARRAY) * sizeof (MonoType*));
4848                 header->code_size = code_size;
4849                 header->code = g_malloc (code_size);
4850                 memcpy ((char*)header->code, code, code_size);
4851                 header->max_stack = max_stack;
4852                 header->init_locals = rmb->init_locals;
4853                 header->num_locals = num_locals;
4854
4855                 for (i = 0; i < num_locals; ++i) {
4856                         MonoReflectionLocalBuilder *lb = 
4857                                 mono_array_get (rmb->ilgen->locals, 
4858                                                                 MonoReflectionLocalBuilder*, i);
4859
4860                         header->locals [i] = g_new0 (MonoType, 1);
4861                         memcpy (header->locals [i], lb->type->type, sizeof (MonoType));
4862                 }
4863
4864                 header->num_clauses = num_clauses;
4865                 if (num_clauses) {
4866                         header->clauses = method_encode_clauses (klass->image->assembly->dynamic,
4867                                                                                                          rmb->ilgen,
4868                                                                                                          num_clauses);
4869                 }
4870
4871                 pm->header = header;
4872         }
4873
4874         return m;
4875 }       
4876
4877 static MonoMethod*
4878 ctorbuilder_to_mono_method (MonoClass *klass, MonoReflectionCtorBuilder* mb)
4879 {
4880         ReflectionMethodBuilder rmb;
4881         const char *name;
4882         MonoMethodSignature *sig;
4883
4884         name = mb->attrs & METHOD_ATTRIBUTE_STATIC ? ".cctor": ".ctor";
4885
4886         sig = ctor_builder_to_signature (mb);
4887
4888         rmb.ilgen = mb->ilgen;
4889         rmb.parameters = mb->parameters;
4890         rmb.pinfo = mb->pinfo;
4891         rmb.attrs = mb->attrs;
4892         rmb.iattrs = mb->iattrs;
4893         rmb.call_conv = mb->call_conv;
4894         rmb.type = mb->type;
4895         rmb.name = mono_string_new (mono_domain_get (), name);
4896         rmb.table_idx = &mb->table_idx;
4897         rmb.init_locals = mb->init_locals;
4898         rmb.code = NULL;
4899
4900         mb->mhandle = reflection_methodbuilder_to_mono_method (klass, &rmb, sig);
4901         return mb->mhandle;
4902 }
4903
4904 static MonoMethod*
4905 methodbuilder_to_mono_method (MonoClass *klass, MonoReflectionMethodBuilder* mb)
4906 {
4907         ReflectionMethodBuilder rmb;
4908         MonoMethodSignature *sig;
4909
4910         sig = method_builder_to_signature (mb);
4911
4912         rmb.ilgen = mb->ilgen;
4913         rmb.parameters = mb->parameters;
4914         rmb.pinfo = mb->pinfo;
4915         rmb.attrs = mb->attrs;
4916         rmb.iattrs = mb->iattrs;
4917         rmb.call_conv = mb->call_conv;
4918         rmb.type = mb->type;
4919         rmb.name = mb->name;
4920         rmb.table_idx = &mb->table_idx;
4921         rmb.init_locals = mb->init_locals;
4922         rmb.code = mb->code;
4923
4924         mb->mhandle = reflection_methodbuilder_to_mono_method (klass, &rmb, sig);
4925         return mb->mhandle;
4926 }
4927
4928 static void
4929 ensure_runtime_vtable (MonoClass *klass)
4930 {
4931         MonoReflectionTypeBuilder *tb = klass->reflection_info;
4932         int i, num, j, onum;
4933         MonoMethod **overrides;
4934
4935         if (!tb || klass->wastypebuilder)
4936                 return;
4937         if (klass->parent)
4938                 ensure_runtime_vtable (klass->parent);
4939
4940         num = tb->ctors? mono_array_length (tb->ctors): 0;
4941         num += tb->methods? mono_array_length (tb->methods): 0;
4942         klass->method.count = num;
4943         klass->methods = g_new (MonoMethod*, num);
4944         num = tb->ctors? mono_array_length (tb->ctors): 0;
4945         for (i = 0; i < num; ++i)
4946                 klass->methods [i] = ctorbuilder_to_mono_method (klass, mono_array_get (tb->ctors, MonoReflectionCtorBuilder*, i));
4947         num = tb->methods? mono_array_length (tb->methods): 0;
4948         j = i;
4949         for (i = 0; i < num; ++i)
4950                 klass->methods [j++] = methodbuilder_to_mono_method (klass, mono_array_get (tb->methods, MonoReflectionMethodBuilder*, i));
4951
4952         klass->wastypebuilder = TRUE;
4953         if (tb->interfaces) {
4954                 klass->interface_count = mono_array_length (tb->interfaces);
4955                 klass->interfaces = g_new (MonoClass*, klass->interface_count);
4956                 for (i = 0; i < klass->interface_count; ++i) {
4957                         MonoReflectionType *iface = mono_array_get (tb->interfaces, gpointer, i);
4958                         klass->interfaces [i] = mono_class_from_mono_type (iface->type);
4959                 }
4960         }
4961
4962         /* Overrides */
4963         onum = 0;
4964         if (tb->methods) {
4965                 for (i = 0; i < mono_array_length (tb->methods); ++i) {
4966                         MonoReflectionMethodBuilder *mb = 
4967                                 mono_array_get (tb->methods, MonoReflectionMethodBuilder*, i);
4968                         if (mb->override_method)
4969                                 onum ++;
4970                 }
4971         }
4972
4973         overrides = (MonoMethod**)g_new0 (MonoMethod, onum * 2);
4974
4975         if (tb->methods) {
4976                 onum = 0;
4977                 for (i = 0; i < mono_array_length (tb->methods); ++i) {
4978                         MonoReflectionMethodBuilder *mb = 
4979                                 mono_array_get (tb->methods, MonoReflectionMethodBuilder*, i);
4980                         if (mb->override_method) {
4981                                 /* FIXME: What if 'override_method' is a MethodBuilder ? */
4982                                 overrides [onum * 2] = 
4983                                         mb->override_method->method;
4984                                 overrides [onum * 2 + 1] =
4985                                         mb->mhandle;
4986
4987                                 g_assert (mb->mhandle);
4988
4989                                 onum ++;
4990                         }
4991                 }
4992         }
4993
4994         mono_class_setup_vtable (klass, overrides, onum);
4995 }
4996
4997 static void
4998 typebuilder_setup_fields (MonoClass *klass)
4999 {
5000         MonoReflectionTypeBuilder *tb = klass->reflection_info;
5001         MonoReflectionFieldBuilder *fb;
5002         MonoClassField *field;
5003         int i;
5004
5005         klass->field.count = tb->fields? mono_array_length (tb->fields): 0;
5006
5007         if (!klass->field.count)
5008                 return;
5009         
5010         klass->fields = g_new0 (MonoClassField, klass->field.count);
5011
5012         for (i = 0; i < klass->field.count; ++i) {
5013                 fb = mono_array_get (tb->fields, gpointer, i);
5014                 field = &klass->fields [i];
5015                 field->name = mono_string_to_utf8 (fb->name);
5016                 if (fb->attrs) {
5017                         /* FIXME: handle type modifiers */
5018                         field->type = g_memdup (fb->type->type, sizeof (MonoType));
5019                         field->type->attrs = fb->attrs;
5020                 } else {
5021                         field->type = fb->type->type;
5022                 }
5023                 if ((fb->attrs & FIELD_ATTRIBUTE_HAS_FIELD_RVA) && fb->rva_data)
5024                         field->data = mono_array_addr (fb->rva_data, char, 0);
5025                 if (fb->offset != -1)
5026                         field->offset = fb->offset;
5027                 field->parent = klass;
5028                 fb->handle = field;
5029         }
5030         mono_class_layout_fields (klass);
5031 }
5032
5033 MonoReflectionType*
5034 mono_reflection_create_runtime_class (MonoReflectionTypeBuilder *tb)
5035 {
5036         MonoClass *klass;
5037         MonoReflectionType* res;
5038
5039         MONO_ARCH_SAVE_REGS;
5040
5041         klass = my_mono_class_from_mono_type (tb->type.type);
5042
5043         /*
5044          * Fields to set in klass:
5045          * the various flags: delegate/unicode/contextbound etc.
5046          * nested_in
5047          * nested_classes
5048          * properties
5049          * events
5050          */
5051         klass->flags = tb->attrs;
5052         klass->element_class = klass;
5053
5054         /* enums are done right away */
5055         if (!klass->enumtype)
5056                 ensure_runtime_vtable (klass);
5057
5058         /* fields and object layout */
5059         if (klass->parent) {
5060                 if (!klass->parent->size_inited)
5061                         mono_class_init (klass->parent);
5062                 klass->instance_size += klass->parent->instance_size;
5063                 klass->class_size += klass->parent->class_size;
5064                 klass->min_align = klass->parent->min_align;
5065         } else {
5066                 klass->instance_size = sizeof (MonoObject);
5067                 klass->min_align = 1;
5068         }
5069         /* FIXME: handle packing_size and instance_size */
5070         typebuilder_setup_fields (klass);
5071
5072         /* FIXME: properties */
5073
5074         res = mono_type_get_object (mono_object_domain (tb), &klass->byval_arg);
5075         /* with enums res == tb: need to fix that. */
5076         if (!klass->enumtype)
5077                 g_assert (res != (MonoReflectionType*)tb);
5078         return res;
5079 }
5080
5081 MonoArray *
5082 mono_reflection_sighelper_get_signature_local (MonoReflectionSigHelper *sig)
5083 {
5084         MonoDynamicAssembly *assembly = sig->module->assemblyb->dynamic_assembly;
5085         guint32 na = mono_array_length (sig->arguments);
5086         guint32 buflen, i;
5087         MonoArray *result;
5088         char *buf, *p;
5089
5090         MONO_ARCH_SAVE_REGS;
5091
5092         p = buf = g_malloc (10 + na * 10);
5093
5094         mono_metadata_encode_value (0x07, p, &p);
5095         mono_metadata_encode_value (na, p, &p);
5096         for (i = 0; i < na; ++i) {
5097                 MonoReflectionType *type = mono_array_get (sig->arguments, MonoReflectionType *, i);
5098                 encode_reflection_type (assembly, type, p, &p);
5099         }
5100
5101         buflen = p - buf;
5102         result = mono_array_new (mono_domain_get (), mono_defaults.byte_class, buflen);
5103         p = mono_array_addr (result, char, 0);
5104         memcpy (p, buf, buflen);
5105         g_free (buf);
5106
5107         return result;
5108 }
5109
5110 MonoArray *
5111 mono_reflection_sighelper_get_signature_field (MonoReflectionSigHelper *sig)
5112 {
5113         MonoDynamicAssembly *assembly = sig->module->assemblyb->dynamic_assembly;
5114         guint32 na = mono_array_length (sig->arguments);
5115         guint32 buflen, i;
5116         MonoArray *result;
5117         char *buf, *p;
5118
5119         MONO_ARCH_SAVE_REGS;
5120
5121         p = buf = g_malloc (10 + na * 10);
5122
5123         mono_metadata_encode_value (0x06, p, &p);
5124         for (i = 0; i < na; ++i) {
5125                 MonoReflectionType *type = mono_array_get (sig->arguments, MonoReflectionType *, i);
5126                 encode_reflection_type (assembly, type, p, &p);
5127         }
5128
5129         buflen = p - buf;
5130         result = mono_array_new (mono_domain_get (), mono_defaults.byte_class, buflen);
5131         p = mono_array_addr (result, char, 0);
5132         memcpy (p, buf, buflen);
5133         g_free (buf);
5134
5135         return result;
5136 }
5137
5138 gpointer
5139 mono_reflection_lookup_dynamic_token (MonoImage *image, guint32 token)
5140 {
5141         MonoDynamicAssembly *assembly = image->assembly->dynamic;
5142         MonoObject *obj;
5143         gpointer result;
5144
5145         obj = mono_g_hash_table_lookup (assembly->tokens, GUINT_TO_POINTER (token));
5146         g_assert (obj);
5147
5148         if (strcmp (obj->vtable->klass->name, "String") == 0) {
5149                 result = obj;
5150                 g_assert (result);
5151         }
5152         else if (strcmp (obj->vtable->klass->name, "MonoType") == 0) {
5153                 MonoReflectionType *tb = (MonoReflectionType*)obj;
5154                 result = mono_class_from_mono_type (tb->type);
5155                 g_assert (result);
5156         }
5157         else if (strcmp (obj->vtable->klass->name, "MonoMethod") == 0) {
5158                 result = ((MonoReflectionMethod*)obj)->method;
5159                 g_assert (result);
5160         }
5161         else if (strcmp (obj->vtable->klass->name, "MonoCMethod") == 0) {
5162                 result = ((MonoReflectionMethod*)obj)->method;
5163                 g_assert (result);
5164         }
5165         else if (strcmp (obj->vtable->klass->name, "MethodBuilder") == 0) {
5166                 MonoReflectionMethodBuilder *mb = (MonoReflectionMethodBuilder*)obj;
5167                 result = mb->mhandle;
5168                 if (!result) {
5169                         /* Type is not yet created */
5170                         MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder*)mb->type;
5171
5172                         mono_domain_try_type_resolve (mono_domain_get (), (MonoObject*)tb);
5173
5174                         /*
5175                          * Hopefully this has been filled in by calling CreateType() on the
5176                          * TypeBuilder.
5177                          */
5178                         /**
5179                          * TODO: This won't work if the application finishes another 
5180                          * TypeBuilder instance instead of this one.
5181                          */
5182                         result = mb->mhandle;
5183                 }
5184         }
5185         else if (strcmp (obj->vtable->klass->name, "ConstructorBuilder") == 0) {
5186                 MonoReflectionCtorBuilder *cb = (MonoReflectionCtorBuilder*)obj;
5187
5188                 result = cb->mhandle;
5189                 if (!result) {
5190                         MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder*)cb->type;
5191
5192                         mono_domain_try_type_resolve (mono_domain_get (), (MonoObject*)tb);
5193                         result = cb->mhandle;
5194                 }
5195         }
5196         else if (strcmp (obj->vtable->klass->name, "MonoField") == 0) {
5197                 result = ((MonoReflectionField*)obj)->field;
5198                 g_assert (result);
5199         }
5200         else if (strcmp (obj->vtable->klass->name, "FieldBuilder") == 0) {
5201                 MonoReflectionFieldBuilder *fb = (MonoReflectionFieldBuilder*)obj;
5202                 result = fb->handle;
5203
5204                 if (!result) {
5205                         MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder*)fb->typeb;
5206
5207                         mono_domain_try_type_resolve (mono_domain_get (), (MonoObject*)tb);
5208                         result = fb->handle;
5209                 }
5210         }
5211         else if (strcmp (obj->vtable->klass->name, "TypeBuilder") == 0) {
5212                 MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder*)obj;
5213                 MonoClass *klass;
5214
5215                 klass = tb->type.type->data.klass;
5216                 if (klass->wastypebuilder) {
5217                         /* Already created */
5218                         result = klass;
5219                 }
5220                 else {
5221                         mono_domain_try_type_resolve (mono_domain_get (), (MonoObject*)tb);
5222                         result = tb->type.type->data.klass;
5223                         g_assert (result);
5224                 }
5225         }
5226         else if (strcmp (obj->vtable->klass->name, "SignatureHelper") == 0) {
5227                 MonoReflectionSigHelper *helper = (MonoReflectionSigHelper*)obj;
5228                 MonoMethodSignature *sig;
5229                 int nargs, i;
5230
5231                 if (helper->arguments)
5232                         nargs = mono_array_length (helper->arguments);
5233                 else
5234                         nargs = 0;
5235
5236                 sig = mono_metadata_signature_alloc (image, nargs);
5237                 sig->explicit_this = helper->call_conv & 64;
5238                 sig->hasthis = helper->call_conv & 32;
5239
5240                 if (helper->call_conv == 0) /* unmanaged */
5241                         sig->call_convention = helper->unmanaged_call_conv - 1;
5242                 else
5243                         if (helper->call_conv & 0x02)
5244                                 sig->call_convention = MONO_CALL_VARARG;
5245                 else
5246                         sig->call_convention = MONO_CALL_DEFAULT;
5247
5248                 sig->param_count = nargs;
5249                 /* TODO: Copy type ? */
5250                 sig->ret = helper->return_type->type;
5251                 for (i = 0; i < nargs; ++i) {
5252                         MonoReflectionType *rt = mono_array_get (helper->arguments, MonoReflectionType*, i);
5253                         sig->params [i] = rt->type;
5254                 }
5255
5256                 result = sig;
5257         }
5258         else {
5259                 g_print (obj->vtable->klass->name);
5260                 g_assert_not_reached ();
5261         }
5262         return result;
5263 }
5264
5265