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