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