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