2003-02-21 Zoltan Varga <vargaz@freemail.hu>
[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         /*
1429          * If it's in the same module:
1430          */
1431         if (!force_ref && (klass->image == assembly->assembly.image)) {
1432                 MonoReflectionTypeBuilder *tb = klass->reflection_info;
1433                 token = TYPEDEFORREF_TYPEDEF | (tb->table_idx << TYPEDEFORREF_BITS);
1434                 mono_g_hash_table_insert (assembly->tokens, GUINT_TO_POINTER (token), klass);
1435                 return token;
1436         }
1437
1438         if (klass->nested_in) {
1439                 enclosing = mono_image_typedef_or_ref (assembly, &klass->nested_in->byval_arg);
1440                 /* get the typeref idx of the enclosing type */
1441                 enclosing >>= TYPEDEFORREF_BITS;
1442                 scope = (enclosing << RESOLTION_SCOPE_BITS) | RESOLTION_SCOPE_TYPEREF;
1443         } else {
1444                 scope = resolution_scope_from_image (assembly, klass->image);
1445         }
1446         table = &assembly->tables [MONO_TABLE_TYPEREF];
1447         alloc_table (table, table->rows + 1);
1448         values = table->values + table->next_idx * MONO_TYPEREF_SIZE;
1449         values [MONO_TYPEREF_SCOPE] = scope;
1450         values [MONO_TYPEREF_NAME] = string_heap_insert (&assembly->sheap, klass->name);
1451         values [MONO_TYPEREF_NAMESPACE] = string_heap_insert (&assembly->sheap, klass->name_space);
1452         token = TYPEDEFORREF_TYPEREF | (table->next_idx << TYPEDEFORREF_BITS); /* typeref */
1453         g_hash_table_insert (assembly->typeref, type, GUINT_TO_POINTER(token));
1454         table->next_idx ++;
1455         mono_g_hash_table_insert (assembly->tokens, GUINT_TO_POINTER (token), klass);
1456         return token;
1457 }
1458
1459 static guint32
1460 mono_image_typedef_or_ref (MonoDynamicAssembly *assembly, MonoType *type)
1461 {
1462         return mono_image_typedef_or_ref_aux (assembly, type, FALSE);
1463 }
1464
1465 /*
1466  * Insert a memberef row into the metadata: the token that point to the memberref
1467  * is returned. Caching is done in the caller (mono_image_get_methodref_token() or
1468  * mono_image_get_fieldref_token()).
1469  * The sig param is an index to an already built signature.
1470  */
1471 static guint32
1472 mono_image_get_memberref_token (MonoDynamicAssembly *assembly, MonoType *type, const char *name, guint32 sig)
1473 {
1474         MonoDynamicTable *table;
1475         guint32 *values;
1476         guint32 token, pclass;
1477         guint32 parent;
1478
1479         parent = mono_image_typedef_or_ref_aux (assembly, type, TRUE);
1480         switch (parent & TYPEDEFORREF_MASK) {
1481         case TYPEDEFORREF_TYPEREF:
1482                 pclass = MEMBERREF_PARENT_TYPEREF;
1483                 break;
1484         case TYPEDEFORREF_TYPESPEC:
1485                 pclass = MEMBERREF_PARENT_TYPESPEC;
1486                 break;
1487         case TYPEDEFORREF_TYPEDEF:
1488                 /* should never get here */
1489         default:
1490                 g_warning ("unknown typeref or def token 0x%08x for %s", parent, name);
1491                 return 0;
1492         }
1493         /* extract the index */
1494         parent >>= TYPEDEFORREF_BITS;
1495
1496         table = &assembly->tables [MONO_TABLE_MEMBERREF];
1497         alloc_table (table, table->rows + 1);
1498         values = table->values + table->next_idx * MONO_MEMBERREF_SIZE;
1499         values [MONO_MEMBERREF_CLASS] = pclass | (parent << MEMBERREF_PARENT_BITS);
1500         values [MONO_MEMBERREF_NAME] = string_heap_insert (&assembly->sheap, name);
1501         values [MONO_MEMBERREF_SIGNATURE] = sig;
1502         token = MONO_TOKEN_MEMBER_REF | table->next_idx;
1503         table->next_idx ++;
1504
1505         return token;
1506 }
1507
1508 static guint32
1509 mono_image_get_methodref_token (MonoDynamicAssembly *assembly, MonoMethod *method)
1510 {
1511         guint32 token;
1512         
1513         token = GPOINTER_TO_UINT (g_hash_table_lookup (assembly->handleref, method));
1514         if (token)
1515                 return token;
1516         token = mono_image_get_memberref_token (assembly, &method->klass->byval_arg,
1517                 method->name,  method_encode_signature (assembly, method->signature));
1518         g_hash_table_insert (assembly->handleref, method, GUINT_TO_POINTER(token));
1519         return token;
1520 }
1521
1522 static guint32
1523 mono_image_get_fieldref_token (MonoDynamicAssembly *assembly, MonoClassField *field, MonoClass *klass)
1524 {
1525         guint32 token;
1526         
1527         token = GPOINTER_TO_UINT (g_hash_table_lookup (assembly->handleref, field));
1528         if (token)
1529                 return token;
1530         field->parent = klass;
1531         token = mono_image_get_memberref_token (assembly, &klass->byval_arg, 
1532                 field->name,  fieldref_encode_signature (assembly, field));
1533         g_hash_table_insert (assembly->handleref, field, GUINT_TO_POINTER(token));
1534         return token;
1535 }
1536
1537 static guint32
1538 mono_reflection_encode_sighelper (MonoDynamicAssembly *assembly, MonoReflectionSigHelper *helper)
1539 {
1540         char *buf;
1541         char *p;
1542         guint32 nargs;
1543         guint32 size;
1544         guint32 i, idx;
1545         char blob_size [6];
1546         char *b = blob_size;
1547
1548         /* FIXME: */
1549         g_assert (helper->type == 2);
1550
1551         if (helper->arguments)
1552                 nargs = mono_array_length (helper->arguments);
1553         else
1554                 nargs = 0;
1555
1556         size = 10 + (nargs * 10);
1557         
1558         p = buf = g_malloc (size);
1559
1560         /* Encode calling convention */
1561         /* Change Any to Standard */
1562         if ((helper->call_conv & 0x03) == 0x03)
1563                 helper->call_conv = 0x01;
1564         /* explicit_this implies has_this */
1565         if (helper->call_conv & 0x40)
1566                 helper->call_conv &= 0x20;
1567
1568         if (helper->call_conv == 0) /* Unmanaged */
1569                 *p = helper->unmanaged_call_conv - 1;
1570         else {
1571                 /* Managed */
1572                 *p = helper->call_conv & 0x60; /* has_this + explicit_this */
1573                 if (helper->call_conv & 0x02) /* varargs */
1574                         *p += 0x05;
1575         }
1576
1577         p++;
1578         mono_metadata_encode_value (nargs, p, &p);
1579         encode_reflection_type (assembly, helper->return_type, p, &p);
1580         for (i = 0; i < nargs; ++i) {
1581                 MonoReflectionType *pt = mono_array_get (helper->arguments, MonoReflectionType*, i);
1582                 encode_reflection_type (assembly, pt, p, &p);
1583         }
1584         /* store length */
1585         g_assert (p - buf < size);
1586         mono_metadata_encode_value (p-buf, b, &b);
1587         idx = add_to_blob_cached (assembly, blob_size, b-blob_size, buf, p-buf);
1588         g_free (buf);
1589
1590         return idx;
1591 }
1592         
1593 static guint32 
1594 mono_image_get_sighelper_token (MonoDynamicAssembly *assembly, MonoReflectionSigHelper *helper)
1595 {
1596         guint32 idx;
1597         MonoDynamicTable *table;
1598         guint32 *values;
1599
1600         table = &assembly->tables [MONO_TABLE_STANDALONESIG];
1601         idx = table->next_idx ++;
1602         table->rows ++;
1603         alloc_table (table, table->rows);
1604         values = table->values + idx * MONO_STAND_ALONE_SIGNATURE_SIZE;
1605
1606         values [MONO_STAND_ALONE_SIGNATURE] =
1607                 mono_reflection_encode_sighelper (assembly, helper);
1608
1609         return idx;
1610 }
1611
1612 static int
1613 reflection_cc_to_file (int call_conv) {
1614         switch (call_conv & 0x3) {
1615         case 0:
1616         case 1: return MONO_CALL_DEFAULT;
1617         case 2: return MONO_CALL_VARARG;
1618         default:
1619                 g_assert_not_reached ();
1620         }
1621         return 0;
1622 }
1623
1624 typedef struct {
1625         MonoType *parent;
1626         MonoMethodSignature *sig;
1627         char *name;
1628         guint32 token;
1629 } ArrayMethod;
1630
1631 static guint32
1632 mono_image_get_array_token (MonoDynamicAssembly *assembly, MonoReflectionArrayMethod *m)
1633 {
1634         guint32 nparams, i;
1635         GList *tmp;
1636         char *name;
1637         MonoMethodSignature *sig;
1638         ArrayMethod *am;
1639         
1640         name = mono_string_to_utf8 (m->name);
1641         nparams = mono_array_length (m->parameters);
1642         sig = g_malloc0 (sizeof (MonoMethodSignature) + sizeof (MonoType*) * nparams);
1643         sig->hasthis = 1;
1644         sig->call_convention = reflection_cc_to_file (m->call_conv);
1645         sig->param_count = nparams;
1646         sig->ret = m->ret? m->ret->type: &mono_defaults.void_class->byval_arg;
1647         for (i = 0; i < nparams; ++i) {
1648                 MonoReflectionType *t = mono_array_get (m->parameters, gpointer, i);
1649                 sig->params [i] = t->type;
1650         }
1651
1652         for (tmp = assembly->array_methods; tmp; tmp = tmp->next) {
1653                 am = tmp->data;
1654                 if (strcmp (name, am->name) == 0 && 
1655                                 mono_metadata_type_equal (am->parent, m->parent->type) &&
1656                                 mono_metadata_signature_equal (am->sig, sig)) {
1657                         g_free (name);
1658                         g_free (sig);
1659                         return am->token;
1660                 }
1661         }
1662         am = g_new0 (ArrayMethod, 1);
1663         am->name = name;
1664         am->sig = sig;
1665         am->parent = m->parent->type;
1666         am->token = mono_image_get_memberref_token (assembly, am->parent,
1667                 name,  method_encode_signature (assembly, sig));
1668         assembly->array_methods = g_list_prepend (assembly->array_methods, am);
1669         m->table_idx = am->token & 0xffffff;
1670         return am->token;
1671 }
1672
1673 /*
1674  * Insert into the metadata tables all the info about the TypeBuilder tb.
1675  * Data in the tables is inserted in a predefined order, since some tables need to be sorted.
1676  */
1677 static void
1678 mono_image_get_type_info (MonoDomain *domain, MonoReflectionTypeBuilder *tb, MonoDynamicAssembly *assembly)
1679 {
1680         MonoDynamicTable *table;
1681         guint *values;
1682         int i, is_object = 0, is_system = 0;
1683         char *n;
1684
1685         table = &assembly->tables [MONO_TABLE_TYPEDEF];
1686         values = table->values + tb->table_idx * MONO_TYPEDEF_SIZE;
1687         values [MONO_TYPEDEF_FLAGS] = tb->attrs;
1688         n = mono_string_to_utf8 (tb->name);
1689         if (strcmp (n, "Object") == 0)
1690                 is_object++;
1691         values [MONO_TYPEDEF_NAME] = string_heap_insert (&assembly->sheap, n);
1692         g_free (n);
1693         n = mono_string_to_utf8 (tb->nspace);
1694         if (strcmp (n, "System") == 0)
1695                 is_system++;
1696         values [MONO_TYPEDEF_NAMESPACE] = string_heap_insert (&assembly->sheap, n);
1697         g_free (n);
1698         if (tb->parent && !(is_system && is_object) && 
1699                 !(tb->attrs & TYPE_ATTRIBUTE_INTERFACE)) { /* interfaces don't have a parent */
1700                 values [MONO_TYPEDEF_EXTENDS] = mono_image_typedef_or_ref (assembly, tb->parent->type);
1701         } else
1702                 values [MONO_TYPEDEF_EXTENDS] = 0;
1703         values [MONO_TYPEDEF_FIELD_LIST] = assembly->tables [MONO_TABLE_FIELD].next_idx;
1704         values [MONO_TYPEDEF_METHOD_LIST] = assembly->tables [MONO_TABLE_METHOD].next_idx;
1705
1706         /*
1707          * if we have explicitlayout or sequentiallayouts, output data in the
1708          * ClassLayout table.
1709          */
1710         if (((tb->attrs & TYPE_ATTRIBUTE_LAYOUT_MASK) != TYPE_ATTRIBUTE_AUTO_LAYOUT) && (tb->class_size != -1)) {
1711                 table = &assembly->tables [MONO_TABLE_CLASSLAYOUT];
1712                 table->rows++;
1713                 alloc_table (table, table->rows);
1714                 values = table->values + table->rows * MONO_CLASS_LAYOUT_SIZE;
1715                 values [MONO_CLASS_LAYOUT_PARENT] = tb->table_idx;
1716                 values [MONO_CLASS_LAYOUT_CLASS_SIZE] = tb->class_size;
1717                 values [MONO_CLASS_LAYOUT_PACKING_SIZE] = tb->packing_size;
1718         }
1719
1720         /* handle interfaces */
1721         if (tb->interfaces) {
1722                 table = &assembly->tables [MONO_TABLE_INTERFACEIMPL];
1723                 i = table->rows;
1724                 table->rows += mono_array_length (tb->interfaces);
1725                 alloc_table (table, table->rows);
1726                 values = table->values + (i + 1) * MONO_INTERFACEIMPL_SIZE;
1727                 for (i = 0; i < mono_array_length (tb->interfaces); ++i) {
1728                         MonoReflectionType* iface = (MonoReflectionType*) mono_array_get (tb->interfaces, gpointer, i);
1729                         values [MONO_INTERFACEIMPL_CLASS] = tb->table_idx;
1730                         values [MONO_INTERFACEIMPL_INTERFACE] = mono_image_typedef_or_ref (assembly, iface->type);
1731                         values += MONO_INTERFACEIMPL_SIZE;
1732                 }
1733         }
1734
1735         /* handle fields */
1736         if (tb->fields) {
1737                 table = &assembly->tables [MONO_TABLE_FIELD];
1738                 table->rows += mono_array_length (tb->fields);
1739                 alloc_table (table, table->rows);
1740                 for (i = 0; i < mono_array_length (tb->fields); ++i)
1741                         mono_image_get_field_info (
1742                                 mono_array_get (tb->fields, MonoReflectionFieldBuilder*, i), assembly);
1743         }
1744
1745         /* handle constructors */
1746         if (tb->ctors) {
1747                 table = &assembly->tables [MONO_TABLE_METHOD];
1748                 table->rows += mono_array_length (tb->ctors);
1749                 alloc_table (table, table->rows);
1750                 for (i = 0; i < mono_array_length (tb->ctors); ++i)
1751                         mono_image_get_ctor_info (domain,
1752                                 mono_array_get (tb->ctors, MonoReflectionCtorBuilder*, i), assembly);
1753         }
1754
1755         /* handle methods */
1756         if (tb->methods) {
1757                 table = &assembly->tables [MONO_TABLE_METHOD];
1758                 table->rows += mono_array_length (tb->methods);
1759                 alloc_table (table, table->rows);
1760                 for (i = 0; i < mono_array_length (tb->methods); ++i)
1761                         mono_image_get_method_info (
1762                                 mono_array_get (tb->methods, MonoReflectionMethodBuilder*, i), assembly);
1763         }
1764
1765         /* Do the same with properties etc.. */
1766         if (tb->events && mono_array_length (tb->events)) {
1767                 table = &assembly->tables [MONO_TABLE_EVENT];
1768                 table->rows += mono_array_length (tb->events);
1769                 alloc_table (table, table->rows);
1770                 table = &assembly->tables [MONO_TABLE_EVENTMAP];
1771                 table->rows ++;
1772                 alloc_table (table, table->rows);
1773                 values = table->values + table->rows * MONO_EVENT_MAP_SIZE;
1774                 values [MONO_EVENT_MAP_PARENT] = tb->table_idx;
1775                 values [MONO_EVENT_MAP_EVENTLIST] = assembly->tables [MONO_TABLE_EVENT].next_idx;
1776                 for (i = 0; i < mono_array_length (tb->events); ++i)
1777                         mono_image_get_event_info (
1778                                 mono_array_get (tb->events, MonoReflectionEventBuilder*, i), assembly);
1779         }
1780         if (tb->properties && mono_array_length (tb->properties)) {
1781                 table = &assembly->tables [MONO_TABLE_PROPERTY];
1782                 table->rows += mono_array_length (tb->properties);
1783                 alloc_table (table, table->rows);
1784                 table = &assembly->tables [MONO_TABLE_PROPERTYMAP];
1785                 table->rows ++;
1786                 alloc_table (table, table->rows);
1787                 values = table->values + table->rows * MONO_PROPERTY_MAP_SIZE;
1788                 values [MONO_PROPERTY_MAP_PARENT] = tb->table_idx;
1789                 values [MONO_PROPERTY_MAP_PROPERTY_LIST] = assembly->tables [MONO_TABLE_PROPERTY].next_idx;
1790                 for (i = 0; i < mono_array_length (tb->properties); ++i)
1791                         mono_image_get_property_info (
1792                                 mono_array_get (tb->properties, MonoReflectionPropertyBuilder*, i), assembly);
1793         }
1794         if (tb->subtypes) {
1795                 MonoDynamicTable *ntable;
1796                 
1797                 table = &assembly->tables [MONO_TABLE_TYPEDEF];
1798                 table->rows += mono_array_length (tb->subtypes);
1799                 alloc_table (table, table->rows);
1800
1801                 ntable = &assembly->tables [MONO_TABLE_NESTEDCLASS];
1802                 ntable->rows += mono_array_length (tb->subtypes);
1803                 alloc_table (ntable, ntable->rows);
1804                 values = ntable->values + ntable->next_idx * MONO_NESTED_CLASS_SIZE;
1805
1806                 for (i = 0; i < mono_array_length (tb->subtypes); ++i) {
1807                         MonoReflectionTypeBuilder *subtype = mono_array_get (tb->subtypes, MonoReflectionTypeBuilder*, i);
1808
1809                         values [MONO_NESTED_CLASS_NESTED] = subtype->table_idx;
1810                         values [MONO_NESTED_CLASS_ENCLOSING] = tb->table_idx;
1811                         /*g_print ("nesting %s (%d) in %s (%d) (rows %d/%d)\n",
1812                                 mono_string_to_utf8 (subtype->name), subtype->table_idx,
1813                                 mono_string_to_utf8 (tb->name), tb->table_idx,
1814                                 ntable->next_idx, ntable->rows);*/
1815                         values += MONO_NESTED_CLASS_SIZE;
1816                         ntable->next_idx++;
1817                 }
1818                 for (i = 0; i < mono_array_length (tb->subtypes); ++i) {
1819                         MonoReflectionTypeBuilder *subtype = mono_array_get (tb->subtypes, MonoReflectionTypeBuilder*, i);
1820
1821                         mono_image_get_type_info (domain, subtype, assembly);
1822                 }
1823         }
1824 }
1825
1826 static void
1827 assign_type_idx (MonoReflectionTypeBuilder *type, MonoDynamicTable *table)
1828 {
1829         int j;
1830
1831         type->table_idx = table->next_idx ++;
1832         if (!type->subtypes)
1833                 return;
1834         for (j = 0; j < mono_array_length (type->subtypes); ++j) {
1835                 MonoReflectionTypeBuilder *subtype = mono_array_get (type->subtypes, MonoReflectionTypeBuilder*, j);
1836                 assign_type_idx (subtype, table);
1837         }
1838 }
1839
1840 static void
1841 params_add_cattrs (MonoDynamicAssembly *assembly, MonoArray *pinfo) {
1842         int i;
1843
1844         if (!pinfo)
1845                 return;
1846         for (i = 0; i < mono_array_length (pinfo); ++i) {
1847                 MonoReflectionParamBuilder *pb;
1848                 pb = mono_array_get (pinfo, MonoReflectionParamBuilder *, i);
1849                 if (!pb)
1850                         continue;
1851                 mono_image_add_cattrs (assembly, pb->table_idx, CUSTOM_ATTR_PARAMDEF, pb->cattrs);
1852         }
1853 }
1854
1855 static void
1856 type_add_cattrs (MonoDynamicAssembly *assembly, MonoReflectionTypeBuilder *tb) {
1857         int i;
1858         
1859         mono_image_add_cattrs (assembly, tb->table_idx, CUSTOM_ATTR_TYPEDEF, tb->cattrs);
1860         if (tb->fields) {
1861                 for (i = 0; i < mono_array_length (tb->fields); ++i) {
1862                         MonoReflectionFieldBuilder* fb;
1863                         fb = mono_array_get (tb->fields, MonoReflectionFieldBuilder*, i);
1864                         mono_image_add_cattrs (assembly, fb->table_idx, CUSTOM_ATTR_FIELDDEF, fb->cattrs);
1865                 }
1866         }
1867         if (tb->events) {
1868                 for (i = 0; i < mono_array_length (tb->events); ++i) {
1869                         MonoReflectionEventBuilder* eb;
1870                         eb = mono_array_get (tb->events, MonoReflectionEventBuilder*, i);
1871                         mono_image_add_cattrs (assembly, eb->table_idx, CUSTOM_ATTR_EVENT, eb->cattrs);
1872                 }
1873         }
1874         if (tb->properties) {
1875                 for (i = 0; i < mono_array_length (tb->properties); ++i) {
1876                         MonoReflectionPropertyBuilder* pb;
1877                         pb = mono_array_get (tb->properties, MonoReflectionPropertyBuilder*, i);
1878                         mono_image_add_cattrs (assembly, pb->table_idx, CUSTOM_ATTR_PROPERTY, pb->cattrs);
1879                 }
1880         }
1881         if (tb->ctors) {
1882                 for (i = 0; i < mono_array_length (tb->ctors); ++i) {
1883                         MonoReflectionCtorBuilder* cb;
1884                         cb = mono_array_get (tb->ctors, MonoReflectionCtorBuilder*, i);
1885                         mono_image_add_cattrs (assembly, cb->table_idx, CUSTOM_ATTR_METHODDEF, cb->cattrs);
1886                         params_add_cattrs (assembly, cb->pinfo);
1887                 }
1888         }
1889
1890         if (tb->methods) {
1891                 for (i = 0; i < mono_array_length (tb->methods); ++i) {
1892                         MonoReflectionMethodBuilder* mb;
1893                         mb = mono_array_get (tb->methods, MonoReflectionMethodBuilder*, i);
1894                         mono_image_add_cattrs (assembly, mb->table_idx, CUSTOM_ATTR_METHODDEF, mb->cattrs);
1895                         params_add_cattrs (assembly, mb->pinfo);
1896                 }
1897         }
1898
1899         if (tb->subtypes) {
1900                 for (i = 0; i < mono_array_length (tb->subtypes); ++i)
1901                         type_add_cattrs (assembly, mono_array_get (tb->subtypes, MonoReflectionTypeBuilder*, i));
1902         }
1903 }
1904
1905 static void
1906 module_add_cattrs (MonoDynamicAssembly *assembly, MonoReflectionModuleBuilder *mb) {
1907         int i;
1908         
1909         mono_image_add_cattrs (assembly, mb->table_idx, CUSTOM_ATTR_MODULE, mb->cattrs);
1910         
1911         /* no types in the module */
1912         if (!mb->types)
1913                 return;
1914         
1915         for (i = 0; i < mono_array_length (mb->types); ++i)
1916                 type_add_cattrs (assembly, mono_array_get (mb->types, MonoReflectionTypeBuilder*, i));
1917 }
1918
1919 static void
1920 mono_image_fill_module_table (MonoDomain *domain, MonoReflectionModuleBuilder *mb, MonoDynamicAssembly *assembly)
1921 {
1922         MonoDynamicTable *table;
1923         int i;
1924         char *name;
1925
1926         table = &assembly->tables [MONO_TABLE_MODULE];
1927         mb->table_idx = table->next_idx ++;
1928         name = mono_string_to_utf8 (mb->module.name);
1929         table->values [mb->table_idx * MONO_MODULE_SIZE + MONO_MODULE_NAME] = string_heap_insert (&assembly->sheap, name);
1930         g_free (name);
1931         i = mono_image_add_stream_data (&assembly->guid, mono_array_addr (mb->guid, char, 0), 16);
1932         i /= 16;
1933         ++i;
1934         table->values [mb->table_idx * MONO_MODULE_SIZE + MONO_MODULE_MVID] = i;
1935         table->values [mb->table_idx * MONO_MODULE_SIZE + MONO_MODULE_ENC] = 0;
1936         table->values [mb->table_idx * MONO_MODULE_SIZE + MONO_MODULE_ENCBASE] = 0;
1937
1938         /* no types in the module */
1939         if (!mb->types)
1940                 return;
1941         
1942         /*
1943          * fill-in info in other tables as well.
1944          */
1945         table = &assembly->tables [MONO_TABLE_TYPEDEF];
1946         table->rows += mono_array_length (mb->types);
1947         alloc_table (table, table->rows);
1948         /*
1949          * We assign here the typedef indexes to avoid mismatches if a type that
1950          * has not yet been stored in the tables is referenced by another type.
1951          */
1952         for (i = 0; i < mono_array_length (mb->types); ++i) {
1953                 MonoReflectionTypeBuilder *type = mono_array_get (mb->types, MonoReflectionTypeBuilder*, i);
1954                 assign_type_idx (type, table);
1955         }
1956         for (i = 0; i < mono_array_length (mb->types); ++i)
1957                 mono_image_get_type_info (domain, mono_array_get (mb->types, MonoReflectionTypeBuilder*, i), assembly);
1958 }
1959
1960 #define align_pointer(base,p)\
1961         do {\
1962                 guint32 __diff = (unsigned char*)(p)-(unsigned char*)(base);\
1963                 if (__diff & 3)\
1964                         (p) += 4 - (__diff & 3);\
1965         } while (0)
1966
1967 static int
1968 compare_semantics (const void *a, const void *b)
1969 {
1970         const guint32 *a_values = a;
1971         const guint32 *b_values = b;
1972         int assoc = a_values [MONO_METHOD_SEMA_ASSOCIATION] - b_values [MONO_METHOD_SEMA_ASSOCIATION];
1973         if (assoc)
1974                 return assoc;
1975         return a_values [MONO_METHOD_SEMA_SEMANTICS] - b_values [MONO_METHOD_SEMA_SEMANTICS];
1976 }
1977
1978 static int
1979 compare_custom_attrs (const void *a, const void *b)
1980 {
1981         const guint32 *a_values = a;
1982         const guint32 *b_values = b;
1983
1984         return a_values [MONO_CUSTOM_ATTR_PARENT] - b_values [MONO_CUSTOM_ATTR_PARENT];
1985 }
1986
1987 static int
1988 compare_field_marshal (const void *a, const void *b)
1989 {
1990         const guint32 *a_values = a;
1991         const guint32 *b_values = b;
1992
1993         return a_values [MONO_FIELD_MARSHAL_PARENT] - b_values [MONO_FIELD_MARSHAL_PARENT];
1994 }
1995
1996 static int
1997 compare_nested (const void *a, const void *b)
1998 {
1999         const guint32 *a_values = a;
2000         const guint32 *b_values = b;
2001
2002         return a_values [MONO_NESTED_CLASS_NESTED] - b_values [MONO_NESTED_CLASS_NESTED];
2003 }
2004
2005 /*
2006  * build_compressed_metadata() fills in the blob of data that represents the 
2007  * raw metadata as it will be saved in the PE file. The five streams are output 
2008  * and the metadata tables are comnpressed from the guint32 array representation, 
2009  * to the compressed on-disk format.
2010  */
2011 static void
2012 build_compressed_metadata (MonoDynamicAssembly *assembly)
2013 {
2014         MonoDynamicTable *table;
2015         int i;
2016         guint64 valid_mask = 0;
2017         guint64 sorted_mask;
2018         guint32 heapt_size = 0;
2019         guint32 meta_size = 256; /* allow for header and other stuff */
2020         guint32 table_offset;
2021         guint32 ntables = 0;
2022         guint64 *int64val;
2023         guint32 *int32val;
2024         guint16 *int16val;
2025         MonoImage *meta;
2026         unsigned char *p;
2027         /*
2028          * We need to use the current ms version or the ms runtime it won't find
2029          * the support dlls. D'oh!
2030          * const char *version = "mono-" VERSION;
2031          */
2032         const char *version = "v1.0.3705";
2033         struct StreamDesc {
2034                 const char *name;
2035                 MonoDynamicStream *stream;
2036         } stream_desc [] = {
2037                 {"#~", &assembly->tstream},
2038                 {"#Strings", &assembly->sheap},
2039                 {"#US", &assembly->us},
2040                 {"#Blob", &assembly->blob},
2041                 {"#GUID", &assembly->guid}
2042         };
2043         
2044         /* tables that are sorted */
2045         sorted_mask = ((guint64)1 << MONO_TABLE_CONSTANT) | ((guint64)1 << MONO_TABLE_FIELDMARSHAL)
2046                 | ((guint64)1 << MONO_TABLE_METHODSEMANTICS) | ((guint64)1 << MONO_TABLE_CLASSLAYOUT)
2047                 | ((guint64)1 << MONO_TABLE_FIELDLAYOUT) | ((guint64)1 << MONO_TABLE_FIELDRVA)
2048                 | ((guint64)1 << MONO_TABLE_IMPLMAP) | ((guint64)1 << MONO_TABLE_NESTEDCLASS)
2049                 | ((guint64)1 << MONO_TABLE_METHODIMPL) | ((guint64)1 << MONO_TABLE_CUSTOMATTRIBUTE)
2050                 | ((guint64)1 << MONO_TABLE_DECLSECURITY);
2051         
2052         /* Compute table sizes */
2053         /* the MonoImage has already been created in mono_image_basic_init() */
2054         meta = assembly->assembly.image;
2055         
2056         /* Setup the info used by compute_sizes () */
2057         meta->idx_blob_wide = assembly->blob.index >= 65536 ? 1 : 0;
2058         meta->idx_guid_wide = assembly->guid.index >= 65536 ? 1 : 0;
2059         meta->idx_string_wide = assembly->sheap.index >= 65536 ? 1 : 0;
2060
2061         meta_size += assembly->blob.index;
2062         meta_size += assembly->guid.index;
2063         meta_size += assembly->sheap.index;
2064         meta_size += assembly->us.index;
2065
2066         for (i=0; i < 64; ++i)
2067                 meta->tables [i].rows = assembly->tables [i].rows;
2068         
2069         for (i = 0; i < 64; i++){
2070                 if (meta->tables [i].rows == 0)
2071                         continue;
2072                 valid_mask |= (guint64)1 << i;
2073                 ntables ++;
2074                 meta->tables [i].row_size = mono_metadata_compute_size (
2075                         meta, i, &meta->tables [i].size_bitfield);
2076                 heapt_size += meta->tables [i].row_size * meta->tables [i].rows;
2077         }
2078         heapt_size += 24; /* #~ header size */
2079         heapt_size += ntables * 4;
2080         meta_size += heapt_size;
2081         meta->raw_metadata = g_malloc0 (meta_size);
2082         p = meta->raw_metadata;
2083         /* the metadata signature */
2084         *p++ = 'B'; *p++ = 'S'; *p++ = 'J'; *p++ = 'B';
2085         /* version numbers and 4 bytes reserved */
2086         int16val = (guint16*)p;
2087         *int16val++ = GUINT16_TO_LE (1);
2088         *int16val = GUINT16_TO_LE (1);
2089         p += 8;
2090         /* version string */
2091         int32val = (guint32*)p;
2092         *int32val = GUINT32_TO_LE ((strlen (version) + 3) & (~3)); /* needs to be multiple of 4 */
2093         p += 4;
2094         memcpy (p, version, GUINT32_FROM_LE (*int32val));
2095         p += GUINT32_FROM_LE (*int32val);
2096         align_pointer (meta->raw_metadata, p);
2097         int16val = (guint16*)p;
2098         *int16val++ = GUINT16_TO_LE (0); /* flags must be 0 */
2099         *int16val = GUINT16_TO_LE (5); /* number of streams */
2100         p += 4;
2101
2102         /*
2103          * write the stream info.
2104          */
2105         table_offset = (p - (unsigned char*)meta->raw_metadata) + 5 * 8 + 40; /* room needed for stream headers */
2106         table_offset += 3; table_offset &= ~3;
2107
2108         assembly->tstream.index = heapt_size;
2109         for (i = 0; i < 5; ++i) {
2110                 int32val = (guint32*)p;
2111                 stream_desc [i].stream->offset = table_offset;
2112                 *int32val++ = GUINT32_TO_LE (table_offset);
2113                 *int32val = GUINT32_TO_LE (stream_desc [i].stream->index);
2114                 table_offset += GUINT32_FROM_LE (*int32val);
2115                 table_offset += 3; table_offset &= ~3;
2116                 p += 8;
2117                 strcpy (p, stream_desc [i].name);
2118                 p += strlen (stream_desc [i].name) + 1;
2119                 align_pointer (meta->raw_metadata, p);
2120         }
2121         /* 
2122          * now copy the data, the table stream header and contents goes first.
2123          */
2124         g_assert ((p - (unsigned char*)meta->raw_metadata) < assembly->tstream.offset);
2125         p = meta->raw_metadata + assembly->tstream.offset;
2126         int32val = (guint32*)p;
2127         *int32val = GUINT32_TO_LE (0); /* reserved */
2128         p += 4;
2129         *p++ = 1; /* version */
2130         *p++ = 0;
2131         if (meta->idx_string_wide)
2132                 *p |= 0x01;
2133         if (meta->idx_guid_wide)
2134                 *p |= 0x02;
2135         if (meta->idx_blob_wide)
2136                 *p |= 0x04;
2137         ++p;
2138         *p++ = 0; /* reserved */
2139         int64val = (guint64*)p;
2140         *int64val++ = GUINT64_TO_LE (valid_mask);
2141         *int64val++ = GUINT64_TO_LE (valid_mask & sorted_mask); /* bitvector of sorted tables  */
2142         p += 16;
2143         int32val = (guint32*)p;
2144         for (i = 0; i < 64; i++){
2145                 if (meta->tables [i].rows == 0)
2146                         continue;
2147                 *int32val++ = GUINT32_TO_LE (meta->tables [i].rows);
2148         }
2149         p = (unsigned char*)int32val;
2150
2151         /* sort the tables that still need sorting */
2152         table = &assembly->tables [MONO_TABLE_METHODSEMANTICS];
2153         if (table->rows)
2154                 qsort (table->values + MONO_METHOD_SEMA_SIZE, table->rows, sizeof (guint32) * MONO_METHOD_SEMA_SIZE, compare_semantics);
2155         table = &assembly->tables [MONO_TABLE_CUSTOMATTRIBUTE];
2156         if (table->rows)
2157                 qsort (table->values + MONO_CUSTOM_ATTR_SIZE, table->rows, sizeof (guint32) * MONO_CUSTOM_ATTR_SIZE, compare_custom_attrs);
2158         table = &assembly->tables [MONO_TABLE_FIELDMARSHAL];
2159         if (table->rows)
2160                 qsort (table->values + MONO_FIELD_MARSHAL_SIZE, table->rows, sizeof (guint32) * MONO_FIELD_MARSHAL_SIZE, compare_field_marshal);
2161         table = &assembly->tables [MONO_TABLE_NESTEDCLASS];
2162         if (table->rows)
2163                 qsort (table->values + MONO_NESTED_CLASS_SIZE, table->rows, sizeof (guint32) * MONO_NESTED_CLASS_SIZE, compare_nested);
2164
2165         /* compress the tables */
2166         for (i = 0; i < 64; i++){
2167                 int row, col;
2168                 guint32 *values;
2169                 guint32 bitfield = meta->tables [i].size_bitfield;
2170                 if (!meta->tables [i].rows)
2171                         continue;
2172                 if (assembly->tables [i].columns != mono_metadata_table_count (bitfield))
2173                         g_error ("col count mismatch in %d: %d %d", i, assembly->tables [i].columns, mono_metadata_table_count (bitfield));
2174                 meta->tables [i].base = p;
2175                 for (row = 1; row <= meta->tables [i].rows; ++row) {
2176                         values = assembly->tables [i].values + row * assembly->tables [i].columns;
2177                         for (col = 0; col < assembly->tables [i].columns; ++col) {
2178                                 switch (mono_metadata_table_size (bitfield, col)) {
2179                                 case 1:
2180                                         *p++ = values [col];
2181                                         break;
2182                                 case 2:
2183                                         *p++ = values [col] & 0xff;
2184                                         *p++ = (values [col] >> 8) & 0xff;
2185                                         break;
2186                                 case 4:
2187                                         *p++ = values [col] & 0xff;
2188                                         *p++ = (values [col] >> 8) & 0xff;
2189                                         *p++ = (values [col] >> 16) & 0xff;
2190                                         *p++ = (values [col] >> 24) & 0xff;
2191                                         break;
2192                                 default:
2193                                         g_assert_not_reached ();
2194                                 }
2195                         }
2196                 }
2197                 g_assert ((p - (const unsigned char*)meta->tables [i].base) == (meta->tables [i].rows * meta->tables [i].row_size));
2198         }
2199         
2200         g_assert (assembly->guid.offset + assembly->guid.index < meta_size);
2201         memcpy (meta->raw_metadata + assembly->sheap.offset, assembly->sheap.data, assembly->sheap.index);
2202         memcpy (meta->raw_metadata + assembly->us.offset, assembly->us.data, assembly->us.index);
2203         memcpy (meta->raw_metadata + assembly->blob.offset, assembly->blob.data, assembly->blob.index);
2204         memcpy (meta->raw_metadata + assembly->guid.offset, assembly->guid.data, assembly->guid.index);
2205
2206         assembly->meta_size = assembly->guid.offset + assembly->guid.index;
2207 }
2208
2209 /*
2210  * Some tables in metadata need to be sorted according to some criteria, but
2211  * when methods and fields are first created with reflection, they may be assigned a token
2212  * that doesn't correspond to the final token they will get assigned after the sorting.
2213  * ILGenerator.cs keeps a fixup table that maps the position of tokens in the IL code stream
2214  * with the reflection objects that represent them. Once all the tables are set up, the 
2215  * reflection objects will contains the correct table index. fixup_method() will fixup the
2216  * tokens for the method with ILGenerator @ilgen.
2217  */
2218 static void
2219 fixup_method (MonoReflectionILGen *ilgen, gpointer value, MonoDynamicAssembly *assembly) {
2220         guint32 code_idx = GPOINTER_TO_UINT (value);
2221         MonoReflectionILTokenInfo *iltoken;
2222         MonoReflectionFieldBuilder *field;
2223         MonoReflectionCtorBuilder *ctor;
2224         MonoReflectionMethodBuilder *method;
2225         MonoReflectionTypeBuilder *tb;
2226         guint32 i, idx;
2227         unsigned char *target;
2228
2229         for (i = 0; i < ilgen->num_token_fixups; ++i) {
2230                 iltoken = (MonoReflectionILTokenInfo *)mono_array_addr_with_size (ilgen->token_fixups, sizeof (MonoReflectionILTokenInfo), i);
2231                 target = assembly->code.data + code_idx + iltoken->code_pos;
2232                 switch (target [3]) {
2233                 case MONO_TABLE_FIELD:
2234                         if (strcmp (iltoken->member->vtable->klass->name, "FieldBuilder"))
2235                                 g_assert_not_reached ();
2236                         field = (MonoReflectionFieldBuilder *)iltoken->member;
2237                         idx = field->table_idx;
2238                         break;
2239                 case MONO_TABLE_METHOD:
2240                         if (!strcmp (iltoken->member->vtable->klass->name, "MethodBuilder")) {
2241                                 method = (MonoReflectionMethodBuilder *)iltoken->member;
2242                                 idx = method->table_idx;
2243                         } else if (!strcmp (iltoken->member->vtable->klass->name, "ConstructorBuilder")) {
2244                                 ctor = (MonoReflectionCtorBuilder *)iltoken->member;
2245                                 idx = ctor->table_idx;
2246                         } else {
2247                                 g_assert_not_reached ();
2248                         }
2249                         break;
2250                 case MONO_TABLE_TYPEDEF:
2251                         if (strcmp (iltoken->member->vtable->klass->name, "TypeBuilder"))
2252                                 g_assert_not_reached ();
2253                         tb = (MonoReflectionTypeBuilder *)iltoken->member;
2254                         idx = tb->table_idx;
2255                         break;
2256                 default:
2257                         g_error ("got unexpected table 0x%02x in fixup", target [3]);
2258                 }
2259                 target [0] = idx & 0xff;
2260                 target [1] = (idx >> 8) & 0xff;
2261                 target [2] = (idx >> 16) & 0xff;
2262         }
2263 }
2264
2265 static void
2266 assembly_add_resource (MonoDynamicAssembly *assembly, MonoReflectionResource *rsrc)
2267 {
2268         MonoDynamicTable *table;
2269         guint32 *values;
2270         char blob_size [6];
2271         guchar hash [20];
2272         char *b = blob_size;
2273         char *name, *sname;
2274         guint32 idx, offset;
2275
2276         if (rsrc->filename) {
2277                 name = mono_string_to_utf8 (rsrc->filename);
2278                 sname = g_path_get_basename (name);
2279         
2280                 table = &assembly->tables [MONO_TABLE_FILE];
2281                 table->rows++;
2282                 alloc_table (table, table->rows);
2283                 values = table->values + table->next_idx * MONO_FILE_SIZE;
2284                 values [MONO_FILE_FLAGS] = FILE_CONTAINS_NO_METADATA;
2285                 values [MONO_FILE_NAME] = string_heap_insert (&assembly->sheap, sname);
2286                 g_free (sname);
2287
2288                 mono_sha1_get_digest_from_file (name, hash);
2289                 mono_metadata_encode_value (20, b, &b);
2290                 values [MONO_FILE_HASH_VALUE] = mono_image_add_stream_data (&assembly->blob, blob_size, b-blob_size);
2291                 mono_image_add_stream_data (&assembly->blob, hash, 20);
2292                 g_free (name);
2293                 idx = table->next_idx++;
2294                 idx = IMPLEMENTATION_FILE | (idx << IMPLEMENTATION_BITS);
2295                 offset = 0;
2296         } else {
2297                 char sizebuf [4];
2298                 offset = mono_array_length (rsrc->data);
2299                 sizebuf [0] = offset; sizebuf [1] = offset >> 8;
2300                 sizebuf [2] = offset >> 16; sizebuf [3] = offset >> 24;
2301                 offset = mono_image_add_stream_data (&assembly->resources, sizebuf, 4);
2302                 mono_image_add_stream_data (&assembly->resources, mono_array_addr (rsrc->data, char, 0), mono_array_length (rsrc->data));
2303                 idx = 0;
2304         }
2305
2306         table = &assembly->tables [MONO_TABLE_MANIFESTRESOURCE];
2307         table->rows++;
2308         alloc_table (table, table->rows);
2309         values = table->values + table->next_idx * MONO_MANIFEST_SIZE;
2310         values [MONO_MANIFEST_OFFSET] = offset;
2311         values [MONO_MANIFEST_FLAGS] = rsrc->attrs;
2312         name = mono_string_to_utf8 (rsrc->name);
2313         values [MONO_MANIFEST_NAME] = string_heap_insert (&assembly->sheap, name);
2314         g_free (name);
2315         values [MONO_MANIFEST_IMPLEMENTATION] = idx;
2316         table->next_idx++;
2317 }
2318
2319 static void
2320 set_version_from_string (MonoString *version, guint32 *values)
2321 {
2322         gchar *ver, *p, *str;
2323         guint32 i;
2324         
2325         values [MONO_ASSEMBLY_MAJOR_VERSION] = 0;
2326         values [MONO_ASSEMBLY_MINOR_VERSION] = 0;
2327         values [MONO_ASSEMBLY_REV_NUMBER] = 0;
2328         values [MONO_ASSEMBLY_BUILD_NUMBER] = 0;
2329         if (!version)
2330                 return;
2331         ver = str = mono_string_to_utf8 (version);
2332         for (i = 0; i < 4; ++i) {
2333                 values [MONO_ASSEMBLY_MAJOR_VERSION + i] = strtol (ver, &p, 10);
2334                 switch (*p) {
2335                 case '.':
2336                         p++;
2337                         break;
2338                 case '*':
2339                         /* handle Revision and Build */
2340                         p++;
2341                         break;
2342                 }
2343                 ver = p;
2344         }
2345         g_free (str);
2346 }
2347
2348 static guint32
2349 load_public_key (MonoString *fname, MonoDynamicAssembly *assembly) {
2350         char *name, *content;
2351         gsize len;
2352         guint32 token = 0;
2353
2354         if (!fname)
2355                 return token;
2356         name = mono_string_to_utf8 (fname);
2357         if (g_file_get_contents (name, &content, &len, NULL)) {
2358                 char blob_size [6];
2359                 char *b = blob_size;
2360                 /* check it's a public key or keypair */
2361                 mono_metadata_encode_value (len, b, &b);
2362                 token = mono_image_add_stream_data (&assembly->blob, blob_size, b - blob_size);
2363                 mono_image_add_stream_data (&assembly->blob, content, len);
2364                 g_free (content);
2365                 /* need to get the actual value from the key type... */
2366                 assembly->strong_name_size = 128;
2367                 assembly->strong_name = g_malloc0 (assembly->strong_name_size);
2368         }
2369         /* FIXME: how do we tell mcs if loading fails? */
2370         g_free (name);
2371         return token;
2372 }
2373
2374 /*
2375  * mono_image_build_metadata() will fill the info in all the needed metadata tables
2376  * for the AssemblyBuilder @assemblyb: it iterates over the assembly modules
2377  * and recursively outputs the info for a module. Each module will output all the info
2378  * about it's types etc.
2379  * At the end of the process, method and field tokens are fixed up and the on-disk
2380  * compressed metadata representation is created.
2381  */
2382 void
2383 mono_image_build_metadata (MonoReflectionAssemblyBuilder *assemblyb)
2384 {
2385         MonoDynamicTable *table;
2386         MonoDynamicAssembly *assembly = assemblyb->dynamic_assembly;
2387         MonoDomain *domain = mono_object_domain (assemblyb);
2388         guint32 len;
2389         guint32 *values;
2390         char *name;
2391         int i;
2392
2393         if (assembly->text_rva)
2394                 return;
2395
2396         assembly->text_rva = START_TEXT_RVA;
2397
2398         table = &assembly->tables [MONO_TABLE_ASSEMBLY];
2399         alloc_table (table, 1);
2400         values = table->values + MONO_ASSEMBLY_SIZE;
2401         values [MONO_ASSEMBLY_HASH_ALG] = assemblyb->algid? assemblyb->algid: ASSEMBLY_HASH_SHA1;
2402         name = mono_string_to_utf8 (assemblyb->name);
2403         values [MONO_ASSEMBLY_NAME] = string_heap_insert (&assembly->sheap, name);
2404         g_free (name);
2405         if (assemblyb->culture) {
2406                 name = mono_string_to_utf8 (assemblyb->culture);
2407                 values [MONO_ASSEMBLY_CULTURE] = string_heap_insert (&assembly->sheap, name);
2408                 g_free (name);
2409         } else {
2410                 values [MONO_ASSEMBLY_CULTURE] = string_heap_insert (&assembly->sheap, "");
2411         }
2412         values [MONO_ASSEMBLY_PUBLIC_KEY] = load_public_key (assemblyb->keyfile, assembly);
2413         values [MONO_ASSEMBLY_FLAGS] = assemblyb->flags;
2414         set_version_from_string (assemblyb->version, values);
2415
2416         table = &assembly->tables [MONO_TABLE_TYPEDEF];
2417         table->rows = 1; /* .<Module> */
2418         table->next_idx++;
2419         alloc_table (table, table->rows);
2420         /*
2421          * Set the first entry.
2422          */
2423         values = table->values + table->columns;
2424         values [MONO_TYPEDEF_FLAGS] = 0;
2425         values [MONO_TYPEDEF_NAME] = string_heap_insert (&assembly->sheap, "<Module>") ;
2426         values [MONO_TYPEDEF_NAMESPACE] = string_heap_insert (&assembly->sheap, "") ;
2427         values [MONO_TYPEDEF_EXTENDS] = 0;
2428         values [MONO_TYPEDEF_FIELD_LIST] = 1;
2429         values [MONO_TYPEDEF_METHOD_LIST] = 1;
2430
2431         /* 
2432          * handle global methods 
2433          * FIXME: test what to do when global methods are defined in multiple modules.
2434          */
2435         if (assemblyb->modules) {
2436                 MonoReflectionModuleBuilder *mod = mono_array_get (assemblyb->modules, MonoReflectionModuleBuilder*, 0);
2437                 if (mod->global_methods) {
2438                         table = &assembly->tables [MONO_TABLE_METHOD];
2439                         table->rows += mono_array_length (mod->global_methods);
2440                         alloc_table (table, table->rows);
2441                         for (i = 0; i < mono_array_length (mod->global_methods); ++i)
2442                                 mono_image_get_method_info (
2443                                         mono_array_get (mod->global_methods, MonoReflectionMethodBuilder*, i), assembly);
2444                 }
2445         }
2446
2447         if (assemblyb->modules) {
2448                 len = mono_array_length (assemblyb->modules);
2449                 table = &assembly->tables [MONO_TABLE_MODULE];
2450                 alloc_table (table, len);
2451                 for (i = 0; i < len; ++i)
2452                         mono_image_fill_module_table (domain, mono_array_get (assemblyb->modules, MonoReflectionModuleBuilder*, i), assembly);
2453         } else {
2454                 table = &assembly->tables [MONO_TABLE_MODULE];
2455                 table->rows++;
2456                 alloc_table (table, table->rows);
2457                 table->values [table->next_idx * MONO_MODULE_SIZE + MONO_MODULE_NAME] = string_heap_insert (&assembly->sheap, "RefEmit_YouForgotToDefineAModule");
2458                 table->next_idx ++;
2459         }
2460
2461         /* 
2462          * table->rows is already set above and in mono_image_fill_module_table.
2463          */
2464         /* add all the custom attributes at the end, once all the indexes are stable */
2465         mono_image_add_cattrs (assembly, 1, CUSTOM_ATTR_ASSEMBLY, assemblyb->cattrs);
2466
2467         if (assemblyb->modules) {
2468                 len = mono_array_length (assemblyb->modules);
2469                 for (i = 0; i < len; ++i)
2470                         module_add_cattrs (assembly, mono_array_get (assemblyb->modules, MonoReflectionModuleBuilder*, i));
2471         }
2472
2473         /* fixup tokens */
2474         mono_g_hash_table_foreach (assembly->token_fixups, (GHFunc)fixup_method, assembly);
2475 }
2476
2477 /*
2478  * mono_image_insert_string:
2479  * @assembly: assembly builder object
2480  * @str: a string
2481  *
2482  * Insert @str into the user string stream of @assembly.
2483  */
2484 guint32
2485 mono_image_insert_string (MonoReflectionAssemblyBuilder *assembly, MonoString *str)
2486 {
2487         guint32 idx;
2488         char buf [16];
2489         char *b = buf;
2490         
2491         MONO_ARCH_SAVE_REGS;
2492
2493         if (!assembly->dynamic_assembly)
2494                 mono_image_basic_init (assembly);
2495         mono_metadata_encode_value (1 | (str->length * 2), b, &b);
2496         idx = mono_image_add_stream_data (&assembly->dynamic_assembly->us, buf, b-buf);
2497 #if G_BYTE_ORDER != G_LITTLE_ENDIAN
2498         {
2499                 char *swapped = g_malloc (2 * mono_string_length (str));
2500                 const char *p = (const char*)mono_string_chars (str);
2501
2502                 swap_with_size (swapped, p, 2, mono_string_length (str));
2503                 mono_image_add_stream_data (&assembly->dynamic_assembly->us, swapped, str->length * 2);
2504                 g_free (swapped);
2505         }
2506 #else
2507         mono_image_add_stream_data (&assembly->dynamic_assembly->us, (const char*)mono_string_chars (str), str->length * 2);
2508 #endif
2509         mono_image_add_stream_data (&assembly->dynamic_assembly->us, "", 1);
2510
2511         mono_g_hash_table_insert (assembly->dynamic_assembly->tokens, 
2512                                                           GUINT_TO_POINTER (MONO_TOKEN_STRING | idx), str);
2513
2514         return MONO_TOKEN_STRING | idx;
2515 }
2516
2517 /*
2518  * mono_image_create_token:
2519  * @assembly: a dynamic assembly
2520  * @obj:
2521  *
2522  * Get a token to insert in the IL code stream for the given MemberInfo.
2523  * @obj can be one of:
2524  *      ConstructorBuilder
2525  *      MethodBuilder
2526  *      FieldBuilder
2527  *      MonoCMethod
2528  *      MonoMethod
2529  *      MonoField
2530  *      MonoType
2531  *      TypeBuilder
2532  */
2533 guint32
2534 mono_image_create_token (MonoDynamicAssembly *assembly, MonoObject *obj)
2535 {
2536         MonoClass *klass;
2537         guint32 token;
2538
2539         if (!obj)
2540                 g_error ("System.Array methods not yet supported");
2541         
2542         klass = obj->vtable->klass;
2543         if (strcmp (klass->name, "MethodBuilder") == 0) {
2544                 MonoReflectionMethodBuilder *mb = (MonoReflectionMethodBuilder *)obj;
2545                 token = mb->table_idx | MONO_TOKEN_METHOD_DEF;
2546                 /*g_print ("got token 0x%08x for %s\n", token, mono_string_to_utf8 (mb->name));*/
2547         }
2548         else if (strcmp (klass->name, "ConstructorBuilder") == 0) {
2549                 MonoReflectionCtorBuilder *mb = (MonoReflectionCtorBuilder *)obj;
2550                 token = mb->table_idx | MONO_TOKEN_METHOD_DEF;
2551                 /*g_print ("got token 0x%08x for %s\n", token, mono_string_to_utf8 (mb->name));*/
2552         }
2553         else if (strcmp (klass->name, "FieldBuilder") == 0) {
2554                 MonoReflectionFieldBuilder *mb = (MonoReflectionFieldBuilder *)obj;
2555                 token = mb->table_idx | MONO_TOKEN_FIELD_DEF;
2556         }
2557         else if (strcmp (klass->name, "TypeBuilder") == 0) {
2558                 MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder *)obj;
2559                 token = tb->table_idx | MONO_TOKEN_TYPE_DEF;
2560         }
2561         else if (strcmp (klass->name, "MonoType") == 0) {
2562                 MonoReflectionType *tb = (MonoReflectionType *)obj;
2563                 token = mono_metadata_token_from_dor (
2564                         mono_image_typedef_or_ref (assembly, tb->type));
2565         }
2566         else if (strcmp (klass->name, "MonoCMethod") == 0 ||
2567                         strcmp (klass->name, "MonoMethod") == 0) {
2568                 MonoReflectionMethod *m = (MonoReflectionMethod *)obj;
2569                 token = mono_image_get_methodref_token (assembly, m->method);
2570                 /*g_print ("got token 0x%08x for %s\n", token, m->method->name);*/
2571         }
2572         else if (strcmp (klass->name, "MonoField") == 0) {
2573                 MonoReflectionField *f = (MonoReflectionField *)obj;
2574                 token = mono_image_get_fieldref_token (assembly, f->field, f->klass);
2575                 /*g_print ("got token 0x%08x for %s\n", token, f->field->name);*/
2576         }
2577         else if (strcmp (klass->name, "MonoArrayMethod") == 0) {
2578                 MonoReflectionArrayMethod *m = (MonoReflectionArrayMethod *)obj;
2579                 token = mono_image_get_array_token (assembly, m);
2580         }
2581         else if (strcmp (klass->name, "SignatureHelper") == 0) {
2582                 MonoReflectionSigHelper *s = (MonoReflectionSigHelper*)obj;
2583                 token = MONO_TOKEN_SIGNATURE | mono_image_get_sighelper_token (assembly, s);
2584         }
2585         else
2586                 g_error ("requested token for %s\n", klass->name);
2587
2588         mono_g_hash_table_insert (assembly->tokens, GUINT_TO_POINTER (token),
2589                                                           obj);
2590
2591         return token;
2592 }
2593
2594 typedef struct {
2595         guint32 import_lookup_table;
2596         guint32 timestamp;
2597         guint32 forwarder;
2598         guint32 name_rva;
2599         guint32 import_address_table_rva;
2600 } MonoIDT;
2601
2602 typedef struct {
2603         guint32 name_rva;
2604         guint32 flags;
2605 } MonoILT;
2606
2607 static void register_assembly (MonoDomain *domain, MonoReflectionAssembly *res, MonoAssembly *assembly);
2608
2609 static MonoImage*
2610 create_dynamic_mono_image (char *assembly_name, char *module_name)
2611 {
2612         MonoImage *image;
2613
2614         image = g_new0 (MonoImage, 1);
2615         
2616         /* keep in sync with image.c */
2617         image->name = assembly_name;
2618         image->assembly_name = image->name; /* they may be different */
2619         image->module_name = module_name;
2620         image->references = g_new0 (MonoAssembly*, 1);
2621         image->references [0] = NULL;
2622
2623         image->method_cache = g_hash_table_new (g_direct_hash, g_direct_equal);
2624         image->class_cache = g_hash_table_new (g_direct_hash, g_direct_equal);
2625         image->name_cache = g_hash_table_new (g_str_hash, g_str_equal);
2626         image->array_cache = g_hash_table_new (g_direct_hash, g_direct_equal);
2627
2628         image->delegate_begin_invoke_cache = 
2629                 g_hash_table_new ((GHashFunc)mono_signature_hash, 
2630                                   (GCompareFunc)mono_metadata_signature_equal);
2631         image->delegate_end_invoke_cache = 
2632                 g_hash_table_new ((GHashFunc)mono_signature_hash, 
2633                                   (GCompareFunc)mono_metadata_signature_equal);
2634         image->delegate_invoke_cache = 
2635                 g_hash_table_new ((GHashFunc)mono_signature_hash, 
2636                                   (GCompareFunc)mono_metadata_signature_equal);
2637
2638         image->runtime_invoke_cache = g_hash_table_new (g_direct_hash, g_direct_equal);
2639         image->managed_wrapper_cache = g_hash_table_new (g_direct_hash, g_direct_equal);
2640         image->native_wrapper_cache = g_hash_table_new (g_direct_hash, g_direct_equal);
2641         image->remoting_invoke_cache = g_hash_table_new (g_direct_hash, g_direct_equal);
2642
2643         return image;
2644 }
2645
2646 /*
2647  * mono_image_basic_init:
2648  * @assembly: an assembly builder object
2649  *
2650  * Create the MonoImage that represents the assembly builder and setup some
2651  * of the helper hash table and the basic metadata streams.
2652  */
2653 void
2654 mono_image_basic_init (MonoReflectionAssemblyBuilder *assemblyb)
2655 {
2656         static const guchar entrycode [16] = {0xff, 0x25, 0};
2657         MonoDynamicAssembly *assembly;
2658         MonoImage *image;
2659         int i;
2660         
2661         MONO_ARCH_SAVE_REGS;
2662
2663         if (assemblyb->dynamic_assembly)
2664                 return;
2665
2666 #if HAVE_BOEHM_GC
2667         assembly = assemblyb->dynamic_assembly = GC_MALLOC (sizeof (MonoDynamicAssembly));
2668 #else
2669         assembly = assemblyb->dynamic_assembly = g_new0 (MonoDynamicAssembly, 1);
2670 #endif
2671
2672         assembly->assembly.dynamic = assembly;
2673         assemblyb->assembly.assembly = (MonoAssembly*)assembly;
2674         assembly->token_fixups = mono_g_hash_table_new (g_direct_hash, g_direct_equal);
2675         assembly->handleref = g_hash_table_new (g_direct_hash, g_direct_equal);
2676         assembly->tokens = mono_g_hash_table_new (g_direct_hash, g_direct_equal);
2677         assembly->typeref = g_hash_table_new ((GHashFunc)mono_metadata_type_hash, (GCompareFunc)mono_metadata_type_equal);
2678         assembly->blob_cache = g_hash_table_new ((GHashFunc)mono_blob_entry_hash, (GCompareFunc)mono_blob_entry_equal);
2679
2680         string_heap_init (&assembly->sheap);
2681         mono_image_add_stream_data (&assembly->us, "", 1);
2682         add_to_blob_cached (assembly, (char*) "", 1, NULL, 0);
2683         /* import tables... */
2684         mono_image_add_stream_data (&assembly->code, entrycode, sizeof (entrycode));
2685         assembly->iat_offset = mono_image_add_stream_zero (&assembly->code, 8); /* two IAT entries */
2686         assembly->idt_offset = mono_image_add_stream_zero (&assembly->code, 2 * sizeof (MonoIDT)); /* two IDT entries */
2687         mono_image_add_stream_zero (&assembly->code, 2); /* flags for name entry */
2688         assembly->imp_names_offset = mono_image_add_stream_data (&assembly->code, "_CorExeMain", 12);
2689         mono_image_add_stream_data (&assembly->code, "mscoree.dll", 12);
2690         assembly->ilt_offset = mono_image_add_stream_zero (&assembly->code, 8); /* two ILT entries */
2691         stream_data_align (&assembly->code);
2692
2693         assembly->cli_header_offset = mono_image_add_stream_zero (&assembly->code, sizeof (MonoCLIHeader));
2694
2695         for (i=0; i < 64; ++i) {
2696                 assembly->tables [i].next_idx = 1;
2697                 assembly->tables [i].columns = table_sizes [i];
2698         }
2699
2700         image = create_dynamic_mono_image (mono_string_to_utf8 (assemblyb->name), g_strdup ("RefEmit_YouForgotToDefineAModule"));
2701         assembly->assembly.aname.name = image->name;
2702         image->assembly = (MonoAssembly*)assembly;
2703         assembly->assembly.image = image;
2704
2705         register_assembly (mono_object_domain (assemblyb), &assemblyb->assembly, &assembly->assembly);
2706         mono_assembly_invoke_load_hook ((MonoAssembly*)assembly);
2707 }
2708
2709 static int
2710 calc_section_size (MonoDynamicAssembly *assembly)
2711 {
2712         int nsections = 0;
2713
2714         /* alignment constraints */
2715         assembly->code.index += 3;
2716         assembly->code.index &= ~3;
2717         assembly->meta_size += 3;
2718         assembly->meta_size &= ~3;
2719         assembly->resources.index += 3;
2720         assembly->resources.index &= ~3;
2721
2722         assembly->sections [MONO_SECTION_TEXT].size = assembly->meta_size + assembly->code.index + assembly->resources.index + assembly->strong_name_size;
2723         assembly->sections [MONO_SECTION_TEXT].attrs = SECT_FLAGS_HAS_CODE | SECT_FLAGS_MEM_EXECUTE | SECT_FLAGS_MEM_READ;
2724         nsections++;
2725
2726         assembly->sections [MONO_SECTION_RELOC].size = 12;
2727         assembly->sections [MONO_SECTION_RELOC].attrs = SECT_FLAGS_MEM_READ | SECT_FLAGS_MEM_DISCARDABLE | SECT_FLAGS_HAS_INITIALIZED_DATA;
2728         nsections++;
2729
2730         return nsections;
2731 }
2732
2733 /*
2734  * mono_image_create_pefile:
2735  * @assemblyb: an assembly builder object
2736  * 
2737  * When we need to save an assembly, we first call this function that ensures the metadata 
2738  * tables are built for all the modules in the assembly. This function creates the PE-COFF
2739  * header, the image sections, the CLI header etc. all the data is written in
2740  * assembly->pefile where it can be easily retrieved later in chunks.
2741  */
2742 void
2743 mono_image_create_pefile (MonoReflectionAssemblyBuilder *assemblyb) {
2744         MonoMSDOSHeader *msdos;
2745         MonoDotNetHeader *header;
2746         MonoSectionTable *section;
2747         MonoCLIHeader *cli_header;
2748         guint32 size, image_size, virtual_base, text_offset;
2749         guint32 header_start, section_start, file_offset, virtual_offset;
2750         MonoDynamicAssembly *assembly;
2751         MonoDynamicStream *pefile;
2752         int i, nsections;
2753         guint32 *rva, value;
2754         guint16 *data16;
2755         guchar *p;
2756         static const unsigned char msheader[] = {
2757                 0x4d, 0x5a, 0x90, 0x00, 0x03, 0x00, 0x00, 0x00,  0x04, 0x00, 0x00, 0x00, 0xff, 0xff, 0x00, 0x00,
2758                 0xb8, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,  0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
2759                 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
2760                 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,  0x00, 0x00, 0x00, 0x00, 0x80, 0x00, 0x00, 0x00,
2761                 0x0e, 0x1f, 0xba, 0x0e, 0x00, 0xb4, 0x09, 0xcd,  0x21, 0xb8, 0x01, 0x4c, 0xcd, 0x21, 0x54, 0x68,
2762                 0x69, 0x73, 0x20, 0x70, 0x72, 0x6f, 0x67, 0x72,  0x61, 0x6d, 0x20, 0x63, 0x61, 0x6e, 0x6e, 0x6f,
2763                 0x74, 0x20, 0x62, 0x65, 0x20, 0x72, 0x75, 0x6e,  0x20, 0x69, 0x6e, 0x20, 0x44, 0x4f, 0x53, 0x20,
2764                 0x6d, 0x6f, 0x64, 0x65, 0x2e, 0x0d, 0x0d, 0x0a,  0x24, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
2765         };
2766
2767         mono_image_basic_init (assemblyb);
2768         assembly = assemblyb->dynamic_assembly;
2769
2770         /* already created */
2771         if (assembly->pefile.index)
2772                 return;
2773         
2774         mono_image_build_metadata (assemblyb);
2775
2776         if (assemblyb->resources) {
2777                 int len = mono_array_length (assemblyb->resources);
2778                 for (i = 0; i < len; ++i)
2779                         assembly_add_resource (assembly, (MonoReflectionResource*)mono_array_addr (assemblyb->resources, MonoReflectionResource, i));
2780         }
2781
2782         
2783         build_compressed_metadata (assembly);
2784
2785         nsections = calc_section_size (assembly);
2786
2787         pefile = &assembly->pefile;
2788
2789         /* The DOS header and stub */
2790         g_assert (sizeof (MonoMSDOSHeader) == sizeof (msheader));
2791         mono_image_add_stream_data (pefile, msheader, sizeof (msheader));
2792
2793         /* the dotnet header */
2794         header_start = mono_image_add_stream_zero (pefile, sizeof (MonoDotNetHeader));
2795
2796         /* the section tables */
2797         section_start = mono_image_add_stream_zero (pefile, sizeof (MonoSectionTable) * nsections);
2798
2799         file_offset = section_start + sizeof (MonoSectionTable) * nsections;
2800         virtual_offset = VIRT_ALIGN;
2801         image_size = 0;
2802
2803         for (i = 0; i < MONO_SECTION_MAX; ++i) {
2804                 if (!assembly->sections [i].size)
2805                         continue;
2806                 /* align offsets */
2807                 file_offset += FILE_ALIGN - 1;
2808                 file_offset &= ~(FILE_ALIGN - 1);
2809                 virtual_offset += VIRT_ALIGN - 1;
2810                 virtual_offset &= ~(VIRT_ALIGN - 1);
2811
2812                 assembly->sections [i].offset = file_offset;
2813                 assembly->sections [i].rva = virtual_offset;
2814
2815                 file_offset += assembly->sections [i].size;
2816                 virtual_offset += assembly->sections [i].size;
2817                 image_size += (assembly->sections [i].size + VIRT_ALIGN - 1) & ~(VIRT_ALIGN - 1);
2818         }
2819
2820         file_offset += FILE_ALIGN - 1;
2821         file_offset &= ~(FILE_ALIGN - 1);
2822         mono_image_add_stream_zero (pefile, file_offset - pefile->index);
2823
2824         image_size += section_start + sizeof (MonoSectionTable) * nsections;
2825
2826         /* back-patch info */
2827         msdos = (MonoMSDOSHeader*)pefile->data;
2828         msdos->nlast_page = GUINT16_FROM_LE (file_offset & (512 - 1));
2829         msdos->npages = GUINT16_FROM_LE ((file_offset + (512 - 1)) / 512);
2830         msdos->pe_offset = GUINT32_FROM_LE (sizeof (MonoMSDOSHeader));
2831
2832         header = (MonoDotNetHeader*)(pefile->data + header_start);
2833         header->pesig [0] = 'P';
2834         header->pesig [1] = 'E';
2835         
2836         header->coff.coff_machine = GUINT16_FROM_LE (0x14c);
2837         header->coff.coff_sections = GUINT16_FROM_LE (nsections);
2838         header->coff.coff_time = GUINT32_FROM_LE (time (NULL));
2839         header->coff.coff_opt_header_size = GUINT16_FROM_LE (sizeof (MonoDotNetHeader) - sizeof (MonoCOFFHeader) - 4);
2840         if (assemblyb->pekind == 1) {
2841                 /* it's a dll */
2842                 header->coff.coff_attributes = GUINT16_FROM_LE (0x210e);
2843         } else {
2844                 /* it's an exe */
2845                 header->coff.coff_attributes = GUINT16_FROM_LE (0x010e);
2846         }
2847
2848         virtual_base = 0x400000; /* FIXME: 0x10000000 if a DLL */
2849
2850         header->pe.pe_magic = GUINT16_FROM_LE (0x10B);
2851         header->pe.pe_major = 6;
2852         header->pe.pe_minor = 0;
2853         size = assembly->sections [MONO_SECTION_TEXT].size;
2854         size += FILE_ALIGN - 1;
2855         size &= ~(FILE_ALIGN - 1);
2856         header->pe.pe_code_size = size;
2857         size = assembly->sections [MONO_SECTION_RSRC].size;
2858         size += FILE_ALIGN - 1;
2859         size &= ~(FILE_ALIGN - 1);
2860         header->pe.pe_data_size = size;
2861         g_assert (START_TEXT_RVA == assembly->sections [MONO_SECTION_TEXT].rva);
2862         header->pe.pe_rva_code_base = assembly->sections [MONO_SECTION_TEXT].rva;
2863         header->pe.pe_rva_data_base = assembly->sections [MONO_SECTION_RSRC].rva;
2864         /* pe_rva_entry_point always at the beginning of the text section */
2865         header->pe.pe_rva_entry_point = assembly->sections [MONO_SECTION_TEXT].rva;
2866
2867         header->nt.pe_image_base = GUINT32_FROM_LE (virtual_base);
2868         header->nt.pe_section_align = GUINT32_FROM_LE (VIRT_ALIGN);
2869         header->nt.pe_file_alignment = GUINT32_FROM_LE (FILE_ALIGN);
2870         header->nt.pe_os_major = GUINT16_FROM_LE (4);
2871         header->nt.pe_os_minor = GUINT16_FROM_LE (0);
2872         header->nt.pe_subsys_major = GUINT16_FROM_LE (4);
2873         size = section_start;
2874         size += FILE_ALIGN - 1;
2875         size &= ~(FILE_ALIGN - 1);
2876         header->nt.pe_header_size = GUINT32_FROM_LE (size);
2877         size = image_size;
2878         size += VIRT_ALIGN - 1;
2879         size &= ~(VIRT_ALIGN - 1);
2880         header->nt.pe_image_size = GUINT32_FROM_LE (size);
2881
2882         //
2883         // Translate the PEFileKind value to the value expected by the Windows loader
2884         //
2885         {
2886                 short kind = assemblyb->pekind;
2887
2888                 //
2889                 // PEFileKinds.ConsoleApplication == 2
2890                 // PEFileKinds.WindowApplication == 3
2891                 //
2892                 // need to get:
2893                 //     IMAGE_SUBSYSTEM_WINDOWS_GUI 2 // Image runs in the Windows GUI subsystem.
2894                 //     IMAGE_SUBSYSTEM_WINDOWS_CUI 3 // Image runs in the Windows character subsystem.
2895                 if (kind == 2)
2896                         kind = 3;
2897                 else if (kind == 3)
2898                         kind = 2;
2899                 
2900                 header->nt.pe_subsys_required = GUINT16_FROM_LE (kind);
2901         }    
2902         header->nt.pe_stack_reserve = GUINT32_FROM_LE (0x00100000);
2903         header->nt.pe_stack_commit = GUINT32_FROM_LE (0x00001000);
2904         header->nt.pe_heap_reserve = GUINT32_FROM_LE (0x00100000);
2905         header->nt.pe_heap_commit = GUINT32_FROM_LE (0x00001000);
2906         header->nt.pe_loader_flags = GUINT32_FROM_LE (0);
2907         header->nt.pe_data_dir_count = GUINT32_FROM_LE (16);
2908
2909         /* fill data directory entries */
2910
2911         header->datadir.pe_resource_table.size = GUINT32_FROM_LE (assembly->sections [MONO_SECTION_RSRC].size);
2912         header->datadir.pe_resource_table.rva = GUINT32_FROM_LE (assembly->sections [MONO_SECTION_RSRC].rva);
2913
2914         header->datadir.pe_reloc_table.size = GUINT32_FROM_LE (assembly->sections [MONO_SECTION_RELOC].size);
2915         header->datadir.pe_reloc_table.rva = GUINT32_FROM_LE (assembly->sections [MONO_SECTION_RELOC].rva);
2916
2917         header->datadir.pe_cli_header.size = GUINT32_FROM_LE (72);
2918         header->datadir.pe_cli_header.rva = GUINT32_FROM_LE (assembly->text_rva + assembly->cli_header_offset);
2919         header->datadir.pe_iat.size = GUINT32_FROM_LE (8);
2920         header->datadir.pe_iat.rva = GUINT32_FROM_LE (assembly->text_rva + assembly->iat_offset);
2921         /* patch imported function RVA name */
2922         rva = (guint32*)(assembly->code.data + assembly->iat_offset);
2923         *rva = GUINT32_FROM_LE (assembly->text_rva + assembly->imp_names_offset);
2924
2925         /* the import table */
2926         header->datadir.pe_import_table.size = GUINT32_FROM_LE (79); /* FIXME: magic number? */
2927         header->datadir.pe_import_table.rva = GUINT32_FROM_LE (assembly->text_rva + assembly->idt_offset);
2928         /* patch imported dll RVA name and other entries in the dir */
2929         rva = (guint32*)(assembly->code.data + assembly->idt_offset + G_STRUCT_OFFSET (MonoIDT, name_rva));
2930         *rva = GUINT32_FROM_LE (assembly->text_rva + assembly->imp_names_offset + 12); /* 12 is strlen+1 of func name */
2931         rva = (guint32*)(assembly->code.data + assembly->idt_offset + G_STRUCT_OFFSET (MonoIDT, import_address_table_rva));
2932         *rva = GUINT32_FROM_LE (assembly->text_rva + assembly->iat_offset);
2933         rva = (guint32*)(assembly->code.data + assembly->idt_offset + G_STRUCT_OFFSET (MonoIDT, import_lookup_table));
2934         *rva = GUINT32_FROM_LE (assembly->text_rva + assembly->ilt_offset);
2935
2936         p = (assembly->code.data + assembly->ilt_offset);
2937         value = (assembly->text_rva + assembly->imp_names_offset - 2);
2938         *p++ = (value) & 0xff;
2939         *p++ = (value >> 8) & (0xff);
2940         *p++ = (value >> 16) & (0xff);
2941         *p++ = (value >> 24) & (0xff);
2942
2943         /* the CLI header info */
2944         cli_header = (MonoCLIHeader*)(assembly->code.data + assembly->cli_header_offset);
2945         cli_header->ch_size = GUINT32_FROM_LE (72);
2946         cli_header->ch_runtime_major = GUINT16_FROM_LE (2);
2947         cli_header->ch_flags = GUINT32_FROM_LE (CLI_FLAGS_ILONLY);
2948         if (assemblyb->entry_point) 
2949                 cli_header->ch_entry_point = GUINT32_FROM_LE (assemblyb->entry_point->table_idx | MONO_TOKEN_METHOD_DEF);
2950         else
2951                 cli_header->ch_entry_point = GUINT32_FROM_LE (0);
2952         /* The embedded managed resources */
2953         text_offset = assembly->text_rva + assembly->code.index;
2954         cli_header->ch_resources.rva = GUINT32_FROM_LE (text_offset);
2955         cli_header->ch_resources.size = GUINT32_FROM_LE (assembly->resources.index);
2956         text_offset += assembly->resources.index;
2957         cli_header->ch_metadata.rva = GUINT32_FROM_LE (text_offset);
2958         cli_header->ch_metadata.size = GUINT32_FROM_LE (assembly->meta_size);
2959         text_offset += assembly->meta_size;
2960         if (assembly->strong_name_size) {
2961                 cli_header->ch_strong_name.rva = GUINT32_FROM_LE (text_offset);
2962                 cli_header->ch_strong_name.size = GUINT32_FROM_LE (assembly->strong_name_size);
2963                 text_offset += assembly->strong_name_size;
2964         }
2965
2966         /* write the section tables and section content */
2967         section = (MonoSectionTable*)(pefile->data + section_start);
2968         for (i = 0; i < MONO_SECTION_MAX; ++i) {
2969                 static const char *section_names [] = {
2970                         ".text", ".rsrc", ".reloc"
2971                 };
2972                 if (!assembly->sections [i].size)
2973                         continue;
2974                 strcpy (section->st_name, section_names [i]);
2975                 /*g_print ("output section %s (%d), size: %d\n", section->st_name, i, assembly->sections [i].size);*/
2976                 section->st_virtual_address = GUINT32_FROM_LE (assembly->sections [i].rva);
2977                 section->st_virtual_size = GUINT32_FROM_LE (assembly->sections [i].size);
2978                 section->st_raw_data_size = GUINT32_FROM_LE (GUINT32_TO_LE (section->st_virtual_size) + (FILE_ALIGN - 1));
2979                 section->st_raw_data_size &= GUINT32_FROM_LE (~(FILE_ALIGN - 1));
2980                 section->st_raw_data_ptr = GUINT32_FROM_LE (assembly->sections [i].offset);
2981                 section->st_flags = GUINT32_FROM_LE (assembly->sections [i].attrs);
2982                 switch (i) {
2983                 case MONO_SECTION_TEXT:
2984                         /* patch entry point */
2985                         p = (assembly->code.data + 2);
2986                         value = (virtual_base + assembly->text_rva + assembly->iat_offset);
2987                         *p++ = (value) & 0xff;
2988                         *p++ = (value >> 8) & 0xff;
2989                         *p++ = (value >> 16) & 0xff;
2990                         *p++ = (value >> 24) & 0xff;
2991
2992                         text_offset = assembly->sections [i].offset;
2993                         memcpy (pefile->data + text_offset, assembly->code.data, assembly->code.index);
2994                         text_offset += assembly->code.index;
2995                         memcpy (pefile->data + text_offset, assembly->resources.data, assembly->resources.index);
2996                         text_offset += assembly->resources.index;
2997                         memcpy (pefile->data + text_offset, assembly->assembly.image->raw_metadata, assembly->meta_size);
2998                         text_offset += assembly->meta_size;
2999                         memcpy (pefile->data + text_offset, assembly->strong_name, assembly->strong_name_size);
3000                         break;
3001                 case MONO_SECTION_RELOC:
3002                         rva = (guint32*)(pefile->data + assembly->sections [i].offset);
3003                         *rva = GUINT32_FROM_LE (assembly->text_rva);
3004                         ++rva;
3005                         *rva = GUINT32_FROM_LE (12);
3006                         ++rva;
3007                         data16 = (guint16*)rva;
3008                         /* 
3009                          * the entrypoint is always at the start of the text section 
3010                          * 3 is IMAGE_REL_BASED_HIGHLOW
3011                          * 2 is patch_size_rva - text_rva
3012                          */
3013                         *data16 = GUINT16_FROM_LE ((3 << 12) + (2));
3014                         data16++;
3015                         *data16 = 0; /* terminate */
3016                         break;
3017                 case MONO_SECTION_RSRC:
3018                 default:
3019                         g_assert_not_reached ();
3020                 }
3021                 section++;
3022         }
3023         
3024         /* check that the file is properly padded */
3025 #if 0
3026         {
3027                 FILE *f = fopen ("mypetest.exe", "w");
3028                 fwrite (pefile->data, pefile->index, 1, f);
3029                 fclose (f);
3030         }
3031 #endif
3032 }
3033
3034 /*
3035  * We need to return always the same object for MethodInfo, FieldInfo etc..
3036  * but we need to consider the reflected type.
3037  * type uses a different hash, since it uses custom hash/equal functions.
3038  */
3039
3040 typedef struct {
3041         gpointer item;
3042         MonoClass *refclass;
3043 } ReflectedEntry;
3044
3045 static gboolean
3046 reflected_equal (gconstpointer a, gconstpointer b) {
3047         const ReflectedEntry *ea = a;
3048         const ReflectedEntry *eb = b;
3049
3050         return (ea->item == eb->item) && (ea->refclass == eb->refclass);
3051 }
3052
3053 static guint
3054 reflected_hash (gconstpointer a) {
3055         const ReflectedEntry *ea = a;
3056         return GPOINTER_TO_UINT (ea->item);
3057 }
3058
3059 #define CHECK_OBJECT(t,p,k)     \
3060         do {    \
3061                 t _obj; \
3062                 ReflectedEntry e;       \
3063                 e.item = (p);   \
3064                 e.refclass = (k);       \
3065                 mono_domain_lock (domain);      \
3066                 if (!domain->refobject_hash)    \
3067                         domain->refobject_hash = mono_g_hash_table_new (reflected_hash, reflected_equal);       \
3068                 if ((_obj = mono_g_hash_table_lookup (domain->refobject_hash, &e))) {   \
3069                         mono_domain_unlock (domain);    \
3070                         return _obj;    \
3071                 }       \
3072         } while (0)
3073
3074 #if HAVE_BOEHM_GC
3075 #define ALLOC_REFENTRY GC_MALLOC (sizeof (ReflectedEntry))
3076 #else
3077 #define ALLOC_REFENTRY mono_mempool_alloc (domain->mp, sizeof (ReflectedEntry))
3078 #endif
3079
3080 #define CACHE_OBJECT(p,o,k)     \
3081         do {    \
3082                 ReflectedEntry *e = ALLOC_REFENTRY;     \
3083                 e->item = (p);  \
3084                 e->refclass = (k);      \
3085                 mono_g_hash_table_insert (domain->refobject_hash, e,o); \
3086                 mono_domain_unlock (domain);    \
3087         } while (0)
3088
3089 static void 
3090 register_assembly (MonoDomain *domain, MonoReflectionAssembly *res, MonoAssembly *assembly)
3091 {
3092         /* this is done only once */
3093         mono_domain_lock (domain);
3094         CACHE_OBJECT (assembly, res, NULL);
3095 }
3096
3097 static void
3098 register_module (MonoDomain *domain, MonoReflectionModuleBuilder *res, MonoImage *module)
3099 {
3100         /* this is done only once */
3101         mono_domain_lock (domain);
3102         CACHE_OBJECT (module, res, NULL);
3103 }
3104
3105 void
3106 mono_image_module_basic_init (MonoReflectionModuleBuilder *moduleb)
3107 {
3108         MonoImage *image = moduleb->module.image;
3109         MonoReflectionAssemblyBuilder *ab = moduleb->assemblyb;
3110         if (!image) {
3111                 if (!ab->modules) {
3112                         /* a MonoImage was already created in mono_image_basic_init () */
3113                         image = ab->dynamic_assembly->assembly.image;
3114                 } else {
3115                         image = create_dynamic_mono_image (mono_string_to_utf8 (ab->name), mono_string_to_utf8 (moduleb->module.name));
3116                 }
3117                 moduleb->module.image = image;
3118                 register_module (mono_object_domain (moduleb), moduleb, image);
3119         }
3120 }
3121
3122 /*
3123  * mono_assembly_get_object:
3124  * @domain: an app domain
3125  * @assembly: an assembly
3126  *
3127  * Return an System.Reflection.Assembly object representing the MonoAssembly @assembly.
3128  */
3129 MonoReflectionAssembly*
3130 mono_assembly_get_object (MonoDomain *domain, MonoAssembly *assembly)
3131 {
3132         static MonoClass *System_Reflection_Assembly;
3133         MonoReflectionAssembly *res;
3134         
3135         CHECK_OBJECT (MonoReflectionAssembly *, assembly, NULL);
3136         if (!System_Reflection_Assembly)
3137                 System_Reflection_Assembly = mono_class_from_name (
3138                         mono_defaults.corlib, "System.Reflection", "Assembly");
3139         res = (MonoReflectionAssembly *)mono_object_new (domain, System_Reflection_Assembly);
3140         res->assembly = assembly;
3141         CACHE_OBJECT (assembly, res, NULL);
3142         return res;
3143 }
3144
3145
3146 MonoReflectionModule*   
3147 mono_module_get_object   (MonoDomain *domain, MonoImage *image)
3148 {
3149         static MonoClass *System_Reflection_Module;
3150         MonoReflectionModule *res;
3151         
3152         CHECK_OBJECT (MonoReflectionModule *, image, NULL);
3153         if (!System_Reflection_Module)
3154                 System_Reflection_Module = mono_class_from_name (
3155                         mono_defaults.corlib, "System.Reflection", "Module");
3156         res = (MonoReflectionModule *)mono_object_new (domain, System_Reflection_Module);
3157
3158         res->image = image;
3159         res->assembly = (MonoReflectionAssembly *) mono_assembly_get_object(domain, image->assembly);
3160
3161         res->fqname    = mono_string_new (domain, image->name);
3162         res->name      = mono_string_new (domain, image->name);
3163         res->scopename = mono_string_new (domain, image->module_name);
3164
3165         CACHE_OBJECT (image, res, NULL);
3166         return res;
3167 }
3168
3169
3170 static gboolean
3171 mymono_metadata_type_equal (MonoType *t1, MonoType *t2)
3172 {
3173         if ((t1->type != t2->type) ||
3174             (t1->byref != t2->byref))
3175                 return FALSE;
3176
3177         switch (t1->type) {
3178         case MONO_TYPE_VOID:
3179         case MONO_TYPE_BOOLEAN:
3180         case MONO_TYPE_CHAR:
3181         case MONO_TYPE_I1:
3182         case MONO_TYPE_U1:
3183         case MONO_TYPE_I2:
3184         case MONO_TYPE_U2:
3185         case MONO_TYPE_I4:
3186         case MONO_TYPE_U4:
3187         case MONO_TYPE_I8:
3188         case MONO_TYPE_U8:
3189         case MONO_TYPE_R4:
3190         case MONO_TYPE_R8:
3191         case MONO_TYPE_STRING:
3192         case MONO_TYPE_I:
3193         case MONO_TYPE_U:
3194         case MONO_TYPE_OBJECT:
3195         case MONO_TYPE_TYPEDBYREF:
3196                 return TRUE;
3197         case MONO_TYPE_VALUETYPE:
3198         case MONO_TYPE_CLASS:
3199                 return t1->data.klass == t2->data.klass;
3200         case MONO_TYPE_PTR:
3201                 return mymono_metadata_type_equal (t1->data.type, t2->data.type);
3202         case MONO_TYPE_SZARRAY:
3203 retry_sz:
3204                 if (t1->data.type->type != t2->data.type->type)
3205                         return FALSE;
3206                 if (t1->data.type->type == MONO_TYPE_CLASS || t1->data.type->type == MONO_TYPE_VALUETYPE)
3207                         return t1->data.type->data.klass == t2->data.type->data.klass;
3208                 if (t1->data.type->type == MONO_TYPE_SZARRAY) {
3209                         t1 = t1->data.type;
3210                         t2 = t2->data.type;
3211                         goto retry_sz;
3212                 }
3213                 return mymono_metadata_type_equal (t1->data.type, t2->data.type);
3214         case MONO_TYPE_ARRAY:
3215                 if (t1->data.array->rank != t2->data.array->rank)
3216                         return FALSE;
3217                 return mymono_metadata_type_equal (t1->data.array->type, t2->data.array->type);
3218         default:
3219                 g_error ("implement type compare for %0x!", t1->type);
3220                 return FALSE;
3221         }
3222
3223         return FALSE;
3224 }
3225
3226 static guint
3227 mymono_metadata_type_hash (MonoType *t1)
3228 {
3229         guint hash;
3230
3231         hash = t1->type;
3232
3233         hash |= t1->byref << 6; /* do not collide with t1->type values */
3234         switch (t1->type) {
3235         case MONO_TYPE_VALUETYPE:
3236         case MONO_TYPE_CLASS:
3237                 /* check if the distribution is good enough */
3238                 return ((hash << 5) - hash) ^ g_str_hash (t1->data.klass->name);
3239         case MONO_TYPE_PTR:
3240         case MONO_TYPE_SZARRAY:
3241                 return ((hash << 5) - hash) ^ mymono_metadata_type_hash (t1->data.type);
3242         }
3243         return hash;
3244 }
3245
3246 /*
3247  * mono_type_get_object:
3248  * @domain: an app domain
3249  * @type: a type
3250  *
3251  * Return an System.MonoType object representing the type @type.
3252  */
3253 MonoReflectionType*
3254 mono_type_get_object (MonoDomain *domain, MonoType *type)
3255 {
3256         MonoReflectionType *res;
3257         MonoClass *klass = mono_class_from_mono_type (type);
3258
3259         mono_domain_lock (domain);
3260         if (!domain->type_hash)
3261                 domain->type_hash = mono_g_hash_table_new ((GHashFunc)mymono_metadata_type_hash, 
3262                                 (GCompareFunc)mymono_metadata_type_equal);
3263         if ((res = mono_g_hash_table_lookup (domain->type_hash, type))) {
3264                 mono_domain_unlock (domain);
3265                 return res;
3266         }
3267         if (klass->reflection_info && !klass->wastypebuilder) {
3268                 //g_assert_not_reached ();
3269                 /* should this be considered an error condition? */
3270                 if (!type->byref) {
3271                         mono_domain_unlock (domain);
3272                         return klass->reflection_info;
3273                 }
3274         }
3275         mono_class_init (klass);
3276         res = (MonoReflectionType *)mono_object_new (domain, mono_defaults.monotype_class);
3277         res->type = type;
3278         mono_g_hash_table_insert (domain->type_hash, type, res);
3279         mono_domain_unlock (domain);
3280         return res;
3281 }
3282
3283 /*
3284  * mono_method_get_object:
3285  * @domain: an app domain
3286  * @method: a method
3287  * @refclass: the reflected type (can be NULL)
3288  *
3289  * Return an System.Reflection.MonoMethod object representing the method @method.
3290  */
3291 MonoReflectionMethod*
3292 mono_method_get_object (MonoDomain *domain, MonoMethod *method, MonoClass *refclass)
3293 {
3294         /*
3295          * We use the same C representation for methods and constructors, but the type 
3296          * name in C# is different.
3297          */
3298         const char *cname;
3299         MonoClass *klass;
3300         MonoReflectionMethod *ret;
3301
3302         if (!refclass)
3303                 refclass = method->klass;
3304
3305         CHECK_OBJECT (MonoReflectionMethod *, method, refclass);
3306         if (*method->name == '.' && (strcmp (method->name, ".ctor") == 0 || strcmp (method->name, ".cctor") == 0))
3307                 cname = "MonoCMethod";
3308         else
3309                 cname = "MonoMethod";
3310         klass = mono_class_from_name (mono_defaults.corlib, "System.Reflection", cname);
3311
3312         ret = (MonoReflectionMethod*)mono_object_new (domain, klass);
3313         ret->method = method;
3314         ret->name = mono_string_new (domain, method->name);
3315         ret->reftype = mono_type_get_object (domain, &refclass->byval_arg);
3316         CACHE_OBJECT (method, ret, refclass);
3317         return ret;
3318 }
3319
3320 /*
3321  * mono_field_get_object:
3322  * @domain: an app domain
3323  * @klass: a type
3324  * @field: a field
3325  *
3326  * Return an System.Reflection.MonoField object representing the field @field
3327  * in class @klass.
3328  */
3329 MonoReflectionField*
3330 mono_field_get_object (MonoDomain *domain, MonoClass *klass, MonoClassField *field)
3331 {
3332         MonoReflectionField *res;
3333         MonoClass *oklass;
3334
3335         CHECK_OBJECT (MonoReflectionField *, field, klass);
3336         oklass = mono_class_from_name (mono_defaults.corlib, "System.Reflection", "MonoField");
3337         res = (MonoReflectionField *)mono_object_new (domain, oklass);
3338         res->klass = klass;
3339         res->field = field;
3340         CACHE_OBJECT (field, res, klass);
3341         return res;
3342 }
3343
3344 /*
3345  * mono_property_get_object:
3346  * @domain: an app domain
3347  * @klass: a type
3348  * @property: a property
3349  *
3350  * Return an System.Reflection.MonoProperty object representing the property @property
3351  * in class @klass.
3352  */
3353 MonoReflectionProperty*
3354 mono_property_get_object (MonoDomain *domain, MonoClass *klass, MonoProperty *property)
3355 {
3356         MonoReflectionProperty *res;
3357         MonoClass *oklass;
3358
3359         CHECK_OBJECT (MonoReflectionProperty *, property, klass);
3360         oklass = mono_class_from_name (mono_defaults.corlib, "System.Reflection", "MonoProperty");
3361         res = (MonoReflectionProperty *)mono_object_new (domain, oklass);
3362         res->klass = klass;
3363         res->property = property;
3364         CACHE_OBJECT (property, res, klass);
3365         return res;
3366 }
3367
3368 /*
3369  * mono_event_get_object:
3370  * @domain: an app domain
3371  * @klass: a type
3372  * @event: a event
3373  *
3374  * Return an System.Reflection.MonoEvent object representing the event @event
3375  * in class @klass.
3376  */
3377 MonoReflectionEvent*
3378 mono_event_get_object (MonoDomain *domain, MonoClass *klass, MonoEvent *event)
3379 {
3380         MonoReflectionEvent *res;
3381         MonoClass *oklass;
3382
3383         CHECK_OBJECT (MonoReflectionEvent *, event, klass);
3384         oklass = mono_class_from_name (mono_defaults.corlib, "System.Reflection", "MonoEvent");
3385         res = (MonoReflectionEvent *)mono_object_new (domain, oklass);
3386         res->klass = klass;
3387         res->event = event;
3388         CACHE_OBJECT (event, res, klass);
3389         return res;
3390 }
3391
3392 /*
3393  * mono_param_get_objects:
3394  * @domain: an app domain
3395  * @method: a method
3396  *
3397  * Return an System.Reflection.ParameterInfo array object representing the parameters
3398  * in the method @method.
3399  */
3400 MonoReflectionParameter**
3401 mono_param_get_objects (MonoDomain *domain, MonoMethod *method)
3402 {
3403         MonoReflectionParameter **res;
3404         MonoReflectionMethod *member;
3405         MonoClass *oklass;
3406         char **names;
3407         int i;
3408
3409         if (!method->signature->param_count)
3410                 return NULL;
3411
3412         member = mono_method_get_object (domain, method, NULL);
3413         names = g_new (char *, method->signature->param_count);
3414         mono_method_get_param_names (method, (const char **) names);
3415         
3416         /* Note: the cache is based on the address of the signature into the method
3417          * since we already cache MethodInfos with the method as keys.
3418          */
3419         CHECK_OBJECT (MonoReflectionParameter**, &(method->signature), NULL);
3420         oklass = mono_class_from_name (mono_defaults.corlib, "System.Reflection", "ParameterInfo");
3421 #if HAVE_BOEHM_GC
3422         res = GC_MALLOC (sizeof (MonoReflectionParameter*) * method->signature->param_count);
3423 #else
3424         res = g_new0 (MonoReflectionParameter*, method->signature->param_count);
3425 #endif
3426         for (i = 0; i < method->signature->param_count; ++i) {
3427                 res [i] = (MonoReflectionParameter *)mono_object_new (domain, oklass);
3428                 res [i]->ClassImpl = mono_type_get_object (domain, method->signature->params [i]);
3429                 res [i]->DefaultValueImpl = NULL; /* FIXME */
3430                 res [i]->MemberImpl = (MonoObject*)member;
3431                 res [i]->NameImpl = mono_string_new (domain, names [i]);
3432                 res [i]->PositionImpl = i + 1;
3433                 res [i]->AttrsImpl = method->signature->params [i]->attrs;
3434         }
3435         g_free (names);
3436         CACHE_OBJECT (&(method->signature), res, NULL);
3437         return res;
3438 }
3439
3440 static int
3441 assembly_name_to_aname (MonoAssemblyName *assembly, char *p) {
3442         int found_sep;
3443         char *s;
3444
3445         memset (assembly, 0, sizeof (MonoAssemblyName));
3446         assembly->name = p;
3447         assembly->culture = "";
3448         
3449         while (*p && (isalnum (*p) || *p == '.'))
3450                 p++;
3451         found_sep = 0;
3452         while (*p == ' ' || *p == ',') {
3453                 *p++ = 0;
3454                 found_sep = 1;
3455                 continue;
3456         }
3457         /* failed */
3458         if (!found_sep)
3459                 return 1;
3460         while (*p) {
3461                 if (*p == 'V' && strncmp (p, "Version=", 8) == 0) {
3462                         p += 8;
3463                         assembly->major = strtoul (p, &s, 10);
3464                         if (s == p || *s != '.')
3465                                 return 1;
3466                         p = ++s;
3467                         assembly->minor = strtoul (p, &s, 10);
3468                         if (s == p || *s != '.')
3469                                 return 1;
3470                         p = ++s;
3471                         assembly->build = strtoul (p, &s, 10);
3472                         if (s == p || *s != '.')
3473                                 return 1;
3474                         p = ++s;
3475                         assembly->revision = strtoul (p, &s, 10);
3476                         if (s == p)
3477                                 return 1;
3478                 } else if (*p == 'C' && strncmp (p, "Culture=", 8) == 0) {
3479                         p += 8;
3480                         if (strncmp (p, "neutral", 7) == 0) {
3481                                 assembly->culture = "";
3482                                 p += 7;
3483                         } else {
3484                                 assembly->culture = p;
3485                                 while (*p && *p != ',') {
3486                                         p++;
3487                                 }
3488                         }
3489                 } else if (*p == 'P' && strncmp (p, "PublicKeyToken=", 15) == 0) {
3490                         p += 15;
3491                         s = p;
3492                         while (*s && isxdigit (*s)) {
3493                                 *s = tolower (*s);
3494                                 s++;
3495                         }
3496                         assembly->hash_len = s - p;
3497                         if (!(s-p) || ((s-p) & 1))
3498                                 return 1;
3499                         assembly->hash_value = s = p;
3500                         while (*s && isxdigit (*s)) {
3501                                 int val;
3502                                 val = *s >= '0' && *s <= '9'? *s - '0': *s - 'a' + 10;
3503                                 s++;
3504                                 *p = val << 4;
3505                                 *p |= *s >= '0' && *s <= '9'? *s - '0': *s - 'a' + 10;
3506                                 p++;
3507                         }
3508                         p = s;
3509                 } else {
3510                         while (*p && *p != ',')
3511                                 p++;
3512                 }
3513                 found_sep = 0;
3514                 while (*p == ' ' || *p == ',') {
3515                         *p++ = 0;
3516                         found_sep = 1;
3517                         continue;
3518                 }
3519                 /* failed */
3520                 if (!found_sep)
3521                         return 1;
3522         }
3523
3524         return 0;
3525 }
3526
3527 /*
3528  * mono_reflection_parse_type:
3529  * @name: type name
3530  *
3531  * Parse a type name as accepted by the GetType () method and output the info
3532  * extracted in the info structure.
3533  * the name param will be mangled, so, make a copy before passing it to this function.
3534  * The fields in info will be valid until the memory pointed to by name is valid.
3535  * Returns 0 on parse error.
3536  * See also mono_type_get_name () below.
3537  */
3538 int
3539 mono_reflection_parse_type (char *name, MonoTypeNameParse *info) {
3540
3541         char *start, *p, *w, *last_point, *startn;
3542         int in_modifiers = 0;
3543         int isbyref = 0, rank;
3544
3545         start = p = w = name;
3546
3547         memset (&info->assembly, 0, sizeof (MonoAssemblyName));
3548         info->name = info->name_space = NULL;
3549         info->nested = NULL;
3550         info->modifiers = NULL;
3551
3552         /* last_point separates the namespace from the name */
3553         last_point = NULL;
3554
3555         while (*p) {
3556                 switch (*p) {
3557                 case '+':
3558                         *p = 0; /* NULL terminate the name */
3559                         startn = p + 1;
3560                         /* we have parsed the nesting namespace + name */
3561                         if (info->name) {
3562                                 info->nested = g_list_append (info->nested, startn);
3563                                 break;
3564                         }
3565                         if (last_point) {
3566                                 info->name_space = start;
3567                                 *last_point = 0;
3568                                 info->name = last_point + 1;
3569                         } else {
3570                                 info->name_space = (char *)"";
3571                                 info->name = start;
3572                         }
3573                         break;
3574                 case '.':
3575                         last_point = w;
3576                         break;
3577                 case '\\':
3578                         ++p;
3579                         break;
3580                 case '&':
3581                 case '*':
3582                 case '[':
3583                 case ',':
3584                         in_modifiers = 1;
3585                         break;
3586                 default:
3587                         break;
3588                 }
3589                 if (in_modifiers)
3590                         break;
3591                 *w++ = *p++;
3592         }
3593         
3594         if (info->name) {
3595                 info->nested = g_list_append (info->nested, startn);
3596         } else {
3597                 if (last_point) {
3598                         info->name_space = start;
3599                         *last_point = 0;
3600                         info->name = last_point + 1;
3601                 } else {
3602                         info->name_space = (char *)"";
3603                         info->name = start;
3604                 }
3605         }
3606         while (*p) {
3607                 switch (*p) {
3608                 case '&':
3609                         if (isbyref) /* only one level allowed by the spec */
3610                                 return 0;
3611                         isbyref = 1;
3612                         info->modifiers = g_list_append (info->modifiers, GUINT_TO_POINTER (0));
3613                         *p++ = 0;
3614                         break;
3615                 case '*':
3616                         info->modifiers = g_list_append (info->modifiers, GUINT_TO_POINTER (-1));
3617                         *p++ = 0;
3618                         break;
3619                 case '[':
3620                         rank = 1;
3621                         *p++ = 0;
3622                         while (*p) {
3623                                 if (*p == ']')
3624                                         break;
3625                                 if (*p == ',')
3626                                         rank++;
3627                                 else if (*p != '*') /* '*' means unknown lower bound */
3628                                         return 0;
3629                                 ++p;
3630                         }
3631                         if (*p++ != ']')
3632                                 return 0;
3633                         info->modifiers = g_list_append (info->modifiers, GUINT_TO_POINTER (rank));
3634                         break;
3635                 case ',':
3636                         *p++ = 0;
3637                         while (*p) {
3638                                 if (*p == ' ') {
3639                                         ++p;
3640                                         continue;
3641                                 }
3642                                 break;
3643                         }
3644                         if (!*p)
3645                                 return 0; /* missing assembly name */
3646                         if (!assembly_name_to_aname (&info->assembly, p))
3647                                 return 0;
3648                         break;
3649                 default:
3650                         break;
3651                 }
3652                 if (info->assembly.name)
3653                         break;
3654         }
3655         *w = 0; /* terminate class name */
3656         if (!info->name || !*info->name)
3657                 return 0;
3658         /* add other consistency checks */
3659         return 1;
3660 }
3661
3662 static void
3663 mono_type_get_name_recurse (MonoType *type, GString *str)
3664 {
3665         MonoClass *klass;
3666         
3667         switch (type->type) {
3668         case MONO_TYPE_ARRAY: {
3669                 int i, rank = type->data.array->rank;
3670
3671                 mono_type_get_name_recurse (type->data.array->type, str);
3672                 g_string_append_c (str, '[');
3673                 for (i = 1; i < rank; i++)
3674                         g_string_append_c (str, ',');
3675                 g_string_append_c (str, ']');
3676                 break;
3677         }
3678         case MONO_TYPE_SZARRAY:
3679                 mono_type_get_name_recurse (type->data.type, str);
3680                 g_string_append (str, "[]");
3681                 break;
3682         case MONO_TYPE_PTR:
3683                 mono_type_get_name_recurse (type->data.type, str);
3684                 g_string_append_c (str, '*');
3685                 break;
3686         default:
3687                 klass = mono_class_from_mono_type (type);
3688                 if (klass->nested_in) {
3689                         mono_type_get_name_recurse (&klass->nested_in->byval_arg, str);
3690                         g_string_append_c (str, '+');
3691                 }
3692                 if (*klass->name_space) {
3693                         g_string_append (str, klass->name_space);
3694                         g_string_append_c (str, '.');
3695                 }
3696                 g_string_append (str, klass->name);
3697                 break;
3698         }
3699 }
3700
3701 /*
3702  * mono_type_get_name:
3703  * @type: a type
3704  *
3705  * Returns the string representation for type as required by System.Reflection.
3706  * The inverse of mono_reflection_parse_type ().
3707  */
3708 char*
3709 mono_type_get_name (MonoType *type)
3710 {
3711         GString* result = g_string_new ("");
3712         mono_type_get_name_recurse (type, result);
3713
3714         if (type->byref)
3715                 g_string_append_c (result, '&');
3716
3717         return g_string_free (result, FALSE);
3718 }
3719
3720 static MonoType*
3721 mono_reflection_get_type_internal (MonoImage* image, MonoTypeNameParse *info, gboolean ignorecase)
3722 {
3723         MonoClass *klass;
3724         GList *mod;
3725         int modval;
3726         
3727         if (!image)
3728                 image = mono_defaults.corlib;
3729
3730         if (ignorecase)
3731                 klass = mono_class_from_name_case (image, info->name_space, info->name);
3732         else
3733                 klass = mono_class_from_name (image, info->name_space, info->name);
3734         if (!klass)
3735                 return NULL;
3736         for (mod = info->nested; mod; mod = mod->next) {
3737                 GList *nested;
3738
3739                 mono_class_init (klass);
3740                 nested = klass->nested_classes;
3741                 klass = NULL;
3742                 while (nested) {
3743                         klass = nested->data;
3744                         if (ignorecase) {
3745                                 if (g_strcasecmp (klass->name, mod->data) == 0)
3746                                         break;
3747                         } else {
3748                                 if (strcmp (klass->name, mod->data) == 0)
3749                                         break;
3750                         }
3751                         klass = NULL;
3752                         nested = nested->next;
3753                 }
3754                 if (!klass)
3755                         break;
3756         }
3757         if (!klass)
3758                 return NULL;
3759         mono_class_init (klass);
3760         for (mod = info->modifiers; mod; mod = mod->next) {
3761                 modval = GPOINTER_TO_UINT (mod->data);
3762                 if (!modval) { /* byref: must be last modifier */
3763                         return &klass->this_arg;
3764                 } else if (modval == -1) {
3765                         klass = mono_ptr_class_get (&klass->byval_arg);
3766                 } else { /* array rank */
3767                         klass = mono_array_class_get (&klass->byval_arg, modval);
3768                 }
3769                 mono_class_init (klass);
3770         }
3771
3772         return &klass->byval_arg;
3773 }
3774
3775 /*
3776  * mono_reflection_get_type:
3777  * @image: a metadata context
3778  * @info: type description structure
3779  * @ignorecase: flag for case-insensitive string compares
3780  *
3781  * Build a MonoType from the type description in @info.
3782  * 
3783  */
3784
3785 MonoType*
3786 mono_reflection_get_type (MonoImage* image, MonoTypeNameParse *info, gboolean ignorecase)
3787 {
3788         MonoType *type;
3789         MonoReflectionAssembly *assembly;
3790         GString *fullName;
3791         GList *mod;
3792
3793         type = mono_reflection_get_type_internal (image, info, ignorecase);
3794         if (type)
3795                 return type;
3796         if (!image || !mono_domain_has_type_resolve (mono_domain_get ()))
3797                 return NULL;
3798         
3799         // Reconstruct the type name
3800         fullName = g_string_new ("");
3801         if (info->name_space && (info->name_space [0] != '\0'))
3802                 g_string_printf (fullName, "%s.%s", info->name_space, info->name);
3803         else
3804                 g_string_printf (fullName, info->name);
3805         for (mod = info->nested; mod; mod = mod->next)
3806                 g_string_append_printf (fullName, "+%s", (char*)mod->data);
3807
3808         assembly = 
3809                 mono_domain_try_type_resolve (
3810                         mono_domain_get (), fullName->str, NULL);
3811         if (assembly)
3812                 type = mono_reflection_get_type_internal (assembly->assembly->image, 
3813                                                                                  info, ignorecase);
3814         g_string_free (fullName, TRUE);
3815         return type;
3816 }
3817
3818 /*
3819  * mono_reflection_type_from_name:
3820  * @name: type name.
3821  * @image: a metadata context (can be NULL).
3822  *
3823  * Retrieves a MonoType from its @name. If the name is not fully qualified,
3824  * it defaults to get the type from @image or, if @image is NULL or loading
3825  * from it fails, uses corlib.
3826  * 
3827  */
3828 MonoType*
3829 mono_reflection_type_from_name (char *name, MonoImage *image)
3830 {
3831         MonoType *type;
3832         MonoTypeNameParse info;
3833         
3834         /*g_print ("requested type %s\n", str);*/
3835         if (!mono_reflection_parse_type (name, &info)) {
3836                 g_list_free (info.modifiers);
3837                 g_list_free (info.nested);
3838                 return NULL;
3839         }
3840
3841         if (info.assembly.name) {
3842                 image = mono_image_loaded (info.assembly.name);
3843                 /* do we need to load if it's not already loaded? */
3844                 if (!image) {
3845                         g_list_free (info.modifiers);
3846                         g_list_free (info.nested);
3847                         return NULL;
3848                 }
3849         } else if (image == NULL) {
3850                 image = mono_defaults.corlib;
3851         }
3852
3853         type = mono_reflection_get_type (image, &info, FALSE);
3854         if (type == NULL && !info.assembly.name && image != mono_defaults.corlib) {
3855                 image = mono_defaults.corlib;
3856                 type = mono_reflection_get_type (image, &info, FALSE);
3857         }
3858         
3859         g_list_free (info.modifiers);
3860         g_list_free (info.nested);
3861         return type;
3862 }
3863
3864 static void*
3865 load_cattr_value (MonoImage *image, MonoType *t, const char *p, const char **end)
3866 {
3867         int slen, type = t->type;
3868 handle_enum:
3869         switch (type) {
3870         case MONO_TYPE_U1:
3871         case MONO_TYPE_I1:
3872         case MONO_TYPE_BOOLEAN: {
3873                 MonoBoolean *bval = g_malloc (sizeof (MonoBoolean));
3874                 *bval = *p;
3875                 *end = p + 1;
3876                 return bval;
3877         }
3878         case MONO_TYPE_CHAR:
3879         case MONO_TYPE_U2:
3880         case MONO_TYPE_I2: {
3881                 guint16 *val = g_malloc (sizeof (guint16));
3882                 *val = read16 (p);
3883                 *end = p + 2;
3884                 return val;
3885         }
3886 #if SIZEOF_VOID_P == 4
3887         case MONO_TYPE_U:
3888         case MONO_TYPE_I:
3889 #endif
3890         case MONO_TYPE_R4:
3891         case MONO_TYPE_U4:
3892         case MONO_TYPE_I4: {
3893                 guint32 *val = g_malloc (sizeof (guint32));
3894                 *val = read32 (p);
3895                 *end = p + 4;
3896                 return val;
3897         }
3898 #if SIZEOF_VOID_P == 8
3899         case MONO_TYPE_U: /* error out instead? this should probably not happen */
3900         case MONO_TYPE_I:
3901 #endif
3902         case MONO_TYPE_R8:
3903         case MONO_TYPE_U8:
3904         case MONO_TYPE_I8: {
3905                 guint64 *val = g_malloc (sizeof (guint64));
3906                 *val = read64 (p);
3907                 *end = p + 8;
3908                 return val;
3909         }
3910         case MONO_TYPE_VALUETYPE:
3911                 if (t->data.klass->enumtype) {
3912                         type = t->data.klass->enum_basetype->type;
3913                         goto handle_enum;
3914                 } else {
3915                         g_error ("generic valutype %s not handled in custom attr value decoding", t->data.klass->name);
3916                 }
3917                 break;
3918         case MONO_TYPE_STRING:
3919                 if (*p == (char)0xFF) {
3920                         *end = p + 1;
3921                         return NULL;
3922                 }
3923                 slen = mono_metadata_decode_value (p, &p);
3924                 *end = p + slen;
3925                 return mono_string_new_len (mono_domain_get (), p, slen);
3926         case MONO_TYPE_CLASS: {
3927                 char *n;
3928                 MonoType *t;
3929 handle_type:
3930                 slen = mono_metadata_decode_value (p, &p);
3931                 n = g_memdup (p, slen + 1);
3932                 n [slen] = 0;
3933                 t = mono_reflection_type_from_name (n, image);
3934                 if (!t)
3935                         g_warning ("Cannot load type '%s'", n);
3936                 g_free (n);
3937                 *end = p + slen;
3938                 return mono_type_get_object (mono_domain_get (), t);
3939         }
3940         case MONO_TYPE_OBJECT: {
3941                 char subt = *p++;
3942                 MonoObject *obj;
3943                 MonoClass *subc;
3944                 void *val;
3945
3946                 if (subt == 0x50) {
3947                         goto handle_type;
3948                 } else if (subt == 0x55) {
3949                         char *n;
3950                         MonoType *t;
3951                         slen = mono_metadata_decode_value (p, &p);
3952                         n = g_memdup (p, slen + 1);
3953                         n [slen] = 0;
3954                         t = mono_reflection_type_from_name (n, image);
3955                         if (!t)
3956                                 g_warning ("Cannot load type '%s'", n);
3957                         g_free (n);
3958                         p += slen;
3959                         subc = mono_class_from_mono_type (t);
3960                 } else if (subt >= MONO_TYPE_BOOLEAN && subt <= MONO_TYPE_R8) {
3961                         MonoType simple_type = {{0}};
3962                         simple_type.type = subt;
3963                         subc = mono_class_from_mono_type (&simple_type);
3964                 } else {
3965                         g_error ("Unknown type 0x%02x for object type encoding in custom attr", subt);
3966                 }
3967                 val = load_cattr_value (image, &subc->byval_arg, p, end);
3968                 obj = mono_object_new (mono_domain_get (), subc);
3969                 memcpy ((char*)obj + sizeof (MonoObject), val, mono_class_value_size (subc, NULL));
3970                 g_free (val);
3971                 return obj;
3972         }
3973         case MONO_TYPE_SZARRAY:
3974         {
3975                 MonoArray *arr;
3976                 guint32 i,alen;
3977                 alen=read32(p);
3978                 p+=4;
3979                 arr=mono_array_new(mono_domain_get(),mono_class_from_mono_type(t->data.type),alen);
3980                 switch (t->data.type->type)
3981                 {
3982                         case MONO_TYPE_U1:
3983                         case MONO_TYPE_I1:
3984                         case MONO_TYPE_BOOLEAN:
3985                                 for (i=0;i<alen;i++)
3986                                 {
3987                                         MonoBoolean val=*p++;
3988                                         mono_array_set(arr,MonoBoolean,i,val);
3989                                 }
3990                                 break;
3991                         case MONO_TYPE_CHAR:
3992                         case MONO_TYPE_U2:
3993                         case MONO_TYPE_I2:
3994                                 for (i=0;i<alen;i++)
3995                                 {
3996                                         guint16 val=read16(p);
3997                                         mono_array_set(arr,guint16,i,val);
3998                                         p+=2;
3999                                 }
4000                                 break;
4001                         case MONO_TYPE_R4:
4002                         case MONO_TYPE_U4:
4003                         case MONO_TYPE_I4:
4004                                 for (i=0;i<alen;i++)
4005                                 {
4006                                         guint32 val=read32(p);
4007                                         mono_array_set(arr,guint32,i,val);
4008                                         p+=4;
4009                                 }
4010                                 break;
4011                         case MONO_TYPE_R8:
4012                         case MONO_TYPE_U8:
4013                         case MONO_TYPE_I8:
4014                                 for (i=0;i<alen;i++)
4015                                 {
4016                                         guint64 val=read64(p);
4017                                         mono_array_set(arr,guint64,i,val);
4018                                         p+=8;
4019                                 }
4020                                 break;
4021                         case MONO_TYPE_STRING:
4022                                 for (i=0;i<alen;i++)
4023                                 {
4024                                         if (*p==(char)0xff)
4025                                         {
4026                                                 mono_array_set(arr,gpointer,i,NULL);
4027                                                 p++;
4028                                         }
4029                                         else
4030                                         {
4031                                                 slen=mono_metadata_decode_value(p,&p);
4032                                                 mono_array_set(arr,gpointer,i,mono_string_new_len(mono_domain_get(),p,slen));
4033                                                 p+=slen;
4034                                         }
4035                                 }
4036                                 break;
4037                         default:
4038                                 g_error("Type 0x%02x not handled in custom attr array decoding",t->data.type->type);
4039                 }
4040                 *end=p;
4041                 return arr;
4042         }
4043         default:
4044                 g_error ("Type 0x%02x not handled in custom attr value decoding", type);
4045         }
4046         return NULL;
4047 }
4048
4049 static gboolean
4050 type_is_reference (MonoType *type)
4051 {
4052         switch (type->type) {
4053         case MONO_TYPE_BOOLEAN:
4054         case MONO_TYPE_CHAR:
4055         case MONO_TYPE_U:
4056         case MONO_TYPE_I:
4057         case MONO_TYPE_U1:
4058         case MONO_TYPE_I1:
4059         case MONO_TYPE_U2:
4060         case MONO_TYPE_I2:
4061         case MONO_TYPE_U4:
4062         case MONO_TYPE_I4:
4063         case MONO_TYPE_U8:
4064         case MONO_TYPE_I8:
4065         case MONO_TYPE_R8:
4066         case MONO_TYPE_R4:
4067         case MONO_TYPE_VALUETYPE:
4068                 return FALSE;
4069         default:
4070                 return TRUE;
4071         }
4072 }
4073
4074 static void
4075 free_param_data (MonoMethodSignature *sig, void **params) {
4076         int i;
4077         for (i = 0; i < sig->param_count; ++i) {
4078                 if (!type_is_reference (sig->params [i]))
4079                         g_free (params [i]);
4080         }
4081 }
4082
4083 /*
4084  * Find the method index in the metadata methodDef table.
4085  * Later put these three helper methods in metadata and export them.
4086  */
4087 static guint32
4088 find_method_index (MonoMethod *method) {
4089         MonoClass *klass = method->klass;
4090         int i;
4091
4092         for (i = 0; i < klass->method.count; ++i) {
4093                 if (method == klass->methods [i])
4094                         return klass->method.first + 1 + i;
4095         }
4096         return 0;
4097 }
4098
4099 /*
4100  * Find the field index in the metadata FieldDef table.
4101  */
4102 static guint32
4103 find_field_index (MonoClass *klass, MonoClassField *field) {
4104         int i;
4105
4106         for (i = 0; i < klass->field.count; ++i) {
4107                 if (field == &klass->fields [i])
4108                         return klass->field.first + 1 + i;
4109         }
4110         return 0;
4111 }
4112
4113 /*
4114  * Find the property index in the metadata Property table.
4115  */
4116 static guint32
4117 find_property_index (MonoClass *klass, MonoProperty *property) {
4118         int i;
4119
4120         for (i = 0; i < klass->property.count; ++i) {
4121                 if (property == &klass->properties [i])
4122                         return klass->property.first + 1 + i;
4123         }
4124         return 0;
4125 }
4126
4127 /*
4128  * Find the event index in the metadata Event table.
4129  */
4130 static guint32
4131 find_event_index (MonoClass *klass, MonoEvent *event) {
4132         int i;
4133
4134         for (i = 0; i < klass->event.count; ++i) {
4135                 if (event == &klass->events [i])
4136                         return klass->event.first + 1 + i;
4137         }
4138         return 0;
4139 }
4140
4141 static MonoObject*
4142 create_custom_attr (MonoImage *image, MonoMethod *method, 
4143                                         const char *data, guint32 len)
4144 {
4145         const char *p = data;
4146         const char *named;
4147         guint32 i, j, num_named;
4148         MonoObject *attr;
4149         void **params;
4150
4151         if (len < 2 || read16 (p) != 0x0001) /* Prolog */
4152                 return NULL;
4153
4154         mono_class_init (method->klass);
4155         /*g_print ("got attr %s\n", method->klass->name);*/
4156         
4157         params = g_new (void*, method->signature->param_count);
4158
4159         /* skip prolog */
4160         p += 2;
4161         for (i = 0; i < method->signature->param_count; ++i) {
4162                 params [i] = load_cattr_value (image, method->signature->params [i], p, &p);
4163         }
4164
4165         named = p;
4166         attr = mono_object_new (mono_domain_get (), method->klass);
4167         mono_runtime_invoke (method, attr, params, NULL);
4168         free_param_data (method->signature, params);
4169         g_free (params);
4170         num_named = read16 (named);
4171         named += 2;
4172         for (j = 0; j < num_named; j++) {
4173                 gint name_len;
4174                 char *name, named_type;
4175                 named_type = *named++;
4176                 named++; /* type of data */
4177                 name_len = mono_metadata_decode_blob_size (named, &named);
4178                 name = g_malloc (name_len + 1);
4179                 memcpy (name, named, name_len);
4180                 name [name_len] = 0;
4181                 named += name_len;
4182                 if (named_type == 0x53) {
4183                         MonoClassField *field = mono_class_get_field_from_name (mono_object_class (attr), name);
4184                         void *val = load_cattr_value (image, field->type, named, &named);
4185                                 mono_field_set_value (attr, field, val);
4186                                 if (!type_is_reference (field->type))
4187                                         g_free (val);
4188                 } else if (named_type == 0x54) {
4189                         MonoProperty *prop = mono_class_get_property_from_name (mono_object_class (attr), name);
4190                         void *pparams [1];
4191                         MonoType *prop_type;
4192                         /* can we have more that 1 arg in a custom attr named property? */
4193                         prop_type = prop->get? prop->get->signature->ret: prop->set->signature->params [prop->set->signature->param_count - 1];
4194                         pparams [0] = load_cattr_value (image, prop_type, named, &named);
4195                         mono_property_set_value (prop, attr, pparams, NULL);
4196                         if (!type_is_reference (prop_type))
4197                                 g_free (pparams [0]);
4198                 }
4199                 g_free (name);
4200         }
4201
4202         return attr;
4203 }
4204
4205 /*
4206  * mono_reflection_get_custom_attrs:
4207  * @obj: a reflection object handle
4208  *
4209  * Return an array with all the custom attributes defined of the
4210  * reflection handle @obj. The objects are fully build.
4211  */
4212 MonoArray*
4213 mono_reflection_get_custom_attrs (MonoObject *obj)
4214 {
4215         guint32 idx, mtoken, i, len;
4216         guint32 cols [MONO_CUSTOM_ATTR_SIZE];
4217         MonoClass *klass;
4218         MonoImage *image;
4219         MonoTableInfo *ca;
4220         MonoMethod *method;
4221         MonoObject *attr;
4222         MonoArray *result;
4223         GList *list = NULL;
4224         MonoArray *dynamic_attrs = NULL;
4225         
4226         MONO_ARCH_SAVE_REGS;
4227         
4228         klass = obj->vtable->klass;
4229         /* FIXME: need to handle: Module */
4230         if (klass == mono_defaults.monotype_class) {
4231                 MonoReflectionType *rtype = (MonoReflectionType*)obj;
4232                 klass = mono_class_from_mono_type (rtype->type);
4233                 idx = mono_metadata_token_index (klass->type_token);
4234                 idx <<= CUSTOM_ATTR_BITS;
4235                 idx |= CUSTOM_ATTR_TYPEDEF;
4236                 image = klass->image;
4237         } else if (strcmp ("Assembly", klass->name) == 0) {
4238                 MonoReflectionAssembly *rassembly = (MonoReflectionAssembly*)obj;
4239                 idx = 1; /* there is only one assembly */
4240                 idx <<= CUSTOM_ATTR_BITS;
4241                 idx |= CUSTOM_ATTR_ASSEMBLY;
4242                 image = rassembly->assembly->image;
4243         } else if (strcmp ("MonoProperty", klass->name) == 0) {
4244                 MonoReflectionProperty *rprop = (MonoReflectionProperty*)obj;
4245                 idx = find_property_index (rprop->klass, rprop->property);
4246                 idx <<= CUSTOM_ATTR_BITS;
4247                 idx |= CUSTOM_ATTR_PROPERTY;
4248                 image = rprop->klass->image;
4249         } else if (strcmp ("MonoEvent", klass->name) == 0) {
4250                 MonoReflectionEvent *revent = (MonoReflectionEvent*)obj;
4251                 idx = find_event_index (revent->klass, revent->event);
4252                 idx <<= CUSTOM_ATTR_BITS;
4253                 idx |= CUSTOM_ATTR_EVENT;
4254                 image = revent->klass->image;
4255         } else if (strcmp ("MonoField", klass->name) == 0) {
4256                 MonoReflectionField *rfield = (MonoReflectionField*)obj;
4257                 idx = find_field_index (rfield->klass, rfield->field);
4258                 idx <<= CUSTOM_ATTR_BITS;
4259                 idx |= CUSTOM_ATTR_FIELDDEF;
4260                 image = rfield->klass->image;
4261         } else if ((strcmp ("MonoMethod", klass->name) == 0) || (strcmp ("MonoCMethod", klass->name) == 0)) {
4262                 MonoReflectionMethod *rmethod = (MonoReflectionMethod*)obj;
4263                 idx = find_method_index (rmethod->method);
4264                 idx <<= CUSTOM_ATTR_BITS;
4265                 idx |= CUSTOM_ATTR_METHODDEF;
4266                 image = rmethod->method->klass->image;
4267         } else if (strcmp ("ParameterInfo", klass->name) == 0) {
4268                 MonoReflectionParameter *param = (MonoReflectionParameter*)obj;
4269                 MonoReflectionMethod *rmethod = (MonoReflectionMethod*)param->MemberImpl;
4270                 guint32 method_index = find_method_index (rmethod->method);
4271                 guint32 param_list, param_last, param_pos, found;
4272
4273                 image = rmethod->method->klass->image;
4274                 ca = &image->tables [MONO_TABLE_METHOD];
4275
4276                 param_list = mono_metadata_decode_row_col (ca, method_index - 1, MONO_METHOD_PARAMLIST);
4277                 if (method_index == ca->rows) {
4278                         ca = &image->tables [MONO_TABLE_PARAM];
4279                         param_last = ca->rows + 1;
4280                 } else {
4281                         param_last = mono_metadata_decode_row_col (ca, method_index, MONO_METHOD_PARAMLIST);
4282                         ca = &image->tables [MONO_TABLE_PARAM];
4283                 }
4284                 found = 0;
4285                 for (i = param_list; i < param_last; ++i) {
4286                         param_pos = mono_metadata_decode_row_col (ca, i - 1, MONO_PARAM_SEQUENCE);
4287                         if (param_pos == param->PositionImpl) {
4288                                 found = 1;
4289                                 break;
4290                         }
4291                 }
4292                 if (!found)
4293                         return mono_array_new (mono_domain_get (), mono_defaults.object_class, 0);
4294                 idx = i;
4295                 idx <<= CUSTOM_ATTR_BITS;
4296                 idx |= CUSTOM_ATTR_PARAMDEF;
4297         } else if (strcmp ("AssemblyBuilder", klass->name) == 0) {
4298                 MonoReflectionAssemblyBuilder *assemblyb = (MonoReflectionAssemblyBuilder*)obj;
4299                 dynamic_attrs = assemblyb->cattrs;
4300                 if (!dynamic_attrs)
4301                         return mono_array_new (mono_domain_get (), mono_defaults.object_class, 0);
4302         } else { /* handle other types here... */
4303                 g_error ("get custom attrs not yet supported for %s", klass->name);
4304         }
4305
4306         if (dynamic_attrs) {
4307                 len = mono_array_length (dynamic_attrs);
4308                 for (i = 0; i < len; ++i) {
4309                         MonoReflectionCustomAttr *cattr = (MonoReflectionCustomAttr*)mono_array_get (dynamic_attrs, gpointer, i);                       
4310                         attr = create_custom_attr (image, cattr->ctor->method, mono_array_addr (cattr->data, int, 0), mono_array_length (cattr->data));
4311                         list = g_list_prepend (list, attr);
4312                 }               
4313         }
4314         else {
4315                 /* at this point image and index are set correctly for searching the custom attr */
4316                 ca = &image->tables [MONO_TABLE_CUSTOMATTRIBUTE];
4317                 /* the table is not sorted */
4318                 for (i = 0; i < ca->rows; ++i) {
4319                         mono_metadata_decode_row (ca, i, cols, MONO_CUSTOM_ATTR_SIZE);
4320                         if (cols [MONO_CUSTOM_ATTR_PARENT] != idx)
4321                                 continue;
4322                         mtoken = cols [MONO_CUSTOM_ATTR_TYPE] >> CUSTOM_ATTR_TYPE_BITS;
4323                         switch (cols [MONO_CUSTOM_ATTR_TYPE] & CUSTOM_ATTR_TYPE_MASK) {
4324                         case CUSTOM_ATTR_TYPE_METHODDEF:
4325                                 mtoken |= MONO_TOKEN_METHOD_DEF;
4326                                 break;
4327                         case CUSTOM_ATTR_TYPE_MEMBERREF:
4328                                 mtoken |= MONO_TOKEN_MEMBER_REF;
4329                                 break;
4330                         default:
4331                                 g_error ("Unknown table for custom attr type %08x", cols [MONO_CUSTOM_ATTR_TYPE]);
4332                                 break;
4333                         }
4334                         method = mono_get_method (image, mtoken, NULL);
4335                         if (!method)
4336                                 g_error ("Can't find custom attr constructor image: %s mtoken: 0x%08x", image->name, mtoken);
4337
4338                         {
4339                                 int data_len;
4340                                 const char *data = mono_metadata_blob_heap (image, cols [MONO_CUSTOM_ATTR_VALUE]);
4341                                 data_len = mono_metadata_decode_value (data, &data);
4342
4343                                 attr = create_custom_attr (image, method, data, data_len);
4344                         }
4345                         list = g_list_prepend (list, attr);
4346                 }
4347         }
4348
4349         len = g_list_length (list);
4350         /*
4351          * The return type is really object[], but System/Attribute.cs does a cast
4352          * to (Attribute []) and that is not allowed: I'm lazy for now, but we should
4353          * probably fix that.
4354          */
4355         klass = mono_class_from_name (mono_defaults.corlib, "System", "Attribute");
4356         result = mono_array_new (mono_domain_get (), klass, len);
4357         for (i = 0; i < len; ++i) {
4358                 mono_array_set (result, gpointer, i, list->data);
4359                 list = list->next;
4360         }
4361         g_list_free (g_list_first (list));
4362
4363         return result;
4364 }
4365
4366 static MonoMethodSignature*
4367 parameters_to_signature (MonoArray *parameters) {
4368         MonoMethodSignature *sig;
4369         int count, i;
4370
4371         count = parameters? mono_array_length (parameters): 0;
4372
4373         sig = g_malloc0 (sizeof (MonoMethodSignature) + sizeof (MonoType*) * count);
4374         sig->param_count = count;
4375         sig->sentinelpos = -1; /* FIXME */
4376         for (i = 0; i < count; ++i) {
4377                 MonoReflectionType *pt = mono_array_get (parameters, MonoReflectionType*, i);
4378                 sig->params [i] = pt->type;
4379         }
4380         return sig;
4381 }
4382
4383 static MonoMethodSignature*
4384 ctor_builder_to_signature (MonoReflectionCtorBuilder *ctor) {
4385         MonoMethodSignature *sig;
4386
4387         sig = parameters_to_signature (ctor->parameters);
4388         sig->hasthis = ctor->attrs & METHOD_ATTRIBUTE_STATIC? 0: 1;
4389         sig->ret = &mono_defaults.void_class->byval_arg;
4390         return sig;
4391 }
4392
4393 static MonoMethodSignature*
4394 method_builder_to_signature (MonoReflectionMethodBuilder *method) {
4395         MonoMethodSignature *sig;
4396
4397         sig = parameters_to_signature (method->parameters);
4398         sig->hasthis = method->attrs & METHOD_ATTRIBUTE_STATIC? 0: 1;
4399         sig->ret = method->rtype? method->rtype->type: &mono_defaults.void_class->byval_arg;
4400         return sig;
4401 }
4402
4403 static void
4404 get_prop_name_and_type (MonoObject *prop, char **name, MonoType **type)
4405 {
4406         MonoClass *klass = mono_object_class (prop);
4407         if (strcmp (klass->name, "PropertyBuilder") == 0) {
4408                 MonoReflectionPropertyBuilder *pb = (MonoReflectionPropertyBuilder *)prop;
4409                 *name = mono_string_to_utf8 (pb->name);
4410                 *type = pb->type->type;
4411         } else {
4412                 MonoReflectionProperty *p = (MonoReflectionProperty *)prop;
4413                 *name = g_strdup (p->property->name);
4414                 if (p->property->get)
4415                         *type = p->property->get->signature->ret;
4416                 else
4417                         *type = p->property->set->signature->params [p->property->set->signature->param_count - 1];
4418         }
4419 }
4420
4421 static void
4422 get_field_name_and_type (MonoObject *field, char **name, MonoType **type)
4423 {
4424         MonoClass *klass = mono_object_class (field);
4425         if (strcmp (klass->name, "FieldBuilder") == 0) {
4426                 MonoReflectionFieldBuilder *fb = (MonoReflectionFieldBuilder *)field;
4427                 *name = mono_string_to_utf8 (fb->name);
4428                 *type = fb->type->type;
4429         } else {
4430                 MonoReflectionField *f = (MonoReflectionField *)field;
4431                 *name = g_strdup (f->field->name);
4432                 *type = f->field->type;
4433         }
4434 }
4435
4436 static char*
4437 type_get_qualified_name (MonoType *type, MonoAssembly *ass) {
4438         char *name, *result;
4439         MonoClass *klass;
4440         MonoAssembly *ta;
4441
4442         name = mono_type_get_name (type);
4443         klass = my_mono_class_from_mono_type (type);
4444         ta = klass->image->assembly;
4445         if (ta == ass || klass->image == mono_defaults.corlib)
4446                 return name;
4447
4448         /* missing public key */
4449         result = g_strdup_printf ("%s, %s, Version=%d.%d.%d.%d, Culture=%s",
4450                 name, ta->aname.name,
4451                 ta->aname.major, ta->aname.minor, ta->aname.build, ta->aname.revision,
4452                 ta->aname.culture && *ta->aname.culture? ta->aname.culture: "neutral");
4453         g_free (name);
4454         return result;
4455 }
4456
4457 static void
4458 encode_cattr_value (char *buffer, char *p, char **retbuffer, char **retp, guint32 *buflen, MonoType *type, MonoObject *arg)
4459 {
4460         char *argval;
4461         MonoTypeEnum simple_type;
4462         
4463         if ((p-buffer) + 10 >= *buflen) {
4464                 char *newbuf;
4465                 *buflen *= 2;
4466                 newbuf = g_realloc (buffer, *buflen);
4467                 p = newbuf + (p-buffer);
4468                 buffer = newbuf;
4469         }
4470         argval = ((char*)arg + sizeof (MonoObject));
4471         simple_type = type->type;
4472 handle_enum:
4473         switch (simple_type) {
4474         case MONO_TYPE_BOOLEAN:
4475         case MONO_TYPE_U1:
4476         case MONO_TYPE_I1:
4477                 *p++ = *argval;
4478                 break;
4479         case MONO_TYPE_CHAR:
4480         case MONO_TYPE_U2:
4481         case MONO_TYPE_I2:
4482                 swap_with_size (p, argval, 2, 1);
4483                 p += 2;
4484                 break;
4485         case MONO_TYPE_U4:
4486         case MONO_TYPE_I4:
4487         case MONO_TYPE_R4:
4488                 swap_with_size (p, argval, 4, 1);
4489                 p += 4;
4490                 break;
4491         case MONO_TYPE_U8:
4492         case MONO_TYPE_I8:
4493         case MONO_TYPE_R8:
4494                 swap_with_size (p, argval, 8, 1);
4495                 p += 8;
4496                 break;
4497         case MONO_TYPE_VALUETYPE:
4498                 if (type->data.klass->enumtype) {
4499                         simple_type = type->data.klass->enum_basetype->type;
4500                         goto handle_enum;
4501                 } else {
4502                         g_warning ("generic valutype %s not handled in custom attr value decoding", type->data.klass->name);
4503                 }
4504                 break;
4505         case MONO_TYPE_STRING: {
4506                 char *str;
4507                 guint32 slen;
4508                 if (!arg) {
4509                         *p++ = 0xFF;
4510                         break;
4511                 }
4512                 str = mono_string_to_utf8 ((MonoString*)arg);
4513                 slen = strlen (str);
4514                 if ((p-buffer) + 10 + slen >= *buflen) {
4515                         char *newbuf;
4516                         *buflen *= 2;
4517                         *buflen += slen;
4518                         newbuf = g_realloc (buffer, *buflen);
4519                         p = newbuf + (p-buffer);
4520                         buffer = newbuf;
4521                 }
4522                 mono_metadata_encode_value (slen, p, &p);
4523                 memcpy (p, str, slen);
4524                 p += slen;
4525                 g_free (str);
4526                 break;
4527         }
4528         case MONO_TYPE_CLASS: {
4529                 char *str;
4530                 guint32 slen;
4531                 MonoClass *k = mono_object_class (arg);
4532                 if (!mono_object_isinst (arg, mono_defaults.monotype_class) &&
4533                                 (strcmp (k->name, "TypeBuilder") || strcmp (k->name_space, "System.Reflection.Emit")))
4534                         g_error ("only types allowed, not %s.%s", k->name_space, k->name);
4535 handle_type:
4536                 str = type_get_qualified_name (((MonoReflectionType*)arg)->type, NULL);
4537                 slen = strlen (str);
4538                 if ((p-buffer) + 10 + slen >= *buflen) {
4539                         char *newbuf;
4540                         *buflen *= 2;
4541                         *buflen += slen;
4542                         newbuf = g_realloc (buffer, *buflen);
4543                         p = newbuf + (p-buffer);
4544                         buffer = newbuf;
4545                 }
4546                 mono_metadata_encode_value (slen, p, &p);
4547                 memcpy (p, str, slen);
4548                 p += slen;
4549                 g_free (str);
4550                 break;
4551         }
4552         /* it may be a boxed value or a Type */
4553         case MONO_TYPE_OBJECT: {
4554                 MonoClass *klass = mono_object_class (arg);
4555                 char *str;
4556                 guint32 slen;
4557                 
4558                 if (mono_object_isinst (arg, mono_defaults.monotype_class)) {
4559                         *p++ = 0x50;
4560                         goto handle_type;
4561                 } else if (klass->enumtype) {
4562                         *p++ = 0x55;
4563                 } else if (klass->byval_arg.type >= MONO_TYPE_BOOLEAN && klass->byval_arg.type <= MONO_TYPE_R8) {
4564                         *p++ = simple_type = klass->byval_arg.type;
4565                         goto handle_enum;
4566                 } else {
4567                         g_error ("unhandled type in custom attr");
4568                 }
4569                 str = type_get_qualified_name (klass->enum_basetype, NULL);
4570                 slen = strlen (str);
4571                 if ((p-buffer) + 10 + slen >= *buflen) {
4572                         char *newbuf;
4573                         *buflen *= 2;
4574                         *buflen += slen;
4575                         newbuf = g_realloc (buffer, *buflen);
4576                         p = newbuf + (p-buffer);
4577                         buffer = newbuf;
4578                 }
4579                 mono_metadata_encode_value (slen, p, &p);
4580                 memcpy (p, str, slen);
4581                 p += slen;
4582                 g_free (str);
4583                 simple_type = klass->enum_basetype->type;
4584                 goto handle_enum;
4585         }
4586         default:
4587                 g_error ("type 0x%02x not yet supported in custom attr encoder", simple_type);
4588         }
4589         *retp = p;
4590         *retbuffer = buffer;
4591 }
4592
4593 /*
4594  * mono_reflection_get_custom_attrs_blob:
4595  * @ctor: custom attribute constructor
4596  * @ctorArgs: arguments o the constructor
4597  * @properties:
4598  * @propValues:
4599  * @fields:
4600  * @fieldValues:
4601  * 
4602  * Creates the blob of data that needs to be saved in the metadata and that represents
4603  * the custom attributed described by @ctor, @ctorArgs etc.
4604  * Returns: a Byte array representing the blob of data.
4605  */
4606 MonoArray*
4607 mono_reflection_get_custom_attrs_blob (MonoObject *ctor, MonoArray *ctorArgs, MonoArray *properties, MonoArray *propValues, MonoArray *fields, MonoArray* fieldValues) 
4608 {
4609         MonoArray *result;
4610         MonoMethodSignature *sig;
4611         MonoObject *arg;
4612         char *buffer, *p;
4613         guint32 buflen, i;
4614
4615         MONO_ARCH_SAVE_REGS;
4616
4617         if (strcmp (ctor->vtable->klass->name, "MonoCMethod")) {
4618                 sig = ctor_builder_to_signature ((MonoReflectionCtorBuilder*)ctor);
4619         } else {
4620                 sig = ((MonoReflectionMethod*)ctor)->method->signature;
4621         }
4622         buflen = 256;
4623         p = buffer = g_malloc (buflen);
4624         /* write the prolog */
4625         *p++ = 1;
4626         *p++ = 0;
4627         for (i = 0; i < sig->param_count; ++i) {
4628                 if (sig->params[i]->type==MONO_TYPE_SZARRAY)
4629                 {
4630                         guint32 alen=mono_array_length(ctorArgs) - i;
4631                         guint32 j;
4632                         if ((p-buffer) + 10 >= buflen) {
4633                                 char *newbuf;
4634                                 buflen *= 2;
4635                                 newbuf = g_realloc (buffer, buflen);
4636                                 p = newbuf + (p-buffer);
4637                                 buffer = newbuf;
4638                         }
4639                         *p++=alen&0xff;
4640                         *p++=(alen>>8)&0xff;
4641                         *p++=(alen>>16)&0xff;
4642                         *p++=(alen>>24)&0xff;
4643                         for (j=0;j<alen;j++)
4644                         {
4645                                 arg=(MonoObject*)mono_array_get(ctorArgs,gpointer,i+j);
4646                                 encode_cattr_value(buffer,p,&buffer,&p,&buflen,sig->params[i]->data.type,arg);
4647                         }
4648                 }
4649                 else
4650                 {
4651                         arg = (MonoObject*)mono_array_get (ctorArgs, gpointer, i);
4652                         encode_cattr_value (buffer, p, &buffer, &p, &buflen, sig->params [i], arg);
4653                 }
4654         }
4655         i = 0;
4656         if (properties)
4657                 i += mono_array_length (properties);
4658         if (fields)
4659                 i += mono_array_length (fields);
4660         *p++ = i & 0xff;
4661         *p++ = (i >> 8) & 0xff;
4662         if (properties) {
4663                 MonoObject *prop;
4664                 for (i = 0; i < mono_array_length (properties); ++i) {
4665                         MonoType *ptype;
4666                         char *pname;
4667                         int len;
4668                         
4669                         prop = mono_array_get (properties, gpointer, i);
4670                         get_prop_name_and_type (prop, &pname, &ptype);
4671                         *p++ = 0x54; /* PROPERTY signature */
4672                         mono_metadata_encode_value (ptype->type, p, &p);
4673                         len = strlen (pname);
4674                         mono_metadata_encode_value (len, p, &p);
4675                         memcpy (p, pname, len);
4676                         p += len;
4677                         encode_cattr_value (buffer, p, &buffer, &p, &buflen, ptype, (MonoObject*)mono_array_get (propValues, gpointer, i));
4678                         g_free (pname);
4679                 }
4680         }
4681
4682         if (fields) {
4683                 MonoObject *field;
4684                 for (i = 0; i < mono_array_length (fields); ++i) {
4685                         MonoType *ftype;
4686                         char *fname;
4687                         int len;
4688                         
4689                         field = mono_array_get (fields, gpointer, i);
4690                         get_field_name_and_type (field, &fname, &ftype);
4691                         *p++ = 0x53; /* FIELD signature */
4692                         mono_metadata_encode_value (ftype->type, p, &p);
4693                         len = strlen (fname);
4694                         mono_metadata_encode_value (len, p, &p);
4695                         memcpy (p, fname, len);
4696                         p += len;
4697                         encode_cattr_value (buffer, p, &buffer, &p, &buflen, ftype, (MonoObject*)mono_array_get (fieldValues, gpointer, i));
4698                         g_free (fname);
4699                 }
4700         }
4701
4702         g_assert (p - buffer <= buflen);
4703         buflen = p - buffer;
4704         result = mono_array_new (mono_domain_get (), mono_defaults.byte_class, buflen);
4705         p = mono_array_addr (result, char, 0);
4706         memcpy (p, buffer, buflen);
4707         g_free (buffer);
4708         if (strcmp (ctor->vtable->klass->name, "MonoCMethod"))
4709                 g_free (sig);
4710         return result;
4711 }
4712
4713 /*
4714  * mono_reflection_setup_internal_class:
4715  * @tb: a TypeBuilder object
4716  *
4717  * Creates a MonoClass that represents the TypeBuilder.
4718  * This is a trick that lets us simplify a lot of reflection code
4719  * (and will allow us to support Build and Run assemblies easier).
4720  */
4721 void
4722 mono_reflection_setup_internal_class (MonoReflectionTypeBuilder *tb)
4723 {
4724         MonoClass *klass, *parent;
4725
4726         MONO_ARCH_SAVE_REGS;
4727
4728         klass = g_new0 (MonoClass, 1);
4729
4730         klass->image = tb->module->assemblyb->dynamic_assembly->assembly.image;
4731
4732         if (tb->parent) {
4733                 /* check so we can compile corlib correctly */
4734                 if (strcmp (mono_object_class (tb->parent)->name, "TypeBuilder") == 0) {
4735                         /* mono_class_setup_mono_type () guaranteess type->data.klass is valid */
4736                         parent = tb->parent->type->data.klass;
4737                 } else 
4738                         parent = my_mono_class_from_mono_type (tb->parent->type);
4739         } else
4740                 parent = NULL;
4741         
4742         klass->inited = 1; /* we lie to the runtime */
4743         klass->name = mono_string_to_utf8 (tb->name);
4744         klass->name_space = mono_string_to_utf8 (tb->nspace);
4745         klass->type_token = MONO_TOKEN_TYPE_DEF | tb->table_idx;
4746         klass->flags = tb->attrs;
4747
4748         klass->element_class = klass;
4749         klass->reflection_info = tb; /* need to pin. */
4750
4751         /* Put into cache so mono_class_get () will find it */
4752         mono_image_add_to_name_cache (klass->image, klass->name_space, klass->name,
4753                                                                   tb->table_idx);
4754
4755         mono_g_hash_table_insert (tb->module->assemblyb->dynamic_assembly->tokens,
4756                                                           GUINT_TO_POINTER (MONO_TOKEN_TYPE_DEF | tb->table_idx),
4757                                                           tb);
4758
4759         if (parent != NULL)
4760                 mono_class_setup_parent (klass, parent);
4761         else if (strcmp (klass->name, "Object") == 0 && strcmp (klass->name_space, "System") == 0) {
4762                 const char *old_n = klass->name;
4763                 /* trick to get relative numbering right when compiling corlib */
4764                 klass->name = "BuildingObject";
4765                 mono_class_setup_parent (klass, mono_defaults.object_class);
4766                 klass->name = old_n;
4767         }
4768         mono_class_setup_mono_type (klass);
4769
4770         /*
4771          * FIXME: handle interfaces.
4772          */
4773
4774         tb->type.type = &klass->byval_arg;
4775
4776         /*g_print ("setup %s as %s (%p)\n", klass->name, ((MonoObject*)tb)->vtable->klass->name, tb);*/
4777 }
4778
4779 /*
4780  * mono_reflection_create_internal_class:
4781  * @tb: a TypeBuilder object
4782  *
4783  * Actually create the MonoClass that is associated with the TypeBuilder.
4784  */
4785 void
4786 mono_reflection_create_internal_class (MonoReflectionTypeBuilder *tb)
4787 {
4788         MonoClass *klass;
4789
4790         MONO_ARCH_SAVE_REGS;
4791
4792         klass = my_mono_class_from_mono_type (tb->type.type);
4793
4794         if (klass->enumtype && klass->enum_basetype == NULL) {
4795                 MonoReflectionFieldBuilder *fb;
4796
4797                 g_assert (tb->fields != NULL);
4798                 g_assert (mono_array_length (tb->fields) >= 1);
4799
4800                 fb = mono_array_get (tb->fields, MonoReflectionFieldBuilder*, 0);
4801
4802                 klass->enum_basetype = fb->type->type;
4803                 klass->element_class = my_mono_class_from_mono_type (klass->enum_basetype);
4804                 if (!klass->element_class)
4805                         klass->element_class = mono_class_from_mono_type (klass->enum_basetype);
4806                 klass->instance_size = klass->element_class->instance_size;
4807                 klass->size_inited = 1;
4808                 /* 
4809                  * this is almost safe to do with enums and it's needed to be able
4810                  * to create objects of the enum type (for use in SetConstant).
4811                  */
4812                 /* FIXME: Does this mean enums can't have method overrides ? */
4813                 mono_class_setup_vtable (klass, NULL, 0);
4814         }
4815 }
4816
4817 static MonoMethod*
4818 reflection_methodbuilder_to_mono_method (MonoClass *klass,
4819                                                                                  ReflectionMethodBuilder *rmb,
4820                                                                                  MonoMethodSignature *sig)
4821 {
4822         MonoMethod *m;
4823         MonoMethodNormal *pm;
4824
4825         if ((rmb->attrs & METHOD_ATTRIBUTE_PINVOKE_IMPL) ||
4826             (rmb->iattrs & METHOD_IMPL_ATTRIBUTE_INTERNAL_CALL))
4827                 m = (MonoMethod *)g_new0 (MonoMethodPInvoke, 1);
4828         else 
4829                 m = (MonoMethod *)g_new0 (MonoMethodNormal, 1);
4830
4831         pm = (MonoMethodNormal*)m;
4832
4833         m->slot = -1;
4834         m->flags = rmb->attrs;
4835         m->iflags = rmb->iattrs;
4836         m->name = mono_string_to_utf8 (rmb->name);
4837         m->klass = klass;
4838         m->signature = sig;
4839
4840         /* TODO: What about m->token ? */
4841         if (m->iflags & METHOD_IMPL_ATTRIBUTE_INTERNAL_CALL) {
4842                 if (klass == mono_defaults.string_class && !strcmp (m->name, ".ctor"))
4843                         m->string_ctor = 1;
4844
4845                 m->addr = mono_lookup_internal_call (m);
4846                 m->signature->pinvoke = 1;
4847         } else if (m->flags & METHOD_ATTRIBUTE_PINVOKE_IMPL) {
4848                 /* TODO */
4849                 m->signature->pinvoke = 1;
4850                 return m;
4851         } else if (!m->klass->dummy && 
4852                            !(m->flags & METHOD_ATTRIBUTE_ABSTRACT) &&
4853                            !(m->iflags & METHOD_IMPL_ATTRIBUTE_RUNTIME)) {
4854                 MonoMethodHeader *header;
4855                 guint32 code_size;
4856                 gint32 max_stack, i;
4857                 gint32 num_locals = 0;
4858                 gint32 num_clauses = 0;
4859                 guint8 *code;
4860
4861                 if (rmb->ilgen) {
4862                         code = mono_array_addr (rmb->ilgen->code, guint8, 0);
4863                         code_size = rmb->ilgen->code_len;
4864                         max_stack = rmb->ilgen->max_stack;
4865                         num_locals = rmb->ilgen->locals ? mono_array_length (rmb->ilgen->locals) : 0;
4866                         if (rmb->ilgen->ex_handlers)
4867                                 num_clauses = method_count_clauses (rmb->ilgen);
4868                 } else {
4869                         if (rmb->code) {
4870                                 code = mono_array_addr (rmb->code, guint8, 0);
4871                                 code_size = mono_array_length (rmb->code);
4872                                 /* we probably need to run a verifier on the code... */
4873                                 max_stack = 8; 
4874                         }
4875                         else {
4876                                 code = NULL;
4877                                 code_size = 0;
4878                                 max_stack = 8;
4879                         }
4880                 }
4881
4882                 header = g_malloc0 (sizeof (MonoMethodHeader) + 
4883                                                         (num_locals - MONO_ZERO_LEN_ARRAY) * sizeof (MonoType*));
4884                 header->code_size = code_size;
4885                 header->code = g_malloc (code_size);
4886                 memcpy ((char*)header->code, code, code_size);
4887                 header->max_stack = max_stack;
4888                 header->init_locals = rmb->init_locals;
4889                 header->num_locals = num_locals;
4890
4891                 for (i = 0; i < num_locals; ++i) {
4892                         MonoReflectionLocalBuilder *lb = 
4893                                 mono_array_get (rmb->ilgen->locals, 
4894                                                                 MonoReflectionLocalBuilder*, i);
4895
4896                         header->locals [i] = g_new0 (MonoType, 1);
4897                         memcpy (header->locals [i], lb->type->type, sizeof (MonoType));
4898                 }
4899
4900                 header->num_clauses = num_clauses;
4901                 if (num_clauses) {
4902                         header->clauses = method_encode_clauses (klass->image->assembly->dynamic,
4903                                                                                                          rmb->ilgen,
4904                                                                                                          num_clauses);
4905                 }
4906
4907                 pm->header = header;
4908         }
4909
4910         return m;
4911 }       
4912
4913 static MonoMethod*
4914 ctorbuilder_to_mono_method (MonoClass *klass, MonoReflectionCtorBuilder* mb)
4915 {
4916         ReflectionMethodBuilder rmb;
4917         const char *name;
4918         MonoMethodSignature *sig;
4919
4920         name = mb->attrs & METHOD_ATTRIBUTE_STATIC ? ".cctor": ".ctor";
4921
4922         sig = ctor_builder_to_signature (mb);
4923
4924         rmb.ilgen = mb->ilgen;
4925         rmb.parameters = mb->parameters;
4926         rmb.pinfo = mb->pinfo;
4927         rmb.attrs = mb->attrs;
4928         rmb.iattrs = mb->iattrs;
4929         rmb.call_conv = mb->call_conv;
4930         rmb.type = mb->type;
4931         rmb.name = mono_string_new (mono_domain_get (), name);
4932         rmb.table_idx = &mb->table_idx;
4933         rmb.init_locals = mb->init_locals;
4934         rmb.code = NULL;
4935
4936         mb->mhandle = reflection_methodbuilder_to_mono_method (klass, &rmb, sig);
4937         return mb->mhandle;
4938 }
4939
4940 static MonoMethod*
4941 methodbuilder_to_mono_method (MonoClass *klass, MonoReflectionMethodBuilder* mb)
4942 {
4943         ReflectionMethodBuilder rmb;
4944         MonoMethodSignature *sig;
4945
4946         sig = method_builder_to_signature (mb);
4947
4948         rmb.ilgen = mb->ilgen;
4949         rmb.parameters = mb->parameters;
4950         rmb.pinfo = mb->pinfo;
4951         rmb.attrs = mb->attrs;
4952         rmb.iattrs = mb->iattrs;
4953         rmb.call_conv = mb->call_conv;
4954         rmb.type = mb->type;
4955         rmb.name = mb->name;
4956         rmb.table_idx = &mb->table_idx;
4957         rmb.init_locals = mb->init_locals;
4958         rmb.code = mb->code;
4959
4960         mb->mhandle = reflection_methodbuilder_to_mono_method (klass, &rmb, sig);
4961         return mb->mhandle;
4962 }
4963
4964 static void
4965 ensure_runtime_vtable (MonoClass *klass)
4966 {
4967         MonoReflectionTypeBuilder *tb = klass->reflection_info;
4968         int i, num, j, onum;
4969         MonoMethod **overrides;
4970
4971         if (!tb || klass->wastypebuilder)
4972                 return;
4973         if (klass->parent)
4974                 ensure_runtime_vtable (klass->parent);
4975
4976         num = tb->ctors? mono_array_length (tb->ctors): 0;
4977         num += tb->methods? mono_array_length (tb->methods): 0;
4978         klass->method.count = num;
4979         klass->methods = g_new (MonoMethod*, num);
4980         num = tb->ctors? mono_array_length (tb->ctors): 0;
4981         for (i = 0; i < num; ++i)
4982                 klass->methods [i] = ctorbuilder_to_mono_method (klass, mono_array_get (tb->ctors, MonoReflectionCtorBuilder*, i));
4983         num = tb->methods? mono_array_length (tb->methods): 0;
4984         j = i;
4985         for (i = 0; i < num; ++i)
4986                 klass->methods [j++] = methodbuilder_to_mono_method (klass, mono_array_get (tb->methods, MonoReflectionMethodBuilder*, i));
4987
4988         klass->wastypebuilder = TRUE;
4989         if (tb->interfaces) {
4990                 klass->interface_count = mono_array_length (tb->interfaces);
4991                 klass->interfaces = g_new (MonoClass*, klass->interface_count);
4992                 for (i = 0; i < klass->interface_count; ++i) {
4993                         MonoReflectionType *iface = mono_array_get (tb->interfaces, gpointer, i);
4994                         klass->interfaces [i] = mono_class_from_mono_type (iface->type);
4995                 }
4996         }
4997
4998         /* Overrides */
4999         onum = 0;
5000         if (tb->methods) {
5001                 for (i = 0; i < mono_array_length (tb->methods); ++i) {
5002                         MonoReflectionMethodBuilder *mb = 
5003                                 mono_array_get (tb->methods, MonoReflectionMethodBuilder*, i);
5004                         if (mb->override_method)
5005                                 onum ++;
5006                 }
5007         }
5008
5009         overrides = (MonoMethod**)g_new0 (MonoMethod, onum * 2);
5010
5011         if (tb->methods) {
5012                 onum = 0;
5013                 for (i = 0; i < mono_array_length (tb->methods); ++i) {
5014                         MonoReflectionMethodBuilder *mb = 
5015                                 mono_array_get (tb->methods, MonoReflectionMethodBuilder*, i);
5016                         if (mb->override_method) {
5017                                 /* FIXME: What if 'override_method' is a MethodBuilder ? */
5018                                 overrides [onum * 2] = 
5019                                         mb->override_method->method;
5020                                 overrides [onum * 2 + 1] =
5021                                         mb->mhandle;
5022
5023                                 g_assert (mb->mhandle);
5024
5025                                 onum ++;
5026                         }
5027                 }
5028         }
5029
5030         mono_class_setup_vtable (klass, overrides, onum);
5031 }
5032
5033 static void
5034 typebuilder_setup_fields (MonoClass *klass)
5035 {
5036         MonoReflectionTypeBuilder *tb = klass->reflection_info;
5037         MonoReflectionFieldBuilder *fb;
5038         MonoClassField *field;
5039         int i;
5040
5041         klass->field.count = tb->fields? mono_array_length (tb->fields): 0;
5042
5043         if (!klass->field.count)
5044                 return;
5045         
5046         klass->fields = g_new0 (MonoClassField, klass->field.count);
5047
5048         for (i = 0; i < klass->field.count; ++i) {
5049                 fb = mono_array_get (tb->fields, gpointer, i);
5050                 field = &klass->fields [i];
5051                 field->name = mono_string_to_utf8 (fb->name);
5052                 if (fb->attrs) {
5053                         /* FIXME: handle type modifiers */
5054                         field->type = g_memdup (fb->type->type, sizeof (MonoType));
5055                         field->type->attrs = fb->attrs;
5056                 } else {
5057                         field->type = fb->type->type;
5058                 }
5059                 if ((fb->attrs & FIELD_ATTRIBUTE_HAS_FIELD_RVA) && fb->rva_data)
5060                         field->data = mono_array_addr (fb->rva_data, char, 0);
5061                 if (fb->offset != -1)
5062                         field->offset = fb->offset;
5063                 field->parent = klass;
5064                 fb->handle = field;
5065         }
5066         mono_class_layout_fields (klass);
5067 }
5068
5069 MonoReflectionType*
5070 mono_reflection_create_runtime_class (MonoReflectionTypeBuilder *tb)
5071 {
5072         MonoClass *klass;
5073         MonoReflectionType* res;
5074
5075         MONO_ARCH_SAVE_REGS;
5076
5077         klass = my_mono_class_from_mono_type (tb->type.type);
5078
5079         /*
5080          * Fields to set in klass:
5081          * the various flags: delegate/unicode/contextbound etc.
5082          * nested_in
5083          * nested_classes
5084          * properties
5085          * events
5086          */
5087         klass->flags = tb->attrs;
5088         klass->element_class = klass;
5089
5090         /* enums are done right away */
5091         if (!klass->enumtype)
5092                 ensure_runtime_vtable (klass);
5093
5094         /* fields and object layout */
5095         if (klass->parent) {
5096                 if (!klass->parent->size_inited)
5097                         mono_class_init (klass->parent);
5098                 klass->instance_size += klass->parent->instance_size;
5099                 klass->class_size += klass->parent->class_size;
5100                 klass->min_align = klass->parent->min_align;
5101         } else {
5102                 klass->instance_size = sizeof (MonoObject);
5103                 klass->min_align = 1;
5104         }
5105         /* FIXME: handle packing_size and instance_size */
5106         typebuilder_setup_fields (klass);
5107
5108         /* FIXME: properties */
5109
5110         res = mono_type_get_object (mono_object_domain (tb), &klass->byval_arg);
5111         /* with enums res == tb: need to fix that. */
5112         if (!klass->enumtype)
5113                 g_assert (res != (MonoReflectionType*)tb);
5114         return res;
5115 }
5116
5117 MonoArray *
5118 mono_reflection_sighelper_get_signature_local (MonoReflectionSigHelper *sig)
5119 {
5120         MonoDynamicAssembly *assembly = sig->module->assemblyb->dynamic_assembly;
5121         guint32 na = mono_array_length (sig->arguments);
5122         guint32 buflen, i;
5123         MonoArray *result;
5124         char *buf, *p;
5125
5126         MONO_ARCH_SAVE_REGS;
5127
5128         p = buf = g_malloc (10 + na * 10);
5129
5130         mono_metadata_encode_value (0x07, p, &p);
5131         mono_metadata_encode_value (na, p, &p);
5132         for (i = 0; i < na; ++i) {
5133                 MonoReflectionType *type = mono_array_get (sig->arguments, MonoReflectionType *, i);
5134                 encode_reflection_type (assembly, type, p, &p);
5135         }
5136
5137         buflen = p - buf;
5138         result = mono_array_new (mono_domain_get (), mono_defaults.byte_class, buflen);
5139         p = mono_array_addr (result, char, 0);
5140         memcpy (p, buf, buflen);
5141         g_free (buf);
5142
5143         return result;
5144 }
5145
5146 MonoArray *
5147 mono_reflection_sighelper_get_signature_field (MonoReflectionSigHelper *sig)
5148 {
5149         MonoDynamicAssembly *assembly = sig->module->assemblyb->dynamic_assembly;
5150         guint32 na = mono_array_length (sig->arguments);
5151         guint32 buflen, i;
5152         MonoArray *result;
5153         char *buf, *p;
5154
5155         MONO_ARCH_SAVE_REGS;
5156
5157         p = buf = g_malloc (10 + na * 10);
5158
5159         mono_metadata_encode_value (0x06, p, &p);
5160         for (i = 0; i < na; ++i) {
5161                 MonoReflectionType *type = mono_array_get (sig->arguments, MonoReflectionType *, i);
5162                 encode_reflection_type (assembly, type, p, &p);
5163         }
5164
5165         buflen = p - buf;
5166         result = mono_array_new (mono_domain_get (), mono_defaults.byte_class, buflen);
5167         p = mono_array_addr (result, char, 0);
5168         memcpy (p, buf, buflen);
5169         g_free (buf);
5170
5171         return result;
5172 }
5173
5174 gpointer
5175 mono_reflection_lookup_dynamic_token (MonoImage *image, guint32 token)
5176 {
5177         MonoDynamicAssembly *assembly = image->assembly->dynamic;
5178         MonoObject *obj;
5179         gpointer result;
5180
5181         obj = mono_g_hash_table_lookup (assembly->tokens, GUINT_TO_POINTER (token));
5182         g_assert (obj);
5183
5184         if (strcmp (obj->vtable->klass->name, "String") == 0) {
5185                 result = obj;
5186                 g_assert (result);
5187         }
5188         else if (strcmp (obj->vtable->klass->name, "MonoType") == 0) {
5189                 MonoReflectionType *tb = (MonoReflectionType*)obj;
5190                 result = mono_class_from_mono_type (tb->type);
5191                 g_assert (result);
5192         }
5193         else if (strcmp (obj->vtable->klass->name, "MonoMethod") == 0) {
5194                 result = ((MonoReflectionMethod*)obj)->method;
5195                 g_assert (result);
5196         }
5197         else if (strcmp (obj->vtable->klass->name, "MonoCMethod") == 0) {
5198                 result = ((MonoReflectionMethod*)obj)->method;
5199                 g_assert (result);
5200         }
5201         else if (strcmp (obj->vtable->klass->name, "MethodBuilder") == 0) {
5202                 MonoReflectionMethodBuilder *mb = (MonoReflectionMethodBuilder*)obj;
5203                 result = mb->mhandle;
5204                 if (!result) {
5205                         /* Type is not yet created */
5206                         MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder*)mb->type;
5207
5208                         mono_domain_try_type_resolve (mono_domain_get (), NULL, (MonoObject*)tb);
5209
5210                         /*
5211                          * Hopefully this has been filled in by calling CreateType() on the
5212                          * TypeBuilder.
5213                          */
5214                         /**
5215                          * TODO: This won't work if the application finishes another 
5216                          * TypeBuilder instance instead of this one.
5217                          */
5218                         result = mb->mhandle;
5219                 }
5220         }
5221         else if (strcmp (obj->vtable->klass->name, "ConstructorBuilder") == 0) {
5222                 MonoReflectionCtorBuilder *cb = (MonoReflectionCtorBuilder*)obj;
5223
5224                 result = cb->mhandle;
5225                 if (!result) {
5226                         MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder*)cb->type;
5227
5228                         mono_domain_try_type_resolve (mono_domain_get (), NULL, (MonoObject*)tb);
5229                         result = cb->mhandle;
5230                 }
5231         }
5232         else if (strcmp (obj->vtable->klass->name, "MonoField") == 0) {
5233                 result = ((MonoReflectionField*)obj)->field;
5234                 g_assert (result);
5235         }
5236         else if (strcmp (obj->vtable->klass->name, "FieldBuilder") == 0) {
5237                 MonoReflectionFieldBuilder *fb = (MonoReflectionFieldBuilder*)obj;
5238                 result = fb->handle;
5239
5240                 if (!result) {
5241                         MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder*)fb->typeb;
5242
5243                         mono_domain_try_type_resolve (mono_domain_get (), NULL, (MonoObject*)tb);
5244                         result = fb->handle;
5245                 }
5246         }
5247         else if (strcmp (obj->vtable->klass->name, "TypeBuilder") == 0) {
5248                 MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder*)obj;
5249                 MonoClass *klass;
5250
5251                 klass = tb->type.type->data.klass;
5252                 if (klass->wastypebuilder) {
5253                         /* Already created */
5254                         result = klass;
5255                 }
5256                 else {
5257                         mono_domain_try_type_resolve (mono_domain_get (), NULL, (MonoObject*)tb);
5258                         result = tb->type.type->data.klass;
5259                         g_assert (result);
5260                 }
5261         }
5262         else if (strcmp (obj->vtable->klass->name, "SignatureHelper") == 0) {
5263                 MonoReflectionSigHelper *helper = (MonoReflectionSigHelper*)obj;
5264                 MonoMethodSignature *sig;
5265                 int nargs, i;
5266
5267                 if (helper->arguments)
5268                         nargs = mono_array_length (helper->arguments);
5269                 else
5270                         nargs = 0;
5271
5272                 sig = mono_metadata_signature_alloc (image, nargs);
5273                 sig->explicit_this = helper->call_conv & 64;
5274                 sig->hasthis = helper->call_conv & 32;
5275
5276                 if (helper->call_conv == 0) /* unmanaged */
5277                         sig->call_convention = helper->unmanaged_call_conv - 1;
5278                 else
5279                         if (helper->call_conv & 0x02)
5280                                 sig->call_convention = MONO_CALL_VARARG;
5281                 else
5282                         sig->call_convention = MONO_CALL_DEFAULT;
5283
5284                 sig->param_count = nargs;
5285                 /* TODO: Copy type ? */
5286                 sig->ret = helper->return_type->type;
5287                 for (i = 0; i < nargs; ++i) {
5288                         MonoReflectionType *rt = mono_array_get (helper->arguments, MonoReflectionType*, i);
5289                         sig->params [i] = rt->type;
5290                 }
5291
5292                 result = sig;
5293         }
5294         else {
5295                 g_print (obj->vtable->klass->name);
5296                 g_assert_not_reached ();
5297         }
5298         return result;
5299 }
5300
5301