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