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