In .:
[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  * Copyright 2001-2003 Ximian, Inc (http://www.ximian.com)
8  * Copyright 2004-2009 Novell, Inc (http://www.novell.com)
9  *
10  */
11 #include <config.h>
12 #ifdef HAVE_ALLOCA_H
13 #include <alloca.h>
14 #endif
15 #include "mono/utils/mono-digest.h"
16 #include "mono/utils/mono-membar.h"
17 #include "mono/metadata/reflection.h"
18 #include "mono/metadata/tabledefs.h"
19 #include "mono/metadata/metadata-internals.h"
20 #include <mono/metadata/profiler-private.h>
21 #include "mono/metadata/class-internals.h"
22 #include "mono/metadata/gc-internal.h"
23 #include "mono/metadata/tokentype.h"
24 #include "mono/metadata/domain-internals.h"
25 #include "mono/metadata/opcodes.h"
26 #include "mono/metadata/assembly.h"
27 #include "mono/metadata/object-internals.h"
28 #include <mono/metadata/exception.h>
29 #include <mono/metadata/marshal.h>
30 #include <mono/metadata/security-manager.h>
31 #include <stdio.h>
32 #include <glib.h>
33 #include <errno.h>
34 #include <time.h>
35 #include <string.h>
36 #include <ctype.h>
37 #include "image.h"
38 #include "cil-coff.h"
39 #include "mono-endian.h"
40 #include <mono/metadata/gc-internal.h>
41 #include <mono/metadata/mempool-internals.h>
42
43 #if HAVE_SGEN_GC
44 static void* reflection_info_desc = NULL;
45 #define MOVING_GC_REGISTER(addr) do {   \
46                 if (!reflection_info_desc) {    \
47                         gsize bmap = 1;         \
48                         reflection_info_desc = mono_gc_make_descr_from_bitmap (&bmap, 1);       \
49                 }       \
50                 mono_gc_register_root ((char*)(addr), sizeof (gpointer), reflection_info_desc); \
51         } while (0)
52 #else
53 #define MOVING_GC_REGISTER(addr)
54 #endif
55
56 typedef struct {
57         char *p;
58         char *buf;
59         char *end;
60 } SigBuffer;
61
62 #define TEXT_OFFSET 512
63 #define CLI_H_SIZE 136
64 #define FILE_ALIGN 512
65 #define VIRT_ALIGN 8192
66 #define START_TEXT_RVA  0x00002000
67
68 typedef struct {
69         MonoReflectionILGen *ilgen;
70         MonoReflectionType *rtype;
71         MonoArray *parameters;
72         MonoArray *generic_params;
73         MonoGenericContainer *generic_container;
74         MonoArray *pinfo;
75         MonoArray *opt_types;
76         guint32 attrs;
77         guint32 iattrs;
78         guint32 call_conv;
79         guint32 *table_idx; /* note: it's a pointer */
80         MonoArray *code;
81         MonoObject *type;
82         MonoString *name;
83         MonoBoolean init_locals;
84         MonoBoolean skip_visibility;
85         MonoArray *return_modreq;
86         MonoArray *return_modopt;
87         MonoArray *param_modreq;
88         MonoArray *param_modopt;
89         MonoArray *permissions;
90         MonoMethod *mhandle;
91         guint32 nrefs;
92         gpointer *refs;
93         /* for PInvoke */
94         int charset, extra_flags, native_cc;
95         MonoString *dll, *dllentry;
96 } ReflectionMethodBuilder;
97
98 typedef struct {
99         guint32 owner;
100         MonoReflectionGenericParam *gparam;
101 } GenericParamTableEntry;
102
103 const unsigned char table_sizes [MONO_TABLE_NUM] = {
104         MONO_MODULE_SIZE,
105         MONO_TYPEREF_SIZE,
106         MONO_TYPEDEF_SIZE,
107         0,
108         MONO_FIELD_SIZE,
109         0,
110         MONO_METHOD_SIZE,
111         0,
112         MONO_PARAM_SIZE,
113         MONO_INTERFACEIMPL_SIZE,
114         MONO_MEMBERREF_SIZE,    /* 0x0A */
115         MONO_CONSTANT_SIZE,
116         MONO_CUSTOM_ATTR_SIZE,
117         MONO_FIELD_MARSHAL_SIZE,
118         MONO_DECL_SECURITY_SIZE,
119         MONO_CLASS_LAYOUT_SIZE,
120         MONO_FIELD_LAYOUT_SIZE, /* 0x10 */
121         MONO_STAND_ALONE_SIGNATURE_SIZE,
122         MONO_EVENT_MAP_SIZE,
123         0,
124         MONO_EVENT_SIZE,
125         MONO_PROPERTY_MAP_SIZE,
126         0,
127         MONO_PROPERTY_SIZE,
128         MONO_METHOD_SEMA_SIZE,
129         MONO_METHODIMPL_SIZE,
130         MONO_MODULEREF_SIZE,    /* 0x1A */
131         MONO_TYPESPEC_SIZE,
132         MONO_IMPLMAP_SIZE,      
133         MONO_FIELD_RVA_SIZE,
134         0,
135         0,
136         MONO_ASSEMBLY_SIZE,     /* 0x20 */
137         MONO_ASSEMBLY_PROCESSOR_SIZE,
138         MONO_ASSEMBLYOS_SIZE,
139         MONO_ASSEMBLYREF_SIZE,
140         MONO_ASSEMBLYREFPROC_SIZE,
141         MONO_ASSEMBLYREFOS_SIZE,
142         MONO_FILE_SIZE,
143         MONO_EXP_TYPE_SIZE,
144         MONO_MANIFEST_SIZE,
145         MONO_NESTED_CLASS_SIZE,
146
147         MONO_GENERICPARAM_SIZE, /* 0x2A */
148         MONO_METHODSPEC_SIZE,
149         MONO_GENPARCONSTRAINT_SIZE
150
151 };
152
153 static void reflection_methodbuilder_from_method_builder (ReflectionMethodBuilder *rmb, MonoReflectionMethodBuilder *mb);
154 static void reflection_methodbuilder_from_ctor_builder (ReflectionMethodBuilder *rmb, MonoReflectionCtorBuilder *mb);
155 static guint32 mono_image_typedef_or_ref (MonoDynamicImage *assembly, MonoType *type);
156 static guint32 mono_image_typedef_or_ref_full (MonoDynamicImage *assembly, MonoType *type, gboolean try_typespec);
157 static guint32 mono_image_get_methodref_token (MonoDynamicImage *assembly, MonoMethod *method, gboolean create_typespec);
158 static guint32 mono_image_get_methodbuilder_token (MonoDynamicImage *assembly, MonoReflectionMethodBuilder *mb, gboolean create_methodspec);
159 static guint32 mono_image_get_ctorbuilder_token (MonoDynamicImage *assembly, MonoReflectionCtorBuilder *cb);
160 static guint32 mono_image_get_sighelper_token (MonoDynamicImage *assembly, MonoReflectionSigHelper *helper);
161 static void    mono_image_get_generic_param_info (MonoReflectionGenericParam *gparam, guint32 owner, MonoDynamicImage *assembly);
162 static guint32 encode_marshal_blob (MonoDynamicImage *assembly, MonoReflectionMarshal *minfo);
163 static guint32 encode_constant (MonoDynamicImage *assembly, MonoObject *val, guint32 *ret_type);
164 static char*   type_get_qualified_name (MonoType *type, MonoAssembly *ass);
165 static void    ensure_runtime_vtable (MonoClass *klass);
166 static gpointer resolve_object (MonoImage *image, MonoObject *obj, MonoClass **handle_class, MonoGenericContext *context);
167 static void    encode_type (MonoDynamicImage *assembly, MonoType *type, SigBuffer *buf);
168 static void get_default_param_value_blobs (MonoMethod *method, char **blobs, guint32 *types);
169 static MonoObject *mono_get_object_from_blob (MonoDomain *domain, MonoType *type, const char *blob);
170 static MonoReflectionType *mono_reflection_type_get_underlying_system_type (MonoReflectionType* t);
171 static MonoType* mono_reflection_get_type_with_rootimage (MonoImage *rootimage, MonoImage* image, MonoTypeNameParse *info, gboolean ignorecase, gboolean *type_resolve);
172 static guint32 mono_image_get_methodref_token_for_methodbuilder (MonoDynamicImage *assembly, MonoReflectionMethodBuilder *method);
173 static guint32 encode_generic_method_sig (MonoDynamicImage *assembly, MonoGenericContext *context);
174
175 #define mono_reflection_lock() EnterCriticalSection (&reflection_mutex)
176 #define mono_reflection_unlock() LeaveCriticalSection (&reflection_mutex)
177 static CRITICAL_SECTION reflection_mutex;
178
179 void
180 mono_reflection_init (void)
181 {
182         InitializeCriticalSection (&reflection_mutex);
183 }
184
185 static void
186 sigbuffer_init (SigBuffer *buf, int size)
187 {
188         buf->buf = g_malloc (size);
189         buf->p = buf->buf;
190         buf->end = buf->buf + size;
191 }
192
193 static void
194 sigbuffer_make_room (SigBuffer *buf, int size)
195 {
196         if (buf->end - buf->p < size) {
197                 int new_size = buf->end - buf->buf + size + 32;
198                 char *p = g_realloc (buf->buf, new_size);
199                 size = buf->p - buf->buf;
200                 buf->buf = p;
201                 buf->p = p + size;
202                 buf->end = buf->buf + new_size;
203         }
204 }
205
206 static void
207 sigbuffer_add_value (SigBuffer *buf, guint32 val)
208 {
209         sigbuffer_make_room (buf, 6);
210         mono_metadata_encode_value (val, buf->p, &buf->p);
211 }
212
213 static void
214 sigbuffer_add_byte (SigBuffer *buf, guint8 val)
215 {
216         sigbuffer_make_room (buf, 1);
217         buf->p [0] = val;
218         buf->p++;
219 }
220
221 static void
222 sigbuffer_add_mem (SigBuffer *buf, char *p, guint32 size)
223 {
224         sigbuffer_make_room (buf, size);
225         memcpy (buf->p, p, size);
226         buf->p += size;
227 }
228
229 static void
230 sigbuffer_free (SigBuffer *buf)
231 {
232         g_free (buf->buf);
233 }
234
235 /**
236  * mp_g_alloc:
237  *
238  * Allocate memory from the @image mempool if it is non-NULL. Otherwise, allocate memory
239  * from the C heap.
240  */
241 static gpointer
242 image_g_malloc (MonoImage *image, guint size)
243 {
244         if (image)
245                 return mono_image_alloc (image, size);
246         else
247                 return g_malloc (size);
248 }
249
250 /**
251  * image_g_alloc0:
252  *
253  * Allocate memory from the @image mempool if it is non-NULL. Otherwise, allocate memory
254  * from the C heap.
255  */
256 static gpointer
257 image_g_malloc0 (MonoImage *image, guint size)
258 {
259         if (image)
260                 return mono_image_alloc0 (image, size);
261         else
262                 return g_malloc0 (size);
263 }
264
265 static char*
266 image_strdup (MonoImage *image, const char *s)
267 {
268         if (image)
269                 return mono_image_strdup (image, s);
270         else
271                 return g_strdup (s);
272 }
273
274 #define image_g_new(image,struct_type, n_structs)               \
275     ((struct_type *) image_g_malloc (image, ((gsize) sizeof (struct_type)) * ((gsize) (n_structs))))
276
277 #define image_g_new0(image,struct_type, n_structs)              \
278     ((struct_type *) image_g_malloc0 (image, ((gsize) sizeof (struct_type)) * ((gsize) (n_structs))))
279
280
281 static void
282 alloc_table (MonoDynamicTable *table, guint nrows)
283 {
284         table->rows = nrows;
285         g_assert (table->columns);
286         if (nrows + 1 >= table->alloc_rows) {
287                 while (nrows + 1 >= table->alloc_rows) {
288                         if (table->alloc_rows == 0)
289                                 table->alloc_rows = 16;
290                         else
291                                 table->alloc_rows *= 2;
292                 }
293
294                 table->values = g_renew (guint32, table->values, (table->alloc_rows) * table->columns);
295         }
296 }
297
298 static void
299 make_room_in_stream (MonoDynamicStream *stream, int size)
300 {
301         if (size <= stream->alloc_size)
302                 return;
303         
304         while (stream->alloc_size <= size) {
305                 if (stream->alloc_size < 4096)
306                         stream->alloc_size = 4096;
307                 else
308                         stream->alloc_size *= 2;
309         }
310         
311         stream->data = g_realloc (stream->data, stream->alloc_size);
312 }
313
314 static guint32
315 string_heap_insert (MonoDynamicStream *sh, const char *str)
316 {
317         guint32 idx;
318         guint32 len;
319         gpointer oldkey, oldval;
320
321         if (g_hash_table_lookup_extended (sh->hash, str, &oldkey, &oldval))
322                 return GPOINTER_TO_UINT (oldval);
323
324         len = strlen (str) + 1;
325         idx = sh->index;
326         
327         make_room_in_stream (sh, idx + len);
328
329         /*
330          * We strdup the string even if we already copy them in sh->data
331          * so that the string pointers in the hash remain valid even if
332          * we need to realloc sh->data. We may want to avoid that later.
333          */
334         g_hash_table_insert (sh->hash, g_strdup (str), GUINT_TO_POINTER (idx));
335         memcpy (sh->data + idx, str, len);
336         sh->index += len;
337         return idx;
338 }
339
340 static guint32
341 string_heap_insert_mstring (MonoDynamicStream *sh, MonoString *str)
342 {
343         char *name = mono_string_to_utf8 (str);
344         guint32 idx;
345         idx = string_heap_insert (sh, name);
346         g_free (name);
347         return idx;
348 }
349
350 static void
351 string_heap_init (MonoDynamicStream *sh)
352 {
353         sh->index = 0;
354         sh->alloc_size = 4096;
355         sh->data = g_malloc (4096);
356         sh->hash = g_hash_table_new_full (g_str_hash, g_str_equal, g_free, NULL);
357         string_heap_insert (sh, "");
358 }
359
360 static guint32
361 mono_image_add_stream_data (MonoDynamicStream *stream, const char *data, guint32 len)
362 {
363         guint32 idx;
364         
365         make_room_in_stream (stream, stream->index + len);
366         memcpy (stream->data + stream->index, data, len);
367         idx = stream->index;
368         stream->index += len;
369         /* 
370          * align index? Not without adding an additional param that controls it since
371          * we may store a blob value in pieces.
372          */
373         return idx;
374 }
375
376 static guint32
377 mono_image_add_stream_zero (MonoDynamicStream *stream, guint32 len)
378 {
379         guint32 idx;
380         
381         make_room_in_stream (stream, stream->index + len);
382         memset (stream->data + stream->index, 0, len);
383         idx = stream->index;
384         stream->index += len;
385         return idx;
386 }
387
388 static void
389 stream_data_align (MonoDynamicStream *stream)
390 {
391         char buf [4] = {0};
392         guint32 count = stream->index % 4;
393
394         /* we assume the stream data will be aligned */
395         if (count)
396                 mono_image_add_stream_data (stream, buf, 4 - count);
397 }
398
399 static int
400 mono_blob_entry_hash (const char* str)
401 {
402         guint len, h;
403         const char *end;
404         len = mono_metadata_decode_blob_size (str, &str);
405         if (len > 0) {
406                 end = str + len;
407                 h = *str;
408                 for (str += 1; str < end; str++)
409                         h = (h << 5) - h + *str;
410                 return h;
411         } else {
412                 return 0;
413         }
414 }
415
416 static gboolean
417 mono_blob_entry_equal (const char *str1, const char *str2) {
418         int len, len2;
419         const char *end1;
420         const char *end2;
421         len = mono_metadata_decode_blob_size (str1, &end1);
422         len2 = mono_metadata_decode_blob_size (str2, &end2);
423         if (len != len2)
424                 return 0;
425         return memcmp (end1, end2, len) == 0;
426 }
427
428 static guint32
429 add_to_blob_cached (MonoDynamicImage *assembly, char *b1, int s1, char *b2, int s2)
430 {
431         guint32 idx;
432         char *copy;
433         gpointer oldkey, oldval;
434
435         copy = g_malloc (s1+s2);
436         memcpy (copy, b1, s1);
437         memcpy (copy + s1, b2, s2);
438         if (g_hash_table_lookup_extended (assembly->blob_cache, copy, &oldkey, &oldval)) {
439                 g_free (copy);
440                 idx = GPOINTER_TO_UINT (oldval);
441         } else {
442                 idx = mono_image_add_stream_data (&assembly->blob, b1, s1);
443                 mono_image_add_stream_data (&assembly->blob, b2, s2);
444                 g_hash_table_insert (assembly->blob_cache, copy, GUINT_TO_POINTER (idx));
445         }
446         return idx;
447 }
448
449 static guint32
450 sigbuffer_add_to_blob_cached (MonoDynamicImage *assembly, SigBuffer *buf)
451 {
452         char blob_size [8];
453         char *b = blob_size;
454         guint32 size = buf->p - buf->buf;
455         /* store length */
456         g_assert (size <= (buf->end - buf->buf));
457         mono_metadata_encode_value (size, b, &b);
458         return add_to_blob_cached (assembly, blob_size, b-blob_size, buf->buf, size);
459 }
460
461 /*
462  * Copy len * nelem bytes from val to dest, swapping bytes to LE if necessary.
463  * dest may be misaligned.
464  */
465 static void
466 swap_with_size (char *dest, const char* val, int len, int nelem) {
467 #if G_BYTE_ORDER != G_LITTLE_ENDIAN
468         int elem;
469
470         for (elem = 0; elem < nelem; ++elem) {
471                 switch (len) {
472                 case 1:
473                         *dest = *val;
474                         break;
475                 case 2:
476                         dest [0] = val [1];
477                         dest [1] = val [0];
478                         break;
479                 case 4:
480                         dest [0] = val [3];
481                         dest [1] = val [2];
482                         dest [2] = val [1];
483                         dest [3] = val [0];
484                         break;
485                 case 8:
486                         dest [0] = val [7];
487                         dest [1] = val [6];
488                         dest [2] = val [5];
489                         dest [3] = val [4];
490                         dest [4] = val [3];
491                         dest [5] = val [2];
492                         dest [6] = val [1];
493                         dest [7] = val [0];
494                         break;
495                 default:
496                         g_assert_not_reached ();
497                 }
498                 dest += len;
499                 val += len;
500         }
501 #else
502         memcpy (dest, val, len * nelem);
503 #endif
504 }
505
506 static guint32
507 add_mono_string_to_blob_cached (MonoDynamicImage *assembly, MonoString *str)
508 {
509         char blob_size [64];
510         char *b = blob_size;
511         guint32 idx = 0, len;
512
513         len = str->length * 2;
514         mono_metadata_encode_value (len, b, &b);
515 #if G_BYTE_ORDER != G_LITTLE_ENDIAN
516         {
517                 char *swapped = g_malloc (2 * mono_string_length (str));
518                 const char *p = (const char*)mono_string_chars (str);
519
520                 swap_with_size (swapped, p, 2, mono_string_length (str));
521                 idx = add_to_blob_cached (assembly, blob_size, b-blob_size, swapped, len);
522                 g_free (swapped);
523         }
524 #else
525         idx = add_to_blob_cached (assembly, blob_size, b-blob_size, (char*)mono_string_chars (str), len);
526 #endif
527         return idx;
528 }
529
530 /* modified version needed to handle building corlib */
531 static MonoClass*
532 my_mono_class_from_mono_type (MonoType *type) {
533         switch (type->type) {
534         case MONO_TYPE_ARRAY:
535         case MONO_TYPE_PTR:
536         case MONO_TYPE_SZARRAY:
537         case MONO_TYPE_GENERICINST:
538                 return mono_class_from_mono_type (type);
539         case MONO_TYPE_VAR:
540         case MONO_TYPE_MVAR:
541                 g_assert (type->data.generic_param->pklass);
542                 return type->data.generic_param->pklass;
543         default:
544                 /* should be always valid when we reach this case... */
545                 return type->data.klass;
546         }
547 }
548
549 static MonoClass *
550 default_class_from_mono_type (MonoType *type)
551 {
552         switch (type->type) {
553         case MONO_TYPE_OBJECT:
554                 return mono_defaults.object_class;
555         case MONO_TYPE_VOID:
556                 return mono_defaults.void_class;
557         case MONO_TYPE_BOOLEAN:
558                 return mono_defaults.boolean_class;
559         case MONO_TYPE_CHAR:
560                 return mono_defaults.char_class;
561         case MONO_TYPE_I1:
562                 return mono_defaults.sbyte_class;
563         case MONO_TYPE_U1:
564                 return mono_defaults.byte_class;
565         case MONO_TYPE_I2:
566                 return mono_defaults.int16_class;
567         case MONO_TYPE_U2:
568                 return mono_defaults.uint16_class;
569         case MONO_TYPE_I4:
570                 return mono_defaults.int32_class;
571         case MONO_TYPE_U4:
572                 return mono_defaults.uint32_class;
573         case MONO_TYPE_I:
574                 return mono_defaults.int_class;
575         case MONO_TYPE_U:
576                 return mono_defaults.uint_class;
577         case MONO_TYPE_I8:
578                 return mono_defaults.int64_class;
579         case MONO_TYPE_U8:
580                 return mono_defaults.uint64_class;
581         case MONO_TYPE_R4:
582                 return mono_defaults.single_class;
583         case MONO_TYPE_R8:
584                 return mono_defaults.double_class;
585         case MONO_TYPE_STRING:
586                 return mono_defaults.string_class;
587         default:
588                 g_warning ("default_class_from_mono_type: implement me 0x%02x\n", type->type);
589                 g_assert_not_reached ();
590         }
591         
592         return NULL;
593 }
594
595 static void
596 encode_generic_class (MonoDynamicImage *assembly, MonoGenericClass *gclass, SigBuffer *buf)
597 {
598         int i;
599         MonoGenericInst *class_inst;
600         MonoClass *klass;
601
602         g_assert (gclass);
603
604         class_inst = gclass->context.class_inst;
605
606         sigbuffer_add_value (buf, MONO_TYPE_GENERICINST);
607         klass = gclass->container_class;
608         sigbuffer_add_value (buf, klass->byval_arg.type);
609         sigbuffer_add_value (buf, mono_image_typedef_or_ref_full (assembly, &klass->byval_arg, FALSE));
610
611         sigbuffer_add_value (buf, class_inst->type_argc);
612         for (i = 0; i < class_inst->type_argc; ++i)
613                 encode_type (assembly, class_inst->type_argv [i], buf);
614
615 }
616
617 static void
618 encode_type (MonoDynamicImage *assembly, MonoType *type, SigBuffer *buf)
619 {
620         if (!type) {
621                 g_assert_not_reached ();
622                 return;
623         }
624                 
625         if (type->byref)
626                 sigbuffer_add_value (buf, MONO_TYPE_BYREF);
627
628         switch (type->type){
629         case MONO_TYPE_VOID:
630         case MONO_TYPE_BOOLEAN:
631         case MONO_TYPE_CHAR:
632         case MONO_TYPE_I1:
633         case MONO_TYPE_U1:
634         case MONO_TYPE_I2:
635         case MONO_TYPE_U2:
636         case MONO_TYPE_I4:
637         case MONO_TYPE_U4:
638         case MONO_TYPE_I8:
639         case MONO_TYPE_U8:
640         case MONO_TYPE_R4:
641         case MONO_TYPE_R8:
642         case MONO_TYPE_I:
643         case MONO_TYPE_U:
644         case MONO_TYPE_STRING:
645         case MONO_TYPE_OBJECT:
646         case MONO_TYPE_TYPEDBYREF:
647                 sigbuffer_add_value (buf, type->type);
648                 break;
649         case MONO_TYPE_PTR:
650                 sigbuffer_add_value (buf, type->type);
651                 encode_type (assembly, type->data.type, buf);
652                 break;
653         case MONO_TYPE_SZARRAY:
654                 sigbuffer_add_value (buf, type->type);
655                 encode_type (assembly, &type->data.klass->byval_arg, buf);
656                 break;
657         case MONO_TYPE_VALUETYPE:
658         case MONO_TYPE_CLASS: {
659                 MonoClass *k = mono_class_from_mono_type (type);
660
661                 if (k->generic_container) {
662                         MonoGenericClass *gclass = mono_metadata_lookup_generic_class (k, k->generic_container->context.class_inst, TRUE);
663                         encode_generic_class (assembly, gclass, buf);
664                 } else {
665                         /*
666                          * Make sure we use the correct type.
667                          */
668                         sigbuffer_add_value (buf, k->byval_arg.type);
669                         /*
670                          * ensure only non-byref gets passed to mono_image_typedef_or_ref(),
671                          * otherwise two typerefs could point to the same type, leading to
672                          * verification errors.
673                          */
674                         sigbuffer_add_value (buf, mono_image_typedef_or_ref (assembly, &k->byval_arg));
675                 }
676                 break;
677         }
678         case MONO_TYPE_ARRAY:
679                 sigbuffer_add_value (buf, type->type);
680                 encode_type (assembly, &type->data.array->eklass->byval_arg, buf);
681                 sigbuffer_add_value (buf, type->data.array->rank);
682                 sigbuffer_add_value (buf, 0); /* FIXME: set to 0 for now */
683                 sigbuffer_add_value (buf, 0);
684                 break;
685         case MONO_TYPE_GENERICINST:
686                 encode_generic_class (assembly, type->data.generic_class, buf);
687                 break;
688         case MONO_TYPE_VAR:
689         case MONO_TYPE_MVAR:
690                 sigbuffer_add_value (buf, type->type);
691                 sigbuffer_add_value (buf, type->data.generic_param->num);
692                 break;
693         default:
694                 g_error ("need to encode type %x", type->type);
695         }
696 }
697
698 static void
699 encode_reflection_type (MonoDynamicImage *assembly, MonoReflectionType *type, SigBuffer *buf)
700 {
701         if (!type) {
702                 sigbuffer_add_value (buf, MONO_TYPE_VOID);
703                 return;
704         }
705
706         if (type->type ||
707             ((type = mono_reflection_type_get_underlying_system_type (type)) && type->type)) {
708                 encode_type (assembly, type->type, buf);
709                 return;
710         }
711
712         g_assert_not_reached ();
713
714 }
715
716 static void
717 encode_custom_modifiers (MonoDynamicImage *assembly, MonoArray *modreq, MonoArray *modopt, SigBuffer *buf)
718 {
719         int i;
720
721         if (modreq) {
722                 for (i = 0; i < mono_array_length (modreq); ++i) {
723                         MonoReflectionType *mod = mono_array_get (modreq, MonoReflectionType*, i);
724                         sigbuffer_add_byte (buf, MONO_TYPE_CMOD_REQD);
725                         sigbuffer_add_value (buf, mono_image_typedef_or_ref (assembly, mod->type));
726                 }
727         }
728         if (modopt) {
729                 for (i = 0; i < mono_array_length (modopt); ++i) {
730                         MonoReflectionType *mod = mono_array_get (modopt, MonoReflectionType*, i);
731                         sigbuffer_add_byte (buf, MONO_TYPE_CMOD_OPT);
732                         sigbuffer_add_value (buf, mono_image_typedef_or_ref (assembly, mod->type));
733                 }
734         }
735 }
736
737 static guint32
738 method_encode_signature (MonoDynamicImage *assembly, MonoMethodSignature *sig)
739 {
740         SigBuffer buf;
741         int i;
742         guint32 nparams =  sig->param_count;
743         guint32 idx;
744
745         if (!assembly->save)
746                 return 0;
747
748         sigbuffer_init (&buf, 32);
749         /*
750          * FIXME: vararg, explicit_this, differenc call_conv values...
751          */
752         idx = sig->call_convention;
753         if (sig->hasthis)
754                 idx |= 0x20; /* hasthis */
755         if (sig->generic_param_count)
756                 idx |= 0x10; /* generic */
757         sigbuffer_add_byte (&buf, idx);
758         if (sig->generic_param_count)
759                 sigbuffer_add_value (&buf, sig->generic_param_count);
760         sigbuffer_add_value (&buf, nparams);
761         encode_type (assembly, sig->ret, &buf);
762         for (i = 0; i < nparams; ++i) {
763                 if (i == sig->sentinelpos)
764                         sigbuffer_add_byte (&buf, MONO_TYPE_SENTINEL);
765                 encode_type (assembly, sig->params [i], &buf);
766         }
767         idx = sigbuffer_add_to_blob_cached (assembly, &buf);
768         sigbuffer_free (&buf);
769         return idx;
770 }
771
772 static guint32
773 method_builder_encode_signature (MonoDynamicImage *assembly, ReflectionMethodBuilder *mb)
774 {
775         /*
776          * FIXME: reuse code from method_encode_signature().
777          */
778         SigBuffer buf;
779         int i;
780         guint32 nparams =  mb->parameters ? mono_array_length (mb->parameters): 0;
781         guint32 ngparams = mb->generic_params ? mono_array_length (mb->generic_params): 0;
782         guint32 notypes = mb->opt_types ? mono_array_length (mb->opt_types): 0;
783         guint32 idx;
784
785         sigbuffer_init (&buf, 32);
786         /* LAMESPEC: all the call conv spec is foobared */
787         idx = mb->call_conv & 0x60; /* has-this, explicit-this */
788         if (mb->call_conv & 2)
789                 idx |= 0x5; /* vararg */
790         if (!(mb->attrs & METHOD_ATTRIBUTE_STATIC))
791                 idx |= 0x20; /* hasthis */
792         if (ngparams)
793                 idx |= 0x10; /* generic */
794         sigbuffer_add_byte (&buf, idx);
795         if (ngparams)
796                 sigbuffer_add_value (&buf, ngparams);
797         sigbuffer_add_value (&buf, nparams + notypes);
798         encode_custom_modifiers (assembly, mb->return_modreq, mb->return_modopt, &buf);
799         encode_reflection_type (assembly, mb->rtype, &buf);
800         for (i = 0; i < nparams; ++i) {
801                 MonoArray *modreq = NULL;
802                 MonoArray *modopt = NULL;
803                 MonoReflectionType *pt;
804
805                 if (mb->param_modreq && (i < mono_array_length (mb->param_modreq)))
806                         modreq = mono_array_get (mb->param_modreq, MonoArray*, i);
807                 if (mb->param_modopt && (i < mono_array_length (mb->param_modopt)))
808                         modopt = mono_array_get (mb->param_modopt, MonoArray*, i);
809                 encode_custom_modifiers (assembly, modreq, modopt, &buf);
810                 pt = mono_array_get (mb->parameters, MonoReflectionType*, i);
811                 encode_reflection_type (assembly, pt, &buf);
812         }
813         if (notypes)
814                 sigbuffer_add_byte (&buf, MONO_TYPE_SENTINEL);
815         for (i = 0; i < notypes; ++i) {
816                 MonoReflectionType *pt;
817
818                 pt = mono_array_get (mb->opt_types, MonoReflectionType*, i);
819                 encode_reflection_type (assembly, pt, &buf);
820         }
821
822         idx = sigbuffer_add_to_blob_cached (assembly, &buf);
823         sigbuffer_free (&buf);
824         return idx;
825 }
826
827 static guint32
828 encode_locals (MonoDynamicImage *assembly, MonoReflectionILGen *ilgen)
829 {
830         MonoDynamicTable *table;
831         guint32 *values;
832         guint32 idx, sig_idx;
833         guint nl = mono_array_length (ilgen->locals);
834         SigBuffer buf;
835         int i;
836
837         sigbuffer_init (&buf, 32);
838         sigbuffer_add_value (&buf, 0x07);
839         sigbuffer_add_value (&buf, nl);
840         for (i = 0; i < nl; ++i) {
841                 MonoReflectionLocalBuilder *lb = mono_array_get (ilgen->locals, MonoReflectionLocalBuilder*, i);
842                 
843                 if (lb->is_pinned)
844                         sigbuffer_add_value (&buf, MONO_TYPE_PINNED);
845                 
846                 encode_reflection_type (assembly, lb->type, &buf);
847         }
848         sig_idx = sigbuffer_add_to_blob_cached (assembly, &buf);
849         sigbuffer_free (&buf);
850
851         if (assembly->standalonesig_cache == NULL)
852                 assembly->standalonesig_cache = g_hash_table_new (NULL, NULL);
853         idx = GPOINTER_TO_UINT (g_hash_table_lookup (assembly->standalonesig_cache, GUINT_TO_POINTER (sig_idx)));
854         if (idx)
855                 return idx;
856
857         table = &assembly->tables [MONO_TABLE_STANDALONESIG];
858         idx = table->next_idx ++;
859         table->rows ++;
860         alloc_table (table, table->rows);
861         values = table->values + idx * MONO_STAND_ALONE_SIGNATURE_SIZE;
862
863         values [MONO_STAND_ALONE_SIGNATURE] = sig_idx;
864
865         g_hash_table_insert (assembly->standalonesig_cache, GUINT_TO_POINTER (sig_idx), GUINT_TO_POINTER (idx));
866
867         return idx;
868 }
869
870 static guint32
871 method_count_clauses (MonoReflectionILGen *ilgen)
872 {
873         guint32 num_clauses = 0;
874         int i;
875
876         MonoILExceptionInfo *ex_info;
877         for (i = 0; i < mono_array_length (ilgen->ex_handlers); ++i) {
878                 ex_info = (MonoILExceptionInfo*)mono_array_addr (ilgen->ex_handlers, MonoILExceptionInfo, i);
879                 if (ex_info->handlers)
880                         num_clauses += mono_array_length (ex_info->handlers);
881                 else
882                         num_clauses++;
883         }
884
885         return num_clauses;
886 }
887
888 static MonoExceptionClause*
889 method_encode_clauses (MonoImage *image, MonoDynamicImage *assembly, MonoReflectionILGen *ilgen, guint32 num_clauses)
890 {
891         MonoExceptionClause *clauses;
892         MonoExceptionClause *clause;
893         MonoILExceptionInfo *ex_info;
894         MonoILExceptionBlock *ex_block;
895         guint32 finally_start;
896         int i, j, clause_index;;
897
898         clauses = image_g_new0 (image, MonoExceptionClause, num_clauses);
899
900         clause_index = 0;
901         for (i = mono_array_length (ilgen->ex_handlers) - 1; i >= 0; --i) {
902                 ex_info = (MonoILExceptionInfo*)mono_array_addr (ilgen->ex_handlers, MonoILExceptionInfo, i);
903                 finally_start = ex_info->start + ex_info->len;
904                 if (!ex_info->handlers)
905                         continue;
906                 for (j = 0; j < mono_array_length (ex_info->handlers); ++j) {
907                         ex_block = (MonoILExceptionBlock*)mono_array_addr (ex_info->handlers, MonoILExceptionBlock, j);
908                         clause = &(clauses [clause_index]);
909
910                         clause->flags = ex_block->type;
911                         clause->try_offset = ex_info->start;
912
913                         if (ex_block->type == MONO_EXCEPTION_CLAUSE_FINALLY)
914                                 clause->try_len = finally_start - ex_info->start;
915                         else
916                                 clause->try_len = ex_info->len;
917                         clause->handler_offset = ex_block->start;
918                         clause->handler_len = ex_block->len;
919                         if (ex_block->extype) {
920                                 clause->data.catch_class = mono_class_from_mono_type (ex_block->extype->type);
921                         } else {
922                                 if (ex_block->type == MONO_EXCEPTION_CLAUSE_FILTER)
923                                         clause->data.filter_offset = ex_block->filter_offset;
924                                 else
925                                         clause->data.filter_offset = 0;
926                         }
927                         finally_start = ex_block->start + ex_block->len;
928
929                         clause_index ++;
930                 }
931         }
932
933         return clauses;
934 }
935
936 static guint32
937 method_encode_code (MonoDynamicImage *assembly, ReflectionMethodBuilder *mb)
938 {
939         char flags = 0;
940         guint32 idx;
941         guint32 code_size;
942         gint32 max_stack, i;
943         gint32 num_locals = 0;
944         gint32 num_exception = 0;
945         gint maybe_small;
946         guint32 fat_flags;
947         char fat_header [12];
948         guint32 int_value;
949         guint16 short_value;
950         guint32 local_sig = 0;
951         guint32 header_size = 12;
952         MonoArray *code;
953
954         if ((mb->attrs & (METHOD_ATTRIBUTE_PINVOKE_IMPL | METHOD_ATTRIBUTE_ABSTRACT)) ||
955                         (mb->iattrs & (METHOD_IMPL_ATTRIBUTE_INTERNAL_CALL | METHOD_IMPL_ATTRIBUTE_RUNTIME)))
956                 return 0;
957
958         /*if (mb->name)
959                 g_print ("Encode method %s\n", mono_string_to_utf8 (mb->name));*/
960         if (mb->ilgen) {
961                 code = mb->ilgen->code;
962                 code_size = mb->ilgen->code_len;
963                 max_stack = mb->ilgen->max_stack;
964                 num_locals = mb->ilgen->locals ? mono_array_length (mb->ilgen->locals) : 0;
965                 if (mb->ilgen->ex_handlers)
966                         num_exception = method_count_clauses (mb->ilgen);
967         } else {
968                 code = mb->code;
969                 if (code == NULL){
970                         char *name = mono_string_to_utf8 (mb->name);
971                         char *str = g_strdup_printf ("Method %s does not have any IL associated", name);
972                         MonoException *exception = mono_get_exception_argument (NULL, "a method does not have any IL associated");
973                         g_free (str);
974                         g_free (name);
975                         mono_raise_exception (exception);
976                 }
977
978                 code_size = mono_array_length (code);
979                 max_stack = 8; /* we probably need to run a verifier on the code... */
980         }
981
982         stream_data_align (&assembly->code);
983
984         /* check for exceptions, maxstack, locals */
985         maybe_small = (max_stack <= 8) && (!num_locals) && (!num_exception);
986         if (maybe_small) {
987                 if (code_size < 64 && !(code_size & 1)) {
988                         flags = (code_size << 2) | 0x2;
989                 } else if (code_size < 32 && (code_size & 1)) {
990                         flags = (code_size << 2) | 0x6; /* LAMESPEC: see metadata.c */
991                 } else {
992                         goto fat_header;
993                 }
994                 idx = mono_image_add_stream_data (&assembly->code, &flags, 1);
995                 /* add to the fixup todo list */
996                 if (mb->ilgen && mb->ilgen->num_token_fixups)
997                         mono_g_hash_table_insert (assembly->token_fixups, mb->ilgen, GUINT_TO_POINTER (idx + 1));
998                 mono_image_add_stream_data (&assembly->code, mono_array_addr (code, char, 0), code_size);
999                 return assembly->text_rva + idx;
1000         } 
1001 fat_header:
1002         if (num_locals)
1003                 local_sig = MONO_TOKEN_SIGNATURE | encode_locals (assembly, mb->ilgen);
1004         /* 
1005          * FIXME: need to set also the header size in fat_flags.
1006          * (and more sects and init locals flags)
1007          */
1008         fat_flags =  0x03;
1009         if (num_exception)
1010                 fat_flags |= METHOD_HEADER_MORE_SECTS;
1011         if (mb->init_locals)
1012                 fat_flags |= METHOD_HEADER_INIT_LOCALS;
1013         fat_header [0] = fat_flags;
1014         fat_header [1] = (header_size / 4 ) << 4;
1015         short_value = GUINT16_TO_LE (max_stack);
1016         memcpy (fat_header + 2, &short_value, 2);
1017         int_value = GUINT32_TO_LE (code_size);
1018         memcpy (fat_header + 4, &int_value, 4);
1019         int_value = GUINT32_TO_LE (local_sig);
1020         memcpy (fat_header + 8, &int_value, 4);
1021         idx = mono_image_add_stream_data (&assembly->code, fat_header, 12);
1022         /* add to the fixup todo list */
1023         if (mb->ilgen && mb->ilgen->num_token_fixups)
1024                 mono_g_hash_table_insert (assembly->token_fixups, mb->ilgen, GUINT_TO_POINTER (idx + 12));
1025         
1026         mono_image_add_stream_data (&assembly->code, mono_array_addr (code, char, 0), code_size);
1027         if (num_exception) {
1028                 unsigned char sheader [4];
1029                 MonoILExceptionInfo * ex_info;
1030                 MonoILExceptionBlock * ex_block;
1031                 int j;
1032
1033                 stream_data_align (&assembly->code);
1034                 /* always use fat format for now */
1035                 sheader [0] = METHOD_HEADER_SECTION_FAT_FORMAT | METHOD_HEADER_SECTION_EHTABLE;
1036                 num_exception *= 6 * sizeof (guint32);
1037                 num_exception += 4; /* include the size of the header */
1038                 sheader [1] = num_exception & 0xff;
1039                 sheader [2] = (num_exception >> 8) & 0xff;
1040                 sheader [3] = (num_exception >> 16) & 0xff;
1041                 mono_image_add_stream_data (&assembly->code, (char*)sheader, 4);
1042                 /* fat header, so we are already aligned */
1043                 /* reverse order */
1044                 for (i = mono_array_length (mb->ilgen->ex_handlers) - 1; i >= 0; --i) {
1045                         ex_info = (MonoILExceptionInfo *)mono_array_addr (mb->ilgen->ex_handlers, MonoILExceptionInfo, i);
1046                         if (ex_info->handlers) {
1047                                 int finally_start = ex_info->start + ex_info->len;
1048                                 for (j = 0; j < mono_array_length (ex_info->handlers); ++j) {
1049                                         guint32 val;
1050                                         ex_block = (MonoILExceptionBlock*)mono_array_addr (ex_info->handlers, MonoILExceptionBlock, j);
1051                                         /* the flags */
1052                                         val = GUINT32_TO_LE (ex_block->type);
1053                                         mono_image_add_stream_data (&assembly->code, (char*)&val, sizeof (guint32));
1054                                         /* try offset */
1055                                         val = GUINT32_TO_LE (ex_info->start);
1056                                         mono_image_add_stream_data (&assembly->code, (char*)&val, sizeof (guint32));
1057                                         /* need fault, too, probably */
1058                                         if (ex_block->type == MONO_EXCEPTION_CLAUSE_FINALLY)
1059                                                 val = GUINT32_TO_LE (finally_start - ex_info->start);
1060                                         else
1061                                                 val = GUINT32_TO_LE (ex_info->len);
1062                                         mono_image_add_stream_data (&assembly->code, (char*)&val, sizeof (guint32));
1063                                         /* handler offset */
1064                                         val = GUINT32_TO_LE (ex_block->start);
1065                                         mono_image_add_stream_data (&assembly->code, (char*)&val, sizeof (guint32));
1066                                         /* handler len */
1067                                         val = GUINT32_TO_LE (ex_block->len);
1068                                         mono_image_add_stream_data (&assembly->code, (char*)&val, sizeof (guint32));
1069                                         finally_start = ex_block->start + ex_block->len;
1070                                         if (ex_block->extype) {
1071                                                 val = mono_metadata_token_from_dor (mono_image_typedef_or_ref (assembly, ex_block->extype->type));
1072                                         } else {
1073                                                 if (ex_block->type == MONO_EXCEPTION_CLAUSE_FILTER)
1074                                                         val = ex_block->filter_offset;
1075                                                 else
1076                                                         val = 0;
1077                                         }
1078                                         val = GUINT32_TO_LE (val);
1079                                         mono_image_add_stream_data (&assembly->code, (char*)&val, sizeof (guint32));
1080                                         /*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", 
1081                                                         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);*/
1082                                 }
1083                         } else {
1084                                 g_error ("No clauses for ex info block %d", i);
1085                         }
1086                 }
1087         }
1088         return assembly->text_rva + idx;
1089 }
1090
1091 static guint32
1092 find_index_in_table (MonoDynamicImage *assembly, int table_idx, int col, guint32 token)
1093 {
1094         int i;
1095         MonoDynamicTable *table;
1096         guint32 *values;
1097         
1098         table = &assembly->tables [table_idx];
1099
1100         g_assert (col < table->columns);
1101
1102         values = table->values + table->columns;
1103         for (i = 1; i <= table->rows; ++i) {
1104                 if (values [col] == token)
1105                         return i;
1106                 values += table->columns;
1107         }
1108         return 0;
1109 }
1110
1111 /*
1112  * LOCKING: Acquires the loader lock. 
1113  */
1114 static MonoCustomAttrInfo*
1115 lookup_custom_attr (MonoImage *image, gpointer member)
1116 {
1117         MonoCustomAttrInfo* res;
1118
1119         res = mono_image_property_lookup (image, member, MONO_PROP_DYNAMIC_CATTR);
1120
1121         if (!res)
1122                 return NULL;
1123
1124         return g_memdup (res, sizeof (MonoCustomAttrInfo) + sizeof (MonoCustomAttrEntry) * (res->num_attrs - MONO_ZERO_LEN_ARRAY));
1125 }
1126
1127 static gboolean
1128 custom_attr_visible (MonoImage *image, MonoReflectionCustomAttr *cattr)
1129 {
1130         /* FIXME: Need to do more checks */
1131         if (cattr->ctor->method && (cattr->ctor->method->klass->image != image)) {
1132                 int visibility = cattr->ctor->method->klass->flags & TYPE_ATTRIBUTE_VISIBILITY_MASK;
1133
1134                 if ((visibility != TYPE_ATTRIBUTE_PUBLIC) && (visibility != TYPE_ATTRIBUTE_NESTED_PUBLIC))
1135                         return FALSE;
1136         }
1137
1138         return TRUE;
1139 }
1140
1141 static MonoCustomAttrInfo*
1142 mono_custom_attrs_from_builders (MonoImage *alloc_img, MonoImage *image, MonoArray *cattrs)
1143 {
1144         int i, index, count, not_visible;
1145         MonoCustomAttrInfo *ainfo;
1146         MonoReflectionCustomAttr *cattr;
1147
1148         if (!cattrs)
1149                 return NULL;
1150         /* FIXME: check in assembly the Run flag is set */
1151
1152         count = mono_array_length (cattrs);
1153
1154         /* Skip nonpublic attributes since MS.NET seems to do the same */
1155         /* FIXME: This needs to be done more globally */
1156         not_visible = 0;
1157         for (i = 0; i < count; ++i) {
1158                 cattr = (MonoReflectionCustomAttr*)mono_array_get (cattrs, gpointer, i);
1159                 if (!custom_attr_visible (image, cattr))
1160                         not_visible ++;
1161         }
1162         count -= not_visible;
1163
1164         ainfo = image_g_malloc0 (alloc_img, sizeof (MonoCustomAttrInfo) + sizeof (MonoCustomAttrEntry) * (count - MONO_ZERO_LEN_ARRAY));
1165
1166         ainfo->image = image;
1167         ainfo->num_attrs = count;
1168         ainfo->cached = alloc_img != NULL;
1169         index = 0;
1170         for (i = 0; i < count; ++i) {
1171                 cattr = (MonoReflectionCustomAttr*)mono_array_get (cattrs, gpointer, i);
1172                 if (custom_attr_visible (image, cattr)) {
1173                         unsigned char *saved = mono_image_alloc (image, mono_array_length (cattr->data));
1174                         memcpy (saved, mono_array_addr (cattr->data, char, 0), mono_array_length (cattr->data));
1175                         ainfo->attrs [index].ctor = cattr->ctor->method;
1176                         ainfo->attrs [index].data = saved;
1177                         ainfo->attrs [index].data_size = mono_array_length (cattr->data);
1178                         index ++;
1179                 }
1180         }
1181
1182         return ainfo;
1183 }
1184
1185 /*
1186  * LOCKING: Acquires the loader lock. 
1187  */
1188 static void
1189 mono_save_custom_attrs (MonoImage *image, void *obj, MonoArray *cattrs)
1190 {
1191         MonoCustomAttrInfo *ainfo, *tmp;
1192
1193         if (!cattrs || !mono_array_length (cattrs))
1194                 return;
1195
1196         ainfo = mono_custom_attrs_from_builders (image, image, cattrs);
1197
1198         mono_loader_lock ();
1199         tmp = mono_image_property_lookup (image, obj, MONO_PROP_DYNAMIC_CATTR);
1200         if (tmp)
1201                 mono_custom_attrs_free (tmp);
1202         mono_image_property_insert (image, obj, MONO_PROP_DYNAMIC_CATTR, ainfo);
1203         mono_loader_unlock ();
1204
1205 }
1206
1207 void
1208 mono_custom_attrs_free (MonoCustomAttrInfo *ainfo)
1209 {
1210         if (!ainfo->cached)
1211                 g_free (ainfo);
1212 }
1213
1214 /*
1215  * idx is the table index of the object
1216  * type is one of MONO_CUSTOM_ATTR_*
1217  */
1218 static void
1219 mono_image_add_cattrs (MonoDynamicImage *assembly, guint32 idx, guint32 type, MonoArray *cattrs)
1220 {
1221         MonoDynamicTable *table;
1222         MonoReflectionCustomAttr *cattr;
1223         guint32 *values;
1224         guint32 count, i, token;
1225         char blob_size [6];
1226         char *p = blob_size;
1227         
1228         /* it is legal to pass a NULL cattrs: we avoid to use the if in a lot of places */
1229         if (!cattrs)
1230                 return;
1231         count = mono_array_length (cattrs);
1232         table = &assembly->tables [MONO_TABLE_CUSTOMATTRIBUTE];
1233         table->rows += count;
1234         alloc_table (table, table->rows);
1235         values = table->values + table->next_idx * MONO_CUSTOM_ATTR_SIZE;
1236         idx <<= MONO_CUSTOM_ATTR_BITS;
1237         idx |= type;
1238         for (i = 0; i < count; ++i) {
1239                 cattr = (MonoReflectionCustomAttr*)mono_array_get (cattrs, gpointer, i);
1240                 values [MONO_CUSTOM_ATTR_PARENT] = idx;
1241                 token = mono_image_create_token (assembly, (MonoObject*)cattr->ctor, FALSE, FALSE);
1242                 type = mono_metadata_token_index (token);
1243                 type <<= MONO_CUSTOM_ATTR_TYPE_BITS;
1244                 switch (mono_metadata_token_table (token)) {
1245                 case MONO_TABLE_METHOD:
1246                         type |= MONO_CUSTOM_ATTR_TYPE_METHODDEF;
1247                         break;
1248                 case MONO_TABLE_MEMBERREF:
1249                         type |= MONO_CUSTOM_ATTR_TYPE_MEMBERREF;
1250                         break;
1251                 default:
1252                         g_warning ("got wrong token in custom attr");
1253                         continue;
1254                 }
1255                 values [MONO_CUSTOM_ATTR_TYPE] = type;
1256                 p = blob_size;
1257                 mono_metadata_encode_value (mono_array_length (cattr->data), p, &p);
1258                 values [MONO_CUSTOM_ATTR_VALUE] = add_to_blob_cached (assembly, blob_size, p - blob_size,
1259                         mono_array_addr (cattr->data, char, 0), mono_array_length (cattr->data));
1260                 values += MONO_CUSTOM_ATTR_SIZE;
1261                 ++table->next_idx;
1262         }
1263 }
1264
1265 static void
1266 mono_image_add_decl_security (MonoDynamicImage *assembly, guint32 parent_token, MonoArray *permissions)
1267 {
1268         MonoDynamicTable *table;
1269         guint32 *values;
1270         guint32 count, i, idx;
1271         MonoReflectionPermissionSet *perm;
1272
1273         if (!permissions)
1274                 return;
1275
1276         count = mono_array_length (permissions);
1277         table = &assembly->tables [MONO_TABLE_DECLSECURITY];
1278         table->rows += count;
1279         alloc_table (table, table->rows);
1280
1281         for (i = 0; i < mono_array_length (permissions); ++i) {
1282                 perm = (MonoReflectionPermissionSet*)mono_array_addr (permissions, MonoReflectionPermissionSet, i);
1283
1284                 values = table->values + table->next_idx * MONO_DECL_SECURITY_SIZE;
1285
1286                 idx = mono_metadata_token_index (parent_token);
1287                 idx <<= MONO_HAS_DECL_SECURITY_BITS;
1288                 switch (mono_metadata_token_table (parent_token)) {
1289                 case MONO_TABLE_TYPEDEF:
1290                         idx |= MONO_HAS_DECL_SECURITY_TYPEDEF;
1291                         break;
1292                 case MONO_TABLE_METHOD:
1293                         idx |= MONO_HAS_DECL_SECURITY_METHODDEF;
1294                         break;
1295                 case MONO_TABLE_ASSEMBLY:
1296                         idx |= MONO_HAS_DECL_SECURITY_ASSEMBLY;
1297                         break;
1298                 default:
1299                         g_assert_not_reached ();
1300                 }
1301
1302                 values [MONO_DECL_SECURITY_ACTION] = perm->action;
1303                 values [MONO_DECL_SECURITY_PARENT] = idx;
1304                 values [MONO_DECL_SECURITY_PERMISSIONSET] = add_mono_string_to_blob_cached (assembly, perm->pset);
1305
1306                 ++table->next_idx;
1307         }
1308 }
1309
1310 /*
1311  * Fill in the MethodDef and ParamDef tables for a method.
1312  * This is used for both normal methods and constructors.
1313  */
1314 static void
1315 mono_image_basic_method (ReflectionMethodBuilder *mb, MonoDynamicImage *assembly)
1316 {
1317         MonoDynamicTable *table;
1318         guint32 *values;
1319         guint i, count;
1320
1321         /* room in this table is already allocated */
1322         table = &assembly->tables [MONO_TABLE_METHOD];
1323         *mb->table_idx = table->next_idx ++;
1324         g_hash_table_insert (assembly->method_to_table_idx, mb->mhandle, GUINT_TO_POINTER ((*mb->table_idx)));
1325         values = table->values + *mb->table_idx * MONO_METHOD_SIZE;
1326         values [MONO_METHOD_NAME] = string_heap_insert_mstring (&assembly->sheap, mb->name);
1327         values [MONO_METHOD_FLAGS] = mb->attrs;
1328         values [MONO_METHOD_IMPLFLAGS] = mb->iattrs;
1329         values [MONO_METHOD_SIGNATURE] = method_builder_encode_signature (assembly, mb);
1330         values [MONO_METHOD_RVA] = method_encode_code (assembly, mb);
1331         
1332         table = &assembly->tables [MONO_TABLE_PARAM];
1333         values [MONO_METHOD_PARAMLIST] = table->next_idx;
1334
1335         mono_image_add_decl_security (assembly, 
1336                 mono_metadata_make_token (MONO_TABLE_METHOD, *mb->table_idx), mb->permissions);
1337
1338         if (mb->pinfo) {
1339                 MonoDynamicTable *mtable;
1340                 guint32 *mvalues;
1341                 
1342                 mtable = &assembly->tables [MONO_TABLE_FIELDMARSHAL];
1343                 mvalues = mtable->values + mtable->next_idx * MONO_FIELD_MARSHAL_SIZE;
1344                 
1345                 count = 0;
1346                 for (i = 0; i < mono_array_length (mb->pinfo); ++i) {
1347                         if (mono_array_get (mb->pinfo, gpointer, i))
1348                                 count++;
1349                 }
1350                 table->rows += count;
1351                 alloc_table (table, table->rows);
1352                 values = table->values + table->next_idx * MONO_PARAM_SIZE;
1353                 for (i = 0; i < mono_array_length (mb->pinfo); ++i) {
1354                         MonoReflectionParamBuilder *pb;
1355                         if ((pb = mono_array_get (mb->pinfo, MonoReflectionParamBuilder*, i))) {
1356                                 values [MONO_PARAM_FLAGS] = pb->attrs;
1357                                 values [MONO_PARAM_SEQUENCE] = i;
1358                                 if (pb->name != NULL) {
1359                                         values [MONO_PARAM_NAME] = string_heap_insert_mstring (&assembly->sheap, pb->name);
1360                                 } else {
1361                                         values [MONO_PARAM_NAME] = 0;
1362                                 }
1363                                 values += MONO_PARAM_SIZE;
1364                                 if (pb->marshal_info) {
1365                                         mtable->rows++;
1366                                         alloc_table (mtable, mtable->rows);
1367                                         mvalues = mtable->values + mtable->rows * MONO_FIELD_MARSHAL_SIZE;
1368                                         mvalues [MONO_FIELD_MARSHAL_PARENT] = (table->next_idx << MONO_HAS_FIELD_MARSHAL_BITS) | MONO_HAS_FIELD_MARSHAL_PARAMDEF;
1369                                         mvalues [MONO_FIELD_MARSHAL_NATIVE_TYPE] = encode_marshal_blob (assembly, pb->marshal_info);
1370                                 }
1371                                 pb->table_idx = table->next_idx++;
1372                                 if (pb->attrs & PARAM_ATTRIBUTE_HAS_DEFAULT) {
1373                                         guint32 field_type = 0;
1374                                         mtable = &assembly->tables [MONO_TABLE_CONSTANT];
1375                                         mtable->rows ++;
1376                                         alloc_table (mtable, mtable->rows);
1377                                         mvalues = mtable->values + mtable->rows * MONO_CONSTANT_SIZE;
1378                                         mvalues [MONO_CONSTANT_PARENT] = MONO_HASCONSTANT_PARAM | (pb->table_idx << MONO_HASCONSTANT_BITS);
1379                                         mvalues [MONO_CONSTANT_VALUE] = encode_constant (assembly, pb->def_value, &field_type);
1380                                         mvalues [MONO_CONSTANT_TYPE] = field_type;
1381                                         mvalues [MONO_CONSTANT_PADDING] = 0;
1382                                 }
1383                         }
1384                 }
1385         }
1386 }
1387
1388 static void
1389 reflection_methodbuilder_from_method_builder (ReflectionMethodBuilder *rmb, MonoReflectionMethodBuilder *mb)
1390 {
1391         memset (rmb, 0, sizeof (ReflectionMethodBuilder));
1392
1393         rmb->ilgen = mb->ilgen;
1394         rmb->rtype = mb->rtype;
1395         rmb->parameters = mb->parameters;
1396         rmb->generic_params = mb->generic_params;
1397         rmb->generic_container = mb->generic_container;
1398         rmb->opt_types = NULL;
1399         rmb->pinfo = mb->pinfo;
1400         rmb->attrs = mb->attrs;
1401         rmb->iattrs = mb->iattrs;
1402         rmb->call_conv = mb->call_conv;
1403         rmb->code = mb->code;
1404         rmb->type = mb->type;
1405         rmb->name = mb->name;
1406         rmb->table_idx = &mb->table_idx;
1407         rmb->init_locals = mb->init_locals;
1408         rmb->skip_visibility = FALSE;
1409         rmb->return_modreq = mb->return_modreq;
1410         rmb->return_modopt = mb->return_modopt;
1411         rmb->param_modreq = mb->param_modreq;
1412         rmb->param_modopt = mb->param_modopt;
1413         rmb->permissions = mb->permissions;
1414         rmb->mhandle = mb->mhandle;
1415         rmb->nrefs = 0;
1416         rmb->refs = NULL;
1417
1418         if (mb->dll) {
1419                 rmb->charset = mb->charset;
1420                 rmb->extra_flags = mb->extra_flags;
1421                 rmb->native_cc = mb->native_cc;
1422                 rmb->dllentry = mb->dllentry;
1423                 rmb->dll = mb->dll;
1424         }
1425 }
1426
1427 static void
1428 reflection_methodbuilder_from_ctor_builder (ReflectionMethodBuilder *rmb, MonoReflectionCtorBuilder *mb)
1429 {
1430         const char *name = mb->attrs & METHOD_ATTRIBUTE_STATIC ? ".cctor": ".ctor";
1431
1432         memset (rmb, 0, sizeof (ReflectionMethodBuilder));
1433
1434         rmb->ilgen = mb->ilgen;
1435         rmb->rtype = mono_type_get_object (mono_domain_get (), &mono_defaults.void_class->byval_arg);
1436         rmb->parameters = mb->parameters;
1437         rmb->generic_params = NULL;
1438         rmb->generic_container = NULL;
1439         rmb->opt_types = NULL;
1440         rmb->pinfo = mb->pinfo;
1441         rmb->attrs = mb->attrs;
1442         rmb->iattrs = mb->iattrs;
1443         rmb->call_conv = mb->call_conv;
1444         rmb->code = NULL;
1445         rmb->type = mb->type;
1446         rmb->name = mono_string_new (mono_domain_get (), name);
1447         rmb->table_idx = &mb->table_idx;
1448         rmb->init_locals = mb->init_locals;
1449         rmb->skip_visibility = FALSE;
1450         rmb->return_modreq = NULL;
1451         rmb->return_modopt = NULL;
1452         rmb->param_modreq = mb->param_modreq;
1453         rmb->param_modopt = mb->param_modopt;
1454         rmb->permissions = mb->permissions;
1455         rmb->mhandle = mb->mhandle;
1456         rmb->nrefs = 0;
1457         rmb->refs = NULL;
1458 }
1459
1460 static void
1461 reflection_methodbuilder_from_dynamic_method (ReflectionMethodBuilder *rmb, MonoReflectionDynamicMethod *mb)
1462 {
1463         memset (rmb, 0, sizeof (ReflectionMethodBuilder));
1464
1465         rmb->ilgen = mb->ilgen;
1466         rmb->rtype = mb->rtype;
1467         rmb->parameters = mb->parameters;
1468         rmb->generic_params = NULL;
1469         rmb->generic_container = NULL;
1470         rmb->opt_types = NULL;
1471         rmb->pinfo = NULL;
1472         rmb->attrs = mb->attrs;
1473         rmb->iattrs = 0;
1474         rmb->call_conv = mb->call_conv;
1475         rmb->code = NULL;
1476         rmb->type = (MonoObject *) mb->owner;
1477         rmb->name = mb->name;
1478         rmb->table_idx = NULL;
1479         rmb->init_locals = mb->init_locals;
1480         rmb->skip_visibility = mb->skip_visibility;
1481         rmb->return_modreq = NULL;
1482         rmb->return_modopt = NULL;
1483         rmb->param_modreq = NULL;
1484         rmb->param_modopt = NULL;
1485         rmb->permissions = NULL;
1486         rmb->mhandle = mb->mhandle;
1487         rmb->nrefs = 0;
1488         rmb->refs = NULL;
1489 }       
1490
1491 static void
1492 mono_image_add_methodimpl (MonoDynamicImage *assembly, MonoReflectionMethodBuilder *mb)
1493 {
1494         MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder *)mb->type;
1495         MonoDynamicTable *table;
1496         guint32 *values;
1497         guint32 tok;
1498
1499         if (!mb->override_method)
1500                 return;
1501
1502         table = &assembly->tables [MONO_TABLE_METHODIMPL];
1503         table->rows ++;
1504         alloc_table (table, table->rows);
1505         values = table->values + table->rows * MONO_METHODIMPL_SIZE;
1506         values [MONO_METHODIMPL_CLASS] = tb->table_idx;
1507         values [MONO_METHODIMPL_BODY] = MONO_METHODDEFORREF_METHODDEF | (mb->table_idx << MONO_METHODDEFORREF_BITS);
1508
1509         tok = mono_image_create_token (assembly, (MonoObject*)mb->override_method, FALSE, FALSE);
1510         switch (mono_metadata_token_table (tok)) {
1511         case MONO_TABLE_MEMBERREF:
1512                 tok = (mono_metadata_token_index (tok) << MONO_METHODDEFORREF_BITS ) | MONO_METHODDEFORREF_METHODREF;
1513                 break;
1514         case MONO_TABLE_METHOD:
1515                 tok = (mono_metadata_token_index (tok) << MONO_METHODDEFORREF_BITS ) | MONO_METHODDEFORREF_METHODDEF;
1516                 break;
1517         default:
1518                 g_assert_not_reached ();
1519         }
1520         values [MONO_METHODIMPL_DECLARATION] = tok;
1521 }
1522
1523 static void
1524 mono_image_get_method_info (MonoReflectionMethodBuilder *mb, MonoDynamicImage *assembly)
1525 {
1526         MonoDynamicTable *table;
1527         guint32 *values;
1528         ReflectionMethodBuilder rmb;
1529         int i;
1530
1531         reflection_methodbuilder_from_method_builder (&rmb, mb);
1532
1533         mono_image_basic_method (&rmb, assembly);
1534         mb->table_idx = *rmb.table_idx;
1535
1536         if (mb->dll) { /* It's a P/Invoke method */
1537                 guint32 moduleref;
1538                 /* map CharSet values to on-disk values */
1539                 int ncharset = (mb->charset ? (mb->charset - 1) * 2 : 0);
1540                 int extra_flags = mb->extra_flags;
1541                 table = &assembly->tables [MONO_TABLE_IMPLMAP];
1542                 table->rows ++;
1543                 alloc_table (table, table->rows);
1544                 values = table->values + table->rows * MONO_IMPLMAP_SIZE;
1545                 
1546                 values [MONO_IMPLMAP_FLAGS] = (mb->native_cc << 8) | ncharset | extra_flags;
1547                 values [MONO_IMPLMAP_MEMBER] = (mb->table_idx << 1) | 1; /* memberforwarded: method */
1548                 if (mb->dllentry)
1549                         values [MONO_IMPLMAP_NAME] = string_heap_insert_mstring (&assembly->sheap, mb->dllentry);
1550                 else
1551                         values [MONO_IMPLMAP_NAME] = string_heap_insert_mstring (&assembly->sheap, mb->name);
1552                 moduleref = string_heap_insert_mstring (&assembly->sheap, mb->dll);
1553                 if (!(values [MONO_IMPLMAP_SCOPE] = find_index_in_table (assembly, MONO_TABLE_MODULEREF, MONO_MODULEREF_NAME, moduleref))) {
1554                         table = &assembly->tables [MONO_TABLE_MODULEREF];
1555                         table->rows ++;
1556                         alloc_table (table, table->rows);
1557                         table->values [table->rows * MONO_MODULEREF_SIZE + MONO_MODULEREF_NAME] = moduleref;
1558                         values [MONO_IMPLMAP_SCOPE] = table->rows;
1559                 }
1560         }
1561
1562         if (mb->generic_params) {
1563                 table = &assembly->tables [MONO_TABLE_GENERICPARAM];
1564                 table->rows += mono_array_length (mb->generic_params);
1565                 alloc_table (table, table->rows);
1566                 for (i = 0; i < mono_array_length (mb->generic_params); ++i) {
1567                         guint32 owner = MONO_TYPEORMETHOD_METHOD | (mb->table_idx << MONO_TYPEORMETHOD_BITS);
1568
1569                         mono_image_get_generic_param_info (
1570                                 mono_array_get (mb->generic_params, gpointer, i), owner, assembly);
1571                 }
1572         }
1573
1574 }
1575
1576 static void
1577 mono_image_get_ctor_info (MonoDomain *domain, MonoReflectionCtorBuilder *mb, MonoDynamicImage *assembly)
1578 {
1579         ReflectionMethodBuilder rmb;
1580
1581         reflection_methodbuilder_from_ctor_builder (&rmb, mb);
1582
1583         mono_image_basic_method (&rmb, assembly);
1584         mb->table_idx = *rmb.table_idx;
1585 }
1586
1587 static char*
1588 type_get_fully_qualified_name (MonoType *type)
1589 {
1590         return mono_type_get_name_full (type, MONO_TYPE_NAME_FORMAT_ASSEMBLY_QUALIFIED);
1591 }
1592
1593 static char*
1594 type_get_qualified_name (MonoType *type, MonoAssembly *ass) {
1595         MonoClass *klass;
1596         MonoAssembly *ta;
1597
1598         klass = my_mono_class_from_mono_type (type);
1599         if (!klass) 
1600                 return mono_type_get_name_full (type, MONO_TYPE_NAME_FORMAT_REFLECTION);
1601         ta = klass->image->assembly;
1602         if (ta->dynamic || (ta == ass)) {
1603                 if (klass->generic_class || klass->generic_container)
1604                         /* For generic type definitions, we want T, while REFLECTION returns T<K> */
1605                         return mono_type_get_name_full (type, MONO_TYPE_NAME_FORMAT_FULL_NAME);
1606                 else
1607                         return mono_type_get_name_full (type, MONO_TYPE_NAME_FORMAT_REFLECTION);
1608         }
1609
1610         return mono_type_get_name_full (type, MONO_TYPE_NAME_FORMAT_ASSEMBLY_QUALIFIED);
1611 }
1612
1613 static guint32
1614 fieldref_encode_signature (MonoDynamicImage *assembly, MonoType *type)
1615 {
1616         SigBuffer buf;
1617         guint32 idx, i;
1618
1619         if (!assembly->save)
1620                 return 0;
1621
1622         sigbuffer_init (&buf, 32);
1623         
1624         sigbuffer_add_value (&buf, 0x06);
1625         /* encode custom attributes before the type */
1626         /* FIXME: This should probably go in encode_type () */
1627         if (type->num_mods) {
1628                 for (i = 0; i < type->num_mods; ++i) {
1629                         if (type->modifiers [i].required)
1630                                 sigbuffer_add_byte (&buf, MONO_TYPE_CMOD_REQD);
1631                         else
1632                                 sigbuffer_add_byte (&buf, MONO_TYPE_CMOD_OPT);
1633                         sigbuffer_add_value (&buf, type->modifiers [i].token);
1634                 }
1635         }
1636         encode_type (assembly, type, &buf);
1637         idx = sigbuffer_add_to_blob_cached (assembly, &buf);
1638         sigbuffer_free (&buf);
1639         return idx;
1640 }
1641
1642 static guint32
1643 field_encode_signature (MonoDynamicImage *assembly, MonoReflectionFieldBuilder *fb)
1644 {
1645         SigBuffer buf;
1646         guint32 idx;
1647
1648         sigbuffer_init (&buf, 32);
1649         
1650         sigbuffer_add_value (&buf, 0x06);
1651         encode_custom_modifiers (assembly, fb->modreq, fb->modopt, &buf);
1652         /* encode custom attributes before the type */
1653         encode_reflection_type (assembly, fb->type, &buf);
1654         idx = sigbuffer_add_to_blob_cached (assembly, &buf);
1655         sigbuffer_free (&buf);
1656         return idx;
1657 }
1658
1659 static guint32
1660 encode_constant (MonoDynamicImage *assembly, MonoObject *val, guint32 *ret_type) {
1661         char blob_size [64];
1662         char *b = blob_size;
1663         char *p, *box_val;
1664         char* buf;
1665         guint32 idx = 0, len = 0, dummy = 0;
1666 #ifdef ARM_FPU_FPA
1667 #if G_BYTE_ORDER == G_LITTLE_ENDIAN
1668         guint32 fpa_double [2];
1669         guint32 *fpa_p;
1670 #endif
1671 #endif
1672         
1673         p = buf = g_malloc (64);
1674         if (!val) {
1675                 *ret_type = MONO_TYPE_CLASS;
1676                 len = 4;
1677                 box_val = (char*)&dummy;
1678         } else {
1679                 box_val = ((char*)val) + sizeof (MonoObject);
1680                 *ret_type = val->vtable->klass->byval_arg.type;
1681         }
1682 handle_enum:
1683         switch (*ret_type) {
1684         case MONO_TYPE_BOOLEAN:
1685         case MONO_TYPE_U1:
1686         case MONO_TYPE_I1:
1687                 len = 1;
1688                 break;
1689         case MONO_TYPE_CHAR:
1690         case MONO_TYPE_U2:
1691         case MONO_TYPE_I2:
1692                 len = 2;
1693                 break;
1694         case MONO_TYPE_U4:
1695         case MONO_TYPE_I4:
1696         case MONO_TYPE_R4:
1697                 len = 4;
1698                 break;
1699         case MONO_TYPE_U8:
1700         case MONO_TYPE_I8:
1701                 len = 8;
1702                 break;
1703         case MONO_TYPE_R8:
1704                 len = 8;
1705 #ifdef ARM_FPU_FPA
1706 #if G_BYTE_ORDER == G_LITTLE_ENDIAN
1707                 fpa_p = (guint32*)box_val;
1708                 fpa_double [0] = fpa_p [1];
1709                 fpa_double [1] = fpa_p [0];
1710                 box_val = (char*)fpa_double;
1711 #endif
1712 #endif
1713                 break;
1714         case MONO_TYPE_VALUETYPE:
1715                 if (val->vtable->klass->enumtype) {
1716                         *ret_type = mono_class_enum_basetype (val->vtable->klass)->type;
1717                         goto handle_enum;
1718                 } else
1719                         g_error ("we can't encode valuetypes");
1720         case MONO_TYPE_CLASS:
1721                 break;
1722         case MONO_TYPE_STRING: {
1723                 MonoString *str = (MonoString*)val;
1724                 /* there is no signature */
1725                 len = str->length * 2;
1726                 mono_metadata_encode_value (len, b, &b);
1727 #if G_BYTE_ORDER != G_LITTLE_ENDIAN
1728                 {
1729                         char *swapped = g_malloc (2 * mono_string_length (str));
1730                         const char *p = (const char*)mono_string_chars (str);
1731
1732                         swap_with_size (swapped, p, 2, mono_string_length (str));
1733                         idx = add_to_blob_cached (assembly, blob_size, b-blob_size, swapped, len);
1734                         g_free (swapped);
1735                 }
1736 #else
1737                 idx = add_to_blob_cached (assembly, blob_size, b-blob_size, (char*)mono_string_chars (str), len);
1738 #endif
1739
1740                 g_free (buf);
1741                 return idx;
1742         }
1743         case MONO_TYPE_GENERICINST:
1744                 *ret_type = val->vtable->klass->generic_class->container_class->byval_arg.type;
1745                 goto handle_enum;
1746         default:
1747                 g_error ("we don't encode constant type 0x%02x yet", *ret_type);
1748         }
1749
1750         /* there is no signature */
1751         mono_metadata_encode_value (len, b, &b);
1752 #if G_BYTE_ORDER != G_LITTLE_ENDIAN
1753         idx = mono_image_add_stream_data (&assembly->blob, blob_size, b-blob_size);
1754         swap_with_size (blob_size, box_val, len, 1);
1755         mono_image_add_stream_data (&assembly->blob, blob_size, len);
1756 #else
1757         idx = add_to_blob_cached (assembly, blob_size, b-blob_size, box_val, len);
1758 #endif
1759
1760         g_free (buf);
1761         return idx;
1762 }
1763
1764 static guint32
1765 encode_marshal_blob (MonoDynamicImage *assembly, MonoReflectionMarshal *minfo) {
1766         char *str;
1767         SigBuffer buf;
1768         guint32 idx, len;
1769
1770         sigbuffer_init (&buf, 32);
1771
1772         sigbuffer_add_value (&buf, minfo->type);
1773
1774         switch (minfo->type) {
1775         case MONO_NATIVE_BYVALTSTR:
1776         case MONO_NATIVE_BYVALARRAY:
1777                 sigbuffer_add_value (&buf, minfo->count);
1778                 break;
1779         case MONO_NATIVE_LPARRAY:
1780                 if (minfo->eltype || minfo->has_size) {
1781                         sigbuffer_add_value (&buf, minfo->eltype);
1782                         if (minfo->has_size) {
1783                                 sigbuffer_add_value (&buf, minfo->param_num != -1? minfo->param_num: 0);
1784                                 sigbuffer_add_value (&buf, minfo->count != -1? minfo->count: 0);
1785
1786                                 /* LAMESPEC: ElemMult is undocumented */
1787                                 sigbuffer_add_value (&buf, minfo->param_num != -1? 1: 0);
1788                         }
1789                 }
1790                 break;
1791         case MONO_NATIVE_CUSTOM:
1792                 if (minfo->guid) {
1793                         str = mono_string_to_utf8 (minfo->guid);
1794                         len = strlen (str);
1795                         sigbuffer_add_value (&buf, len);
1796                         sigbuffer_add_mem (&buf, str, len);
1797                         g_free (str);
1798                 } else {
1799                         sigbuffer_add_value (&buf, 0);
1800                 }
1801                 /* native type name */
1802                 sigbuffer_add_value (&buf, 0);
1803                 /* custom marshaler type name */
1804                 if (minfo->marshaltype || minfo->marshaltyperef) {
1805                         if (minfo->marshaltyperef)
1806                                 str = type_get_fully_qualified_name (minfo->marshaltyperef->type);
1807                         else
1808                                 str = mono_string_to_utf8 (minfo->marshaltype);
1809                         len = strlen (str);
1810                         sigbuffer_add_value (&buf, len);
1811                         sigbuffer_add_mem (&buf, str, len);
1812                         g_free (str);
1813                 } else {
1814                         /* FIXME: Actually a bug, since this field is required.  Punting for now ... */
1815                         sigbuffer_add_value (&buf, 0);
1816                 }
1817                 if (minfo->mcookie) {
1818                         str = mono_string_to_utf8 (minfo->mcookie);
1819                         len = strlen (str);
1820                         sigbuffer_add_value (&buf, len);
1821                         sigbuffer_add_mem (&buf, str, len);
1822                         g_free (str);
1823                 } else {
1824                         sigbuffer_add_value (&buf, 0);
1825                 }
1826                 break;
1827         default:
1828                 break;
1829         }
1830         idx = sigbuffer_add_to_blob_cached (assembly, &buf);
1831         sigbuffer_free (&buf);
1832         return idx;
1833 }
1834
1835 static void
1836 mono_image_get_field_info (MonoReflectionFieldBuilder *fb, MonoDynamicImage *assembly)
1837 {
1838         MonoDynamicTable *table;
1839         guint32 *values;
1840
1841         /* maybe this fixup should be done in the C# code */
1842         if (fb->attrs & FIELD_ATTRIBUTE_LITERAL)
1843                 fb->attrs |= FIELD_ATTRIBUTE_HAS_DEFAULT;
1844         table = &assembly->tables [MONO_TABLE_FIELD];
1845         fb->table_idx = table->next_idx ++;
1846         g_hash_table_insert (assembly->field_to_table_idx, fb->handle, GUINT_TO_POINTER (fb->table_idx));
1847         values = table->values + fb->table_idx * MONO_FIELD_SIZE;
1848         values [MONO_FIELD_NAME] = string_heap_insert_mstring (&assembly->sheap, fb->name);
1849         values [MONO_FIELD_FLAGS] = fb->attrs;
1850         values [MONO_FIELD_SIGNATURE] = field_encode_signature (assembly, fb);
1851
1852         if (fb->offset != -1) {
1853                 table = &assembly->tables [MONO_TABLE_FIELDLAYOUT];
1854                 table->rows ++;
1855                 alloc_table (table, table->rows);
1856                 values = table->values + table->rows * MONO_FIELD_LAYOUT_SIZE;
1857                 values [MONO_FIELD_LAYOUT_FIELD] = fb->table_idx;
1858                 values [MONO_FIELD_LAYOUT_OFFSET] = fb->offset;
1859         }
1860         if (fb->attrs & FIELD_ATTRIBUTE_LITERAL) {
1861                 guint32 field_type = 0;
1862                 table = &assembly->tables [MONO_TABLE_CONSTANT];
1863                 table->rows ++;
1864                 alloc_table (table, table->rows);
1865                 values = table->values + table->rows * MONO_CONSTANT_SIZE;
1866                 values [MONO_CONSTANT_PARENT] = MONO_HASCONSTANT_FIEDDEF | (fb->table_idx << MONO_HASCONSTANT_BITS);
1867                 values [MONO_CONSTANT_VALUE] = encode_constant (assembly, fb->def_value, &field_type);
1868                 values [MONO_CONSTANT_TYPE] = field_type;
1869                 values [MONO_CONSTANT_PADDING] = 0;
1870         }
1871         if (fb->attrs & FIELD_ATTRIBUTE_HAS_FIELD_RVA) {
1872                 guint32 rva_idx;
1873                 table = &assembly->tables [MONO_TABLE_FIELDRVA];
1874                 table->rows ++;
1875                 alloc_table (table, table->rows);
1876                 values = table->values + table->rows * MONO_FIELD_RVA_SIZE;
1877                 values [MONO_FIELD_RVA_FIELD] = fb->table_idx;
1878                 /*
1879                  * We store it in the code section because it's simpler for now.
1880                  */
1881                 if (fb->rva_data) {
1882                         if (mono_array_length (fb->rva_data) >= 10)
1883                                 stream_data_align (&assembly->code);
1884                         rva_idx = mono_image_add_stream_data (&assembly->code, mono_array_addr (fb->rva_data, char, 0), mono_array_length (fb->rva_data));
1885                 } else
1886                         rva_idx = mono_image_add_stream_zero (&assembly->code, mono_class_value_size (fb->handle->parent, NULL));
1887                 values [MONO_FIELD_RVA_RVA] = rva_idx + assembly->text_rva;
1888         }
1889         if (fb->marshal_info) {
1890                 table = &assembly->tables [MONO_TABLE_FIELDMARSHAL];
1891                 table->rows ++;
1892                 alloc_table (table, table->rows);
1893                 values = table->values + table->rows * MONO_FIELD_MARSHAL_SIZE;
1894                 values [MONO_FIELD_MARSHAL_PARENT] = (fb->table_idx << MONO_HAS_FIELD_MARSHAL_BITS) | MONO_HAS_FIELD_MARSHAL_FIELDSREF;
1895                 values [MONO_FIELD_MARSHAL_NATIVE_TYPE] = encode_marshal_blob (assembly, fb->marshal_info);
1896         }
1897 }
1898
1899 static guint32
1900 property_encode_signature (MonoDynamicImage *assembly, MonoReflectionPropertyBuilder *fb)
1901 {
1902         SigBuffer buf;
1903         guint32 nparams = 0;
1904         MonoReflectionMethodBuilder *mb = fb->get_method;
1905         MonoReflectionMethodBuilder *smb = fb->set_method;
1906         guint32 idx, i;
1907
1908         if (mb && mb->parameters)
1909                 nparams = mono_array_length (mb->parameters);
1910         if (!mb && smb && smb->parameters)
1911                 nparams = mono_array_length (smb->parameters) - 1;
1912         sigbuffer_init (&buf, 32);
1913         sigbuffer_add_byte (&buf, 0x08);
1914         sigbuffer_add_value (&buf, nparams);
1915         if (mb) {
1916                 encode_reflection_type (assembly, mb->rtype, &buf);
1917                 for (i = 0; i < nparams; ++i) {
1918                         MonoReflectionType *pt = mono_array_get (mb->parameters, MonoReflectionType*, i);
1919                         encode_reflection_type (assembly, pt, &buf);
1920                 }
1921         } else if (smb && smb->parameters) {
1922                 /* the property type is the last param */
1923                 encode_reflection_type (assembly, mono_array_get (smb->parameters, MonoReflectionType*, nparams), &buf);
1924                 for (i = 0; i < nparams; ++i) {
1925                         MonoReflectionType *pt = mono_array_get (smb->parameters, MonoReflectionType*, i);
1926                         encode_reflection_type (assembly, pt, &buf);
1927                 }
1928         } else {
1929                 encode_reflection_type (assembly, fb->type, &buf);
1930         }
1931
1932         idx = sigbuffer_add_to_blob_cached (assembly, &buf);
1933         sigbuffer_free (&buf);
1934         return idx;
1935 }
1936
1937 static void
1938 mono_image_get_property_info (MonoReflectionPropertyBuilder *pb, MonoDynamicImage *assembly)
1939 {
1940         MonoDynamicTable *table;
1941         guint32 *values;
1942         guint num_methods = 0;
1943         guint32 semaidx;
1944
1945         /* 
1946          * we need to set things in the following tables:
1947          * PROPERTYMAP (info already filled in _get_type_info ())
1948          * PROPERTY    (rows already preallocated in _get_type_info ())
1949          * METHOD      (method info already done with the generic method code)
1950          * METHODSEMANTICS
1951          */
1952         table = &assembly->tables [MONO_TABLE_PROPERTY];
1953         pb->table_idx = table->next_idx ++;
1954         values = table->values + pb->table_idx * MONO_PROPERTY_SIZE;
1955         values [MONO_PROPERTY_NAME] = string_heap_insert_mstring (&assembly->sheap, pb->name);
1956         values [MONO_PROPERTY_FLAGS] = pb->attrs;
1957         values [MONO_PROPERTY_TYPE] = property_encode_signature (assembly, pb);
1958
1959         /* FIXME: we still don't handle 'other' methods */
1960         if (pb->get_method) num_methods ++;
1961         if (pb->set_method) num_methods ++;
1962
1963         table = &assembly->tables [MONO_TABLE_METHODSEMANTICS];
1964         table->rows += num_methods;
1965         alloc_table (table, table->rows);
1966
1967         if (pb->get_method) {
1968                 semaidx = table->next_idx ++;
1969                 values = table->values + semaidx * MONO_METHOD_SEMA_SIZE;
1970                 values [MONO_METHOD_SEMA_SEMANTICS] = METHOD_SEMANTIC_GETTER;
1971                 values [MONO_METHOD_SEMA_METHOD] = pb->get_method->table_idx;
1972                 values [MONO_METHOD_SEMA_ASSOCIATION] = (pb->table_idx << MONO_HAS_SEMANTICS_BITS) | MONO_HAS_SEMANTICS_PROPERTY;
1973         }
1974         if (pb->set_method) {
1975                 semaidx = table->next_idx ++;
1976                 values = table->values + semaidx * MONO_METHOD_SEMA_SIZE;
1977                 values [MONO_METHOD_SEMA_SEMANTICS] = METHOD_SEMANTIC_SETTER;
1978                 values [MONO_METHOD_SEMA_METHOD] = pb->set_method->table_idx;
1979                 values [MONO_METHOD_SEMA_ASSOCIATION] = (pb->table_idx << MONO_HAS_SEMANTICS_BITS) | MONO_HAS_SEMANTICS_PROPERTY;
1980         }
1981 }
1982
1983 static void
1984 mono_image_get_event_info (MonoReflectionEventBuilder *eb, MonoDynamicImage *assembly)
1985 {
1986         MonoDynamicTable *table;
1987         guint32 *values;
1988         guint num_methods = 0;
1989         guint32 semaidx;
1990
1991         /* 
1992          * we need to set things in the following tables:
1993          * EVENTMAP (info already filled in _get_type_info ())
1994          * EVENT    (rows already preallocated in _get_type_info ())
1995          * METHOD      (method info already done with the generic method code)
1996          * METHODSEMANTICS
1997          */
1998         table = &assembly->tables [MONO_TABLE_EVENT];
1999         eb->table_idx = table->next_idx ++;
2000         values = table->values + eb->table_idx * MONO_EVENT_SIZE;
2001         values [MONO_EVENT_NAME] = string_heap_insert_mstring (&assembly->sheap, eb->name);
2002         values [MONO_EVENT_FLAGS] = eb->attrs;
2003         values [MONO_EVENT_TYPE] = mono_image_typedef_or_ref (assembly, eb->type->type);
2004
2005         /*
2006          * FIXME: we still don't handle 'other' methods 
2007          */
2008         if (eb->add_method) num_methods ++;
2009         if (eb->remove_method) num_methods ++;
2010         if (eb->raise_method) num_methods ++;
2011
2012         table = &assembly->tables [MONO_TABLE_METHODSEMANTICS];
2013         table->rows += num_methods;
2014         alloc_table (table, table->rows);
2015
2016         if (eb->add_method) {
2017                 semaidx = table->next_idx ++;
2018                 values = table->values + semaidx * MONO_METHOD_SEMA_SIZE;
2019                 values [MONO_METHOD_SEMA_SEMANTICS] = METHOD_SEMANTIC_ADD_ON;
2020                 values [MONO_METHOD_SEMA_METHOD] = eb->add_method->table_idx;
2021                 values [MONO_METHOD_SEMA_ASSOCIATION] = (eb->table_idx << MONO_HAS_SEMANTICS_BITS) | MONO_HAS_SEMANTICS_EVENT;
2022         }
2023         if (eb->remove_method) {
2024                 semaidx = table->next_idx ++;
2025                 values = table->values + semaidx * MONO_METHOD_SEMA_SIZE;
2026                 values [MONO_METHOD_SEMA_SEMANTICS] = METHOD_SEMANTIC_REMOVE_ON;
2027                 values [MONO_METHOD_SEMA_METHOD] = eb->remove_method->table_idx;
2028                 values [MONO_METHOD_SEMA_ASSOCIATION] = (eb->table_idx << MONO_HAS_SEMANTICS_BITS) | MONO_HAS_SEMANTICS_EVENT;
2029         }
2030         if (eb->raise_method) {
2031                 semaidx = table->next_idx ++;
2032                 values = table->values + semaidx * MONO_METHOD_SEMA_SIZE;
2033                 values [MONO_METHOD_SEMA_SEMANTICS] = METHOD_SEMANTIC_FIRE;
2034                 values [MONO_METHOD_SEMA_METHOD] = eb->raise_method->table_idx;
2035                 values [MONO_METHOD_SEMA_ASSOCIATION] = (eb->table_idx << MONO_HAS_SEMANTICS_BITS) | MONO_HAS_SEMANTICS_EVENT;
2036         }
2037 }
2038
2039 static void
2040 encode_constraints (MonoReflectionGenericParam *gparam, guint32 owner, MonoDynamicImage *assembly)
2041 {
2042         MonoDynamicTable *table;
2043         guint32 num_constraints, i;
2044         guint32 *values;
2045         guint32 table_idx;
2046
2047         table = &assembly->tables [MONO_TABLE_GENERICPARAMCONSTRAINT];
2048         num_constraints = gparam->iface_constraints ?
2049                 mono_array_length (gparam->iface_constraints) : 0;
2050         table->rows += num_constraints;
2051         if (gparam->base_type)
2052                 table->rows++;
2053         alloc_table (table, table->rows);
2054
2055         if (gparam->base_type) {
2056                 table_idx = table->next_idx ++;
2057                 values = table->values + table_idx * MONO_GENPARCONSTRAINT_SIZE;
2058
2059                 values [MONO_GENPARCONSTRAINT_GENERICPAR] = owner;
2060                 values [MONO_GENPARCONSTRAINT_CONSTRAINT] = mono_image_typedef_or_ref (
2061                         assembly, gparam->base_type->type);
2062         }
2063
2064         for (i = 0; i < num_constraints; i++) {
2065                 MonoReflectionType *constraint = mono_array_get (
2066                         gparam->iface_constraints, gpointer, i);
2067
2068                 table_idx = table->next_idx ++;
2069                 values = table->values + table_idx * MONO_GENPARCONSTRAINT_SIZE;
2070
2071                 values [MONO_GENPARCONSTRAINT_GENERICPAR] = owner;
2072                 values [MONO_GENPARCONSTRAINT_CONSTRAINT] = mono_image_typedef_or_ref (
2073                         assembly, constraint->type);
2074         }
2075 }
2076
2077 static void
2078 mono_image_get_generic_param_info (MonoReflectionGenericParam *gparam, guint32 owner, MonoDynamicImage *assembly)
2079 {
2080         GenericParamTableEntry *entry;
2081
2082         /*
2083          * The GenericParam table must be sorted according to the `owner' field.
2084          * We need to do this sorting prior to writing the GenericParamConstraint
2085          * table, since we have to use the final GenericParam table indices there
2086          * and they must also be sorted.
2087          */
2088
2089         entry = g_new0 (GenericParamTableEntry, 1);
2090         entry->owner = owner;
2091         /* FIXME: track where gen_params should be freed and remove the GC root as well */
2092         MOVING_GC_REGISTER (&entry->gparam);
2093         entry->gparam = gparam;
2094
2095         g_ptr_array_add (assembly->gen_params, entry);
2096 }
2097
2098 static void
2099 write_generic_param_entry (MonoDynamicImage *assembly, GenericParamTableEntry *entry)
2100 {
2101         MonoDynamicTable *table;
2102         MonoGenericParam *param;
2103         guint32 *values;
2104         guint32 table_idx;
2105
2106         table = &assembly->tables [MONO_TABLE_GENERICPARAM];
2107         table_idx = table->next_idx ++;
2108         values = table->values + table_idx * MONO_GENERICPARAM_SIZE;
2109
2110         param = entry->gparam->type.type->data.generic_param;
2111
2112         values [MONO_GENERICPARAM_OWNER] = entry->owner;
2113         values [MONO_GENERICPARAM_FLAGS] = entry->gparam->attrs;
2114         values [MONO_GENERICPARAM_NUMBER] = param->num;
2115         values [MONO_GENERICPARAM_NAME] = string_heap_insert (&assembly->sheap, param->name);
2116
2117         mono_image_add_cattrs (assembly, table_idx, MONO_CUSTOM_ATTR_GENERICPAR, entry->gparam->cattrs);
2118
2119         encode_constraints (entry->gparam, table_idx, assembly);
2120 }
2121
2122 static guint32
2123 resolution_scope_from_image (MonoDynamicImage *assembly, MonoImage *image)
2124 {
2125         MonoDynamicTable *table;
2126         guint32 token;
2127         guint32 *values;
2128         guint32 cols [MONO_ASSEMBLY_SIZE];
2129         const char *pubkey;
2130         guint32 publen;
2131
2132         if ((token = GPOINTER_TO_UINT (g_hash_table_lookup (assembly->handleref, image))))
2133                 return token;
2134
2135         if (image->assembly->dynamic && (image->assembly == assembly->image.assembly)) {
2136                 table = &assembly->tables [MONO_TABLE_MODULEREF];
2137                 token = table->next_idx ++;
2138                 table->rows ++;
2139                 alloc_table (table, table->rows);
2140                 values = table->values + token * MONO_MODULEREF_SIZE;
2141                 values [MONO_MODULEREF_NAME] = string_heap_insert (&assembly->sheap, image->module_name);
2142
2143                 token <<= MONO_RESOLTION_SCOPE_BITS;
2144                 token |= MONO_RESOLTION_SCOPE_MODULEREF;
2145                 g_hash_table_insert (assembly->handleref, image, GUINT_TO_POINTER (token));
2146
2147                 return token;
2148         }
2149         
2150         if (image->assembly->dynamic)
2151                 /* FIXME: */
2152                 memset (cols, 0, sizeof (cols));
2153         else {
2154                 /* image->assembly->image is the manifest module */
2155                 image = image->assembly->image;
2156                 mono_metadata_decode_row (&image->tables [MONO_TABLE_ASSEMBLY], 0, cols, MONO_ASSEMBLY_SIZE);
2157         }
2158
2159         table = &assembly->tables [MONO_TABLE_ASSEMBLYREF];
2160         token = table->next_idx ++;
2161         table->rows ++;
2162         alloc_table (table, table->rows);
2163         values = table->values + token * MONO_ASSEMBLYREF_SIZE;
2164         values [MONO_ASSEMBLYREF_NAME] = string_heap_insert (&assembly->sheap, image->assembly_name);
2165         values [MONO_ASSEMBLYREF_MAJOR_VERSION] = cols [MONO_ASSEMBLY_MAJOR_VERSION];
2166         values [MONO_ASSEMBLYREF_MINOR_VERSION] = cols [MONO_ASSEMBLY_MINOR_VERSION];
2167         values [MONO_ASSEMBLYREF_BUILD_NUMBER] = cols [MONO_ASSEMBLY_BUILD_NUMBER];
2168         values [MONO_ASSEMBLYREF_REV_NUMBER] = cols [MONO_ASSEMBLY_REV_NUMBER];
2169         values [MONO_ASSEMBLYREF_FLAGS] = 0;
2170         values [MONO_ASSEMBLYREF_CULTURE] = 0;
2171         values [MONO_ASSEMBLYREF_HASH_VALUE] = 0;
2172
2173         if (strcmp ("", image->assembly->aname.culture)) {
2174                 values [MONO_ASSEMBLYREF_CULTURE] = string_heap_insert (&assembly->sheap,
2175                                 image->assembly->aname.culture);
2176         }
2177
2178         if ((pubkey = mono_image_get_public_key (image, &publen))) {
2179                 guchar pubtoken [9];
2180                 pubtoken [0] = 8;
2181                 mono_digest_get_public_token (pubtoken + 1, (guchar*)pubkey, publen);
2182                 values [MONO_ASSEMBLYREF_PUBLIC_KEY] = mono_image_add_stream_data (&assembly->blob, (char*)pubtoken, 9);
2183         } else {
2184                 values [MONO_ASSEMBLYREF_PUBLIC_KEY] = 0;
2185         }
2186         token <<= MONO_RESOLTION_SCOPE_BITS;
2187         token |= MONO_RESOLTION_SCOPE_ASSEMBLYREF;
2188         g_hash_table_insert (assembly->handleref, image, GUINT_TO_POINTER (token));
2189         return token;
2190 }
2191
2192 static guint32
2193 create_typespec (MonoDynamicImage *assembly, MonoType *type)
2194 {
2195         MonoDynamicTable *table;
2196         guint32 *values;
2197         guint32 token;
2198         SigBuffer buf;
2199
2200         if ((token = GPOINTER_TO_UINT (g_hash_table_lookup (assembly->typespec, type))))
2201                 return token;
2202
2203         sigbuffer_init (&buf, 32);
2204         switch (type->type) {
2205         case MONO_TYPE_FNPTR:
2206         case MONO_TYPE_PTR:
2207         case MONO_TYPE_SZARRAY:
2208         case MONO_TYPE_ARRAY:
2209         case MONO_TYPE_VAR:
2210         case MONO_TYPE_MVAR:
2211         case MONO_TYPE_GENERICINST:
2212                 encode_type (assembly, type, &buf);
2213                 break;
2214         case MONO_TYPE_CLASS:
2215         case MONO_TYPE_VALUETYPE: {
2216                 MonoClass *k = mono_class_from_mono_type (type);
2217                 if (!k || !k->generic_container) {
2218                         sigbuffer_free (&buf);
2219                         return 0;
2220                 }
2221                 encode_type (assembly, type, &buf);
2222                 break;
2223         }
2224         default:
2225                 sigbuffer_free (&buf);
2226                 return 0;
2227         }
2228
2229         table = &assembly->tables [MONO_TABLE_TYPESPEC];
2230         if (assembly->save) {
2231                 token = sigbuffer_add_to_blob_cached (assembly, &buf);
2232                 alloc_table (table, table->rows + 1);
2233                 values = table->values + table->next_idx * MONO_TYPESPEC_SIZE;
2234                 values [MONO_TYPESPEC_SIGNATURE] = token;
2235         }
2236         sigbuffer_free (&buf);
2237
2238         token = MONO_TYPEDEFORREF_TYPESPEC | (table->next_idx << MONO_TYPEDEFORREF_BITS);
2239         g_hash_table_insert (assembly->typespec, type, GUINT_TO_POINTER(token));
2240         table->next_idx ++;
2241         return token;
2242 }
2243
2244 static guint32
2245 mono_image_typedef_or_ref_full (MonoDynamicImage *assembly, MonoType *type, gboolean try_typespec)
2246 {
2247         MonoDynamicTable *table;
2248         guint32 *values;
2249         guint32 token, scope, enclosing;
2250         MonoClass *klass;
2251
2252         /* if the type requires a typespec, we must try that first*/
2253         if (try_typespec && (token = create_typespec (assembly, type)))
2254                 return token;
2255         token = GPOINTER_TO_UINT (g_hash_table_lookup (assembly->typeref, type));
2256         if (token)
2257                 return token;
2258         klass = my_mono_class_from_mono_type (type);
2259         if (!klass)
2260                 klass = mono_class_from_mono_type (type);
2261
2262         /*
2263          * If it's in the same module and not a generic type parameter:
2264          */
2265         if ((klass->image == &assembly->image) && (type->type != MONO_TYPE_VAR) && 
2266                         (type->type != MONO_TYPE_MVAR)) {
2267                 MonoReflectionTypeBuilder *tb = klass->reflection_info;
2268                 token = MONO_TYPEDEFORREF_TYPEDEF | (tb->table_idx << MONO_TYPEDEFORREF_BITS);
2269                 mono_g_hash_table_insert (assembly->tokens, GUINT_TO_POINTER (token), klass->reflection_info);
2270                 return token;
2271         }
2272
2273         if (klass->nested_in) {
2274                 enclosing = mono_image_typedef_or_ref_full (assembly, &klass->nested_in->byval_arg, FALSE);
2275                 /* get the typeref idx of the enclosing type */
2276                 enclosing >>= MONO_TYPEDEFORREF_BITS;
2277                 scope = (enclosing << MONO_RESOLTION_SCOPE_BITS) | MONO_RESOLTION_SCOPE_TYPEREF;
2278         } else {
2279                 scope = resolution_scope_from_image (assembly, klass->image);
2280         }
2281         table = &assembly->tables [MONO_TABLE_TYPEREF];
2282         if (assembly->save) {
2283                 alloc_table (table, table->rows + 1);
2284                 values = table->values + table->next_idx * MONO_TYPEREF_SIZE;
2285                 values [MONO_TYPEREF_SCOPE] = scope;
2286                 values [MONO_TYPEREF_NAME] = string_heap_insert (&assembly->sheap, klass->name);
2287                 values [MONO_TYPEREF_NAMESPACE] = string_heap_insert (&assembly->sheap, klass->name_space);
2288         }
2289         token = MONO_TYPEDEFORREF_TYPEREF | (table->next_idx << MONO_TYPEDEFORREF_BITS); /* typeref */
2290         g_hash_table_insert (assembly->typeref, type, GUINT_TO_POINTER(token));
2291         table->next_idx ++;
2292         mono_g_hash_table_insert (assembly->tokens, GUINT_TO_POINTER (token), klass->reflection_info);
2293         return token;
2294 }
2295
2296 /*
2297  * Despite the name, we handle also TypeSpec (with the above helper).
2298  */
2299 static guint32
2300 mono_image_typedef_or_ref (MonoDynamicImage *assembly, MonoType *type)
2301 {
2302         return mono_image_typedef_or_ref_full (assembly, type, TRUE);
2303 }
2304
2305 /*
2306  * Insert a memberef row into the metadata: the token that point to the memberref
2307  * is returned. Caching is done in the caller (mono_image_get_methodref_token() or
2308  * mono_image_get_fieldref_token()).
2309  * The sig param is an index to an already built signature.
2310  */
2311 static guint32
2312 mono_image_get_memberref_token (MonoDynamicImage *assembly, MonoType *type, const char *name, guint32 sig)
2313 {
2314         MonoDynamicTable *table;
2315         guint32 *values;
2316         guint32 token, pclass;
2317         guint32 parent;
2318
2319         parent = mono_image_typedef_or_ref (assembly, type);
2320         switch (parent & MONO_TYPEDEFORREF_MASK) {
2321         case MONO_TYPEDEFORREF_TYPEREF:
2322                 pclass = MONO_MEMBERREF_PARENT_TYPEREF;
2323                 break;
2324         case MONO_TYPEDEFORREF_TYPESPEC:
2325                 pclass = MONO_MEMBERREF_PARENT_TYPESPEC;
2326                 break;
2327         case MONO_TYPEDEFORREF_TYPEDEF:
2328                 pclass = MONO_MEMBERREF_PARENT_TYPEDEF;
2329                 break;
2330         default:
2331                 g_warning ("unknown typeref or def token 0x%08x for %s", parent, name);
2332                 return 0;
2333         }
2334         /* extract the index */
2335         parent >>= MONO_TYPEDEFORREF_BITS;
2336
2337         table = &assembly->tables [MONO_TABLE_MEMBERREF];
2338
2339         if (assembly->save) {
2340                 alloc_table (table, table->rows + 1);
2341                 values = table->values + table->next_idx * MONO_MEMBERREF_SIZE;
2342                 values [MONO_MEMBERREF_CLASS] = pclass | (parent << MONO_MEMBERREF_PARENT_BITS);
2343                 values [MONO_MEMBERREF_NAME] = string_heap_insert (&assembly->sheap, name);
2344                 values [MONO_MEMBERREF_SIGNATURE] = sig;
2345         }
2346
2347         token = MONO_TOKEN_MEMBER_REF | table->next_idx;
2348         table->next_idx ++;
2349
2350         return token;
2351 }
2352
2353 static guint32
2354 mono_image_get_methodref_token (MonoDynamicImage *assembly, MonoMethod *method, gboolean create_typespec)
2355 {
2356         guint32 token;
2357         MonoMethodSignature *sig;
2358         
2359         create_typespec = create_typespec && method->is_generic && method->klass->image != &assembly->image;
2360
2361         if (create_typespec) {
2362                 token = GPOINTER_TO_UINT (g_hash_table_lookup (assembly->handleref, GUINT_TO_POINTER (GPOINTER_TO_UINT (method) + 1)));
2363                 if (token)
2364                         return token;
2365         } 
2366
2367         token = GPOINTER_TO_UINT (g_hash_table_lookup (assembly->handleref, method));
2368         if (token && !create_typespec)
2369                 return token;
2370
2371         g_assert (!method->is_inflated);
2372         if (!token) {
2373                 /*
2374                  * A methodref signature can't contain an unmanaged calling convention.
2375                  */
2376                 sig = mono_metadata_signature_dup (mono_method_signature (method));
2377                 if ((sig->call_convention != MONO_CALL_DEFAULT) && (sig->call_convention != MONO_CALL_VARARG))
2378                         sig->call_convention = MONO_CALL_DEFAULT;
2379                 token = mono_image_get_memberref_token (assembly, &method->klass->byval_arg,
2380                         method->name,  method_encode_signature (assembly, sig));
2381                 g_free (sig);
2382                 g_hash_table_insert (assembly->handleref, method, GUINT_TO_POINTER(token));
2383         }
2384
2385         if (create_typespec) {
2386                 MonoDynamicTable *table = &assembly->tables [MONO_TABLE_METHODSPEC];
2387                 g_assert (mono_metadata_token_table (token) == MONO_TABLE_MEMBERREF);
2388                 token = (mono_metadata_token_index (token) << MONO_METHODDEFORREF_BITS) | MONO_METHODDEFORREF_METHODREF;
2389
2390                 if (assembly->save) {
2391                         guint32 *values;
2392
2393                         alloc_table (table, table->rows + 1);
2394                         values = table->values + table->next_idx * MONO_METHODSPEC_SIZE;
2395                         values [MONO_METHODSPEC_METHOD] = token;
2396                         values [MONO_METHODSPEC_SIGNATURE] = encode_generic_method_sig (assembly, &mono_method_get_generic_container (method)->context);
2397                 }
2398
2399                 token = MONO_TOKEN_METHOD_SPEC | table->next_idx;
2400                 table->next_idx ++;
2401                 /*methodspec and memberef tokens are diferent, */
2402                 g_hash_table_insert (assembly->handleref, GUINT_TO_POINTER (GPOINTER_TO_UINT (method) + 1), GUINT_TO_POINTER (token));
2403                 return token;
2404         }
2405         return token;
2406 }
2407
2408 static guint32
2409 mono_image_get_methodref_token_for_methodbuilder (MonoDynamicImage *assembly, MonoReflectionMethodBuilder *method)
2410 {
2411         guint32 token;
2412         ReflectionMethodBuilder rmb;
2413         char *name;
2414         
2415         token = GPOINTER_TO_UINT (g_hash_table_lookup (assembly->handleref, method));
2416         if (token)
2417                 return token;
2418
2419         name = mono_string_to_utf8 (method->name);
2420         reflection_methodbuilder_from_method_builder (&rmb, method);
2421
2422         /*
2423          * A methodref signature can't contain an unmanaged calling convention.
2424          * Since some flags are encoded as part of call_conv, we need to check against it.
2425         */
2426         if ((rmb.call_conv & ~0x60) != MONO_CALL_DEFAULT && (rmb.call_conv & ~0x60) != MONO_CALL_VARARG)
2427                 rmb.call_conv = (rmb.call_conv & 0x60) | MONO_CALL_DEFAULT;
2428         token = mono_image_get_memberref_token (assembly, ((MonoReflectionTypeBuilder*)rmb.type)->type.type,
2429                                         name, method_builder_encode_signature (assembly, &rmb));
2430
2431         g_free (name);
2432         g_hash_table_insert (assembly->handleref, method, GUINT_TO_POINTER(token));
2433         return token;
2434 }
2435
2436 static guint32
2437 mono_image_get_varargs_method_token (MonoDynamicImage *assembly, guint32 original,
2438                                      const gchar *name, guint32 sig)
2439 {
2440         MonoDynamicTable *table;
2441         guint32 token;
2442         guint32 *values;
2443         
2444         table = &assembly->tables [MONO_TABLE_MEMBERREF];
2445
2446         if (assembly->save) {
2447                 alloc_table (table, table->rows + 1);
2448                 values = table->values + table->next_idx * MONO_MEMBERREF_SIZE;
2449                 values [MONO_MEMBERREF_CLASS] = original;
2450                 values [MONO_MEMBERREF_NAME] = string_heap_insert (&assembly->sheap, name);
2451                 values [MONO_MEMBERREF_SIGNATURE] = sig;
2452         }
2453
2454         token = MONO_TOKEN_MEMBER_REF | table->next_idx;
2455         table->next_idx ++;
2456
2457         return token;
2458 }
2459
2460 static guint32
2461 encode_generic_method_definition_sig (MonoDynamicImage *assembly, MonoReflectionMethodBuilder *mb)
2462 {
2463         SigBuffer buf;
2464         int i;
2465         guint32 nparams = mono_array_length (mb->generic_params);
2466         guint32 idx;
2467
2468         if (!assembly->save)
2469                 return 0;
2470
2471         sigbuffer_init (&buf, 32);
2472
2473         sigbuffer_add_value (&buf, 0xa);
2474         sigbuffer_add_value (&buf, nparams);
2475
2476         for (i = 0; i < nparams; i++) {
2477                 sigbuffer_add_value (&buf, MONO_TYPE_MVAR);
2478                 sigbuffer_add_value (&buf, i);
2479         }
2480
2481         idx = sigbuffer_add_to_blob_cached (assembly, &buf);
2482         sigbuffer_free (&buf);
2483         return idx;
2484 }
2485
2486 static guint32
2487 mono_image_get_methodspec_token_for_generic_method_definition (MonoDynamicImage *assembly, MonoReflectionMethodBuilder *mb)
2488 {
2489         MonoDynamicTable *table;
2490         guint32 *values;
2491         guint32 token, mtoken = 0;
2492
2493         token = GPOINTER_TO_UINT (mono_g_hash_table_lookup (assembly->methodspec, mb));
2494         if (token)
2495                 return token;
2496
2497         table = &assembly->tables [MONO_TABLE_METHODSPEC];
2498
2499         mtoken = mono_image_get_methodref_token_for_methodbuilder (assembly, mb);
2500         switch (mono_metadata_token_table (mtoken)) {
2501         case MONO_TABLE_MEMBERREF:
2502                 mtoken = (mono_metadata_token_index (mtoken) << MONO_METHODDEFORREF_BITS) | MONO_METHODDEFORREF_METHODREF;
2503                 break;
2504         case MONO_TABLE_METHOD:
2505                 mtoken = (mono_metadata_token_index (mtoken) << MONO_METHODDEFORREF_BITS) | MONO_METHODDEFORREF_METHODDEF;
2506                 break;
2507         default:
2508                 g_assert_not_reached ();
2509         }
2510
2511         if (assembly->save) {
2512                 alloc_table (table, table->rows + 1);
2513                 values = table->values + table->next_idx * MONO_METHODSPEC_SIZE;
2514                 values [MONO_METHODSPEC_METHOD] = mtoken;
2515                 values [MONO_METHODSPEC_SIGNATURE] = encode_generic_method_definition_sig (assembly, mb);
2516         }
2517
2518         token = MONO_TOKEN_METHOD_SPEC | table->next_idx;
2519         table->next_idx ++;
2520
2521         mono_g_hash_table_insert (assembly->methodspec, mb, GUINT_TO_POINTER(token));
2522         return token;
2523 }
2524
2525 static guint32
2526 mono_image_get_methodbuilder_token (MonoDynamicImage *assembly, MonoReflectionMethodBuilder *mb, gboolean create_methodspec)
2527 {
2528         guint32 token;
2529         
2530         if (mb->generic_params && create_methodspec) 
2531                 return mono_image_get_methodspec_token_for_generic_method_definition (assembly, mb);
2532
2533         token = GPOINTER_TO_UINT (g_hash_table_lookup (assembly->handleref, mb));
2534         if (token)
2535                 return token;
2536
2537         token = mono_image_get_methodref_token_for_methodbuilder (assembly, mb);
2538         g_hash_table_insert (assembly->handleref, mb, GUINT_TO_POINTER(token));
2539         return token;
2540 }
2541
2542 static guint32
2543 mono_image_get_ctorbuilder_token (MonoDynamicImage *assembly, MonoReflectionCtorBuilder *mb)
2544 {
2545         guint32 token;
2546         ReflectionMethodBuilder rmb;
2547         char *name;
2548         
2549         token = GPOINTER_TO_UINT (g_hash_table_lookup (assembly->handleref, mb));
2550         if (token)
2551                 return token;
2552
2553         reflection_methodbuilder_from_ctor_builder (&rmb, mb);
2554
2555         name = mono_string_to_utf8 (rmb.name);
2556         token = mono_image_get_memberref_token (assembly, ((MonoReflectionTypeBuilder*)rmb.type)->type.type,
2557                 name, method_builder_encode_signature (assembly, &rmb));
2558
2559         g_free (name);
2560         g_hash_table_insert (assembly->handleref, mb, GUINT_TO_POINTER(token));
2561         return token;
2562 }
2563
2564 static gboolean
2565 is_field_on_inst (MonoClassField *field)
2566 {
2567         return (field->parent->generic_class && field->parent->generic_class->is_dynamic && ((MonoDynamicGenericClass*)field->parent->generic_class)->fields);
2568 }
2569
2570 /*
2571  * If FIELD is a field of a MonoDynamicGenericClass, return its non-inflated type.
2572  */
2573 static MonoType*
2574 get_field_on_inst_generic_type (MonoClassField *field)
2575 {
2576         MonoDynamicGenericClass *dgclass;
2577         int field_index;
2578
2579         g_assert (is_field_on_inst (field));
2580
2581         dgclass = (MonoDynamicGenericClass*)field->parent->generic_class;
2582         field_index = field - dgclass->fields;
2583
2584         g_assert (field_index >= 0 && field_index < dgclass->count_fields);
2585         return dgclass->field_generic_types [field_index];
2586 }
2587
2588 static guint32
2589 mono_image_get_fieldref_token (MonoDynamicImage *assembly, MonoReflectionField *f)
2590 {
2591         MonoType *type;
2592         guint32 token;
2593         MonoClassField *field;
2594
2595         token = GPOINTER_TO_UINT (g_hash_table_lookup (assembly->handleref, f));
2596         if (token)
2597                 return token;
2598         g_assert (f->field->parent);
2599
2600         field = f->field;
2601         if (field->parent->generic_class && field->parent->generic_class->container_class && field->parent->generic_class->container_class->fields) {
2602                 int index = field - field->parent->fields;
2603                 type = field->parent->generic_class->container_class->fields [index].type;
2604         } else {
2605                 if (is_field_on_inst (f->field))
2606                         type = get_field_on_inst_generic_type (f->field);
2607                 else
2608                         type = f->field->type;
2609         }
2610         token = mono_image_get_memberref_token (assembly, &f->field->parent->byval_arg, 
2611                                                                                         mono_field_get_name (f->field),  
2612                                                                                         fieldref_encode_signature (assembly, type));
2613         g_hash_table_insert (assembly->handleref, f, GUINT_TO_POINTER(token));
2614         return token;
2615 }
2616
2617 static guint32
2618 mono_image_get_field_on_inst_token (MonoDynamicImage *assembly, MonoReflectionFieldOnTypeBuilderInst *f)
2619 {
2620         guint32 token;
2621         MonoClass *klass;
2622         MonoGenericClass *gclass;
2623         MonoDynamicGenericClass *dgclass;
2624         MonoReflectionFieldBuilder *fb = f->fb;
2625         char *name;
2626
2627         token = GPOINTER_TO_UINT (g_hash_table_lookup (assembly->handleref, f));
2628         if (token)
2629                 return token;
2630         klass = mono_class_from_mono_type (f->inst->type.type);
2631         gclass = f->inst->type.type->data.generic_class;
2632         g_assert (gclass->is_dynamic);
2633         dgclass = (MonoDynamicGenericClass *) gclass;
2634
2635         name = mono_string_to_utf8 (fb->name);
2636         token = mono_image_get_memberref_token (assembly, &klass->byval_arg, name, 
2637                                                                                         field_encode_signature (assembly, fb));
2638         g_free (name);
2639         g_hash_table_insert (assembly->handleref, f, GUINT_TO_POINTER (token));
2640         return token;
2641 }
2642
2643 static guint32
2644 mono_image_get_ctor_on_inst_token (MonoDynamicImage *assembly, MonoReflectionCtorOnTypeBuilderInst *c, gboolean create_methodspec)
2645 {
2646         guint32 sig, token;
2647         MonoClass *klass;
2648         MonoGenericClass *gclass;
2649         MonoDynamicGenericClass *dgclass;
2650         MonoReflectionCtorBuilder *cb = c->cb;
2651         ReflectionMethodBuilder rmb;
2652         char *name;
2653
2654         /* A ctor cannot be a generic method, so we can ignore create_methodspec */
2655
2656         token = GPOINTER_TO_UINT (g_hash_table_lookup (assembly->handleref, c));
2657         if (token)
2658                 return token;
2659         klass = mono_class_from_mono_type (c->inst->type.type);
2660         gclass = c->inst->type.type->data.generic_class;
2661         g_assert (gclass->is_dynamic);
2662         dgclass = (MonoDynamicGenericClass *) gclass;
2663
2664         reflection_methodbuilder_from_ctor_builder (&rmb, cb);
2665
2666         name = mono_string_to_utf8 (rmb.name);
2667
2668         sig = method_builder_encode_signature (assembly, &rmb);
2669
2670         token = mono_image_get_memberref_token (assembly, &klass->byval_arg, name, sig);
2671         g_free (name);
2672
2673         g_hash_table_insert (assembly->handleref, c, GUINT_TO_POINTER (token));
2674         return token;
2675 }
2676
2677 static guint32
2678 mono_image_get_method_on_inst_token (MonoDynamicImage *assembly, MonoReflectionMethodOnTypeBuilderInst *m, gboolean create_methodspec)
2679 {
2680         guint32 sig, token;
2681         MonoClass *klass;
2682         MonoGenericClass *gclass;
2683         MonoReflectionMethodBuilder *mb = m->mb;
2684         ReflectionMethodBuilder rmb;
2685         char *name;
2686
2687         if (create_methodspec && mb->generic_params)
2688                 // FIXME:
2689                 g_assert_not_reached ();
2690
2691         token = GPOINTER_TO_UINT (g_hash_table_lookup (assembly->handleref, m));
2692         if (token)
2693                 return token;
2694         klass = mono_class_from_mono_type (m->inst->type.type);
2695         gclass = m->inst->type.type->data.generic_class;
2696         g_assert (gclass->is_dynamic);
2697
2698         reflection_methodbuilder_from_method_builder (&rmb, mb);
2699
2700         name = mono_string_to_utf8 (rmb.name);
2701
2702         sig = method_builder_encode_signature (assembly, &rmb);
2703
2704         token = mono_image_get_memberref_token (assembly, &klass->byval_arg, name, sig);
2705         g_free (name);
2706
2707         g_hash_table_insert (assembly->handleref, m, GUINT_TO_POINTER (token));
2708         return token;
2709 }
2710
2711 static guint32
2712 encode_generic_method_sig (MonoDynamicImage *assembly, MonoGenericContext *context)
2713 {
2714         SigBuffer buf;
2715         int i;
2716         guint32 nparams = context->method_inst->type_argc;
2717         guint32 idx;
2718
2719         if (!assembly->save)
2720                 return 0;
2721
2722         sigbuffer_init (&buf, 32);
2723         /*
2724          * FIXME: vararg, explicit_this, differenc call_conv values...
2725          */
2726         sigbuffer_add_value (&buf, 0xa); /* FIXME FIXME FIXME */
2727         sigbuffer_add_value (&buf, nparams);
2728
2729         for (i = 0; i < nparams; i++)
2730                 encode_type (assembly, context->method_inst->type_argv [i], &buf);
2731
2732         idx = sigbuffer_add_to_blob_cached (assembly, &buf);
2733         sigbuffer_free (&buf);
2734         return idx;
2735 }
2736
2737 static guint32
2738 method_encode_methodspec (MonoDynamicImage *assembly, MonoMethod *method)
2739 {
2740         MonoDynamicTable *table;
2741         guint32 *values;
2742         guint32 token, mtoken = 0, sig;
2743         MonoMethodInflated *imethod;
2744         MonoMethod *declaring;
2745
2746         table = &assembly->tables [MONO_TABLE_METHODSPEC];
2747
2748         g_assert (method->is_inflated);
2749         imethod = (MonoMethodInflated *) method;
2750         declaring = imethod->declaring;
2751
2752         sig = method_encode_signature (assembly, mono_method_signature (declaring));
2753         mtoken = mono_image_get_memberref_token (assembly, &method->klass->byval_arg, declaring->name, sig);
2754
2755         if (!mono_method_signature (declaring)->generic_param_count)
2756                 return mtoken;
2757
2758         switch (mono_metadata_token_table (mtoken)) {
2759         case MONO_TABLE_MEMBERREF:
2760                 mtoken = (mono_metadata_token_index (mtoken) << MONO_METHODDEFORREF_BITS) | MONO_METHODDEFORREF_METHODREF;
2761                 break;
2762         case MONO_TABLE_METHOD:
2763                 mtoken = (mono_metadata_token_index (mtoken) << MONO_METHODDEFORREF_BITS) | MONO_METHODDEFORREF_METHODDEF;
2764                 break;
2765         default:
2766                 g_assert_not_reached ();
2767         }
2768
2769         sig = encode_generic_method_sig (assembly, mono_method_get_context (method));
2770
2771         if (assembly->save) {
2772                 alloc_table (table, table->rows + 1);
2773                 values = table->values + table->next_idx * MONO_METHODSPEC_SIZE;
2774                 values [MONO_METHODSPEC_METHOD] = mtoken;
2775                 values [MONO_METHODSPEC_SIGNATURE] = sig;
2776         }
2777
2778         token = MONO_TOKEN_METHOD_SPEC | table->next_idx;
2779         table->next_idx ++;
2780
2781         return token;
2782 }
2783
2784 static guint32
2785 mono_image_get_methodspec_token (MonoDynamicImage *assembly, MonoMethod *method)
2786 {
2787         MonoMethodInflated *imethod;
2788         guint32 token;
2789         
2790         token = GPOINTER_TO_UINT (g_hash_table_lookup (assembly->handleref, method));
2791         if (token)
2792                 return token;
2793
2794         g_assert (method->is_inflated);
2795         imethod = (MonoMethodInflated *) method;
2796
2797         if (mono_method_signature (imethod->declaring)->generic_param_count) {
2798                 token = method_encode_methodspec (assembly, method);
2799         } else {
2800                 guint32 sig = method_encode_signature (
2801                         assembly, mono_method_signature (imethod->declaring));
2802                 token = mono_image_get_memberref_token (
2803                         assembly, &method->klass->byval_arg, method->name, sig);
2804         }
2805
2806         g_hash_table_insert (assembly->handleref, method, GUINT_TO_POINTER(token));
2807         return token;
2808 }
2809
2810 static guint32
2811 mono_image_get_inflated_method_token (MonoDynamicImage *assembly, MonoMethod *m)
2812 {
2813         MonoMethodInflated *imethod = (MonoMethodInflated *) m;
2814         guint32 sig, token;
2815
2816         sig = method_encode_signature (assembly, mono_method_signature (imethod->declaring));
2817         token = mono_image_get_memberref_token (
2818                 assembly, &m->klass->byval_arg, m->name, sig);
2819
2820         return token;
2821 }
2822
2823 static guint32
2824 create_generic_typespec (MonoDynamicImage *assembly, MonoReflectionTypeBuilder *tb)
2825 {
2826         MonoDynamicTable *table;
2827         MonoClass *klass;
2828         guint32 *values;
2829         guint32 token;
2830         SigBuffer buf;
2831         int count, i;
2832
2833         /*
2834          * We're creating a TypeSpec for the TypeBuilder of a generic type declaration,
2835          * ie. what we'd normally use as the generic type in a TypeSpec signature.
2836          * Because of this, we must not insert it into the `typeref' hash table.
2837          */
2838
2839         token = GPOINTER_TO_UINT (g_hash_table_lookup (assembly->typespec, tb->type.type));
2840         if (token)
2841                 return token;
2842
2843         sigbuffer_init (&buf, 32);
2844
2845         g_assert (tb->generic_params);
2846         klass = mono_class_from_mono_type (tb->type.type);
2847
2848         if (tb->generic_container)
2849                 mono_reflection_create_generic_class (tb);
2850
2851         sigbuffer_add_value (&buf, MONO_TYPE_GENERICINST);
2852         g_assert (klass->generic_container);
2853         sigbuffer_add_value (&buf, klass->byval_arg.type);
2854         sigbuffer_add_value (&buf, mono_image_typedef_or_ref_full (assembly, &klass->byval_arg, FALSE));
2855
2856         count = mono_array_length (tb->generic_params);
2857         sigbuffer_add_value (&buf, count);
2858         for (i = 0; i < count; i++) {
2859                 MonoReflectionGenericParam *gparam;
2860
2861                 gparam = mono_array_get (tb->generic_params, MonoReflectionGenericParam *, i);
2862
2863                 encode_type (assembly, gparam->type.type, &buf);
2864         }
2865
2866         table = &assembly->tables [MONO_TABLE_TYPESPEC];
2867
2868         if (assembly->save) {
2869                 token = sigbuffer_add_to_blob_cached (assembly, &buf);
2870                 alloc_table (table, table->rows + 1);
2871                 values = table->values + table->next_idx * MONO_TYPESPEC_SIZE;
2872                 values [MONO_TYPESPEC_SIGNATURE] = token;
2873         }
2874         sigbuffer_free (&buf);
2875
2876         token = MONO_TYPEDEFORREF_TYPESPEC | (table->next_idx << MONO_TYPEDEFORREF_BITS);
2877         g_hash_table_insert (assembly->typespec, tb->type.type, GUINT_TO_POINTER(token));
2878         table->next_idx ++;
2879         return token;
2880 }
2881
2882 /*
2883  * Return a copy of TYPE, adding the custom modifiers in MODREQ and MODOPT.
2884  */
2885 static MonoType*
2886 add_custom_modifiers (MonoDynamicImage *assembly, MonoType *type, MonoArray *modreq, MonoArray *modopt)
2887 {
2888         int i, count, len, pos;
2889         MonoType *t;
2890
2891         count = 0;
2892         if (modreq)
2893                 count += mono_array_length (modreq);
2894         if (modopt)
2895                 count += mono_array_length (modopt);
2896
2897         if (count == 0)
2898                 return mono_metadata_type_dup (NULL, type);
2899
2900         len = sizeof (MonoType) + ((gint32)count - MONO_ZERO_LEN_ARRAY) * sizeof (MonoCustomMod);
2901         t = g_malloc (len);
2902         memcpy (t, type, len);
2903
2904         t->num_mods = count;
2905         pos = 0;
2906         if (modreq) {
2907                 for (i = 0; i < mono_array_length (modreq); ++i) {
2908                         MonoReflectionType *mod = mono_array_get (modreq, MonoReflectionType*, i);
2909                         t->modifiers [pos].required = 1;
2910                         t->modifiers [pos].token = mono_image_typedef_or_ref (assembly, mod->type);
2911                         pos ++;
2912                 }
2913         }
2914         if (modopt) {
2915                 for (i = 0; i < mono_array_length (modopt); ++i) {
2916                         MonoReflectionType *mod = mono_array_get (modopt, MonoReflectionType*, i);
2917                         t->modifiers [pos].required = 0;
2918                         t->modifiers [pos].token = mono_image_typedef_or_ref (assembly, mod->type);
2919                         pos ++;
2920                 }
2921         }
2922
2923         return t;
2924 }
2925
2926 static guint32
2927 mono_image_get_generic_field_token (MonoDynamicImage *assembly, MonoReflectionFieldBuilder *fb)
2928 {
2929         MonoDynamicTable *table;
2930         MonoClass *klass;
2931         MonoType *custom = NULL;
2932         guint32 *values;
2933         guint32 token, pclass, parent, sig;
2934         gchar *name;
2935
2936         token = GPOINTER_TO_UINT (g_hash_table_lookup (assembly->handleref, fb));
2937         if (token)
2938                 return token;
2939
2940         klass = mono_class_from_mono_type (fb->typeb->type);
2941         name = mono_string_to_utf8 (fb->name);
2942
2943         /* fb->type does not include the custom modifiers */
2944         /* FIXME: We should do this in one place when a fieldbuilder is created */
2945         if (fb->modreq || fb->modopt) {
2946                 custom = add_custom_modifiers (assembly, fb->type->type, fb->modreq, fb->modopt);
2947                 sig = fieldref_encode_signature (assembly, custom);
2948                 g_free (custom);
2949         } else {
2950                 sig = fieldref_encode_signature (assembly, fb->type->type);
2951         }
2952
2953         parent = create_generic_typespec (assembly, (MonoReflectionTypeBuilder *) fb->typeb);
2954         g_assert ((parent & MONO_TYPEDEFORREF_MASK) == MONO_TYPEDEFORREF_TYPESPEC);
2955         
2956         pclass = MONO_MEMBERREF_PARENT_TYPESPEC;
2957         parent >>= MONO_TYPEDEFORREF_BITS;
2958
2959         table = &assembly->tables [MONO_TABLE_MEMBERREF];
2960
2961         if (assembly->save) {
2962                 alloc_table (table, table->rows + 1);
2963                 values = table->values + table->next_idx * MONO_MEMBERREF_SIZE;
2964                 values [MONO_MEMBERREF_CLASS] = pclass | (parent << MONO_MEMBERREF_PARENT_BITS);
2965                 values [MONO_MEMBERREF_NAME] = string_heap_insert (&assembly->sheap, name);
2966                 values [MONO_MEMBERREF_SIGNATURE] = sig;
2967         }
2968
2969         token = MONO_TOKEN_MEMBER_REF | table->next_idx;
2970         table->next_idx ++;
2971         g_hash_table_insert (assembly->handleref, fb, GUINT_TO_POINTER(token));
2972         g_free (name);
2973         return token;
2974 }
2975
2976 static guint32
2977 mono_reflection_encode_sighelper (MonoDynamicImage *assembly, MonoReflectionSigHelper *helper)
2978 {
2979         SigBuffer buf;
2980         guint32 nargs;
2981         guint32 size;
2982         guint32 i, idx;
2983
2984         if (!assembly->save)
2985                 return 0;
2986
2987         /* FIXME: this means SignatureHelper.SignatureHelpType.HELPER_METHOD */
2988         g_assert (helper->type == 2);
2989
2990         if (helper->arguments)
2991                 nargs = mono_array_length (helper->arguments);
2992         else
2993                 nargs = 0;
2994
2995         size = 10 + (nargs * 10);
2996         
2997         sigbuffer_init (&buf, 32);
2998
2999         /* Encode calling convention */
3000         /* Change Any to Standard */
3001         if ((helper->call_conv & 0x03) == 0x03)
3002                 helper->call_conv = 0x01;
3003         /* explicit_this implies has_this */
3004         if (helper->call_conv & 0x40)
3005                 helper->call_conv &= 0x20;
3006
3007         if (helper->call_conv == 0) { /* Unmanaged */
3008                 idx = helper->unmanaged_call_conv - 1;
3009         } else {
3010                 /* Managed */
3011                 idx = helper->call_conv & 0x60; /* has_this + explicit_this */
3012                 if (helper->call_conv & 0x02) /* varargs */
3013                         idx += 0x05;
3014         }
3015
3016         sigbuffer_add_byte (&buf, idx);
3017         sigbuffer_add_value (&buf, nargs);
3018         encode_reflection_type (assembly, helper->return_type, &buf);
3019         for (i = 0; i < nargs; ++i) {
3020                 MonoArray *modreqs = NULL;
3021                 MonoArray *modopts = NULL;
3022                 MonoReflectionType *pt;
3023
3024                 if (helper->modreqs && (i < mono_array_length (helper->modreqs)))
3025                         modreqs = mono_array_get (helper->modreqs, MonoArray*, i);
3026                 if (helper->modopts && (i < mono_array_length (helper->modopts)))
3027                         modopts = mono_array_get (helper->modopts, MonoArray*, i);
3028
3029                 encode_custom_modifiers (assembly, modreqs, modopts, &buf);
3030                 pt = mono_array_get (helper->arguments, MonoReflectionType*, i);
3031                 encode_reflection_type (assembly, pt, &buf);
3032         }
3033         idx = sigbuffer_add_to_blob_cached (assembly, &buf);
3034         sigbuffer_free (&buf);
3035
3036         return idx;
3037 }
3038         
3039 static guint32 
3040 mono_image_get_sighelper_token (MonoDynamicImage *assembly, MonoReflectionSigHelper *helper)
3041 {
3042         guint32 idx;
3043         MonoDynamicTable *table;
3044         guint32 *values;
3045
3046         table = &assembly->tables [MONO_TABLE_STANDALONESIG];
3047         idx = table->next_idx ++;
3048         table->rows ++;
3049         alloc_table (table, table->rows);
3050         values = table->values + idx * MONO_STAND_ALONE_SIGNATURE_SIZE;
3051
3052         values [MONO_STAND_ALONE_SIGNATURE] =
3053                 mono_reflection_encode_sighelper (assembly, helper);
3054
3055         return idx;
3056 }
3057
3058 static int
3059 reflection_cc_to_file (int call_conv) {
3060         switch (call_conv & 0x3) {
3061         case 0:
3062         case 1: return MONO_CALL_DEFAULT;
3063         case 2: return MONO_CALL_VARARG;
3064         default:
3065                 g_assert_not_reached ();
3066         }
3067         return 0;
3068 }
3069
3070 typedef struct {
3071         MonoType *parent;
3072         MonoMethodSignature *sig;
3073         char *name;
3074         guint32 token;
3075 } ArrayMethod;
3076
3077 static guint32
3078 mono_image_get_array_token (MonoDynamicImage *assembly, MonoReflectionArrayMethod *m)
3079 {
3080         guint32 nparams, i;
3081         GList *tmp;
3082         char *name;
3083         MonoMethodSignature *sig;
3084         ArrayMethod *am;
3085         
3086         name = mono_string_to_utf8 (m->name);
3087         nparams = mono_array_length (m->parameters);
3088         sig = g_malloc0 (sizeof (MonoMethodSignature) + sizeof (MonoType*) * nparams);
3089         sig->hasthis = 1;
3090         sig->sentinelpos = -1;
3091         sig->call_convention = reflection_cc_to_file (m->call_conv);
3092         sig->param_count = nparams;
3093         sig->ret = m->ret? m->ret->type: &mono_defaults.void_class->byval_arg;
3094         for (i = 0; i < nparams; ++i) {
3095                 MonoReflectionType *t = mono_array_get (m->parameters, gpointer, i);
3096                 sig->params [i] = t->type;
3097         }
3098
3099         for (tmp = assembly->array_methods; tmp; tmp = tmp->next) {
3100                 am = tmp->data;
3101                 if (strcmp (name, am->name) == 0 && 
3102                                 mono_metadata_type_equal (am->parent, m->parent->type) &&
3103                                 mono_metadata_signature_equal (am->sig, sig)) {
3104                         g_free (name);
3105                         g_free (sig);
3106                         m->table_idx = am->token & 0xffffff;
3107                         return am->token;
3108                 }
3109         }
3110         am = g_new0 (ArrayMethod, 1);
3111         am->name = name;
3112         am->sig = sig;
3113         am->parent = m->parent->type;
3114         am->token = mono_image_get_memberref_token (assembly, am->parent, name,
3115                 method_encode_signature (assembly, sig));
3116         assembly->array_methods = g_list_prepend (assembly->array_methods, am);
3117         m->table_idx = am->token & 0xffffff;
3118         return am->token;
3119 }
3120
3121 /*
3122  * Insert into the metadata tables all the info about the TypeBuilder tb.
3123  * Data in the tables is inserted in a predefined order, since some tables need to be sorted.
3124  */
3125 static void
3126 mono_image_get_type_info (MonoDomain *domain, MonoReflectionTypeBuilder *tb, MonoDynamicImage *assembly)
3127 {
3128         MonoDynamicTable *table;
3129         guint *values;
3130         int i, is_object = 0, is_system = 0;
3131         char *n;
3132
3133         table = &assembly->tables [MONO_TABLE_TYPEDEF];
3134         values = table->values + tb->table_idx * MONO_TYPEDEF_SIZE;
3135         values [MONO_TYPEDEF_FLAGS] = tb->attrs;
3136         n = mono_string_to_utf8 (tb->name);
3137         if (strcmp (n, "Object") == 0)
3138                 is_object++;
3139         values [MONO_TYPEDEF_NAME] = string_heap_insert (&assembly->sheap, n);
3140         g_free (n);
3141         n = mono_string_to_utf8 (tb->nspace);
3142         if (strcmp (n, "System") == 0)
3143                 is_system++;
3144         values [MONO_TYPEDEF_NAMESPACE] = string_heap_insert (&assembly->sheap, n);
3145         g_free (n);
3146         if (tb->parent && !(is_system && is_object) && 
3147                         !(tb->attrs & TYPE_ATTRIBUTE_INTERFACE)) { /* interfaces don't have a parent */
3148                 values [MONO_TYPEDEF_EXTENDS] = mono_image_typedef_or_ref (assembly, tb->parent->type);
3149         } else {
3150                 values [MONO_TYPEDEF_EXTENDS] = 0;
3151         }
3152         values [MONO_TYPEDEF_FIELD_LIST] = assembly->tables [MONO_TABLE_FIELD].next_idx;
3153         values [MONO_TYPEDEF_METHOD_LIST] = assembly->tables [MONO_TABLE_METHOD].next_idx;
3154
3155         /*
3156          * if we have explicitlayout or sequentiallayouts, output data in the
3157          * ClassLayout table.
3158          */
3159         if (((tb->attrs & TYPE_ATTRIBUTE_LAYOUT_MASK) != TYPE_ATTRIBUTE_AUTO_LAYOUT) &&
3160                         ((tb->class_size > 0) || (tb->packing_size > 0))) {
3161                 table = &assembly->tables [MONO_TABLE_CLASSLAYOUT];
3162                 table->rows++;
3163                 alloc_table (table, table->rows);
3164                 values = table->values + table->rows * MONO_CLASS_LAYOUT_SIZE;
3165                 values [MONO_CLASS_LAYOUT_PARENT] = tb->table_idx;
3166                 values [MONO_CLASS_LAYOUT_CLASS_SIZE] = tb->class_size;
3167                 values [MONO_CLASS_LAYOUT_PACKING_SIZE] = tb->packing_size;
3168         }
3169
3170         /* handle interfaces */
3171         if (tb->interfaces) {
3172                 table = &assembly->tables [MONO_TABLE_INTERFACEIMPL];
3173                 i = table->rows;
3174                 table->rows += mono_array_length (tb->interfaces);
3175                 alloc_table (table, table->rows);
3176                 values = table->values + (i + 1) * MONO_INTERFACEIMPL_SIZE;
3177                 for (i = 0; i < mono_array_length (tb->interfaces); ++i) {
3178                         MonoReflectionType* iface = (MonoReflectionType*) mono_array_get (tb->interfaces, gpointer, i);
3179                         values [MONO_INTERFACEIMPL_CLASS] = tb->table_idx;
3180                         values [MONO_INTERFACEIMPL_INTERFACE] = mono_image_typedef_or_ref (assembly, iface->type);
3181                         values += MONO_INTERFACEIMPL_SIZE;
3182                 }
3183         }
3184
3185         /* handle fields */
3186         if (tb->fields) {
3187                 table = &assembly->tables [MONO_TABLE_FIELD];
3188                 table->rows += tb->num_fields;
3189                 alloc_table (table, table->rows);
3190                 for (i = 0; i < tb->num_fields; ++i)
3191                         mono_image_get_field_info (
3192                                 mono_array_get (tb->fields, MonoReflectionFieldBuilder*, i), assembly);
3193         }
3194
3195         /* handle constructors */
3196         if (tb->ctors) {
3197                 table = &assembly->tables [MONO_TABLE_METHOD];
3198                 table->rows += mono_array_length (tb->ctors);
3199                 alloc_table (table, table->rows);
3200                 for (i = 0; i < mono_array_length (tb->ctors); ++i)
3201                         mono_image_get_ctor_info (domain,
3202                                 mono_array_get (tb->ctors, MonoReflectionCtorBuilder*, i), assembly);
3203         }
3204
3205         /* handle methods */
3206         if (tb->methods) {
3207                 table = &assembly->tables [MONO_TABLE_METHOD];
3208                 table->rows += tb->num_methods;
3209                 alloc_table (table, table->rows);
3210                 for (i = 0; i < tb->num_methods; ++i)
3211                         mono_image_get_method_info (
3212                                 mono_array_get (tb->methods, MonoReflectionMethodBuilder*, i), assembly);
3213         }
3214
3215         /* Do the same with properties etc.. */
3216         if (tb->events && mono_array_length (tb->events)) {
3217                 table = &assembly->tables [MONO_TABLE_EVENT];
3218                 table->rows += mono_array_length (tb->events);
3219                 alloc_table (table, table->rows);
3220                 table = &assembly->tables [MONO_TABLE_EVENTMAP];
3221                 table->rows ++;
3222                 alloc_table (table, table->rows);
3223                 values = table->values + table->rows * MONO_EVENT_MAP_SIZE;
3224                 values [MONO_EVENT_MAP_PARENT] = tb->table_idx;
3225                 values [MONO_EVENT_MAP_EVENTLIST] = assembly->tables [MONO_TABLE_EVENT].next_idx;
3226                 for (i = 0; i < mono_array_length (tb->events); ++i)
3227                         mono_image_get_event_info (
3228                                 mono_array_get (tb->events, MonoReflectionEventBuilder*, i), assembly);
3229         }
3230         if (tb->properties && mono_array_length (tb->properties)) {
3231                 table = &assembly->tables [MONO_TABLE_PROPERTY];
3232                 table->rows += mono_array_length (tb->properties);
3233                 alloc_table (table, table->rows);
3234                 table = &assembly->tables [MONO_TABLE_PROPERTYMAP];
3235                 table->rows ++;
3236                 alloc_table (table, table->rows);
3237                 values = table->values + table->rows * MONO_PROPERTY_MAP_SIZE;
3238                 values [MONO_PROPERTY_MAP_PARENT] = tb->table_idx;
3239                 values [MONO_PROPERTY_MAP_PROPERTY_LIST] = assembly->tables [MONO_TABLE_PROPERTY].next_idx;
3240                 for (i = 0; i < mono_array_length (tb->properties); ++i)
3241                         mono_image_get_property_info (
3242                                 mono_array_get (tb->properties, MonoReflectionPropertyBuilder*, i), assembly);
3243         }
3244
3245         /* handle generic parameters */
3246         if (tb->generic_params) {
3247                 table = &assembly->tables [MONO_TABLE_GENERICPARAM];
3248                 table->rows += mono_array_length (tb->generic_params);
3249                 alloc_table (table, table->rows);
3250                 for (i = 0; i < mono_array_length (tb->generic_params); ++i) {
3251                         guint32 owner = MONO_TYPEORMETHOD_TYPE | (tb->table_idx << MONO_TYPEORMETHOD_BITS);
3252
3253                         mono_image_get_generic_param_info (
3254                                 mono_array_get (tb->generic_params, MonoReflectionGenericParam*, i), owner, assembly);
3255                 }
3256         }
3257
3258         mono_image_add_decl_security (assembly, 
3259                 mono_metadata_make_token (MONO_TABLE_TYPEDEF, tb->table_idx), tb->permissions);
3260
3261         if (tb->subtypes) {
3262                 MonoDynamicTable *ntable;
3263                 
3264                 ntable = &assembly->tables [MONO_TABLE_NESTEDCLASS];
3265                 ntable->rows += mono_array_length (tb->subtypes);
3266                 alloc_table (ntable, ntable->rows);
3267                 values = ntable->values + ntable->next_idx * MONO_NESTED_CLASS_SIZE;
3268
3269                 for (i = 0; i < mono_array_length (tb->subtypes); ++i) {
3270                         MonoReflectionTypeBuilder *subtype = mono_array_get (tb->subtypes, MonoReflectionTypeBuilder*, i);
3271
3272                         values [MONO_NESTED_CLASS_NESTED] = subtype->table_idx;
3273                         values [MONO_NESTED_CLASS_ENCLOSING] = tb->table_idx;
3274                         /*g_print ("nesting %s (%d) in %s (%d) (rows %d/%d)\n",
3275                                 mono_string_to_utf8 (subtype->name), subtype->table_idx,
3276                                 mono_string_to_utf8 (tb->name), tb->table_idx,
3277                                 ntable->next_idx, ntable->rows);*/
3278                         values += MONO_NESTED_CLASS_SIZE;
3279                         ntable->next_idx++;
3280                 }
3281         }
3282 }
3283
3284 static void
3285 collect_types (GPtrArray *types, MonoReflectionTypeBuilder *type)
3286 {
3287         int i;
3288
3289         g_ptr_array_add (types, type); /* FIXME: GC object added to unmanaged memory */
3290
3291         if (!type->subtypes)
3292                 return;
3293
3294         for (i = 0; i < mono_array_length (type->subtypes); ++i) {
3295                 MonoReflectionTypeBuilder *subtype = mono_array_get (type->subtypes, MonoReflectionTypeBuilder*, i);
3296                 collect_types (types, subtype);
3297         }
3298 }
3299
3300 static gint
3301 compare_types_by_table_idx (MonoReflectionTypeBuilder **type1, MonoReflectionTypeBuilder **type2)
3302 {
3303         if ((*type1)->table_idx < (*type2)->table_idx)
3304                 return -1;
3305         else
3306                 if ((*type1)->table_idx > (*type2)->table_idx)
3307                         return 1;
3308         else
3309                 return 0;
3310 }
3311
3312 static void
3313 params_add_cattrs (MonoDynamicImage *assembly, MonoArray *pinfo) {
3314         int i;
3315
3316         if (!pinfo)
3317                 return;
3318         for (i = 0; i < mono_array_length (pinfo); ++i) {
3319                 MonoReflectionParamBuilder *pb;
3320                 pb = mono_array_get (pinfo, MonoReflectionParamBuilder *, i);
3321                 if (!pb)
3322                         continue;
3323                 mono_image_add_cattrs (assembly, pb->table_idx, MONO_CUSTOM_ATTR_PARAMDEF, pb->cattrs);
3324         }
3325 }
3326
3327 static void
3328 type_add_cattrs (MonoDynamicImage *assembly, MonoReflectionTypeBuilder *tb) {
3329         int i;
3330         
3331         mono_image_add_cattrs (assembly, tb->table_idx, MONO_CUSTOM_ATTR_TYPEDEF, tb->cattrs);
3332         if (tb->fields) {
3333                 for (i = 0; i < tb->num_fields; ++i) {
3334                         MonoReflectionFieldBuilder* fb;
3335                         fb = mono_array_get (tb->fields, MonoReflectionFieldBuilder*, i);
3336                         mono_image_add_cattrs (assembly, fb->table_idx, MONO_CUSTOM_ATTR_FIELDDEF, fb->cattrs);
3337                 }
3338         }
3339         if (tb->events) {
3340                 for (i = 0; i < mono_array_length (tb->events); ++i) {
3341                         MonoReflectionEventBuilder* eb;
3342                         eb = mono_array_get (tb->events, MonoReflectionEventBuilder*, i);
3343                         mono_image_add_cattrs (assembly, eb->table_idx, MONO_CUSTOM_ATTR_EVENT, eb->cattrs);
3344                 }
3345         }
3346         if (tb->properties) {
3347                 for (i = 0; i < mono_array_length (tb->properties); ++i) {
3348                         MonoReflectionPropertyBuilder* pb;
3349                         pb = mono_array_get (tb->properties, MonoReflectionPropertyBuilder*, i);
3350                         mono_image_add_cattrs (assembly, pb->table_idx, MONO_CUSTOM_ATTR_PROPERTY, pb->cattrs);
3351                 }
3352         }
3353         if (tb->ctors) {
3354                 for (i = 0; i < mono_array_length (tb->ctors); ++i) {
3355                         MonoReflectionCtorBuilder* cb;
3356                         cb = mono_array_get (tb->ctors, MonoReflectionCtorBuilder*, i);
3357                         mono_image_add_cattrs (assembly, cb->table_idx, MONO_CUSTOM_ATTR_METHODDEF, cb->cattrs);
3358                         params_add_cattrs (assembly, cb->pinfo);
3359                 }
3360         }
3361
3362         if (tb->methods) {
3363                 for (i = 0; i < tb->num_methods; ++i) {
3364                         MonoReflectionMethodBuilder* mb;
3365                         mb = mono_array_get (tb->methods, MonoReflectionMethodBuilder*, i);
3366                         mono_image_add_cattrs (assembly, mb->table_idx, MONO_CUSTOM_ATTR_METHODDEF, mb->cattrs);
3367                         params_add_cattrs (assembly, mb->pinfo);
3368                 }
3369         }
3370
3371         if (tb->subtypes) {
3372                 for (i = 0; i < mono_array_length (tb->subtypes); ++i)
3373                         type_add_cattrs (assembly, mono_array_get (tb->subtypes, MonoReflectionTypeBuilder*, i));
3374         }
3375 }
3376
3377 static void
3378 module_add_cattrs (MonoDynamicImage *assembly, MonoReflectionModuleBuilder *moduleb)
3379 {
3380         int i;
3381         
3382         mono_image_add_cattrs (assembly, moduleb->table_idx, MONO_CUSTOM_ATTR_MODULE, moduleb->cattrs);
3383
3384         if (moduleb->global_methods) {
3385                 for (i = 0; i < mono_array_length (moduleb->global_methods); ++i) {
3386                         MonoReflectionMethodBuilder* mb = mono_array_get (moduleb->global_methods, MonoReflectionMethodBuilder*, i);
3387                         mono_image_add_cattrs (assembly, mb->table_idx, MONO_CUSTOM_ATTR_METHODDEF, mb->cattrs);
3388                         params_add_cattrs (assembly, mb->pinfo);
3389                 }
3390         }
3391
3392         if (moduleb->global_fields) {
3393                 for (i = 0; i < mono_array_length (moduleb->global_fields); ++i) {
3394                         MonoReflectionFieldBuilder *fb = mono_array_get (moduleb->global_fields, MonoReflectionFieldBuilder*, i);
3395                         mono_image_add_cattrs (assembly, fb->table_idx, MONO_CUSTOM_ATTR_FIELDDEF, fb->cattrs);
3396                 }
3397         }
3398         
3399         if (moduleb->types) {
3400                 for (i = 0; i < moduleb->num_types; ++i)
3401                         type_add_cattrs (assembly, mono_array_get (moduleb->types, MonoReflectionTypeBuilder*, i));
3402         }
3403 }
3404
3405 static void
3406 mono_image_fill_file_table (MonoDomain *domain, MonoReflectionModule *module, MonoDynamicImage *assembly)
3407 {
3408         MonoDynamicTable *table;
3409         guint32 *values;
3410         char blob_size [6];
3411         guchar hash [20];
3412         char *b = blob_size;
3413         char *dir, *path;
3414
3415         table = &assembly->tables [MONO_TABLE_FILE];
3416         table->rows++;
3417         alloc_table (table, table->rows);
3418         values = table->values + table->next_idx * MONO_FILE_SIZE;
3419         values [MONO_FILE_FLAGS] = FILE_CONTAINS_METADATA;
3420         values [MONO_FILE_NAME] = string_heap_insert (&assembly->sheap, module->image->module_name);
3421         if (module->image->dynamic) {
3422                 /* This depends on the fact that the main module is emitted last */
3423                 dir = mono_string_to_utf8 (((MonoReflectionModuleBuilder*)module)->assemblyb->dir);
3424                 path = g_strdup_printf ("%s%c%s", dir, G_DIR_SEPARATOR, module->image->module_name);
3425         } else {
3426                 dir = NULL;
3427                 path = g_strdup (module->image->name);
3428         }
3429         mono_sha1_get_digest_from_file (path, hash);
3430         g_free (dir);
3431         g_free (path);
3432         mono_metadata_encode_value (20, b, &b);
3433         values [MONO_FILE_HASH_VALUE] = mono_image_add_stream_data (&assembly->blob, blob_size, b-blob_size);
3434         mono_image_add_stream_data (&assembly->blob, (char*)hash, 20);
3435         table->next_idx ++;
3436 }
3437
3438 static void
3439 mono_image_fill_module_table (MonoDomain *domain, MonoReflectionModuleBuilder *mb, MonoDynamicImage *assembly)
3440 {
3441         MonoDynamicTable *table;
3442         int i;
3443
3444         table = &assembly->tables [MONO_TABLE_MODULE];
3445         mb->table_idx = table->next_idx ++;
3446         table->values [mb->table_idx * MONO_MODULE_SIZE + MONO_MODULE_NAME] = string_heap_insert_mstring (&assembly->sheap, mb->module.name);
3447         i = mono_image_add_stream_data (&assembly->guid, mono_array_addr (mb->guid, char, 0), 16);
3448         i /= 16;
3449         ++i;
3450         table->values [mb->table_idx * MONO_MODULE_SIZE + MONO_MODULE_GENERATION] = 0;
3451         table->values [mb->table_idx * MONO_MODULE_SIZE + MONO_MODULE_MVID] = i;
3452         table->values [mb->table_idx * MONO_MODULE_SIZE + MONO_MODULE_ENC] = 0;
3453         table->values [mb->table_idx * MONO_MODULE_SIZE + MONO_MODULE_ENCBASE] = 0;
3454 }
3455
3456 static guint32
3457 mono_image_fill_export_table_from_class (MonoDomain *domain, MonoClass *klass,
3458         guint32 module_index, guint32 parent_index, MonoDynamicImage *assembly)
3459 {
3460         MonoDynamicTable *table;
3461         guint32 *values;
3462         guint32 visib, res;
3463
3464         visib = klass->flags & TYPE_ATTRIBUTE_VISIBILITY_MASK;
3465         if (! ((visib & TYPE_ATTRIBUTE_PUBLIC) || (visib & TYPE_ATTRIBUTE_NESTED_PUBLIC)))
3466                 return 0;
3467
3468         table = &assembly->tables [MONO_TABLE_EXPORTEDTYPE];
3469         table->rows++;
3470         alloc_table (table, table->rows);
3471         values = table->values + table->next_idx * MONO_EXP_TYPE_SIZE;
3472
3473         values [MONO_EXP_TYPE_FLAGS] = klass->flags;
3474         values [MONO_EXP_TYPE_TYPEDEF] = klass->type_token;
3475         if (klass->nested_in)
3476                 values [MONO_EXP_TYPE_IMPLEMENTATION] = (parent_index << MONO_IMPLEMENTATION_BITS) + MONO_IMPLEMENTATION_EXP_TYPE;
3477         else
3478                 values [MONO_EXP_TYPE_IMPLEMENTATION] = (module_index << MONO_IMPLEMENTATION_BITS) + MONO_IMPLEMENTATION_FILE;
3479         values [MONO_EXP_TYPE_NAME] = string_heap_insert (&assembly->sheap, klass->name);
3480         values [MONO_EXP_TYPE_NAMESPACE] = string_heap_insert (&assembly->sheap, klass->name_space);
3481
3482         res = table->next_idx;
3483
3484         table->next_idx ++;
3485
3486         /* Emit nested types */
3487         if (klass->ext && klass->ext->nested_classes) {
3488                 GList *tmp;
3489
3490                 for (tmp = klass->ext->nested_classes; tmp; tmp = tmp->next)
3491                         mono_image_fill_export_table_from_class (domain, tmp->data, module_index, table->next_idx - 1, assembly);
3492         }
3493
3494         return res;
3495 }
3496
3497 static void
3498 mono_image_fill_export_table (MonoDomain *domain, MonoReflectionTypeBuilder *tb,
3499         guint32 module_index, guint32 parent_index, MonoDynamicImage *assembly)
3500 {
3501         MonoClass *klass;
3502         guint32 idx, i;
3503
3504         klass = mono_class_from_mono_type (tb->type.type);
3505
3506         klass->type_token = mono_metadata_make_token (MONO_TABLE_TYPEDEF, tb->table_idx);
3507
3508         idx = mono_image_fill_export_table_from_class (domain, klass, module_index, 
3509                                                                                                    parent_index, assembly);
3510
3511         /* 
3512          * Emit nested types
3513          * We need to do this ourselves since klass->nested_classes is not set up.
3514          */
3515         if (tb->subtypes) {
3516                 for (i = 0; i < mono_array_length (tb->subtypes); ++i)
3517                         mono_image_fill_export_table (domain, mono_array_get (tb->subtypes, MonoReflectionTypeBuilder*, i), module_index, idx, assembly);
3518         }
3519 }
3520
3521 static void
3522 mono_image_fill_export_table_from_module (MonoDomain *domain, MonoReflectionModule *module,
3523         guint32 module_index, MonoDynamicImage *assembly)
3524 {
3525         MonoImage *image = module->image;
3526         MonoTableInfo  *t;
3527         guint32 i;
3528
3529         t = &image->tables [MONO_TABLE_TYPEDEF];
3530
3531         for (i = 0; i < t->rows; ++i) {
3532                 MonoClass *klass = mono_class_get (image, mono_metadata_make_token (MONO_TABLE_TYPEDEF, i + 1));
3533
3534                 if (klass->flags & TYPE_ATTRIBUTE_PUBLIC)
3535                         mono_image_fill_export_table_from_class (domain, klass, module_index, 0, assembly);
3536         }
3537 }
3538
3539 static void
3540 mono_image_fill_export_table_from_type_forwarders (MonoReflectionAssemblyBuilder *assemblyb, MonoDynamicImage *assembly)
3541 {
3542         MonoDynamicTable *table;
3543         MonoClass *klass;
3544         guint32 *values;
3545         guint32 scope, idx;
3546         int i;
3547
3548         table = &assembly->tables [MONO_TABLE_EXPORTEDTYPE];
3549
3550         if (assemblyb->type_forwarders) {
3551                 for (i = 0; i < mono_array_length (assemblyb->type_forwarders); ++i) {
3552                         MonoReflectionType *t = mono_array_get (assemblyb->type_forwarders, MonoReflectionType*, i);
3553                         if (!t)
3554                                 continue;
3555
3556                         g_assert (t->type);
3557
3558                         klass = mono_class_from_mono_type (t->type);
3559
3560                         scope = resolution_scope_from_image (assembly, klass->image);
3561                         g_assert ((scope & MONO_RESOLTION_SCOPE_MASK) == MONO_RESOLTION_SCOPE_ASSEMBLYREF);
3562                         idx = scope >> MONO_RESOLTION_SCOPE_BITS;
3563
3564                         table->rows++;
3565                         alloc_table (table, table->rows);
3566                         values = table->values + table->next_idx * MONO_EXP_TYPE_SIZE;
3567
3568                         values [MONO_EXP_TYPE_FLAGS] = TYPE_ATTRIBUTE_FORWARDER;
3569                         values [MONO_EXP_TYPE_TYPEDEF] = 0;
3570                         values [MONO_EXP_TYPE_IMPLEMENTATION] = (idx << MONO_IMPLEMENTATION_BITS) + MONO_IMPLEMENTATION_ASSEMBLYREF;
3571                         values [MONO_EXP_TYPE_NAME] = string_heap_insert (&assembly->sheap, klass->name);
3572                         values [MONO_EXP_TYPE_NAMESPACE] = string_heap_insert (&assembly->sheap, klass->name_space);
3573
3574                         table->next_idx++;
3575                 }
3576         }
3577 }
3578
3579 #define align_pointer(base,p)\
3580         do {\
3581                 guint32 __diff = (unsigned char*)(p)-(unsigned char*)(base);\
3582                 if (__diff & 3)\
3583                         (p) += 4 - (__diff & 3);\
3584         } while (0)
3585
3586 static int
3587 compare_constants (const void *a, const void *b)
3588 {
3589         const guint32 *a_values = a;
3590         const guint32 *b_values = b;
3591         return a_values [MONO_CONSTANT_PARENT] - b_values [MONO_CONSTANT_PARENT];
3592 }
3593
3594 static int
3595 compare_semantics (const void *a, const void *b)
3596 {
3597         const guint32 *a_values = a;
3598         const guint32 *b_values = b;
3599         int assoc = a_values [MONO_METHOD_SEMA_ASSOCIATION] - b_values [MONO_METHOD_SEMA_ASSOCIATION];
3600         if (assoc)
3601                 return assoc;
3602         return a_values [MONO_METHOD_SEMA_SEMANTICS] - b_values [MONO_METHOD_SEMA_SEMANTICS];
3603 }
3604
3605 static int
3606 compare_custom_attrs (const void *a, const void *b)
3607 {
3608         const guint32 *a_values = a;
3609         const guint32 *b_values = b;
3610
3611         return a_values [MONO_CUSTOM_ATTR_PARENT] - b_values [MONO_CUSTOM_ATTR_PARENT];
3612 }
3613
3614 static int
3615 compare_field_marshal (const void *a, const void *b)
3616 {
3617         const guint32 *a_values = a;
3618         const guint32 *b_values = b;
3619
3620         return a_values [MONO_FIELD_MARSHAL_PARENT] - b_values [MONO_FIELD_MARSHAL_PARENT];
3621 }
3622
3623 static int
3624 compare_nested (const void *a, const void *b)
3625 {
3626         const guint32 *a_values = a;
3627         const guint32 *b_values = b;
3628
3629         return a_values [MONO_NESTED_CLASS_NESTED] - b_values [MONO_NESTED_CLASS_NESTED];
3630 }
3631
3632 static int
3633 compare_genericparam (const void *a, const void *b)
3634 {
3635         const GenericParamTableEntry **a_entry = (const GenericParamTableEntry **) a;
3636         const GenericParamTableEntry **b_entry = (const GenericParamTableEntry **) b;
3637
3638         if ((*b_entry)->owner == (*a_entry)->owner)
3639                 return 
3640                         (*a_entry)->gparam->type.type->data.generic_param->num - 
3641                         (*b_entry)->gparam->type.type->data.generic_param->num;
3642         else
3643                 return (*a_entry)->owner - (*b_entry)->owner;
3644 }
3645
3646 static int
3647 compare_declsecurity_attrs (const void *a, const void *b)
3648 {
3649         const guint32 *a_values = a;
3650         const guint32 *b_values = b;
3651
3652         return a_values [MONO_DECL_SECURITY_PARENT] - b_values [MONO_DECL_SECURITY_PARENT];
3653 }
3654
3655 static int
3656 compare_interface_impl (const void *a, const void *b)
3657 {
3658         const guint32 *a_values = a;
3659         const guint32 *b_values = b;
3660
3661         int klass = a_values [MONO_INTERFACEIMPL_CLASS] - b_values [MONO_INTERFACEIMPL_CLASS];
3662         if (klass)
3663                 return klass;
3664
3665         return a_values [MONO_INTERFACEIMPL_INTERFACE] - b_values [MONO_INTERFACEIMPL_INTERFACE];
3666 }
3667
3668 static void
3669 pad_heap (MonoDynamicStream *sh)
3670 {
3671         if (sh->index & 3) {
3672                 int sz = 4 - (sh->index & 3);
3673                 memset (sh->data + sh->index, 0, sz);
3674                 sh->index += sz;
3675         }
3676 }
3677
3678 struct StreamDesc {
3679         const char *name;
3680         MonoDynamicStream *stream;
3681 };
3682
3683 /*
3684  * build_compressed_metadata() fills in the blob of data that represents the 
3685  * raw metadata as it will be saved in the PE file. The five streams are output 
3686  * and the metadata tables are comnpressed from the guint32 array representation, 
3687  * to the compressed on-disk format.
3688  */
3689 static void
3690 build_compressed_metadata (MonoDynamicImage *assembly)
3691 {
3692         MonoDynamicTable *table;
3693         int i;
3694         guint64 valid_mask = 0;
3695         guint64 sorted_mask;
3696         guint32 heapt_size = 0;
3697         guint32 meta_size = 256; /* allow for header and other stuff */
3698         guint32 table_offset;
3699         guint32 ntables = 0;
3700         guint64 *int64val;
3701         guint32 *int32val;
3702         guint16 *int16val;
3703         MonoImage *meta;
3704         unsigned char *p;
3705         struct StreamDesc stream_desc [5];
3706
3707         qsort (assembly->gen_params->pdata, assembly->gen_params->len, sizeof (gpointer), compare_genericparam);
3708         for (i = 0; i < assembly->gen_params->len; i++){
3709                 GenericParamTableEntry *entry = g_ptr_array_index (assembly->gen_params, i);
3710                 write_generic_param_entry (assembly, entry);
3711         }
3712
3713         stream_desc [0].name  = "#~";
3714         stream_desc [0].stream = &assembly->tstream;
3715         stream_desc [1].name  = "#Strings";
3716         stream_desc [1].stream = &assembly->sheap;
3717         stream_desc [2].name  = "#US";
3718         stream_desc [2].stream = &assembly->us;
3719         stream_desc [3].name  = "#Blob";
3720         stream_desc [3].stream = &assembly->blob;
3721         stream_desc [4].name  = "#GUID";
3722         stream_desc [4].stream = &assembly->guid;
3723         
3724         /* tables that are sorted */
3725         sorted_mask = ((guint64)1 << MONO_TABLE_CONSTANT) | ((guint64)1 << MONO_TABLE_FIELDMARSHAL)
3726                 | ((guint64)1 << MONO_TABLE_METHODSEMANTICS) | ((guint64)1 << MONO_TABLE_CLASSLAYOUT)
3727                 | ((guint64)1 << MONO_TABLE_FIELDLAYOUT) | ((guint64)1 << MONO_TABLE_FIELDRVA)
3728                 | ((guint64)1 << MONO_TABLE_IMPLMAP) | ((guint64)1 << MONO_TABLE_NESTEDCLASS)
3729                 | ((guint64)1 << MONO_TABLE_METHODIMPL) | ((guint64)1 << MONO_TABLE_CUSTOMATTRIBUTE)
3730                 | ((guint64)1 << MONO_TABLE_DECLSECURITY) | ((guint64)1 << MONO_TABLE_GENERICPARAM)
3731                 | ((guint64)1 << MONO_TABLE_INTERFACEIMPL);
3732         
3733         /* Compute table sizes */
3734         /* the MonoImage has already been created in mono_image_basic_init() */
3735         meta = &assembly->image;
3736
3737         /* sizes should be multiple of 4 */
3738         pad_heap (&assembly->blob);
3739         pad_heap (&assembly->guid);
3740         pad_heap (&assembly->sheap);
3741         pad_heap (&assembly->us);
3742
3743         /* Setup the info used by compute_sizes () */
3744         meta->idx_blob_wide = assembly->blob.index >= 65536 ? 1 : 0;
3745         meta->idx_guid_wide = assembly->guid.index >= 65536 ? 1 : 0;
3746         meta->idx_string_wide = assembly->sheap.index >= 65536 ? 1 : 0;
3747
3748         meta_size += assembly->blob.index;
3749         meta_size += assembly->guid.index;
3750         meta_size += assembly->sheap.index;
3751         meta_size += assembly->us.index;
3752
3753         for (i=0; i < MONO_TABLE_NUM; ++i)
3754                 meta->tables [i].rows = assembly->tables [i].rows;
3755         
3756         for (i = 0; i < MONO_TABLE_NUM; i++){
3757                 if (meta->tables [i].rows == 0)
3758                         continue;
3759                 valid_mask |= (guint64)1 << i;
3760                 ntables ++;
3761                 meta->tables [i].row_size = mono_metadata_compute_size (
3762                         meta, i, &meta->tables [i].size_bitfield);
3763                 heapt_size += meta->tables [i].row_size * meta->tables [i].rows;
3764         }
3765         heapt_size += 24; /* #~ header size */
3766         heapt_size += ntables * 4;
3767         /* make multiple of 4 */
3768         heapt_size += 3;
3769         heapt_size &= ~3;
3770         meta_size += heapt_size;
3771         meta->raw_metadata = g_malloc0 (meta_size);
3772         p = (unsigned char*)meta->raw_metadata;
3773         /* the metadata signature */
3774         *p++ = 'B'; *p++ = 'S'; *p++ = 'J'; *p++ = 'B';
3775         /* version numbers and 4 bytes reserved */
3776         int16val = (guint16*)p;
3777         *int16val++ = GUINT16_TO_LE (meta->md_version_major);
3778         *int16val = GUINT16_TO_LE (meta->md_version_minor);
3779         p += 8;
3780         /* version string */
3781         int32val = (guint32*)p;
3782         *int32val = GUINT32_TO_LE ((strlen (meta->version) + 3) & (~3)); /* needs to be multiple of 4 */
3783         p += 4;
3784         memcpy (p, meta->version, strlen (meta->version));
3785         p += GUINT32_FROM_LE (*int32val);
3786         align_pointer (meta->raw_metadata, p);
3787         int16val = (guint16*)p;
3788         *int16val++ = GUINT16_TO_LE (0); /* flags must be 0 */
3789         *int16val = GUINT16_TO_LE (5); /* number of streams */
3790         p += 4;
3791
3792         /*
3793          * write the stream info.
3794          */
3795         table_offset = (p - (unsigned char*)meta->raw_metadata) + 5 * 8 + 40; /* room needed for stream headers */
3796         table_offset += 3; table_offset &= ~3;
3797
3798         assembly->tstream.index = heapt_size;
3799         for (i = 0; i < 5; ++i) {
3800                 int32val = (guint32*)p;
3801                 stream_desc [i].stream->offset = table_offset;
3802                 *int32val++ = GUINT32_TO_LE (table_offset);
3803                 *int32val = GUINT32_TO_LE (stream_desc [i].stream->index);
3804                 table_offset += GUINT32_FROM_LE (*int32val);
3805                 table_offset += 3; table_offset &= ~3;
3806                 p += 8;
3807                 strcpy ((char*)p, stream_desc [i].name);
3808                 p += strlen (stream_desc [i].name) + 1;
3809                 align_pointer (meta->raw_metadata, p);
3810         }
3811         /* 
3812          * now copy the data, the table stream header and contents goes first.
3813          */
3814         g_assert ((p - (unsigned char*)meta->raw_metadata) < assembly->tstream.offset);
3815         p = (guchar*)meta->raw_metadata + assembly->tstream.offset;
3816         int32val = (guint32*)p;
3817         *int32val = GUINT32_TO_LE (0); /* reserved */
3818         p += 4;
3819
3820         if (mono_framework_version () > 1) {
3821                 *p++ = 2; /* version */
3822                 *p++ = 0;
3823         } else {
3824                 *p++ = 1; /* version */
3825                 *p++ = 0;
3826         }
3827
3828         if (meta->idx_string_wide)
3829                 *p |= 0x01;
3830         if (meta->idx_guid_wide)
3831                 *p |= 0x02;
3832         if (meta->idx_blob_wide)
3833                 *p |= 0x04;
3834         ++p;
3835         *p++ = 1; /* reserved */
3836         int64val = (guint64*)p;
3837         *int64val++ = GUINT64_TO_LE (valid_mask);
3838         *int64val++ = GUINT64_TO_LE (valid_mask & sorted_mask); /* bitvector of sorted tables  */
3839         p += 16;
3840         int32val = (guint32*)p;
3841         for (i = 0; i < MONO_TABLE_NUM; i++){
3842                 if (meta->tables [i].rows == 0)
3843                         continue;
3844                 *int32val++ = GUINT32_TO_LE (meta->tables [i].rows);
3845         }
3846         p = (unsigned char*)int32val;
3847
3848         /* sort the tables that still need sorting */
3849         table = &assembly->tables [MONO_TABLE_CONSTANT];
3850         if (table->rows)
3851                 qsort (table->values + MONO_CONSTANT_SIZE, table->rows, sizeof (guint32) * MONO_CONSTANT_SIZE, compare_constants);
3852         table = &assembly->tables [MONO_TABLE_METHODSEMANTICS];
3853         if (table->rows)
3854                 qsort (table->values + MONO_METHOD_SEMA_SIZE, table->rows, sizeof (guint32) * MONO_METHOD_SEMA_SIZE, compare_semantics);
3855         table = &assembly->tables [MONO_TABLE_CUSTOMATTRIBUTE];
3856         if (table->rows)
3857                 qsort (table->values + MONO_CUSTOM_ATTR_SIZE, table->rows, sizeof (guint32) * MONO_CUSTOM_ATTR_SIZE, compare_custom_attrs);
3858         table = &assembly->tables [MONO_TABLE_FIELDMARSHAL];
3859         if (table->rows)
3860                 qsort (table->values + MONO_FIELD_MARSHAL_SIZE, table->rows, sizeof (guint32) * MONO_FIELD_MARSHAL_SIZE, compare_field_marshal);
3861         table = &assembly->tables [MONO_TABLE_NESTEDCLASS];
3862         if (table->rows)
3863                 qsort (table->values + MONO_NESTED_CLASS_SIZE, table->rows, sizeof (guint32) * MONO_NESTED_CLASS_SIZE, compare_nested);
3864         /* Section 21.11 DeclSecurity in Partition II doesn't specify this to be sorted by MS implementation requires it */
3865         table = &assembly->tables [MONO_TABLE_DECLSECURITY];
3866         if (table->rows)
3867                 qsort (table->values + MONO_DECL_SECURITY_SIZE, table->rows, sizeof (guint32) * MONO_DECL_SECURITY_SIZE, compare_declsecurity_attrs);
3868         table = &assembly->tables [MONO_TABLE_INTERFACEIMPL];
3869         if (table->rows)
3870                 qsort (table->values + MONO_INTERFACEIMPL_SIZE, table->rows, sizeof (guint32) * MONO_INTERFACEIMPL_SIZE, compare_interface_impl);
3871
3872         /* compress the tables */
3873         for (i = 0; i < MONO_TABLE_NUM; i++){
3874                 int row, col;
3875                 guint32 *values;
3876                 guint32 bitfield = meta->tables [i].size_bitfield;
3877                 if (!meta->tables [i].rows)
3878                         continue;
3879                 if (assembly->tables [i].columns != mono_metadata_table_count (bitfield))
3880                         g_error ("col count mismatch in %d: %d %d", i, assembly->tables [i].columns, mono_metadata_table_count (bitfield));
3881                 meta->tables [i].base = (char*)p;
3882                 for (row = 1; row <= meta->tables [i].rows; ++row) {
3883                         values = assembly->tables [i].values + row * assembly->tables [i].columns;
3884                         for (col = 0; col < assembly->tables [i].columns; ++col) {
3885                                 switch (mono_metadata_table_size (bitfield, col)) {
3886                                 case 1:
3887                                         *p++ = values [col];
3888                                         break;
3889                                 case 2:
3890                                         *p++ = values [col] & 0xff;
3891                                         *p++ = (values [col] >> 8) & 0xff;
3892                                         break;
3893                                 case 4:
3894                                         *p++ = values [col] & 0xff;
3895                                         *p++ = (values [col] >> 8) & 0xff;
3896                                         *p++ = (values [col] >> 16) & 0xff;
3897                                         *p++ = (values [col] >> 24) & 0xff;
3898                                         break;
3899                                 default:
3900                                         g_assert_not_reached ();
3901                                 }
3902                         }
3903                 }
3904                 g_assert ((p - (const unsigned char*)meta->tables [i].base) == (meta->tables [i].rows * meta->tables [i].row_size));
3905         }
3906         
3907         g_assert (assembly->guid.offset + assembly->guid.index < meta_size);
3908         memcpy (meta->raw_metadata + assembly->sheap.offset, assembly->sheap.data, assembly->sheap.index);
3909         memcpy (meta->raw_metadata + assembly->us.offset, assembly->us.data, assembly->us.index);
3910         memcpy (meta->raw_metadata + assembly->blob.offset, assembly->blob.data, assembly->blob.index);
3911         memcpy (meta->raw_metadata + assembly->guid.offset, assembly->guid.data, assembly->guid.index);
3912
3913         assembly->meta_size = assembly->guid.offset + assembly->guid.index;
3914 }
3915
3916 /*
3917  * Some tables in metadata need to be sorted according to some criteria, but
3918  * when methods and fields are first created with reflection, they may be assigned a token
3919  * that doesn't correspond to the final token they will get assigned after the sorting.
3920  * ILGenerator.cs keeps a fixup table that maps the position of tokens in the IL code stream
3921  * with the reflection objects that represent them. Once all the tables are set up, the 
3922  * reflection objects will contains the correct table index. fixup_method() will fixup the
3923  * tokens for the method with ILGenerator @ilgen.
3924  */
3925 static void
3926 fixup_method (MonoReflectionILGen *ilgen, gpointer value, MonoDynamicImage *assembly)
3927 {
3928         guint32 code_idx = GPOINTER_TO_UINT (value);
3929         MonoReflectionILTokenInfo *iltoken;
3930         MonoReflectionFieldBuilder *field;
3931         MonoReflectionCtorBuilder *ctor;
3932         MonoReflectionMethodBuilder *method;
3933         MonoReflectionTypeBuilder *tb;
3934         MonoReflectionArrayMethod *am;
3935         guint32 i, idx = 0;
3936         unsigned char *target;
3937
3938         for (i = 0; i < ilgen->num_token_fixups; ++i) {
3939                 iltoken = (MonoReflectionILTokenInfo *)mono_array_addr_with_size (ilgen->token_fixups, sizeof (MonoReflectionILTokenInfo), i);
3940                 target = (guchar*)assembly->code.data + code_idx + iltoken->code_pos;
3941                 switch (target [3]) {
3942                 case MONO_TABLE_FIELD:
3943                         if (!strcmp (iltoken->member->vtable->klass->name, "FieldBuilder")) {
3944                                 field = (MonoReflectionFieldBuilder *)iltoken->member;
3945                                 idx = field->table_idx;
3946                         } else if (!strcmp (iltoken->member->vtable->klass->name, "MonoField")) {
3947                                 MonoClassField *f = ((MonoReflectionField*)iltoken->member)->field;
3948                                 idx = GPOINTER_TO_UINT (g_hash_table_lookup (assembly->field_to_table_idx, f));
3949                         } else {
3950                                 g_assert_not_reached ();
3951                         }
3952                         break;
3953                 case MONO_TABLE_METHOD:
3954                         if (!strcmp (iltoken->member->vtable->klass->name, "MethodBuilder")) {
3955                                 method = (MonoReflectionMethodBuilder *)iltoken->member;
3956                                 idx = method->table_idx;
3957                         } else if (!strcmp (iltoken->member->vtable->klass->name, "ConstructorBuilder")) {
3958                                 ctor = (MonoReflectionCtorBuilder *)iltoken->member;
3959                                 idx = ctor->table_idx;
3960                         } else if (!strcmp (iltoken->member->vtable->klass->name, "MonoMethod") || 
3961                                            !strcmp (iltoken->member->vtable->klass->name, "MonoCMethod")) {
3962                                 MonoMethod *m = ((MonoReflectionMethod*)iltoken->member)->method;
3963                                 idx = GPOINTER_TO_UINT (g_hash_table_lookup (assembly->method_to_table_idx, m));
3964                         } else {
3965                                 g_assert_not_reached ();
3966                         }
3967                         break;
3968                 case MONO_TABLE_TYPEDEF:
3969                         if (strcmp (iltoken->member->vtable->klass->name, "TypeBuilder"))
3970                                 g_assert_not_reached ();
3971                         tb = (MonoReflectionTypeBuilder *)iltoken->member;
3972                         idx = tb->table_idx;
3973                         break;
3974                 case MONO_TABLE_MEMBERREF:
3975                         if (!strcmp (iltoken->member->vtable->klass->name, "MonoArrayMethod")) {
3976                                 am = (MonoReflectionArrayMethod*)iltoken->member;
3977                                 idx = am->table_idx;
3978                         } else if (!strcmp (iltoken->member->vtable->klass->name, "MonoMethod") ||
3979                                    !strcmp (iltoken->member->vtable->klass->name, "MonoCMethod") ||
3980                                    !strcmp (iltoken->member->vtable->klass->name, "MonoGenericMethod") ||
3981                                    !strcmp (iltoken->member->vtable->klass->name, "MonoGenericCMethod")) {
3982                                 MonoMethod *m = ((MonoReflectionMethod*)iltoken->member)->method;
3983                                 g_assert (m->klass->generic_class || m->klass->generic_container);
3984                                 continue;
3985                         } else if (!strcmp (iltoken->member->vtable->klass->name, "FieldBuilder")) {
3986                                 continue;
3987                         } else if (!strcmp (iltoken->member->vtable->klass->name, "MonoField")) {
3988                                 MonoClassField *f = ((MonoReflectionField*)iltoken->member)->field;
3989                                 g_assert (is_field_on_inst (f));
3990                                 continue;
3991                         } else if (!strcmp (iltoken->member->vtable->klass->name, "MethodBuilder") ||
3992                                         !strcmp (iltoken->member->vtable->klass->name, "ConstructorBuilder")) {
3993                                 continue;
3994                         } else if (!strcmp (iltoken->member->vtable->klass->name, "FieldOnTypeBuilderInst")) {
3995                                 continue;
3996                         } else if (!strcmp (iltoken->member->vtable->klass->name, "MethodOnTypeBuilderInst")) {
3997                                 continue;
3998                         } else if (!strcmp (iltoken->member->vtable->klass->name, "ConstructorOnTypeBuilderInst")) {
3999                                 continue;
4000                         } else {
4001                                 g_assert_not_reached ();
4002                         }
4003                         break;
4004                 case MONO_TABLE_METHODSPEC:
4005                         if (!strcmp (iltoken->member->vtable->klass->name, "MonoGenericMethod")) {
4006                                 MonoMethod *m = ((MonoReflectionMethod*)iltoken->member)->method;
4007                                 g_assert (mono_method_signature (m)->generic_param_count);
4008                                 continue;
4009                         } else if (!strcmp (iltoken->member->vtable->klass->name, "MethodBuilder")) {
4010                                 continue;
4011                         } else {
4012                                 g_assert_not_reached ();
4013                         }
4014                         break;
4015                 default:
4016                         g_error ("got unexpected table 0x%02x in fixup", target [3]);
4017                 }
4018                 target [0] = idx & 0xff;
4019                 target [1] = (idx >> 8) & 0xff;
4020                 target [2] = (idx >> 16) & 0xff;
4021         }
4022 }
4023
4024 /*
4025  * fixup_cattrs:
4026  *
4027  *   The CUSTOM_ATTRIBUTE table might contain METHODDEF tokens whose final
4028  * value is not known when the table is emitted.
4029  */
4030 static void
4031 fixup_cattrs (MonoDynamicImage *assembly)
4032 {
4033         MonoDynamicTable *table;
4034         guint32 *values;
4035         guint32 type, i, idx, token;
4036         MonoObject *ctor;
4037
4038         table = &assembly->tables [MONO_TABLE_CUSTOMATTRIBUTE];
4039
4040         for (i = 0; i < table->rows; ++i) {
4041                 values = table->values + ((i + 1) * MONO_CUSTOM_ATTR_SIZE);
4042
4043                 type = values [MONO_CUSTOM_ATTR_TYPE];
4044                 if ((type & MONO_CUSTOM_ATTR_TYPE_MASK) == MONO_CUSTOM_ATTR_TYPE_METHODDEF) {
4045                         idx = type >> MONO_CUSTOM_ATTR_TYPE_BITS;
4046                         token = mono_metadata_make_token (MONO_TABLE_METHOD, idx);
4047                         ctor = mono_g_hash_table_lookup (assembly->tokens, GUINT_TO_POINTER (token));
4048                         g_assert (ctor);
4049
4050                         if (!strcmp (ctor->vtable->klass->name, "MonoCMethod")) {
4051                                 MonoMethod *m = ((MonoReflectionMethod*)ctor)->method;
4052                                 idx = GPOINTER_TO_UINT (g_hash_table_lookup (assembly->method_to_table_idx, m));
4053                                 values [MONO_CUSTOM_ATTR_TYPE] = (idx << MONO_CUSTOM_ATTR_TYPE_BITS) | MONO_CUSTOM_ATTR_TYPE_METHODDEF;
4054                         }
4055                 }
4056         }
4057 }
4058
4059 static void
4060 assembly_add_resource_manifest (MonoReflectionModuleBuilder *mb, MonoDynamicImage *assembly, MonoReflectionResource *rsrc, guint32 implementation)
4061 {
4062         MonoDynamicTable *table;
4063         guint32 *values;
4064
4065         table = &assembly->tables [MONO_TABLE_MANIFESTRESOURCE];
4066         table->rows++;
4067         alloc_table (table, table->rows);
4068         values = table->values + table->next_idx * MONO_MANIFEST_SIZE;
4069         values [MONO_MANIFEST_OFFSET] = rsrc->offset;
4070         values [MONO_MANIFEST_FLAGS] = rsrc->attrs;
4071         values [MONO_MANIFEST_NAME] = string_heap_insert_mstring (&assembly->sheap, rsrc->name);
4072         values [MONO_MANIFEST_IMPLEMENTATION] = implementation;
4073         table->next_idx++;
4074 }
4075
4076 static void
4077 assembly_add_resource (MonoReflectionModuleBuilder *mb, MonoDynamicImage *assembly, MonoReflectionResource *rsrc)
4078 {
4079         MonoDynamicTable *table;
4080         guint32 *values;
4081         char blob_size [6];
4082         guchar hash [20];
4083         char *b = blob_size;
4084         char *name, *sname;
4085         guint32 idx, offset;
4086
4087         if (rsrc->filename) {
4088                 name = mono_string_to_utf8 (rsrc->filename);
4089                 sname = g_path_get_basename (name);
4090         
4091                 table = &assembly->tables [MONO_TABLE_FILE];
4092                 table->rows++;
4093                 alloc_table (table, table->rows);
4094                 values = table->values + table->next_idx * MONO_FILE_SIZE;
4095                 values [MONO_FILE_FLAGS] = FILE_CONTAINS_NO_METADATA;
4096                 values [MONO_FILE_NAME] = string_heap_insert (&assembly->sheap, sname);
4097                 g_free (sname);
4098
4099                 mono_sha1_get_digest_from_file (name, hash);
4100                 mono_metadata_encode_value (20, b, &b);
4101                 values [MONO_FILE_HASH_VALUE] = mono_image_add_stream_data (&assembly->blob, blob_size, b-blob_size);
4102                 mono_image_add_stream_data (&assembly->blob, (char*)hash, 20);
4103                 g_free (name);
4104                 idx = table->next_idx++;
4105                 rsrc->offset = 0;
4106                 idx = MONO_IMPLEMENTATION_FILE | (idx << MONO_IMPLEMENTATION_BITS);
4107         } else {
4108                 char sizebuf [4];
4109                 char *data;
4110                 guint len;
4111                 if (rsrc->data) {
4112                         data = mono_array_addr (rsrc->data, char, 0);
4113                         len = mono_array_length (rsrc->data);
4114                 } else {
4115                         data = NULL;
4116                         len = 0;
4117                 }
4118                 offset = len;
4119                 sizebuf [0] = offset; sizebuf [1] = offset >> 8;
4120                 sizebuf [2] = offset >> 16; sizebuf [3] = offset >> 24;
4121                 rsrc->offset = mono_image_add_stream_data (&assembly->resources, sizebuf, 4);
4122                 mono_image_add_stream_data (&assembly->resources, data, len);
4123
4124                 if (!mb->is_main)
4125                         /* 
4126                          * The entry should be emitted into the MANIFESTRESOURCE table of 
4127                          * the main module, but that needs to reference the FILE table
4128                          * which isn't emitted yet.
4129                          */
4130                         return;
4131                 else
4132                         idx = 0;
4133         }
4134
4135         assembly_add_resource_manifest (mb, assembly, rsrc, idx);
4136 }
4137
4138 static void
4139 set_version_from_string (MonoString *version, guint32 *values)
4140 {
4141         gchar *ver, *p, *str;
4142         guint32 i;
4143         
4144         values [MONO_ASSEMBLY_MAJOR_VERSION] = 0;
4145         values [MONO_ASSEMBLY_MINOR_VERSION] = 0;
4146         values [MONO_ASSEMBLY_REV_NUMBER] = 0;
4147         values [MONO_ASSEMBLY_BUILD_NUMBER] = 0;
4148         if (!version)
4149                 return;
4150         ver = str = mono_string_to_utf8 (version);
4151         for (i = 0; i < 4; ++i) {
4152                 values [MONO_ASSEMBLY_MAJOR_VERSION + i] = strtol (ver, &p, 10);
4153                 switch (*p) {
4154                 case '.':
4155                         p++;
4156                         break;
4157                 case '*':
4158                         /* handle Revision and Build */
4159                         p++;
4160                         break;
4161                 }
4162                 ver = p;
4163         }
4164         g_free (str);
4165 }
4166
4167 static guint32
4168 load_public_key (MonoArray *pkey, MonoDynamicImage *assembly) {
4169         gsize len;
4170         guint32 token = 0;
4171         char blob_size [6];
4172         char *b = blob_size;
4173
4174         if (!pkey)
4175                 return token;
4176
4177         len = mono_array_length (pkey);
4178         mono_metadata_encode_value (len, b, &b);
4179         token = mono_image_add_stream_data (&assembly->blob, blob_size, b - blob_size);
4180         mono_image_add_stream_data (&assembly->blob, mono_array_addr (pkey, char, 0), len);
4181
4182         assembly->public_key = g_malloc (len);
4183         memcpy (assembly->public_key, mono_array_addr (pkey, char, 0), len);
4184         assembly->public_key_len = len;
4185
4186         /* Special case: check for ECMA key (16 bytes) */
4187         if ((len == MONO_ECMA_KEY_LENGTH) && mono_is_ecma_key (mono_array_addr (pkey, char, 0), len)) {
4188                 /* In this case we must reserve 128 bytes (1024 bits) for the signature */
4189                 assembly->strong_name_size = MONO_DEFAULT_PUBLIC_KEY_LENGTH;
4190         } else if (len >= MONO_PUBLIC_KEY_HEADER_LENGTH + MONO_MINIMUM_PUBLIC_KEY_LENGTH) {
4191                 /* minimum key size (in 2.0) is 384 bits */
4192                 assembly->strong_name_size = len - MONO_PUBLIC_KEY_HEADER_LENGTH;
4193         } else {
4194                 /* FIXME - verifier */
4195                 g_warning ("Invalid public key length: %d bits (total: %d)", (int)MONO_PUBLIC_KEY_BIT_SIZE (len), (int)len);
4196                 assembly->strong_name_size = MONO_DEFAULT_PUBLIC_KEY_LENGTH; /* to be safe */
4197         }
4198         assembly->strong_name = g_malloc0 (assembly->strong_name_size);
4199
4200         return token;
4201 }
4202
4203 static void
4204 mono_image_emit_manifest (MonoReflectionModuleBuilder *moduleb)
4205 {
4206         MonoDynamicTable *table;
4207         MonoDynamicImage *assembly;
4208         MonoReflectionAssemblyBuilder *assemblyb;
4209         MonoDomain *domain;
4210         guint32 *values;
4211         int i;
4212         guint32 module_index;
4213
4214         assemblyb = moduleb->assemblyb;
4215         assembly = moduleb->dynamic_image;
4216         domain = mono_object_domain (assemblyb);
4217
4218         /* Emit ASSEMBLY table */
4219         table = &assembly->tables [MONO_TABLE_ASSEMBLY];
4220         alloc_table (table, 1);
4221         values = table->values + MONO_ASSEMBLY_SIZE;
4222         values [MONO_ASSEMBLY_HASH_ALG] = assemblyb->algid? assemblyb->algid: ASSEMBLY_HASH_SHA1;
4223         values [MONO_ASSEMBLY_NAME] = string_heap_insert_mstring (&assembly->sheap, assemblyb->name);
4224         if (assemblyb->culture) {
4225                 values [MONO_ASSEMBLY_CULTURE] = string_heap_insert_mstring (&assembly->sheap, assemblyb->culture);
4226         } else {
4227                 values [MONO_ASSEMBLY_CULTURE] = string_heap_insert (&assembly->sheap, "");
4228         }
4229         values [MONO_ASSEMBLY_PUBLIC_KEY] = load_public_key (assemblyb->public_key, assembly);
4230         values [MONO_ASSEMBLY_FLAGS] = assemblyb->flags;
4231         set_version_from_string (assemblyb->version, values);
4232
4233         /* Emit FILE + EXPORTED_TYPE table */
4234         module_index = 0;
4235         for (i = 0; i < mono_array_length (assemblyb->modules); ++i) {
4236                 int j;
4237                 MonoReflectionModuleBuilder *file_module = 
4238                         mono_array_get (assemblyb->modules, MonoReflectionModuleBuilder*, i);
4239                 if (file_module != moduleb) {
4240                         mono_image_fill_file_table (domain, (MonoReflectionModule*)file_module, assembly);
4241                         module_index ++;
4242                         if (file_module->types) {
4243                                 for (j = 0; j < file_module->num_types; ++j) {
4244                                         MonoReflectionTypeBuilder *tb = mono_array_get (file_module->types, MonoReflectionTypeBuilder*, j);
4245                                         mono_image_fill_export_table (domain, tb, module_index, 0, assembly);
4246                                 }
4247                         }
4248                 }
4249         }
4250         if (assemblyb->loaded_modules) {
4251                 for (i = 0; i < mono_array_length (assemblyb->loaded_modules); ++i) {
4252                         MonoReflectionModule *file_module = 
4253                                 mono_array_get (assemblyb->loaded_modules, MonoReflectionModule*, i);
4254                         mono_image_fill_file_table (domain, file_module, assembly);
4255                         module_index ++;
4256                         mono_image_fill_export_table_from_module (domain, file_module, module_index, assembly);
4257                 }
4258         }
4259         if (assemblyb->type_forwarders)
4260                 mono_image_fill_export_table_from_type_forwarders (assemblyb, assembly);
4261
4262         /* Emit MANIFESTRESOURCE table */
4263         module_index = 0;
4264         for (i = 0; i < mono_array_length (assemblyb->modules); ++i) {
4265                 int j;
4266                 MonoReflectionModuleBuilder *file_module = 
4267                         mono_array_get (assemblyb->modules, MonoReflectionModuleBuilder*, i);
4268                 /* The table for the main module is emitted later */
4269                 if (file_module != moduleb) {
4270                         module_index ++;
4271                         if (file_module->resources) {
4272                                 int len = mono_array_length (file_module->resources);
4273                                 for (j = 0; j < len; ++j) {
4274                                         MonoReflectionResource* res = (MonoReflectionResource*)mono_array_addr (file_module->resources, MonoReflectionResource, j);
4275                                         assembly_add_resource_manifest (file_module, assembly, res, MONO_IMPLEMENTATION_FILE | (module_index << MONO_IMPLEMENTATION_BITS));
4276                                 }
4277                         }
4278                 }
4279         }               
4280 }
4281
4282 #ifndef DISABLE_REFLECTION_EMIT_SAVE
4283
4284 /*
4285  * mono_image_build_metadata() will fill the info in all the needed metadata tables
4286  * for the modulebuilder @moduleb.
4287  * At the end of the process, method and field tokens are fixed up and the 
4288  * on-disk compressed metadata representation is created.
4289  */
4290 void
4291 mono_image_build_metadata (MonoReflectionModuleBuilder *moduleb)
4292 {
4293         MonoDynamicTable *table;
4294         MonoDynamicImage *assembly;
4295         MonoReflectionAssemblyBuilder *assemblyb;
4296         MonoDomain *domain;
4297         GPtrArray *types;
4298         guint32 *values;
4299         int i, j;
4300
4301         assemblyb = moduleb->assemblyb;
4302         assembly = moduleb->dynamic_image;
4303         domain = mono_object_domain (assemblyb);
4304
4305         if (assembly->text_rva)
4306                 return;
4307
4308         assembly->text_rva = START_TEXT_RVA;
4309
4310         if (moduleb->is_main) {
4311                 mono_image_emit_manifest (moduleb);
4312         }
4313
4314         table = &assembly->tables [MONO_TABLE_TYPEDEF];
4315         table->rows = 1; /* .<Module> */
4316         table->next_idx++;
4317         alloc_table (table, table->rows);
4318         /*
4319          * Set the first entry.
4320          */
4321         values = table->values + table->columns;
4322         values [MONO_TYPEDEF_FLAGS] = 0;
4323         values [MONO_TYPEDEF_NAME] = string_heap_insert (&assembly->sheap, "<Module>") ;
4324         values [MONO_TYPEDEF_NAMESPACE] = string_heap_insert (&assembly->sheap, "") ;
4325         values [MONO_TYPEDEF_EXTENDS] = 0;
4326         values [MONO_TYPEDEF_FIELD_LIST] = 1;
4327         values [MONO_TYPEDEF_METHOD_LIST] = 1;
4328
4329         /* 
4330          * handle global methods 
4331          * FIXME: test what to do when global methods are defined in multiple modules.
4332          */
4333         if (moduleb->global_methods) {
4334                 table = &assembly->tables [MONO_TABLE_METHOD];
4335                 table->rows += mono_array_length (moduleb->global_methods);
4336                 alloc_table (table, table->rows);
4337                 for (i = 0; i < mono_array_length (moduleb->global_methods); ++i)
4338                         mono_image_get_method_info (
4339                                 mono_array_get (moduleb->global_methods, MonoReflectionMethodBuilder*, i), assembly);
4340         }
4341         if (moduleb->global_fields) {
4342                 table = &assembly->tables [MONO_TABLE_FIELD];
4343                 table->rows += mono_array_length (moduleb->global_fields);
4344                 alloc_table (table, table->rows);
4345                 for (i = 0; i < mono_array_length (moduleb->global_fields); ++i)
4346                         mono_image_get_field_info (
4347                                 mono_array_get (moduleb->global_fields, MonoReflectionFieldBuilder*, i), assembly);
4348         }
4349
4350         table = &assembly->tables [MONO_TABLE_MODULE];
4351         alloc_table (table, 1);
4352         mono_image_fill_module_table (domain, moduleb, assembly);
4353
4354         /* Collect all types into a list sorted by their table_idx */
4355         types = g_ptr_array_new ();
4356
4357         if (moduleb->types)
4358                 for (i = 0; i < moduleb->num_types; ++i) {
4359                         MonoReflectionTypeBuilder *type = mono_array_get (moduleb->types, MonoReflectionTypeBuilder*, i);
4360                         collect_types (types, type);
4361                 }
4362
4363         g_ptr_array_sort (types, (GCompareFunc)compare_types_by_table_idx);
4364         table = &assembly->tables [MONO_TABLE_TYPEDEF];
4365         table->rows += types->len;
4366         alloc_table (table, table->rows);
4367
4368         /*
4369          * Emit type names + namespaces at one place inside the string heap,
4370          * so load_class_names () needs to touch fewer pages.
4371          */
4372         for (i = 0; i < types->len; ++i) {
4373                 MonoReflectionTypeBuilder *tb = g_ptr_array_index (types, i);
4374                 string_heap_insert_mstring (&assembly->sheap, tb->nspace);
4375         }
4376         for (i = 0; i < types->len; ++i) {
4377                 MonoReflectionTypeBuilder *tb = g_ptr_array_index (types, i);
4378                 string_heap_insert_mstring (&assembly->sheap, tb->name);
4379         }
4380
4381         for (i = 0; i < types->len; ++i) {
4382                 MonoReflectionTypeBuilder *type = g_ptr_array_index (types, i);
4383                 mono_image_get_type_info (domain, type, assembly);
4384         }
4385
4386         /* 
4387          * table->rows is already set above and in mono_image_fill_module_table.
4388          */
4389         /* add all the custom attributes at the end, once all the indexes are stable */
4390         mono_image_add_cattrs (assembly, 1, MONO_CUSTOM_ATTR_ASSEMBLY, assemblyb->cattrs);
4391
4392         /* CAS assembly permissions */
4393         if (assemblyb->permissions_minimum)
4394                 mono_image_add_decl_security (assembly, mono_metadata_make_token (MONO_TABLE_ASSEMBLY, 1), assemblyb->permissions_minimum);
4395         if (assemblyb->permissions_optional)
4396                 mono_image_add_decl_security (assembly, mono_metadata_make_token (MONO_TABLE_ASSEMBLY, 1), assemblyb->permissions_optional);
4397         if (assemblyb->permissions_refused)
4398                 mono_image_add_decl_security (assembly, mono_metadata_make_token (MONO_TABLE_ASSEMBLY, 1), assemblyb->permissions_refused);
4399
4400         module_add_cattrs (assembly, moduleb);
4401
4402         /* fixup tokens */
4403         mono_g_hash_table_foreach (assembly->token_fixups, (GHFunc)fixup_method, assembly);
4404
4405         /* Create the MethodImpl table.  We do this after emitting all methods so we already know
4406          * the final tokens and don't need another fixup pass. */
4407
4408         if (moduleb->global_methods) {
4409                 for (i = 0; i < mono_array_length (moduleb->global_methods); ++i) {
4410                         MonoReflectionMethodBuilder *mb = mono_array_get (
4411                                 moduleb->global_methods, MonoReflectionMethodBuilder*, i);
4412                         mono_image_add_methodimpl (assembly, mb);
4413                 }
4414         }
4415
4416         for (i = 0; i < types->len; ++i) {
4417                 MonoReflectionTypeBuilder *type = g_ptr_array_index (types, i);
4418                 if (type->methods) {
4419                         for (j = 0; j < type->num_methods; ++j) {
4420                                 MonoReflectionMethodBuilder *mb = mono_array_get (
4421                                         type->methods, MonoReflectionMethodBuilder*, j);
4422
4423                                 mono_image_add_methodimpl (assembly, mb);
4424                         }
4425                 }
4426         }
4427
4428         g_ptr_array_free (types, TRUE);
4429
4430         fixup_cattrs (assembly);
4431 }
4432
4433 #else /* DISABLE_REFLECTION_EMIT_SAVE */
4434
4435 void
4436 mono_image_build_metadata (MonoReflectionModuleBuilder *moduleb)
4437 {
4438         g_error ("This mono runtime was configured with --enable-minimal=reflection_emit_save, so saving of dynamic assemblies is not supported.");
4439 }
4440
4441 #endif /* DISABLE_REFLECTION_EMIT_SAVE */
4442
4443 #ifndef DISABLE_REFLECTION_EMIT
4444
4445 /*
4446  * mono_image_insert_string:
4447  * @module: module builder object
4448  * @str: a string
4449  *
4450  * Insert @str into the user string stream of @module.
4451  */
4452 guint32
4453 mono_image_insert_string (MonoReflectionModuleBuilder *module, MonoString *str)
4454 {
4455         MonoDynamicImage *assembly;
4456         guint32 idx;
4457         char buf [16];
4458         char *b = buf;
4459         
4460         MONO_ARCH_SAVE_REGS;
4461
4462         if (!module->dynamic_image)
4463                 mono_image_module_basic_init (module);
4464
4465         assembly = module->dynamic_image;
4466         
4467         if (assembly->save) {
4468                 mono_metadata_encode_value (1 | (str->length * 2), b, &b);
4469                 idx = mono_image_add_stream_data (&assembly->us, buf, b-buf);
4470 #if G_BYTE_ORDER != G_LITTLE_ENDIAN
4471         {
4472                 char *swapped = g_malloc (2 * mono_string_length (str));
4473                 const char *p = (const char*)mono_string_chars (str);
4474
4475                 swap_with_size (swapped, p, 2, mono_string_length (str));
4476                 mono_image_add_stream_data (&assembly->us, swapped, str->length * 2);
4477                 g_free (swapped);
4478         }
4479 #else
4480                 mono_image_add_stream_data (&assembly->us, (const char*)mono_string_chars (str), str->length * 2);
4481 #endif
4482                 mono_image_add_stream_data (&assembly->us, "", 1);
4483         } else {
4484                 idx = assembly->us.index ++;
4485         }
4486
4487         mono_g_hash_table_insert (assembly->tokens, GUINT_TO_POINTER (MONO_TOKEN_STRING | idx), str);
4488
4489         return MONO_TOKEN_STRING | idx;
4490 }
4491
4492 guint32
4493 mono_image_create_method_token (MonoDynamicImage *assembly, MonoObject *obj, MonoArray *opt_param_types)
4494 {
4495         MonoClass *klass;
4496         guint32 token = 0;
4497
4498         klass = obj->vtable->klass;
4499         if (strcmp (klass->name, "MonoMethod") == 0) {
4500                 MonoMethod *method = ((MonoReflectionMethod *)obj)->method;
4501                 MonoMethodSignature *sig, *old;
4502                 guint32 sig_token, parent;
4503                 int nargs, i;
4504
4505                 g_assert (opt_param_types && (mono_method_signature (method)->sentinelpos >= 0));
4506
4507                 nargs = mono_array_length (opt_param_types);
4508                 old = mono_method_signature (method);
4509                 sig = mono_metadata_signature_alloc ( &assembly->image, old->param_count + nargs);
4510
4511                 sig->hasthis = old->hasthis;
4512                 sig->explicit_this = old->explicit_this;
4513                 sig->call_convention = old->call_convention;
4514                 sig->generic_param_count = old->generic_param_count;
4515                 sig->param_count = old->param_count + nargs;
4516                 sig->sentinelpos = old->param_count;
4517                 sig->ret = old->ret;
4518
4519                 for (i = 0; i < old->param_count; i++)
4520                         sig->params [i] = old->params [i];
4521
4522                 for (i = 0; i < nargs; i++) {
4523                         MonoReflectionType *rt = mono_array_get (opt_param_types, MonoReflectionType *, i);
4524                         sig->params [old->param_count + i] = rt->type;
4525                 }
4526
4527                 parent = mono_image_typedef_or_ref (assembly, &method->klass->byval_arg);
4528                 g_assert ((parent & MONO_TYPEDEFORREF_MASK) == MONO_MEMBERREF_PARENT_TYPEREF);
4529                 parent >>= MONO_TYPEDEFORREF_BITS;
4530
4531                 parent <<= MONO_MEMBERREF_PARENT_BITS;
4532                 parent |= MONO_MEMBERREF_PARENT_TYPEREF;
4533
4534                 sig_token = method_encode_signature (assembly, sig);
4535                 token = mono_image_get_varargs_method_token (assembly, parent, method->name, sig_token);
4536         } else if (strcmp (klass->name, "MethodBuilder") == 0) {
4537                 MonoReflectionMethodBuilder *mb = (MonoReflectionMethodBuilder *)obj;
4538                 ReflectionMethodBuilder rmb;
4539                 guint32 parent, sig;
4540                 char *name;
4541
4542                 reflection_methodbuilder_from_method_builder (&rmb, mb);
4543                 rmb.opt_types = opt_param_types;
4544
4545                 sig = method_builder_encode_signature (assembly, &rmb);
4546
4547                 parent = mono_image_create_token (assembly, obj, TRUE, TRUE);
4548                 g_assert (mono_metadata_token_table (parent) == MONO_TABLE_METHOD);
4549
4550                 parent = mono_metadata_token_index (parent) << MONO_MEMBERREF_PARENT_BITS;
4551                 parent |= MONO_MEMBERREF_PARENT_METHODDEF;
4552
4553                 name = mono_string_to_utf8 (rmb.name);
4554                 token = mono_image_get_varargs_method_token (
4555                         assembly, parent, name, sig);
4556                 g_free (name);
4557         } else {
4558                 g_error ("requested method token for %s\n", klass->name);
4559         }
4560
4561         return token;
4562 }
4563
4564 /*
4565  * mono_image_create_token:
4566  * @assembly: a dynamic assembly
4567  * @obj:
4568  * @register_token: Whenever to register the token in the assembly->tokens hash. 
4569  *
4570  * Get a token to insert in the IL code stream for the given MemberInfo.
4571  * The metadata emission routines need to pass FALSE as REGISTER_TOKEN, since by that time, 
4572  * the table_idx-es were recomputed, so registering the token would overwrite an existing 
4573  * entry.
4574  */
4575 guint32
4576 mono_image_create_token (MonoDynamicImage *assembly, MonoObject *obj, 
4577                                                  gboolean create_methodspec, gboolean register_token)
4578 {
4579         MonoClass *klass;
4580         guint32 token = 0;
4581
4582         klass = obj->vtable->klass;
4583         if (strcmp (klass->name, "MethodBuilder") == 0) {
4584                 MonoReflectionMethodBuilder *mb = (MonoReflectionMethodBuilder *)obj;
4585                 MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder*)mb->type;
4586
4587                 if (tb->module->dynamic_image == assembly && !tb->generic_params && !mb->generic_params)
4588                         token = mb->table_idx | MONO_TOKEN_METHOD_DEF;
4589                 else
4590                         token = mono_image_get_methodbuilder_token (assembly, mb, create_methodspec);
4591                 /*g_print ("got token 0x%08x for %s\n", token, mono_string_to_utf8 (mb->name));*/
4592         } else if (strcmp (klass->name, "ConstructorBuilder") == 0) {
4593                 MonoReflectionCtorBuilder *mb = (MonoReflectionCtorBuilder *)obj;
4594                 MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder*)mb->type;
4595
4596                 if (tb->module->dynamic_image == assembly && !tb->generic_params)
4597                         token = mb->table_idx | MONO_TOKEN_METHOD_DEF;
4598                 else
4599                         token = mono_image_get_ctorbuilder_token (assembly, mb);
4600                 /*g_print ("got token 0x%08x for %s\n", token, mono_string_to_utf8 (mb->name));*/
4601         } else if (strcmp (klass->name, "FieldBuilder") == 0) {
4602                 MonoReflectionFieldBuilder *fb = (MonoReflectionFieldBuilder *)obj;
4603                 MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder *)fb->typeb;
4604                 if (tb->generic_params) {
4605                         token = mono_image_get_generic_field_token (assembly, fb);
4606                 } else {
4607                         token = fb->table_idx | MONO_TOKEN_FIELD_DEF;
4608                 }
4609         } else if (strcmp (klass->name, "TypeBuilder") == 0) {
4610                 MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder *)obj;
4611                 token = tb->table_idx | MONO_TOKEN_TYPE_DEF;
4612         } else if (strcmp (klass->name, "MonoType") == 0) {
4613                 MonoReflectionType *tb = (MonoReflectionType *)obj;
4614                 MonoClass *mc = mono_class_from_mono_type (tb->type);
4615                 token = mono_metadata_token_from_dor (
4616                         mono_image_typedef_or_ref_full (assembly, tb->type, mc->generic_container == NULL));
4617         } else if (strcmp (klass->name, "GenericTypeParameterBuilder") == 0) {
4618                 MonoReflectionType *tb = (MonoReflectionType *)obj;
4619                 token = mono_metadata_token_from_dor (
4620                         mono_image_typedef_or_ref (assembly, tb->type));
4621         } else if (strcmp (klass->name, "MonoGenericClass") == 0) {
4622                 MonoReflectionType *tb = (MonoReflectionType *)obj;
4623                 token = mono_metadata_token_from_dor (
4624                         mono_image_typedef_or_ref (assembly, tb->type));
4625         } else if (strcmp (klass->name, "MonoCMethod") == 0 ||
4626                    strcmp (klass->name, "MonoMethod") == 0 ||
4627                    strcmp (klass->name, "MonoGenericMethod") == 0 ||
4628                    strcmp (klass->name, "MonoGenericCMethod") == 0) {
4629                 MonoReflectionMethod *m = (MonoReflectionMethod *)obj;
4630                 if (m->method->is_inflated) {
4631                         if (create_methodspec)
4632                                 token = mono_image_get_methodspec_token (assembly, m->method);
4633                         else
4634                                 token = mono_image_get_inflated_method_token (assembly, m->method);
4635                 } else if ((m->method->klass->image == &assembly->image) &&
4636                          !m->method->klass->generic_class) {
4637                         static guint32 method_table_idx = 0xffffff;
4638                         if (m->method->klass->wastypebuilder) {
4639                                 /* we use the same token as the one that was assigned
4640                                  * to the Methodbuilder.
4641                                  * FIXME: do the equivalent for Fields.
4642                                  */
4643                                 token = m->method->token;
4644                         } else {
4645                                 /*
4646                                  * Each token should have a unique index, but the indexes are
4647                                  * assigned by managed code, so we don't know about them. An
4648                                  * easy solution is to count backwards...
4649                                  */
4650                                 method_table_idx --;
4651                                 token = MONO_TOKEN_METHOD_DEF | method_table_idx;
4652                         }
4653                 } else {
4654                         token = mono_image_get_methodref_token (assembly, m->method, create_methodspec);
4655                 }
4656                 /*g_print ("got token 0x%08x for %s\n", token, m->method->name);*/
4657         } else if (strcmp (klass->name, "MonoField") == 0) {
4658                 MonoReflectionField *f = (MonoReflectionField *)obj;
4659                 if ((f->field->parent->image == &assembly->image) && !is_field_on_inst (f->field)) {
4660                         static guint32 field_table_idx = 0xffffff;
4661                         field_table_idx --;
4662                         token = MONO_TOKEN_FIELD_DEF | field_table_idx;
4663                 } else {
4664                         token = mono_image_get_fieldref_token (assembly, f);
4665                 }
4666                 /*g_print ("got token 0x%08x for %s\n", token, f->field->name);*/
4667         } else if (strcmp (klass->name, "MonoArrayMethod") == 0) {
4668                 MonoReflectionArrayMethod *m = (MonoReflectionArrayMethod *)obj;
4669                 token = mono_image_get_array_token (assembly, m);
4670         } else if (strcmp (klass->name, "SignatureHelper") == 0) {
4671                 MonoReflectionSigHelper *s = (MonoReflectionSigHelper*)obj;
4672                 token = MONO_TOKEN_SIGNATURE | mono_image_get_sighelper_token (assembly, s);
4673         } else if (strcmp (klass->name, "EnumBuilder") == 0) {
4674                 MonoReflectionType *tb = (MonoReflectionType *)obj;
4675                 token = mono_metadata_token_from_dor (
4676                         mono_image_typedef_or_ref (assembly, tb->type));
4677         } else if (strcmp (klass->name, "FieldOnTypeBuilderInst") == 0) {
4678                 MonoReflectionFieldOnTypeBuilderInst *f = (MonoReflectionFieldOnTypeBuilderInst*)obj;
4679                 token = mono_image_get_field_on_inst_token (assembly, f);
4680         } else if (strcmp (klass->name, "ConstructorOnTypeBuilderInst") == 0) {
4681                 MonoReflectionCtorOnTypeBuilderInst *c = (MonoReflectionCtorOnTypeBuilderInst*)obj;
4682                 token = mono_image_get_ctor_on_inst_token (assembly, c, create_methodspec);
4683         } else if (strcmp (klass->name, "MethodOnTypeBuilderInst") == 0) {
4684                 MonoReflectionMethodOnTypeBuilderInst *m = (MonoReflectionMethodOnTypeBuilderInst*)obj;
4685                 token = mono_image_get_method_on_inst_token (assembly, m, create_methodspec);
4686         } else {
4687                 g_error ("requested token for %s\n", klass->name);
4688         }
4689
4690         if (register_token)
4691                 mono_image_register_token (assembly, token, obj);
4692
4693         return token;
4694 }
4695
4696 /*
4697  * mono_image_register_token:
4698  *
4699  *   Register the TOKEN->OBJ mapping in the mapping table in ASSEMBLY. This is required for
4700  * the Module.ResolveXXXToken () methods to work.
4701  */
4702 void
4703 mono_image_register_token (MonoDynamicImage *assembly, guint32 token, MonoObject *obj)
4704 {
4705         MonoObject *prev = mono_g_hash_table_lookup (assembly->tokens, GUINT_TO_POINTER (token));
4706         if (prev) {
4707                 /* There could be multiple MethodInfo objects with the same token */
4708                 //g_assert (prev == obj);
4709         } else {
4710                 mono_g_hash_table_insert (assembly->tokens, GUINT_TO_POINTER (token), obj);
4711         }
4712 }
4713
4714 #endif /* DISABLE_REFLECTION_EMIT */
4715
4716 typedef struct {
4717         guint32 import_lookup_table;
4718         guint32 timestamp;
4719         guint32 forwarder;
4720         guint32 name_rva;
4721         guint32 import_address_table_rva;
4722 } MonoIDT;
4723
4724 typedef struct {
4725         guint32 name_rva;
4726         guint32 flags;
4727 } MonoILT;
4728
4729 static gpointer register_assembly (MonoDomain *domain, MonoReflectionAssembly *res, MonoAssembly *assembly);
4730
4731 static MonoDynamicImage*
4732 create_dynamic_mono_image (MonoDynamicAssembly *assembly, char *assembly_name, char *module_name)
4733 {
4734         static const guchar entrycode [16] = {0xff, 0x25, 0};
4735         MonoDynamicImage *image;
4736         int i;
4737
4738         const char *version;
4739
4740         if (!strcmp (mono_get_runtime_info ()->framework_version, "2.1"))
4741                 version = "v2.0.50727"; /* HACK: SL 2 enforces the .net 2 metadata version */
4742         else
4743                 version = mono_get_runtime_info ()->runtime_version;
4744
4745 #if HAVE_BOEHM_GC
4746         image = GC_MALLOC (sizeof (MonoDynamicImage));
4747 #else
4748         image = g_new0 (MonoDynamicImage, 1);
4749 #endif
4750         
4751         mono_profiler_module_event (&image->image, MONO_PROFILE_START_LOAD);
4752         
4753         /*g_print ("created image %p\n", image);*/
4754         /* keep in sync with image.c */
4755         image->image.name = assembly_name;
4756         image->image.assembly_name = image->image.name; /* they may be different */
4757         image->image.module_name = module_name;
4758         image->image.version = g_strdup (version);
4759         image->image.md_version_major = 1;
4760         image->image.md_version_minor = 1;
4761         image->image.dynamic = TRUE;
4762
4763         image->image.references = g_new0 (MonoAssembly*, 1);
4764         image->image.references [0] = NULL;
4765
4766         mono_image_init (&image->image);
4767
4768         image->token_fixups = mono_g_hash_table_new_type (NULL, NULL, MONO_HASH_KEY_GC);
4769         image->method_to_table_idx = g_hash_table_new (NULL, NULL);
4770         image->field_to_table_idx = g_hash_table_new (NULL, NULL);
4771         image->method_aux_hash = g_hash_table_new (NULL, NULL);
4772         image->handleref = g_hash_table_new (NULL, NULL);
4773         image->tokens = mono_g_hash_table_new_type (NULL, NULL, MONO_HASH_VALUE_GC);
4774         image->generic_def_objects = mono_g_hash_table_new_type (NULL, NULL, MONO_HASH_VALUE_GC);
4775         image->methodspec = mono_g_hash_table_new_type (NULL, NULL, MONO_HASH_KEY_GC);
4776         image->typespec = g_hash_table_new ((GHashFunc)mono_metadata_type_hash, (GCompareFunc)mono_metadata_type_equal);
4777         image->typeref = g_hash_table_new ((GHashFunc)mono_metadata_type_hash, (GCompareFunc)mono_metadata_type_equal);
4778         image->blob_cache = g_hash_table_new ((GHashFunc)mono_blob_entry_hash, (GCompareFunc)mono_blob_entry_equal);
4779         image->gen_params = g_ptr_array_new ();
4780
4781         /*g_print ("string heap create for image %p (%s)\n", image, module_name);*/
4782         string_heap_init (&image->sheap);
4783         mono_image_add_stream_data (&image->us, "", 1);
4784         add_to_blob_cached (image, (char*) "", 1, NULL, 0);
4785         /* import tables... */
4786         mono_image_add_stream_data (&image->code, (char*)entrycode, sizeof (entrycode));
4787         image->iat_offset = mono_image_add_stream_zero (&image->code, 8); /* two IAT entries */
4788         image->idt_offset = mono_image_add_stream_zero (&image->code, 2 * sizeof (MonoIDT)); /* two IDT entries */
4789         image->imp_names_offset = mono_image_add_stream_zero (&image->code, 2); /* flags for name entry */
4790         mono_image_add_stream_data (&image->code, "_CorExeMain", 12);
4791         mono_image_add_stream_data (&image->code, "mscoree.dll", 12);
4792         image->ilt_offset = mono_image_add_stream_zero (&image->code, 8); /* two ILT entries */
4793         stream_data_align (&image->code);
4794
4795         image->cli_header_offset = mono_image_add_stream_zero (&image->code, sizeof (MonoCLIHeader));
4796
4797         for (i=0; i < MONO_TABLE_NUM; ++i) {
4798                 image->tables [i].next_idx = 1;
4799                 image->tables [i].columns = table_sizes [i];
4800         }
4801
4802         image->image.assembly = (MonoAssembly*)assembly;
4803         image->run = assembly->run;
4804         image->save = assembly->save;
4805         image->pe_kind = 0x1; /* ILOnly */
4806         image->machine = 0x14c; /* I386 */
4807         
4808         mono_profiler_module_loaded (&image->image, MONO_PROFILE_OK);
4809
4810         return image;
4811 }
4812
4813 static void
4814 free_blob_cache_entry (gpointer key, gpointer val, gpointer user_data)
4815 {
4816         g_free (key);
4817 }
4818
4819 void
4820 mono_dynamic_image_free (MonoDynamicImage *image)
4821 {
4822         MonoDynamicImage *di = image;
4823         GList *list;
4824         int i;
4825
4826         if (di->methodspec)
4827                 mono_g_hash_table_destroy (di->methodspec);
4828         if (di->typespec)
4829                 g_hash_table_destroy (di->typespec);
4830         if (di->typeref)
4831                 g_hash_table_destroy (di->typeref);
4832         if (di->handleref)
4833                 g_hash_table_destroy (di->handleref);
4834         if (di->tokens)
4835                 mono_g_hash_table_destroy (di->tokens);
4836         if (di->generic_def_objects)
4837                 mono_g_hash_table_destroy (di->generic_def_objects);
4838         if (di->blob_cache) {
4839                 g_hash_table_foreach (di->blob_cache, free_blob_cache_entry, NULL);
4840                 g_hash_table_destroy (di->blob_cache);
4841         }
4842         if (di->standalonesig_cache)
4843                 g_hash_table_destroy (di->standalonesig_cache);
4844         for (list = di->array_methods; list; list = list->next) {
4845                 ArrayMethod *am = (ArrayMethod *)list->data;
4846                 g_free (am->sig);
4847                 g_free (am->name);
4848                 g_free (am);
4849         }
4850         g_list_free (di->array_methods);
4851         if (di->gen_params) {
4852                 for (i = 0; i < di->gen_params->len; i++) {
4853                         GenericParamTableEntry *entry = g_ptr_array_index (di->gen_params, i);
4854                         if (entry->gparam->type.type) {
4855                                 MonoGenericParam *param = entry->gparam->type.type->data.generic_param;
4856                                 g_free ((char*)param->name);
4857                                 g_free (param);
4858                         }
4859                         g_free (entry);
4860                 }
4861                 g_ptr_array_free (di->gen_params, TRUE);
4862         }
4863         if (di->token_fixups)
4864                 mono_g_hash_table_destroy (di->token_fixups);
4865         if (di->method_to_table_idx)
4866                 g_hash_table_destroy (di->method_to_table_idx);
4867         if (di->field_to_table_idx)
4868                 g_hash_table_destroy (di->field_to_table_idx);
4869         if (di->method_aux_hash)
4870                 g_hash_table_destroy (di->method_aux_hash);
4871         g_free (di->strong_name);
4872         g_free (di->win32_res);
4873         if (di->public_key)
4874                 g_free (di->public_key);
4875
4876         /*g_print ("string heap destroy for image %p\n", di);*/
4877         mono_dynamic_stream_reset (&di->sheap);
4878         mono_dynamic_stream_reset (&di->code);
4879         mono_dynamic_stream_reset (&di->resources);
4880         mono_dynamic_stream_reset (&di->us);
4881         mono_dynamic_stream_reset (&di->blob);
4882         mono_dynamic_stream_reset (&di->tstream);
4883         mono_dynamic_stream_reset (&di->guid);
4884         for (i = 0; i < MONO_TABLE_NUM; ++i) {
4885                 g_free (di->tables [i].values);
4886         }
4887 }       
4888
4889 #ifndef DISABLE_REFLECTION_EMIT
4890
4891 /*
4892  * mono_image_basic_init:
4893  * @assembly: an assembly builder object
4894  *
4895  * Create the MonoImage that represents the assembly builder and setup some
4896  * of the helper hash table and the basic metadata streams.
4897  */
4898 void
4899 mono_image_basic_init (MonoReflectionAssemblyBuilder *assemblyb)
4900 {
4901         MonoDynamicAssembly *assembly;
4902         MonoDynamicImage *image;
4903         MonoDomain *domain = mono_object_domain (assemblyb);
4904         
4905         MONO_ARCH_SAVE_REGS;
4906
4907         if (assemblyb->dynamic_assembly)
4908                 return;
4909
4910 #if HAVE_BOEHM_GC
4911         assembly = assemblyb->dynamic_assembly = GC_MALLOC (sizeof (MonoDynamicAssembly));
4912 #else
4913         assembly = assemblyb->dynamic_assembly = g_new0 (MonoDynamicAssembly, 1);
4914 #endif
4915
4916         mono_profiler_assembly_event (&assembly->assembly, MONO_PROFILE_START_LOAD);
4917         
4918         assembly->assembly.ref_count = 1;
4919         assembly->assembly.dynamic = TRUE;
4920         assembly->assembly.corlib_internal = assemblyb->corlib_internal;
4921         assemblyb->assembly.assembly = (MonoAssembly*)assembly;
4922         assembly->assembly.basedir = mono_string_to_utf8 (assemblyb->dir);
4923         if (assemblyb->culture)
4924                 assembly->assembly.aname.culture = mono_string_to_utf8 (assemblyb->culture);
4925         else
4926                 assembly->assembly.aname.culture = g_strdup ("");
4927
4928         if (assemblyb->version) {
4929                         char *vstr = mono_string_to_utf8 (assemblyb->version);
4930                         char **version = g_strsplit (vstr, ".", 4);
4931                         char **parts = version;
4932                         assembly->assembly.aname.major = atoi (*parts++);
4933                         assembly->assembly.aname.minor = atoi (*parts++);
4934                         assembly->assembly.aname.build = *parts != NULL ? atoi (*parts++) : 0;
4935                         assembly->assembly.aname.revision = *parts != NULL ? atoi (*parts) : 0;
4936
4937                         g_strfreev (version);
4938                         g_free (vstr);
4939         } else {
4940                         assembly->assembly.aname.major = 0;
4941                         assembly->assembly.aname.minor = 0;
4942                         assembly->assembly.aname.build = 0;
4943                         assembly->assembly.aname.revision = 0;
4944         }
4945
4946         assembly->run = assemblyb->access != 2;
4947         assembly->save = assemblyb->access != 1;
4948
4949         image = create_dynamic_mono_image (assembly, mono_string_to_utf8 (assemblyb->name), g_strdup ("RefEmit_YouForgotToDefineAModule"));
4950         image->initial_image = TRUE;
4951         assembly->assembly.aname.name = image->image.name;
4952         assembly->assembly.image = &image->image;
4953
4954         mono_domain_assemblies_lock (domain);
4955         domain->domain_assemblies = g_slist_prepend (domain->domain_assemblies, assembly);
4956         mono_domain_assemblies_unlock (domain);
4957
4958         register_assembly (mono_object_domain (assemblyb), &assemblyb->assembly, &assembly->assembly);
4959         
4960         mono_profiler_assembly_loaded (&assembly->assembly, MONO_PROFILE_OK);
4961         
4962         mono_assembly_invoke_load_hook ((MonoAssembly*)assembly);
4963 }
4964
4965 #endif /* DISABLE_REFLECTION_EMIT */
4966
4967 static int
4968 calc_section_size (MonoDynamicImage *assembly)
4969 {
4970         int nsections = 0;
4971
4972         /* alignment constraints */
4973         mono_image_add_stream_zero (&assembly->code, 4 - (assembly->code.index % 4));
4974         g_assert ((assembly->code.index % 4) == 0);
4975         assembly->meta_size += 3;
4976         assembly->meta_size &= ~3;
4977         mono_image_add_stream_zero (&assembly->resources, 4 - (assembly->resources.index % 4));
4978         g_assert ((assembly->resources.index % 4) == 0);
4979
4980         assembly->sections [MONO_SECTION_TEXT].size = assembly->meta_size + assembly->code.index + assembly->resources.index + assembly->strong_name_size;
4981         assembly->sections [MONO_SECTION_TEXT].attrs = SECT_FLAGS_HAS_CODE | SECT_FLAGS_MEM_EXECUTE | SECT_FLAGS_MEM_READ;
4982         nsections++;
4983
4984         if (assembly->win32_res) {
4985                 guint32 res_size = (assembly->win32_res_size + 3) & ~3;
4986
4987                 assembly->sections [MONO_SECTION_RSRC].size = res_size;
4988                 assembly->sections [MONO_SECTION_RSRC].attrs = SECT_FLAGS_HAS_INITIALIZED_DATA | SECT_FLAGS_MEM_READ;
4989                 nsections++;
4990         }
4991
4992         assembly->sections [MONO_SECTION_RELOC].size = 12;
4993         assembly->sections [MONO_SECTION_RELOC].attrs = SECT_FLAGS_MEM_READ | SECT_FLAGS_MEM_DISCARDABLE | SECT_FLAGS_HAS_INITIALIZED_DATA;
4994         nsections++;
4995
4996         return nsections;
4997 }
4998
4999 typedef struct {
5000         guint32 id;
5001         guint32 offset;
5002         GSList *children;
5003         MonoReflectionWin32Resource *win32_res; /* Only for leaf nodes */
5004 } ResTreeNode;
5005
5006 static int
5007 resource_tree_compare_by_id (gconstpointer a, gconstpointer b)
5008 {
5009         ResTreeNode *t1 = (ResTreeNode*)a;
5010         ResTreeNode *t2 = (ResTreeNode*)b;
5011
5012         return t1->id - t2->id;
5013 }
5014
5015 /*
5016  * resource_tree_create:
5017  *
5018  *  Organize the resources into a resource tree.
5019  */
5020 static ResTreeNode *
5021 resource_tree_create (MonoArray *win32_resources)
5022 {
5023         ResTreeNode *tree, *res_node, *type_node, *lang_node;
5024         GSList *l;
5025         int i;
5026
5027         tree = g_new0 (ResTreeNode, 1);
5028         
5029         for (i = 0; i < mono_array_length (win32_resources); ++i) {
5030                 MonoReflectionWin32Resource *win32_res =
5031                         (MonoReflectionWin32Resource*)mono_array_addr (win32_resources, MonoReflectionWin32Resource, i);
5032
5033                 /* Create node */
5034
5035                 /* FIXME: BUG: this stores managed references in unmanaged memory */
5036                 lang_node = g_new0 (ResTreeNode, 1);
5037                 lang_node->id = win32_res->lang_id;
5038                 lang_node->win32_res = win32_res;
5039
5040                 /* Create type node if neccesary */
5041                 type_node = NULL;
5042                 for (l = tree->children; l; l = l->next)
5043                         if (((ResTreeNode*)(l->data))->id == win32_res->res_type) {
5044                                 type_node = (ResTreeNode*)l->data;
5045                                 break;
5046                         }
5047
5048                 if (!type_node) {
5049                         type_node = g_new0 (ResTreeNode, 1);
5050                         type_node->id = win32_res->res_type;
5051
5052                         /* 
5053                          * The resource types have to be sorted otherwise
5054                          * Windows Explorer can't display the version information.
5055                          */
5056                         tree->children = g_slist_insert_sorted (tree->children, 
5057                                 type_node, resource_tree_compare_by_id);
5058                 }
5059
5060                 /* Create res node if neccesary */
5061                 res_node = NULL;
5062                 for (l = type_node->children; l; l = l->next)
5063                         if (((ResTreeNode*)(l->data))->id == win32_res->res_id) {
5064                                 res_node = (ResTreeNode*)l->data;
5065                                 break;
5066                         }
5067
5068                 if (!res_node) {
5069                         res_node = g_new0 (ResTreeNode, 1);
5070                         res_node->id = win32_res->res_id;
5071                         type_node->children = g_slist_append (type_node->children, res_node);
5072                 }
5073
5074                 res_node->children = g_slist_append (res_node->children, lang_node);
5075         }
5076
5077         return tree;
5078 }
5079
5080 /*
5081  * resource_tree_encode:
5082  * 
5083  *   Encode the resource tree into the format used in the PE file.
5084  */
5085 static void
5086 resource_tree_encode (ResTreeNode *node, char *begin, char *p, char **endbuf)
5087 {
5088         char *entries;
5089         MonoPEResourceDir dir;
5090         MonoPEResourceDirEntry dir_entry;
5091         MonoPEResourceDataEntry data_entry;
5092         GSList *l;
5093         guint32 res_id_entries;
5094
5095         /*
5096          * For the format of the resource directory, see the article
5097          * "An In-Depth Look into the Win32 Portable Executable File Format" by
5098          * Matt Pietrek
5099          */
5100
5101         memset (&dir, 0, sizeof (dir));
5102         memset (&dir_entry, 0, sizeof (dir_entry));
5103         memset (&data_entry, 0, sizeof (data_entry));
5104
5105         g_assert (sizeof (dir) == 16);
5106         g_assert (sizeof (dir_entry) == 8);
5107         g_assert (sizeof (data_entry) == 16);
5108
5109         node->offset = p - begin;
5110
5111         /* IMAGE_RESOURCE_DIRECTORY */
5112         res_id_entries = g_slist_length (node->children);
5113         dir.res_id_entries = GUINT16_TO_LE (res_id_entries);
5114
5115         memcpy (p, &dir, sizeof (dir));
5116         p += sizeof (dir);
5117
5118         /* Reserve space for entries */
5119         entries = p;
5120         p += sizeof (dir_entry) * res_id_entries;
5121
5122         /* Write children */
5123         for (l = node->children; l; l = l->next) {
5124                 ResTreeNode *child = (ResTreeNode*)l->data;
5125
5126                 if (child->win32_res) {
5127                         guint32 size;
5128
5129                         child->offset = p - begin;
5130
5131                         /* IMAGE_RESOURCE_DATA_ENTRY */
5132                         data_entry.rde_data_offset = GUINT32_TO_LE (p - begin + sizeof (data_entry));
5133                         size = mono_array_length (child->win32_res->res_data);
5134                         data_entry.rde_size = GUINT32_TO_LE (size);
5135
5136                         memcpy (p, &data_entry, sizeof (data_entry));
5137                         p += sizeof (data_entry);
5138
5139                         memcpy (p, mono_array_addr (child->win32_res->res_data, char, 0), size);
5140                         p += size;
5141                 } else {
5142                         resource_tree_encode (child, begin, p, &p);
5143                 }
5144         }
5145
5146         /* IMAGE_RESOURCE_ENTRY */
5147         for (l = node->children; l; l = l->next) {
5148                 ResTreeNode *child = (ResTreeNode*)l->data;
5149
5150                 MONO_PE_RES_DIR_ENTRY_SET_NAME (dir_entry, FALSE, child->id);
5151                 MONO_PE_RES_DIR_ENTRY_SET_DIR (dir_entry, !child->win32_res, child->offset);
5152
5153                 memcpy (entries, &dir_entry, sizeof (dir_entry));
5154                 entries += sizeof (dir_entry);
5155         }
5156
5157         *endbuf = p;
5158 }
5159
5160 static void
5161 resource_tree_free (ResTreeNode * node)
5162 {
5163         GSList * list;
5164         for (list = node->children; list; list = list->next)
5165                 resource_tree_free ((ResTreeNode*)list->data);
5166         g_slist_free(node->children);
5167         g_free (node);
5168 }
5169
5170 static void
5171 assembly_add_win32_resources (MonoDynamicImage *assembly, MonoReflectionAssemblyBuilder *assemblyb)
5172 {
5173         char *buf;
5174         char *p;
5175         guint32 size, i;
5176         MonoReflectionWin32Resource *win32_res;
5177         ResTreeNode *tree;
5178
5179         if (!assemblyb->win32_resources)
5180                 return;
5181
5182         /*
5183          * Resources are stored in a three level tree inside the PE file.
5184          * - level one contains a node for each type of resource
5185          * - level two contains a node for each resource
5186          * - level three contains a node for each instance of a resource for a
5187          *   specific language.
5188          */
5189
5190         tree = resource_tree_create (assemblyb->win32_resources);
5191
5192         /* Estimate the size of the encoded tree */
5193         size = 0;
5194         for (i = 0; i < mono_array_length (assemblyb->win32_resources); ++i) {
5195                 win32_res = (MonoReflectionWin32Resource*)mono_array_addr (assemblyb->win32_resources, MonoReflectionWin32Resource, i);
5196                 size += mono_array_length (win32_res->res_data);
5197         }
5198         /* Directory structure */
5199         size += mono_array_length (assemblyb->win32_resources) * 256;
5200         p = buf = g_malloc (size);
5201
5202         resource_tree_encode (tree, p, p, &p);
5203
5204         g_assert (p - buf <= size);
5205
5206         assembly->win32_res = g_malloc (p - buf);
5207         assembly->win32_res_size = p - buf;
5208         memcpy (assembly->win32_res, buf, p - buf);
5209
5210         g_free (buf);
5211         resource_tree_free (tree);
5212 }
5213
5214 static void
5215 fixup_resource_directory (char *res_section, char *p, guint32 rva)
5216 {
5217         MonoPEResourceDir *dir = (MonoPEResourceDir*)p;
5218         int i;
5219
5220         p += sizeof (MonoPEResourceDir);
5221         for (i = 0; i < GUINT16_FROM_LE (dir->res_named_entries) + GUINT16_FROM_LE (dir->res_id_entries); ++i) {
5222                 MonoPEResourceDirEntry *dir_entry = (MonoPEResourceDirEntry*)p;
5223                 char *child = res_section + MONO_PE_RES_DIR_ENTRY_DIR_OFFSET (*dir_entry);
5224                 if (MONO_PE_RES_DIR_ENTRY_IS_DIR (*dir_entry)) {
5225                         fixup_resource_directory (res_section, child, rva);
5226                 } else {
5227                         MonoPEResourceDataEntry *data_entry = (MonoPEResourceDataEntry*)child;
5228                         data_entry->rde_data_offset = GUINT32_TO_LE (GUINT32_FROM_LE (data_entry->rde_data_offset) + rva);
5229                 }
5230
5231                 p += sizeof (MonoPEResourceDirEntry);
5232         }
5233 }
5234
5235 static void
5236 checked_write_file (HANDLE f, gconstpointer buffer, guint32 numbytes)
5237 {
5238         guint32 dummy;
5239         if (!WriteFile (f, buffer, numbytes, &dummy, NULL))
5240                 g_error ("WriteFile returned %d\n", GetLastError ());
5241 }
5242
5243 #ifndef DISABLE_REFLECTION_EMIT_SAVE
5244
5245 /*
5246  * mono_image_create_pefile:
5247  * @mb: a module builder object
5248  * 
5249  * This function creates the PE-COFF header, the image sections, the CLI header  * etc. all the data is written in
5250  * assembly->pefile where it can be easily retrieved later in chunks.
5251  */
5252 void
5253 mono_image_create_pefile (MonoReflectionModuleBuilder *mb, HANDLE file)
5254 {
5255         MonoMSDOSHeader *msdos;
5256         MonoDotNetHeader *header;
5257         MonoSectionTable *section;
5258         MonoCLIHeader *cli_header;
5259         guint32 size, image_size, virtual_base, text_offset;
5260         guint32 header_start, section_start, file_offset, virtual_offset;
5261         MonoDynamicImage *assembly;
5262         MonoReflectionAssemblyBuilder *assemblyb;
5263         MonoDynamicStream pefile_stream = {0};
5264         MonoDynamicStream *pefile = &pefile_stream;
5265         int i, nsections;
5266         guint32 *rva, value;
5267         guchar *p;
5268         static const unsigned char msheader[] = {
5269                 0x4d, 0x5a, 0x90, 0x00, 0x03, 0x00, 0x00, 0x00,  0x04, 0x00, 0x00, 0x00, 0xff, 0xff, 0x00, 0x00,
5270                 0xb8, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,  0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
5271                 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
5272                 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,  0x00, 0x00, 0x00, 0x00, 0x80, 0x00, 0x00, 0x00,
5273                 0x0e, 0x1f, 0xba, 0x0e, 0x00, 0xb4, 0x09, 0xcd,  0x21, 0xb8, 0x01, 0x4c, 0xcd, 0x21, 0x54, 0x68,
5274                 0x69, 0x73, 0x20, 0x70, 0x72, 0x6f, 0x67, 0x72,  0x61, 0x6d, 0x20, 0x63, 0x61, 0x6e, 0x6e, 0x6f,
5275                 0x74, 0x20, 0x62, 0x65, 0x20, 0x72, 0x75, 0x6e,  0x20, 0x69, 0x6e, 0x20, 0x44, 0x4f, 0x53, 0x20,
5276                 0x6d, 0x6f, 0x64, 0x65, 0x2e, 0x0d, 0x0d, 0x0a,  0x24, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
5277         };
5278
5279         assemblyb = mb->assemblyb;
5280
5281         mono_image_basic_init (assemblyb);
5282         assembly = mb->dynamic_image;
5283
5284         assembly->pe_kind = assemblyb->pe_kind;
5285         assembly->machine = assemblyb->machine;
5286         ((MonoDynamicImage*)assemblyb->dynamic_assembly->assembly.image)->pe_kind = assemblyb->pe_kind;
5287         ((MonoDynamicImage*)assemblyb->dynamic_assembly->assembly.image)->machine = assemblyb->machine;
5288         
5289         mono_image_build_metadata (mb);
5290
5291         if (mb->is_main && assemblyb->resources) {
5292                 int len = mono_array_length (assemblyb->resources);
5293                 for (i = 0; i < len; ++i)
5294                         assembly_add_resource (mb, assembly, (MonoReflectionResource*)mono_array_addr (assemblyb->resources, MonoReflectionResource, i));
5295         }
5296
5297         if (mb->resources) {
5298                 int len = mono_array_length (mb->resources);
5299                 for (i = 0; i < len; ++i)
5300                         assembly_add_resource (mb, assembly, (MonoReflectionResource*)mono_array_addr (mb->resources, MonoReflectionResource, i));
5301         }
5302
5303         build_compressed_metadata (assembly);
5304
5305         if (mb->is_main)
5306                 assembly_add_win32_resources (assembly, assemblyb);
5307
5308         nsections = calc_section_size (assembly);
5309         
5310         /* The DOS header and stub */
5311         g_assert (sizeof (MonoMSDOSHeader) == sizeof (msheader));
5312         mono_image_add_stream_data (pefile, (char*)msheader, sizeof (msheader));
5313
5314         /* the dotnet header */
5315         header_start = mono_image_add_stream_zero (pefile, sizeof (MonoDotNetHeader));
5316
5317         /* the section tables */
5318         section_start = mono_image_add_stream_zero (pefile, sizeof (MonoSectionTable) * nsections);
5319
5320         file_offset = section_start + sizeof (MonoSectionTable) * nsections;
5321         virtual_offset = VIRT_ALIGN;
5322         image_size = 0;
5323
5324         for (i = 0; i < MONO_SECTION_MAX; ++i) {
5325                 if (!assembly->sections [i].size)
5326                         continue;
5327                 /* align offsets */
5328                 file_offset += FILE_ALIGN - 1;
5329                 file_offset &= ~(FILE_ALIGN - 1);
5330                 virtual_offset += VIRT_ALIGN - 1;
5331                 virtual_offset &= ~(VIRT_ALIGN - 1);
5332
5333                 assembly->sections [i].offset = file_offset;
5334                 assembly->sections [i].rva = virtual_offset;
5335
5336                 file_offset += assembly->sections [i].size;
5337                 virtual_offset += assembly->sections [i].size;
5338                 image_size += (assembly->sections [i].size + VIRT_ALIGN - 1) & ~(VIRT_ALIGN - 1);
5339         }
5340
5341         file_offset += FILE_ALIGN - 1;
5342         file_offset &= ~(FILE_ALIGN - 1);
5343
5344         image_size += section_start + sizeof (MonoSectionTable) * nsections;
5345
5346         /* back-patch info */
5347         msdos = (MonoMSDOSHeader*)pefile->data;
5348         msdos->pe_offset = GUINT32_FROM_LE (sizeof (MonoMSDOSHeader));
5349
5350         header = (MonoDotNetHeader*)(pefile->data + header_start);
5351         header->pesig [0] = 'P';
5352         header->pesig [1] = 'E';
5353         
5354         header->coff.coff_machine = GUINT16_FROM_LE (assemblyb->machine);
5355         header->coff.coff_sections = GUINT16_FROM_LE (nsections);
5356         header->coff.coff_time = GUINT32_FROM_LE (time (NULL));
5357         header->coff.coff_opt_header_size = GUINT16_FROM_LE (sizeof (MonoDotNetHeader) - sizeof (MonoCOFFHeader) - 4);
5358         if (assemblyb->pekind == 1) {
5359                 /* it's a dll */
5360                 header->coff.coff_attributes = GUINT16_FROM_LE (0x210e);
5361         } else {
5362                 /* it's an exe */
5363                 header->coff.coff_attributes = GUINT16_FROM_LE (0x010e);
5364         }
5365
5366         virtual_base = 0x400000; /* FIXME: 0x10000000 if a DLL */
5367
5368         header->pe.pe_magic = GUINT16_FROM_LE (0x10B);
5369         header->pe.pe_major = 6;
5370         header->pe.pe_minor = 0;
5371         size = assembly->sections [MONO_SECTION_TEXT].size;
5372         size += FILE_ALIGN - 1;
5373         size &= ~(FILE_ALIGN - 1);
5374         header->pe.pe_code_size = GUINT32_FROM_LE(size);
5375         size = assembly->sections [MONO_SECTION_RSRC].size;
5376         size += FILE_ALIGN - 1;
5377         size &= ~(FILE_ALIGN - 1);
5378         header->pe.pe_data_size = GUINT32_FROM_LE(size);
5379         g_assert (START_TEXT_RVA == assembly->sections [MONO_SECTION_TEXT].rva);
5380         header->pe.pe_rva_code_base = GUINT32_FROM_LE (assembly->sections [MONO_SECTION_TEXT].rva);
5381         header->pe.pe_rva_data_base = GUINT32_FROM_LE (assembly->sections [MONO_SECTION_RSRC].rva);
5382         /* pe_rva_entry_point always at the beginning of the text section */
5383         header->pe.pe_rva_entry_point = GUINT32_FROM_LE (assembly->sections [MONO_SECTION_TEXT].rva);
5384
5385         header->nt.pe_image_base = GUINT32_FROM_LE (virtual_base);
5386         header->nt.pe_section_align = GUINT32_FROM_LE (VIRT_ALIGN);
5387         header->nt.pe_file_alignment = GUINT32_FROM_LE (FILE_ALIGN);
5388         header->nt.pe_os_major = GUINT16_FROM_LE (4);
5389         header->nt.pe_os_minor = GUINT16_FROM_LE (0);
5390         header->nt.pe_subsys_major = GUINT16_FROM_LE (4);
5391         size = section_start;
5392         size += FILE_ALIGN - 1;
5393         size &= ~(FILE_ALIGN - 1);
5394         header->nt.pe_header_size = GUINT32_FROM_LE (size);
5395         size = image_size;
5396         size += VIRT_ALIGN - 1;
5397         size &= ~(VIRT_ALIGN - 1);
5398         header->nt.pe_image_size = GUINT32_FROM_LE (size);
5399
5400         /*
5401         // Translate the PEFileKind value to the value expected by the Windows loader
5402         */
5403         {
5404                 short kind;
5405
5406                 /*
5407                 // PEFileKinds.Dll == 1
5408                 // PEFileKinds.ConsoleApplication == 2
5409                 // PEFileKinds.WindowApplication == 3
5410                 //
5411                 // need to get:
5412                 //     IMAGE_SUBSYSTEM_WINDOWS_GUI 2 // Image runs in the Windows GUI subsystem.
5413                 //     IMAGE_SUBSYSTEM_WINDOWS_CUI 3 // Image runs in the Windows character subsystem.
5414                 */
5415                 if (assemblyb->pekind == 3)
5416                         kind = 2;
5417                 else
5418                         kind = 3;
5419                 
5420                 header->nt.pe_subsys_required = GUINT16_FROM_LE (kind);
5421         }    
5422         header->nt.pe_stack_reserve = GUINT32_FROM_LE (0x00100000);
5423         header->nt.pe_stack_commit = GUINT32_FROM_LE (0x00001000);
5424         header->nt.pe_heap_reserve = GUINT32_FROM_LE (0x00100000);
5425         header->nt.pe_heap_commit = GUINT32_FROM_LE (0x00001000);
5426         header->nt.pe_loader_flags = GUINT32_FROM_LE (0);
5427         header->nt.pe_data_dir_count = GUINT32_FROM_LE (16);
5428
5429         /* fill data directory entries */
5430
5431         header->datadir.pe_resource_table.size = GUINT32_FROM_LE (assembly->sections [MONO_SECTION_RSRC].size);
5432         header->datadir.pe_resource_table.rva = GUINT32_FROM_LE (assembly->sections [MONO_SECTION_RSRC].rva);
5433
5434         header->datadir.pe_reloc_table.size = GUINT32_FROM_LE (assembly->sections [MONO_SECTION_RELOC].size);
5435         header->datadir.pe_reloc_table.rva = GUINT32_FROM_LE (assembly->sections [MONO_SECTION_RELOC].rva);
5436
5437         header->datadir.pe_cli_header.size = GUINT32_FROM_LE (72);
5438         header->datadir.pe_cli_header.rva = GUINT32_FROM_LE (assembly->text_rva + assembly->cli_header_offset);
5439         header->datadir.pe_iat.size = GUINT32_FROM_LE (8);
5440         header->datadir.pe_iat.rva = GUINT32_FROM_LE (assembly->text_rva + assembly->iat_offset);
5441         /* patch entrypoint name */
5442         if (assemblyb->pekind == 1)
5443                 memcpy (assembly->code.data + assembly->imp_names_offset + 2, "_CorDllMain", 12);
5444         else
5445                 memcpy (assembly->code.data + assembly->imp_names_offset + 2, "_CorExeMain", 12);
5446         /* patch imported function RVA name */
5447         rva = (guint32*)(assembly->code.data + assembly->iat_offset);
5448         *rva = GUINT32_FROM_LE (assembly->text_rva + assembly->imp_names_offset);
5449
5450         /* the import table */
5451         header->datadir.pe_import_table.size = GUINT32_FROM_LE (79); /* FIXME: magic number? */
5452         header->datadir.pe_import_table.rva = GUINT32_FROM_LE (assembly->text_rva + assembly->idt_offset);
5453         /* patch imported dll RVA name and other entries in the dir */
5454         rva = (guint32*)(assembly->code.data + assembly->idt_offset + G_STRUCT_OFFSET (MonoIDT, name_rva));
5455         *rva = GUINT32_FROM_LE (assembly->text_rva + assembly->imp_names_offset + 14); /* 14 is hint+strlen+1 of func name */
5456         rva = (guint32*)(assembly->code.data + assembly->idt_offset + G_STRUCT_OFFSET (MonoIDT, import_address_table_rva));
5457         *rva = GUINT32_FROM_LE (assembly->text_rva + assembly->iat_offset);
5458         rva = (guint32*)(assembly->code.data + assembly->idt_offset + G_STRUCT_OFFSET (MonoIDT, import_lookup_table));
5459         *rva = GUINT32_FROM_LE (assembly->text_rva + assembly->ilt_offset);
5460
5461         p = (guchar*)(assembly->code.data + assembly->ilt_offset);
5462         value = (assembly->text_rva + assembly->imp_names_offset);
5463         *p++ = (value) & 0xff;
5464         *p++ = (value >> 8) & (0xff);
5465         *p++ = (value >> 16) & (0xff);
5466         *p++ = (value >> 24) & (0xff);
5467
5468         /* the CLI header info */
5469         cli_header = (MonoCLIHeader*)(assembly->code.data + assembly->cli_header_offset);
5470         cli_header->ch_size = GUINT32_FROM_LE (72);
5471         cli_header->ch_runtime_major = GUINT16_FROM_LE (2);
5472         if (mono_framework_version () > 1)
5473                 cli_header->ch_runtime_minor = GUINT16_FROM_LE (5);
5474         else 
5475                 cli_header->ch_runtime_minor = GUINT16_FROM_LE (0);
5476         cli_header->ch_flags = GUINT32_FROM_LE (assemblyb->pe_kind);
5477         if (assemblyb->entry_point) {
5478                 guint32 table_idx = 0;
5479                 if (!strcmp (assemblyb->entry_point->object.vtable->klass->name, "MethodBuilder")) {
5480                         MonoReflectionMethodBuilder *methodb = (MonoReflectionMethodBuilder*)assemblyb->entry_point;
5481                         table_idx = methodb->table_idx;
5482                 } else {
5483                         table_idx = GPOINTER_TO_UINT (g_hash_table_lookup (assembly->method_to_table_idx, assemblyb->entry_point->method));
5484                 }
5485                 cli_header->ch_entry_point = GUINT32_FROM_LE (table_idx | MONO_TOKEN_METHOD_DEF);
5486         } else {
5487                 cli_header->ch_entry_point = GUINT32_FROM_LE (0);
5488         }
5489         /* The embedded managed resources */
5490         text_offset = assembly->text_rva + assembly->code.index;
5491         cli_header->ch_resources.rva = GUINT32_FROM_LE (text_offset);
5492         cli_header->ch_resources.size = GUINT32_FROM_LE (assembly->resources.index);
5493         text_offset += assembly->resources.index;
5494         cli_header->ch_metadata.rva = GUINT32_FROM_LE (text_offset);
5495         cli_header->ch_metadata.size = GUINT32_FROM_LE (assembly->meta_size);
5496         text_offset += assembly->meta_size;
5497         if (assembly->strong_name_size) {
5498                 cli_header->ch_strong_name.rva = GUINT32_FROM_LE (text_offset);
5499                 cli_header->ch_strong_name.size = GUINT32_FROM_LE (assembly->strong_name_size);
5500                 text_offset += assembly->strong_name_size;
5501         }
5502
5503         /* write the section tables and section content */
5504         section = (MonoSectionTable*)(pefile->data + section_start);
5505         for (i = 0; i < MONO_SECTION_MAX; ++i) {
5506                 static const char section_names [][7] = {
5507                         ".text", ".rsrc", ".reloc"
5508                 };
5509                 if (!assembly->sections [i].size)
5510                         continue;
5511                 strcpy (section->st_name, section_names [i]);
5512                 /*g_print ("output section %s (%d), size: %d\n", section->st_name, i, assembly->sections [i].size);*/
5513                 section->st_virtual_address = GUINT32_FROM_LE (assembly->sections [i].rva);
5514                 section->st_virtual_size = GUINT32_FROM_LE (assembly->sections [i].size);
5515                 section->st_raw_data_size = GUINT32_FROM_LE (GUINT32_TO_LE (section->st_virtual_size) + (FILE_ALIGN - 1));
5516                 section->st_raw_data_size &= GUINT32_FROM_LE (~(FILE_ALIGN - 1));
5517                 section->st_raw_data_ptr = GUINT32_FROM_LE (assembly->sections [i].offset);
5518                 section->st_flags = GUINT32_FROM_LE (assembly->sections [i].attrs);
5519                 section ++;
5520         }
5521         
5522         checked_write_file (file, pefile->data, pefile->index);
5523         
5524         mono_dynamic_stream_reset (pefile);
5525         
5526         for (i = 0; i < MONO_SECTION_MAX; ++i) {
5527                 if (!assembly->sections [i].size)
5528                         continue;
5529                 
5530                 if (SetFilePointer (file, assembly->sections [i].offset, NULL, FILE_BEGIN) == INVALID_SET_FILE_POINTER)
5531                         g_error ("SetFilePointer returned %d\n", GetLastError ());
5532                 
5533                 switch (i) {
5534                 case MONO_SECTION_TEXT:
5535                         /* patch entry point */
5536                         p = (guchar*)(assembly->code.data + 2);
5537                         value = (virtual_base + assembly->text_rva + assembly->iat_offset);
5538                         *p++ = (value) & 0xff;
5539                         *p++ = (value >> 8) & 0xff;
5540                         *p++ = (value >> 16) & 0xff;
5541                         *p++ = (value >> 24) & 0xff;
5542                 
5543                         checked_write_file (file, assembly->code.data, assembly->code.index);
5544                         checked_write_file (file, assembly->resources.data, assembly->resources.index);
5545                         checked_write_file (file, assembly->image.raw_metadata, assembly->meta_size);
5546                         checked_write_file (file, assembly->strong_name, assembly->strong_name_size);
5547                                 
5548
5549                         g_free (assembly->image.raw_metadata);
5550                         break;
5551                 case MONO_SECTION_RELOC: {
5552                         struct {
5553                                 guint32 page_rva;
5554                                 guint32 block_size;
5555                                 guint16 type_and_offset;
5556                                 guint16 term;
5557                         } reloc;
5558                         
5559                         g_assert (sizeof (reloc) == 12);
5560                         
5561                         reloc.page_rva = GUINT32_FROM_LE (assembly->text_rva);
5562                         reloc.block_size = GUINT32_FROM_LE (12);
5563                         
5564                         /* 
5565                          * the entrypoint is always at the start of the text section 
5566                          * 3 is IMAGE_REL_BASED_HIGHLOW
5567                          * 2 is patch_size_rva - text_rva
5568                          */
5569                         reloc.type_and_offset = GUINT16_FROM_LE ((3 << 12) + (2));
5570                         reloc.term = 0;
5571                         
5572                         checked_write_file (file, &reloc, sizeof (reloc));
5573                         
5574                         break;
5575                 }
5576                 case MONO_SECTION_RSRC:
5577                         if (assembly->win32_res) {
5578
5579                                 /* Fixup the offsets in the IMAGE_RESOURCE_DATA_ENTRY structures */
5580                                 fixup_resource_directory (assembly->win32_res, assembly->win32_res, assembly->sections [i].rva);
5581                                 checked_write_file (file, assembly->win32_res, assembly->win32_res_size);
5582                         }
5583                         break;
5584                 default:
5585                         g_assert_not_reached ();
5586                 }
5587         }
5588         
5589         /* check that the file is properly padded */
5590         if (SetFilePointer (file, file_offset, NULL, FILE_BEGIN) == INVALID_SET_FILE_POINTER)
5591                 g_error ("SetFilePointer returned %d\n", GetLastError ());
5592         if (! SetEndOfFile (file))
5593                 g_error ("SetEndOfFile returned %d\n", GetLastError ());
5594         
5595         mono_dynamic_stream_reset (&assembly->code);
5596         mono_dynamic_stream_reset (&assembly->us);
5597         mono_dynamic_stream_reset (&assembly->blob);
5598         mono_dynamic_stream_reset (&assembly->guid);
5599         mono_dynamic_stream_reset (&assembly->sheap);
5600
5601         g_hash_table_foreach (assembly->blob_cache, (GHFunc)g_free, NULL);
5602         g_hash_table_destroy (assembly->blob_cache);
5603         assembly->blob_cache = NULL;
5604 }
5605
5606 #else /* DISABLE_REFLECTION_EMIT_SAVE */
5607
5608 void
5609 mono_image_create_pefile (MonoReflectionModuleBuilder *mb, HANDLE file)
5610 {
5611         g_assert_not_reached ();
5612 }
5613
5614 #endif /* DISABLE_REFLECTION_EMIT_SAVE */
5615
5616 #ifndef DISABLE_REFLECTION_EMIT
5617
5618 MonoReflectionModule *
5619 mono_image_load_module_dynamic (MonoReflectionAssemblyBuilder *ab, MonoString *fileName)
5620 {
5621         char *name;
5622         MonoImage *image;
5623         MonoImageOpenStatus status;
5624         MonoDynamicAssembly *assembly;
5625         guint32 module_count;
5626         MonoImage **new_modules;
5627         gboolean *new_modules_loaded;
5628         
5629         name = mono_string_to_utf8 (fileName);
5630
5631         image = mono_image_open (name, &status);
5632         if (!image) {
5633                 MonoException *exc;
5634                 if (status == MONO_IMAGE_ERROR_ERRNO)
5635                         exc = mono_get_exception_file_not_found (fileName);
5636                 else
5637                         exc = mono_get_exception_bad_image_format (name);
5638                 g_free (name);
5639                 mono_raise_exception (exc);
5640         }
5641
5642         g_free (name);
5643
5644         assembly = ab->dynamic_assembly;
5645         image->assembly = (MonoAssembly*)assembly;
5646
5647         module_count = image->assembly->image->module_count;
5648         new_modules = g_new0 (MonoImage *, module_count + 1);
5649         new_modules_loaded = g_new0 (gboolean, module_count + 1);
5650
5651         if (image->assembly->image->modules)
5652                 memcpy (new_modules, image->assembly->image->modules, module_count * sizeof (MonoImage *));
5653         if (image->assembly->image->modules_loaded)
5654                 memcpy (new_modules_loaded, image->assembly->image->modules_loaded, module_count * sizeof (gboolean));
5655         new_modules [module_count] = image;
5656         new_modules_loaded [module_count] = TRUE;
5657         mono_image_addref (image);
5658
5659         g_free (image->assembly->image->modules);
5660         image->assembly->image->modules = new_modules;
5661         image->assembly->image->modules_loaded = new_modules_loaded;
5662         image->assembly->image->module_count ++;
5663
5664         mono_assembly_load_references (image, &status);
5665         if (status) {
5666                 mono_image_close (image);
5667                 mono_raise_exception (mono_get_exception_file_not_found (fileName));
5668         }
5669
5670         return mono_module_get_object (mono_domain_get (), image);
5671 }
5672
5673 #endif /* DISABLE_REFLECTION_EMIT */
5674
5675 /*
5676  * We need to return always the same object for MethodInfo, FieldInfo etc..
5677  * but we need to consider the reflected type.
5678  * type uses a different hash, since it uses custom hash/equal functions.
5679  */
5680
5681 typedef struct {
5682         gpointer item;
5683         MonoClass *refclass;
5684 } ReflectedEntry;
5685
5686 static gboolean
5687 reflected_equal (gconstpointer a, gconstpointer b) {
5688         const ReflectedEntry *ea = a;
5689         const ReflectedEntry *eb = b;
5690
5691         return (ea->item == eb->item) && (ea->refclass == eb->refclass);
5692 }
5693
5694 static guint
5695 reflected_hash (gconstpointer a) {
5696         const ReflectedEntry *ea = a;
5697         return mono_aligned_addr_hash (ea->item);
5698 }
5699
5700 #define CHECK_OBJECT(t,p,k)     \
5701         do {    \
5702                 t _obj; \
5703                 ReflectedEntry e;       \
5704                 e.item = (p);   \
5705                 e.refclass = (k);       \
5706                 mono_domain_lock (domain);      \
5707                 if (!domain->refobject_hash)    \
5708                         domain->refobject_hash = mono_g_hash_table_new_type (reflected_hash, reflected_equal, MONO_HASH_VALUE_GC);      \
5709                 if ((_obj = mono_g_hash_table_lookup (domain->refobject_hash, &e))) {   \
5710                         mono_domain_unlock (domain);    \
5711                         return _obj;    \
5712                 }       \
5713         mono_domain_unlock (domain); \
5714         } while (0)
5715
5716 #ifdef HAVE_BOEHM_GC
5717 #define ALLOC_REFENTRY mono_gc_alloc_fixed (sizeof (ReflectedEntry), NULL)
5718 #define FREE_REFENTRY(entry) mono_gc_free_fixed ((entry))
5719 #else
5720 #define ALLOC_REFENTRY mono_mempool_alloc (domain->mp, sizeof (ReflectedEntry))
5721 /* FIXME: */
5722 #define FREE_REFENTRY(entry)
5723 #endif
5724
5725 #define CACHE_OBJECT(t,p,o,k)   \
5726         do {    \
5727                 t _obj; \
5728         ReflectedEntry pe; \
5729         pe.item = (p); \
5730         pe.refclass = (k); \
5731         mono_domain_lock (domain); \
5732                 if (!domain->refobject_hash)    \
5733                         domain->refobject_hash = mono_g_hash_table_new_type (reflected_hash, reflected_equal, MONO_HASH_VALUE_GC);      \
5734         _obj = mono_g_hash_table_lookup (domain->refobject_hash, &pe); \
5735         if (!_obj) { \
5736                     ReflectedEntry *e = ALLOC_REFENTRY;         \
5737                     e->item = (p);      \
5738                     e->refclass = (k);  \
5739                     mono_g_hash_table_insert (domain->refobject_hash, e,o);     \
5740             _obj = o; \
5741         } \
5742                 mono_domain_unlock (domain);    \
5743         return _obj; \
5744         } while (0)
5745
5746 static void
5747 clear_cached_object (MonoDomain *domain, gpointer o, MonoClass *klass)
5748 {
5749         mono_domain_lock (domain);
5750         if (domain->refobject_hash) {
5751         ReflectedEntry pe;
5752                 gpointer orig_pe, orig_value;
5753
5754                 pe.item = o;
5755                 pe.refclass = klass;
5756                 if (mono_g_hash_table_lookup_extended (domain->refobject_hash, &pe, &orig_pe, &orig_value)) {
5757                         mono_g_hash_table_remove (domain->refobject_hash, &pe);
5758                         FREE_REFENTRY (orig_pe);
5759                 }
5760         }
5761         mono_domain_unlock (domain);
5762 }
5763
5764 static gpointer
5765 register_assembly (MonoDomain *domain, MonoReflectionAssembly *res, MonoAssembly *assembly)
5766 {
5767         CACHE_OBJECT (MonoReflectionAssembly *, assembly, res, NULL);
5768 }
5769
5770 static gpointer
5771 register_module (MonoDomain *domain, MonoReflectionModuleBuilder *res, MonoDynamicImage *module)
5772 {
5773         CACHE_OBJECT (MonoReflectionModuleBuilder *, module, res, NULL);
5774 }
5775
5776 #ifndef DISABLE_REFLECTION_EMIT
5777
5778 void
5779 mono_image_module_basic_init (MonoReflectionModuleBuilder *moduleb)
5780 {
5781         MonoDynamicImage *image = moduleb->dynamic_image;
5782         MonoReflectionAssemblyBuilder *ab = moduleb->assemblyb;
5783         if (!image) {
5784                 int module_count;
5785                 MonoImage **new_modules;
5786                 MonoImage *ass;
5787                 /*
5788                  * FIXME: we already created an image in mono_image_basic_init (), but
5789                  * we don't know which module it belongs to, since that is only 
5790                  * determined at assembly save time.
5791                  */
5792                 /*image = (MonoDynamicImage*)ab->dynamic_assembly->assembly.image; */
5793                 image = create_dynamic_mono_image (ab->dynamic_assembly, mono_string_to_utf8 (ab->name), mono_string_to_utf8 (moduleb->module.fqname));
5794
5795                 moduleb->module.image = &image->image;
5796                 moduleb->dynamic_image = image;
5797                 register_module (mono_object_domain (moduleb), moduleb, image);
5798
5799                 /* register the module with the assembly */
5800                 ass = ab->dynamic_assembly->assembly.image;
5801                 module_count = ass->module_count;
5802                 new_modules = g_new0 (MonoImage *, module_count + 1);
5803
5804                 if (ass->modules)
5805                         memcpy (new_modules, ass->modules, module_count * sizeof (MonoImage *));
5806                 new_modules [module_count] = &image->image;
5807                 mono_image_addref (&image->image);
5808
5809                 g_free (ass->modules);
5810                 ass->modules = new_modules;
5811                 ass->module_count ++;
5812         }
5813 }
5814
5815 #endif
5816
5817 /*
5818  * mono_assembly_get_object:
5819  * @domain: an app domain
5820  * @assembly: an assembly
5821  *
5822  * Return an System.Reflection.Assembly object representing the MonoAssembly @assembly.
5823  */
5824 MonoReflectionAssembly*
5825 mono_assembly_get_object (MonoDomain *domain, MonoAssembly *assembly)
5826 {
5827         static MonoClass *System_Reflection_Assembly;
5828         MonoReflectionAssembly *res;
5829         
5830         CHECK_OBJECT (MonoReflectionAssembly *, assembly, NULL);
5831         if (!System_Reflection_Assembly)
5832                 System_Reflection_Assembly = mono_class_from_name (
5833                         mono_defaults.corlib, "System.Reflection", "Assembly");
5834         res = (MonoReflectionAssembly *)mono_object_new (domain, System_Reflection_Assembly);
5835         res->assembly = assembly;
5836
5837         CACHE_OBJECT (MonoReflectionAssembly *, assembly, res, NULL);
5838 }
5839
5840
5841
5842 MonoReflectionModule*   
5843 mono_module_get_object   (MonoDomain *domain, MonoImage *image)
5844 {
5845         static MonoClass *System_Reflection_Module;
5846         MonoReflectionModule *res;
5847         char* basename;
5848         
5849         CHECK_OBJECT (MonoReflectionModule *, image, NULL);
5850         if (!System_Reflection_Module)
5851                 System_Reflection_Module = mono_class_from_name (
5852                         mono_defaults.corlib, "System.Reflection", "Module");
5853         res = (MonoReflectionModule *)mono_object_new (domain, System_Reflection_Module);
5854
5855         res->image = image;
5856         MONO_OBJECT_SETREF (res, assembly, (MonoReflectionAssembly *) mono_assembly_get_object(domain, image->assembly));
5857
5858         MONO_OBJECT_SETREF (res, fqname, mono_string_new (domain, image->name));
5859         basename = g_path_get_basename (image->name);
5860         MONO_OBJECT_SETREF (res, name, mono_string_new (domain, basename));
5861         MONO_OBJECT_SETREF (res, scopename, mono_string_new (domain, image->module_name));
5862         
5863         g_free (basename);
5864
5865         if (image->assembly->image == image) {
5866                 res->token = mono_metadata_make_token (MONO_TABLE_MODULE, 1);
5867         } else {
5868                 int i;
5869                 res->token = 0;
5870                 if (image->assembly->image->modules) {
5871                         for (i = 0; i < image->assembly->image->module_count; i++) {
5872                                 if (image->assembly->image->modules [i] == image)
5873                                         res->token = mono_metadata_make_token (MONO_TABLE_MODULEREF, i + 1);
5874                         }
5875                         g_assert (res->token);
5876                 }
5877         }
5878
5879         CACHE_OBJECT (MonoReflectionModule *, image, res, NULL);
5880 }
5881
5882 MonoReflectionModule*   
5883 mono_module_file_get_object (MonoDomain *domain, MonoImage *image, int table_index)
5884 {
5885         static MonoClass *System_Reflection_Module;
5886         MonoReflectionModule *res;
5887         MonoTableInfo *table;
5888         guint32 cols [MONO_FILE_SIZE];
5889         const char *name;
5890         guint32 i, name_idx;
5891         const char *val;
5892         
5893         if (!System_Reflection_Module)
5894                 System_Reflection_Module = mono_class_from_name (
5895                         mono_defaults.corlib, "System.Reflection", "Module");
5896         res = (MonoReflectionModule *)mono_object_new (domain, System_Reflection_Module);
5897
5898         table = &image->tables [MONO_TABLE_FILE];
5899         g_assert (table_index < table->rows);
5900         mono_metadata_decode_row (table, table_index, cols, MONO_FILE_SIZE);
5901
5902         res->image = NULL;
5903         MONO_OBJECT_SETREF (res, assembly, (MonoReflectionAssembly *) mono_assembly_get_object(domain, image->assembly));
5904         name = mono_metadata_string_heap (image, cols [MONO_FILE_NAME]);
5905
5906         /* Check whenever the row has a corresponding row in the moduleref table */
5907         table = &image->tables [MONO_TABLE_MODULEREF];
5908         for (i = 0; i < table->rows; ++i) {
5909                 name_idx = mono_metadata_decode_row_col (table, i, MONO_MODULEREF_NAME);
5910                 val = mono_metadata_string_heap (image, name_idx);
5911                 if (strcmp (val, name) == 0)
5912                         res->image = image->modules [i];
5913         }
5914
5915         MONO_OBJECT_SETREF (res, fqname, mono_string_new (domain, name));
5916         MONO_OBJECT_SETREF (res, name, mono_string_new (domain, name));
5917         MONO_OBJECT_SETREF (res, scopename, mono_string_new (domain, name));
5918         res->is_resource = cols [MONO_FILE_FLAGS] && FILE_CONTAINS_NO_METADATA;
5919         res->token = mono_metadata_make_token (MONO_TABLE_FILE, table_index + 1);
5920
5921         return res;
5922 }
5923
5924 static gboolean
5925 mymono_metadata_type_equal (MonoType *t1, MonoType *t2)
5926 {
5927         if ((t1->type != t2->type) ||
5928             (t1->byref != t2->byref))
5929                 return FALSE;
5930
5931         switch (t1->type) {
5932         case MONO_TYPE_VOID:
5933         case MONO_TYPE_BOOLEAN:
5934         case MONO_TYPE_CHAR:
5935         case MONO_TYPE_I1:
5936         case MONO_TYPE_U1:
5937         case MONO_TYPE_I2:
5938         case MONO_TYPE_U2:
5939         case MONO_TYPE_I4:
5940         case MONO_TYPE_U4:
5941         case MONO_TYPE_I8:
5942         case MONO_TYPE_U8:
5943         case MONO_TYPE_R4:
5944         case MONO_TYPE_R8:
5945         case MONO_TYPE_STRING:
5946         case MONO_TYPE_I:
5947         case MONO_TYPE_U:
5948         case MONO_TYPE_OBJECT:
5949         case MONO_TYPE_TYPEDBYREF:
5950                 return TRUE;
5951         case MONO_TYPE_VALUETYPE:
5952         case MONO_TYPE_CLASS:
5953         case MONO_TYPE_SZARRAY:
5954                 return t1->data.klass == t2->data.klass;
5955         case MONO_TYPE_PTR:
5956                 return mymono_metadata_type_equal (t1->data.type, t2->data.type);
5957         case MONO_TYPE_ARRAY:
5958                 if (t1->data.array->rank != t2->data.array->rank)
5959                         return FALSE;
5960                 return t1->data.array->eklass == t2->data.array->eklass;
5961         case MONO_TYPE_GENERICINST: {
5962                 int i;
5963                 MonoGenericInst *i1 = t1->data.generic_class->context.class_inst;
5964                 MonoGenericInst *i2 = t2->data.generic_class->context.class_inst;
5965                 if (i1->type_argc != i2->type_argc)
5966                         return FALSE;
5967                 if (!mono_metadata_type_equal (&t1->data.generic_class->container_class->byval_arg,
5968                                                &t2->data.generic_class->container_class->byval_arg))
5969                         return FALSE;
5970                 /* FIXME: we should probably just compare the instance pointers directly.  */
5971                 for (i = 0; i < i1->type_argc; ++i) {
5972                         if (!mono_metadata_type_equal (i1->type_argv [i], i2->type_argv [i]))
5973                                 return FALSE;
5974                 }
5975                 return TRUE;
5976         }
5977         case MONO_TYPE_VAR:
5978         case MONO_TYPE_MVAR:
5979                 return t1->data.generic_param == t2->data.generic_param;
5980         default:
5981                 g_error ("implement type compare for %0x!", t1->type);
5982                 return FALSE;
5983         }
5984
5985         return FALSE;
5986 }
5987
5988 static guint
5989 mymono_metadata_type_hash (MonoType *t1)
5990 {
5991         guint hash;
5992
5993         hash = t1->type;
5994
5995         hash |= t1->byref << 6; /* do not collide with t1->type values */
5996         switch (t1->type) {
5997         case MONO_TYPE_VALUETYPE:
5998         case MONO_TYPE_CLASS:
5999         case MONO_TYPE_SZARRAY:
6000                 /* check if the distribution is good enough */
6001                 return ((hash << 5) - hash) ^ g_str_hash (t1->data.klass->name);
6002         case MONO_TYPE_PTR:
6003                 return ((hash << 5) - hash) ^ mymono_metadata_type_hash (t1->data.type);
6004         case MONO_TYPE_GENERICINST: {
6005                 int i;
6006                 MonoGenericInst *inst = t1->data.generic_class->context.class_inst;
6007                 hash += g_str_hash (t1->data.generic_class->container_class->name);
6008                 hash *= 13;
6009                 for (i = 0; i < inst->type_argc; ++i) {
6010                         hash += mymono_metadata_type_hash (inst->type_argv [i]);
6011                         hash *= 13;
6012                 }
6013                 return hash;
6014         }
6015         }
6016         return hash;
6017 }
6018
6019 static MonoReflectionGenericClass*
6020 mono_generic_class_get_object (MonoDomain *domain, MonoType *geninst)
6021 {
6022         static MonoClass *System_Reflection_MonoGenericClass;
6023         MonoReflectionGenericClass *res;
6024         MonoClass *klass, *gklass;
6025
6026         if (!System_Reflection_MonoGenericClass) {
6027                 System_Reflection_MonoGenericClass = mono_class_from_name (
6028                         mono_defaults.corlib, "System.Reflection", "MonoGenericClass");
6029                 g_assert (System_Reflection_MonoGenericClass);
6030         }
6031
6032         klass = mono_class_from_mono_type (geninst);
6033         gklass = klass->generic_class->container_class;
6034
6035         mono_class_init (klass);
6036
6037 #ifdef HAVE_SGEN_GC
6038         res = (MonoReflectionGenericClass *) mono_gc_alloc_pinned_obj (mono_class_vtable (domain, System_Reflection_MonoGenericClass), mono_class_instance_size (System_Reflection_MonoGenericClass));
6039 #else
6040         res = (MonoReflectionGenericClass *) mono_object_new (domain, System_Reflection_MonoGenericClass);
6041 #endif
6042
6043         res->type.type = geninst;
6044         g_assert (gklass->reflection_info);
6045         g_assert (!strcmp (((MonoObject*)gklass->reflection_info)->vtable->klass->name, "TypeBuilder"));
6046         MONO_OBJECT_SETREF (res, generic_type, gklass->reflection_info);
6047
6048         return res;
6049 }
6050
6051 static gboolean
6052 verify_safe_for_managed_space (MonoType *type)
6053 {
6054         switch (type->type) {
6055 #ifdef DEBUG_HARDER
6056         case MONO_TYPE_ARRAY:
6057                 return verify_safe_for_managed_space (&type->data.array->eklass->byval_arg);
6058         case MONO_TYPE_PTR:
6059                 return verify_safe_for_managed_space (type->data.type);
6060         case MONO_TYPE_SZARRAY:
6061                 return verify_safe_for_managed_space (&type->data.klass->byval_arg);
6062         case MONO_TYPE_GENERICINST: {
6063                 MonoGenericInst *inst = type->data.generic_class->inst;
6064                 int i;
6065                 if (!inst->is_open)
6066                         break;
6067                 for (i = 0; i < inst->type_argc; ++i)
6068                         if (!verify_safe_for_managed_space (inst->type_argv [i]))
6069                                 return FALSE;
6070                 break;
6071         }
6072 #endif
6073         case MONO_TYPE_VAR:
6074         case MONO_TYPE_MVAR:
6075                 return TRUE;
6076         }
6077         return TRUE;
6078 }
6079
6080 /*
6081  * mono_type_get_object:
6082  * @domain: an app domain
6083  * @type: a type
6084  *
6085  * Return an System.MonoType object representing the type @type.
6086  */
6087 MonoReflectionType*
6088 mono_type_get_object (MonoDomain *domain, MonoType *type)
6089 {
6090         MonoReflectionType *res;
6091         MonoClass *klass = mono_class_from_mono_type (type);
6092
6093         /*we must avoid using @type as it might have come
6094          * from a mono_metadata_type_dup and the caller
6095          * expects that is can be freed.
6096          * Using the right type from 
6097          */
6098         type = klass->byval_arg.byref == type->byref ? &klass->byval_arg : &klass->this_arg;
6099
6100         /* void is very common */
6101         if (type->type == MONO_TYPE_VOID && domain->typeof_void)
6102                 return (MonoReflectionType*)domain->typeof_void;
6103
6104         /*
6105          * If the vtable of the given class was already created, we can use
6106          * the MonoType from there and avoid all locking and hash table lookups.
6107          * 
6108          * We cannot do this for TypeBuilders as mono_reflection_create_runtime_class expects
6109          * that the resulting object is diferent.   
6110          */
6111         if (type == &klass->byval_arg && !klass->image->dynamic) {
6112                 MonoVTable *vtable = mono_class_try_get_vtable (domain, klass);
6113                 if (vtable && vtable->type)
6114                         return vtable->type;
6115         }
6116
6117         mono_domain_lock (domain);
6118         if (!domain->type_hash)
6119                 domain->type_hash = mono_g_hash_table_new_type ((GHashFunc)mymono_metadata_type_hash, 
6120                                 (GCompareFunc)mymono_metadata_type_equal, MONO_HASH_VALUE_GC);
6121         if ((res = mono_g_hash_table_lookup (domain->type_hash, type))) {
6122                 mono_domain_unlock (domain);
6123                 return res;
6124         }
6125         /* Create a MonoGenericClass object for instantiations of not finished TypeBuilders */
6126         if ((type->type == MONO_TYPE_GENERICINST) && type->data.generic_class->is_dynamic && !type->data.generic_class->container_class->wastypebuilder) {
6127                 res = (MonoReflectionType *)mono_generic_class_get_object (domain, type);
6128                 mono_g_hash_table_insert (domain->type_hash, type, res);
6129                 mono_domain_unlock (domain);
6130                 return res;
6131         }
6132
6133         if (!verify_safe_for_managed_space (type)) {
6134                 mono_domain_unlock (domain);
6135                 mono_raise_exception (mono_get_exception_invalid_operation ("This type cannot be propagated to managed space"));
6136         }
6137
6138         if (klass->reflection_info && !klass->wastypebuilder) {
6139                 /* g_assert_not_reached (); */
6140                 /* should this be considered an error condition? */
6141                 if (!type->byref) {
6142                         mono_domain_unlock (domain);
6143                         return klass->reflection_info;
6144                 }
6145         }
6146         // FIXME: Get rid of this, do it in the icalls for Type
6147         mono_class_init (klass);
6148 #ifdef HAVE_SGEN_GC
6149         res = (MonoReflectionType *)mono_gc_alloc_pinned_obj (mono_class_vtable (domain, mono_defaults.monotype_class), mono_class_instance_size (mono_defaults.monotype_class));
6150 #else
6151         res = (MonoReflectionType *)mono_object_new (domain, mono_defaults.monotype_class);
6152 #endif
6153         res->type = type;
6154         mono_g_hash_table_insert (domain->type_hash, type, res);
6155
6156         if (type->type == MONO_TYPE_VOID)
6157                 MONO_OBJECT_SETREF (domain, typeof_void, res);
6158
6159         mono_domain_unlock (domain);
6160         return res;
6161 }
6162
6163 /*
6164  * mono_method_get_object:
6165  * @domain: an app domain
6166  * @method: a method
6167  * @refclass: the reflected type (can be NULL)
6168  *
6169  * Return an System.Reflection.MonoMethod object representing the method @method.
6170  */
6171 MonoReflectionMethod*
6172 mono_method_get_object (MonoDomain *domain, MonoMethod *method, MonoClass *refclass)
6173 {
6174         /*
6175          * We use the same C representation for methods and constructors, but the type 
6176          * name in C# is different.
6177          */
6178         static MonoClass *System_Reflection_MonoMethod = NULL;
6179         static MonoClass *System_Reflection_MonoCMethod = NULL;
6180         static MonoClass *System_Reflection_MonoGenericMethod = NULL;
6181         static MonoClass *System_Reflection_MonoGenericCMethod = NULL;
6182         MonoClass *klass;
6183         MonoReflectionMethod *ret;
6184
6185         /*
6186          * Don't let static RGCTX invoke wrappers get into
6187          * MonoReflectionMethods.
6188          */
6189         if (method->wrapper_type == MONO_WRAPPER_STATIC_RGCTX_INVOKE)
6190                 method = mono_marshal_method_from_wrapper (method);
6191
6192         if (method->is_inflated) {
6193                 MonoReflectionGenericMethod *gret;
6194
6195                 refclass = method->klass;
6196                 CHECK_OBJECT (MonoReflectionMethod *, method, refclass);
6197                 if ((*method->name == '.') && (!strcmp (method->name, ".ctor") || !strcmp (method->name, ".cctor"))) {
6198                         if (!System_Reflection_MonoGenericCMethod)
6199                                 System_Reflection_MonoGenericCMethod = mono_class_from_name (mono_defaults.corlib, "System.Reflection", "MonoGenericCMethod");
6200                         klass = System_Reflection_MonoGenericCMethod;
6201                 } else {
6202                         if (!System_Reflection_MonoGenericMethod)
6203                                 System_Reflection_MonoGenericMethod = mono_class_from_name (mono_defaults.corlib, "System.Reflection", "MonoGenericMethod");
6204                         klass = System_Reflection_MonoGenericMethod;
6205                 }
6206                 gret = (MonoReflectionGenericMethod*)mono_object_new (domain, klass);
6207                 gret->method.method = method;
6208                 MONO_OBJECT_SETREF (gret, method.name, mono_string_new (domain, method->name));
6209                 MONO_OBJECT_SETREF (gret, method.reftype, mono_type_get_object (domain, &refclass->byval_arg));
6210                 CACHE_OBJECT (MonoReflectionMethod *, method, (MonoReflectionMethod*)gret, refclass);
6211         }
6212
6213         if (!refclass)
6214                 refclass = method->klass;
6215
6216         CHECK_OBJECT (MonoReflectionMethod *, method, refclass);
6217         if (*method->name == '.' && (strcmp (method->name, ".ctor") == 0 || strcmp (method->name, ".cctor") == 0)) {
6218                 if (!System_Reflection_MonoCMethod)
6219                         System_Reflection_MonoCMethod = mono_class_from_name (mono_defaults.corlib, "System.Reflection", "MonoCMethod");
6220                 klass = System_Reflection_MonoCMethod;
6221         }
6222         else {
6223                 if (!System_Reflection_MonoMethod)
6224                         System_Reflection_MonoMethod = mono_class_from_name (mono_defaults.corlib, "System.Reflection", "MonoMethod");
6225                 klass = System_Reflection_MonoMethod;
6226         }
6227         ret = (MonoReflectionMethod*)mono_object_new (domain, klass);
6228         ret->method = method;
6229         MONO_OBJECT_SETREF (ret, reftype, mono_type_get_object (domain, &refclass->byval_arg));
6230         CACHE_OBJECT (MonoReflectionMethod *, method, ret, refclass);
6231 }
6232
6233 /*
6234  * mono_method_clear_object:
6235  *
6236  *   Clear the cached reflection objects for the dynamic method METHOD.
6237  */
6238 void
6239 mono_method_clear_object (MonoDomain *domain, MonoMethod *method)
6240 {
6241         g_assert (method->dynamic);
6242
6243         clear_cached_object (domain, method, method->klass);
6244         /* Added by mono_param_get_objects () */
6245         clear_cached_object (domain, &(method->signature), NULL);
6246 }
6247
6248 /*
6249  * mono_field_get_object:
6250  * @domain: an app domain
6251  * @klass: a type
6252  * @field: a field
6253  *
6254  * Return an System.Reflection.MonoField object representing the field @field
6255  * in class @klass.
6256  */
6257 MonoReflectionField*
6258 mono_field_get_object (MonoDomain *domain, MonoClass *klass, MonoClassField *field)
6259 {
6260         MonoReflectionField *res;
6261         static MonoClass *monofield_klass;
6262
6263         CHECK_OBJECT (MonoReflectionField *, field, klass);
6264         if (!monofield_klass)
6265                 monofield_klass = mono_class_from_name (mono_defaults.corlib, "System.Reflection", "MonoField");
6266         res = (MonoReflectionField *)mono_object_new (domain, monofield_klass);
6267         res->klass = klass;
6268         res->field = field;
6269         MONO_OBJECT_SETREF (res, name, mono_string_new (domain, mono_field_get_name (field)));
6270         if (is_field_on_inst (field))
6271                 res->attrs = get_field_on_inst_generic_type (field)->attrs;
6272         else
6273                 res->attrs = field->type->attrs;
6274         MONO_OBJECT_SETREF (res, type, mono_type_get_object (domain, field->type));
6275         CACHE_OBJECT (MonoReflectionField *, field, res, klass);
6276 }
6277
6278 /*
6279  * mono_property_get_object:
6280  * @domain: an app domain
6281  * @klass: a type
6282  * @property: a property
6283  *
6284  * Return an System.Reflection.MonoProperty object representing the property @property
6285  * in class @klass.
6286  */
6287 MonoReflectionProperty*
6288 mono_property_get_object (MonoDomain *domain, MonoClass *klass, MonoProperty *property)
6289 {
6290         MonoReflectionProperty *res;
6291         static MonoClass *monoproperty_klass;
6292
6293         CHECK_OBJECT (MonoReflectionProperty *, property, klass);
6294         if (!monoproperty_klass)
6295                 monoproperty_klass = mono_class_from_name (mono_defaults.corlib, "System.Reflection", "MonoProperty");
6296         res = (MonoReflectionProperty *)mono_object_new (domain, monoproperty_klass);
6297         res->klass = klass;
6298         res->property = property;
6299         CACHE_OBJECT (MonoReflectionProperty *, property, res, klass);
6300 }
6301
6302 /*
6303  * mono_event_get_object:
6304  * @domain: an app domain
6305  * @klass: a type
6306  * @event: a event
6307  *
6308  * Return an System.Reflection.MonoEvent object representing the event @event
6309  * in class @klass.
6310  */
6311 MonoReflectionEvent*
6312 mono_event_get_object (MonoDomain *domain, MonoClass *klass, MonoEvent *event)
6313 {
6314         MonoReflectionEvent *res;
6315         static MonoClass *monoevent_klass;
6316
6317         CHECK_OBJECT (MonoReflectionEvent *, event, klass);
6318         if (!monoevent_klass)
6319                 monoevent_klass = mono_class_from_name (mono_defaults.corlib, "System.Reflection", "MonoEvent");
6320         res = (MonoReflectionEvent *)mono_object_new (domain, monoevent_klass);
6321         res->klass = klass;
6322         res->event = event;
6323         CACHE_OBJECT (MonoReflectionEvent *, event, res, klass);
6324 }
6325
6326 /**
6327  * mono_get_reflection_missing_object:
6328  * @domain: Domain where the object lives
6329  *
6330  * Returns the System.Reflection.Missing.Value singleton object
6331  * (of type System.Reflection.Missing).
6332  *
6333  * Used as the value for ParameterInfo.DefaultValue when Optional
6334  * is present
6335  */
6336 static MonoObject *
6337 mono_get_reflection_missing_object (MonoDomain *domain)
6338 {
6339         MonoObject *obj;
6340         static MonoClassField *missing_value_field = NULL;
6341         
6342         if (!missing_value_field) {
6343                 MonoClass *missing_klass;
6344                 missing_klass = mono_class_from_name (mono_defaults.corlib, "System.Reflection", "Missing");
6345                 mono_class_init (missing_klass);
6346                 missing_value_field = mono_class_get_field_from_name (missing_klass, "Value");
6347                 g_assert (missing_value_field);
6348         }
6349         obj = mono_field_get_value_object (domain, missing_value_field, NULL); 
6350         g_assert (obj);
6351         return obj;
6352 }
6353
6354 static MonoObject*
6355 get_dbnull (MonoDomain *domain, MonoObject **dbnull)
6356 {
6357         if (!*dbnull)
6358                 *dbnull = mono_get_dbnull_object (domain);
6359         return *dbnull;
6360 }
6361
6362 static MonoObject*
6363 get_reflection_missing (MonoDomain *domain, MonoObject **reflection_missing)
6364 {
6365         if (!*reflection_missing)
6366                 *reflection_missing = mono_get_reflection_missing_object (domain);
6367         return *reflection_missing;
6368 }
6369
6370 /*
6371  * mono_param_get_objects:
6372  * @domain: an app domain
6373  * @method: a method
6374  *
6375  * Return an System.Reflection.ParameterInfo array object representing the parameters
6376  * in the method @method.
6377  */
6378 MonoArray*
6379 mono_param_get_objects (MonoDomain *domain, MonoMethod *method)
6380 {
6381         static MonoClass *System_Reflection_ParameterInfo;
6382         static MonoClass *System_Reflection_ParameterInfo_array;
6383         MonoArray *res = NULL;
6384         MonoReflectionMethod *member = NULL;
6385         MonoReflectionParameter *param = NULL;
6386         char **names, **blobs = NULL;
6387         guint32 *types = NULL;
6388         MonoType *type = NULL;
6389         MonoObject *dbnull = NULL;
6390         MonoObject *missing = NULL;
6391         MonoMarshalSpec **mspecs;
6392         MonoMethodSignature *sig;
6393         MonoVTable *pinfo_vtable;
6394         int i;
6395
6396         if (!System_Reflection_ParameterInfo_array) {
6397                 MonoClass *klass;
6398
6399                 klass = mono_class_from_name (mono_defaults.corlib, "System.Reflection", "ParameterInfo");
6400                 mono_memory_barrier ();
6401                 System_Reflection_ParameterInfo = klass; 
6402         
6403                 klass = mono_array_class_get (klass, 1);
6404                 mono_memory_barrier ();
6405                 System_Reflection_ParameterInfo_array = klass;
6406         }
6407         
6408         if (!mono_method_signature (method)->param_count)
6409                 return mono_array_new_specific (mono_class_vtable (domain, System_Reflection_ParameterInfo_array), 0);
6410
6411         /* Note: the cache is based on the address of the signature into the method
6412          * since we already cache MethodInfos with the method as keys.
6413          */
6414         CHECK_OBJECT (MonoArray*, &(method->signature), NULL);
6415
6416         sig = mono_method_signature (method);
6417         member = mono_method_get_object (domain, method, NULL);
6418         names = g_new (char *, sig->param_count);
6419         mono_method_get_param_names (method, (const char **) names);
6420
6421         mspecs = g_new (MonoMarshalSpec*, sig->param_count + 1);
6422         mono_method_get_marshal_info (method, mspecs);
6423
6424         res = mono_array_new_specific (mono_class_vtable (domain, System_Reflection_ParameterInfo_array), sig->param_count);
6425         pinfo_vtable = mono_class_vtable (domain, System_Reflection_ParameterInfo);
6426         for (i = 0; i < sig->param_count; ++i) {
6427                 param = (MonoReflectionParameter *)mono_object_new_specific (pinfo_vtable);
6428                 MONO_OBJECT_SETREF (param, ClassImpl, mono_type_get_object (domain, sig->params [i]));
6429                 MONO_OBJECT_SETREF (param, MemberImpl, (MonoObject*)member);
6430                 MONO_OBJECT_SETREF (param, NameImpl, mono_string_new (domain, names [i]));
6431                 param->PositionImpl = i;
6432                 param->AttrsImpl = sig->params [i]->attrs;
6433
6434                 if (!(param->AttrsImpl & PARAM_ATTRIBUTE_HAS_DEFAULT)) {
6435                         if (param->AttrsImpl & PARAM_ATTRIBUTE_OPTIONAL)
6436                                 MONO_OBJECT_SETREF (param, DefaultValueImpl, get_reflection_missing (domain, &missing));
6437                         else
6438                                 MONO_OBJECT_SETREF (param, DefaultValueImpl, get_dbnull (domain, &dbnull));
6439                 } else {
6440
6441                         if (!blobs) {
6442                                 blobs = g_new0 (char *, sig->param_count);
6443                                 types = g_new0 (guint32, sig->param_count);
6444                                 get_default_param_value_blobs (method, blobs, types); 
6445                         }
6446
6447                         /* Build MonoType for the type from the Constant Table */
6448                         if (!type)
6449                                 type = g_new0 (MonoType, 1);
6450                         type->type = types [i];
6451                         type->data.klass = NULL;
6452                         if (types [i] == MONO_TYPE_CLASS)
6453                                 type->data.klass = mono_defaults.object_class;
6454                         else if ((sig->params [i]->type == MONO_TYPE_VALUETYPE) && sig->params [i]->data.klass->enumtype) {
6455                                 /* For enums, types [i] contains the base type */
6456
6457                                         type->type = MONO_TYPE_VALUETYPE;
6458                                         type->data.klass = mono_class_from_mono_type (sig->params [i]);
6459                         } else
6460                                 type->data.klass = mono_class_from_mono_type (type);
6461
6462                         MONO_OBJECT_SETREF (param, DefaultValueImpl, mono_get_object_from_blob (domain, type, blobs [i]));
6463
6464                         /* Type in the Constant table is MONO_TYPE_CLASS for nulls */
6465                         if (types [i] != MONO_TYPE_CLASS && !param->DefaultValueImpl) {
6466                                 if (param->AttrsImpl & PARAM_ATTRIBUTE_OPTIONAL)
6467                                         MONO_OBJECT_SETREF (param, DefaultValueImpl, get_reflection_missing (domain, &missing));
6468                                 else
6469                                         MONO_OBJECT_SETREF (param, DefaultValueImpl, get_dbnull (domain, &dbnull));
6470                         }
6471                         
6472                 }
6473
6474                 if (mspecs [i + 1])
6475                         MONO_OBJECT_SETREF (param, MarshalAsImpl, (MonoObject*)mono_reflection_marshal_from_marshal_spec (domain, method->klass, mspecs [i + 1]));
6476                 
6477                 mono_array_setref (res, i, param);
6478         }
6479         g_free (names);
6480         g_free (blobs);
6481         g_free (types);
6482         g_free (type);
6483
6484         for (i = mono_method_signature (method)->param_count; i >= 0; i--)
6485                 if (mspecs [i])
6486                         mono_metadata_free_marshal_spec (mspecs [i]);
6487         g_free (mspecs);
6488         
6489         CACHE_OBJECT (MonoArray *, &(method->signature), res, NULL);
6490 }
6491
6492 /*
6493  * mono_method_body_get_object:
6494  * @domain: an app domain
6495  * @method: a method
6496  *
6497  * Return an System.Reflection.MethodBody object representing the method @method.
6498  */
6499 MonoReflectionMethodBody*
6500 mono_method_body_get_object (MonoDomain *domain, MonoMethod *method)
6501 {
6502         static MonoClass *System_Reflection_MethodBody = NULL;
6503         static MonoClass *System_Reflection_LocalVariableInfo = NULL;
6504         static MonoClass *System_Reflection_ExceptionHandlingClause = NULL;
6505         MonoReflectionMethodBody *ret;
6506         MonoMethodNormal *mn;
6507         MonoMethodHeader *header;
6508         guint32 method_rva, local_var_sig_token;
6509     char *ptr;
6510         unsigned char format, flags;
6511         int i;
6512
6513         if (!System_Reflection_MethodBody)
6514                 System_Reflection_MethodBody = mono_class_from_name (mono_defaults.corlib, "System.Reflection", "MethodBody");
6515         if (!System_Reflection_LocalVariableInfo)
6516                 System_Reflection_LocalVariableInfo = mono_class_from_name (mono_defaults.corlib, "System.Reflection", "LocalVariableInfo");
6517         if (!System_Reflection_ExceptionHandlingClause)
6518                 System_Reflection_ExceptionHandlingClause = mono_class_from_name (mono_defaults.corlib, "System.Reflection", "ExceptionHandlingClause");
6519
6520         CHECK_OBJECT (MonoReflectionMethodBody *, method, NULL);
6521
6522         if ((method->flags & METHOD_ATTRIBUTE_PINVOKE_IMPL) ||
6523                 (method->flags & METHOD_ATTRIBUTE_ABSTRACT) ||
6524             (method->iflags & METHOD_IMPL_ATTRIBUTE_INTERNAL_CALL) ||
6525             (method->iflags & METHOD_IMPL_ATTRIBUTE_RUNTIME))
6526                 return NULL;
6527         mn = (MonoMethodNormal *)method;
6528         header = mono_method_get_header (method);
6529         
6530         /* Obtain local vars signature token */
6531         method_rva = mono_metadata_decode_row_col (&method->klass->image->tables [MONO_TABLE_METHOD], mono_metadata_token_index (method->token) - 1, MONO_METHOD_RVA);
6532         ptr = mono_image_rva_map (method->klass->image, method_rva);
6533         flags = *(const unsigned char *) ptr;
6534         format = flags & METHOD_HEADER_FORMAT_MASK;
6535         switch (format){
6536         case METHOD_HEADER_TINY_FORMAT:
6537         case METHOD_HEADER_TINY_FORMAT1:
6538                 local_var_sig_token = 0;
6539                 break;
6540         case METHOD_HEADER_FAT_FORMAT:
6541                 ptr += 2;
6542                 ptr += 2;
6543                 ptr += 4;
6544                 local_var_sig_token = read32 (ptr);
6545                 break;
6546         default:
6547                 g_assert_not_reached ();
6548         }
6549
6550         ret = (MonoReflectionMethodBody*)mono_object_new (domain, System_Reflection_MethodBody);
6551
6552         ret->init_locals = header->init_locals;
6553         ret->max_stack = header->max_stack;
6554         ret->local_var_sig_token = local_var_sig_token;
6555         MONO_OBJECT_SETREF (ret, il, mono_array_new (domain, mono_defaults.byte_class, header->code_size));
6556         memcpy (mono_array_addr (ret->il, guint8, 0), header->code, header->code_size);
6557
6558         /* Locals */
6559         MONO_OBJECT_SETREF (ret, locals, mono_array_new (domain, System_Reflection_LocalVariableInfo, header->num_locals));
6560         for (i = 0; i < header->num_locals; ++i) {
6561                 MonoReflectionLocalVariableInfo *info = (MonoReflectionLocalVariableInfo*)mono_object_new (domain, System_Reflection_LocalVariableInfo);
6562                 MONO_OBJECT_SETREF (info, local_type, mono_type_get_object (domain, header->locals [i]));
6563                 info->is_pinned = header->locals [i]->pinned;
6564                 info->local_index = i;
6565                 mono_array_setref (ret->locals, i, info);
6566         }
6567
6568         /* Exceptions */
6569         MONO_OBJECT_SETREF (ret, clauses, mono_array_new (domain, System_Reflection_ExceptionHandlingClause, header->num_clauses));
6570         for (i = 0; i < header->num_clauses; ++i) {
6571                 MonoReflectionExceptionHandlingClause *info = (MonoReflectionExceptionHandlingClause*)mono_object_new (domain, System_Reflection_ExceptionHandlingClause);
6572                 MonoExceptionClause *clause = &header->clauses [i];
6573
6574                 info->flags = clause->flags;
6575                 info->try_offset = clause->try_offset;
6576                 info->try_length = clause->try_len;
6577                 info->handler_offset = clause->handler_offset;
6578                 info->handler_length = clause->handler_len;
6579                 if (clause->flags == MONO_EXCEPTION_CLAUSE_FILTER)
6580                         info->filter_offset = clause->data.filter_offset;
6581                 else if (clause->data.catch_class)
6582                         MONO_OBJECT_SETREF (info, catch_type, mono_type_get_object (mono_domain_get (), &clause->data.catch_class->byval_arg));
6583
6584                 mono_array_setref (ret->clauses, i, info);
6585         }
6586
6587         CACHE_OBJECT (MonoReflectionMethodBody *, method, ret, NULL);
6588         return ret;
6589 }
6590
6591 /**
6592  * mono_get_dbnull_object:
6593  * @domain: Domain where the object lives
6594  *
6595  * Returns the System.DBNull.Value singleton object
6596  *
6597  * Used as the value for ParameterInfo.DefaultValue 
6598  */
6599 MonoObject *
6600 mono_get_dbnull_object (MonoDomain *domain)
6601 {
6602         MonoObject *obj;
6603         static MonoClassField *dbnull_value_field = NULL;
6604         
6605         if (!dbnull_value_field) {
6606                 MonoClass *dbnull_klass;
6607                 dbnull_klass = mono_class_from_name (mono_defaults.corlib, "System", "DBNull");
6608                 mono_class_init (dbnull_klass);
6609                 dbnull_value_field = mono_class_get_field_from_name (dbnull_klass, "Value");
6610                 g_assert (dbnull_value_field);
6611         }
6612         obj = mono_field_get_value_object (domain, dbnull_value_field, NULL); 
6613         g_assert (obj);
6614         return obj;
6615 }
6616
6617 static void
6618 get_default_param_value_blobs (MonoMethod *method, char **blobs, guint32 *types)
6619 {
6620         guint32 param_index, i, lastp, crow = 0;
6621         guint32 param_cols [MONO_PARAM_SIZE], const_cols [MONO_CONSTANT_SIZE];
6622         gint32 idx;
6623
6624         MonoClass *klass = method->klass;
6625         MonoImage *image = klass->image;
6626         MonoMethodSignature *methodsig = mono_method_signature (method);
6627
6628         MonoTableInfo *constt;
6629         MonoTableInfo *methodt;
6630         MonoTableInfo *paramt;
6631
6632         if (!methodsig->param_count)
6633                 return;
6634
6635         mono_class_init (klass);
6636
6637         if (klass->image->dynamic) {
6638                 MonoReflectionMethodAux *aux;
6639                 if (method->is_inflated)
6640                         method = ((MonoMethodInflated*)method)->declaring;
6641                 aux = g_hash_table_lookup (((MonoDynamicImage*)method->klass->image)->method_aux_hash, method);
6642                 if (aux && aux->param_defaults) {
6643                         memcpy (blobs, &(aux->param_defaults [1]), methodsig->param_count * sizeof (char*));
6644                         memcpy (types, &(aux->param_default_types [1]), methodsig->param_count * sizeof (guint32));
6645                 }
6646                 return;
6647         }
6648
6649         methodt = &klass->image->tables [MONO_TABLE_METHOD];
6650         paramt = &klass->image->tables [MONO_TABLE_PARAM];
6651         constt = &image->tables [MONO_TABLE_CONSTANT];
6652
6653         idx = mono_method_get_index (method) - 1;
6654         g_assert (idx != -1);
6655
6656         param_index = mono_metadata_decode_row_col (methodt, idx, MONO_METHOD_PARAMLIST);
6657         if (idx + 1 < methodt->rows)
6658                 lastp = mono_metadata_decode_row_col (methodt, idx + 1, MONO_METHOD_PARAMLIST);
6659         else
6660                 lastp = paramt->rows + 1;
6661
6662         for (i = param_index; i < lastp; ++i) {
6663                 guint32 paramseq;
6664
6665                 mono_metadata_decode_row (paramt, i - 1, param_cols, MONO_PARAM_SIZE);
6666                 paramseq = param_cols [MONO_PARAM_SEQUENCE];
6667
6668                 if (!param_cols [MONO_PARAM_FLAGS] & PARAM_ATTRIBUTE_HAS_DEFAULT) 
6669                         continue;
6670
6671                 crow = mono_metadata_get_constant_index (image, MONO_TOKEN_PARAM_DEF | i, crow + 1);
6672                 if (!crow) {
6673                         continue;
6674                 }
6675         
6676                 mono_metadata_decode_row (constt, crow - 1, const_cols, MONO_CONSTANT_SIZE);
6677                 blobs [paramseq - 1] = (gpointer) mono_metadata_blob_heap (image, const_cols [MONO_CONSTANT_VALUE]);
6678                 types [paramseq - 1] = const_cols [MONO_CONSTANT_TYPE];
6679         }
6680
6681         return;
6682 }
6683
6684 static MonoObject *
6685 mono_get_object_from_blob (MonoDomain *domain, MonoType *type, const char *blob)
6686 {
6687         void *retval;
6688         MonoClass *klass;
6689         MonoObject *object;
6690         MonoType *basetype = type;
6691
6692         if (!blob)
6693                 return NULL;
6694         
6695         klass = mono_class_from_mono_type (type);
6696         if (klass->valuetype) {
6697                 object = mono_object_new (domain, klass);
6698                 retval = ((gchar *) object + sizeof (MonoObject));
6699                 if (klass->enumtype)
6700                         basetype = mono_class_enum_basetype (klass);
6701         } else {
6702                 retval = &object;
6703         }
6704                         
6705         if (!mono_get_constant_value_from_blob (domain, basetype->type,  blob, retval))
6706                 return object;
6707         else
6708                 return NULL;
6709 }
6710
6711 static int
6712 assembly_name_to_aname (MonoAssemblyName *assembly, char *p) {
6713         int found_sep;
6714         char *s;
6715
6716         memset (assembly, 0, sizeof (MonoAssemblyName));
6717         assembly->name = p;
6718         assembly->culture = "";
6719         memset (assembly->public_key_token, 0, MONO_PUBLIC_KEY_TOKEN_LENGTH);
6720
6721         while (*p && (isalnum (*p) || *p == '.' || *p == '-' || *p == '_' || *p == '$' || *p == '@'))
6722                 p++;
6723         found_sep = 0;
6724         while (g_ascii_isspace (*p) || *p == ',') {
6725                 *p++ = 0;
6726                 found_sep = 1;
6727                 continue;
6728         }
6729         /* failed */
6730         if (!found_sep)
6731                 return 1;
6732         while (*p) {
6733                 if (*p == 'V' && g_ascii_strncasecmp (p, "Version=", 8) == 0) {
6734                         p += 8;
6735                         assembly->major = strtoul (p, &s, 10);
6736                         if (s == p || *s != '.')
6737                                 return 1;
6738                         p = ++s;
6739                         assembly->minor = strtoul (p, &s, 10);
6740                         if (s == p || *s != '.')
6741                                 return 1;
6742                         p = ++s;
6743                         assembly->build = strtoul (p, &s, 10);
6744                         if (s == p || *s != '.')
6745                                 return 1;
6746                         p = ++s;
6747                         assembly->revision = strtoul (p, &s, 10);
6748                         if (s == p)
6749                                 return 1;
6750                         p = s;
6751                 } else if (*p == 'C' && g_ascii_strncasecmp (p, "Culture=", 8) == 0) {
6752                         p += 8;
6753                         if (g_ascii_strncasecmp (p, "neutral", 7) == 0) {
6754                                 assembly->culture = "";
6755                                 p += 7;
6756                         } else {
6757                                 assembly->culture = p;
6758                                 while (*p && *p != ',') {
6759                                         p++;
6760                                 }
6761                         }
6762                 } else if (*p == 'P' && g_ascii_strncasecmp (p, "PublicKeyToken=", 15) == 0) {
6763                         p += 15;
6764                         if (strncmp (p, "null", 4) == 0) {
6765                                 p += 4;
6766                         } else {
6767                                 int len;
6768                                 gchar *start = p;
6769                                 while (*p && *p != ',') {
6770                                         p++;
6771                                 }
6772                                 len = (p - start + 1);
6773                                 if (len > MONO_PUBLIC_KEY_TOKEN_LENGTH)
6774                                         len = MONO_PUBLIC_KEY_TOKEN_LENGTH;
6775                                 g_strlcpy ((char*)assembly->public_key_token, start, len);
6776                         }
6777                 } else {
6778                         while (*p && *p != ',')
6779                                 p++;
6780                 }
6781                 found_sep = 0;
6782                 while (g_ascii_isspace (*p) || *p == ',') {
6783                         *p++ = 0;
6784                         found_sep = 1;
6785                         continue;
6786                 }
6787                 /* failed */
6788                 if (!found_sep)
6789                         return 1;
6790         }
6791
6792         return 0;
6793 }
6794
6795 /*
6796  * mono_reflection_parse_type:
6797  * @name: type name
6798  *
6799  * Parse a type name as accepted by the GetType () method and output the info
6800  * extracted in the info structure.
6801  * the name param will be mangled, so, make a copy before passing it to this function.
6802  * The fields in info will be valid until the memory pointed to by name is valid.
6803  *
6804  * See also mono_type_get_name () below.
6805  *
6806  * Returns: 0 on parse error.
6807  */
6808 static int
6809 _mono_reflection_parse_type (char *name, char **endptr, gboolean is_recursed,
6810                              MonoTypeNameParse *info)
6811 {
6812         char *start, *p, *w, *temp, *last_point, *startn;
6813         int in_modifiers = 0;
6814         int isbyref = 0, rank, arity = 0, i;
6815
6816         start = p = w = name;
6817
6818         //FIXME could we just zero the whole struct? memset (&info, 0, sizeof (MonoTypeNameParse))
6819         memset (&info->assembly, 0, sizeof (MonoAssemblyName));
6820         info->name = info->name_space = NULL;
6821         info->nested = NULL;
6822         info->modifiers = NULL;
6823         info->type_arguments = NULL;
6824
6825         /* last_point separates the namespace from the name */
6826         last_point = NULL;
6827         /* Skips spaces */
6828         while (*p == ' ') p++, start++, w++, name++;
6829
6830         while (*p) {
6831                 switch (*p) {
6832                 case '+':
6833                         *p = 0; /* NULL terminate the name */
6834                         startn = p + 1;
6835                         info->nested = g_list_append (info->nested, startn);
6836                         /* we have parsed the nesting namespace + name */
6837                         if (info->name)
6838                                 break;
6839                         if (last_point) {
6840                                 info->name_space = start;
6841                                 *last_point = 0;
6842                                 info->name = last_point + 1;
6843                         } else {
6844                                 info->name_space = (char *)"";
6845                                 info->name = start;
6846                         }
6847                         break;
6848                 case '.':
6849                         last_point = p;
6850                         break;
6851                 case '\\':
6852                         ++p;
6853                         break;
6854                 case '&':
6855                 case '*':
6856                 case '[':
6857                 case ',':
6858                 case ']':
6859                         in_modifiers = 1;
6860                         break;
6861                 case '`':
6862                         ++p;
6863                         i = strtol (p, &temp, 10);
6864                         arity += i;
6865                         if (p == temp)
6866                                 return 0;
6867                         p = temp-1;
6868                         break;
6869                 default:
6870                         break;
6871                 }
6872                 if (in_modifiers)
6873                         break;
6874                 // *w++ = *p++;
6875                 p++;
6876         }
6877         
6878         if (!info->name) {
6879                 if (last_point) {
6880                         info->name_space = start;
6881                         *last_point = 0;
6882                         info->name = last_point + 1;
6883                 } else {
6884                         info->name_space = (char *)"";
6885                         info->name = start;
6886                 }
6887         }
6888         while (*p) {
6889                 switch (*p) {
6890                 case '&':
6891                         if (isbyref) /* only one level allowed by the spec */
6892                                 return 0;
6893                         isbyref = 1;
6894                         info->modifiers = g_list_append (info->modifiers, GUINT_TO_POINTER (0));
6895                         *p++ = 0;
6896                         break;
6897                 case '*':
6898                         info->modifiers = g_list_append (info->modifiers, GUINT_TO_POINTER (-1));
6899                         *p++ = 0;
6900                         break;
6901                 case '[':
6902                         if (arity != 0) {
6903                                 *p++ = 0;
6904                                 info->type_arguments = g_ptr_array_new ();
6905                                 for (i = 0; i < arity; i++) {
6906                                         MonoTypeNameParse *subinfo = g_new0 (MonoTypeNameParse, 1);
6907                                         gboolean fqname = FALSE;
6908
6909                                         g_ptr_array_add (info->type_arguments, subinfo);
6910
6911                                         if (*p == '[') {
6912                                                 p++;
6913                                                 fqname = TRUE;
6914                                         }
6915
6916                                         if (!_mono_reflection_parse_type (p, &p, TRUE, subinfo))
6917                                                 return 0;
6918
6919                                         if (fqname) {
6920                                                 char *aname;
6921
6922                                                 if (*p != ',')
6923                                                         return 0;
6924                                                 *p++ = 0;
6925
6926                                                 aname = p;
6927                                                 while (*p && (*p != ']'))
6928                                                         p++;
6929
6930                                                 if (*p != ']')
6931                                                         return 0;
6932
6933                                                 *p++ = 0;
6934                                                 while (*aname) {
6935                                                         if (g_ascii_isspace (*aname)) {
6936                                                                 ++aname;
6937                                                                 continue;
6938                                                         }
6939                                                         break;
6940                                                 }
6941                                                 if (!*aname ||
6942                                                     !assembly_name_to_aname (&subinfo->assembly, aname))
6943                                                         return 0;
6944                                         }
6945
6946                                         if (i + 1 < arity) {
6947                                                 if (*p != ',')
6948                                                         return 0;
6949                                         } else {
6950                                                 if (*p != ']')
6951                                                         return 0;
6952                                         }
6953                                         *p++ = 0;
6954                                 }
6955
6956                                 arity = 0;
6957                                 break;
6958                         }
6959                         rank = 1;
6960                         *p++ = 0;
6961                         while (*p) {
6962                                 if (*p == ']')
6963                                         break;
6964                                 if (*p == ',')
6965                                         rank++;
6966                                 else if (*p == '*') /* '*' means unknown lower bound */
6967                                         info->modifiers = g_list_append (info->modifiers, GUINT_TO_POINTER (-2));
6968                                 else
6969                                         return 0;
6970                                 ++p;
6971                         }
6972                         if (*p++ != ']')
6973                                 return 0;
6974                         info->modifiers = g_list_append (info->modifiers, GUINT_TO_POINTER (rank));
6975                         break;
6976                 case ']':
6977                         if (is_recursed)
6978                                 goto end;
6979                         return 0;
6980                 case ',':
6981                         if (is_recursed)
6982                                 goto end;
6983                         *p++ = 0;
6984                         while (*p) {
6985                                 if (g_ascii_isspace (*p)) {
6986                                         ++p;
6987                                         continue;
6988                                 }
6989                                 break;
6990                         }
6991                         if (!*p)
6992                                 return 0; /* missing assembly name */
6993                         if (!assembly_name_to_aname (&info->assembly, p))
6994                                 return 0;
6995                         break;
6996                 default:
6997                         return 0;
6998                 }
6999                 if (info->assembly.name)
7000                         break;
7001         }
7002         // *w = 0; /* terminate class name */
7003  end:
7004         if (!info->name || !*info->name)
7005                 return 0;
7006         if (endptr)
7007                 *endptr = p;
7008         /* add other consistency checks */
7009         return 1;
7010 }
7011
7012 int
7013 mono_reflection_parse_type (char *name, MonoTypeNameParse *info)
7014 {
7015         return _mono_reflection_parse_type (name, NULL, FALSE, info);
7016 }
7017
7018 static MonoType*
7019 _mono_reflection_get_type_from_info (MonoTypeNameParse *info, MonoImage *image, gboolean ignorecase)
7020 {
7021         gboolean type_resolve = FALSE;
7022         MonoType *type;
7023         MonoImage *rootimage = image;
7024
7025         if (info->assembly.name) {
7026                 MonoAssembly *assembly = mono_assembly_loaded (&info->assembly);
7027                 if (!assembly && image && image->assembly && mono_assembly_names_equal (&info->assembly, &image->assembly->aname))
7028                         /* 
7029                          * This could happen in the AOT compiler case when the search hook is not
7030                          * installed.
7031                          */
7032                         assembly = image->assembly;
7033                 if (!assembly) {
7034                         /* then we must load the assembly ourselve - see #60439 */
7035                         assembly = mono_assembly_load (&info->assembly, NULL, NULL);
7036                         if (!assembly)
7037                                 return NULL;
7038                 }
7039                 image = assembly->image;
7040         } else if (!image) {
7041                 image = mono_defaults.corlib;
7042         }
7043
7044         type = mono_reflection_get_type_with_rootimage (rootimage, image, info, ignorecase, &type_resolve);
7045         if (type == NULL && !info->assembly.name && image != mono_defaults.corlib) {
7046                 image = mono_defaults.corlib;
7047                 type = mono_reflection_get_type_with_rootimage (rootimage, image, info, ignorecase, &type_resolve);
7048         }
7049
7050         return type;
7051 }
7052
7053 static MonoType*
7054 mono_reflection_get_type_internal (MonoImage *rootimage, MonoImage* image, MonoTypeNameParse *info, gboolean ignorecase)
7055 {
7056         MonoClass *klass;
7057         GList *mod;
7058         int modval;
7059         gboolean bounded = FALSE;
7060         
7061         if (!image)
7062                 image = mono_defaults.corlib;
7063
7064         if (ignorecase)
7065                 klass = mono_class_from_name_case (image, info->name_space, info->name);
7066         else
7067                 klass = mono_class_from_name (image, info->name_space, info->name);
7068         if (!klass)
7069                 return NULL;
7070         for (mod = info->nested; mod; mod = mod->next) {
7071                 gpointer iter = NULL;
7072                 MonoClass *parent;
7073
7074                 parent = klass;
7075                 mono_class_init (parent);
7076
7077                 while ((klass = mono_class_get_nested_types (parent, &iter))) {
7078                         if (ignorecase) {
7079                                 if (g_strcasecmp (klass->name, mod->data) == 0)
7080                                         break;
7081                         } else {
7082                                 if (strcmp (klass->name, mod->data) == 0)
7083                                         break;
7084                         }
7085                 }
7086                 if (!klass)
7087                         break;
7088         }
7089         if (!klass)
7090                 return NULL;
7091         mono_class_init (klass);
7092
7093         if (info->type_arguments) {
7094                 MonoType **type_args = g_new0 (MonoType *, info->type_arguments->len);
7095                 MonoReflectionType *the_type;
7096                 MonoType *instance;
7097                 int i;
7098
7099                 for (i = 0; i < info->type_arguments->len; i++) {
7100                         MonoTypeNameParse *subinfo = g_ptr_array_index (info->type_arguments, i);
7101
7102                         type_args [i] = _mono_reflection_get_type_from_info (subinfo, rootimage, ignorecase);
7103                         if (!type_args [i]) {
7104                                 g_free (type_args);
7105                                 return NULL;
7106                         }
7107                 }
7108
7109                 the_type = mono_type_get_object (mono_domain_get (), &klass->byval_arg);
7110
7111                 instance = mono_reflection_bind_generic_parameters (
7112                         the_type, info->type_arguments->len, type_args);
7113
7114                 g_free (type_args);
7115                 if (!instance)
7116                         return NULL;
7117
7118                 klass = mono_class_from_mono_type (instance);
7119         }
7120
7121         for (mod = info->modifiers; mod; mod = mod->next) {
7122                 modval = GPOINTER_TO_UINT (mod->data);
7123                 if (!modval) { /* byref: must be last modifier */
7124                         return &klass->this_arg;
7125                 } else if (modval == -1) {
7126                         klass = mono_ptr_class_get (&klass->byval_arg);
7127                 } else if (modval == -2) {
7128                         bounded = TRUE;
7129                 } else { /* array rank */
7130                         klass = mono_bounded_array_class_get (klass, modval, bounded);
7131                 }
7132                 mono_class_init (klass);
7133         }
7134
7135         return &klass->byval_arg;
7136 }
7137
7138 /*
7139  * mono_reflection_get_type:
7140  * @image: a metadata context
7141  * @info: type description structure
7142  * @ignorecase: flag for case-insensitive string compares
7143  * @type_resolve: whenever type resolve was already tried
7144  *
7145  * Build a MonoType from the type description in @info.
7146  * 
7147  */
7148
7149 MonoType*
7150 mono_reflection_get_type (MonoImage* image, MonoTypeNameParse *info, gboolean ignorecase, gboolean *type_resolve) {
7151         return mono_reflection_get_type_with_rootimage(image, image, info, ignorecase, type_resolve);
7152 }
7153
7154 static MonoType*
7155 mono_reflection_get_type_internal_dynamic (MonoImage *rootimage, MonoAssembly *assembly, MonoTypeNameParse *info, gboolean ignorecase)
7156 {
7157         MonoReflectionAssemblyBuilder *abuilder = (MonoReflectionAssemblyBuilder*)mono_assembly_get_object (mono_domain_get (), assembly);
7158         MonoType *type;
7159         int i;
7160
7161         g_assert (assembly->dynamic);
7162
7163         /* Enumerate all modules */
7164
7165         type = NULL;
7166         if (abuilder->modules) {
7167                 for (i = 0; i < mono_array_length (abuilder->modules); ++i) {
7168                         MonoReflectionModuleBuilder *mb = mono_array_get (abuilder->modules, MonoReflectionModuleBuilder*, i);
7169                         type = mono_reflection_get_type_internal (rootimage, &mb->dynamic_image->image, info, ignorecase);
7170                         if (type)
7171                                 break;
7172                 }
7173         }
7174
7175         if (!type && abuilder->loaded_modules) {
7176                 for (i = 0; i < mono_array_length (abuilder->loaded_modules); ++i) {
7177                         MonoReflectionModule *mod = mono_array_get (abuilder->loaded_modules, MonoReflectionModule*, i);
7178                         type = mono_reflection_get_type_internal (rootimage, mod->image, info, ignorecase);
7179                         if (type)
7180                                 break;
7181                 }
7182         }
7183
7184         return type;
7185 }
7186         
7187 MonoType*
7188 mono_reflection_get_type_with_rootimage (MonoImage *rootimage, MonoImage* image, MonoTypeNameParse *info, gboolean ignorecase, gboolean *type_resolve)
7189 {
7190         MonoType *type;
7191         MonoReflectionAssembly *assembly;
7192         GString *fullName;
7193         GList *mod;
7194
7195         if (image && image->dynamic)
7196                 type = mono_reflection_get_type_internal_dynamic (rootimage, image->assembly, info, ignorecase);
7197         else
7198                 type = mono_reflection_get_type_internal (rootimage, image, info, ignorecase);
7199         if (type)
7200                 return type;
7201         if (!mono_domain_has_type_resolve (mono_domain_get ()))
7202                 return NULL;
7203
7204         if (type_resolve) {
7205                 if (*type_resolve) 
7206                         return NULL;
7207                 else
7208                         *type_resolve = TRUE;
7209         }
7210         
7211         /* Reconstruct the type name */
7212         fullName = g_string_new ("");
7213         if (info->name_space && (info->name_space [0] != '\0'))
7214                 g_string_printf (fullName, "%s.%s", info->name_space, info->name);
7215         else
7216                 g_string_printf (fullName, info->name);
7217         for (mod = info->nested; mod; mod = mod->next)
7218                 g_string_append_printf (fullName, "+%s", (char*)mod->data);
7219
7220         assembly = mono_domain_try_type_resolve ( mono_domain_get (), fullName->str, NULL);
7221         if (assembly) {
7222                 if (assembly->assembly->dynamic)
7223                         type = mono_reflection_get_type_internal_dynamic (rootimage, assembly->assembly, info, ignorecase);
7224                 else
7225                         type = mono_reflection_get_type_internal (rootimage, assembly->assembly->image, 
7226                                                                                                           info, ignorecase);
7227         }
7228         g_string_free (fullName, TRUE);
7229         return type;
7230 }
7231
7232 void
7233 mono_reflection_free_type_info (MonoTypeNameParse *info)
7234 {
7235         g_list_free (info->modifiers);
7236         g_list_free (info->nested);
7237
7238         if (info->type_arguments) {
7239                 int i;
7240
7241                 for (i = 0; i < info->type_arguments->len; i++) {
7242                         MonoTypeNameParse *subinfo = g_ptr_array_index (info->type_arguments, i);
7243
7244                         mono_reflection_free_type_info (subinfo);
7245                         /*We free the subinfo since it is allocated by _mono_reflection_parse_type*/
7246                         g_free (subinfo);
7247                 }
7248
7249                 g_ptr_array_free (info->type_arguments, TRUE);
7250         }
7251 }
7252
7253 /*
7254  * mono_reflection_type_from_name:
7255  * @name: type name.
7256  * @image: a metadata context (can be NULL).
7257  *
7258  * Retrieves a MonoType from its @name. If the name is not fully qualified,
7259  * it defaults to get the type from @image or, if @image is NULL or loading
7260  * from it fails, uses corlib.
7261  * 
7262  */
7263 MonoType*
7264 mono_reflection_type_from_name (char *name, MonoImage *image)
7265 {
7266         MonoType *type = NULL;
7267         MonoTypeNameParse info;
7268         char *tmp;
7269
7270         /* Make a copy since parse_type modifies its argument */
7271         tmp = g_strdup (name);
7272         
7273         /*g_print ("requested type %s\n", str);*/
7274         if (mono_reflection_parse_type (tmp, &info)) {
7275                 type = _mono_reflection_get_type_from_info (&info, image, FALSE);
7276         }
7277
7278         g_free (tmp);
7279         mono_reflection_free_type_info (&info);
7280         return type;
7281 }
7282
7283 /*
7284  * mono_reflection_get_token:
7285  *
7286  *   Return the metadata token of OBJ which should be an object
7287  * representing a metadata element.
7288  */
7289 guint32
7290 mono_reflection_get_token (MonoObject *obj)
7291 {
7292         MonoClass *klass;
7293         guint32 token = 0;
7294
7295         klass = obj->vtable->klass;
7296
7297         if (strcmp (klass->name, "MethodBuilder") == 0) {
7298                 MonoReflectionMethodBuilder *mb = (MonoReflectionMethodBuilder *)obj;
7299
7300                 token = mb->table_idx | MONO_TOKEN_METHOD_DEF;
7301         } else if (strcmp (klass->name, "ConstructorBuilder") == 0) {
7302                 MonoReflectionCtorBuilder *mb = (MonoReflectionCtorBuilder *)obj;
7303
7304                 token = mb->table_idx | MONO_TOKEN_METHOD_DEF;
7305         } else if (strcmp (klass->name, "FieldBuilder") == 0) {
7306                 MonoReflectionFieldBuilder *fb = (MonoReflectionFieldBuilder *)obj;
7307
7308                 /* Call mono_image_create_token so the object gets added to the tokens hash table */
7309                 token = mono_image_create_token (((MonoReflectionTypeBuilder*)fb->typeb)->module->dynamic_image, obj, FALSE, TRUE);
7310         } else if (strcmp (klass->name, "TypeBuilder") == 0) {
7311                 MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder *)obj;
7312                 token = tb->table_idx | MONO_TOKEN_TYPE_DEF;
7313         } else if (strcmp (klass->name, "MonoType") == 0) {
7314                 MonoReflectionType *tb = (MonoReflectionType *)obj;
7315                 token = mono_class_from_mono_type (tb->type)->type_token;
7316         } else if (strcmp (klass->name, "MonoCMethod") == 0 ||
7317                    strcmp (klass->name, "MonoMethod") == 0 ||
7318                    strcmp (klass->name, "MonoGenericMethod") == 0 ||
7319                    strcmp (klass->name, "MonoGenericCMethod") == 0) {
7320                 MonoReflectionMethod *m = (MonoReflectionMethod *)obj;
7321                 if (m->method->is_inflated) {
7322                         MonoMethodInflated *inflated = (MonoMethodInflated *) m->method;
7323                         return inflated->declaring->token;
7324                 } else {
7325                         token = m->method->token;
7326                 }
7327         } else if (strcmp (klass->name, "MonoField") == 0) {
7328                 MonoReflectionField *f = (MonoReflectionField*)obj;
7329
7330                 if (is_field_on_inst (f->field)) {
7331                         MonoDynamicGenericClass *dgclass = (MonoDynamicGenericClass*)f->field->parent->generic_class;
7332                         int field_index = f->field - dgclass->fields;
7333                         MonoObject *obj;
7334
7335                         g_assert (field_index >= 0 && field_index < dgclass->count_fields);
7336                         obj = dgclass->field_objects [field_index];
7337                         return mono_reflection_get_token (obj);
7338                 }
7339                 token = mono_class_get_field_token (f->field);
7340         } else if (strcmp (klass->name, "MonoProperty") == 0) {
7341                 MonoReflectionProperty *p = (MonoReflectionProperty*)obj;
7342
7343                 token = mono_class_get_property_token (p->property);
7344         } else if (strcmp (klass->name, "MonoEvent") == 0) {
7345                 MonoReflectionEvent *p = (MonoReflectionEvent*)obj;
7346
7347                 token = mono_class_get_event_token (p->event);
7348         } else if (strcmp (klass->name, "ParameterInfo") == 0) {
7349                 MonoReflectionParameter *p = (MonoReflectionParameter*)obj;
7350
7351                 token = mono_method_get_param_token (((MonoReflectionMethod*)p->MemberImpl)->method, p->PositionImpl);
7352         } else if (strcmp (klass->name, "Module") == 0) {
7353                 MonoReflectionModule *m = (MonoReflectionModule*)obj;
7354
7355                 token = m->token;
7356         } else if (strcmp (klass->name, "Assembly") == 0) {
7357                 token = mono_metadata_make_token (MONO_TABLE_ASSEMBLY, 1);
7358         } else {
7359                 gchar *msg = g_strdup_printf ("MetadataToken is not supported for type '%s.%s'", klass->name_space, klass->name);
7360                 MonoException *ex = mono_get_exception_not_implemented (msg);
7361                 g_free (msg);
7362                 mono_raise_exception (ex);
7363         }
7364
7365         return token;
7366 }
7367
7368 static void*
7369 load_cattr_value (MonoImage *image, MonoType *t, const char *p, const char **end)
7370 {
7371         int slen, type = t->type;
7372         MonoClass *tklass = t->data.klass;
7373
7374 handle_enum:
7375         switch (type) {
7376         case MONO_TYPE_U1:
7377         case MONO_TYPE_I1:
7378         case MONO_TYPE_BOOLEAN: {
7379                 MonoBoolean *bval = g_malloc (sizeof (MonoBoolean));
7380                 *bval = *p;
7381                 *end = p + 1;
7382                 return bval;
7383         }
7384         case MONO_TYPE_CHAR:
7385         case MONO_TYPE_U2:
7386         case MONO_TYPE_I2: {
7387                 guint16 *val = g_malloc (sizeof (guint16));
7388                 *val = read16 (p);
7389                 *end = p + 2;
7390                 return val;
7391         }
7392 #if SIZEOF_VOID_P == 4
7393         case MONO_TYPE_U:
7394         case MONO_TYPE_I:
7395 #endif
7396         case MONO_TYPE_R4:
7397         case MONO_TYPE_U4:
7398         case MONO_TYPE_I4: {
7399                 guint32 *val = g_malloc (sizeof (guint32));
7400                 *val = read32 (p);
7401                 *end = p + 4;
7402                 return val;
7403         }
7404 #if SIZEOF_VOID_P == 8
7405         case MONO_TYPE_U: /* error out instead? this should probably not happen */
7406         case MONO_TYPE_I:
7407 #endif
7408         case MONO_TYPE_U8:
7409         case MONO_TYPE_I8: {
7410                 guint64 *val = g_malloc (sizeof (guint64));
7411                 *val = read64 (p);
7412                 *end = p + 8;
7413                 return val;
7414         }
7415         case MONO_TYPE_R8: {
7416                 double *val = g_malloc (sizeof (double));
7417                 readr8 (p, val);
7418                 *end = p + 8;
7419                 return val;
7420         }
7421         case MONO_TYPE_VALUETYPE:
7422                 if (t->data.klass->enumtype) {
7423                         type = mono_class_enum_basetype (t->data.klass)->type;
7424                         goto handle_enum;
7425                 } else {
7426                         g_error ("generic valutype %s not handled in custom attr value decoding", t->data.klass->name);
7427                 }
7428                 break;
7429         case MONO_TYPE_STRING:
7430                 if (*p == (char)0xFF) {
7431                         *end = p + 1;
7432                         return NULL;
7433                 }
7434                 slen = mono_metadata_decode_value (p, &p);
7435                 *end = p + slen;
7436                 return mono_string_new_len (mono_domain_get (), p, slen);
7437         case MONO_TYPE_CLASS: {
7438                 char *n;
7439                 MonoType *t;
7440                 if (*p == (char)0xFF) {
7441                         *end = p + 1;
7442                         return NULL;
7443                 }
7444 handle_type:
7445                 slen = mono_metadata_decode_value (p, &p);
7446                 n = g_memdup (p, slen + 1);
7447                 n [slen] = 0;
7448                 t = mono_reflection_type_from_name (n, image);
7449                 if (!t)
7450                         g_warning ("Cannot load type '%s'", n);
7451                 g_free (n);
7452                 *end = p + slen;
7453                 if (t)
7454                         return mono_type_get_object (mono_domain_get (), t);
7455                 else
7456                         return NULL;
7457         }
7458         case MONO_TYPE_OBJECT: {
7459                 char subt = *p++;
7460                 MonoObject *obj;
7461                 MonoClass *subc = NULL;
7462                 void *val;
7463
7464                 if (subt == 0x50) {
7465                         goto handle_type;
7466                 } else if (subt == 0x0E) {
7467                         type = MONO_TYPE_STRING;
7468                         goto handle_enum;
7469                 } else if (subt == 0x1D) {
7470                         MonoType simple_type = {{0}};
7471                         int etype = *p;
7472                         p ++;
7473
7474                         if (etype == 0x51)
7475                                 /* See Partition II, Appendix B3 */
7476                                 etype = MONO_TYPE_OBJECT;
7477                         type = MONO_TYPE_SZARRAY;
7478                         simple_type.type = etype;
7479                         tklass = mono_class_from_mono_type (&simple_type);
7480                         goto handle_enum;
7481                 } else if (subt == 0x55) {
7482                         char *n;
7483                         MonoType *t;
7484                         slen = mono_metadata_decode_value (p, &p);
7485                         n = g_memdup (p, slen + 1);
7486                         n [slen] = 0;
7487                         t = mono_reflection_type_from_name (n, image);
7488                         if (!t)
7489                                 g_error ("Cannot load type '%s'", n);
7490                         g_free (n);
7491                         p += slen;
7492                         subc = mono_class_from_mono_type (t);
7493                 } else if (subt >= MONO_TYPE_BOOLEAN && subt <= MONO_TYPE_R8) {
7494                         MonoType simple_type = {{0}};
7495                         simple_type.type = subt;
7496                         subc = mono_class_from_mono_type (&simple_type);
7497                 } else {
7498                         g_error ("Unknown type 0x%02x for object type encoding in custom attr", subt);
7499                 }
7500                 val = load_cattr_value (image, &subc->byval_arg, p, end);
7501                 obj = mono_object_new (mono_domain_get (), subc);
7502                 memcpy ((char*)obj + sizeof (MonoObject), val, mono_class_value_size (subc, NULL));
7503                 g_free (val);
7504                 return obj;
7505         }
7506         case MONO_TYPE_SZARRAY: {
7507                 MonoArray *arr;
7508                 guint32 i, alen, basetype;
7509                 alen = read32 (p);
7510                 p += 4;
7511                 if (alen == 0xffffffff) {
7512                         *end = p;
7513                         return NULL;
7514                 }
7515                 arr = mono_array_new (mono_domain_get(), tklass, alen);
7516                 basetype = tklass->byval_arg.type;
7517                 if (basetype == MONO_TYPE_VALUETYPE && tklass->enumtype)
7518                         basetype = mono_class_enum_basetype (tklass)->type;
7519                 switch (basetype)
7520                 {
7521                         case MONO_TYPE_U1:
7522                         case MONO_TYPE_I1:
7523                         case MONO_TYPE_BOOLEAN:
7524                                 for (i = 0; i < alen; i++) {
7525                                         MonoBoolean val = *p++;
7526                                         mono_array_set (arr, MonoBoolean, i, val);
7527                                 }
7528                                 break;
7529                         case MONO_TYPE_CHAR:
7530                         case MONO_TYPE_U2:
7531                         case MONO_TYPE_I2:
7532                                 for (i = 0; i < alen; i++) {
7533                                         guint16 val = read16 (p);
7534                                         mono_array_set (arr, guint16, i, val);
7535                                         p += 2;
7536                                 }
7537                                 break;
7538                         case MONO_TYPE_R4:
7539                         case MONO_TYPE_U4:
7540                         case MONO_TYPE_I4:
7541                                 for (i = 0; i < alen; i++) {
7542                                         guint32 val = read32 (p);
7543                                         mono_array_set (arr, guint32, i, val);
7544                                         p += 4;
7545                                 }
7546                                 break;
7547                         case MONO_TYPE_R8:
7548                                 for (i = 0; i < alen; i++) {
7549                                         double val;
7550                                         readr8 (p, &val);
7551                                         mono_array_set (arr, double, i, val);
7552                                         p += 8;
7553                                 }
7554                                 break;
7555                         case MONO_TYPE_U8:
7556                         case MONO_TYPE_I8:
7557                                 for (i = 0; i < alen; i++) {
7558                                         guint64 val = read64 (p);
7559                                         mono_array_set (arr, guint64, i, val);
7560                                         p += 8;
7561                                 }
7562                                 break;
7563                         case MONO_TYPE_CLASS:
7564                         case MONO_TYPE_OBJECT:
7565                         case MONO_TYPE_STRING:
7566                                 for (i = 0; i < alen; i++) {
7567                                         MonoObject *item = load_cattr_value (image, &tklass->byval_arg, p, &p);
7568                                         mono_array_setref (arr, i, item);
7569                                 }
7570                                 break;
7571                         default:
7572                                 g_error ("Type 0x%02x not handled in custom attr array decoding", basetype);
7573                 }
7574                 *end=p;
7575                 return arr;
7576         }
7577         default:
7578                 g_error ("Type 0x%02x not handled in custom attr value decoding", type);
7579         }
7580         return NULL;
7581 }
7582
7583 static MonoObject*
7584 create_cattr_typed_arg (MonoType *t, MonoObject *val)
7585 {
7586         static MonoClass *klass;
7587         static MonoMethod *ctor;
7588         MonoObject *retval;
7589         void *params [2], *unboxed;
7590
7591         if (!klass)
7592                 klass = mono_class_from_name (mono_defaults.corlib, "System.Reflection", "CustomAttributeTypedArgument");
7593         if (!ctor)
7594                 ctor = mono_class_get_method_from_name (klass, ".ctor", 2);
7595         
7596         params [0] = mono_type_get_object (mono_domain_get (), t);
7597         params [1] = val;
7598         retval = mono_object_new (mono_domain_get (), klass);
7599         unboxed = mono_object_unbox (retval);
7600         mono_runtime_invoke (ctor, unboxed, params, NULL);
7601
7602         return retval;
7603 }
7604
7605 static MonoObject*
7606 create_cattr_named_arg (void *minfo, MonoObject *typedarg)
7607 {
7608         static MonoClass *klass;
7609         static MonoMethod *ctor;
7610         MonoObject *retval;
7611         void *unboxed, *params [2];
7612
7613         if (!klass)
7614                 klass = mono_class_from_name (mono_defaults.corlib, "System.Reflection", "CustomAttributeNamedArgument");
7615         if (!ctor)
7616                 ctor = mono_class_get_method_from_name (klass, ".ctor", 2);
7617
7618         params [0] = minfo;
7619         params [1] = typedarg;
7620         retval = mono_object_new (mono_domain_get (), klass);
7621         unboxed = mono_object_unbox (retval);
7622         mono_runtime_invoke (ctor, unboxed, params, NULL);
7623
7624         return retval;
7625 }
7626
7627 static gboolean
7628 type_is_reference (MonoType *type)
7629 {
7630         switch (type->type) {
7631         case MONO_TYPE_BOOLEAN:
7632         case MONO_TYPE_CHAR:
7633         case MONO_TYPE_U:
7634         case MONO_TYPE_I:
7635         case MONO_TYPE_U1:
7636         case MONO_TYPE_I1:
7637         case MONO_TYPE_U2:
7638         case MONO_TYPE_I2:
7639         case MONO_TYPE_U4:
7640         case MONO_TYPE_I4:
7641         case MONO_TYPE_U8:
7642         case MONO_TYPE_I8:
7643         case MONO_TYPE_R8:
7644         case MONO_TYPE_R4:
7645         case MONO_TYPE_VALUETYPE:
7646                 return FALSE;
7647         default:
7648                 return TRUE;
7649         }
7650 }
7651
7652 static void
7653 free_param_data (MonoMethodSignature *sig, void **params) {
7654         int i;
7655         for (i = 0; i < sig->param_count; ++i) {
7656                 if (!type_is_reference (sig->params [i]))
7657                         g_free (params [i]);
7658         }
7659 }
7660
7661 /*
7662  * Find the field index in the metadata FieldDef table.
7663  */
7664 static guint32
7665 find_field_index (MonoClass *klass, MonoClassField *field) {
7666         int i;
7667
7668         for (i = 0; i < klass->field.count; ++i) {
7669                 if (field == &klass->fields [i])
7670                         return klass->field.first + 1 + i;
7671         }
7672         return 0;
7673 }
7674
7675 /*
7676  * Find the property index in the metadata Property table.
7677  */
7678 static guint32
7679 find_property_index (MonoClass *klass, MonoProperty *property) {
7680         int i;
7681
7682         for (i = 0; i < klass->ext->property.count; ++i) {
7683                 if (property == &klass->ext->properties [i])
7684                         return klass->ext->property.first + 1 + i;
7685         }
7686         return 0;
7687 }
7688
7689 /*
7690  * Find the event index in the metadata Event table.
7691  */
7692 static guint32
7693 find_event_index (MonoClass *klass, MonoEvent *event) {
7694         int i;
7695
7696         for (i = 0; i < klass->ext->event.count; ++i) {
7697                 if (event == &klass->ext->events [i])
7698                         return klass->ext->event.first + 1 + i;
7699         }
7700         return 0;
7701 }
7702
7703 static MonoObject*
7704 create_custom_attr (MonoImage *image, MonoMethod *method, const guchar *data, guint32 len)
7705 {
7706         const char *p = (const char*)data;
7707         const char *named;
7708         guint32 i, j, num_named;
7709         MonoObject *attr;
7710         void **params;
7711
7712         mono_class_init (method->klass);
7713
7714         if (len == 0) {
7715                 attr = mono_object_new (mono_domain_get (), method->klass);
7716                 mono_runtime_invoke (method, attr, NULL, NULL);
7717                 return attr;
7718         }
7719
7720         if (len < 2 || read16 (p) != 0x0001) /* Prolog */
7721                 return NULL;
7722
7723         /*g_print ("got attr %s\n", method->klass->name);*/
7724
7725         /* Allocate using alloca so it gets GC tracking */
7726         params = alloca (mono_method_signature (method)->param_count * sizeof (void*)); 
7727
7728         /* skip prolog */
7729         p += 2;
7730         for (i = 0; i < mono_method_signature (method)->param_count; ++i) {
7731                 params [i] = load_cattr_value (image, mono_method_signature (method)->params [i], p, &p);
7732         }
7733
7734         named = p;
7735         attr = mono_object_new (mono_domain_get (), method->klass);
7736         mono_runtime_invoke (method, attr, params, NULL);
7737         free_param_data (method->signature, params);
7738         num_named = read16 (named);
7739         named += 2;
7740         for (j = 0; j < num_named; j++) {
7741                 gint name_len;
7742                 char *name, named_type, data_type;
7743                 named_type = *named++;
7744                 data_type = *named++; /* type of data */
7745                 if (data_type == MONO_TYPE_SZARRAY)
7746                         data_type = *named++;
7747                 if (data_type == MONO_TYPE_ENUM) {
7748                         gint type_len;
7749                         char *type_name;
7750                         type_len = mono_metadata_decode_blob_size (named, &named);
7751                         type_name = g_malloc (type_len + 1);
7752                         memcpy (type_name, named, type_len);
7753                         type_name [type_len] = 0;
7754                         named += type_len;
7755                         /* FIXME: lookup the type and check type consistency */
7756                         g_free (type_name);
7757                 }
7758                 name_len = mono_metadata_decode_blob_size (named, &named);
7759                 name = g_malloc (name_len + 1);
7760                 memcpy (name, named, name_len);
7761                 name [name_len] = 0;
7762                 named += name_len;
7763                 if (named_type == 0x53) {
7764                         MonoClassField *field = mono_class_get_field_from_name (mono_object_class (attr), name);
7765                         void *val = load_cattr_value (image, field->type, named, &named);
7766                         mono_field_set_value (attr, field, val);
7767                         if (!type_is_reference (field->type))
7768                                 g_free (val);
7769                 } else if (named_type == 0x54) {
7770                         MonoProperty *prop;
7771                         void *pparams [1];
7772                         MonoType *prop_type;
7773
7774                         prop = mono_class_get_property_from_name (mono_object_class (attr), name);
7775                         /* can we have more that 1 arg in a custom attr named property? */
7776                         prop_type = prop->get? mono_method_signature (prop->get)->ret :
7777                              mono_method_signature (prop->set)->params [mono_method_signature (prop->set)->param_count - 1];
7778                         pparams [0] = load_cattr_value (image, prop_type, named, &named);
7779                         mono_property_set_value (prop, attr, pparams, NULL);
7780                         if (!type_is_reference (prop_type))
7781                                 g_free (pparams [0]);
7782                 }
7783                 g_free (name);
7784         }
7785
7786         return attr;
7787 }
7788
7789 static MonoObject*
7790 create_custom_attr_data (MonoImage *image, MonoMethod *method, const guchar *data, guint32 len)
7791 {
7792         MonoArray *typedargs, *namedargs;
7793         MonoClass *attrklass;
7794         static MonoMethod *ctor;
7795         MonoDomain *domain;
7796         MonoObject *attr;
7797         const char *p = (const char*)data;
7798         const char *named;
7799         guint32 i, j, num_named;
7800         void *params [3];
7801
7802         mono_class_init (method->klass);
7803
7804         if (!ctor)
7805                 ctor = mono_class_get_method_from_name (mono_defaults.customattribute_data_class, ".ctor", 3);
7806
7807         domain = mono_domain_get ();
7808         if (len == 0) {
7809                 /* This is for Attributes with no parameters */
7810                 attr = mono_object_new (domain, mono_defaults.customattribute_data_class);
7811                 params [0] = mono_method_get_object (domain, method, NULL);
7812                 params [1] = params [2] = NULL;
7813                 mono_runtime_invoke (method, attr, params, NULL);
7814                 return attr;
7815         }
7816
7817         if (len < 2 || read16 (p) != 0x0001) /* Prolog */
7818                 return NULL;
7819
7820         typedargs = mono_array_new (domain, mono_get_object_class (), mono_method_signature (method)->param_count);
7821         
7822         /* skip prolog */
7823         p += 2;
7824         for (i = 0; i < mono_method_signature (method)->param_count; ++i) {
7825                 MonoObject *obj, *typedarg;
7826                 void *val;
7827
7828                 val = load_cattr_value (image, mono_method_signature (method)->params [i], p, &p);
7829                 obj = type_is_reference (mono_method_signature (method)->params [i]) ? 
7830                         val : mono_value_box (domain, mono_class_from_mono_type (mono_method_signature (method)->params [i]), val);
7831                 typedarg = create_cattr_typed_arg (mono_method_signature (method)->params [i], obj);
7832                 mono_array_setref (typedargs, i, typedarg);
7833
7834                 if (!type_is_reference (mono_method_signature (method)->params [i]))
7835                         g_free (val);
7836         }
7837
7838         named = p;
7839         num_named = read16 (named);
7840         namedargs = mono_array_new (domain, mono_get_object_class (), num_named);
7841         named += 2;
7842         attrklass = method->klass;
7843         for (j = 0; j < num_named; j++) {
7844                 gint name_len;
7845                 char *name, named_type, data_type;
7846                 named_type = *named++;
7847                 data_type = *named++; /* type of data */
7848                 if (data_type == MONO_TYPE_SZARRAY)
7849                         data_type = *named++;
7850                 if (data_type == MONO_TYPE_ENUM) {
7851                         gint type_len;
7852                         char *type_name;
7853                         type_len = mono_metadata_decode_blob_size (named, &named);
7854                         type_name = g_malloc (type_len + 1);
7855                         memcpy (type_name, named, type_len);
7856                         type_name [type_len] = 0;
7857                         named += type_len;
7858                         /* FIXME: lookup the type and check type consistency */
7859                         g_free (type_name);
7860                 }
7861                 name_len = mono_metadata_decode_blob_size (named, &named);
7862                 name = g_malloc (name_len + 1);
7863                 memcpy (name, named, name_len);
7864                 name [name_len] = 0;
7865                 named += name_len;
7866                 if (named_type == 0x53) {
7867                         MonoObject *obj, *typedarg, *namedarg;
7868                         MonoClassField *field = mono_class_get_field_from_name (attrklass, name);
7869                         void *minfo, *val = load_cattr_value (image, field->type, named, &named);
7870                         
7871                         minfo = mono_field_get_object (domain, NULL, field);
7872                         obj = type_is_reference (field->type) ? val : mono_value_box (domain, mono_class_from_mono_type (field->type), val);
7873                         typedarg = create_cattr_typed_arg (field->type, obj);
7874                         namedarg = create_cattr_named_arg (minfo, typedarg);
7875                         mono_array_setref (namedargs, j, namedarg);
7876                         if (!type_is_reference (field->type))
7877                                 g_free (val);
7878                 } else if (named_type == 0x54) {
7879                         MonoObject *obj, *typedarg, *namedarg;
7880                         MonoType *prop_type;
7881                         void *val, *minfo;
7882                         MonoProperty *prop = mono_class_get_property_from_name (attrklass, name);
7883
7884                         prop_type = prop->get? mono_method_signature (prop->get)->ret :
7885                              mono_method_signature (prop->set)->params [mono_method_signature (prop->set)->param_count - 1];
7886                         minfo =  mono_property_get_object (domain, NULL, prop);
7887                         val = load_cattr_value (image, prop_type, named, &named);
7888                         obj = type_is_reference (prop_type) ? val : mono_value_box (domain, mono_class_from_mono_type (prop_type), val);
7889                         typedarg = create_cattr_typed_arg (prop_type, obj);
7890                         namedarg = create_cattr_named_arg (minfo, typedarg);
7891                         mono_array_setref (namedargs, j, namedarg);
7892                         if (!type_is_reference (prop_type))
7893                                 g_free (val);
7894                 }
7895                 g_free (name);
7896         }
7897         attr = mono_object_new (domain, mono_defaults.customattribute_data_class);
7898         params [0] = mono_method_get_object (domain, method, NULL);
7899         params [1] = typedargs;
7900         params [2] = namedargs;
7901         mono_runtime_invoke (ctor, attr, params, NULL);
7902         return attr;
7903 }
7904
7905 MonoArray*
7906 mono_custom_attrs_construct (MonoCustomAttrInfo *cinfo)
7907 {
7908         MonoArray *result;
7909         MonoObject *attr;
7910         int i;
7911
7912         result = mono_array_new (mono_domain_get (), mono_defaults.attribute_class, cinfo->num_attrs);
7913         for (i = 0; i < cinfo->num_attrs; ++i) {
7914                 if (!cinfo->attrs [i].ctor)
7915                         /* The cattr type is not finished yet */
7916                         /* We should include the type name but cinfo doesn't contain it */
7917                         mono_raise_exception (mono_get_exception_type_load (NULL, NULL));
7918                 attr = create_custom_attr (cinfo->image, cinfo->attrs [i].ctor, cinfo->attrs [i].data, cinfo->attrs [i].data_size);
7919                 mono_array_setref (result, i, attr);
7920         }
7921         return result;
7922 }
7923
7924 static MonoArray*
7925 mono_custom_attrs_construct_by_type (MonoCustomAttrInfo *cinfo, MonoClass *attr_klass)
7926 {
7927         MonoArray *result;
7928         MonoObject *attr;
7929         int i, n;
7930
7931         n = 0;
7932         for (i = 0; i < cinfo->num_attrs; ++i) {
7933                 if (mono_class_is_assignable_from (attr_klass, cinfo->attrs [i].ctor->klass))
7934                         n ++;
7935         }
7936
7937         result = mono_array_new (mono_domain_get (), mono_defaults.attribute_class, n);
7938         n = 0;
7939         for (i = 0; i < cinfo->num_attrs; ++i) {
7940                 if (mono_class_is_assignable_from (attr_klass, cinfo->attrs [i].ctor->klass)) {
7941                         attr = create_custom_attr (cinfo->image, cinfo->attrs [i].ctor, cinfo->attrs [i].data, cinfo->attrs [i].data_size);
7942                         mono_array_setref (result, n, attr);
7943                         n ++;
7944                 }
7945         }
7946         return result;
7947 }
7948
7949 static MonoArray*
7950 mono_custom_attrs_data_construct (MonoCustomAttrInfo *cinfo)
7951 {
7952         MonoArray *result;
7953         MonoObject *attr;
7954         int i;
7955         
7956         result = mono_array_new (mono_domain_get (), mono_defaults.customattribute_data_class, cinfo->num_attrs);
7957         for (i = 0; i < cinfo->num_attrs; ++i) {
7958                 attr = create_custom_attr_data (cinfo->image, cinfo->attrs [i].ctor, cinfo->attrs [i].data, cinfo->attrs [i].data_size);
7959                 mono_array_setref (result, i, attr);
7960         }
7961         return result;
7962 }
7963
7964 /**
7965  * mono_custom_attrs_from_index:
7966  *
7967  * Returns: NULL if no attributes are found or if a loading error occurs.
7968  */
7969 MonoCustomAttrInfo*
7970 mono_custom_attrs_from_index (MonoImage *image, guint32 idx)
7971 {
7972         guint32 mtoken, i, len;
7973         guint32 cols [MONO_CUSTOM_ATTR_SIZE];
7974         MonoTableInfo *ca;
7975         MonoCustomAttrInfo *ainfo;
7976         GList *tmp, *list = NULL;
7977         const char *data;
7978
7979         ca = &image->tables [MONO_TABLE_CUSTOMATTRIBUTE];
7980
7981         i = mono_metadata_custom_attrs_from_index (image, idx);
7982         if (!i)
7983                 return NULL;
7984         i --;
7985         while (i < ca->rows) {
7986                 if (mono_metadata_decode_row_col (ca, i, MONO_CUSTOM_ATTR_PARENT) != idx)
7987                         break;
7988                 list = g_list_prepend (list, GUINT_TO_POINTER (i));
7989                 ++i;
7990         }
7991         len = g_list_length (list);
7992         if (!len)
7993                 return NULL;
7994         ainfo = g_malloc0 (sizeof (MonoCustomAttrInfo) + sizeof (MonoCustomAttrEntry) * (len - MONO_ZERO_LEN_ARRAY));
7995         ainfo->num_attrs = len;
7996         ainfo->image = image;
7997         for (i = 0, tmp = list; i < len; ++i, tmp = tmp->next) {
7998                 mono_metadata_decode_row (ca, GPOINTER_TO_UINT (tmp->data), cols, MONO_CUSTOM_ATTR_SIZE);
7999                 mtoken = cols [MONO_CUSTOM_ATTR_TYPE] >> MONO_CUSTOM_ATTR_TYPE_BITS;
8000                 switch (cols [MONO_CUSTOM_ATTR_TYPE] & MONO_CUSTOM_ATTR_TYPE_MASK) {
8001                 case MONO_CUSTOM_ATTR_TYPE_METHODDEF:
8002                         mtoken |= MONO_TOKEN_METHOD_DEF;
8003                         break;
8004                 case MONO_CUSTOM_ATTR_TYPE_MEMBERREF:
8005                         mtoken |= MONO_TOKEN_MEMBER_REF;
8006                         break;
8007                 default:
8008                         g_error ("Unknown table for custom attr type %08x", cols [MONO_CUSTOM_ATTR_TYPE]);
8009                         break;
8010                 }
8011                 ainfo->attrs [i].ctor = mono_get_method (image, mtoken, NULL);
8012                 if (!ainfo->attrs [i].ctor) {
8013                         g_warning ("Can't find custom attr constructor image: %s mtoken: 0x%08x", image->name, mtoken);
8014                         g_list_free (list);
8015                         g_free (ainfo);
8016                         return NULL;
8017                 }
8018                 data = mono_metadata_blob_heap (image, cols [MONO_CUSTOM_ATTR_VALUE]);
8019                 ainfo->attrs [i].data_size = mono_metadata_decode_value (data, &data);
8020                 ainfo->attrs [i].data = (guchar*)data;
8021         }
8022         g_list_free (list);
8023
8024         return ainfo;
8025 }
8026
8027 MonoCustomAttrInfo*
8028 mono_custom_attrs_from_method (MonoMethod *method)
8029 {
8030         guint32 idx;
8031
8032         /*
8033          * An instantiated method has the same cattrs as the generic method definition.
8034          *
8035          * LAMESPEC: The .NET SRE throws an exception for instantiations of generic method builders
8036          *           Note that this stanza is not necessary for non-SRE types, but it's a micro-optimization
8037          */
8038         if (method->is_inflated)
8039                 method = ((MonoMethodInflated *) method)->declaring;
8040         
8041         if (method->dynamic || method->klass->image->dynamic)
8042                 return lookup_custom_attr (method->klass->image, method);
8043
8044         idx = mono_method_get_index (method);
8045         idx <<= MONO_CUSTOM_ATTR_BITS;
8046         idx |= MONO_CUSTOM_ATTR_METHODDEF;
8047         return mono_custom_attrs_from_index (method->klass->image, idx);
8048 }
8049
8050 MonoCustomAttrInfo*
8051 mono_custom_attrs_from_class (MonoClass *klass)
8052 {
8053         guint32 idx;
8054
8055         if (klass->generic_class)
8056                 klass = klass->generic_class->container_class;
8057
8058         if (klass->image->dynamic)
8059                 return lookup_custom_attr (klass->image, klass);
8060
8061         if (klass->byval_arg.type == MONO_TYPE_VAR || klass->byval_arg.type == MONO_TYPE_MVAR) {
8062                 idx = mono_metadata_token_index (klass->sizes.generic_param_token);
8063                 idx <<= MONO_CUSTOM_ATTR_BITS;
8064                 idx |= MONO_CUSTOM_ATTR_GENERICPAR;
8065         } else {
8066                 idx = mono_metadata_token_index (klass->type_token);
8067                 idx <<= MONO_CUSTOM_ATTR_BITS;
8068                 idx |= MONO_CUSTOM_ATTR_TYPEDEF;
8069         }
8070         return mono_custom_attrs_from_index (klass->image, idx);
8071 }
8072
8073 MonoCustomAttrInfo*
8074 mono_custom_attrs_from_assembly (MonoAssembly *assembly)
8075 {
8076         guint32 idx;
8077         
8078         if (assembly->image->dynamic)
8079                 return lookup_custom_attr (assembly->image, assembly);
8080         idx = 1; /* there is only one assembly */
8081         idx <<= MONO_CUSTOM_ATTR_BITS;
8082         idx |= MONO_CUSTOM_ATTR_ASSEMBLY;
8083         return mono_custom_attrs_from_index (assembly->image, idx);
8084 }
8085
8086 static MonoCustomAttrInfo*
8087 mono_custom_attrs_from_module (MonoImage *image)
8088 {
8089         guint32 idx;
8090         
8091         if (image->dynamic)
8092                 return lookup_custom_attr (image, image);
8093         idx = 1; /* there is only one module */
8094         idx <<= MONO_CUSTOM_ATTR_BITS;
8095         idx |= MONO_CUSTOM_ATTR_MODULE;
8096         return mono_custom_attrs_from_index (image, idx);
8097 }
8098
8099 MonoCustomAttrInfo*
8100 mono_custom_attrs_from_property (MonoClass *klass, MonoProperty *property)
8101 {
8102         guint32 idx;
8103         
8104         if (klass->image->dynamic) {
8105                 property = mono_metadata_get_corresponding_property_from_generic_type_definition (property);
8106                 return lookup_custom_attr (klass->image, property);
8107         }
8108         idx = find_property_index (klass, property);
8109         idx <<= MONO_CUSTOM_ATTR_BITS;
8110         idx |= MONO_CUSTOM_ATTR_PROPERTY;
8111         return mono_custom_attrs_from_index (klass->image, idx);
8112 }
8113
8114 MonoCustomAttrInfo*
8115 mono_custom_attrs_from_event (MonoClass *klass, MonoEvent *event)
8116 {
8117         guint32 idx;
8118         
8119         if (klass->image->dynamic) {
8120                 event = mono_metadata_get_corresponding_event_from_generic_type_definition (event);
8121                 return lookup_custom_attr (klass->image, event);
8122         }
8123         idx = find_event_index (klass, event);
8124         idx <<= MONO_CUSTOM_ATTR_BITS;
8125         idx |= MONO_CUSTOM_ATTR_EVENT;
8126         return mono_custom_attrs_from_index (klass->image, idx);
8127 }
8128
8129 MonoCustomAttrInfo*
8130 mono_custom_attrs_from_field (MonoClass *klass, MonoClassField *field)
8131 {
8132         guint32 idx;
8133         if (klass->image->dynamic) {
8134                 field = mono_metadata_get_corresponding_field_from_generic_type_definition (field);
8135                 return lookup_custom_attr (klass->image, field);
8136         }
8137         idx = find_field_index (klass, field);
8138         idx <<= MONO_CUSTOM_ATTR_BITS;
8139         idx |= MONO_CUSTOM_ATTR_FIELDDEF;
8140         return mono_custom_attrs_from_index (klass->image, idx);
8141 }
8142
8143 MonoCustomAttrInfo*
8144 mono_custom_attrs_from_param (MonoMethod *method, guint32 param)
8145 {
8146         MonoTableInfo *ca;
8147         guint32 i, idx, method_index;
8148         guint32 param_list, param_last, param_pos, found;
8149         MonoImage *image;
8150         MonoReflectionMethodAux *aux;
8151
8152         /*
8153          * An instantiated method has the same cattrs as the generic method definition.
8154          *
8155          * LAMESPEC: The .NET SRE throws an exception for instantiations of generic method builders
8156          *           Note that this stanza is not necessary for non-SRE types, but it's a micro-optimization
8157          */
8158         if (method->is_inflated)
8159                 method = ((MonoMethodInflated *) method)->declaring;
8160
8161         if (method->klass->image->dynamic) {
8162                 MonoCustomAttrInfo *res, *ainfo;
8163                 int size;
8164
8165                 aux = g_hash_table_lookup (((MonoDynamicImage*)method->klass->image)->method_aux_hash, method);
8166                 if (!aux || !aux->param_cattr)
8167                         return NULL;
8168
8169                 /* Need to copy since it will be freed later */
8170                 ainfo = aux->param_cattr [param];
8171                 size = sizeof (MonoCustomAttrInfo) + sizeof (MonoCustomAttrEntry) * (ainfo->num_attrs - MONO_ZERO_LEN_ARRAY);
8172                 res = g_malloc0 (size);
8173                 memcpy (res, ainfo, size);
8174                 return res;
8175         }
8176
8177         image = method->klass->image;
8178         method_index = mono_method_get_index (method);
8179         ca = &image->tables [MONO_TABLE_METHOD];
8180
8181         param_list = mono_metadata_decode_row_col (ca, method_index - 1, MONO_METHOD_PARAMLIST);
8182         if (method_index == ca->rows) {
8183                 ca = &image->tables [MONO_TABLE_PARAM];
8184                 param_last = ca->rows + 1;
8185         } else {
8186                 param_last = mono_metadata_decode_row_col (ca, method_index, MONO_METHOD_PARAMLIST);
8187                 ca = &image->tables [MONO_TABLE_PARAM];
8188         }
8189         found = FALSE;
8190         for (i = param_list; i < param_last; ++i) {
8191                 param_pos = mono_metadata_decode_row_col (ca, i - 1, MONO_PARAM_SEQUENCE);
8192                 if (param_pos == param) {
8193                         found = TRUE;
8194                         break;
8195                 }
8196         }
8197         if (!found)
8198                 return NULL;
8199         idx = i;
8200         idx <<= MONO_CUSTOM_ATTR_BITS;
8201         idx |= MONO_CUSTOM_ATTR_PARAMDEF;
8202         return mono_custom_attrs_from_index (image, idx);
8203 }
8204
8205 gboolean
8206 mono_custom_attrs_has_attr (MonoCustomAttrInfo *ainfo, MonoClass *attr_klass)
8207 {
8208         int i;
8209         MonoClass *klass;
8210         for (i = 0; i < ainfo->num_attrs; ++i) {
8211                 klass = ainfo->attrs [i].ctor->klass;
8212                 if (mono_class_has_parent (klass, attr_klass))
8213                         return TRUE;
8214         }
8215         return FALSE;
8216 }
8217
8218 MonoObject*
8219 mono_custom_attrs_get_attr (MonoCustomAttrInfo *ainfo, MonoClass *attr_klass)
8220 {
8221         int i, attr_index;
8222         MonoClass *klass;
8223         MonoArray *attrs;
8224
8225         attr_index = -1;
8226         for (i = 0; i < ainfo->num_attrs; ++i) {
8227                 klass = ainfo->attrs [i].ctor->klass;
8228                 if (mono_class_has_parent (klass, attr_klass)) {
8229                         attr_index = i;
8230                         break;
8231                 }
8232         }
8233         if (attr_index == -1)
8234                 return NULL;
8235
8236         attrs = mono_custom_attrs_construct (ainfo);
8237         if (attrs)
8238                 return mono_array_get (attrs, MonoObject*, attr_index);
8239         else
8240                 return NULL;
8241 }
8242
8243 /*
8244  * mono_reflection_get_custom_attrs_info:
8245  * @obj: a reflection object handle
8246  *
8247  * Return the custom attribute info for attributes defined for the
8248  * reflection handle @obj. The objects.
8249  *
8250  * FIXME this function leaks like a sieve for SRE objects.
8251  */
8252 MonoCustomAttrInfo*
8253 mono_reflection_get_custom_attrs_info (MonoObject *obj)
8254 {
8255         MonoClass *klass;
8256         MonoCustomAttrInfo *cinfo = NULL;
8257         
8258         klass = obj->vtable->klass;
8259         if (klass == mono_defaults.monotype_class) {
8260                 MonoReflectionType *rtype = (MonoReflectionType*)obj;
8261                 klass = mono_class_from_mono_type (rtype->type);
8262                 cinfo = mono_custom_attrs_from_class (klass);
8263         } else if (strcmp ("Assembly", klass->name) == 0) {
8264                 MonoReflectionAssembly *rassembly = (MonoReflectionAssembly*)obj;
8265                 cinfo = mono_custom_attrs_from_assembly (rassembly->assembly);
8266         } else if (strcmp ("Module", klass->name) == 0) {
8267                 MonoReflectionModule *module = (MonoReflectionModule*)obj;
8268                 cinfo = mono_custom_attrs_from_module (module->image);
8269         } else if (strcmp ("MonoProperty", klass->name) == 0) {
8270                 MonoReflectionProperty *rprop = (MonoReflectionProperty*)obj;
8271                 cinfo = mono_custom_attrs_from_property (rprop->property->parent, rprop->property);
8272         } else if (strcmp ("MonoEvent", klass->name) == 0) {
8273                 MonoReflectionEvent *revent = (MonoReflectionEvent*)obj;
8274                 cinfo = mono_custom_attrs_from_event (revent->event->parent, revent->event);
8275         } else if (strcmp ("MonoField", klass->name) == 0) {
8276                 MonoReflectionField *rfield = (MonoReflectionField*)obj;
8277                 cinfo = mono_custom_attrs_from_field (rfield->field->parent, rfield->field);
8278         } else if ((strcmp ("MonoMethod", klass->name) == 0) || (strcmp ("MonoCMethod", klass->name) == 0)) {
8279                 MonoReflectionMethod *rmethod = (MonoReflectionMethod*)obj;
8280                 cinfo = mono_custom_attrs_from_method (rmethod->method);
8281         } else if ((strcmp ("MonoGenericMethod", klass->name) == 0) || (strcmp ("MonoGenericCMethod", klass->name) == 0)) {
8282                 MonoReflectionMethod *rmethod = (MonoReflectionMethod*)obj;
8283                 cinfo = mono_custom_attrs_from_method (rmethod->method);
8284         } else if (strcmp ("ParameterInfo", klass->name) == 0) {
8285                 MonoReflectionParameter *param = (MonoReflectionParameter*)obj;
8286                 MonoReflectionMethod *rmethod = (MonoReflectionMethod*)param->MemberImpl;
8287                 cinfo = mono_custom_attrs_from_param (rmethod->method, param->PositionImpl + 1);
8288         } else if (strcmp ("AssemblyBuilder", klass->name) == 0) {
8289                 MonoReflectionAssemblyBuilder *assemblyb = (MonoReflectionAssemblyBuilder*)obj;
8290                 cinfo = mono_custom_attrs_from_builders (NULL, assemblyb->assembly.assembly->image, assemblyb->cattrs);
8291         } else if (strcmp ("TypeBuilder", klass->name) == 0) {
8292                 MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder*)obj;
8293                 cinfo = mono_custom_attrs_from_builders (NULL, &tb->module->dynamic_image->image, tb->cattrs);
8294         } else if (strcmp ("ModuleBuilder", klass->name) == 0) {
8295                 MonoReflectionModuleBuilder *mb = (MonoReflectionModuleBuilder*)obj;
8296                 cinfo = mono_custom_attrs_from_builders (NULL, &mb->dynamic_image->image, mb->cattrs);
8297         } else if (strcmp ("ConstructorBuilder", klass->name) == 0) {
8298                 MonoReflectionCtorBuilder *cb = (MonoReflectionCtorBuilder*)obj;
8299                 cinfo = mono_custom_attrs_from_builders (NULL, cb->mhandle->klass->image, cb->cattrs);
8300         } else if (strcmp ("MethodBuilder", klass->name) == 0) {
8301                 MonoReflectionMethodBuilder *mb = (MonoReflectionMethodBuilder*)obj;
8302                 cinfo = mono_custom_attrs_from_builders (NULL, mb->mhandle->klass->image, mb->cattrs);
8303         } else if (strcmp ("FieldBuilder", klass->name) == 0) {
8304                 MonoReflectionFieldBuilder *fb = (MonoReflectionFieldBuilder*)obj;
8305                 cinfo = mono_custom_attrs_from_builders (NULL, &((MonoReflectionTypeBuilder*)fb->typeb)->module->dynamic_image->image, fb->cattrs);
8306         } else if (strcmp ("MonoGenericClass", klass->name) == 0) {
8307                 MonoReflectionGenericClass *gclass = (MonoReflectionGenericClass*)obj;
8308                 cinfo = mono_reflection_get_custom_attrs_info ((MonoObject*)gclass->generic_type);
8309         } else { /* handle other types here... */
8310                 g_error ("get custom attrs not yet supported for %s", klass->name);
8311         }
8312
8313         return cinfo;
8314 }
8315
8316 /*
8317  * mono_reflection_get_custom_attrs_by_type:
8318  * @obj: a reflection object handle
8319  *
8320  * Return an array with all the custom attributes defined of the
8321  * reflection handle @obj. If @attr_klass is non-NULL, only custom attributes 
8322  * of that type are returned. The objects are fully build. Return NULL if a loading error
8323  * occurs.
8324  */
8325 MonoArray*
8326 mono_reflection_get_custom_attrs_by_type (MonoObject *obj, MonoClass *attr_klass)
8327 {
8328         MonoArray *result;
8329         MonoCustomAttrInfo *cinfo;
8330
8331         cinfo = mono_reflection_get_custom_attrs_info (obj);
8332         if (cinfo) {
8333                 if (attr_klass)
8334                         result = mono_custom_attrs_construct_by_type (cinfo, attr_klass);
8335                 else
8336                         result = mono_custom_attrs_construct (cinfo);
8337                 if (!cinfo->cached)
8338                         mono_custom_attrs_free (cinfo);
8339         } else {
8340                 if (mono_loader_get_last_error ())
8341                         return NULL;
8342                 result = mono_array_new (mono_domain_get (), mono_defaults.attribute_class, 0);
8343         }
8344
8345         return result;
8346 }
8347
8348 /*
8349  * mono_reflection_get_custom_attrs:
8350  * @obj: a reflection object handle
8351  *
8352  * Return an array with all the custom attributes defined of the
8353  * reflection handle @obj. The objects are fully build. Return NULL if a loading error
8354  * occurs.
8355  */
8356 MonoArray*
8357 mono_reflection_get_custom_attrs (MonoObject *obj)
8358 {
8359         return mono_reflection_get_custom_attrs_by_type (obj, NULL);
8360 }
8361
8362 /*
8363  * mono_reflection_get_custom_attrs_data:
8364  * @obj: a reflection obj handle
8365  *
8366  * Returns an array of System.Reflection.CustomAttributeData,
8367  * which include information about attributes reflected on
8368  * types loaded using the Reflection Only methods
8369  */
8370 MonoArray*
8371 mono_reflection_get_custom_attrs_data (MonoObject *obj)
8372 {
8373         MonoArray *result;
8374         MonoCustomAttrInfo *cinfo;
8375
8376         cinfo = mono_reflection_get_custom_attrs_info (obj);
8377         if (cinfo) {
8378                 result = mono_custom_attrs_data_construct (cinfo);
8379                 if (!cinfo->cached)
8380                         mono_custom_attrs_free (cinfo);
8381         } else
8382                 result = mono_array_new (mono_domain_get (), mono_defaults.customattribute_data_class, 0);
8383
8384         return result;
8385 }
8386
8387 static MonoReflectionType*
8388 mono_reflection_type_get_underlying_system_type (MonoReflectionType* t)
8389 {
8390         MonoMethod *method_get_underlying_system_type;
8391
8392         method_get_underlying_system_type = mono_object_get_virtual_method ((MonoObject *) t,
8393                                                                             mono_class_get_method_from_name (mono_object_class (t),
8394                                                                                                              "get_UnderlyingSystemType",
8395                                                                                                              0));
8396         return (MonoReflectionType *) mono_runtime_invoke (method_get_underlying_system_type, t, NULL, NULL);
8397 }
8398
8399 static MonoType*
8400 mono_reflection_type_get_handle (MonoReflectionType* t)
8401 {
8402         if (t->type)
8403             return t->type;
8404
8405         t = mono_reflection_type_get_underlying_system_type (t);
8406         if (t)
8407             return t->type;
8408
8409         return NULL;
8410 }
8411
8412 /**
8413  * LOCKING: Assumes the loader lock is held.
8414  */
8415 static MonoMethodSignature*
8416 parameters_to_signature (MonoImage *image, MonoArray *parameters) {
8417         MonoMethodSignature *sig;
8418         int count, i;
8419
8420         count = parameters? mono_array_length (parameters): 0;
8421
8422         sig = image_g_malloc0 (image, sizeof (MonoMethodSignature) + sizeof (MonoType*) * count);
8423         sig->param_count = count;
8424         sig->sentinelpos = -1; /* FIXME */
8425         for (i = 0; i < count; ++i) {
8426                 MonoReflectionType *pt = mono_array_get (parameters, MonoReflectionType*, i);
8427                 sig->params [i] = mono_reflection_type_get_handle (pt);
8428         }
8429         return sig;
8430 }
8431
8432 /**
8433  * LOCKING: Assumes the loader lock is held.
8434  */
8435 static MonoMethodSignature*
8436 ctor_builder_to_signature (MonoImage *image, MonoReflectionCtorBuilder *ctor) {
8437         MonoMethodSignature *sig;
8438
8439         sig = parameters_to_signature (image, ctor->parameters);
8440         sig->hasthis = ctor->attrs & METHOD_ATTRIBUTE_STATIC? 0: 1;
8441         sig->ret = &mono_defaults.void_class->byval_arg;
8442         return sig;
8443 }
8444
8445 /**
8446  * LOCKING: Assumes the loader lock is held.
8447  */
8448 static MonoMethodSignature*
8449 method_builder_to_signature (MonoImage *image, MonoReflectionMethodBuilder *method) {
8450         MonoMethodSignature *sig;
8451
8452         sig = parameters_to_signature (image, method->parameters);
8453         sig->hasthis = method->attrs & METHOD_ATTRIBUTE_STATIC? 0: 1;
8454         sig->ret = method->rtype? method->rtype->type: &mono_defaults.void_class->byval_arg;
8455         sig->generic_param_count = method->generic_params ? mono_array_length (method->generic_params) : 0;
8456         return sig;
8457 }
8458
8459 static MonoMethodSignature*
8460 dynamic_method_to_signature (MonoReflectionDynamicMethod *method) {
8461         MonoMethodSignature *sig;
8462
8463         sig = parameters_to_signature (NULL, method->parameters);
8464         sig->hasthis = method->attrs & METHOD_ATTRIBUTE_STATIC? 0: 1;
8465         sig->ret = method->rtype? method->rtype->type: &mono_defaults.void_class->byval_arg;
8466         sig->generic_param_count = 0;
8467         return sig;
8468 }
8469
8470 static void
8471 get_prop_name_and_type (MonoObject *prop, char **name, MonoType **type)
8472 {
8473         MonoClass *klass = mono_object_class (prop);
8474         if (strcmp (klass->name, "PropertyBuilder") == 0) {
8475                 MonoReflectionPropertyBuilder *pb = (MonoReflectionPropertyBuilder *)prop;
8476                 *name = mono_string_to_utf8 (pb->name);
8477                 *type = pb->type->type;
8478         } else {
8479                 MonoReflectionProperty *p = (MonoReflectionProperty *)prop;
8480                 *name = g_strdup (p->property->name);
8481                 if (p->property->get)
8482                         *type = mono_method_signature (p->property->get)->ret;
8483                 else
8484                         *type = mono_method_signature (p->property->set)->params [mono_method_signature (p->property->set)->param_count - 1];
8485         }
8486 }
8487
8488 static void
8489 get_field_name_and_type (MonoObject *field, char **name, MonoType **type)
8490 {
8491         MonoClass *klass = mono_object_class (field);
8492         if (strcmp (klass->name, "FieldBuilder") == 0) {
8493                 MonoReflectionFieldBuilder *fb = (MonoReflectionFieldBuilder *)field;
8494                 *name = mono_string_to_utf8 (fb->name);
8495                 *type = fb->type->type;
8496         } else {
8497                 MonoReflectionField *f = (MonoReflectionField *)field;
8498                 *name = g_strdup (mono_field_get_name (f->field));
8499                 *type = f->field->type;
8500         }
8501 }
8502
8503 /*
8504  * Encode a value in a custom attribute stream of bytes.
8505  * The value to encode is either supplied as an object in argument val
8506  * (valuetypes are boxed), or as a pointer to the data in the
8507  * argument argval.
8508  * @type represents the type of the value
8509  * @buffer is the start of the buffer
8510  * @p the current position in the buffer
8511  * @buflen contains the size of the buffer and is used to return the new buffer size
8512  * if this needs to be realloced.
8513  * @retbuffer and @retp return the start and the position of the buffer
8514  */
8515 static void
8516 encode_cattr_value (MonoAssembly *assembly, char *buffer, char *p, char **retbuffer, char **retp, guint32 *buflen, MonoType *type, MonoObject *arg, char *argval)
8517 {
8518         MonoTypeEnum simple_type;
8519         
8520         if ((p-buffer) + 10 >= *buflen) {
8521                 char *newbuf;
8522                 *buflen *= 2;
8523                 newbuf = g_realloc (buffer, *buflen);
8524                 p = newbuf + (p-buffer);
8525                 buffer = newbuf;
8526         }
8527         if (!argval)
8528                 argval = ((char*)arg + sizeof (MonoObject));
8529         simple_type = type->type;
8530 handle_enum:
8531         switch (simple_type) {
8532         case MONO_TYPE_BOOLEAN:
8533         case MONO_TYPE_U1:
8534         case MONO_TYPE_I1:
8535                 *p++ = *argval;
8536                 break;
8537         case MONO_TYPE_CHAR:
8538         case MONO_TYPE_U2:
8539         case MONO_TYPE_I2:
8540                 swap_with_size (p, argval, 2, 1);
8541                 p += 2;
8542                 break;
8543         case MONO_TYPE_U4:
8544         case MONO_TYPE_I4:
8545         case MONO_TYPE_R4:
8546                 swap_with_size (p, argval, 4, 1);
8547                 p += 4;
8548                 break;
8549         case MONO_TYPE_R8:
8550 #if defined(ARM_FPU_FPA) && G_BYTE_ORDER == G_LITTLE_ENDIAN
8551                 p [0] = argval [4];
8552                 p [1] = argval [5];
8553                 p [2] = argval [6];
8554                 p [3] = argval [7];
8555                 p [4] = argval [0];
8556                 p [5] = argval [1];
8557                 p [6] = argval [2];
8558                 p [7] = argval [3];
8559 #else
8560                 swap_with_size (p, argval, 8, 1);
8561 #endif
8562                 p += 8;
8563                 break;
8564         case MONO_TYPE_U8:
8565         case MONO_TYPE_I8:
8566                 swap_with_size (p, argval, 8, 1);
8567                 p += 8;
8568                 break;
8569         case MONO_TYPE_VALUETYPE:
8570                 if (type->data.klass->enumtype) {
8571                         simple_type = mono_class_enum_basetype (type->data.klass)->type;
8572                         goto handle_enum;
8573                 } else {
8574                         g_warning ("generic valutype %s not handled in custom attr value decoding", type->data.klass->name);
8575                 }
8576                 break;
8577         case MONO_TYPE_STRING: {
8578                 char *str;
8579                 guint32 slen;
8580                 if (!arg) {
8581                         *p++ = 0xFF;
8582                         break;
8583                 }
8584                 str = mono_string_to_utf8 ((MonoString*)arg);
8585                 slen = strlen (str);
8586                 if ((p-buffer) + 10 + slen >= *buflen) {
8587                         char *newbuf;
8588                         *buflen *= 2;
8589                         *buflen += slen;
8590                         newbuf = g_realloc (buffer, *buflen);
8591                         p = newbuf + (p-buffer);
8592                         buffer = newbuf;
8593                 }
8594                 mono_metadata_encode_value (slen, p, &p);
8595                 memcpy (p, str, slen);
8596                 p += slen;
8597                 g_free (str);
8598                 break;
8599         }
8600         case MONO_TYPE_CLASS: {
8601                 char *str;
8602                 guint32 slen;
8603                 MonoClass *k;
8604                 if (!arg) {
8605                         *p++ = 0xFF;
8606                         break;
8607                 }
8608                 k = mono_object_class (arg);
8609                 if (!mono_object_isinst (arg, mono_defaults.monotype_class) &&
8610                         (strcmp (k->name, "TypeBuilder") || strcmp (k->name_space, "System.Reflection.Emit"))) {
8611                         MonoReflectionType* rt = mono_reflection_type_get_underlying_system_type ((MonoReflectionType*) arg);
8612                         MonoClass *rtc;
8613                         
8614                         if (rt && (rtc = mono_object_class (rt)) &&
8615                                    (mono_object_isinst ((MonoObject *) rt, mono_defaults.monotype_class) ||
8616                                     !strcmp (rtc->name, "TypeBuilder") || !strcmp (rtc->name_space, "System.Reflection.Emit"))) {
8617                                 arg = (MonoObject *) rt;
8618                                 k = rtc;
8619                         } else
8620                                 g_error ("Only System.Type allowed, not %s.%s", k->name_space, k->name);
8621                 }
8622 handle_type:
8623                 str = type_get_qualified_name (((MonoReflectionType*)arg)->type, NULL);
8624                 slen = strlen (str);
8625                 if ((p-buffer) + 10 + slen >= *buflen) {
8626                         char *newbuf;
8627                         *buflen *= 2;
8628                         *buflen += slen;
8629                         newbuf = g_realloc (buffer, *buflen);
8630                         p = newbuf + (p-buffer);
8631                         buffer = newbuf;
8632                 }
8633                 mono_metadata_encode_value (slen, p, &p);
8634                 memcpy (p, str, slen);
8635                 p += slen;
8636                 g_free (str);
8637                 break;
8638         }
8639         case MONO_TYPE_SZARRAY: {
8640                 int len, i;
8641                 MonoClass *eclass, *arg_eclass;
8642
8643                 if (!arg) {
8644                         *p++ = 0xff; *p++ = 0xff; *p++ = 0xff; *p++ = 0xff;
8645                         break;
8646                 }
8647                 len = mono_array_length ((MonoArray*)arg);
8648                 *p++ = len & 0xff;
8649                 *p++ = (len >> 8) & 0xff;
8650                 *p++ = (len >> 16) & 0xff;
8651                 *p++ = (len >> 24) & 0xff;
8652                 *retp = p;
8653                 *retbuffer = buffer;
8654                 eclass = type->data.klass;
8655                 arg_eclass = mono_object_class (arg)->element_class;
8656
8657                 if (!eclass) {
8658                         /* Happens when we are called from the MONO_TYPE_OBJECT case below */
8659                         eclass = mono_defaults.object_class;
8660                 }
8661                 if (eclass == mono_defaults.object_class && arg_eclass->valuetype) {
8662                         char *elptr = mono_array_addr ((MonoArray*)arg, char, 0);
8663                         int elsize = mono_class_array_element_size (arg_eclass);
8664                         for (i = 0; i < len; ++i) {
8665                                 encode_cattr_value (assembly, buffer, p, &buffer, &p, buflen, &arg_eclass->byval_arg, NULL, elptr);
8666                                 elptr += elsize;
8667                         }
8668                 } else if (eclass->valuetype && arg_eclass->valuetype) {
8669                         char *elptr = mono_array_addr ((MonoArray*)arg, char, 0);
8670                         int elsize = mono_class_array_element_size (eclass);
8671                         for (i = 0; i < len; ++i) {
8672                                 encode_cattr_value (assembly, buffer, p, &buffer, &p, buflen, &eclass->byval_arg, NULL, elptr);
8673                                 elptr += elsize;
8674                         }
8675                 } else {
8676                         for (i = 0; i < len; ++i) {
8677                                 encode_cattr_value (assembly, buffer, p, &buffer, &p, buflen, &eclass->byval_arg, mono_array_get ((MonoArray*)arg, MonoObject*, i), NULL);
8678                         }
8679                 }
8680                 break;
8681         }
8682         case MONO_TYPE_OBJECT: {
8683                 MonoClass *klass;
8684                 char *str;
8685                 guint32 slen;
8686
8687                 /*
8688                  * The parameter type is 'object' but the type of the actual
8689                  * argument is not. So we have to add type information to the blob
8690                  * too. This is completely undocumented in the spec.
8691                  */
8692
8693                 if (arg == NULL) {
8694                         *p++ = MONO_TYPE_STRING;        // It's same hack as MS uses
8695                         *p++ = 0xFF;
8696                         break;
8697                 }
8698                 
8699                 klass = mono_object_class (arg);
8700
8701                 if (mono_object_isinst (arg, mono_defaults.systemtype_class)) {
8702                         *p++ = 0x50;
8703                         goto handle_type;
8704                 } else if (klass->enumtype) {
8705                         *p++ = 0x55;
8706                 } else if (klass == mono_defaults.string_class) {
8707                         simple_type = MONO_TYPE_STRING;
8708                         *p++ = 0x0E;
8709                         goto handle_enum;
8710                 } else if (klass->rank == 1) {
8711                         *p++ = 0x1D;
8712                         if (klass->element_class->byval_arg.type == MONO_TYPE_OBJECT)
8713                                 /* See Partition II, Appendix B3 */
8714                                 *p++ = 0x51;
8715                         else
8716                                 *p++ = klass->element_class->byval_arg.type;
8717                         encode_cattr_value (assembly, buffer, p, &buffer, &p, buflen, &klass->byval_arg, arg, NULL);
8718                         break;
8719                 } else if (klass->byval_arg.type >= MONO_TYPE_BOOLEAN && klass->byval_arg.type <= MONO_TYPE_R8) {
8720                         *p++ = simple_type = klass->byval_arg.type;
8721                         goto handle_enum;
8722                 } else {
8723                         g_error ("unhandled type in custom attr");
8724                 }
8725                 str = type_get_qualified_name (mono_class_get_type(klass), NULL);
8726                 slen = strlen (str);
8727                 if ((p-buffer) + 10 + slen >= *buflen) {
8728                         char *newbuf;
8729                         *buflen *= 2;
8730                         *buflen += slen;
8731                         newbuf = g_realloc (buffer, *buflen);
8732                         p = newbuf + (p-buffer);
8733                         buffer = newbuf;
8734                 }
8735                 mono_metadata_encode_value (slen, p, &p);
8736                 memcpy (p, str, slen);
8737                 p += slen;
8738                 g_free (str);
8739                 simple_type = mono_class_enum_basetype (klass)->type;
8740                 goto handle_enum;
8741         }
8742         default:
8743                 g_error ("type 0x%02x not yet supported in custom attr encoder", simple_type);
8744         }
8745         *retp = p;
8746         *retbuffer = buffer;
8747 }
8748
8749 static void
8750 encode_field_or_prop_type (MonoType *type, char *p, char **retp)
8751 {
8752         if (type->type == MONO_TYPE_VALUETYPE && type->data.klass->enumtype) {
8753                 char *str = type_get_qualified_name (type, NULL);
8754                 int slen = strlen (str);
8755
8756                 *p++ = 0x55;
8757                 /*
8758                  * This seems to be optional...
8759                  * *p++ = 0x80;
8760                  */
8761                 mono_metadata_encode_value (slen, p, &p);
8762                 memcpy (p, str, slen);
8763                 p += slen;
8764                 g_free (str);
8765         } else if (type->type == MONO_TYPE_OBJECT) {
8766                 *p++ = 0x51;
8767         } else if (type->type == MONO_TYPE_CLASS) {
8768                 /* it should be a type: encode_cattr_value () has the check */
8769                 *p++ = 0x50;
8770         } else {
8771                 mono_metadata_encode_value (type->type, p, &p);
8772                 if (type->type == MONO_TYPE_SZARRAY)
8773                         /* See the examples in Partition VI, Annex B */
8774                         encode_field_or_prop_type (&type->data.klass->byval_arg, p, &p);
8775         }
8776
8777         *retp = p;
8778 }
8779
8780 static void
8781 encode_named_val (MonoReflectionAssembly *assembly, char *buffer, char *p, char **retbuffer, char **retp, guint32 *buflen, MonoType *type, char *name, MonoObject *value)
8782 {
8783         int len;
8784         /* Preallocate a large enough buffer */
8785         if (type->type == MONO_TYPE_VALUETYPE && type->data.klass->enumtype) {
8786                 char *str = type_get_qualified_name (type, NULL);
8787                 len = strlen (str);
8788                 g_free (str);
8789         } else if (type->type == MONO_TYPE_SZARRAY && type->data.klass->enumtype) {
8790                 char *str = type_get_qualified_name (&type->data.klass->byval_arg, NULL);
8791                 len = strlen (str);
8792                 g_free (str);
8793         } else {
8794                 len = 0;
8795         }
8796         len += strlen (name);
8797
8798         if ((p-buffer) + 20 + len >= *buflen) {
8799                 char *newbuf;
8800                 *buflen *= 2;
8801                 *buflen += len;
8802                 newbuf = g_realloc (buffer, *buflen);
8803                 p = newbuf + (p-buffer);
8804                 buffer = newbuf;
8805         }
8806
8807         encode_field_or_prop_type (type, p, &p);
8808
8809         len = strlen (name);
8810         mono_metadata_encode_value (len, p, &p);
8811         memcpy (p, name, len);
8812         p += len;
8813         encode_cattr_value (assembly->assembly, buffer, p, &buffer, &p, buflen, type, value, NULL);
8814         *retp = p;
8815         *retbuffer = buffer;
8816 }
8817
8818 #ifndef DISABLE_REFLECTION_EMIT
8819
8820 /*
8821  * mono_reflection_get_custom_attrs_blob:
8822  * @ctor: custom attribute constructor
8823  * @ctorArgs: arguments o the constructor
8824  * @properties:
8825  * @propValues:
8826  * @fields:
8827  * @fieldValues:
8828  * 
8829  * Creates the blob of data that needs to be saved in the metadata and that represents
8830  * the custom attributed described by @ctor, @ctorArgs etc.
8831  * Returns: a Byte array representing the blob of data.
8832  */
8833 MonoArray*
8834 mono_reflection_get_custom_attrs_blob (MonoReflectionAssembly *assembly, MonoObject *ctor, MonoArray *ctorArgs, MonoArray *properties, MonoArray *propValues, MonoArray *fields, MonoArray* fieldValues) 
8835 {
8836         MonoArray *result;
8837         MonoMethodSignature *sig;
8838         MonoObject *arg;
8839         char *buffer, *p;
8840         guint32 buflen, i;
8841
8842         MONO_ARCH_SAVE_REGS;
8843
8844         if (strcmp (ctor->vtable->klass->name, "MonoCMethod")) {
8845                 /* sig is freed later so allocate it in the heap */
8846                 sig = ctor_builder_to_signature (NULL, (MonoReflectionCtorBuilder*)ctor);
8847         } else {
8848                 sig = mono_method_signature (((MonoReflectionMethod*)ctor)->method);
8849         }
8850
8851         g_assert (mono_array_length (ctorArgs) == sig->param_count);
8852         buflen = 256;
8853         p = buffer = g_malloc (buflen);
8854         /* write the prolog */
8855         *p++ = 1;
8856         *p++ = 0;
8857         for (i = 0; i < sig->param_count; ++i) {
8858                 arg = mono_array_get (ctorArgs, MonoObject*, i);
8859                 encode_cattr_value (assembly->assembly, buffer, p, &buffer, &p, &buflen, sig->params [i], arg, NULL);
8860         }
8861         i = 0;
8862         if (properties)
8863                 i += mono_array_length (properties);
8864         if (fields)
8865                 i += mono_array_length (fields);
8866         *p++ = i & 0xff;
8867         *p++ = (i >> 8) & 0xff;
8868         if (properties) {
8869                 MonoObject *prop;
8870                 for (i = 0; i < mono_array_length (properties); ++i) {
8871                         MonoType *ptype;
8872                         char *pname;
8873
8874                         prop = mono_array_get (properties, gpointer, i);
8875                         get_prop_name_and_type (prop, &pname, &ptype);
8876                         *p++ = 0x54; /* PROPERTY signature */
8877                         encode_named_val (assembly, buffer, p, &buffer, &p, &buflen, ptype, pname, (MonoObject*)mono_array_get (propValues, gpointer, i));
8878                         g_free (pname);
8879                 }
8880         }
8881
8882         if (fields) {
8883                 MonoObject *field;
8884                 for (i = 0; i < mono_array_length (fields); ++i) {
8885                         MonoType *ftype;
8886                         char *fname;
8887
8888                         field = mono_array_get (fields, gpointer, i);
8889                         get_field_name_and_type (field, &fname, &ftype);
8890                         *p++ = 0x53; /* FIELD signature */
8891                         encode_named_val (assembly, buffer, p, &buffer, &p, &buflen, ftype, fname, (MonoObject*)mono_array_get (fieldValues, gpointer, i));
8892                         g_free (fname);
8893                 }
8894         }
8895
8896         g_assert (p - buffer <= buflen);
8897         buflen = p - buffer;
8898         result = mono_array_new (mono_domain_get (), mono_defaults.byte_class, buflen);
8899         p = mono_array_addr (result, char, 0);
8900         memcpy (p, buffer, buflen);
8901         g_free (buffer);
8902         if (strcmp (ctor->vtable->klass->name, "MonoCMethod"))
8903                 g_free (sig);
8904         return result;
8905 }
8906
8907 /*
8908  * mono_reflection_setup_internal_class:
8909  * @tb: a TypeBuilder object
8910  *
8911  * Creates a MonoClass that represents the TypeBuilder.
8912  * This is a trick that lets us simplify a lot of reflection code
8913  * (and will allow us to support Build and Run assemblies easier).
8914  */
8915 void
8916 mono_reflection_setup_internal_class (MonoReflectionTypeBuilder *tb)
8917 {
8918         MonoClass *klass, *parent;
8919
8920         MONO_ARCH_SAVE_REGS;
8921
8922         mono_loader_lock ();
8923
8924         if (tb->parent) {
8925                 /* check so we can compile corlib correctly */
8926                 if (strcmp (mono_object_class (tb->parent)->name, "TypeBuilder") == 0) {
8927                         /* mono_class_setup_mono_type () guaranteess type->data.klass is valid */
8928                         parent = tb->parent->type->data.klass;
8929                 } else {
8930                         parent = my_mono_class_from_mono_type (tb->parent->type);
8931                 }
8932         } else {
8933                 parent = NULL;
8934         }
8935         
8936         /* the type has already being created: it means we just have to change the parent */
8937         if (tb->type.type) {
8938                 klass = mono_class_from_mono_type (tb->type.type);
8939                 klass->parent = NULL;
8940                 /* fool mono_class_setup_parent */
8941                 klass->supertypes = NULL;
8942                 mono_class_setup_parent (klass, parent);
8943                 mono_class_setup_mono_type (klass);
8944                 mono_loader_unlock ();
8945                 return;
8946         }
8947
8948         klass = mono_image_alloc0 (&tb->module->dynamic_image->image, sizeof (MonoClass));
8949
8950         klass->image = &tb->module->dynamic_image->image;
8951
8952         klass->inited = 1; /* we lie to the runtime */
8953         klass->name = mono_string_to_utf8_image (klass->image, tb->name);
8954         klass->name_space = mono_string_to_utf8_image (klass->image, tb->nspace);
8955         klass->type_token = MONO_TOKEN_TYPE_DEF | tb->table_idx;
8956         klass->flags = tb->attrs;
8957         
8958         mono_profiler_class_event (klass, MONO_PROFILE_START_LOAD);
8959
8960         klass->element_class = klass;
8961
8962         MOVING_GC_REGISTER (&klass->reflection_info);
8963         klass->reflection_info = tb;
8964
8965         /* Put into cache so mono_class_get () will find it */
8966         mono_image_add_to_name_cache (klass->image, klass->name_space, klass->name, tb->table_idx);
8967
8968         mono_g_hash_table_insert (tb->module->dynamic_image->tokens,
8969                 GUINT_TO_POINTER (MONO_TOKEN_TYPE_DEF | tb->table_idx), tb);
8970
8971         if (parent != NULL) {
8972                 mono_class_setup_parent (klass, parent);
8973         } else if (strcmp (klass->name, "Object") == 0 && strcmp (klass->name_space, "System") == 0) {
8974                 const char *old_n = klass->name;
8975                 /* trick to get relative numbering right when compiling corlib */
8976                 klass->name = "BuildingObject";
8977                 mono_class_setup_parent (klass, mono_defaults.object_class);
8978                 klass->name = old_n;
8979         }
8980
8981         if ((!strcmp (klass->name, "ValueType") && !strcmp (klass->name_space, "System")) ||
8982                         (!strcmp (klass->name, "Object") && !strcmp (klass->name_space, "System")) ||
8983                         (!strcmp (klass->name, "Enum") && !strcmp (klass->name_space, "System"))) {
8984                 klass->instance_size = sizeof (MonoObject);
8985                 klass->size_inited = 1;
8986                 mono_class_setup_vtable_general (klass, NULL, 0);
8987         }
8988
8989         mono_class_setup_mono_type (klass);
8990
8991         mono_class_setup_supertypes (klass);
8992
8993         /*
8994          * FIXME: handle interfaces.
8995          */
8996
8997         tb->type.type = &klass->byval_arg;
8998
8999         if (tb->nesting_type) {
9000                 g_assert (tb->nesting_type->type);
9001                 klass->nested_in = mono_class_from_mono_type (tb->nesting_type->type);
9002         }
9003
9004         /*g_print ("setup %s as %s (%p)\n", klass->name, ((MonoObject*)tb)->vtable->klass->name, tb);*/
9005
9006         mono_profiler_class_loaded (klass, MONO_PROFILE_OK);
9007         
9008         mono_loader_unlock ();
9009 }
9010
9011 /*
9012  * mono_reflection_setup_generic_class:
9013  * @tb: a TypeBuilder object
9014  *
9015  * Setup the generic class before adding the first generic parameter.
9016  */
9017 void
9018 mono_reflection_setup_generic_class (MonoReflectionTypeBuilder *tb)
9019 {
9020 }
9021
9022 /*
9023  * mono_reflection_create_generic_class:
9024  * @tb: a TypeBuilder object
9025  *
9026  * Creates the generic class after all generic parameters have been added.
9027  */
9028 void
9029 mono_reflection_create_generic_class (MonoReflectionTypeBuilder *tb)
9030 {
9031         MonoClass *klass;
9032         int count, i;
9033
9034         MONO_ARCH_SAVE_REGS;
9035
9036         klass = my_mono_class_from_mono_type (tb->type.type);
9037
9038         count = tb->generic_params ? mono_array_length (tb->generic_params) : 0;
9039
9040         if (klass->generic_container || (count == 0))
9041                 return;
9042
9043         g_assert (tb->generic_container && (tb->generic_container->owner.klass == klass));
9044
9045         klass->generic_container = mono_image_alloc0 (klass->image, sizeof (MonoGenericContainer));
9046
9047         klass->generic_container->owner.klass = klass;
9048         klass->generic_container->type_argc = count;
9049         klass->generic_container->type_params = mono_image_alloc0 (klass->image, sizeof (MonoGenericParam) * count);
9050
9051         klass->is_generic = 1;
9052
9053         for (i = 0; i < count; i++) {
9054                 MonoReflectionGenericParam *gparam = mono_array_get (tb->generic_params, gpointer, i);
9055                 klass->generic_container->type_params [i] = *gparam->type.type->data.generic_param;
9056                 /*Make sure we are a diferent type instance */
9057                 klass->generic_container->type_params [i].owner = klass->generic_container;
9058                 klass->generic_container->type_params [i].pklass = NULL;
9059
9060                 g_assert (klass->generic_container->type_params [i].owner);
9061         }
9062
9063         klass->generic_container->context.class_inst = mono_get_shared_generic_inst (klass->generic_container);
9064 }
9065
9066 /*
9067  * mono_reflection_create_internal_class:
9068  * @tb: a TypeBuilder object
9069  *
9070  * Actually create the MonoClass that is associated with the TypeBuilder.
9071  */
9072 void
9073 mono_reflection_create_internal_class (MonoReflectionTypeBuilder *tb)
9074 {
9075         MonoClass *klass;
9076
9077         MONO_ARCH_SAVE_REGS;
9078
9079         klass = my_mono_class_from_mono_type (tb->type.type);
9080
9081         mono_loader_lock ();
9082         if (klass->enumtype && mono_class_enum_basetype (klass) == NULL) {
9083                 MonoReflectionFieldBuilder *fb;
9084                 MonoClass *ec;
9085                 MonoType *enum_basetype;
9086
9087                 g_assert (tb->fields != NULL);
9088                 g_assert (mono_array_length (tb->fields) >= 1);
9089
9090                 fb = mono_array_get (tb->fields, MonoReflectionFieldBuilder*, 0);
9091
9092                 if (!mono_type_is_valid_enum_basetype (fb->type->type)) {
9093                         mono_loader_unlock ();
9094                         return;
9095                 }
9096
9097                 enum_basetype = fb->type->type;
9098                 klass->element_class = my_mono_class_from_mono_type (enum_basetype);
9099                 if (!klass->element_class)
9100                         klass->element_class = mono_class_from_mono_type (enum_basetype);
9101
9102                 /*
9103                  * get the element_class from the current corlib.
9104                  */
9105                 ec = default_class_from_mono_type (enum_basetype);
9106                 klass->instance_size = ec->instance_size;
9107                 klass->size_inited = 1;
9108                 /* 
9109                  * this is almost safe to do with enums and it's needed to be able
9110                  * to create objects of the enum type (for use in SetConstant).
9111                  */
9112                 /* FIXME: Does this mean enums can't have method overrides ? */
9113                 mono_class_setup_vtable_general (klass, NULL, 0);
9114         }
9115         mono_loader_unlock ();
9116 }
9117
9118 #endif /* DISABLE_REFLECTION_EMIT */
9119
9120 static MonoMarshalSpec*
9121 mono_marshal_spec_from_builder (MonoImage *image, MonoAssembly *assembly,
9122                                                                 MonoReflectionMarshal *minfo)
9123 {
9124         MonoMarshalSpec *res;
9125
9126         res = image_g_new0 (image, MonoMarshalSpec, 1);
9127         res->native = minfo->type;
9128
9129         switch (minfo->type) {
9130         case MONO_NATIVE_LPARRAY:
9131                 res->data.array_data.elem_type = minfo->eltype;
9132                 if (minfo->has_size) {
9133                         res->data.array_data.param_num = minfo->param_num;
9134                         res->data.array_data.num_elem = minfo->count;
9135                         res->data.array_data.elem_mult = minfo->param_num == -1 ? 0 : 1;
9136                 }
9137                 else {
9138                         res->data.array_data.param_num = -1;
9139                         res->data.array_data.num_elem = -1;
9140                         res->data.array_data.elem_mult = -1;
9141                 }
9142                 break;
9143
9144         case MONO_NATIVE_BYVALTSTR:
9145         case MONO_NATIVE_BYVALARRAY:
9146                 res->data.array_data.num_elem = minfo->count;
9147                 break;
9148
9149         case MONO_NATIVE_CUSTOM:
9150                 if (minfo->marshaltyperef)
9151                         res->data.custom_data.custom_name =
9152                                 type_get_fully_qualified_name (minfo->marshaltyperef->type);
9153                 if (minfo->mcookie)
9154                         res->data.custom_data.cookie = mono_string_to_utf8 (minfo->mcookie);
9155                 break;
9156
9157         default:
9158                 break;
9159         }
9160
9161         return res;
9162 }
9163
9164 MonoReflectionMarshal*
9165 mono_reflection_marshal_from_marshal_spec (MonoDomain *domain, MonoClass *klass,
9166                                                                                    MonoMarshalSpec *spec)
9167 {
9168         static MonoClass *System_Reflection_Emit_UnmanagedMarshalClass;
9169         MonoReflectionMarshal *minfo;
9170         MonoType *mtype;
9171
9172         if (!System_Reflection_Emit_UnmanagedMarshalClass) {
9173                 System_Reflection_Emit_UnmanagedMarshalClass = mono_class_from_name (
9174                    mono_defaults.corlib, "System.Reflection.Emit", "UnmanagedMarshal");
9175                 g_assert (System_Reflection_Emit_UnmanagedMarshalClass);
9176         }
9177
9178         minfo = (MonoReflectionMarshal*)mono_object_new (domain, System_Reflection_Emit_UnmanagedMarshalClass);
9179         minfo->type = spec->native;
9180
9181         switch (minfo->type) {
9182         case MONO_NATIVE_LPARRAY:
9183                 minfo->eltype = spec->data.array_data.elem_type;
9184                 minfo->count = spec->data.array_data.num_elem;
9185                 minfo->param_num = spec->data.array_data.param_num;
9186                 break;
9187
9188         case MONO_NATIVE_BYVALTSTR:
9189         case MONO_NATIVE_BYVALARRAY:
9190                 minfo->count = spec->data.array_data.num_elem;
9191                 break;
9192
9193         case MONO_NATIVE_CUSTOM:
9194                 if (spec->data.custom_data.custom_name) {
9195                         mtype = mono_reflection_type_from_name (spec->data.custom_data.custom_name, klass->image);
9196                         if (mtype)
9197                                 MONO_OBJECT_SETREF (minfo, marshaltyperef, mono_type_get_object (domain, mtype));
9198
9199                         MONO_OBJECT_SETREF (minfo, marshaltype, mono_string_new (domain, spec->data.custom_data.custom_name));
9200                 }
9201                 if (spec->data.custom_data.cookie)
9202                         MONO_OBJECT_SETREF (minfo, mcookie, mono_string_new (domain, spec->data.custom_data.cookie));
9203                 break;
9204
9205         default:
9206                 break;
9207         }
9208
9209         return minfo;
9210 }
9211
9212 static MonoMethod*
9213 reflection_methodbuilder_to_mono_method (MonoClass *klass,
9214                                          ReflectionMethodBuilder *rmb,
9215                                          MonoMethodSignature *sig)
9216 {
9217         MonoMethod *m;
9218         MonoMethodNormal *pm;
9219         MonoMarshalSpec **specs;
9220         MonoReflectionMethodAux *method_aux;
9221         MonoImage *image;
9222         gboolean dynamic;
9223         int i;
9224
9225         /*
9226          * Methods created using a MethodBuilder should have their memory allocated
9227          * inside the image mempool, while dynamic methods should have their memory
9228          * malloc'd.
9229          */
9230         dynamic = rmb->refs != NULL;
9231         image = dynamic ? NULL : klass->image;
9232
9233         if (!dynamic)
9234                 g_assert (!klass->generic_class);
9235
9236         mono_loader_lock ();
9237
9238         if ((rmb->attrs & METHOD_ATTRIBUTE_PINVOKE_IMPL) ||
9239                         (rmb->iattrs & METHOD_IMPL_ATTRIBUTE_INTERNAL_CALL))
9240                 m = (MonoMethod *)image_g_new0 (image, MonoMethodPInvoke, 1);
9241         else if (rmb->refs)
9242                 m = (MonoMethod *)image_g_new0 (image, MonoMethodWrapper, 1);
9243         else
9244                 m = (MonoMethod *)image_g_new0 (image, MonoMethodNormal, 1);
9245
9246         pm = (MonoMethodNormal*)m;
9247
9248         m->dynamic = dynamic;
9249         m->slot = -1;
9250         m->flags = rmb->attrs;
9251         m->iflags = rmb->iattrs;
9252         m->name = mono_string_to_utf8_image (image, rmb->name);
9253         m->klass = klass;
9254         m->signature = sig;
9255         m->skip_visibility = rmb->skip_visibility;
9256         if (rmb->table_idx)
9257                 m->token = MONO_TOKEN_METHOD_DEF | (*rmb->table_idx);
9258
9259         if (m->iflags & METHOD_IMPL_ATTRIBUTE_INTERNAL_CALL) {
9260                 if (klass == mono_defaults.string_class && !strcmp (m->name, ".ctor"))
9261                         m->string_ctor = 1;
9262
9263                 m->signature->pinvoke = 1;
9264         } else if (m->flags & METHOD_ATTRIBUTE_PINVOKE_IMPL) {
9265                 m->signature->pinvoke = 1;
9266
9267                 method_aux = image_g_new0 (image, MonoReflectionMethodAux, 1);
9268
9269                 method_aux->dllentry = rmb->dllentry ? mono_string_to_utf8_image (image, rmb->dllentry) : image_strdup (image, m->name);
9270                 method_aux->dll = mono_string_to_utf8_image (image, rmb->dll);
9271                 
9272                 ((MonoMethodPInvoke*)m)->piflags = (rmb->native_cc << 8) | (rmb->charset ? (rmb->charset - 1) * 2 : 0) | rmb->extra_flags;
9273
9274                 if (klass->image->dynamic)
9275                         g_hash_table_insert (((MonoDynamicImage*)klass->image)->method_aux_hash, m, method_aux);
9276
9277                 mono_loader_unlock ();
9278
9279                 return m;
9280         } else if (!(m->flags & METHOD_ATTRIBUTE_ABSTRACT) &&
9281                            !(m->iflags & METHOD_IMPL_ATTRIBUTE_RUNTIME)) {
9282                 MonoMethodHeader *header;
9283                 guint32 code_size;
9284                 gint32 max_stack, i;
9285                 gint32 num_locals = 0;
9286                 gint32 num_clauses = 0;
9287                 guint8 *code;
9288
9289                 if (rmb->ilgen) {
9290                         code = mono_array_addr (rmb->ilgen->code, guint8, 0);
9291                         code_size = rmb->ilgen->code_len;
9292                         max_stack = rmb->ilgen->max_stack;
9293                         num_locals = rmb->ilgen->locals ? mono_array_length (rmb->ilgen->locals) : 0;
9294                         if (rmb->ilgen->ex_handlers)
9295                                 num_clauses = method_count_clauses (rmb->ilgen);
9296                 } else {
9297                         if (rmb->code) {
9298                                 code = mono_array_addr (rmb->code, guint8, 0);
9299                                 code_size = mono_array_length (rmb->code);
9300                                 /* we probably need to run a verifier on the code... */
9301                                 max_stack = 8; 
9302                         }
9303                         else {
9304                                 code = NULL;
9305                                 code_size = 0;
9306                                 max_stack = 8;
9307                         }
9308                 }
9309
9310                 header = image_g_malloc0 (image, sizeof (MonoMethodHeader) + 
9311                         (num_locals - MONO_ZERO_LEN_ARRAY) * sizeof (MonoType*));
9312                 header->code_size = code_size;
9313                 header->code = image_g_malloc (image, code_size);
9314                 memcpy ((char*)header->code, code, code_size);
9315                 header->max_stack = max_stack;
9316                 header->init_locals = rmb->init_locals;
9317                 header->num_locals = num_locals;
9318
9319                 for (i = 0; i < num_locals; ++i) {
9320                         MonoReflectionLocalBuilder *lb = 
9321                                 mono_array_get (rmb->ilgen->locals, MonoReflectionLocalBuilder*, i);
9322
9323                         header->locals [i] = image_g_new0 (image, MonoType, 1);
9324                         memcpy (header->locals [i], lb->type->type, sizeof (MonoType));
9325                 }
9326
9327                 header->num_clauses = num_clauses;
9328                 if (num_clauses) {
9329                         header->clauses = method_encode_clauses (image, (MonoDynamicImage*)klass->image,
9330                                  rmb->ilgen, num_clauses);
9331                 }
9332
9333                 pm->header = header;
9334         }
9335
9336         if (rmb->generic_params) {
9337                 int count = mono_array_length (rmb->generic_params);
9338                 MonoGenericContainer *container;
9339
9340                 container = rmb->generic_container;
9341                 if (container) {
9342                         m->is_generic = TRUE;
9343                         mono_method_set_generic_container (m, container);
9344                 }
9345                 container->type_argc = count;
9346                 container->type_params = image_g_new0 (image, MonoGenericParam, count);
9347                 container->owner.method = m;
9348
9349                 for (i = 0; i < count; i++) {
9350                         MonoReflectionGenericParam *gp =
9351                                 mono_array_get (rmb->generic_params, MonoReflectionGenericParam*, i);
9352
9353                         container->type_params [i] = *gp->type.type->data.generic_param;
9354                 }
9355
9356                 if (klass->generic_container) {
9357                         container->parent = klass->generic_container;
9358                         container->context.class_inst = klass->generic_container->context.class_inst;
9359                 }
9360                 container->context.method_inst = mono_get_shared_generic_inst (container);
9361         }
9362
9363         if (rmb->refs) {
9364                 MonoMethodWrapper *mw = (MonoMethodWrapper*)m;
9365                 int i;
9366                 void **data;
9367
9368                 m->wrapper_type = MONO_WRAPPER_DYNAMIC_METHOD;
9369
9370                 mw->method_data = data = image_g_new (image, gpointer, rmb->nrefs + 1);
9371                 data [0] = GUINT_TO_POINTER (rmb->nrefs);
9372                 for (i = 0; i < rmb->nrefs; ++i)
9373                         data [i + 1] = rmb->refs [i];
9374         }
9375
9376         method_aux = NULL;
9377
9378         /* Parameter info */
9379         if (rmb->pinfo) {
9380                 if (!method_aux)
9381                         method_aux = image_g_new0 (image, MonoReflectionMethodAux, 1);
9382                 method_aux->param_names = image_g_new0 (image, char *, mono_method_signature (m)->param_count + 1);
9383                 for (i = 0; i <= m->signature->param_count; ++i) {
9384                         MonoReflectionParamBuilder *pb;
9385                         if ((pb = mono_array_get (rmb->pinfo, MonoReflectionParamBuilder*, i))) {
9386                                 if ((i > 0) && (pb->attrs)) {
9387                                         /* Make a copy since it might point to a shared type structure */
9388                                         m->signature->params [i - 1] = mono_metadata_type_dup (klass->image, m->signature->params [i - 1]);
9389                                         m->signature->params [i - 1]->attrs = pb->attrs;
9390                                 }
9391
9392                                 if (pb->attrs & PARAM_ATTRIBUTE_HAS_DEFAULT) {
9393                                         MonoDynamicImage *assembly;
9394                                         guint32 idx, def_type, len;
9395                                         char *p;
9396                                         const char *p2;
9397
9398                                         if (!method_aux->param_defaults) {
9399                                                 method_aux->param_defaults = image_g_new0 (image, guint8*, m->signature->param_count + 1);
9400                                                 method_aux->param_default_types = image_g_new0 (image, guint32, m->signature->param_count + 1);
9401                                         }
9402                                         assembly = (MonoDynamicImage*)klass->image;
9403                                         idx = encode_constant (assembly, pb->def_value, &def_type);
9404                                         /* Copy the data from the blob since it might get realloc-ed */
9405                                         p = assembly->blob.data + idx;
9406                                         len = mono_metadata_decode_blob_size (p, &p2);
9407                                         len += p2 - p;
9408                                         method_aux->param_defaults [i] = image_g_malloc (image, len);
9409                                         method_aux->param_default_types [i] = def_type;
9410                                         memcpy ((gpointer)method_aux->param_defaults [i], p, len);
9411                                 }
9412
9413                                 if (pb->name)
9414                                         method_aux->param_names [i] = mono_string_to_utf8_image (image, pb->name);
9415                                 if (pb->cattrs) {
9416                                         if (!method_aux->param_cattr)
9417                                                 method_aux->param_cattr = image_g_new0 (image, MonoCustomAttrInfo*, m->signature->param_count + 1);
9418                                         method_aux->param_cattr [i] = mono_custom_attrs_from_builders (image, klass->image, pb->cattrs);
9419                                 }
9420                         }
9421                 }
9422         }
9423
9424         /* Parameter marshalling */
9425         specs = NULL;
9426         if (rmb->pinfo)         
9427                 for (i = 0; i < mono_array_length (rmb->pinfo); ++i) {
9428                         MonoReflectionParamBuilder *pb;
9429                         if ((pb = mono_array_get (rmb->pinfo, MonoReflectionParamBuilder*, i))) {
9430                                 if (pb->marshal_info) {
9431                                         if (specs == NULL)
9432                                                 specs = image_g_new0 (image, MonoMarshalSpec*, sig->param_count + 1);
9433                                         specs [pb->position] = 
9434                                                 mono_marshal_spec_from_builder (image, klass->image->assembly, pb->marshal_info);
9435                                 }
9436                         }
9437                 }
9438         if (specs != NULL) {
9439                 if (!method_aux)
9440                         method_aux = image_g_new0 (image, MonoReflectionMethodAux, 1);
9441                 method_aux->param_marshall = specs;
9442         }
9443
9444         if (klass->image->dynamic && method_aux)
9445                 g_hash_table_insert (((MonoDynamicImage*)klass->image)->method_aux_hash, m, method_aux);
9446
9447         mono_loader_unlock ();
9448
9449         return m;
9450 }       
9451
9452 static MonoMethod*
9453 ctorbuilder_to_mono_method (MonoClass *klass, MonoReflectionCtorBuilder* mb)
9454 {
9455         ReflectionMethodBuilder rmb;
9456         MonoMethodSignature *sig;
9457
9458         mono_loader_lock ();
9459         sig = ctor_builder_to_signature (klass->image, mb);
9460         mono_loader_unlock ();
9461
9462         reflection_methodbuilder_from_ctor_builder (&rmb, mb);
9463
9464         mb->mhandle = reflection_methodbuilder_to_mono_method (klass, &rmb, sig);
9465         mono_save_custom_attrs (klass->image, mb->mhandle, mb->cattrs);
9466
9467         /* If we are in a generic class, we might be called multiple times from inflate_method */
9468         if (!((MonoDynamicImage*)(MonoDynamicImage*)klass->image)->save && !klass->generic_container) {
9469                 /* ilgen is no longer needed */
9470                 mb->ilgen = NULL;
9471         }
9472
9473         return mb->mhandle;
9474 }
9475
9476 static MonoMethod*
9477 methodbuilder_to_mono_method (MonoClass *klass, MonoReflectionMethodBuilder* mb)
9478 {
9479         ReflectionMethodBuilder rmb;
9480         MonoMethodSignature *sig;
9481
9482         mono_loader_lock ();
9483         sig = method_builder_to_signature (klass->image, mb);
9484         mono_loader_unlock ();
9485
9486         reflection_methodbuilder_from_method_builder (&rmb, mb);
9487
9488         mb->mhandle = reflection_methodbuilder_to_mono_method (klass, &rmb, sig);
9489         mono_save_custom_attrs (klass->image, mb->mhandle, mb->cattrs);
9490
9491         /* If we are in a generic class, we might be called multiple times from inflate_method */
9492         if (!((MonoDynamicImage*)(MonoDynamicImage*)klass->image)->save && !klass->generic_container) {
9493                 /* ilgen is no longer needed */
9494                 mb->ilgen = NULL;
9495         }
9496         return mb->mhandle;
9497 }
9498
9499 static MonoClassField*
9500 fieldbuilder_to_mono_class_field (MonoClass *klass, MonoReflectionFieldBuilder* fb)
9501 {
9502         MonoClassField *field;
9503         MonoType *custom;
9504
9505         field = g_new0 (MonoClassField, 1);
9506
9507         field->name = mono_string_to_utf8 (fb->name);
9508         if (fb->attrs || fb->modreq || fb->modopt) {
9509                 field->type = mono_metadata_type_dup (NULL, fb->type->type);
9510                 field->type->attrs = fb->attrs;
9511
9512                 g_assert (klass->image->dynamic);
9513                 custom = add_custom_modifiers ((MonoDynamicImage*)klass->image, field->type, fb->modreq, fb->modopt);
9514                 g_free (field->type);
9515                 field->type = custom;
9516         } else {
9517                 field->type = fb->type->type;
9518         }
9519         if (fb->offset != -1)
9520                 field->offset = fb->offset;
9521         field->parent = klass;
9522         mono_save_custom_attrs (klass->image, field, fb->cattrs);
9523
9524         // FIXME: Can't store fb->def_value/RVA, is it needed for field_on_insts ?
9525
9526         return field;
9527 }
9528
9529 MonoType*
9530 mono_reflection_bind_generic_parameters (MonoReflectionType *type, int type_argc, MonoType **types)
9531 {
9532         MonoClass *klass;
9533         MonoReflectionTypeBuilder *tb = NULL;
9534         gboolean is_dynamic = FALSE;
9535         MonoDomain *domain;
9536         MonoClass *geninst;
9537
9538         mono_loader_lock ();
9539
9540         domain = mono_object_domain (type);
9541
9542         if (!strcmp (((MonoObject *) type)->vtable->klass->name, "TypeBuilder")) {
9543                 tb = (MonoReflectionTypeBuilder *) type;
9544
9545                 is_dynamic = TRUE;
9546         } else if (!strcmp (((MonoObject *) type)->vtable->klass->name, "MonoGenericClass")) {
9547                 MonoReflectionGenericClass *rgi = (MonoReflectionGenericClass *) type;
9548
9549                 tb = rgi->generic_type;
9550                 is_dynamic = TRUE;
9551         }
9552
9553         /* FIXME: fix the CreateGenericParameters protocol to avoid the two stage setup of TypeBuilders */
9554         if (tb && tb->generic_container)
9555                 mono_reflection_create_generic_class (tb);
9556
9557         klass = mono_class_from_mono_type (type->type);
9558         if (!klass->generic_container) {
9559                 mono_loader_unlock ();
9560                 return NULL;
9561         }
9562
9563         if (klass->wastypebuilder) {
9564                 tb = (MonoReflectionTypeBuilder *) klass->reflection_info;
9565
9566                 is_dynamic = TRUE;
9567         }
9568
9569         mono_loader_unlock ();
9570
9571         geninst = mono_class_bind_generic_parameters (klass, type_argc, types, is_dynamic);
9572
9573         return &geninst->byval_arg;
9574 }
9575
9576 MonoClass*
9577 mono_class_bind_generic_parameters (MonoClass *klass, int type_argc, MonoType **types, gboolean is_dynamic)
9578 {
9579         MonoGenericClass *gclass;
9580         MonoGenericInst *inst;
9581
9582         g_assert (klass->generic_container);
9583
9584         inst = mono_metadata_get_generic_inst (type_argc, types);
9585         gclass = mono_metadata_lookup_generic_class (klass, inst, is_dynamic);
9586
9587         return mono_generic_class_get_class (gclass);
9588 }
9589
9590 MonoReflectionMethod*
9591 mono_reflection_bind_generic_method_parameters (MonoReflectionMethod *rmethod, MonoArray *types)
9592 {
9593         MonoClass *klass;
9594         MonoMethod *method, *inflated;
9595         MonoMethodInflated *imethod;
9596         MonoReflectionMethodBuilder *mb = NULL;
9597         MonoGenericContext tmp_context;
9598         MonoGenericInst *ginst;
9599         MonoType **type_argv;
9600         int count, i;
9601
9602         MONO_ARCH_SAVE_REGS;
9603
9604         if (!strcmp (rmethod->object.vtable->klass->name, "MethodBuilder")) {
9605 #ifndef DISABLE_REFLECTION_EMIT
9606                 MonoReflectionTypeBuilder *tb;
9607                 MonoClass *klass;
9608
9609                 mb = (MonoReflectionMethodBuilder *) rmethod;
9610                 tb = (MonoReflectionTypeBuilder *) mb->type;
9611                 klass = mono_class_from_mono_type (tb->type.type);
9612
9613                 method = methodbuilder_to_mono_method (klass, mb);
9614 #else
9615                 g_assert_not_reached ();
9616                 method = NULL;
9617 #endif
9618         } else {
9619                 method = rmethod->method;
9620         }
9621
9622         klass = method->klass;
9623
9624         if (method->is_inflated)
9625                 method = ((MonoMethodInflated *) method)->declaring;
9626
9627         count = mono_method_signature (method)->generic_param_count;
9628         if (count != mono_array_length (types))
9629                 return NULL;
9630
9631         type_argv = g_new0 (MonoType *, count);
9632         for (i = 0; i < count; i++) {
9633                 MonoReflectionType *garg = mono_array_get (types, gpointer, i);
9634                 type_argv [i] = garg->type;
9635         }
9636         ginst = mono_metadata_get_generic_inst (count, type_argv);
9637         g_free (type_argv);
9638
9639         tmp_context.class_inst = klass->generic_class ? klass->generic_class->context.class_inst : NULL;
9640         tmp_context.method_inst = ginst;
9641
9642         inflated = mono_class_inflate_generic_method (method, &tmp_context);
9643         imethod = (MonoMethodInflated *) inflated;
9644
9645         if (method->klass->image->dynamic) {
9646                 MonoDynamicImage *image = (MonoDynamicImage*)method->klass->image;
9647                 /*
9648                  * This table maps metadata structures representing inflated methods/fields
9649                  * to the reflection objects representing their generic definitions.
9650                  */
9651                 mono_loader_lock ();
9652                 mono_g_hash_table_insert (image->generic_def_objects, imethod, rmethod);
9653                 mono_loader_unlock ();
9654         }
9655         
9656         return mono_method_get_object (mono_object_domain (rmethod), inflated, NULL);
9657 }
9658
9659 #ifndef DISABLE_REFLECTION_EMIT
9660
9661 static MonoMethod *
9662 inflate_mono_method (MonoClass *klass, MonoMethod *method, MonoObject *obj)
9663 {
9664         MonoMethodInflated *imethod;
9665         MonoGenericContext *context;
9666         int i;
9667
9668         /*
9669          * With generic code sharing the klass might not be inflated.
9670          * This can happen because classes inflated with their own
9671          * type arguments are "normalized" to the uninflated class.
9672          */
9673         if (!klass->generic_class)
9674                 return method;
9675
9676         context = mono_class_get_context (klass);
9677
9678         if (klass->method.count) {
9679                 /* Find the already created inflated method */
9680                 for (i = 0; i < klass->method.count; ++i) {
9681                         g_assert (klass->methods [i]->is_inflated);
9682                         if (((MonoMethodInflated*)klass->methods [i])->declaring == method)
9683                                 break;
9684                 }
9685                 g_assert (i < klass->method.count);
9686                 imethod = (MonoMethodInflated*)klass->methods [i];
9687         } else {
9688                 imethod = (MonoMethodInflated *) mono_class_inflate_generic_method_full (method, klass, context);
9689         }
9690
9691         if (method->is_generic && method->klass->image->dynamic) {
9692                 MonoDynamicImage *image = (MonoDynamicImage*)method->klass->image;
9693
9694                 mono_loader_lock ();
9695                 mono_g_hash_table_insert (image->generic_def_objects, imethod, obj);
9696                 mono_loader_unlock ();
9697         }
9698         return (MonoMethod *) imethod;
9699 }
9700
9701 static MonoMethod *
9702 inflate_method (MonoReflectionGenericClass *type, MonoObject *obj)
9703 {
9704         MonoMethod *method;
9705         MonoClass *gklass;
9706
9707         gklass = mono_class_from_mono_type (type->generic_type->type.type);
9708
9709         if (!strcmp (obj->vtable->klass->name, "MethodBuilder"))
9710                 if (((MonoReflectionMethodBuilder*)obj)->mhandle)
9711                         method = ((MonoReflectionMethodBuilder*)obj)->mhandle;
9712                 else
9713                         method = methodbuilder_to_mono_method (gklass, (MonoReflectionMethodBuilder *) obj);
9714         else if (!strcmp (obj->vtable->klass->name, "ConstructorBuilder"))
9715                 method = ctorbuilder_to_mono_method (gklass, (MonoReflectionCtorBuilder *) obj);
9716         else if (!strcmp (obj->vtable->klass->name, "MonoMethod") || !strcmp (obj->vtable->klass->name, "MonoCMethod"))
9717                 method = ((MonoReflectionMethod *) obj)->method;
9718         else {
9719                 method = NULL; /* prevent compiler warning */
9720                 g_assert_not_reached ();
9721         }
9722
9723         return inflate_mono_method (mono_class_from_mono_type (type->type.type), method, obj);
9724 }
9725
9726 /*TODO avoid saving custom attrs for generic classes as it's enough to have them on the generic type definition.*/
9727 void
9728 mono_reflection_generic_class_initialize (MonoReflectionGenericClass *type, MonoArray *methods, 
9729                                           MonoArray *ctors, MonoArray *fields, MonoArray *properties,
9730                                           MonoArray *events)
9731 {
9732         MonoGenericClass *gclass;
9733         MonoDynamicGenericClass *dgclass;
9734         MonoClass *klass, *gklass;
9735         int i;
9736
9737         MONO_ARCH_SAVE_REGS;
9738
9739         klass = mono_class_from_mono_type (type->type.type);
9740         g_assert (type->type.type->type == MONO_TYPE_GENERICINST);
9741         gclass = type->type.type->data.generic_class;
9742
9743         g_assert (gclass->is_dynamic);
9744         dgclass = (MonoDynamicGenericClass *) gclass;
9745
9746         if (dgclass->initialized)
9747                 return;
9748
9749         gklass = gclass->container_class;
9750         mono_class_init (gklass);
9751
9752         dgclass->count_methods = methods ? mono_array_length (methods) : 0;
9753         dgclass->count_ctors = ctors ? mono_array_length (ctors) : 0;
9754         dgclass->count_fields = fields ? mono_array_length (fields) : 0;
9755         dgclass->count_properties = properties ? mono_array_length (properties) : 0;
9756         dgclass->count_events = events ? mono_array_length (events) : 0;
9757
9758         dgclass->methods = g_new0 (MonoMethod *, dgclass->count_methods);
9759         dgclass->ctors = g_new0 (MonoMethod *, dgclass->count_ctors);
9760         dgclass->fields = g_new0 (MonoClassField, dgclass->count_fields);
9761         dgclass->properties = g_new0 (MonoProperty, dgclass->count_properties);
9762         dgclass->events = g_new0 (MonoEvent, dgclass->count_events);
9763         dgclass->field_objects = g_new0 (MonoObject*, dgclass->count_fields);
9764         dgclass->field_generic_types = g_new0 (MonoType*, dgclass->count_fields);
9765
9766         for (i = 0; i < dgclass->count_methods; i++) {
9767                 MonoObject *obj = mono_array_get (methods, gpointer, i);
9768
9769                 dgclass->methods [i] = inflate_method (type, obj);
9770         }
9771
9772         for (i = 0; i < dgclass->count_ctors; i++) {
9773                 MonoObject *obj = mono_array_get (ctors, gpointer, i);
9774
9775                 dgclass->ctors [i] = inflate_method (type, obj);
9776         }
9777
9778         for (i = 0; i < dgclass->count_fields; i++) {
9779                 MonoObject *obj = mono_array_get (fields, gpointer, i);
9780                 MonoClassField *field, *inflated_field = NULL;
9781
9782                 if (!strcmp (obj->vtable->klass->name, "FieldBuilder"))
9783                         inflated_field = field = fieldbuilder_to_mono_class_field (klass, (MonoReflectionFieldBuilder *) obj);
9784                 else if (!strcmp (obj->vtable->klass->name, "MonoField"))
9785                         field = ((MonoReflectionField *) obj)->field;
9786                 else {
9787                         field = NULL; /* prevent compiler warning */
9788                         g_assert_not_reached ();
9789                 }
9790
9791                 dgclass->fields [i] = *field;
9792                 dgclass->fields [i].parent = klass;
9793                 dgclass->fields [i].type = mono_class_inflate_generic_type (
9794                         field->type, mono_generic_class_get_context ((MonoGenericClass *) dgclass));
9795                 dgclass->field_generic_types [i] = field->type;
9796                 MOVING_GC_REGISTER (&dgclass->field_objects [i]);
9797                 dgclass->field_objects [i] = obj;
9798
9799                 if (inflated_field) {
9800                         g_free (inflated_field);
9801                 } else {
9802                         dgclass->fields [i].name = g_strdup (dgclass->fields [i].name);
9803                 }
9804         }
9805
9806         for (i = 0; i < dgclass->count_properties; i++) {
9807                 MonoObject *obj = mono_array_get (properties, gpointer, i);
9808                 MonoProperty *property = &dgclass->properties [i];
9809
9810                 if (!strcmp (obj->vtable->klass->name, "PropertyBuilder")) {
9811                         MonoReflectionPropertyBuilder *pb = (MonoReflectionPropertyBuilder *) obj;
9812
9813                         property->parent = klass;
9814                         property->attrs = pb->attrs;
9815                         property->name = mono_string_to_utf8 (pb->name);
9816                         if (pb->get_method)
9817                                 property->get = inflate_method (type, (MonoObject *) pb->get_method);
9818                         if (pb->set_method)
9819                                 property->set = inflate_method (type, (MonoObject *) pb->set_method);
9820                 } else if (!strcmp (obj->vtable->klass->name, "MonoProperty")) {
9821                         *property = *((MonoReflectionProperty *) obj)->property;
9822                         property->name = g_strdup (property->name);
9823
9824                         if (property->get)
9825                                 property->get = inflate_mono_method (klass, property->get, NULL);
9826                         if (property->set)
9827                                 property->set = inflate_mono_method (klass, property->set, NULL);
9828                 } else
9829                         g_assert_not_reached ();
9830         }
9831
9832         for (i = 0; i < dgclass->count_events; i++) {
9833                 MonoObject *obj = mono_array_get (events, gpointer, i);
9834                 MonoEvent *event = &dgclass->events [i];
9835
9836                 if (!strcmp (obj->vtable->klass->name, "EventBuilder")) {
9837                         MonoReflectionEventBuilder *eb = (MonoReflectionEventBuilder *) obj;
9838
9839                         event->parent = klass;
9840                         event->attrs = eb->attrs;
9841                         event->name = mono_string_to_utf8 (eb->name);
9842                         if (eb->add_method)
9843                                 event->add = inflate_method (type, (MonoObject *) eb->add_method);
9844                         if (eb->remove_method)
9845                                 event->remove = inflate_method (type, (MonoObject *) eb->remove_method);
9846                 } else if (!strcmp (obj->vtable->klass->name, "MonoEvent")) {
9847                         *event = *((MonoReflectionEvent *) obj)->event;
9848                         event->name = g_strdup (event->name);
9849
9850                         if (event->add)
9851                                 event->add = inflate_mono_method (klass, event->add, NULL);
9852                         if (event->remove)
9853                                 event->remove = inflate_mono_method (klass, event->remove, NULL);
9854                 } else
9855                         g_assert_not_reached ();
9856         }
9857
9858         dgclass->initialized = TRUE;
9859 }
9860
9861 static void
9862 ensure_generic_class_runtime_vtable (MonoClass *klass)
9863 {
9864         MonoClass *gklass = klass->generic_class->container_class;
9865         int i;
9866
9867         if (klass->wastypebuilder)
9868                 return;
9869
9870         ensure_runtime_vtable (gklass);
9871
9872         klass->method.count = gklass->method.count;
9873         klass->methods = mono_image_alloc (klass->image, sizeof (MonoMethod*) * (klass->method.count + 1));
9874
9875         for (i = 0; i < klass->method.count; i++) {
9876                 klass->methods [i] = mono_class_inflate_generic_method_full (
9877                         gklass->methods [i], klass, mono_class_get_context (klass));
9878         }
9879
9880         klass->interface_count = gklass->interface_count;
9881         klass->interfaces = mono_image_alloc (klass->image, sizeof (MonoClass*) * klass->interface_count);
9882         for (i = 0; i < klass->interface_count; ++i) {
9883                 MonoType *iface_type = mono_class_inflate_generic_type (&gklass->interfaces [i]->byval_arg, mono_class_get_context (klass));
9884                 klass->interfaces [i] = mono_class_from_mono_type (iface_type);
9885                 mono_metadata_free_type (iface_type);
9886
9887                 ensure_runtime_vtable (klass->interfaces [i]);
9888         }
9889         klass->interfaces_inited = 1;
9890
9891         /*We can only finish with this klass once it's parent has as well*/
9892         if (gklass->wastypebuilder)
9893                 klass->wastypebuilder = TRUE;
9894         return;
9895 }
9896
9897 static void
9898 ensure_runtime_vtable (MonoClass *klass)
9899 {
9900         MonoReflectionTypeBuilder *tb = klass->reflection_info;
9901         int i, num, j;
9902
9903         if (!klass->image->dynamic || (!tb && !klass->generic_class) || klass->wastypebuilder)
9904                 return;
9905         if (klass->parent)
9906                 ensure_runtime_vtable (klass->parent);
9907
9908         if (tb) {
9909                 num = tb->ctors? mono_array_length (tb->ctors): 0;
9910                 num += tb->num_methods;
9911                 klass->method.count = num;
9912                 klass->methods = mono_image_alloc (klass->image, sizeof (MonoMethod*) * num);
9913                 num = tb->ctors? mono_array_length (tb->ctors): 0;
9914                 for (i = 0; i < num; ++i)
9915                         klass->methods [i] = ctorbuilder_to_mono_method (klass, mono_array_get (tb->ctors, MonoReflectionCtorBuilder*, i));
9916                 num = tb->num_methods;
9917                 j = i;
9918                 for (i = 0; i < num; ++i)
9919                         klass->methods [j++] = methodbuilder_to_mono_method (klass, mono_array_get (tb->methods, MonoReflectionMethodBuilder*, i));
9920         
9921                 if (tb->interfaces) {
9922                         klass->interface_count = mono_array_length (tb->interfaces);
9923                         klass->interfaces = mono_image_alloc (klass->image, sizeof (MonoClass*) * klass->interface_count);
9924                         for (i = 0; i < klass->interface_count; ++i) {
9925                                 MonoReflectionType *iface = mono_array_get (tb->interfaces, gpointer, i);
9926                                 klass->interfaces [i] = mono_class_from_mono_type (iface->type);
9927                                 ensure_runtime_vtable (klass->interfaces [i]);
9928                         }
9929                         klass->interfaces_inited = 1;
9930                 }
9931         } else if (klass->generic_class){
9932                 ensure_generic_class_runtime_vtable (klass);
9933         }
9934
9935         if (klass->flags & TYPE_ATTRIBUTE_INTERFACE) {
9936                 for (i = 0; i < klass->method.count; ++i)
9937                         klass->methods [i]->slot = i;
9938                 
9939                 mono_class_setup_interface_offsets (klass);
9940                 mono_class_setup_interface_id (klass);
9941         }
9942
9943         /*
9944          * The generic vtable is needed even if image->run is not set since some
9945          * runtime code like ves_icall_Type_GetMethodsByName depends on 
9946          * method->slot being defined.
9947          */
9948
9949         /* 
9950          * tb->methods could not be freed since it is used for determining 
9951          * overrides during dynamic vtable construction.
9952          */
9953 }
9954
9955 void
9956 mono_reflection_get_dynamic_overrides (MonoClass *klass, MonoMethod ***overrides, int *num_overrides)
9957 {
9958         MonoReflectionTypeBuilder *tb;
9959         int i, onum;
9960
9961         *overrides = NULL;
9962         *num_overrides = 0;
9963
9964         g_assert (klass->image->dynamic);
9965
9966         if (!klass->reflection_info)
9967                 return;
9968
9969         g_assert (strcmp (((MonoObject*)klass->reflection_info)->vtable->klass->name, "TypeBuilder") == 0);
9970
9971         tb = (MonoReflectionTypeBuilder*)klass->reflection_info;
9972
9973         onum = 0;
9974         if (tb->methods) {
9975                 for (i = 0; i < tb->num_methods; ++i) {
9976                         MonoReflectionMethodBuilder *mb = 
9977                                 mono_array_get (tb->methods, MonoReflectionMethodBuilder*, i);
9978                         if (mb->override_method)
9979                                 onum ++;
9980                 }
9981         }
9982
9983         if (onum) {
9984                 *overrides = g_new0 (MonoMethod*, onum * 2);
9985
9986                 onum = 0;
9987                 for (i = 0; i < tb->num_methods; ++i) {
9988                         MonoReflectionMethodBuilder *mb = 
9989                                 mono_array_get (tb->methods, MonoReflectionMethodBuilder*, i);
9990                         if (mb->override_method) {
9991                                 (*overrides) [onum * 2] = 
9992                                         mb->override_method->method;
9993                                 (*overrides) [onum * 2 + 1] =
9994                                         mb->mhandle;
9995
9996                                 /* FIXME: What if 'override_method' is a MethodBuilder ? */
9997                                 g_assert (mb->override_method->method);
9998                                 g_assert (mb->mhandle);
9999
10000                                 onum ++;
10001                         }
10002                 }
10003         }
10004
10005         *num_overrides = onum;
10006 }
10007
10008 static void
10009 typebuilder_setup_fields (MonoClass *klass)
10010 {
10011         MonoReflectionTypeBuilder *tb = klass->reflection_info;
10012         MonoReflectionFieldBuilder *fb;
10013         MonoClassField *field;
10014         MonoImage *image = klass->image;
10015         const char *p, *p2;
10016         int i;
10017         guint32 len, idx, real_size = 0;
10018
10019         klass->field.count = tb->num_fields;
10020         klass->field.first = 0;
10021
10022         if (tb->class_size) {
10023                 g_assert ((tb->packing_size & 0xfffffff0) == 0);
10024                 klass->packing_size = tb->packing_size;
10025                 real_size = klass->instance_size + tb->class_size;
10026         }
10027
10028         if (!klass->field.count) {
10029                 klass->instance_size = MAX (klass->instance_size, real_size);
10030                 return;
10031         }
10032         
10033         klass->fields = image_g_new0 (image, MonoClassField, klass->field.count);
10034         mono_class_alloc_ext (klass);
10035         klass->ext->field_def_values = image_g_new0 (image, MonoFieldDefaultValue, klass->field.count);
10036
10037         for (i = 0; i < klass->field.count; ++i) {
10038                 fb = mono_array_get (tb->fields, gpointer, i);
10039                 field = &klass->fields [i];
10040                 field->name = mono_string_to_utf8_image (image, fb->name);
10041                 if (fb->attrs) {
10042                         field->type = mono_metadata_type_dup (klass->image, fb->type->type);
10043                         field->type->attrs = fb->attrs;
10044                 } else {
10045                         field->type = fb->type->type;
10046                 }
10047                 if ((fb->attrs & FIELD_ATTRIBUTE_HAS_FIELD_RVA) && fb->rva_data)
10048                         klass->ext->field_def_values [i].data = mono_array_addr (fb->rva_data, char, 0);
10049                 if (fb->offset != -1)
10050                         field->offset = fb->offset;
10051                 field->parent = klass;
10052                 fb->handle = field;
10053                 mono_save_custom_attrs (klass->image, field, fb->cattrs);
10054
10055                 if (fb->def_value) {
10056                         MonoDynamicImage *assembly = (MonoDynamicImage*)klass->image;
10057                         field->type->attrs |= FIELD_ATTRIBUTE_HAS_DEFAULT;
10058                         idx = encode_constant (assembly, fb->def_value, &klass->ext->field_def_values [i].def_type);
10059                         /* Copy the data from the blob since it might get realloc-ed */
10060                         p = assembly->blob.data + idx;
10061                         len = mono_metadata_decode_blob_size (p, &p2);
10062                         len += p2 - p;
10063                         klass->ext->field_def_values [i].data = mono_image_alloc (image, len);
10064                         memcpy ((gpointer)klass->ext->field_def_values [i].data, p, len);
10065                 }
10066         }
10067
10068         klass->instance_size = MAX (klass->instance_size, real_size);
10069         mono_class_layout_fields (klass);
10070 }
10071
10072 static void
10073 typebuilder_setup_properties (MonoClass *klass)
10074 {
10075         MonoReflectionTypeBuilder *tb = klass->reflection_info;
10076         MonoReflectionPropertyBuilder *pb;
10077         MonoImage *image = klass->image;
10078         MonoProperty *properties;
10079         int i;
10080
10081         if (!klass->ext)
10082                 klass->ext = image_g_new0 (image, MonoClassExt, 1);
10083
10084         klass->ext->property.count = tb->properties ? mono_array_length (tb->properties) : 0;
10085         klass->ext->property.first = 0;
10086
10087         properties = image_g_new0 (image, MonoProperty, klass->ext->property.count);
10088         klass->ext->properties = properties;
10089         for (i = 0; i < klass->ext->property.count; ++i) {
10090                 pb = mono_array_get (tb->properties, MonoReflectionPropertyBuilder*, i);
10091                 properties [i].parent = klass;
10092                 properties [i].attrs = pb->attrs;
10093                 properties [i].name = mono_string_to_utf8_image (image, pb->name);
10094                 if (pb->get_method)
10095                         properties [i].get = pb->get_method->mhandle;
10096                 if (pb->set_method)
10097                         properties [i].set = pb->set_method->mhandle;
10098
10099                 mono_save_custom_attrs (klass->image, &properties [i], pb->cattrs);
10100         }
10101 }
10102
10103 MonoReflectionEvent *
10104 mono_reflection_event_builder_get_event_info (MonoReflectionTypeBuilder *tb, MonoReflectionEventBuilder *eb)
10105 {
10106         MonoEvent *event = g_new0 (MonoEvent, 1);
10107         MonoClass *klass;
10108         int j;
10109
10110         klass = my_mono_class_from_mono_type (tb->type.type);
10111
10112         event->parent = klass;
10113         event->attrs = eb->attrs;
10114         event->name = mono_string_to_utf8 (eb->name);
10115         if (eb->add_method)
10116                 event->add = eb->add_method->mhandle;
10117         if (eb->remove_method)
10118                 event->remove = eb->remove_method->mhandle;
10119         if (eb->raise_method)
10120                 event->raise = eb->raise_method->mhandle;
10121
10122         if (eb->other_methods) {
10123                 event->other = g_new0 (MonoMethod*, mono_array_length (eb->other_methods) + 1);
10124                 for (j = 0; j < mono_array_length (eb->other_methods); ++j) {
10125                         MonoReflectionMethodBuilder *mb = 
10126                                 mono_array_get (eb->other_methods,
10127                                                 MonoReflectionMethodBuilder*, j);
10128                         event->other [j] = mb->mhandle;
10129                 }
10130         }
10131
10132         return mono_event_get_object (mono_object_domain (tb), klass, event);
10133 }
10134
10135 static void
10136 typebuilder_setup_events (MonoClass *klass)
10137 {
10138         MonoReflectionTypeBuilder *tb = klass->reflection_info;
10139         MonoReflectionEventBuilder *eb;
10140         MonoImage *image = klass->image;
10141         MonoEvent *events;
10142         int i, j;
10143
10144         if (!klass->ext)
10145                 klass->ext = image_g_new0 (image, MonoClassExt, 1);
10146
10147         klass->ext->event.count = tb->events ? mono_array_length (tb->events) : 0;
10148         klass->ext->event.first = 0;
10149
10150         events = image_g_new0 (image, MonoEvent, klass->ext->event.count);
10151         klass->ext->events = events;
10152         for (i = 0; i < klass->ext->event.count; ++i) {
10153                 eb = mono_array_get (tb->events, MonoReflectionEventBuilder*, i);
10154                 events [i].parent = klass;
10155                 events [i].attrs = eb->attrs;
10156                 events [i].name = mono_string_to_utf8_image (image, eb->name);
10157                 if (eb->add_method)
10158                         events [i].add = eb->add_method->mhandle;
10159                 if (eb->remove_method)
10160                         events [i].remove = eb->remove_method->mhandle;
10161                 if (eb->raise_method)
10162                         events [i].raise = eb->raise_method->mhandle;
10163
10164                 if (eb->other_methods) {
10165                         events [i].other = image_g_new0 (image, MonoMethod*, mono_array_length (eb->other_methods) + 1);
10166                         for (j = 0; j < mono_array_length (eb->other_methods); ++j) {
10167                                 MonoReflectionMethodBuilder *mb = 
10168                                         mono_array_get (eb->other_methods,
10169                                                                         MonoReflectionMethodBuilder*, j);
10170                                 events [i].other [j] = mb->mhandle;
10171                         }
10172                 }
10173                 mono_save_custom_attrs (klass->image, &events [i], eb->cattrs);
10174         }
10175 }
10176
10177 static gboolean
10178 remove_instantiations_of (gpointer key,
10179                                                   gpointer value,
10180                                                   gpointer user_data)
10181 {
10182         MonoType *type = (MonoType*)key;
10183         MonoClass *klass = (MonoClass*)user_data;
10184
10185         if ((type->type == MONO_TYPE_GENERICINST) && (type->data.generic_class->container_class == klass))
10186                 return TRUE;
10187         else
10188                 return FALSE;
10189 }
10190
10191 MonoReflectionType*
10192 mono_reflection_create_runtime_class (MonoReflectionTypeBuilder *tb)
10193 {
10194         MonoClass *klass;
10195         MonoDomain* domain;
10196         MonoReflectionType* res;
10197         int i;
10198
10199         MONO_ARCH_SAVE_REGS;
10200
10201         domain = mono_object_domain (tb);
10202         klass = my_mono_class_from_mono_type (tb->type.type);
10203
10204         mono_save_custom_attrs (klass->image, klass, tb->cattrs);
10205         
10206         /* 
10207          * we need to lock the domain because the lock will be taken inside
10208          * So, we need to keep the locking order correct.
10209          */
10210         mono_domain_lock (domain);
10211         mono_loader_lock ();
10212         if (klass->wastypebuilder) {
10213                 mono_loader_unlock ();
10214                 mono_domain_unlock (domain);
10215                 return mono_type_get_object (mono_object_domain (tb), &klass->byval_arg);
10216         }
10217         /*
10218          * Fields to set in klass:
10219          * the various flags: delegate/unicode/contextbound etc.
10220          */
10221         klass->flags = tb->attrs;
10222         klass->has_cctor = 1;
10223         klass->has_finalize = 1;
10224
10225 #if 0
10226         if (!((MonoDynamicImage*)klass->image)->run) {
10227                 if (klass->generic_container) {
10228                         /* FIXME: The code below can't handle generic classes */
10229                         klass->wastypebuilder = TRUE;
10230                         mono_loader_unlock ();
10231                         mono_domain_unlock (domain);
10232                         return mono_type_get_object (mono_object_domain (tb), &klass->byval_arg);
10233                 }
10234         }
10235 #endif
10236
10237         /* enums are done right away */
10238         if (!klass->enumtype)
10239                 ensure_runtime_vtable (klass);
10240
10241         if (tb->subtypes) {
10242                 for (i = 0; i < mono_array_length (tb->subtypes); ++i) {
10243                         MonoReflectionTypeBuilder *subtb = mono_array_get (tb->subtypes, MonoReflectionTypeBuilder*, i);
10244                         mono_class_alloc_ext (klass);
10245                         klass->ext->nested_classes = g_list_prepend_image (klass->image, klass->ext->nested_classes, my_mono_class_from_mono_type (subtb->type.type));
10246                 }
10247         }
10248
10249         klass->nested_classes_inited = TRUE;
10250
10251         /* fields and object layout */
10252         if (klass->parent) {
10253                 if (!klass->parent->size_inited)
10254                         mono_class_init (klass->parent);
10255                 klass->instance_size = klass->parent->instance_size;
10256                 klass->sizes.class_size = 0;
10257                 klass->min_align = klass->parent->min_align;
10258                 /* if the type has no fields we won't call the field_setup
10259                  * routine which sets up klass->has_references.
10260                  */
10261                 klass->has_references |= klass->parent->has_references;
10262         } else {
10263                 klass->instance_size = sizeof (MonoObject);
10264                 klass->min_align = 1;
10265         }
10266
10267         /* FIXME: handle packing_size and instance_size */
10268         typebuilder_setup_fields (klass);
10269
10270         typebuilder_setup_properties (klass);
10271
10272         typebuilder_setup_events (klass);
10273         
10274         klass->wastypebuilder = TRUE;
10275
10276         /* 
10277          * If we are a generic TypeBuilder, there might be instantiations in the type cache
10278          * which have type System.Reflection.MonoGenericClass, but after the type is created, 
10279          * we want to return normal System.MonoType objects, so clear these out from the cache.
10280          */
10281         if (domain->type_hash && klass->generic_container)
10282                 mono_g_hash_table_foreach_remove (domain->type_hash, remove_instantiations_of, klass);
10283
10284         mono_loader_unlock ();
10285         mono_domain_unlock (domain);
10286
10287         if (klass->enumtype && !mono_class_is_valid_enum (klass)) {
10288                 mono_class_set_failure (klass, MONO_EXCEPTION_TYPE_LOAD, NULL);
10289                 mono_raise_exception (mono_get_exception_type_load (tb->name, NULL));
10290         }
10291
10292         res = mono_type_get_object (mono_object_domain (tb), &klass->byval_arg);
10293         g_assert (res != (MonoReflectionType*)tb);
10294
10295         return res;
10296 }
10297
10298 void
10299 mono_reflection_initialize_generic_parameter (MonoReflectionGenericParam *gparam)
10300 {
10301         MonoGenericParam *param;
10302         MonoImage *image;
10303
10304         MONO_ARCH_SAVE_REGS;
10305
10306         param = g_new0 (MonoGenericParam, 1);
10307
10308         if (gparam->mbuilder) {
10309                 if (!gparam->mbuilder->generic_container) {
10310                         MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder *)gparam->mbuilder->type;
10311                         MonoClass *klass = my_mono_class_from_mono_type (tb->type.type);
10312                         gparam->mbuilder->generic_container = mono_image_alloc0 (klass->image, sizeof (MonoGenericContainer));
10313                         gparam->mbuilder->generic_container->is_method = TRUE;
10314                 }
10315                 param->owner = gparam->mbuilder->generic_container;
10316         } else if (gparam->tbuilder) {
10317                 if (!gparam->tbuilder->generic_container) {
10318                         MonoClass *klass = my_mono_class_from_mono_type (gparam->tbuilder->type.type);
10319                         gparam->tbuilder->generic_container = mono_image_alloc0 (klass->image, sizeof (MonoGenericContainer));
10320                         gparam->tbuilder->generic_container->owner.klass = klass;
10321                 }
10322                 param->owner = gparam->tbuilder->generic_container;
10323         }
10324
10325         param->name = mono_string_to_utf8 (gparam->name);
10326         param->num = gparam->index;
10327
10328         image = &gparam->tbuilder->module->dynamic_image->image;
10329         mono_class_from_generic_parameter (param, image, gparam->mbuilder != NULL);
10330
10331         gparam->type.type = &param->pklass->byval_arg;
10332
10333         MOVING_GC_REGISTER (&param->pklass->reflection_info);
10334         param->pklass->reflection_info = gparam; /* FIXME: GC pin gparam */
10335 }
10336
10337 MonoArray *
10338 mono_reflection_sighelper_get_signature_local (MonoReflectionSigHelper *sig)
10339 {
10340         MonoDynamicImage *assembly = sig->module->dynamic_image;
10341         guint32 na = mono_array_length (sig->arguments);
10342         guint32 buflen, i;
10343         MonoArray *result;
10344         SigBuffer buf;
10345
10346         sigbuffer_init (&buf, 32);
10347
10348         sigbuffer_add_value (&buf, 0x07);
10349         sigbuffer_add_value (&buf, na);
10350         for (i = 0; i < na; ++i) {
10351                 MonoReflectionType *type = mono_array_get (sig->arguments, MonoReflectionType *, i);
10352                 encode_reflection_type (assembly, type, &buf);
10353         }
10354
10355         buflen = buf.p - buf.buf;
10356         result = mono_array_new (mono_domain_get (), mono_defaults.byte_class, buflen);
10357         memcpy (mono_array_addr (result, char, 0), buf.buf, buflen);
10358         sigbuffer_free (&buf);
10359
10360         return result;
10361 }
10362
10363 MonoArray *
10364 mono_reflection_sighelper_get_signature_field (MonoReflectionSigHelper *sig)
10365 {
10366         MonoDynamicImage *assembly = sig->module->dynamic_image;
10367         guint32 na = mono_array_length (sig->arguments);
10368         guint32 buflen, i;
10369         MonoArray *result;
10370         SigBuffer buf;
10371
10372         sigbuffer_init (&buf, 32);
10373
10374         sigbuffer_add_value (&buf, 0x06);
10375         for (i = 0; i < na; ++i) {
10376                 MonoReflectionType *type = mono_array_get (sig->arguments, MonoReflectionType *, i);
10377                 encode_reflection_type (assembly, type, &buf);
10378         }
10379
10380         buflen = buf.p - buf.buf;
10381         result = mono_array_new (mono_domain_get (), mono_defaults.byte_class, buflen);
10382         memcpy (mono_array_addr (result, char, 0), buf.buf, buflen);
10383         sigbuffer_free (&buf);
10384
10385         return result;
10386 }
10387
10388 void 
10389 mono_reflection_create_dynamic_method (MonoReflectionDynamicMethod *mb)
10390 {
10391         ReflectionMethodBuilder rmb;
10392         MonoMethodSignature *sig;
10393         MonoClass *klass;
10394         GSList *l;
10395         int i;
10396
10397         sig = dynamic_method_to_signature (mb);
10398
10399         reflection_methodbuilder_from_dynamic_method (&rmb, mb);
10400
10401         /*
10402          * Resolve references.
10403          */
10404         /* 
10405          * Every second entry in the refs array is reserved for storing handle_class,
10406          * which is needed by the ldtoken implementation in the JIT.
10407          */
10408         rmb.nrefs = mb->nrefs;
10409         rmb.refs = g_new0 (gpointer, mb->nrefs + 1);
10410         for (i = 0; i < mb->nrefs; i += 2) {
10411                 MonoClass *handle_class;
10412                 gpointer ref;
10413                 MonoObject *obj = mono_array_get (mb->refs, MonoObject*, i);
10414
10415                 if (strcmp (obj->vtable->klass->name, "DynamicMethod") == 0) {
10416                         MonoReflectionDynamicMethod *method = (MonoReflectionDynamicMethod*)obj;
10417                         /*
10418                          * The referenced DynamicMethod should already be created by the managed
10419                          * code, except in the case of circular references. In that case, we store
10420                          * method in the refs array, and fix it up later when the referenced 
10421                          * DynamicMethod is created.
10422                          */
10423                         if (method->mhandle) {
10424                                 ref = method->mhandle;
10425                         } else {
10426                                 /* FIXME: GC object stored in unmanaged memory */
10427                                 ref = method;
10428
10429                                 /* FIXME: GC object stored in unmanaged memory */
10430                                 method->referenced_by = g_slist_append (method->referenced_by, mb);
10431                         }
10432                         handle_class = mono_defaults.methodhandle_class;
10433                 } else {
10434                         ref = resolve_object (mb->module->image, obj, &handle_class, NULL);
10435                         if (!ref) {
10436                                 g_free (rmb.refs);
10437                                 mono_raise_exception (mono_get_exception_type_load (NULL, NULL));
10438                                 return;
10439                         }
10440                 }
10441
10442                 rmb.refs [i] = ref; /* FIXME: GC object stored in unmanaged memory (change also resolve_object() signature) */
10443                 rmb.refs [i + 1] = handle_class;
10444         }               
10445
10446         klass = mb->owner ? mono_class_from_mono_type (mb->owner->type) : mono_defaults.object_class;
10447
10448         mb->mhandle = reflection_methodbuilder_to_mono_method (klass, &rmb, sig);
10449
10450         /* Fix up refs entries pointing at us */
10451         for (l = mb->referenced_by; l; l = l->next) {
10452                 MonoReflectionDynamicMethod *method = (MonoReflectionDynamicMethod*)l->data;
10453                 MonoMethodWrapper *wrapper = (MonoMethodWrapper*)method->mhandle;
10454                 gpointer *data;
10455                 
10456                 g_assert (method->mhandle);
10457
10458                 data = (gpointer*)wrapper->method_data;
10459                 for (i = 0; i < GPOINTER_TO_UINT (data [0]); i += 2) {
10460                         if ((data [i + 1] == mb) && (data [i + 1 + 1] == mono_defaults.methodhandle_class))
10461                                 data [i + 1] = mb->mhandle;
10462                 }
10463         }
10464         g_slist_free (mb->referenced_by);
10465
10466         g_free (rmb.refs);
10467
10468         /* ilgen is no longer needed */
10469         mb->ilgen = NULL;
10470 }
10471
10472 #endif /* DISABLE_REFLECTION_EMIT */
10473
10474 void
10475 mono_reflection_destroy_dynamic_method (MonoReflectionDynamicMethod *mb)
10476 {
10477         g_assert (mb);
10478
10479         if (mb->mhandle)
10480                 mono_runtime_free_method (
10481                         mono_object_get_domain ((MonoObject*)mb), mb->mhandle);
10482 }
10483
10484 /**
10485  * 
10486  * mono_reflection_is_valid_dynamic_token:
10487  * 
10488  * Returns TRUE if token is valid.
10489  * 
10490  */
10491 gboolean
10492 mono_reflection_is_valid_dynamic_token (MonoDynamicImage *image, guint32 token)
10493 {
10494         return mono_g_hash_table_lookup (image->tokens, GUINT_TO_POINTER (token)) != NULL;
10495 }
10496
10497 #ifndef DISABLE_REFLECTION_EMIT
10498
10499 /**
10500  * mono_reflection_lookup_dynamic_token:
10501  *
10502  * Finish the Builder object pointed to by TOKEN and return the corresponding
10503  * runtime structure. If HANDLE_CLASS is not NULL, it is set to the class required by 
10504  * mono_ldtoken. If valid_token is TRUE, assert if it is not found in the token->object
10505  * mapping table.
10506  *
10507  * LOCKING: Take the loader lock
10508  */
10509 gpointer
10510 mono_reflection_lookup_dynamic_token (MonoImage *image, guint32 token, gboolean valid_token, MonoClass **handle_class, MonoGenericContext *context)
10511 {
10512         MonoDynamicImage *assembly = (MonoDynamicImage*)image;
10513         MonoObject *obj;
10514         MonoClass *klass;
10515
10516         mono_loader_lock ();
10517         obj = mono_g_hash_table_lookup (assembly->tokens, GUINT_TO_POINTER (token));
10518         mono_loader_unlock ();
10519         if (!obj) {
10520                 if (valid_token)
10521                         g_assert_not_reached ();
10522                 else
10523                         return NULL;
10524         }
10525
10526         if (!handle_class)
10527                 handle_class = &klass;
10528         return resolve_object (image, obj, handle_class, context);
10529 }
10530
10531 static gpointer
10532 resolve_object (MonoImage *image, MonoObject *obj, MonoClass **handle_class, MonoGenericContext *context)
10533 {
10534         gpointer result = NULL;
10535
10536         if (strcmp (obj->vtable->klass->name, "String") == 0) {
10537                 result = mono_string_intern ((MonoString*)obj);
10538                 *handle_class = NULL;
10539                 g_assert (result);
10540         } else if (strcmp (obj->vtable->klass->name, "MonoType") == 0) {
10541                 MonoReflectionType *tb = (MonoReflectionType*)obj;
10542                 if (context) {
10543                         MonoType *inflated = mono_class_inflate_generic_type (tb->type, context);
10544                         result = mono_class_from_mono_type (inflated);
10545                         mono_metadata_free_type (inflated);
10546                 } else {
10547                         result = mono_class_from_mono_type (tb->type);
10548                 }
10549                 *handle_class = mono_defaults.typehandle_class;
10550                 g_assert (result);
10551         } else if (strcmp (obj->vtable->klass->name, "MonoMethod") == 0 ||
10552                    strcmp (obj->vtable->klass->name, "MonoCMethod") == 0 ||
10553                    strcmp (obj->vtable->klass->name, "MonoGenericCMethod") == 0 ||
10554                    strcmp (obj->vtable->klass->name, "MonoGenericMethod") == 0) {
10555                 result = ((MonoReflectionMethod*)obj)->method;
10556                 if (context)
10557                         result = mono_class_inflate_generic_method (result, context);
10558                 *handle_class = mono_defaults.methodhandle_class;
10559                 g_assert (result);
10560         } else if (strcmp (obj->vtable->klass->name, "MethodBuilder") == 0) {
10561                 MonoReflectionMethodBuilder *mb = (MonoReflectionMethodBuilder*)obj;
10562                 result = mb->mhandle;
10563                 if (!result) {
10564                         /* Type is not yet created */
10565                         MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder*)mb->type;
10566
10567                         mono_domain_try_type_resolve (mono_domain_get (), NULL, (MonoObject*)tb);
10568
10569                         /*
10570                          * Hopefully this has been filled in by calling CreateType() on the
10571                          * TypeBuilder.
10572                          */
10573                         /*
10574                          * TODO: This won't work if the application finishes another 
10575                          * TypeBuilder instance instead of this one.
10576                          */
10577                         result = mb->mhandle;
10578                 }
10579                 if (context)
10580                         result = mono_class_inflate_generic_method (result, context);
10581                 *handle_class = mono_defaults.methodhandle_class;
10582         } else if (strcmp (obj->vtable->klass->name, "ConstructorBuilder") == 0) {
10583                 MonoReflectionCtorBuilder *cb = (MonoReflectionCtorBuilder*)obj;
10584
10585                 result = cb->mhandle;
10586                 if (!result) {
10587                         MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder*)cb->type;
10588
10589                         mono_domain_try_type_resolve (mono_domain_get (), NULL, (MonoObject*)tb);
10590                         result = cb->mhandle;
10591                 }
10592                 if (context)
10593                         result = mono_class_inflate_generic_method (result, context);
10594                 *handle_class = mono_defaults.methodhandle_class;
10595         } else if (strcmp (obj->vtable->klass->name, "MonoField") == 0) {
10596                 MonoClassField *field = ((MonoReflectionField*)obj)->field;
10597                 if (context) {
10598                         MonoType *inflated = mono_class_inflate_generic_type (&field->parent->byval_arg, context);
10599                         MonoClass *class = mono_class_from_mono_type (inflated);
10600                         MonoClassField *inflated_field;
10601                         gpointer iter = NULL;
10602                         mono_metadata_free_type (inflated);
10603                         while ((inflated_field = mono_class_get_fields (class, &iter))) {
10604                                 if (!strcmp (field->name, inflated_field->name))
10605                                         break;
10606                         }
10607                         g_assert (inflated_field && !strcmp (field->name, inflated_field->name));
10608                         result = inflated_field;
10609                 } else {
10610                         result = field;
10611                 }
10612                 *handle_class = mono_defaults.fieldhandle_class;
10613                 g_assert (result);
10614         } else if (strcmp (obj->vtable->klass->name, "FieldBuilder") == 0) {
10615                 MonoReflectionFieldBuilder *fb = (MonoReflectionFieldBuilder*)obj;
10616                 result = fb->handle;
10617
10618                 if (!result) {
10619                         MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder*)fb->typeb;
10620
10621                         mono_domain_try_type_resolve (mono_domain_get (), NULL, (MonoObject*)tb);
10622                         result = fb->handle;
10623                 }
10624
10625                 if (fb->handle && fb->handle->parent->generic_container) {
10626                         MonoClass *klass = fb->handle->parent;
10627                         MonoType *type = mono_class_inflate_generic_type (&klass->byval_arg, context);
10628                         MonoClass *inflated = mono_class_from_mono_type (type);
10629
10630                         result = mono_class_get_field_from_name (inflated, mono_field_get_name (fb->handle));
10631                         g_assert (result);
10632                         mono_metadata_free_type (type);
10633                 }
10634                 *handle_class = mono_defaults.fieldhandle_class;
10635         } else if (strcmp (obj->vtable->klass->name, "TypeBuilder") == 0) {
10636                 MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder*)obj;
10637                 MonoClass *klass;
10638
10639                 klass = tb->type.type->data.klass;
10640                 if (klass->wastypebuilder) {
10641                         /* Already created */
10642                         result = klass;
10643                 }
10644                 else {
10645                         mono_domain_try_type_resolve (mono_domain_get (), NULL, (MonoObject*)tb);
10646                         result = tb->type.type->data.klass;
10647                         g_assert (result);
10648                 }
10649                 *handle_class = mono_defaults.typehandle_class;
10650         } else if (strcmp (obj->vtable->klass->name, "SignatureHelper") == 0) {
10651                 MonoReflectionSigHelper *helper = (MonoReflectionSigHelper*)obj;
10652                 MonoMethodSignature *sig;
10653                 int nargs, i;
10654
10655                 if (helper->arguments)
10656                         nargs = mono_array_length (helper->arguments);
10657                 else
10658                         nargs = 0;
10659
10660                 sig = mono_metadata_signature_alloc (image, nargs);
10661                 sig->explicit_this = helper->call_conv & 64 ? 1 : 0;
10662                 sig->hasthis = helper->call_conv & 32 ? 1 : 0;
10663
10664                 if (helper->call_conv == 0) /* unmanaged */
10665                         sig->call_convention = helper->unmanaged_call_conv - 1;
10666                 else
10667                         if (helper->call_conv & 0x02)
10668                                 sig->call_convention = MONO_CALL_VARARG;
10669                 else
10670                         sig->call_convention = MONO_CALL_DEFAULT;
10671
10672                 sig->param_count = nargs;
10673                 /* TODO: Copy type ? */
10674                 sig->ret = helper->return_type->type;
10675                 for (i = 0; i < nargs; ++i) {
10676                         MonoReflectionType *rt = mono_array_get (helper->arguments, MonoReflectionType*, i);
10677                         sig->params [i] = rt->type;
10678                 }
10679
10680                 result = sig;
10681                 *handle_class = NULL;
10682         } else if (strcmp (obj->vtable->klass->name, "DynamicMethod") == 0) {
10683                 MonoReflectionDynamicMethod *method = (MonoReflectionDynamicMethod*)obj;
10684                 /* Already created by the managed code */
10685                 g_assert (method->mhandle);
10686                 result = method->mhandle;
10687                 *handle_class = mono_defaults.methodhandle_class;
10688         } else if (strcmp (obj->vtable->klass->name, "GenericTypeParameterBuilder") == 0) {
10689                 MonoReflectionType *tb = (MonoReflectionType*)obj;
10690                 MonoType *type = mono_class_inflate_generic_type (tb->type, context);
10691                 result = mono_class_from_mono_type (type);
10692                 *handle_class = mono_defaults.typehandle_class;
10693                 g_assert (result);
10694                 mono_metadata_free_type (type);
10695         } else if (strcmp (obj->vtable->klass->name, "MonoGenericClass") == 0) {
10696                 MonoReflectionGenericClass *ref = (MonoReflectionGenericClass*)obj;
10697                 MonoType *type = mono_class_inflate_generic_type (ref->type.type, context);
10698                 result = mono_class_from_mono_type (type);
10699                 *handle_class = mono_defaults.typehandle_class;
10700                 g_assert (result);
10701                 mono_metadata_free_type (type);
10702         } else if (strcmp (obj->vtable->klass->name, "FieldOnTypeBuilderInst") == 0) {
10703                 MonoReflectionFieldOnTypeBuilderInst *f = (MonoReflectionFieldOnTypeBuilderInst*)obj;
10704                 MonoClass *inflated;
10705                 MonoType *type;
10706
10707                 type = mono_class_inflate_generic_type (f->inst->type.type, context);
10708                 inflated = mono_class_from_mono_type (type);
10709
10710                 g_assert (f->fb->handle);
10711                 result = mono_class_get_field_from_name (inflated, mono_field_get_name (f->fb->handle));
10712                 g_assert (result);
10713                 mono_metadata_free_type (type);
10714                 *handle_class = mono_defaults.fieldhandle_class;
10715         } else if (strcmp (obj->vtable->klass->name, "ConstructorOnTypeBuilderInst") == 0) {
10716                 MonoReflectionCtorOnTypeBuilderInst *c = (MonoReflectionCtorOnTypeBuilderInst*)obj;
10717                 MonoType *type = mono_class_inflate_generic_type (c->inst->type.type, context);
10718                 MonoClass *inflated_klass = mono_class_from_mono_type (type);
10719                 g_assert (c->cb->mhandle);
10720                 result = inflate_mono_method (inflated_klass, c->cb->mhandle, (MonoObject*)c->cb);
10721                 *handle_class = mono_defaults.methodhandle_class;
10722                 mono_metadata_free_type (type);
10723         } else if (strcmp (obj->vtable->klass->name, "MethodOnTypeBuilderInst") == 0) {
10724                 MonoReflectionMethodOnTypeBuilderInst *m = (MonoReflectionMethodOnTypeBuilderInst*)obj;
10725                 MonoType *type = mono_class_inflate_generic_type (m->inst->type.type, context);
10726                 MonoClass *inflated_klass = mono_class_from_mono_type (type);
10727                 g_assert (m->mb->mhandle);
10728                 result = inflate_mono_method (inflated_klass, m->mb->mhandle, (MonoObject*)m->mb);
10729                 *handle_class = mono_defaults.methodhandle_class;
10730                 mono_metadata_free_type (type);
10731         } else {
10732                 g_print (obj->vtable->klass->name);
10733                 g_assert_not_reached ();
10734         }
10735         return result;
10736 }
10737
10738 #else /* DISABLE_REFLECTION_EMIT */
10739
10740 MonoArray*
10741 mono_reflection_get_custom_attrs_blob (MonoReflectionAssembly *assembly, MonoObject *ctor, MonoArray *ctorArgs, MonoArray *properties, MonoArray *propValues, MonoArray *fields, MonoArray* fieldValues) 
10742 {
10743         g_assert_not_reached ();
10744         return NULL;
10745 }
10746
10747 void
10748 mono_reflection_setup_internal_class (MonoReflectionTypeBuilder *tb)
10749 {
10750         g_assert_not_reached ();
10751 }
10752
10753 void
10754 mono_reflection_setup_generic_class (MonoReflectionTypeBuilder *tb)
10755 {
10756         g_assert_not_reached ();
10757 }
10758
10759 void
10760 mono_reflection_create_generic_class (MonoReflectionTypeBuilder *tb)
10761 {
10762         g_assert_not_reached ();
10763 }
10764
10765 void
10766 mono_reflection_create_internal_class (MonoReflectionTypeBuilder *tb)
10767 {
10768         g_assert_not_reached ();
10769 }
10770
10771 void
10772 mono_image_basic_init (MonoReflectionAssemblyBuilder *assemblyb)
10773 {
10774         g_error ("This mono runtime was configured with --enable-minimal=reflection_emit, so System.Reflection.Emit is not supported.");
10775 }
10776
10777 void
10778 mono_image_module_basic_init (MonoReflectionModuleBuilder *moduleb)
10779 {
10780         g_assert_not_reached ();
10781 }
10782
10783 MonoReflectionModule *
10784 mono_image_load_module_dynamic (MonoReflectionAssemblyBuilder *ab, MonoString *fileName)
10785 {
10786         g_assert_not_reached ();
10787         return NULL;
10788 }
10789
10790 guint32
10791 mono_image_insert_string (MonoReflectionModuleBuilder *module, MonoString *str)
10792 {
10793         g_assert_not_reached ();
10794         return 0;
10795 }
10796
10797 guint32
10798 mono_image_create_method_token (MonoDynamicImage *assembly, MonoObject *obj, MonoArray *opt_param_types)
10799 {
10800         g_assert_not_reached ();
10801         return 0;
10802 }
10803
10804 guint32
10805 mono_image_create_token (MonoDynamicImage *assembly, MonoObject *obj, 
10806                                                  gboolean create_methodspec, gboolean register_token)
10807 {
10808         g_assert_not_reached ();
10809         return 0;
10810 }
10811
10812 void
10813 mono_image_register_token (MonoDynamicImage *assembly, guint32 token, MonoObject *obj)
10814 {
10815 }
10816
10817 void
10818 mono_reflection_generic_class_initialize (MonoReflectionGenericClass *type, MonoArray *methods, 
10819                                           MonoArray *ctors, MonoArray *fields, MonoArray *properties,
10820                                           MonoArray *events)
10821 {
10822         g_assert_not_reached ();
10823 }
10824
10825 void
10826 mono_reflection_get_dynamic_overrides (MonoClass *klass, MonoMethod ***overrides, int *num_overrides)
10827 {
10828         *overrides = NULL;
10829         *num_overrides = 0;
10830 }
10831
10832 MonoReflectionEvent *
10833 mono_reflection_event_builder_get_event_info (MonoReflectionTypeBuilder *tb, MonoReflectionEventBuilder *eb)
10834 {
10835         g_assert_not_reached ();
10836         return NULL;
10837 }
10838
10839 MonoReflectionType*
10840 mono_reflection_create_runtime_class (MonoReflectionTypeBuilder *tb)
10841 {
10842         g_assert_not_reached ();
10843         return NULL;
10844 }
10845
10846 void
10847 mono_reflection_initialize_generic_parameter (MonoReflectionGenericParam *gparam)
10848 {
10849         g_assert_not_reached ();
10850 }
10851
10852 MonoArray *
10853 mono_reflection_sighelper_get_signature_local (MonoReflectionSigHelper *sig)
10854 {
10855         g_assert_not_reached ();
10856         return NULL;
10857 }
10858
10859 MonoArray *
10860 mono_reflection_sighelper_get_signature_field (MonoReflectionSigHelper *sig)
10861 {
10862         g_assert_not_reached ();
10863         return NULL;
10864 }
10865
10866 void 
10867 mono_reflection_create_dynamic_method (MonoReflectionDynamicMethod *mb)
10868 {
10869 }
10870
10871 gpointer
10872 mono_reflection_lookup_dynamic_token (MonoImage *image, guint32 token, gboolean valid_token, MonoClass **handle_class, MonoGenericContext *context)
10873 {
10874         return NULL;
10875 }
10876
10877 #endif /* DISABLE_REFLECTION_EMIT */
10878
10879 /* SECURITY_ACTION_* are defined in mono/metadata/tabledefs.h */
10880 const static guint32 declsec_flags_map[] = {
10881         0x00000000,                                     /* empty */
10882         MONO_DECLSEC_FLAG_REQUEST,                      /* SECURITY_ACTION_REQUEST                      (x01) */
10883         MONO_DECLSEC_FLAG_DEMAND,                       /* SECURITY_ACTION_DEMAND                       (x02) */
10884         MONO_DECLSEC_FLAG_ASSERT,                       /* SECURITY_ACTION_ASSERT                       (x03) */
10885         MONO_DECLSEC_FLAG_DENY,                         /* SECURITY_ACTION_DENY                         (x04) */
10886         MONO_DECLSEC_FLAG_PERMITONLY,                   /* SECURITY_ACTION_PERMITONLY                   (x05) */
10887         MONO_DECLSEC_FLAG_LINKDEMAND,                   /* SECURITY_ACTION_LINKDEMAND                   (x06) */
10888         MONO_DECLSEC_FLAG_INHERITANCEDEMAND,            /* SECURITY_ACTION_INHERITANCEDEMAND            (x07) */
10889         MONO_DECLSEC_FLAG_REQUEST_MINIMUM,              /* SECURITY_ACTION_REQUEST_MINIMUM              (x08) */
10890         MONO_DECLSEC_FLAG_REQUEST_OPTIONAL,             /* SECURITY_ACTION_REQUEST_OPTIONAL             (x09) */
10891         MONO_DECLSEC_FLAG_REQUEST_REFUSE,               /* SECURITY_ACTION_REQUEST_REFUSE               (x0A) */
10892         MONO_DECLSEC_FLAG_PREJIT_GRANT,                 /* SECURITY_ACTION_PREJIT_GRANT                 (x0B) */
10893         MONO_DECLSEC_FLAG_PREJIT_DENY,                  /* SECURITY_ACTION_PREJIT_DENY                  (x0C) */
10894         MONO_DECLSEC_FLAG_NONCAS_DEMAND,                /* SECURITY_ACTION_NONCAS_DEMAND                (x0D) */
10895         MONO_DECLSEC_FLAG_NONCAS_LINKDEMAND,            /* SECURITY_ACTION_NONCAS_LINKDEMAND            (x0E) */
10896         MONO_DECLSEC_FLAG_NONCAS_INHERITANCEDEMAND,     /* SECURITY_ACTION_NONCAS_INHERITANCEDEMAND     (x0F) */
10897         MONO_DECLSEC_FLAG_LINKDEMAND_CHOICE,            /* SECURITY_ACTION_LINKDEMAND_CHOICE            (x10) */
10898         MONO_DECLSEC_FLAG_INHERITANCEDEMAND_CHOICE,     /* SECURITY_ACTION_INHERITANCEDEMAND_CHOICE     (x11) */
10899         MONO_DECLSEC_FLAG_DEMAND_CHOICE,                /* SECURITY_ACTION_DEMAND_CHOICE                (x12) */
10900 };
10901
10902 /*
10903  * Returns flags that includes all available security action associated to the handle.
10904  * @token: metadata token (either for a class or a method)
10905  * @image: image where resides the metadata.
10906  */
10907 static guint32
10908 mono_declsec_get_flags (MonoImage *image, guint32 token)
10909 {
10910         int index = mono_metadata_declsec_from_index (image, token);
10911         MonoTableInfo *t = &image->tables [MONO_TABLE_DECLSECURITY];
10912         guint32 result = 0;
10913         guint32 action;
10914         int i;
10915
10916         /* HasSecurity can be present for other, not specially encoded, attributes,
10917            e.g. SuppressUnmanagedCodeSecurityAttribute */
10918         if (index < 0)
10919                 return 0;
10920
10921         for (i = index; i < t->rows; i++) {
10922                 guint32 cols [MONO_DECL_SECURITY_SIZE];
10923
10924                 mono_metadata_decode_row (t, i, cols, MONO_DECL_SECURITY_SIZE);
10925                 if (cols [MONO_DECL_SECURITY_PARENT] != token)
10926                         break;
10927
10928                 action = cols [MONO_DECL_SECURITY_ACTION];
10929                 if ((action >= MONO_DECLSEC_ACTION_MIN) && (action <= MONO_DECLSEC_ACTION_MAX)) {
10930                         result |= declsec_flags_map [action];
10931                 } else {
10932                         g_assert_not_reached ();
10933                 }
10934         }
10935         return result;
10936 }
10937
10938 /*
10939  * Get the security actions (in the form of flags) associated with the specified method.
10940  *
10941  * @method: The method for which we want the declarative security flags.
10942  * Return the declarative security flags for the method (only).
10943  *
10944  * Note: To keep MonoMethod size down we do not cache the declarative security flags
10945  *       (except for the stack modifiers which are kept in the MonoJitInfo structure)
10946  */
10947 guint32
10948 mono_declsec_flags_from_method (MonoMethod *method)
10949 {
10950         if (method->flags & METHOD_ATTRIBUTE_HAS_SECURITY) {
10951                 /* FIXME: No cache (for the moment) */
10952                 guint32 idx = mono_method_get_index (method);
10953                 idx <<= MONO_HAS_DECL_SECURITY_BITS;
10954                 idx |= MONO_HAS_DECL_SECURITY_METHODDEF;
10955                 return mono_declsec_get_flags (method->klass->image, idx);
10956         }
10957         return 0;
10958 }
10959
10960 /*
10961  * Get the security actions (in the form of flags) associated with the specified class.
10962  *
10963  * @klass: The class for which we want the declarative security flags.
10964  * Return the declarative security flags for the class.
10965  *
10966  * Note: We cache the flags inside the MonoClass structure as this will get 
10967  *       called very often (at least for each method).
10968  */
10969 guint32
10970 mono_declsec_flags_from_class (MonoClass *klass)
10971 {
10972         if (klass->flags & TYPE_ATTRIBUTE_HAS_SECURITY) {
10973                 if (!klass->ext || !klass->ext->declsec_flags) {
10974                         guint32 idx;
10975
10976                         idx = mono_metadata_token_index (klass->type_token);
10977                         idx <<= MONO_HAS_DECL_SECURITY_BITS;
10978                         idx |= MONO_HAS_DECL_SECURITY_TYPEDEF;
10979                         mono_loader_lock ();
10980                         mono_class_alloc_ext (klass);
10981                         mono_loader_unlock ();
10982                         /* we cache the flags on classes */
10983                         klass->ext->declsec_flags = mono_declsec_get_flags (klass->image, idx);
10984                 }
10985                 return klass->ext->declsec_flags;
10986         }
10987         return 0;
10988 }
10989
10990 /*
10991  * Get the security actions (in the form of flags) associated with the specified assembly.
10992  *
10993  * @assembly: The assembly for which we want the declarative security flags.
10994  * Return the declarative security flags for the assembly.
10995  */
10996 guint32
10997 mono_declsec_flags_from_assembly (MonoAssembly *assembly)
10998 {
10999         guint32 idx = 1; /* there is only one assembly */
11000         idx <<= MONO_HAS_DECL_SECURITY_BITS;
11001         idx |= MONO_HAS_DECL_SECURITY_ASSEMBLY;
11002         return mono_declsec_get_flags (assembly->image, idx);
11003 }
11004
11005
11006 /*
11007  * Fill actions for the specific index (which may either be an encoded class token or
11008  * an encoded method token) from the metadata image.
11009  * Returns TRUE if some actions requiring code generation are present, FALSE otherwise.
11010  */
11011 static MonoBoolean
11012 fill_actions_from_index (MonoImage *image, guint32 token, MonoDeclSecurityActions* actions,
11013         guint32 id_std, guint32 id_noncas, guint32 id_choice)
11014 {
11015         MonoBoolean result = FALSE;
11016         MonoTableInfo *t;
11017         guint32 cols [MONO_DECL_SECURITY_SIZE];
11018         int index = mono_metadata_declsec_from_index (image, token);
11019         int i;
11020
11021         t  = &image->tables [MONO_TABLE_DECLSECURITY];
11022         for (i = index; i < t->rows; i++) {
11023                 mono_metadata_decode_row (t, i, cols, MONO_DECL_SECURITY_SIZE);
11024
11025                 if (cols [MONO_DECL_SECURITY_PARENT] != token)
11026                         return result;
11027
11028                 /* if present only replace (class) permissions with method permissions */
11029                 /* if empty accept either class or method permissions */
11030                 if (cols [MONO_DECL_SECURITY_ACTION] == id_std) {
11031                         if (!actions->demand.blob) {
11032                                 const char *blob = mono_metadata_blob_heap (image, cols [MONO_DECL_SECURITY_PERMISSIONSET]);
11033                                 actions->demand.index = cols [MONO_DECL_SECURITY_PERMISSIONSET];
11034                                 actions->demand.blob = (char*) (blob + 2);
11035                                 actions->demand.size = mono_metadata_decode_blob_size (blob, &blob);
11036                                 result = TRUE;
11037                         }
11038                 } else if (cols [MONO_DECL_SECURITY_ACTION] == id_noncas) {
11039                         if (!actions->noncasdemand.blob) {
11040                                 const char *blob = mono_metadata_blob_heap (image, cols [MONO_DECL_SECURITY_PERMISSIONSET]);
11041                                 actions->noncasdemand.index = cols [MONO_DECL_SECURITY_PERMISSIONSET];
11042                                 actions->noncasdemand.blob = (char*) (blob + 2);
11043                                 actions->noncasdemand.size = mono_metadata_decode_blob_size (blob, &blob);
11044                                 result = TRUE;
11045                         }
11046                 } else if (cols [MONO_DECL_SECURITY_ACTION] == id_choice) {
11047                         if (!actions->demandchoice.blob) {
11048                                 const char *blob = mono_metadata_blob_heap (image, cols [MONO_DECL_SECURITY_PERMISSIONSET]);
11049                                 actions->demandchoice.index = cols [MONO_DECL_SECURITY_PERMISSIONSET];
11050                                 actions->demandchoice.blob = (char*) (blob + 2);
11051                                 actions->demandchoice.size = mono_metadata_decode_blob_size (blob, &blob);
11052                                 result = TRUE;
11053                         }
11054                 }
11055         }
11056
11057         return result;
11058 }
11059
11060 static MonoBoolean
11061 mono_declsec_get_class_demands_params (MonoClass *klass, MonoDeclSecurityActions* demands, 
11062         guint32 id_std, guint32 id_noncas, guint32 id_choice)
11063 {
11064         guint32 idx = mono_metadata_token_index (klass->type_token);
11065         idx <<= MONO_HAS_DECL_SECURITY_BITS;
11066         idx |= MONO_HAS_DECL_SECURITY_TYPEDEF;
11067         return fill_actions_from_index (klass->image, idx, demands, id_std, id_noncas, id_choice);
11068 }
11069
11070 static MonoBoolean
11071 mono_declsec_get_method_demands_params (MonoMethod *method, MonoDeclSecurityActions* demands, 
11072         guint32 id_std, guint32 id_noncas, guint32 id_choice)
11073 {
11074         guint32 idx = mono_method_get_index (method);
11075         idx <<= MONO_HAS_DECL_SECURITY_BITS;
11076         idx |= MONO_HAS_DECL_SECURITY_METHODDEF;
11077         return fill_actions_from_index (method->klass->image, idx, demands, id_std, id_noncas, id_choice);
11078 }
11079
11080 /*
11081  * Collect all actions (that requires to generate code in mini) assigned for
11082  * the specified method.
11083  * Note: Don't use the content of actions if the function return FALSE.
11084  */
11085 MonoBoolean
11086 mono_declsec_get_demands (MonoMethod *method, MonoDeclSecurityActions* demands)
11087 {
11088         guint32 mask = MONO_DECLSEC_FLAG_DEMAND | MONO_DECLSEC_FLAG_NONCAS_DEMAND | 
11089                 MONO_DECLSEC_FLAG_DEMAND_CHOICE;
11090         MonoBoolean result = FALSE;
11091         guint32 flags;
11092
11093         /* quick exit if no declarative security is present in the metadata */
11094         if (!method->klass->image->tables [MONO_TABLE_DECLSECURITY].rows)
11095                 return FALSE;
11096
11097         /* we want the original as the wrapper is "free" of the security informations */
11098         if (method->wrapper_type == MONO_WRAPPER_MANAGED_TO_NATIVE || method->wrapper_type == MONO_WRAPPER_MANAGED_TO_MANAGED) {
11099                 method = mono_marshal_method_from_wrapper (method);
11100                 if (!method)
11101                         return FALSE;
11102         }
11103
11104         /* First we look for method-level attributes */
11105         if (method->flags & METHOD_ATTRIBUTE_HAS_SECURITY) {
11106                 mono_class_init (method->klass);
11107                 memset (demands, 0, sizeof (MonoDeclSecurityActions));
11108
11109                 result = mono_declsec_get_method_demands_params (method, demands, 
11110                         SECURITY_ACTION_DEMAND, SECURITY_ACTION_NONCASDEMAND, SECURITY_ACTION_DEMANDCHOICE);
11111         }
11112
11113         /* Here we use (or create) the class declarative cache to look for demands */
11114         flags = mono_declsec_flags_from_class (method->klass);
11115         if (flags & mask) {
11116                 if (!result) {
11117                         mono_class_init (method->klass);
11118                         memset (demands, 0, sizeof (MonoDeclSecurityActions));
11119                 }
11120                 result |= mono_declsec_get_class_demands_params (method->klass, demands, 
11121                         SECURITY_ACTION_DEMAND, SECURITY_ACTION_NONCASDEMAND, SECURITY_ACTION_DEMANDCHOICE);
11122         }
11123
11124         /* The boolean return value is used as a shortcut in case nothing needs to
11125            be generated (e.g. LinkDemand[Choice] and InheritanceDemand[Choice]) */
11126         return result;
11127 }
11128
11129
11130 /*
11131  * Collect all Link actions: LinkDemand, NonCasLinkDemand and LinkDemandChoice (2.0).
11132  *
11133  * Note: Don't use the content of actions if the function return FALSE.
11134  */
11135 MonoBoolean
11136 mono_declsec_get_linkdemands (MonoMethod *method, MonoDeclSecurityActions* klass, MonoDeclSecurityActions *cmethod)
11137 {
11138         MonoBoolean result = FALSE;
11139         guint32 flags;
11140
11141         /* quick exit if no declarative security is present in the metadata */
11142         if (!method->klass->image->tables [MONO_TABLE_DECLSECURITY].rows)
11143                 return FALSE;
11144
11145         /* we want the original as the wrapper is "free" of the security informations */
11146         if (method->wrapper_type == MONO_WRAPPER_MANAGED_TO_NATIVE || method->wrapper_type == MONO_WRAPPER_MANAGED_TO_MANAGED) {
11147                 method = mono_marshal_method_from_wrapper (method);
11148                 if (!method)
11149                         return FALSE;
11150         }
11151
11152         /* results are independant - zeroize both */
11153         memset (cmethod, 0, sizeof (MonoDeclSecurityActions));
11154         memset (klass, 0, sizeof (MonoDeclSecurityActions));
11155
11156         /* First we look for method-level attributes */
11157         if (method->flags & METHOD_ATTRIBUTE_HAS_SECURITY) {
11158                 mono_class_init (method->klass);
11159
11160                 result = mono_declsec_get_method_demands_params (method, cmethod, 
11161                         SECURITY_ACTION_LINKDEMAND, SECURITY_ACTION_NONCASLINKDEMAND, SECURITY_ACTION_LINKDEMANDCHOICE);
11162         }
11163
11164         /* Here we use (or create) the class declarative cache to look for demands */
11165         flags = mono_declsec_flags_from_class (method->klass);
11166         if (flags & (MONO_DECLSEC_FLAG_LINKDEMAND | MONO_DECLSEC_FLAG_NONCAS_LINKDEMAND | MONO_DECLSEC_FLAG_LINKDEMAND_CHOICE)) {
11167                 mono_class_init (method->klass);
11168
11169                 result |= mono_declsec_get_class_demands_params (method->klass, klass, 
11170                         SECURITY_ACTION_LINKDEMAND, SECURITY_ACTION_NONCASLINKDEMAND, SECURITY_ACTION_LINKDEMANDCHOICE);
11171         }
11172
11173         return result;
11174 }
11175
11176 /*
11177  * Collect all Inherit actions: InheritanceDemand, NonCasInheritanceDemand and InheritanceDemandChoice (2.0).
11178  *
11179  * @klass       The inherited class - this is the class that provides the security check (attributes)
11180  * @demans      
11181  * return TRUE if inheritance demands (any kind) are present, FALSE otherwise.
11182  * 
11183  * Note: Don't use the content of actions if the function return FALSE.
11184  */
11185 MonoBoolean
11186 mono_declsec_get_inheritdemands_class (MonoClass *klass, MonoDeclSecurityActions* demands)
11187 {
11188         MonoBoolean result = FALSE;
11189         guint32 flags;
11190
11191         /* quick exit if no declarative security is present in the metadata */
11192         if (!klass->image->tables [MONO_TABLE_DECLSECURITY].rows)
11193                 return FALSE;
11194
11195         /* Here we use (or create) the class declarative cache to look for demands */
11196         flags = mono_declsec_flags_from_class (klass);
11197         if (flags & (MONO_DECLSEC_FLAG_INHERITANCEDEMAND | MONO_DECLSEC_FLAG_NONCAS_INHERITANCEDEMAND | MONO_DECLSEC_FLAG_INHERITANCEDEMAND_CHOICE)) {
11198                 mono_class_init (klass);
11199                 memset (demands, 0, sizeof (MonoDeclSecurityActions));
11200
11201                 result |= mono_declsec_get_class_demands_params (klass, demands, 
11202                         SECURITY_ACTION_INHERITDEMAND, SECURITY_ACTION_NONCASINHERITANCE, SECURITY_ACTION_INHERITDEMANDCHOICE);
11203         }
11204
11205         return result;
11206 }
11207
11208 /*
11209  * Collect all Inherit actions: InheritanceDemand, NonCasInheritanceDemand and InheritanceDemandChoice (2.0).
11210  *
11211  * Note: Don't use the content of actions if the function return FALSE.
11212  */
11213 MonoBoolean
11214 mono_declsec_get_inheritdemands_method (MonoMethod *method, MonoDeclSecurityActions* demands)
11215 {
11216         /* quick exit if no declarative security is present in the metadata */
11217         if (!method->klass->image->tables [MONO_TABLE_DECLSECURITY].rows)
11218                 return FALSE;
11219
11220         /* we want the original as the wrapper is "free" of the security informations */
11221         if (method->wrapper_type == MONO_WRAPPER_MANAGED_TO_NATIVE || method->wrapper_type == MONO_WRAPPER_MANAGED_TO_MANAGED) {
11222                 method = mono_marshal_method_from_wrapper (method);
11223                 if (!method)
11224                         return FALSE;
11225         }
11226
11227         if (method->flags & METHOD_ATTRIBUTE_HAS_SECURITY) {
11228                 mono_class_init (method->klass);
11229                 memset (demands, 0, sizeof (MonoDeclSecurityActions));
11230
11231                 return mono_declsec_get_method_demands_params (method, demands, 
11232                         SECURITY_ACTION_INHERITDEMAND, SECURITY_ACTION_NONCASINHERITANCE, SECURITY_ACTION_INHERITDEMANDCHOICE);
11233         }
11234         return FALSE;
11235 }
11236
11237
11238 static MonoBoolean
11239 get_declsec_action (MonoImage *image, guint32 token, guint32 action, MonoDeclSecurityEntry *entry)
11240 {
11241         guint32 cols [MONO_DECL_SECURITY_SIZE];
11242         MonoTableInfo *t;
11243         int i;
11244
11245         int index = mono_metadata_declsec_from_index (image, token);
11246         if (index == -1)
11247                 return FALSE;
11248
11249         t =  &image->tables [MONO_TABLE_DECLSECURITY];
11250         for (i = index; i < t->rows; i++) {
11251                 mono_metadata_decode_row (t, i, cols, MONO_DECL_SECURITY_SIZE);
11252
11253                 /* shortcut - index are ordered */
11254                 if (token != cols [MONO_DECL_SECURITY_PARENT])
11255                         return FALSE;
11256
11257                 if (cols [MONO_DECL_SECURITY_ACTION] == action) {
11258                         const char *metadata = mono_metadata_blob_heap (image, cols [MONO_DECL_SECURITY_PERMISSIONSET]);
11259                         entry->blob = (char*) (metadata + 2);
11260                         entry->size = mono_metadata_decode_blob_size (metadata, &metadata);
11261                         return TRUE;
11262                 }
11263         }
11264
11265         return FALSE;
11266 }
11267
11268 MonoBoolean
11269 mono_declsec_get_method_action (MonoMethod *method, guint32 action, MonoDeclSecurityEntry *entry)
11270 {
11271         if (method->flags & METHOD_ATTRIBUTE_HAS_SECURITY) {
11272                 guint32 idx = mono_method_get_index (method);
11273                 idx <<= MONO_HAS_DECL_SECURITY_BITS;
11274                 idx |= MONO_HAS_DECL_SECURITY_METHODDEF;
11275                 return get_declsec_action (method->klass->image, idx, action, entry);
11276         }
11277         return FALSE;
11278 }
11279
11280 MonoBoolean
11281 mono_declsec_get_class_action (MonoClass *klass, guint32 action, MonoDeclSecurityEntry *entry)
11282 {
11283         /* use cache */
11284         guint32 flags = mono_declsec_flags_from_class (klass);
11285         if (declsec_flags_map [action] & flags) {
11286                 guint32 idx = mono_metadata_token_index (klass->type_token);
11287                 idx <<= MONO_HAS_DECL_SECURITY_BITS;
11288                 idx |= MONO_HAS_DECL_SECURITY_TYPEDEF;
11289                 return get_declsec_action (klass->image, idx, action, entry);
11290         }
11291         return FALSE;
11292 }
11293
11294 MonoBoolean
11295 mono_declsec_get_assembly_action (MonoAssembly *assembly, guint32 action, MonoDeclSecurityEntry *entry)
11296 {
11297         guint32 idx = 1; /* there is only one assembly */
11298         idx <<= MONO_HAS_DECL_SECURITY_BITS;
11299         idx |= MONO_HAS_DECL_SECURITY_ASSEMBLY;
11300
11301         return get_declsec_action (assembly->image, idx, action, entry);
11302 }
11303
11304 gboolean
11305 mono_reflection_call_is_assignable_to (MonoClass *klass, MonoClass *oklass)
11306 {
11307         MonoObject *res, *exc;
11308         void *params [1];
11309         static MonoClass *System_Reflection_Emit_TypeBuilder = NULL;
11310         static MonoMethod *method = NULL;
11311
11312         if (!System_Reflection_Emit_TypeBuilder) {
11313                 System_Reflection_Emit_TypeBuilder = mono_class_from_name (mono_defaults.corlib, "System.Reflection.Emit", "TypeBuilder");
11314                 g_assert (System_Reflection_Emit_TypeBuilder);
11315         }
11316         if (method == NULL) {
11317                 method = mono_class_get_method_from_name (System_Reflection_Emit_TypeBuilder, "IsAssignableTo", 1);
11318                 g_assert (method);
11319         }
11320
11321         /* 
11322          * The result of mono_type_get_object () might be a System.MonoType but we
11323          * need a TypeBuilder so use klass->reflection_info.
11324          */
11325         g_assert (klass->reflection_info);
11326         g_assert (!strcmp (((MonoObject*)(klass->reflection_info))->vtable->klass->name, "TypeBuilder"));
11327
11328         params [0] = mono_type_get_object (mono_domain_get (), &oklass->byval_arg);
11329
11330         res = mono_runtime_invoke (method, (MonoObject*)(klass->reflection_info), params, &exc);
11331         if (exc)
11332                 return FALSE;
11333         else
11334                 return *(MonoBoolean*)mono_object_unbox (res);
11335 }