Merge pull request #1857 from slluis/fix-assembly-resolver
[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  * Copyright 2011 Rodrigo Kumpera
10  *
11  */
12 #include <config.h>
13 #include "mono/utils/mono-digest.h"
14 #include "mono/utils/mono-membar.h"
15 #include "mono/metadata/reflection-internals.h"
16 #include "mono/metadata/tabledefs.h"
17 #include "mono/metadata/metadata-internals.h"
18 #include <mono/metadata/profiler-private.h>
19 #include "mono/metadata/class-internals.h"
20 #include "mono/metadata/gc-internal.h"
21 #include "mono/metadata/tokentype.h"
22 #include "mono/metadata/domain-internals.h"
23 #include "mono/metadata/opcodes.h"
24 #include "mono/metadata/assembly.h"
25 #include "mono/metadata/object-internals.h"
26 #include <mono/metadata/exception.h>
27 #include <mono/metadata/marshal.h>
28 #include <mono/metadata/security-manager.h>
29 #include <stdio.h>
30 #include <glib.h>
31 #include <errno.h>
32 #include <time.h>
33 #include <string.h>
34 #include <ctype.h>
35 #include "image.h"
36 #include "cil-coff.h"
37 #include "mono-endian.h"
38 #include <mono/metadata/gc-internal.h>
39 #include <mono/metadata/mempool-internals.h>
40 #include <mono/metadata/security-core-clr.h>
41 #include <mono/metadata/debug-helpers.h>
42 #include <mono/metadata/verify-internals.h>
43 #include <mono/metadata/mono-ptr-array.h>
44 #include <mono/utils/mono-string.h>
45 #include <mono/utils/mono-error-internals.h>
46
47 static gboolean is_usertype (MonoReflectionType *ref);
48 static MonoReflectionType *mono_reflection_type_resolve_user_types (MonoReflectionType *type);
49
50 typedef struct {
51         char *p;
52         char *buf;
53         char *end;
54 } SigBuffer;
55
56 #define TEXT_OFFSET 512
57 #define CLI_H_SIZE 136
58 #define FILE_ALIGN 512
59 #define VIRT_ALIGN 8192
60 #define START_TEXT_RVA  0x00002000
61
62 typedef struct {
63         MonoReflectionILGen *ilgen;
64         MonoReflectionType *rtype;
65         MonoArray *parameters;
66         MonoArray *generic_params;
67         MonoGenericContainer *generic_container;
68         MonoArray *pinfo;
69         MonoArray *opt_types;
70         guint32 attrs;
71         guint32 iattrs;
72         guint32 call_conv;
73         guint32 *table_idx; /* note: it's a pointer */
74         MonoArray *code;
75         MonoObject *type;
76         MonoString *name;
77         MonoBoolean init_locals;
78         MonoBoolean skip_visibility;
79         MonoArray *return_modreq;
80         MonoArray *return_modopt;
81         MonoArray *param_modreq;
82         MonoArray *param_modopt;
83         MonoArray *permissions;
84         MonoMethod *mhandle;
85         guint32 nrefs;
86         gpointer *refs;
87         /* for PInvoke */
88         int charset, extra_flags, native_cc;
89         MonoString *dll, *dllentry;
90 } ReflectionMethodBuilder;
91
92 typedef struct {
93         guint32 owner;
94         MonoReflectionGenericParam *gparam;
95 } GenericParamTableEntry;
96
97 const unsigned char table_sizes [MONO_TABLE_NUM] = {
98         MONO_MODULE_SIZE,
99         MONO_TYPEREF_SIZE,
100         MONO_TYPEDEF_SIZE,
101         0,
102         MONO_FIELD_SIZE,
103         0,
104         MONO_METHOD_SIZE,
105         0,
106         MONO_PARAM_SIZE,
107         MONO_INTERFACEIMPL_SIZE,
108         MONO_MEMBERREF_SIZE,    /* 0x0A */
109         MONO_CONSTANT_SIZE,
110         MONO_CUSTOM_ATTR_SIZE,
111         MONO_FIELD_MARSHAL_SIZE,
112         MONO_DECL_SECURITY_SIZE,
113         MONO_CLASS_LAYOUT_SIZE,
114         MONO_FIELD_LAYOUT_SIZE, /* 0x10 */
115         MONO_STAND_ALONE_SIGNATURE_SIZE,
116         MONO_EVENT_MAP_SIZE,
117         0,
118         MONO_EVENT_SIZE,
119         MONO_PROPERTY_MAP_SIZE,
120         0,
121         MONO_PROPERTY_SIZE,
122         MONO_METHOD_SEMA_SIZE,
123         MONO_METHODIMPL_SIZE,
124         MONO_MODULEREF_SIZE,    /* 0x1A */
125         MONO_TYPESPEC_SIZE,
126         MONO_IMPLMAP_SIZE,      
127         MONO_FIELD_RVA_SIZE,
128         0,
129         0,
130         MONO_ASSEMBLY_SIZE,     /* 0x20 */
131         MONO_ASSEMBLY_PROCESSOR_SIZE,
132         MONO_ASSEMBLYOS_SIZE,
133         MONO_ASSEMBLYREF_SIZE,
134         MONO_ASSEMBLYREFPROC_SIZE,
135         MONO_ASSEMBLYREFOS_SIZE,
136         MONO_FILE_SIZE,
137         MONO_EXP_TYPE_SIZE,
138         MONO_MANIFEST_SIZE,
139         MONO_NESTED_CLASS_SIZE,
140
141         MONO_GENERICPARAM_SIZE, /* 0x2A */
142         MONO_METHODSPEC_SIZE,
143         MONO_GENPARCONSTRAINT_SIZE
144
145 };
146
147 #ifndef DISABLE_REFLECTION_EMIT
148 static guint32 mono_image_get_methodref_token (MonoDynamicImage *assembly, MonoMethod *method, gboolean create_typespec);
149 static guint32 mono_image_get_methodbuilder_token (MonoDynamicImage *assembly, MonoReflectionMethodBuilder *mb, gboolean create_open_instance);
150 static guint32 mono_image_get_ctorbuilder_token (MonoDynamicImage *assembly, MonoReflectionCtorBuilder *cb);
151 static guint32 mono_image_get_sighelper_token (MonoDynamicImage *assembly, MonoReflectionSigHelper *helper);
152 static void    ensure_runtime_vtable (MonoClass *klass);
153 static gpointer resolve_object (MonoImage *image, MonoObject *obj, MonoClass **handle_class, MonoGenericContext *context);
154 static guint32 mono_image_get_methodref_token_for_methodbuilder (MonoDynamicImage *assembly, MonoReflectionMethodBuilder *method);
155 static guint32 encode_generic_method_sig (MonoDynamicImage *assembly, MonoGenericContext *context);
156 static gpointer register_assembly (MonoDomain *domain, MonoReflectionAssembly *res, MonoAssembly *assembly);
157 static void reflection_methodbuilder_from_method_builder (ReflectionMethodBuilder *rmb, MonoReflectionMethodBuilder *mb);
158 static void reflection_methodbuilder_from_ctor_builder (ReflectionMethodBuilder *rmb, MonoReflectionCtorBuilder *mb);
159 static guint32 create_generic_typespec (MonoDynamicImage *assembly, MonoReflectionTypeBuilder *tb);
160 #endif
161
162 static guint32 mono_image_typedef_or_ref (MonoDynamicImage *assembly, MonoType *type);
163 static guint32 mono_image_typedef_or_ref_full (MonoDynamicImage *assembly, MonoType *type, gboolean try_typespec);
164 static void    mono_image_get_generic_param_info (MonoReflectionGenericParam *gparam, guint32 owner, MonoDynamicImage *assembly);
165 static guint32 encode_marshal_blob (MonoDynamicImage *assembly, MonoReflectionMarshal *minfo);
166 static guint32 encode_constant (MonoDynamicImage *assembly, MonoObject *val, guint32 *ret_type);
167 static char*   type_get_qualified_name (MonoType *type, MonoAssembly *ass);
168 static void    encode_type (MonoDynamicImage *assembly, MonoType *type, SigBuffer *buf);
169 static void get_default_param_value_blobs (MonoMethod *method, char **blobs, guint32 *types);
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 MonoReflectionType* mono_reflection_type_resolve_user_types (MonoReflectionType *type);
173 static gboolean is_sre_array (MonoClass *class);
174 static gboolean is_sre_byref (MonoClass *class);
175 static gboolean is_sre_pointer (MonoClass *class);
176 static gboolean is_sre_type_builder (MonoClass *class);
177 static gboolean is_sre_method_builder (MonoClass *class);
178 static gboolean is_sre_ctor_builder (MonoClass *class);
179 static gboolean is_sre_field_builder (MonoClass *class);
180 static gboolean is_sr_mono_method (MonoClass *class);
181 static gboolean is_sr_mono_cmethod (MonoClass *class);
182 static gboolean is_sr_mono_generic_method (MonoClass *class);
183 static gboolean is_sr_mono_generic_cmethod (MonoClass *class);
184 static gboolean is_sr_mono_field (MonoClass *class);
185 static gboolean is_sr_mono_property (MonoClass *class);
186 static gboolean is_sre_method_on_tb_inst (MonoClass *class);
187 static gboolean is_sre_ctor_on_tb_inst (MonoClass *class);
188
189 static guint32 mono_image_get_methodspec_token (MonoDynamicImage *assembly, MonoMethod *method);
190 static guint32 mono_image_get_inflated_method_token (MonoDynamicImage *assembly, MonoMethod *m);
191 static MonoMethod * inflate_method (MonoReflectionType *type, MonoObject *obj);
192
193 static guint32 create_typespec (MonoDynamicImage *assembly, MonoType *type);
194 static void init_type_builder_generics (MonoObject *type);
195
196 #define RESOLVE_TYPE(type) do { type = (void*)mono_reflection_type_resolve_user_types ((MonoReflectionType*)type); } while (0)
197 #define RESOLVE_ARRAY_TYPE_ELEMENT(array, index) do {   \
198         MonoReflectionType *__type = mono_array_get (array, MonoReflectionType*, index);        \
199         __type = mono_reflection_type_resolve_user_types (__type);      \
200         mono_array_set (arr, MonoReflectionType*, index, __type);       \
201 } while (0)
202
203 #define mono_type_array_get_and_resolve(array, index) mono_reflection_type_get_handle ((MonoReflectionType*)mono_array_get (array, gpointer, index))
204
205 #define CHECK_ADD4_OVERFLOW_UN(a, b) ((guint32)(0xFFFFFFFFU) - (guint32)(b) < (guint32)(a))
206 #define CHECK_ADD8_OVERFLOW_UN(a, b) ((guint64)(0xFFFFFFFFFFFFFFFFUL) - (guint64)(b) < (guint64)(a))
207
208 #if SIZEOF_VOID_P == 4
209 #define CHECK_ADDP_OVERFLOW_UN(a,b) CHECK_ADD4_OVERFLOW_UN(a, b)
210 #else
211 #define CHECK_ADDP_OVERFLOW_UN(a,b) CHECK_ADD8_OVERFLOW_UN(a, b)
212 #endif
213
214 #define ADDP_IS_GREATER_OR_OVF(a, b, c) (((a) + (b) > (c)) || CHECK_ADDP_OVERFLOW_UN (a, b))
215 #define ADD_IS_GREATER_OR_OVF(a, b, c) (((a) + (b) > (c)) || CHECK_ADD4_OVERFLOW_UN (a, b))
216
217
218 void
219 mono_reflection_init (void)
220 {
221 }
222
223 static inline void
224 dynamic_image_lock (MonoDynamicImage *image)
225 {
226         mono_image_lock ((MonoImage*)image);
227 }
228
229 static inline void
230 dynamic_image_unlock (MonoDynamicImage *image)
231 {
232         mono_image_unlock ((MonoImage*)image);
233 }
234
235 static void
236 register_dyn_token (MonoDynamicImage *assembly, guint32 token, MonoObject *obj)
237 {
238         dynamic_image_lock (assembly);
239         mono_g_hash_table_insert (assembly->tokens, GUINT_TO_POINTER (token), obj);
240         dynamic_image_unlock (assembly);
241 }
242
243 static MonoObject*
244 lookup_dyn_token (MonoDynamicImage *assembly, guint32 token)
245 {
246         MonoObject *obj;
247
248         dynamic_image_lock (assembly);
249         obj = mono_g_hash_table_lookup (assembly->tokens, GUINT_TO_POINTER (token));
250         dynamic_image_unlock (assembly);
251
252         return obj;
253 }
254
255 static void
256 sigbuffer_init (SigBuffer *buf, int size)
257 {
258         buf->buf = g_malloc (size);
259         buf->p = buf->buf;
260         buf->end = buf->buf + size;
261 }
262
263 static void
264 sigbuffer_make_room (SigBuffer *buf, int size)
265 {
266         if (buf->end - buf->p < size) {
267                 int new_size = buf->end - buf->buf + size + 32;
268                 char *p = g_realloc (buf->buf, new_size);
269                 size = buf->p - buf->buf;
270                 buf->buf = p;
271                 buf->p = p + size;
272                 buf->end = buf->buf + new_size;
273         }
274 }
275
276 static void
277 sigbuffer_add_value (SigBuffer *buf, guint32 val)
278 {
279         sigbuffer_make_room (buf, 6);
280         mono_metadata_encode_value (val, buf->p, &buf->p);
281 }
282
283 static void
284 sigbuffer_add_byte (SigBuffer *buf, guint8 val)
285 {
286         sigbuffer_make_room (buf, 1);
287         buf->p [0] = val;
288         buf->p++;
289 }
290
291 static void
292 sigbuffer_add_mem (SigBuffer *buf, char *p, guint32 size)
293 {
294         sigbuffer_make_room (buf, size);
295         memcpy (buf->p, p, size);
296         buf->p += size;
297 }
298
299 static void
300 sigbuffer_free (SigBuffer *buf)
301 {
302         g_free (buf->buf);
303 }
304
305 #ifndef DISABLE_REFLECTION_EMIT
306 /**
307  * mp_g_alloc:
308  *
309  * Allocate memory from the @image mempool if it is non-NULL. Otherwise, allocate memory
310  * from the C heap.
311  */
312 static gpointer
313 image_g_malloc (MonoImage *image, guint size)
314 {
315         if (image)
316                 return mono_image_alloc (image, size);
317         else
318                 return g_malloc (size);
319 }
320 #endif /* !DISABLE_REFLECTION_EMIT */
321
322 /**
323  * image_g_alloc0:
324  *
325  * Allocate memory from the @image mempool if it is non-NULL. Otherwise, allocate memory
326  * from the C heap.
327  */
328 static gpointer
329 image_g_malloc0 (MonoImage *image, guint size)
330 {
331         if (image)
332                 return mono_image_alloc0 (image, size);
333         else
334                 return g_malloc0 (size);
335 }
336
337 #ifndef DISABLE_REFLECTION_EMIT
338 static char*
339 image_strdup (MonoImage *image, const char *s)
340 {
341         if (image)
342                 return mono_image_strdup (image, s);
343         else
344                 return g_strdup (s);
345 }
346 #endif
347
348 #define image_g_new(image,struct_type, n_structs)               \
349     ((struct_type *) image_g_malloc (image, ((gsize) sizeof (struct_type)) * ((gsize) (n_structs))))
350
351 #define image_g_new0(image,struct_type, n_structs)              \
352     ((struct_type *) image_g_malloc0 (image, ((gsize) sizeof (struct_type)) * ((gsize) (n_structs))))
353
354
355 static void
356 alloc_table (MonoDynamicTable *table, guint nrows)
357 {
358         table->rows = nrows;
359         g_assert (table->columns);
360         if (nrows + 1 >= table->alloc_rows) {
361                 while (nrows + 1 >= table->alloc_rows) {
362                         if (table->alloc_rows == 0)
363                                 table->alloc_rows = 16;
364                         else
365                                 table->alloc_rows *= 2;
366                 }
367
368                 table->values = g_renew (guint32, table->values, (table->alloc_rows) * table->columns);
369         }
370 }
371
372 static void
373 make_room_in_stream (MonoDynamicStream *stream, int size)
374 {
375         if (size <= stream->alloc_size)
376                 return;
377         
378         while (stream->alloc_size <= size) {
379                 if (stream->alloc_size < 4096)
380                         stream->alloc_size = 4096;
381                 else
382                         stream->alloc_size *= 2;
383         }
384         
385         stream->data = g_realloc (stream->data, stream->alloc_size);
386 }
387
388 static guint32
389 string_heap_insert (MonoDynamicStream *sh, const char *str)
390 {
391         guint32 idx;
392         guint32 len;
393         gpointer oldkey, oldval;
394
395         if (g_hash_table_lookup_extended (sh->hash, str, &oldkey, &oldval))
396                 return GPOINTER_TO_UINT (oldval);
397
398         len = strlen (str) + 1;
399         idx = sh->index;
400         
401         make_room_in_stream (sh, idx + len);
402
403         /*
404          * We strdup the string even if we already copy them in sh->data
405          * so that the string pointers in the hash remain valid even if
406          * we need to realloc sh->data. We may want to avoid that later.
407          */
408         g_hash_table_insert (sh->hash, g_strdup (str), GUINT_TO_POINTER (idx));
409         memcpy (sh->data + idx, str, len);
410         sh->index += len;
411         return idx;
412 }
413
414 static guint32
415 string_heap_insert_mstring (MonoDynamicStream *sh, MonoString *str)
416 {
417         char *name = mono_string_to_utf8 (str);
418         guint32 idx;
419         idx = string_heap_insert (sh, name);
420         g_free (name);
421         return idx;
422 }
423
424 #ifndef DISABLE_REFLECTION_EMIT
425 static void
426 string_heap_init (MonoDynamicStream *sh)
427 {
428         sh->index = 0;
429         sh->alloc_size = 4096;
430         sh->data = g_malloc (4096);
431         sh->hash = g_hash_table_new_full (g_str_hash, g_str_equal, g_free, NULL);
432         string_heap_insert (sh, "");
433 }
434 #endif
435
436 static guint32
437 mono_image_add_stream_data (MonoDynamicStream *stream, const char *data, guint32 len)
438 {
439         guint32 idx;
440         
441         make_room_in_stream (stream, stream->index + len);
442         memcpy (stream->data + stream->index, data, len);
443         idx = stream->index;
444         stream->index += len;
445         /* 
446          * align index? Not without adding an additional param that controls it since
447          * we may store a blob value in pieces.
448          */
449         return idx;
450 }
451
452 static guint32
453 mono_image_add_stream_zero (MonoDynamicStream *stream, guint32 len)
454 {
455         guint32 idx;
456         
457         make_room_in_stream (stream, stream->index + len);
458         memset (stream->data + stream->index, 0, len);
459         idx = stream->index;
460         stream->index += len;
461         return idx;
462 }
463
464 static void
465 stream_data_align (MonoDynamicStream *stream)
466 {
467         char buf [4] = {0};
468         guint32 count = stream->index % 4;
469
470         /* we assume the stream data will be aligned */
471         if (count)
472                 mono_image_add_stream_data (stream, buf, 4 - count);
473 }
474
475 #ifndef DISABLE_REFLECTION_EMIT
476 static int
477 mono_blob_entry_hash (const char* str)
478 {
479         guint len, h;
480         const char *end;
481         len = mono_metadata_decode_blob_size (str, &str);
482         if (len > 0) {
483                 end = str + len;
484                 h = *str;
485                 for (str += 1; str < end; str++)
486                         h = (h << 5) - h + *str;
487                 return h;
488         } else {
489                 return 0;
490         }
491 }
492
493 static gboolean
494 mono_blob_entry_equal (const char *str1, const char *str2) {
495         int len, len2;
496         const char *end1;
497         const char *end2;
498         len = mono_metadata_decode_blob_size (str1, &end1);
499         len2 = mono_metadata_decode_blob_size (str2, &end2);
500         if (len != len2)
501                 return 0;
502         return memcmp (end1, end2, len) == 0;
503 }
504 #endif
505 static guint32
506 add_to_blob_cached (MonoDynamicImage *assembly, char *b1, int s1, char *b2, int s2)
507 {
508         guint32 idx;
509         char *copy;
510         gpointer oldkey, oldval;
511
512         copy = g_malloc (s1+s2);
513         memcpy (copy, b1, s1);
514         memcpy (copy + s1, b2, s2);
515         if (g_hash_table_lookup_extended (assembly->blob_cache, copy, &oldkey, &oldval)) {
516                 g_free (copy);
517                 idx = GPOINTER_TO_UINT (oldval);
518         } else {
519                 idx = mono_image_add_stream_data (&assembly->blob, b1, s1);
520                 mono_image_add_stream_data (&assembly->blob, b2, s2);
521                 g_hash_table_insert (assembly->blob_cache, copy, GUINT_TO_POINTER (idx));
522         }
523         return idx;
524 }
525
526 static guint32
527 sigbuffer_add_to_blob_cached (MonoDynamicImage *assembly, SigBuffer *buf)
528 {
529         char blob_size [8];
530         char *b = blob_size;
531         guint32 size = buf->p - buf->buf;
532         /* store length */
533         g_assert (size <= (buf->end - buf->buf));
534         mono_metadata_encode_value (size, b, &b);
535         return add_to_blob_cached (assembly, blob_size, b-blob_size, buf->buf, size);
536 }
537
538 /*
539  * Copy len * nelem bytes from val to dest, swapping bytes to LE if necessary.
540  * dest may be misaligned.
541  */
542 static void
543 swap_with_size (char *dest, const char* val, int len, int nelem) {
544 #if G_BYTE_ORDER != G_LITTLE_ENDIAN
545         int elem;
546
547         for (elem = 0; elem < nelem; ++elem) {
548                 switch (len) {
549                 case 1:
550                         *dest = *val;
551                         break;
552                 case 2:
553                         dest [0] = val [1];
554                         dest [1] = val [0];
555                         break;
556                 case 4:
557                         dest [0] = val [3];
558                         dest [1] = val [2];
559                         dest [2] = val [1];
560                         dest [3] = val [0];
561                         break;
562                 case 8:
563                         dest [0] = val [7];
564                         dest [1] = val [6];
565                         dest [2] = val [5];
566                         dest [3] = val [4];
567                         dest [4] = val [3];
568                         dest [5] = val [2];
569                         dest [6] = val [1];
570                         dest [7] = val [0];
571                         break;
572                 default:
573                         g_assert_not_reached ();
574                 }
575                 dest += len;
576                 val += len;
577         }
578 #else
579         memcpy (dest, val, len * nelem);
580 #endif
581 }
582
583 static guint32
584 add_mono_string_to_blob_cached (MonoDynamicImage *assembly, MonoString *str)
585 {
586         char blob_size [64];
587         char *b = blob_size;
588         guint32 idx = 0, len;
589
590         len = str->length * 2;
591         mono_metadata_encode_value (len, b, &b);
592 #if G_BYTE_ORDER != G_LITTLE_ENDIAN
593         {
594                 char *swapped = g_malloc (2 * mono_string_length (str));
595                 const char *p = (const char*)mono_string_chars (str);
596
597                 swap_with_size (swapped, p, 2, mono_string_length (str));
598                 idx = add_to_blob_cached (assembly, blob_size, b-blob_size, swapped, len);
599                 g_free (swapped);
600         }
601 #else
602         idx = add_to_blob_cached (assembly, blob_size, b-blob_size, (char*)mono_string_chars (str), len);
603 #endif
604         return idx;
605 }
606
607 #ifndef DISABLE_REFLECTION_EMIT
608 static MonoClass *
609 default_class_from_mono_type (MonoType *type)
610 {
611         switch (type->type) {
612         case MONO_TYPE_OBJECT:
613                 return mono_defaults.object_class;
614         case MONO_TYPE_VOID:
615                 return mono_defaults.void_class;
616         case MONO_TYPE_BOOLEAN:
617                 return mono_defaults.boolean_class;
618         case MONO_TYPE_CHAR:
619                 return mono_defaults.char_class;
620         case MONO_TYPE_I1:
621                 return mono_defaults.sbyte_class;
622         case MONO_TYPE_U1:
623                 return mono_defaults.byte_class;
624         case MONO_TYPE_I2:
625                 return mono_defaults.int16_class;
626         case MONO_TYPE_U2:
627                 return mono_defaults.uint16_class;
628         case MONO_TYPE_I4:
629                 return mono_defaults.int32_class;
630         case MONO_TYPE_U4:
631                 return mono_defaults.uint32_class;
632         case MONO_TYPE_I:
633                 return mono_defaults.int_class;
634         case MONO_TYPE_U:
635                 return mono_defaults.uint_class;
636         case MONO_TYPE_I8:
637                 return mono_defaults.int64_class;
638         case MONO_TYPE_U8:
639                 return mono_defaults.uint64_class;
640         case MONO_TYPE_R4:
641                 return mono_defaults.single_class;
642         case MONO_TYPE_R8:
643                 return mono_defaults.double_class;
644         case MONO_TYPE_STRING:
645                 return mono_defaults.string_class;
646         default:
647                 g_warning ("default_class_from_mono_type: implement me 0x%02x\n", type->type);
648                 g_assert_not_reached ();
649         }
650         
651         return NULL;
652 }
653 #endif
654
655 /*
656  * mono_class_get_ref_info:
657  *
658  *   Return the type builder/generic param builder corresponding to KLASS, if it exists.
659  */
660 gpointer
661 mono_class_get_ref_info (MonoClass *klass)
662 {
663         if (klass->ref_info_handle == 0)
664                 return NULL;
665         else
666                 return mono_gchandle_get_target (klass->ref_info_handle);
667 }
668
669 void
670 mono_class_set_ref_info (MonoClass *klass, gpointer obj)
671 {
672         klass->ref_info_handle = mono_gchandle_new ((MonoObject*)obj, FALSE);
673         g_assert (klass->ref_info_handle != 0);
674 }
675
676 void
677 mono_class_free_ref_info (MonoClass *klass)
678 {
679         if (klass->ref_info_handle) {
680                 mono_gchandle_free (klass->ref_info_handle);
681                 klass->ref_info_handle = 0;
682         }
683 }
684
685 static void
686 encode_generic_class (MonoDynamicImage *assembly, MonoGenericClass *gclass, SigBuffer *buf)
687 {
688         int i;
689         MonoGenericInst *class_inst;
690         MonoClass *klass;
691
692         g_assert (gclass);
693
694         class_inst = gclass->context.class_inst;
695
696         sigbuffer_add_value (buf, MONO_TYPE_GENERICINST);
697         klass = gclass->container_class;
698         sigbuffer_add_value (buf, klass->byval_arg.type);
699         sigbuffer_add_value (buf, mono_image_typedef_or_ref_full (assembly, &klass->byval_arg, FALSE));
700
701         sigbuffer_add_value (buf, class_inst->type_argc);
702         for (i = 0; i < class_inst->type_argc; ++i)
703                 encode_type (assembly, class_inst->type_argv [i], buf);
704
705 }
706
707 static void
708 encode_type (MonoDynamicImage *assembly, MonoType *type, SigBuffer *buf)
709 {
710         if (!type) {
711                 g_assert_not_reached ();
712                 return;
713         }
714                 
715         if (type->byref)
716                 sigbuffer_add_value (buf, MONO_TYPE_BYREF);
717
718         switch (type->type){
719         case MONO_TYPE_VOID:
720         case MONO_TYPE_BOOLEAN:
721         case MONO_TYPE_CHAR:
722         case MONO_TYPE_I1:
723         case MONO_TYPE_U1:
724         case MONO_TYPE_I2:
725         case MONO_TYPE_U2:
726         case MONO_TYPE_I4:
727         case MONO_TYPE_U4:
728         case MONO_TYPE_I8:
729         case MONO_TYPE_U8:
730         case MONO_TYPE_R4:
731         case MONO_TYPE_R8:
732         case MONO_TYPE_I:
733         case MONO_TYPE_U:
734         case MONO_TYPE_STRING:
735         case MONO_TYPE_OBJECT:
736         case MONO_TYPE_TYPEDBYREF:
737                 sigbuffer_add_value (buf, type->type);
738                 break;
739         case MONO_TYPE_PTR:
740                 sigbuffer_add_value (buf, type->type);
741                 encode_type (assembly, type->data.type, buf);
742                 break;
743         case MONO_TYPE_SZARRAY:
744                 sigbuffer_add_value (buf, type->type);
745                 encode_type (assembly, &type->data.klass->byval_arg, buf);
746                 break;
747         case MONO_TYPE_VALUETYPE:
748         case MONO_TYPE_CLASS: {
749                 MonoClass *k = mono_class_from_mono_type (type);
750
751                 if (k->generic_container) {
752                         MonoGenericClass *gclass = mono_metadata_lookup_generic_class (k, k->generic_container->context.class_inst, TRUE);
753                         encode_generic_class (assembly, gclass, buf);
754                 } else {
755                         /*
756                          * Make sure we use the correct type.
757                          */
758                         sigbuffer_add_value (buf, k->byval_arg.type);
759                         /*
760                          * ensure only non-byref gets passed to mono_image_typedef_or_ref(),
761                          * otherwise two typerefs could point to the same type, leading to
762                          * verification errors.
763                          */
764                         sigbuffer_add_value (buf, mono_image_typedef_or_ref (assembly, &k->byval_arg));
765                 }
766                 break;
767         }
768         case MONO_TYPE_ARRAY:
769                 sigbuffer_add_value (buf, type->type);
770                 encode_type (assembly, &type->data.array->eklass->byval_arg, buf);
771                 sigbuffer_add_value (buf, type->data.array->rank);
772                 sigbuffer_add_value (buf, 0); /* FIXME: set to 0 for now */
773                 sigbuffer_add_value (buf, 0);
774                 break;
775         case MONO_TYPE_GENERICINST:
776                 encode_generic_class (assembly, type->data.generic_class, buf);
777                 break;
778         case MONO_TYPE_VAR:
779         case MONO_TYPE_MVAR:
780                 sigbuffer_add_value (buf, type->type);
781                 sigbuffer_add_value (buf, mono_type_get_generic_param_num (type));
782                 break;
783         default:
784                 g_error ("need to encode type %x", type->type);
785         }
786 }
787
788 static void
789 encode_reflection_type (MonoDynamicImage *assembly, MonoReflectionType *type, SigBuffer *buf)
790 {
791         if (!type) {
792                 sigbuffer_add_value (buf, MONO_TYPE_VOID);
793                 return;
794         }
795
796         encode_type (assembly, mono_reflection_type_get_handle (type), buf);
797 }
798
799 static void
800 encode_custom_modifiers (MonoDynamicImage *assembly, MonoArray *modreq, MonoArray *modopt, SigBuffer *buf)
801 {
802         int i;
803
804         if (modreq) {
805                 for (i = 0; i < mono_array_length (modreq); ++i) {
806                         MonoType *mod = mono_type_array_get_and_resolve (modreq, i);
807                         sigbuffer_add_byte (buf, MONO_TYPE_CMOD_REQD);
808                         sigbuffer_add_value (buf, mono_image_typedef_or_ref (assembly, mod));
809                 }
810         }
811         if (modopt) {
812                 for (i = 0; i < mono_array_length (modopt); ++i) {
813                         MonoType *mod = mono_type_array_get_and_resolve (modopt, i);
814                         sigbuffer_add_byte (buf, MONO_TYPE_CMOD_OPT);
815                         sigbuffer_add_value (buf, mono_image_typedef_or_ref (assembly, mod));
816                 }
817         }
818 }
819
820 #ifndef DISABLE_REFLECTION_EMIT
821 static guint32
822 method_encode_signature (MonoDynamicImage *assembly, MonoMethodSignature *sig)
823 {
824         SigBuffer buf;
825         int i;
826         guint32 nparams =  sig->param_count;
827         guint32 idx;
828
829         if (!assembly->save)
830                 return 0;
831
832         sigbuffer_init (&buf, 32);
833         /*
834          * FIXME: vararg, explicit_this, differenc call_conv values...
835          */
836         idx = sig->call_convention;
837         if (sig->hasthis)
838                 idx |= 0x20; /* hasthis */
839         if (sig->generic_param_count)
840                 idx |= 0x10; /* generic */
841         sigbuffer_add_byte (&buf, idx);
842         if (sig->generic_param_count)
843                 sigbuffer_add_value (&buf, sig->generic_param_count);
844         sigbuffer_add_value (&buf, nparams);
845         encode_type (assembly, sig->ret, &buf);
846         for (i = 0; i < nparams; ++i) {
847                 if (i == sig->sentinelpos)
848                         sigbuffer_add_byte (&buf, MONO_TYPE_SENTINEL);
849                 encode_type (assembly, sig->params [i], &buf);
850         }
851         idx = sigbuffer_add_to_blob_cached (assembly, &buf);
852         sigbuffer_free (&buf);
853         return idx;
854 }
855 #endif
856
857 static guint32
858 method_builder_encode_signature (MonoDynamicImage *assembly, ReflectionMethodBuilder *mb)
859 {
860         /*
861          * FIXME: reuse code from method_encode_signature().
862          */
863         SigBuffer buf;
864         int i;
865         guint32 nparams =  mb->parameters ? mono_array_length (mb->parameters): 0;
866         guint32 ngparams = mb->generic_params ? mono_array_length (mb->generic_params): 0;
867         guint32 notypes = mb->opt_types ? mono_array_length (mb->opt_types): 0;
868         guint32 idx;
869
870         sigbuffer_init (&buf, 32);
871         /* LAMESPEC: all the call conv spec is foobared */
872         idx = mb->call_conv & 0x60; /* has-this, explicit-this */
873         if (mb->call_conv & 2)
874                 idx |= 0x5; /* vararg */
875         if (!(mb->attrs & METHOD_ATTRIBUTE_STATIC))
876                 idx |= 0x20; /* hasthis */
877         if (ngparams)
878                 idx |= 0x10; /* generic */
879         sigbuffer_add_byte (&buf, idx);
880         if (ngparams)
881                 sigbuffer_add_value (&buf, ngparams);
882         sigbuffer_add_value (&buf, nparams + notypes);
883         encode_custom_modifiers (assembly, mb->return_modreq, mb->return_modopt, &buf);
884         encode_reflection_type (assembly, mb->rtype, &buf);
885         for (i = 0; i < nparams; ++i) {
886                 MonoArray *modreq = NULL;
887                 MonoArray *modopt = NULL;
888                 MonoReflectionType *pt;
889
890                 if (mb->param_modreq && (i < mono_array_length (mb->param_modreq)))
891                         modreq = mono_array_get (mb->param_modreq, MonoArray*, i);
892                 if (mb->param_modopt && (i < mono_array_length (mb->param_modopt)))
893                         modopt = mono_array_get (mb->param_modopt, MonoArray*, i);
894                 encode_custom_modifiers (assembly, modreq, modopt, &buf);
895                 pt = mono_array_get (mb->parameters, MonoReflectionType*, i);
896                 encode_reflection_type (assembly, pt, &buf);
897         }
898         if (notypes)
899                 sigbuffer_add_byte (&buf, MONO_TYPE_SENTINEL);
900         for (i = 0; i < notypes; ++i) {
901                 MonoReflectionType *pt;
902
903                 pt = mono_array_get (mb->opt_types, MonoReflectionType*, i);
904                 encode_reflection_type (assembly, pt, &buf);
905         }
906
907         idx = sigbuffer_add_to_blob_cached (assembly, &buf);
908         sigbuffer_free (&buf);
909         return idx;
910 }
911
912 static guint32
913 encode_locals (MonoDynamicImage *assembly, MonoReflectionILGen *ilgen)
914 {
915         MonoDynamicTable *table;
916         guint32 *values;
917         guint32 idx, sig_idx;
918         guint nl = mono_array_length (ilgen->locals);
919         SigBuffer buf;
920         int i;
921
922         sigbuffer_init (&buf, 32);
923         sigbuffer_add_value (&buf, 0x07);
924         sigbuffer_add_value (&buf, nl);
925         for (i = 0; i < nl; ++i) {
926                 MonoReflectionLocalBuilder *lb = mono_array_get (ilgen->locals, MonoReflectionLocalBuilder*, i);
927                 
928                 if (lb->is_pinned)
929                         sigbuffer_add_value (&buf, MONO_TYPE_PINNED);
930                 
931                 encode_reflection_type (assembly, (MonoReflectionType*)lb->type, &buf);
932         }
933         sig_idx = sigbuffer_add_to_blob_cached (assembly, &buf);
934         sigbuffer_free (&buf);
935
936         if (assembly->standalonesig_cache == NULL)
937                 assembly->standalonesig_cache = g_hash_table_new (NULL, NULL);
938         idx = GPOINTER_TO_UINT (g_hash_table_lookup (assembly->standalonesig_cache, GUINT_TO_POINTER (sig_idx)));
939         if (idx)
940                 return idx;
941
942         table = &assembly->tables [MONO_TABLE_STANDALONESIG];
943         idx = table->next_idx ++;
944         table->rows ++;
945         alloc_table (table, table->rows);
946         values = table->values + idx * MONO_STAND_ALONE_SIGNATURE_SIZE;
947
948         values [MONO_STAND_ALONE_SIGNATURE] = sig_idx;
949
950         g_hash_table_insert (assembly->standalonesig_cache, GUINT_TO_POINTER (sig_idx), GUINT_TO_POINTER (idx));
951
952         return idx;
953 }
954
955 static guint32
956 method_count_clauses (MonoReflectionILGen *ilgen)
957 {
958         guint32 num_clauses = 0;
959         int i;
960
961         MonoILExceptionInfo *ex_info;
962         for (i = 0; i < mono_array_length (ilgen->ex_handlers); ++i) {
963                 ex_info = (MonoILExceptionInfo*)mono_array_addr (ilgen->ex_handlers, MonoILExceptionInfo, i);
964                 if (ex_info->handlers)
965                         num_clauses += mono_array_length (ex_info->handlers);
966                 else
967                         num_clauses++;
968         }
969
970         return num_clauses;
971 }
972
973 #ifndef DISABLE_REFLECTION_EMIT
974 static MonoExceptionClause*
975 method_encode_clauses (MonoImage *image, MonoDynamicImage *assembly, MonoReflectionILGen *ilgen, guint32 num_clauses)
976 {
977         MonoExceptionClause *clauses;
978         MonoExceptionClause *clause;
979         MonoILExceptionInfo *ex_info;
980         MonoILExceptionBlock *ex_block;
981         guint32 finally_start;
982         int i, j, clause_index;;
983
984         clauses = image_g_new0 (image, MonoExceptionClause, num_clauses);
985
986         clause_index = 0;
987         for (i = mono_array_length (ilgen->ex_handlers) - 1; i >= 0; --i) {
988                 ex_info = (MonoILExceptionInfo*)mono_array_addr (ilgen->ex_handlers, MonoILExceptionInfo, i);
989                 finally_start = ex_info->start + ex_info->len;
990                 if (!ex_info->handlers)
991                         continue;
992                 for (j = 0; j < mono_array_length (ex_info->handlers); ++j) {
993                         ex_block = (MonoILExceptionBlock*)mono_array_addr (ex_info->handlers, MonoILExceptionBlock, j);
994                         clause = &(clauses [clause_index]);
995
996                         clause->flags = ex_block->type;
997                         clause->try_offset = ex_info->start;
998
999                         if (ex_block->type == MONO_EXCEPTION_CLAUSE_FINALLY)
1000                                 clause->try_len = finally_start - ex_info->start;
1001                         else
1002                                 clause->try_len = ex_info->len;
1003                         clause->handler_offset = ex_block->start;
1004                         clause->handler_len = ex_block->len;
1005                         if (ex_block->extype) {
1006                                 clause->data.catch_class = mono_class_from_mono_type (mono_reflection_type_get_handle ((MonoReflectionType*)ex_block->extype));
1007                         } else {
1008                                 if (ex_block->type == MONO_EXCEPTION_CLAUSE_FILTER)
1009                                         clause->data.filter_offset = ex_block->filter_offset;
1010                                 else
1011                                         clause->data.filter_offset = 0;
1012                         }
1013                         finally_start = ex_block->start + ex_block->len;
1014
1015                         clause_index ++;
1016                 }
1017         }
1018
1019         return clauses;
1020 }
1021 #endif /* !DISABLE_REFLECTION_EMIT */
1022
1023 static guint32
1024 method_encode_code (MonoDynamicImage *assembly, ReflectionMethodBuilder *mb)
1025 {
1026         char flags = 0;
1027         guint32 idx;
1028         guint32 code_size;
1029         gint32 max_stack, i;
1030         gint32 num_locals = 0;
1031         gint32 num_exception = 0;
1032         gint maybe_small;
1033         guint32 fat_flags;
1034         char fat_header [12];
1035         guint32 int_value;
1036         guint16 short_value;
1037         guint32 local_sig = 0;
1038         guint32 header_size = 12;
1039         MonoArray *code;
1040
1041         if ((mb->attrs & (METHOD_ATTRIBUTE_PINVOKE_IMPL | METHOD_ATTRIBUTE_ABSTRACT)) ||
1042                         (mb->iattrs & (METHOD_IMPL_ATTRIBUTE_INTERNAL_CALL | METHOD_IMPL_ATTRIBUTE_RUNTIME)))
1043                 return 0;
1044
1045         /*if (mb->name)
1046                 g_print ("Encode method %s\n", mono_string_to_utf8 (mb->name));*/
1047         if (mb->ilgen) {
1048                 code = mb->ilgen->code;
1049                 code_size = mb->ilgen->code_len;
1050                 max_stack = mb->ilgen->max_stack;
1051                 num_locals = mb->ilgen->locals ? mono_array_length (mb->ilgen->locals) : 0;
1052                 if (mb->ilgen->ex_handlers)
1053                         num_exception = method_count_clauses (mb->ilgen);
1054         } else {
1055                 code = mb->code;
1056                 if (code == NULL){
1057                         char *name = mono_string_to_utf8 (mb->name);
1058                         char *str = g_strdup_printf ("Method %s does not have any IL associated", name);
1059                         MonoException *exception = mono_get_exception_argument (NULL, "a method does not have any IL associated");
1060                         g_free (str);
1061                         g_free (name);
1062                         mono_raise_exception (exception);
1063                 }
1064
1065                 code_size = mono_array_length (code);
1066                 max_stack = 8; /* we probably need to run a verifier on the code... */
1067         }
1068
1069         stream_data_align (&assembly->code);
1070
1071         /* check for exceptions, maxstack, locals */
1072         maybe_small = (max_stack <= 8) && (!num_locals) && (!num_exception);
1073         if (maybe_small) {
1074                 if (code_size < 64 && !(code_size & 1)) {
1075                         flags = (code_size << 2) | 0x2;
1076                 } else if (code_size < 32 && (code_size & 1)) {
1077                         flags = (code_size << 2) | 0x6; /* LAMESPEC: see metadata.c */
1078                 } else {
1079                         goto fat_header;
1080                 }
1081                 idx = mono_image_add_stream_data (&assembly->code, &flags, 1);
1082                 /* add to the fixup todo list */
1083                 if (mb->ilgen && mb->ilgen->num_token_fixups)
1084                         mono_g_hash_table_insert (assembly->token_fixups, mb->ilgen, GUINT_TO_POINTER (idx + 1));
1085                 mono_image_add_stream_data (&assembly->code, mono_array_addr (code, char, 0), code_size);
1086                 return assembly->text_rva + idx;
1087         } 
1088 fat_header:
1089         if (num_locals)
1090                 local_sig = MONO_TOKEN_SIGNATURE | encode_locals (assembly, mb->ilgen);
1091         /* 
1092          * FIXME: need to set also the header size in fat_flags.
1093          * (and more sects and init locals flags)
1094          */
1095         fat_flags =  0x03;
1096         if (num_exception)
1097                 fat_flags |= METHOD_HEADER_MORE_SECTS;
1098         if (mb->init_locals)
1099                 fat_flags |= METHOD_HEADER_INIT_LOCALS;
1100         fat_header [0] = fat_flags;
1101         fat_header [1] = (header_size / 4 ) << 4;
1102         short_value = GUINT16_TO_LE (max_stack);
1103         memcpy (fat_header + 2, &short_value, 2);
1104         int_value = GUINT32_TO_LE (code_size);
1105         memcpy (fat_header + 4, &int_value, 4);
1106         int_value = GUINT32_TO_LE (local_sig);
1107         memcpy (fat_header + 8, &int_value, 4);
1108         idx = mono_image_add_stream_data (&assembly->code, fat_header, 12);
1109         /* add to the fixup todo list */
1110         if (mb->ilgen && mb->ilgen->num_token_fixups)
1111                 mono_g_hash_table_insert (assembly->token_fixups, mb->ilgen, GUINT_TO_POINTER (idx + 12));
1112         
1113         mono_image_add_stream_data (&assembly->code, mono_array_addr (code, char, 0), code_size);
1114         if (num_exception) {
1115                 unsigned char sheader [4];
1116                 MonoILExceptionInfo * ex_info;
1117                 MonoILExceptionBlock * ex_block;
1118                 int j;
1119
1120                 stream_data_align (&assembly->code);
1121                 /* always use fat format for now */
1122                 sheader [0] = METHOD_HEADER_SECTION_FAT_FORMAT | METHOD_HEADER_SECTION_EHTABLE;
1123                 num_exception *= 6 * sizeof (guint32);
1124                 num_exception += 4; /* include the size of the header */
1125                 sheader [1] = num_exception & 0xff;
1126                 sheader [2] = (num_exception >> 8) & 0xff;
1127                 sheader [3] = (num_exception >> 16) & 0xff;
1128                 mono_image_add_stream_data (&assembly->code, (char*)sheader, 4);
1129                 /* fat header, so we are already aligned */
1130                 /* reverse order */
1131                 for (i = mono_array_length (mb->ilgen->ex_handlers) - 1; i >= 0; --i) {
1132                         ex_info = (MonoILExceptionInfo *)mono_array_addr (mb->ilgen->ex_handlers, MonoILExceptionInfo, i);
1133                         if (ex_info->handlers) {
1134                                 int finally_start = ex_info->start + ex_info->len;
1135                                 for (j = 0; j < mono_array_length (ex_info->handlers); ++j) {
1136                                         guint32 val;
1137                                         ex_block = (MonoILExceptionBlock*)mono_array_addr (ex_info->handlers, MonoILExceptionBlock, j);
1138                                         /* the flags */
1139                                         val = GUINT32_TO_LE (ex_block->type);
1140                                         mono_image_add_stream_data (&assembly->code, (char*)&val, sizeof (guint32));
1141                                         /* try offset */
1142                                         val = GUINT32_TO_LE (ex_info->start);
1143                                         mono_image_add_stream_data (&assembly->code, (char*)&val, sizeof (guint32));
1144                                         /* need fault, too, probably */
1145                                         if (ex_block->type == MONO_EXCEPTION_CLAUSE_FINALLY)
1146                                                 val = GUINT32_TO_LE (finally_start - ex_info->start);
1147                                         else
1148                                                 val = GUINT32_TO_LE (ex_info->len);
1149                                         mono_image_add_stream_data (&assembly->code, (char*)&val, sizeof (guint32));
1150                                         /* handler offset */
1151                                         val = GUINT32_TO_LE (ex_block->start);
1152                                         mono_image_add_stream_data (&assembly->code, (char*)&val, sizeof (guint32));
1153                                         /* handler len */
1154                                         val = GUINT32_TO_LE (ex_block->len);
1155                                         mono_image_add_stream_data (&assembly->code, (char*)&val, sizeof (guint32));
1156                                         finally_start = ex_block->start + ex_block->len;
1157                                         if (ex_block->extype) {
1158                                                 val = mono_metadata_token_from_dor (mono_image_typedef_or_ref (assembly, mono_reflection_type_get_handle ((MonoReflectionType*)ex_block->extype)));
1159                                         } else {
1160                                                 if (ex_block->type == MONO_EXCEPTION_CLAUSE_FILTER)
1161                                                         val = ex_block->filter_offset;
1162                                                 else
1163                                                         val = 0;
1164                                         }
1165                                         val = GUINT32_TO_LE (val);
1166                                         mono_image_add_stream_data (&assembly->code, (char*)&val, sizeof (guint32));
1167                                         /*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", 
1168                                                         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);*/
1169                                 }
1170                         } else {
1171                                 g_error ("No clauses for ex info block %d", i);
1172                         }
1173                 }
1174         }
1175         return assembly->text_rva + idx;
1176 }
1177
1178 static guint32
1179 find_index_in_table (MonoDynamicImage *assembly, int table_idx, int col, guint32 token)
1180 {
1181         int i;
1182         MonoDynamicTable *table;
1183         guint32 *values;
1184         
1185         table = &assembly->tables [table_idx];
1186
1187         g_assert (col < table->columns);
1188
1189         values = table->values + table->columns;
1190         for (i = 1; i <= table->rows; ++i) {
1191                 if (values [col] == token)
1192                         return i;
1193                 values += table->columns;
1194         }
1195         return 0;
1196 }
1197
1198 /*
1199  * LOCKING: Acquires the loader lock. 
1200  */
1201 static MonoCustomAttrInfo*
1202 lookup_custom_attr (MonoImage *image, gpointer member)
1203 {
1204         MonoCustomAttrInfo* res;
1205
1206         res = mono_image_property_lookup (image, member, MONO_PROP_DYNAMIC_CATTR);
1207
1208         if (!res)
1209                 return NULL;
1210
1211         res = g_memdup (res, MONO_SIZEOF_CUSTOM_ATTR_INFO + sizeof (MonoCustomAttrEntry) * res->num_attrs);
1212         res->cached = 0;
1213         return res;
1214 }
1215
1216 static gboolean
1217 custom_attr_visible (MonoImage *image, MonoReflectionCustomAttr *cattr)
1218 {
1219         /* FIXME: Need to do more checks */
1220         if (cattr->ctor->method && (cattr->ctor->method->klass->image != image)) {
1221                 int visibility = cattr->ctor->method->klass->flags & TYPE_ATTRIBUTE_VISIBILITY_MASK;
1222
1223                 if ((visibility != TYPE_ATTRIBUTE_PUBLIC) && (visibility != TYPE_ATTRIBUTE_NESTED_PUBLIC))
1224                         return FALSE;
1225         }
1226
1227         return TRUE;
1228 }
1229
1230 static MonoCustomAttrInfo*
1231 mono_custom_attrs_from_builders (MonoImage *alloc_img, MonoImage *image, MonoArray *cattrs)
1232 {
1233         int i, index, count, not_visible;
1234         MonoCustomAttrInfo *ainfo;
1235         MonoReflectionCustomAttr *cattr;
1236
1237         if (!cattrs)
1238                 return NULL;
1239         /* FIXME: check in assembly the Run flag is set */
1240
1241         count = mono_array_length (cattrs);
1242
1243         /* Skip nonpublic attributes since MS.NET seems to do the same */
1244         /* FIXME: This needs to be done more globally */
1245         not_visible = 0;
1246         for (i = 0; i < count; ++i) {
1247                 cattr = (MonoReflectionCustomAttr*)mono_array_get (cattrs, gpointer, i);
1248                 if (!custom_attr_visible (image, cattr))
1249                         not_visible ++;
1250         }
1251         count -= not_visible;
1252
1253         ainfo = image_g_malloc0 (alloc_img, MONO_SIZEOF_CUSTOM_ATTR_INFO + sizeof (MonoCustomAttrEntry) * count);
1254
1255         ainfo->image = image;
1256         ainfo->num_attrs = count;
1257         ainfo->cached = alloc_img != NULL;
1258         index = 0;
1259         for (i = 0; i < count; ++i) {
1260                 cattr = (MonoReflectionCustomAttr*)mono_array_get (cattrs, gpointer, i);
1261                 if (custom_attr_visible (image, cattr)) {
1262                         unsigned char *saved = mono_image_alloc (image, mono_array_length (cattr->data));
1263                         memcpy (saved, mono_array_addr (cattr->data, char, 0), mono_array_length (cattr->data));
1264                         ainfo->attrs [index].ctor = cattr->ctor->method;
1265                         ainfo->attrs [index].data = saved;
1266                         ainfo->attrs [index].data_size = mono_array_length (cattr->data);
1267                         index ++;
1268                 }
1269         }
1270
1271         return ainfo;
1272 }
1273
1274 #ifndef DISABLE_REFLECTION_EMIT
1275 /*
1276  * LOCKING: Acquires the loader lock. 
1277  */
1278 static void
1279 mono_save_custom_attrs (MonoImage *image, void *obj, MonoArray *cattrs)
1280 {
1281         MonoCustomAttrInfo *ainfo, *tmp;
1282
1283         if (!cattrs || !mono_array_length (cattrs))
1284                 return;
1285
1286         ainfo = mono_custom_attrs_from_builders (image, image, cattrs);
1287
1288         mono_loader_lock ();
1289         tmp = mono_image_property_lookup (image, obj, MONO_PROP_DYNAMIC_CATTR);
1290         if (tmp)
1291                 mono_custom_attrs_free (tmp);
1292         mono_image_property_insert (image, obj, MONO_PROP_DYNAMIC_CATTR, ainfo);
1293         mono_loader_unlock ();
1294
1295 }
1296 #endif
1297
1298 void
1299 mono_custom_attrs_free (MonoCustomAttrInfo *ainfo)
1300 {
1301         if (!ainfo->cached)
1302                 g_free (ainfo);
1303 }
1304
1305 /*
1306  * idx is the table index of the object
1307  * type is one of MONO_CUSTOM_ATTR_*
1308  */
1309 static void
1310 mono_image_add_cattrs (MonoDynamicImage *assembly, guint32 idx, guint32 type, MonoArray *cattrs)
1311 {
1312         MonoDynamicTable *table;
1313         MonoReflectionCustomAttr *cattr;
1314         guint32 *values;
1315         guint32 count, i, token;
1316         char blob_size [6];
1317         char *p = blob_size;
1318         
1319         /* it is legal to pass a NULL cattrs: we avoid to use the if in a lot of places */
1320         if (!cattrs)
1321                 return;
1322         count = mono_array_length (cattrs);
1323         table = &assembly->tables [MONO_TABLE_CUSTOMATTRIBUTE];
1324         table->rows += count;
1325         alloc_table (table, table->rows);
1326         values = table->values + table->next_idx * MONO_CUSTOM_ATTR_SIZE;
1327         idx <<= MONO_CUSTOM_ATTR_BITS;
1328         idx |= type;
1329         for (i = 0; i < count; ++i) {
1330                 cattr = (MonoReflectionCustomAttr*)mono_array_get (cattrs, gpointer, i);
1331                 values [MONO_CUSTOM_ATTR_PARENT] = idx;
1332                 token = mono_image_create_token (assembly, (MonoObject*)cattr->ctor, FALSE, FALSE);
1333                 type = mono_metadata_token_index (token);
1334                 type <<= MONO_CUSTOM_ATTR_TYPE_BITS;
1335                 switch (mono_metadata_token_table (token)) {
1336                 case MONO_TABLE_METHOD:
1337                         type |= MONO_CUSTOM_ATTR_TYPE_METHODDEF;
1338                         /*
1339                          * fixup_cattrs () needs to fix this up. We can't use image->tokens, since it contains the old token for the
1340                          * method, not the one returned by mono_image_create_token ().
1341                          */
1342                         mono_g_hash_table_insert (assembly->remapped_tokens, GUINT_TO_POINTER (token), cattr->ctor);
1343                         break;
1344                 case MONO_TABLE_MEMBERREF:
1345                         type |= MONO_CUSTOM_ATTR_TYPE_MEMBERREF;
1346                         break;
1347                 default:
1348                         g_warning ("got wrong token in custom attr");
1349                         continue;
1350                 }
1351                 values [MONO_CUSTOM_ATTR_TYPE] = type;
1352                 p = blob_size;
1353                 mono_metadata_encode_value (mono_array_length (cattr->data), p, &p);
1354                 values [MONO_CUSTOM_ATTR_VALUE] = add_to_blob_cached (assembly, blob_size, p - blob_size,
1355                         mono_array_addr (cattr->data, char, 0), mono_array_length (cattr->data));
1356                 values += MONO_CUSTOM_ATTR_SIZE;
1357                 ++table->next_idx;
1358         }
1359 }
1360
1361 static void
1362 mono_image_add_decl_security (MonoDynamicImage *assembly, guint32 parent_token, MonoArray *permissions)
1363 {
1364         MonoDynamicTable *table;
1365         guint32 *values;
1366         guint32 count, i, idx;
1367         MonoReflectionPermissionSet *perm;
1368
1369         if (!permissions)
1370                 return;
1371
1372         count = mono_array_length (permissions);
1373         table = &assembly->tables [MONO_TABLE_DECLSECURITY];
1374         table->rows += count;
1375         alloc_table (table, table->rows);
1376
1377         for (i = 0; i < mono_array_length (permissions); ++i) {
1378                 perm = (MonoReflectionPermissionSet*)mono_array_addr (permissions, MonoReflectionPermissionSet, i);
1379
1380                 values = table->values + table->next_idx * MONO_DECL_SECURITY_SIZE;
1381
1382                 idx = mono_metadata_token_index (parent_token);
1383                 idx <<= MONO_HAS_DECL_SECURITY_BITS;
1384                 switch (mono_metadata_token_table (parent_token)) {
1385                 case MONO_TABLE_TYPEDEF:
1386                         idx |= MONO_HAS_DECL_SECURITY_TYPEDEF;
1387                         break;
1388                 case MONO_TABLE_METHOD:
1389                         idx |= MONO_HAS_DECL_SECURITY_METHODDEF;
1390                         break;
1391                 case MONO_TABLE_ASSEMBLY:
1392                         idx |= MONO_HAS_DECL_SECURITY_ASSEMBLY;
1393                         break;
1394                 default:
1395                         g_assert_not_reached ();
1396                 }
1397
1398                 values [MONO_DECL_SECURITY_ACTION] = perm->action;
1399                 values [MONO_DECL_SECURITY_PARENT] = idx;
1400                 values [MONO_DECL_SECURITY_PERMISSIONSET] = add_mono_string_to_blob_cached (assembly, perm->pset);
1401
1402                 ++table->next_idx;
1403         }
1404 }
1405
1406 /*
1407  * Fill in the MethodDef and ParamDef tables for a method.
1408  * This is used for both normal methods and constructors.
1409  */
1410 static void
1411 mono_image_basic_method (ReflectionMethodBuilder *mb, MonoDynamicImage *assembly)
1412 {
1413         MonoDynamicTable *table;
1414         guint32 *values;
1415         guint i, count;
1416
1417         /* room in this table is already allocated */
1418         table = &assembly->tables [MONO_TABLE_METHOD];
1419         *mb->table_idx = table->next_idx ++;
1420         g_hash_table_insert (assembly->method_to_table_idx, mb->mhandle, GUINT_TO_POINTER ((*mb->table_idx)));
1421         values = table->values + *mb->table_idx * MONO_METHOD_SIZE;
1422         values [MONO_METHOD_NAME] = string_heap_insert_mstring (&assembly->sheap, mb->name);
1423         values [MONO_METHOD_FLAGS] = mb->attrs;
1424         values [MONO_METHOD_IMPLFLAGS] = mb->iattrs;
1425         values [MONO_METHOD_SIGNATURE] = method_builder_encode_signature (assembly, mb);
1426         values [MONO_METHOD_RVA] = method_encode_code (assembly, mb);
1427         
1428         table = &assembly->tables [MONO_TABLE_PARAM];
1429         values [MONO_METHOD_PARAMLIST] = table->next_idx;
1430
1431         mono_image_add_decl_security (assembly, 
1432                 mono_metadata_make_token (MONO_TABLE_METHOD, *mb->table_idx), mb->permissions);
1433
1434         if (mb->pinfo) {
1435                 MonoDynamicTable *mtable;
1436                 guint32 *mvalues;
1437                 
1438                 mtable = &assembly->tables [MONO_TABLE_FIELDMARSHAL];
1439                 mvalues = mtable->values + mtable->next_idx * MONO_FIELD_MARSHAL_SIZE;
1440                 
1441                 count = 0;
1442                 for (i = 0; i < mono_array_length (mb->pinfo); ++i) {
1443                         if (mono_array_get (mb->pinfo, gpointer, i))
1444                                 count++;
1445                 }
1446                 table->rows += count;
1447                 alloc_table (table, table->rows);
1448                 values = table->values + table->next_idx * MONO_PARAM_SIZE;
1449                 for (i = 0; i < mono_array_length (mb->pinfo); ++i) {
1450                         MonoReflectionParamBuilder *pb;
1451                         if ((pb = mono_array_get (mb->pinfo, MonoReflectionParamBuilder*, i))) {
1452                                 values [MONO_PARAM_FLAGS] = pb->attrs;
1453                                 values [MONO_PARAM_SEQUENCE] = i;
1454                                 if (pb->name != NULL) {
1455                                         values [MONO_PARAM_NAME] = string_heap_insert_mstring (&assembly->sheap, pb->name);
1456                                 } else {
1457                                         values [MONO_PARAM_NAME] = 0;
1458                                 }
1459                                 values += MONO_PARAM_SIZE;
1460                                 if (pb->marshal_info) {
1461                                         mtable->rows++;
1462                                         alloc_table (mtable, mtable->rows);
1463                                         mvalues = mtable->values + mtable->rows * MONO_FIELD_MARSHAL_SIZE;
1464                                         mvalues [MONO_FIELD_MARSHAL_PARENT] = (table->next_idx << MONO_HAS_FIELD_MARSHAL_BITS) | MONO_HAS_FIELD_MARSHAL_PARAMDEF;
1465                                         mvalues [MONO_FIELD_MARSHAL_NATIVE_TYPE] = encode_marshal_blob (assembly, pb->marshal_info);
1466                                 }
1467                                 pb->table_idx = table->next_idx++;
1468                                 if (pb->attrs & PARAM_ATTRIBUTE_HAS_DEFAULT) {
1469                                         guint32 field_type = 0;
1470                                         mtable = &assembly->tables [MONO_TABLE_CONSTANT];
1471                                         mtable->rows ++;
1472                                         alloc_table (mtable, mtable->rows);
1473                                         mvalues = mtable->values + mtable->rows * MONO_CONSTANT_SIZE;
1474                                         mvalues [MONO_CONSTANT_PARENT] = MONO_HASCONSTANT_PARAM | (pb->table_idx << MONO_HASCONSTANT_BITS);
1475                                         mvalues [MONO_CONSTANT_VALUE] = encode_constant (assembly, pb->def_value, &field_type);
1476                                         mvalues [MONO_CONSTANT_TYPE] = field_type;
1477                                         mvalues [MONO_CONSTANT_PADDING] = 0;
1478                                 }
1479                         }
1480                 }
1481         }
1482 }
1483
1484 #ifndef DISABLE_REFLECTION_EMIT
1485 static void
1486 reflection_methodbuilder_from_method_builder (ReflectionMethodBuilder *rmb, MonoReflectionMethodBuilder *mb)
1487 {
1488         memset (rmb, 0, sizeof (ReflectionMethodBuilder));
1489
1490         rmb->ilgen = mb->ilgen;
1491         rmb->rtype = mono_reflection_type_resolve_user_types ((MonoReflectionType*)mb->rtype);
1492         rmb->parameters = mb->parameters;
1493         rmb->generic_params = mb->generic_params;
1494         rmb->generic_container = mb->generic_container;
1495         rmb->opt_types = NULL;
1496         rmb->pinfo = mb->pinfo;
1497         rmb->attrs = mb->attrs;
1498         rmb->iattrs = mb->iattrs;
1499         rmb->call_conv = mb->call_conv;
1500         rmb->code = mb->code;
1501         rmb->type = mb->type;
1502         rmb->name = mb->name;
1503         rmb->table_idx = &mb->table_idx;
1504         rmb->init_locals = mb->init_locals;
1505         rmb->skip_visibility = FALSE;
1506         rmb->return_modreq = mb->return_modreq;
1507         rmb->return_modopt = mb->return_modopt;
1508         rmb->param_modreq = mb->param_modreq;
1509         rmb->param_modopt = mb->param_modopt;
1510         rmb->permissions = mb->permissions;
1511         rmb->mhandle = mb->mhandle;
1512         rmb->nrefs = 0;
1513         rmb->refs = NULL;
1514
1515         if (mb->dll) {
1516                 rmb->charset = mb->charset;
1517                 rmb->extra_flags = mb->extra_flags;
1518                 rmb->native_cc = mb->native_cc;
1519                 rmb->dllentry = mb->dllentry;
1520                 rmb->dll = mb->dll;
1521         }
1522 }
1523
1524 static void
1525 reflection_methodbuilder_from_ctor_builder (ReflectionMethodBuilder *rmb, MonoReflectionCtorBuilder *mb)
1526 {
1527         const char *name = mb->attrs & METHOD_ATTRIBUTE_STATIC ? ".cctor": ".ctor";
1528
1529         memset (rmb, 0, sizeof (ReflectionMethodBuilder));
1530
1531         rmb->ilgen = mb->ilgen;
1532         rmb->rtype = mono_type_get_object (mono_domain_get (), &mono_defaults.void_class->byval_arg);
1533         rmb->parameters = mb->parameters;
1534         rmb->generic_params = NULL;
1535         rmb->generic_container = NULL;
1536         rmb->opt_types = NULL;
1537         rmb->pinfo = mb->pinfo;
1538         rmb->attrs = mb->attrs;
1539         rmb->iattrs = mb->iattrs;
1540         rmb->call_conv = mb->call_conv;
1541         rmb->code = NULL;
1542         rmb->type = mb->type;
1543         rmb->name = mono_string_new (mono_domain_get (), name);
1544         rmb->table_idx = &mb->table_idx;
1545         rmb->init_locals = mb->init_locals;
1546         rmb->skip_visibility = FALSE;
1547         rmb->return_modreq = NULL;
1548         rmb->return_modopt = NULL;
1549         rmb->param_modreq = mb->param_modreq;
1550         rmb->param_modopt = mb->param_modopt;
1551         rmb->permissions = mb->permissions;
1552         rmb->mhandle = mb->mhandle;
1553         rmb->nrefs = 0;
1554         rmb->refs = NULL;
1555 }
1556
1557 static void
1558 reflection_methodbuilder_from_dynamic_method (ReflectionMethodBuilder *rmb, MonoReflectionDynamicMethod *mb)
1559 {
1560         memset (rmb, 0, sizeof (ReflectionMethodBuilder));
1561
1562         rmb->ilgen = mb->ilgen;
1563         rmb->rtype = mb->rtype;
1564         rmb->parameters = mb->parameters;
1565         rmb->generic_params = NULL;
1566         rmb->generic_container = NULL;
1567         rmb->opt_types = NULL;
1568         rmb->pinfo = NULL;
1569         rmb->attrs = mb->attrs;
1570         rmb->iattrs = 0;
1571         rmb->call_conv = mb->call_conv;
1572         rmb->code = NULL;
1573         rmb->type = (MonoObject *) mb->owner;
1574         rmb->name = mb->name;
1575         rmb->table_idx = NULL;
1576         rmb->init_locals = mb->init_locals;
1577         rmb->skip_visibility = mb->skip_visibility;
1578         rmb->return_modreq = NULL;
1579         rmb->return_modopt = NULL;
1580         rmb->param_modreq = NULL;
1581         rmb->param_modopt = NULL;
1582         rmb->permissions = NULL;
1583         rmb->mhandle = mb->mhandle;
1584         rmb->nrefs = 0;
1585         rmb->refs = NULL;
1586 }       
1587 #endif
1588
1589 static void
1590 mono_image_add_methodimpl (MonoDynamicImage *assembly, MonoReflectionMethodBuilder *mb)
1591 {
1592         MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder *)mb->type;
1593         MonoDynamicTable *table;
1594         guint32 *values;
1595         guint32 tok;
1596         MonoReflectionMethod *m;
1597         int i;
1598
1599         if (!mb->override_methods)
1600                 return;
1601
1602         for (i = 0; i < mono_array_length (mb->override_methods); ++i) {
1603                 m = mono_array_get (mb->override_methods, MonoReflectionMethod*, i);
1604
1605                 table = &assembly->tables [MONO_TABLE_METHODIMPL];
1606                 table->rows ++;
1607                 alloc_table (table, table->rows);
1608                 values = table->values + table->rows * MONO_METHODIMPL_SIZE;
1609                 values [MONO_METHODIMPL_CLASS] = tb->table_idx;
1610                 values [MONO_METHODIMPL_BODY] = MONO_METHODDEFORREF_METHODDEF | (mb->table_idx << MONO_METHODDEFORREF_BITS);
1611
1612                 tok = mono_image_create_token (assembly, (MonoObject*)m, FALSE, FALSE);
1613                 switch (mono_metadata_token_table (tok)) {
1614                 case MONO_TABLE_MEMBERREF:
1615                         tok = (mono_metadata_token_index (tok) << MONO_METHODDEFORREF_BITS ) | MONO_METHODDEFORREF_METHODREF;
1616                         break;
1617                 case MONO_TABLE_METHOD:
1618                         tok = (mono_metadata_token_index (tok) << MONO_METHODDEFORREF_BITS ) | MONO_METHODDEFORREF_METHODDEF;
1619                         break;
1620                 default:
1621                         g_assert_not_reached ();
1622                 }
1623                 values [MONO_METHODIMPL_DECLARATION] = tok;
1624         }
1625 }
1626
1627 #ifndef DISABLE_REFLECTION_EMIT
1628 static void
1629 mono_image_get_method_info (MonoReflectionMethodBuilder *mb, MonoDynamicImage *assembly)
1630 {
1631         MonoDynamicTable *table;
1632         guint32 *values;
1633         ReflectionMethodBuilder rmb;
1634         int i;
1635
1636         reflection_methodbuilder_from_method_builder (&rmb, mb);
1637
1638         mono_image_basic_method (&rmb, assembly);
1639         mb->table_idx = *rmb.table_idx;
1640
1641         if (mb->dll) { /* It's a P/Invoke method */
1642                 guint32 moduleref;
1643                 /* map CharSet values to on-disk values */
1644                 int ncharset = (mb->charset ? (mb->charset - 1) * 2 : 0);
1645                 int extra_flags = mb->extra_flags;
1646                 table = &assembly->tables [MONO_TABLE_IMPLMAP];
1647                 table->rows ++;
1648                 alloc_table (table, table->rows);
1649                 values = table->values + table->rows * MONO_IMPLMAP_SIZE;
1650                 
1651                 values [MONO_IMPLMAP_FLAGS] = (mb->native_cc << 8) | ncharset | extra_flags;
1652                 values [MONO_IMPLMAP_MEMBER] = (mb->table_idx << 1) | 1; /* memberforwarded: method */
1653                 if (mb->dllentry)
1654                         values [MONO_IMPLMAP_NAME] = string_heap_insert_mstring (&assembly->sheap, mb->dllentry);
1655                 else
1656                         values [MONO_IMPLMAP_NAME] = string_heap_insert_mstring (&assembly->sheap, mb->name);
1657                 moduleref = string_heap_insert_mstring (&assembly->sheap, mb->dll);
1658                 if (!(values [MONO_IMPLMAP_SCOPE] = find_index_in_table (assembly, MONO_TABLE_MODULEREF, MONO_MODULEREF_NAME, moduleref))) {
1659                         table = &assembly->tables [MONO_TABLE_MODULEREF];
1660                         table->rows ++;
1661                         alloc_table (table, table->rows);
1662                         table->values [table->rows * MONO_MODULEREF_SIZE + MONO_MODULEREF_NAME] = moduleref;
1663                         values [MONO_IMPLMAP_SCOPE] = table->rows;
1664                 }
1665         }
1666
1667         if (mb->generic_params) {
1668                 table = &assembly->tables [MONO_TABLE_GENERICPARAM];
1669                 table->rows += mono_array_length (mb->generic_params);
1670                 alloc_table (table, table->rows);
1671                 for (i = 0; i < mono_array_length (mb->generic_params); ++i) {
1672                         guint32 owner = MONO_TYPEORMETHOD_METHOD | (mb->table_idx << MONO_TYPEORMETHOD_BITS);
1673
1674                         mono_image_get_generic_param_info (
1675                                 mono_array_get (mb->generic_params, gpointer, i), owner, assembly);
1676                 }
1677         }
1678
1679 }
1680
1681 static void
1682 mono_image_get_ctor_info (MonoDomain *domain, MonoReflectionCtorBuilder *mb, MonoDynamicImage *assembly)
1683 {
1684         ReflectionMethodBuilder rmb;
1685
1686         reflection_methodbuilder_from_ctor_builder (&rmb, mb);
1687
1688         mono_image_basic_method (&rmb, assembly);
1689         mb->table_idx = *rmb.table_idx;
1690 }
1691 #endif
1692
1693 static char*
1694 type_get_fully_qualified_name (MonoType *type)
1695 {
1696         return mono_type_get_name_full (type, MONO_TYPE_NAME_FORMAT_ASSEMBLY_QUALIFIED);
1697 }
1698
1699 static char*
1700 type_get_qualified_name (MonoType *type, MonoAssembly *ass) {
1701         MonoClass *klass;
1702         MonoAssembly *ta;
1703
1704         klass = mono_class_from_mono_type (type);
1705         if (!klass) 
1706                 return mono_type_get_name_full (type, MONO_TYPE_NAME_FORMAT_REFLECTION);
1707         ta = klass->image->assembly;
1708         if (assembly_is_dynamic (ta) || (ta == ass)) {
1709                 if (klass->generic_class || klass->generic_container)
1710                         /* For generic type definitions, we want T, while REFLECTION returns T<K> */
1711                         return mono_type_get_name_full (type, MONO_TYPE_NAME_FORMAT_FULL_NAME);
1712                 else
1713                         return mono_type_get_name_full (type, MONO_TYPE_NAME_FORMAT_REFLECTION);
1714         }
1715
1716         return mono_type_get_name_full (type, MONO_TYPE_NAME_FORMAT_ASSEMBLY_QUALIFIED);
1717 }
1718
1719 #ifndef DISABLE_REFLECTION_EMIT
1720 /*field_image is the image to which the eventual custom mods have been encoded against*/
1721 static guint32
1722 fieldref_encode_signature (MonoDynamicImage *assembly, MonoImage *field_image, MonoType *type)
1723 {
1724         SigBuffer buf;
1725         guint32 idx, i, token;
1726
1727         if (!assembly->save)
1728                 return 0;
1729
1730         sigbuffer_init (&buf, 32);
1731         
1732         sigbuffer_add_value (&buf, 0x06);
1733         /* encode custom attributes before the type */
1734         if (type->num_mods) {
1735                 for (i = 0; i < type->num_mods; ++i) {
1736                         if (field_image) {
1737                                 MonoError error;
1738                                 MonoClass *class = mono_class_get_checked (field_image, type->modifiers [i].token, &error);
1739                                 g_assert (mono_error_ok (&error)); /* FIXME don't swallow the error */
1740
1741                                 token = mono_image_typedef_or_ref (assembly, &class->byval_arg);
1742                         } else {
1743                                 token = type->modifiers [i].token;
1744                         }
1745
1746                         if (type->modifiers [i].required)
1747                                 sigbuffer_add_byte (&buf, MONO_TYPE_CMOD_REQD);
1748                         else
1749                                 sigbuffer_add_byte (&buf, MONO_TYPE_CMOD_OPT);
1750
1751                         sigbuffer_add_value (&buf, token);
1752                 }
1753         }
1754         encode_type (assembly, type, &buf);
1755         idx = sigbuffer_add_to_blob_cached (assembly, &buf);
1756         sigbuffer_free (&buf);
1757         return idx;
1758 }
1759 #endif
1760
1761 static guint32
1762 field_encode_signature (MonoDynamicImage *assembly, MonoReflectionFieldBuilder *fb)
1763 {
1764         SigBuffer buf;
1765         guint32 idx;
1766         guint32 typespec = 0;
1767         MonoType *type;
1768         MonoClass *class;
1769
1770         init_type_builder_generics (fb->type);
1771
1772         type = mono_reflection_type_get_handle ((MonoReflectionType*)fb->type);
1773         class = mono_class_from_mono_type (type);
1774
1775         sigbuffer_init (&buf, 32);
1776         
1777         sigbuffer_add_value (&buf, 0x06);
1778         encode_custom_modifiers (assembly, fb->modreq, fb->modopt, &buf);
1779         /* encode custom attributes before the type */
1780
1781         if (class->generic_container)
1782                 typespec = create_typespec (assembly, type);
1783
1784         if (typespec) {
1785                 MonoGenericClass *gclass;
1786                 gclass = mono_metadata_lookup_generic_class (class, class->generic_container->context.class_inst, TRUE);
1787                 encode_generic_class (assembly, gclass, &buf);
1788         } else {
1789                 encode_type (assembly, type, &buf);
1790         }
1791         idx = sigbuffer_add_to_blob_cached (assembly, &buf);
1792         sigbuffer_free (&buf);
1793         return idx;
1794 }
1795
1796 static guint32
1797 encode_constant (MonoDynamicImage *assembly, MonoObject *val, guint32 *ret_type) {
1798         char blob_size [64];
1799         char *b = blob_size;
1800         char *box_val;
1801         char* buf;
1802         guint32 idx = 0, len = 0, dummy = 0;
1803
1804         buf = g_malloc (64);
1805         if (!val) {
1806                 *ret_type = MONO_TYPE_CLASS;
1807                 len = 4;
1808                 box_val = (char*)&dummy;
1809         } else {
1810                 box_val = ((char*)val) + sizeof (MonoObject);
1811                 *ret_type = val->vtable->klass->byval_arg.type;
1812         }
1813 handle_enum:
1814         switch (*ret_type) {
1815         case MONO_TYPE_BOOLEAN:
1816         case MONO_TYPE_U1:
1817         case MONO_TYPE_I1:
1818                 len = 1;
1819                 break;
1820         case MONO_TYPE_CHAR:
1821         case MONO_TYPE_U2:
1822         case MONO_TYPE_I2:
1823                 len = 2;
1824                 break;
1825         case MONO_TYPE_U4:
1826         case MONO_TYPE_I4:
1827         case MONO_TYPE_R4:
1828                 len = 4;
1829                 break;
1830         case MONO_TYPE_U8:
1831         case MONO_TYPE_I8:
1832                 len = 8;
1833                 break;
1834         case MONO_TYPE_R8:
1835                 len = 8;
1836                 break;
1837         case MONO_TYPE_VALUETYPE: {
1838                 MonoClass *klass = val->vtable->klass;
1839                 
1840                 if (klass->enumtype) {
1841                         *ret_type = mono_class_enum_basetype (klass)->type;
1842                         goto handle_enum;
1843                 } else if (mono_is_corlib_image (klass->image) && strcmp (klass->name_space, "System") == 0 && strcmp (klass->name, "DateTime") == 0) {
1844                         len = 8;
1845                 } else 
1846                         g_error ("we can't encode valuetypes, we should have never reached this line");
1847                 break;
1848         }
1849         case MONO_TYPE_CLASS:
1850                 break;
1851         case MONO_TYPE_STRING: {
1852                 MonoString *str = (MonoString*)val;
1853                 /* there is no signature */
1854                 len = str->length * 2;
1855                 mono_metadata_encode_value (len, b, &b);
1856 #if G_BYTE_ORDER != G_LITTLE_ENDIAN
1857                 {
1858                         char *swapped = g_malloc (2 * mono_string_length (str));
1859                         const char *p = (const char*)mono_string_chars (str);
1860
1861                         swap_with_size (swapped, p, 2, mono_string_length (str));
1862                         idx = add_to_blob_cached (assembly, blob_size, b-blob_size, swapped, len);
1863                         g_free (swapped);
1864                 }
1865 #else
1866                 idx = add_to_blob_cached (assembly, blob_size, b-blob_size, (char*)mono_string_chars (str), len);
1867 #endif
1868
1869                 g_free (buf);
1870                 return idx;
1871         }
1872         case MONO_TYPE_GENERICINST:
1873                 *ret_type = val->vtable->klass->generic_class->container_class->byval_arg.type;
1874                 goto handle_enum;
1875         default:
1876                 g_error ("we don't encode constant type 0x%02x yet", *ret_type);
1877         }
1878
1879         /* there is no signature */
1880         mono_metadata_encode_value (len, b, &b);
1881 #if G_BYTE_ORDER != G_LITTLE_ENDIAN
1882         idx = mono_image_add_stream_data (&assembly->blob, blob_size, b-blob_size);
1883         swap_with_size (blob_size, box_val, len, 1);
1884         mono_image_add_stream_data (&assembly->blob, blob_size, len);
1885 #else
1886         idx = add_to_blob_cached (assembly, blob_size, b-blob_size, box_val, len);
1887 #endif
1888
1889         g_free (buf);
1890         return idx;
1891 }
1892
1893 static guint32
1894 encode_marshal_blob (MonoDynamicImage *assembly, MonoReflectionMarshal *minfo) {
1895         char *str;
1896         SigBuffer buf;
1897         guint32 idx, len;
1898
1899         sigbuffer_init (&buf, 32);
1900
1901         sigbuffer_add_value (&buf, minfo->type);
1902
1903         switch (minfo->type) {
1904         case MONO_NATIVE_BYVALTSTR:
1905         case MONO_NATIVE_BYVALARRAY:
1906                 sigbuffer_add_value (&buf, minfo->count);
1907                 break;
1908         case MONO_NATIVE_LPARRAY:
1909                 if (minfo->eltype || minfo->has_size) {
1910                         sigbuffer_add_value (&buf, minfo->eltype);
1911                         if (minfo->has_size) {
1912                                 sigbuffer_add_value (&buf, minfo->param_num != -1? minfo->param_num: 0);
1913                                 sigbuffer_add_value (&buf, minfo->count != -1? minfo->count: 0);
1914
1915                                 /* LAMESPEC: ElemMult is undocumented */
1916                                 sigbuffer_add_value (&buf, minfo->param_num != -1? 1: 0);
1917                         }
1918                 }
1919                 break;
1920         case MONO_NATIVE_SAFEARRAY:
1921                 if (minfo->eltype)
1922                         sigbuffer_add_value (&buf, minfo->eltype);
1923                 break;
1924         case MONO_NATIVE_CUSTOM:
1925                 if (minfo->guid) {
1926                         str = mono_string_to_utf8 (minfo->guid);
1927                         len = strlen (str);
1928                         sigbuffer_add_value (&buf, len);
1929                         sigbuffer_add_mem (&buf, str, len);
1930                         g_free (str);
1931                 } else {
1932                         sigbuffer_add_value (&buf, 0);
1933                 }
1934                 /* native type name */
1935                 sigbuffer_add_value (&buf, 0);
1936                 /* custom marshaler type name */
1937                 if (minfo->marshaltype || minfo->marshaltyperef) {
1938                         if (minfo->marshaltyperef)
1939                                 str = type_get_fully_qualified_name (mono_reflection_type_get_handle ((MonoReflectionType*)minfo->marshaltyperef));
1940                         else
1941                                 str = mono_string_to_utf8 (minfo->marshaltype);
1942                         len = strlen (str);
1943                         sigbuffer_add_value (&buf, len);
1944                         sigbuffer_add_mem (&buf, str, len);
1945                         g_free (str);
1946                 } else {
1947                         /* FIXME: Actually a bug, since this field is required.  Punting for now ... */
1948                         sigbuffer_add_value (&buf, 0);
1949                 }
1950                 if (minfo->mcookie) {
1951                         str = mono_string_to_utf8 (minfo->mcookie);
1952                         len = strlen (str);
1953                         sigbuffer_add_value (&buf, len);
1954                         sigbuffer_add_mem (&buf, str, len);
1955                         g_free (str);
1956                 } else {
1957                         sigbuffer_add_value (&buf, 0);
1958                 }
1959                 break;
1960         default:
1961                 break;
1962         }
1963         idx = sigbuffer_add_to_blob_cached (assembly, &buf);
1964         sigbuffer_free (&buf);
1965         return idx;
1966 }
1967
1968 static void
1969 mono_image_get_field_info (MonoReflectionFieldBuilder *fb, MonoDynamicImage *assembly)
1970 {
1971         MonoDynamicTable *table;
1972         guint32 *values;
1973
1974         /* maybe this fixup should be done in the C# code */
1975         if (fb->attrs & FIELD_ATTRIBUTE_LITERAL)
1976                 fb->attrs |= FIELD_ATTRIBUTE_HAS_DEFAULT;
1977         table = &assembly->tables [MONO_TABLE_FIELD];
1978         fb->table_idx = table->next_idx ++;
1979         g_hash_table_insert (assembly->field_to_table_idx, fb->handle, GUINT_TO_POINTER (fb->table_idx));
1980         values = table->values + fb->table_idx * MONO_FIELD_SIZE;
1981         values [MONO_FIELD_NAME] = string_heap_insert_mstring (&assembly->sheap, fb->name);
1982         values [MONO_FIELD_FLAGS] = fb->attrs;
1983         values [MONO_FIELD_SIGNATURE] = field_encode_signature (assembly, fb);
1984
1985         if (fb->offset != -1) {
1986                 table = &assembly->tables [MONO_TABLE_FIELDLAYOUT];
1987                 table->rows ++;
1988                 alloc_table (table, table->rows);
1989                 values = table->values + table->rows * MONO_FIELD_LAYOUT_SIZE;
1990                 values [MONO_FIELD_LAYOUT_FIELD] = fb->table_idx;
1991                 values [MONO_FIELD_LAYOUT_OFFSET] = fb->offset;
1992         }
1993         if (fb->attrs & FIELD_ATTRIBUTE_LITERAL) {
1994                 guint32 field_type = 0;
1995                 table = &assembly->tables [MONO_TABLE_CONSTANT];
1996                 table->rows ++;
1997                 alloc_table (table, table->rows);
1998                 values = table->values + table->rows * MONO_CONSTANT_SIZE;
1999                 values [MONO_CONSTANT_PARENT] = MONO_HASCONSTANT_FIEDDEF | (fb->table_idx << MONO_HASCONSTANT_BITS);
2000                 values [MONO_CONSTANT_VALUE] = encode_constant (assembly, fb->def_value, &field_type);
2001                 values [MONO_CONSTANT_TYPE] = field_type;
2002                 values [MONO_CONSTANT_PADDING] = 0;
2003         }
2004         if (fb->attrs & FIELD_ATTRIBUTE_HAS_FIELD_RVA) {
2005                 guint32 rva_idx;
2006                 table = &assembly->tables [MONO_TABLE_FIELDRVA];
2007                 table->rows ++;
2008                 alloc_table (table, table->rows);
2009                 values = table->values + table->rows * MONO_FIELD_RVA_SIZE;
2010                 values [MONO_FIELD_RVA_FIELD] = fb->table_idx;
2011                 /*
2012                  * We store it in the code section because it's simpler for now.
2013                  */
2014                 if (fb->rva_data) {
2015                         if (mono_array_length (fb->rva_data) >= 10)
2016                                 stream_data_align (&assembly->code);
2017                         rva_idx = mono_image_add_stream_data (&assembly->code, mono_array_addr (fb->rva_data, char, 0), mono_array_length (fb->rva_data));
2018                 } else
2019                         rva_idx = mono_image_add_stream_zero (&assembly->code, mono_class_value_size (fb->handle->parent, NULL));
2020                 values [MONO_FIELD_RVA_RVA] = rva_idx + assembly->text_rva;
2021         }
2022         if (fb->marshal_info) {
2023                 table = &assembly->tables [MONO_TABLE_FIELDMARSHAL];
2024                 table->rows ++;
2025                 alloc_table (table, table->rows);
2026                 values = table->values + table->rows * MONO_FIELD_MARSHAL_SIZE;
2027                 values [MONO_FIELD_MARSHAL_PARENT] = (fb->table_idx << MONO_HAS_FIELD_MARSHAL_BITS) | MONO_HAS_FIELD_MARSHAL_FIELDSREF;
2028                 values [MONO_FIELD_MARSHAL_NATIVE_TYPE] = encode_marshal_blob (assembly, fb->marshal_info);
2029         }
2030 }
2031
2032 static guint32
2033 property_encode_signature (MonoDynamicImage *assembly, MonoReflectionPropertyBuilder *fb)
2034 {
2035         SigBuffer buf;
2036         guint32 nparams = 0;
2037         MonoReflectionMethodBuilder *mb = fb->get_method;
2038         MonoReflectionMethodBuilder *smb = fb->set_method;
2039         guint32 idx, i;
2040
2041         if (mb && mb->parameters)
2042                 nparams = mono_array_length (mb->parameters);
2043         if (!mb && smb && smb->parameters)
2044                 nparams = mono_array_length (smb->parameters) - 1;
2045         sigbuffer_init (&buf, 32);
2046         if (fb->call_conv & 0x20)
2047                 sigbuffer_add_byte (&buf, 0x28);
2048         else
2049                 sigbuffer_add_byte (&buf, 0x08);
2050         sigbuffer_add_value (&buf, nparams);
2051         if (mb) {
2052                 encode_reflection_type (assembly, (MonoReflectionType*)mb->rtype, &buf);
2053                 for (i = 0; i < nparams; ++i) {
2054                         MonoReflectionType *pt = mono_array_get (mb->parameters, MonoReflectionType*, i);
2055                         encode_reflection_type (assembly, pt, &buf);
2056                 }
2057         } else if (smb && smb->parameters) {
2058                 /* the property type is the last param */
2059                 encode_reflection_type (assembly, mono_array_get (smb->parameters, MonoReflectionType*, nparams), &buf);
2060                 for (i = 0; i < nparams; ++i) {
2061                         MonoReflectionType *pt = mono_array_get (smb->parameters, MonoReflectionType*, i);
2062                         encode_reflection_type (assembly, pt, &buf);
2063                 }
2064         } else {
2065                 encode_reflection_type (assembly, (MonoReflectionType*)fb->type, &buf);
2066         }
2067
2068         idx = sigbuffer_add_to_blob_cached (assembly, &buf);
2069         sigbuffer_free (&buf);
2070         return idx;
2071 }
2072
2073 static void
2074 mono_image_get_property_info (MonoReflectionPropertyBuilder *pb, MonoDynamicImage *assembly)
2075 {
2076         MonoDynamicTable *table;
2077         guint32 *values;
2078         guint num_methods = 0;
2079         guint32 semaidx;
2080
2081         /* 
2082          * we need to set things in the following tables:
2083          * PROPERTYMAP (info already filled in _get_type_info ())
2084          * PROPERTY    (rows already preallocated in _get_type_info ())
2085          * METHOD      (method info already done with the generic method code)
2086          * METHODSEMANTICS
2087          * CONSTANT
2088          */
2089         table = &assembly->tables [MONO_TABLE_PROPERTY];
2090         pb->table_idx = table->next_idx ++;
2091         values = table->values + pb->table_idx * MONO_PROPERTY_SIZE;
2092         values [MONO_PROPERTY_NAME] = string_heap_insert_mstring (&assembly->sheap, pb->name);
2093         values [MONO_PROPERTY_FLAGS] = pb->attrs;
2094         values [MONO_PROPERTY_TYPE] = property_encode_signature (assembly, pb);
2095
2096         /* FIXME: we still don't handle 'other' methods */
2097         if (pb->get_method) num_methods ++;
2098         if (pb->set_method) num_methods ++;
2099
2100         table = &assembly->tables [MONO_TABLE_METHODSEMANTICS];
2101         table->rows += num_methods;
2102         alloc_table (table, table->rows);
2103
2104         if (pb->get_method) {
2105                 semaidx = table->next_idx ++;
2106                 values = table->values + semaidx * MONO_METHOD_SEMA_SIZE;
2107                 values [MONO_METHOD_SEMA_SEMANTICS] = METHOD_SEMANTIC_GETTER;
2108                 values [MONO_METHOD_SEMA_METHOD] = pb->get_method->table_idx;
2109                 values [MONO_METHOD_SEMA_ASSOCIATION] = (pb->table_idx << MONO_HAS_SEMANTICS_BITS) | MONO_HAS_SEMANTICS_PROPERTY;
2110         }
2111         if (pb->set_method) {
2112                 semaidx = table->next_idx ++;
2113                 values = table->values + semaidx * MONO_METHOD_SEMA_SIZE;
2114                 values [MONO_METHOD_SEMA_SEMANTICS] = METHOD_SEMANTIC_SETTER;
2115                 values [MONO_METHOD_SEMA_METHOD] = pb->set_method->table_idx;
2116                 values [MONO_METHOD_SEMA_ASSOCIATION] = (pb->table_idx << MONO_HAS_SEMANTICS_BITS) | MONO_HAS_SEMANTICS_PROPERTY;
2117         }
2118         if (pb->attrs & PROPERTY_ATTRIBUTE_HAS_DEFAULT) {
2119                 guint32 field_type = 0;
2120                 table = &assembly->tables [MONO_TABLE_CONSTANT];
2121                 table->rows ++;
2122                 alloc_table (table, table->rows);
2123                 values = table->values + table->rows * MONO_CONSTANT_SIZE;
2124                 values [MONO_CONSTANT_PARENT] = MONO_HASCONSTANT_PROPERTY | (pb->table_idx << MONO_HASCONSTANT_BITS);
2125                 values [MONO_CONSTANT_VALUE] = encode_constant (assembly, pb->def_value, &field_type);
2126                 values [MONO_CONSTANT_TYPE] = field_type;
2127                 values [MONO_CONSTANT_PADDING] = 0;
2128         }
2129 }
2130
2131 static void
2132 mono_image_get_event_info (MonoReflectionEventBuilder *eb, MonoDynamicImage *assembly)
2133 {
2134         MonoDynamicTable *table;
2135         guint32 *values;
2136         guint num_methods = 0;
2137         guint32 semaidx;
2138
2139         /* 
2140          * we need to set things in the following tables:
2141          * EVENTMAP (info already filled in _get_type_info ())
2142          * EVENT    (rows already preallocated in _get_type_info ())
2143          * METHOD      (method info already done with the generic method code)
2144          * METHODSEMANTICS
2145          */
2146         table = &assembly->tables [MONO_TABLE_EVENT];
2147         eb->table_idx = table->next_idx ++;
2148         values = table->values + eb->table_idx * MONO_EVENT_SIZE;
2149         values [MONO_EVENT_NAME] = string_heap_insert_mstring (&assembly->sheap, eb->name);
2150         values [MONO_EVENT_FLAGS] = eb->attrs;
2151         values [MONO_EVENT_TYPE] = mono_image_typedef_or_ref (assembly, mono_reflection_type_get_handle (eb->type));
2152
2153         /*
2154          * FIXME: we still don't handle 'other' methods 
2155          */
2156         if (eb->add_method) num_methods ++;
2157         if (eb->remove_method) num_methods ++;
2158         if (eb->raise_method) num_methods ++;
2159
2160         table = &assembly->tables [MONO_TABLE_METHODSEMANTICS];
2161         table->rows += num_methods;
2162         alloc_table (table, table->rows);
2163
2164         if (eb->add_method) {
2165                 semaidx = table->next_idx ++;
2166                 values = table->values + semaidx * MONO_METHOD_SEMA_SIZE;
2167                 values [MONO_METHOD_SEMA_SEMANTICS] = METHOD_SEMANTIC_ADD_ON;
2168                 values [MONO_METHOD_SEMA_METHOD] = eb->add_method->table_idx;
2169                 values [MONO_METHOD_SEMA_ASSOCIATION] = (eb->table_idx << MONO_HAS_SEMANTICS_BITS) | MONO_HAS_SEMANTICS_EVENT;
2170         }
2171         if (eb->remove_method) {
2172                 semaidx = table->next_idx ++;
2173                 values = table->values + semaidx * MONO_METHOD_SEMA_SIZE;
2174                 values [MONO_METHOD_SEMA_SEMANTICS] = METHOD_SEMANTIC_REMOVE_ON;
2175                 values [MONO_METHOD_SEMA_METHOD] = eb->remove_method->table_idx;
2176                 values [MONO_METHOD_SEMA_ASSOCIATION] = (eb->table_idx << MONO_HAS_SEMANTICS_BITS) | MONO_HAS_SEMANTICS_EVENT;
2177         }
2178         if (eb->raise_method) {
2179                 semaidx = table->next_idx ++;
2180                 values = table->values + semaidx * MONO_METHOD_SEMA_SIZE;
2181                 values [MONO_METHOD_SEMA_SEMANTICS] = METHOD_SEMANTIC_FIRE;
2182                 values [MONO_METHOD_SEMA_METHOD] = eb->raise_method->table_idx;
2183                 values [MONO_METHOD_SEMA_ASSOCIATION] = (eb->table_idx << MONO_HAS_SEMANTICS_BITS) | MONO_HAS_SEMANTICS_EVENT;
2184         }
2185 }
2186
2187 static void
2188 encode_constraints (MonoReflectionGenericParam *gparam, guint32 owner, MonoDynamicImage *assembly)
2189 {
2190         MonoDynamicTable *table;
2191         guint32 num_constraints, i;
2192         guint32 *values;
2193         guint32 table_idx;
2194
2195         table = &assembly->tables [MONO_TABLE_GENERICPARAMCONSTRAINT];
2196         num_constraints = gparam->iface_constraints ?
2197                 mono_array_length (gparam->iface_constraints) : 0;
2198         table->rows += num_constraints;
2199         if (gparam->base_type)
2200                 table->rows++;
2201         alloc_table (table, table->rows);
2202
2203         if (gparam->base_type) {
2204                 table_idx = table->next_idx ++;
2205                 values = table->values + table_idx * MONO_GENPARCONSTRAINT_SIZE;
2206
2207                 values [MONO_GENPARCONSTRAINT_GENERICPAR] = owner;
2208                 values [MONO_GENPARCONSTRAINT_CONSTRAINT] = mono_image_typedef_or_ref (
2209                         assembly, mono_reflection_type_get_handle (gparam->base_type));
2210         }
2211
2212         for (i = 0; i < num_constraints; i++) {
2213                 MonoReflectionType *constraint = mono_array_get (
2214                         gparam->iface_constraints, gpointer, i);
2215
2216                 table_idx = table->next_idx ++;
2217                 values = table->values + table_idx * MONO_GENPARCONSTRAINT_SIZE;
2218
2219                 values [MONO_GENPARCONSTRAINT_GENERICPAR] = owner;
2220                 values [MONO_GENPARCONSTRAINT_CONSTRAINT] = mono_image_typedef_or_ref (
2221                         assembly, mono_reflection_type_get_handle (constraint));
2222         }
2223 }
2224
2225 static void
2226 mono_image_get_generic_param_info (MonoReflectionGenericParam *gparam, guint32 owner, MonoDynamicImage *assembly)
2227 {
2228         GenericParamTableEntry *entry;
2229
2230         /*
2231          * The GenericParam table must be sorted according to the `owner' field.
2232          * We need to do this sorting prior to writing the GenericParamConstraint
2233          * table, since we have to use the final GenericParam table indices there
2234          * and they must also be sorted.
2235          */
2236
2237         entry = g_new0 (GenericParamTableEntry, 1);
2238         entry->owner = owner;
2239         /* FIXME: track where gen_params should be freed and remove the GC root as well */
2240         MONO_GC_REGISTER_ROOT_IF_MOVING (entry->gparam);
2241         entry->gparam = gparam;
2242         
2243         g_ptr_array_add (assembly->gen_params, entry);
2244 }
2245
2246 static void
2247 write_generic_param_entry (MonoDynamicImage *assembly, GenericParamTableEntry *entry)
2248 {
2249         MonoDynamicTable *table;
2250         MonoGenericParam *param;
2251         guint32 *values;
2252         guint32 table_idx;
2253
2254         table = &assembly->tables [MONO_TABLE_GENERICPARAM];
2255         table_idx = table->next_idx ++;
2256         values = table->values + table_idx * MONO_GENERICPARAM_SIZE;
2257
2258         param = mono_reflection_type_get_handle ((MonoReflectionType*)entry->gparam)->data.generic_param;
2259
2260         values [MONO_GENERICPARAM_OWNER] = entry->owner;
2261         values [MONO_GENERICPARAM_FLAGS] = entry->gparam->attrs;
2262         values [MONO_GENERICPARAM_NUMBER] = mono_generic_param_num (param);
2263         values [MONO_GENERICPARAM_NAME] = string_heap_insert (&assembly->sheap, mono_generic_param_info (param)->name);
2264
2265         mono_image_add_cattrs (assembly, table_idx, MONO_CUSTOM_ATTR_GENERICPAR, entry->gparam->cattrs);
2266
2267         encode_constraints (entry->gparam, table_idx, assembly);
2268 }
2269
2270 static guint32
2271 resolution_scope_from_image (MonoDynamicImage *assembly, MonoImage *image)
2272 {
2273         MonoDynamicTable *table;
2274         guint32 token;
2275         guint32 *values;
2276         guint32 cols [MONO_ASSEMBLY_SIZE];
2277         const char *pubkey;
2278         guint32 publen;
2279
2280         if ((token = GPOINTER_TO_UINT (g_hash_table_lookup (assembly->handleref, image))))
2281                 return token;
2282
2283         if (assembly_is_dynamic (image->assembly) && (image->assembly == assembly->image.assembly)) {
2284                 table = &assembly->tables [MONO_TABLE_MODULEREF];
2285                 token = table->next_idx ++;
2286                 table->rows ++;
2287                 alloc_table (table, table->rows);
2288                 values = table->values + token * MONO_MODULEREF_SIZE;
2289                 values [MONO_MODULEREF_NAME] = string_heap_insert (&assembly->sheap, image->module_name);
2290
2291                 token <<= MONO_RESOLUTION_SCOPE_BITS;
2292                 token |= MONO_RESOLUTION_SCOPE_MODULEREF;
2293                 g_hash_table_insert (assembly->handleref, image, GUINT_TO_POINTER (token));
2294
2295                 return token;
2296         }
2297         
2298         if (assembly_is_dynamic (image->assembly))
2299                 /* FIXME: */
2300                 memset (cols, 0, sizeof (cols));
2301         else {
2302                 /* image->assembly->image is the manifest module */
2303                 image = image->assembly->image;
2304                 mono_metadata_decode_row (&image->tables [MONO_TABLE_ASSEMBLY], 0, cols, MONO_ASSEMBLY_SIZE);
2305         }
2306
2307         table = &assembly->tables [MONO_TABLE_ASSEMBLYREF];
2308         token = table->next_idx ++;
2309         table->rows ++;
2310         alloc_table (table, table->rows);
2311         values = table->values + token * MONO_ASSEMBLYREF_SIZE;
2312         values [MONO_ASSEMBLYREF_NAME] = string_heap_insert (&assembly->sheap, image->assembly_name);
2313         values [MONO_ASSEMBLYREF_MAJOR_VERSION] = cols [MONO_ASSEMBLY_MAJOR_VERSION];
2314         values [MONO_ASSEMBLYREF_MINOR_VERSION] = cols [MONO_ASSEMBLY_MINOR_VERSION];
2315         values [MONO_ASSEMBLYREF_BUILD_NUMBER] = cols [MONO_ASSEMBLY_BUILD_NUMBER];
2316         values [MONO_ASSEMBLYREF_REV_NUMBER] = cols [MONO_ASSEMBLY_REV_NUMBER];
2317         values [MONO_ASSEMBLYREF_FLAGS] = 0;
2318         values [MONO_ASSEMBLYREF_CULTURE] = 0;
2319         values [MONO_ASSEMBLYREF_HASH_VALUE] = 0;
2320
2321         if (strcmp ("", image->assembly->aname.culture)) {
2322                 values [MONO_ASSEMBLYREF_CULTURE] = string_heap_insert (&assembly->sheap,
2323                                 image->assembly->aname.culture);
2324         }
2325
2326         if ((pubkey = mono_image_get_public_key (image, &publen))) {
2327                 guchar pubtoken [9];
2328                 pubtoken [0] = 8;
2329                 mono_digest_get_public_token (pubtoken + 1, (guchar*)pubkey, publen);
2330                 values [MONO_ASSEMBLYREF_PUBLIC_KEY] = mono_image_add_stream_data (&assembly->blob, (char*)pubtoken, 9);
2331         } else {
2332                 values [MONO_ASSEMBLYREF_PUBLIC_KEY] = 0;
2333         }
2334         token <<= MONO_RESOLUTION_SCOPE_BITS;
2335         token |= MONO_RESOLUTION_SCOPE_ASSEMBLYREF;
2336         g_hash_table_insert (assembly->handleref, image, GUINT_TO_POINTER (token));
2337         return token;
2338 }
2339
2340 static guint32
2341 create_typespec (MonoDynamicImage *assembly, MonoType *type)
2342 {
2343         MonoDynamicTable *table;
2344         guint32 *values;
2345         guint32 token;
2346         SigBuffer buf;
2347
2348         if ((token = GPOINTER_TO_UINT (g_hash_table_lookup (assembly->typespec, type))))
2349                 return token;
2350
2351         sigbuffer_init (&buf, 32);
2352         switch (type->type) {
2353         case MONO_TYPE_FNPTR:
2354         case MONO_TYPE_PTR:
2355         case MONO_TYPE_SZARRAY:
2356         case MONO_TYPE_ARRAY:
2357         case MONO_TYPE_VAR:
2358         case MONO_TYPE_MVAR:
2359         case MONO_TYPE_GENERICINST:
2360                 encode_type (assembly, type, &buf);
2361                 break;
2362         case MONO_TYPE_CLASS:
2363         case MONO_TYPE_VALUETYPE: {
2364                 MonoClass *k = mono_class_from_mono_type (type);
2365                 if (!k || !k->generic_container) {
2366                         sigbuffer_free (&buf);
2367                         return 0;
2368                 }
2369                 encode_type (assembly, type, &buf);
2370                 break;
2371         }
2372         default:
2373                 sigbuffer_free (&buf);
2374                 return 0;
2375         }
2376
2377         table = &assembly->tables [MONO_TABLE_TYPESPEC];
2378         if (assembly->save) {
2379                 token = sigbuffer_add_to_blob_cached (assembly, &buf);
2380                 alloc_table (table, table->rows + 1);
2381                 values = table->values + table->next_idx * MONO_TYPESPEC_SIZE;
2382                 values [MONO_TYPESPEC_SIGNATURE] = token;
2383         }
2384         sigbuffer_free (&buf);
2385
2386         token = MONO_TYPEDEFORREF_TYPESPEC | (table->next_idx << MONO_TYPEDEFORREF_BITS);
2387         g_hash_table_insert (assembly->typespec, type, GUINT_TO_POINTER(token));
2388         table->next_idx ++;
2389         return token;
2390 }
2391
2392 static guint32
2393 mono_image_typedef_or_ref_full (MonoDynamicImage *assembly, MonoType *type, gboolean try_typespec)
2394 {
2395         MonoDynamicTable *table;
2396         guint32 *values;
2397         guint32 token, scope, enclosing;
2398         MonoClass *klass;
2399
2400         /* if the type requires a typespec, we must try that first*/
2401         if (try_typespec && (token = create_typespec (assembly, type)))
2402                 return token;
2403         token = GPOINTER_TO_UINT (g_hash_table_lookup (assembly->typeref, type));
2404         if (token)
2405                 return token;
2406         klass = mono_class_from_mono_type (type);
2407         if (!klass)
2408                 klass = mono_class_from_mono_type (type);
2409
2410         /*
2411          * If it's in the same module and not a generic type parameter:
2412          */
2413         if ((klass->image == &assembly->image) && (type->type != MONO_TYPE_VAR) && 
2414                         (type->type != MONO_TYPE_MVAR)) {
2415                 MonoReflectionTypeBuilder *tb = mono_class_get_ref_info (klass);
2416                 token = MONO_TYPEDEFORREF_TYPEDEF | (tb->table_idx << MONO_TYPEDEFORREF_BITS);
2417                 register_dyn_token (assembly, token, mono_class_get_ref_info (klass));
2418                 return token;
2419         }
2420
2421         if (klass->nested_in) {
2422                 enclosing = mono_image_typedef_or_ref_full (assembly, &klass->nested_in->byval_arg, FALSE);
2423                 /* get the typeref idx of the enclosing type */
2424                 enclosing >>= MONO_TYPEDEFORREF_BITS;
2425                 scope = (enclosing << MONO_RESOLUTION_SCOPE_BITS) | MONO_RESOLUTION_SCOPE_TYPEREF;
2426         } else {
2427                 scope = resolution_scope_from_image (assembly, klass->image);
2428         }
2429         table = &assembly->tables [MONO_TABLE_TYPEREF];
2430         if (assembly->save) {
2431                 alloc_table (table, table->rows + 1);
2432                 values = table->values + table->next_idx * MONO_TYPEREF_SIZE;
2433                 values [MONO_TYPEREF_SCOPE] = scope;
2434                 values [MONO_TYPEREF_NAME] = string_heap_insert (&assembly->sheap, klass->name);
2435                 values [MONO_TYPEREF_NAMESPACE] = string_heap_insert (&assembly->sheap, klass->name_space);
2436         }
2437         token = MONO_TYPEDEFORREF_TYPEREF | (table->next_idx << MONO_TYPEDEFORREF_BITS); /* typeref */
2438         g_hash_table_insert (assembly->typeref, type, GUINT_TO_POINTER(token));
2439         table->next_idx ++;
2440         register_dyn_token (assembly, token, mono_class_get_ref_info (klass));
2441         return token;
2442 }
2443
2444 /*
2445  * Despite the name, we handle also TypeSpec (with the above helper).
2446  */
2447 static guint32
2448 mono_image_typedef_or_ref (MonoDynamicImage *assembly, MonoType *type)
2449 {
2450         return mono_image_typedef_or_ref_full (assembly, type, TRUE);
2451 }
2452
2453 #ifndef DISABLE_REFLECTION_EMIT
2454 static guint32
2455 mono_image_add_memberef_row (MonoDynamicImage *assembly, guint32 parent, const char *name, guint32 sig)
2456 {
2457         MonoDynamicTable *table;
2458         guint32 *values;
2459         guint32 token, pclass;
2460
2461         switch (parent & MONO_TYPEDEFORREF_MASK) {
2462         case MONO_TYPEDEFORREF_TYPEREF:
2463                 pclass = MONO_MEMBERREF_PARENT_TYPEREF;
2464                 break;
2465         case MONO_TYPEDEFORREF_TYPESPEC:
2466                 pclass = MONO_MEMBERREF_PARENT_TYPESPEC;
2467                 break;
2468         case MONO_TYPEDEFORREF_TYPEDEF:
2469                 pclass = MONO_MEMBERREF_PARENT_TYPEDEF;
2470                 break;
2471         default:
2472                 g_warning ("unknown typeref or def token 0x%08x for %s", parent, name);
2473                 return 0;
2474         }
2475         /* extract the index */
2476         parent >>= MONO_TYPEDEFORREF_BITS;
2477
2478         table = &assembly->tables [MONO_TABLE_MEMBERREF];
2479
2480         if (assembly->save) {
2481                 alloc_table (table, table->rows + 1);
2482                 values = table->values + table->next_idx * MONO_MEMBERREF_SIZE;
2483                 values [MONO_MEMBERREF_CLASS] = pclass | (parent << MONO_MEMBERREF_PARENT_BITS);
2484                 values [MONO_MEMBERREF_NAME] = string_heap_insert (&assembly->sheap, name);
2485                 values [MONO_MEMBERREF_SIGNATURE] = sig;
2486         }
2487
2488         token = MONO_TOKEN_MEMBER_REF | table->next_idx;
2489         table->next_idx ++;
2490
2491         return token;
2492 }
2493
2494 /*
2495  * Insert a memberef row into the metadata: the token that point to the memberref
2496  * is returned. Caching is done in the caller (mono_image_get_methodref_token() or
2497  * mono_image_get_fieldref_token()).
2498  * The sig param is an index to an already built signature.
2499  */
2500 static guint32
2501 mono_image_get_memberref_token (MonoDynamicImage *assembly, MonoType *type, const char *name, guint32 sig)
2502 {
2503         guint32 parent = mono_image_typedef_or_ref (assembly, type);
2504         return mono_image_add_memberef_row (assembly, parent, name, sig);
2505 }
2506
2507
2508 static guint32
2509 mono_image_get_methodref_token (MonoDynamicImage *assembly, MonoMethod *method, gboolean create_typespec)
2510 {
2511         guint32 token;
2512         MonoMethodSignature *sig;
2513         
2514         create_typespec = create_typespec && method->is_generic && method->klass->image != &assembly->image;
2515
2516         if (create_typespec) {
2517                 token = GPOINTER_TO_UINT (g_hash_table_lookup (assembly->handleref, GUINT_TO_POINTER (GPOINTER_TO_UINT (method) + 1)));
2518                 if (token)
2519                         return token;
2520         } 
2521
2522         token = GPOINTER_TO_UINT (g_hash_table_lookup (assembly->handleref, method));
2523         if (token && !create_typespec)
2524                 return token;
2525
2526         g_assert (!method->is_inflated);
2527         if (!token) {
2528                 /*
2529                  * A methodref signature can't contain an unmanaged calling convention.
2530                  */
2531                 sig = mono_metadata_signature_dup (mono_method_signature (method));
2532                 if ((sig->call_convention != MONO_CALL_DEFAULT) && (sig->call_convention != MONO_CALL_VARARG))
2533                         sig->call_convention = MONO_CALL_DEFAULT;
2534                 token = mono_image_get_memberref_token (assembly, &method->klass->byval_arg,
2535                         method->name,  method_encode_signature (assembly, sig));
2536                 g_free (sig);
2537                 g_hash_table_insert (assembly->handleref, method, GUINT_TO_POINTER(token));
2538         }
2539
2540         if (create_typespec) {
2541                 MonoDynamicTable *table = &assembly->tables [MONO_TABLE_METHODSPEC];
2542                 g_assert (mono_metadata_token_table (token) == MONO_TABLE_MEMBERREF);
2543                 token = (mono_metadata_token_index (token) << MONO_METHODDEFORREF_BITS) | MONO_METHODDEFORREF_METHODREF;
2544
2545                 if (assembly->save) {
2546                         guint32 *values;
2547
2548                         alloc_table (table, table->rows + 1);
2549                         values = table->values + table->next_idx * MONO_METHODSPEC_SIZE;
2550                         values [MONO_METHODSPEC_METHOD] = token;
2551                         values [MONO_METHODSPEC_SIGNATURE] = encode_generic_method_sig (assembly, &mono_method_get_generic_container (method)->context);
2552                 }
2553
2554                 token = MONO_TOKEN_METHOD_SPEC | table->next_idx;
2555                 table->next_idx ++;
2556                 /*methodspec and memberef tokens are diferent, */
2557                 g_hash_table_insert (assembly->handleref, GUINT_TO_POINTER (GPOINTER_TO_UINT (method) + 1), GUINT_TO_POINTER (token));
2558                 return token;
2559         }
2560         return token;
2561 }
2562
2563 static guint32
2564 mono_image_get_methodref_token_for_methodbuilder (MonoDynamicImage *assembly, MonoReflectionMethodBuilder *method)
2565 {
2566         guint32 token, parent, sig;
2567         ReflectionMethodBuilder rmb;
2568         char *name;
2569         MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder *)method->type;
2570         
2571         token = GPOINTER_TO_UINT (g_hash_table_lookup (assembly->handleref, method));
2572         if (token)
2573                 return token;
2574
2575         name = mono_string_to_utf8 (method->name);
2576         reflection_methodbuilder_from_method_builder (&rmb, method);
2577
2578         /*
2579          * A methodref signature can't contain an unmanaged calling convention.
2580          * Since some flags are encoded as part of call_conv, we need to check against it.
2581         */
2582         if ((rmb.call_conv & ~0x60) != MONO_CALL_DEFAULT && (rmb.call_conv & ~0x60) != MONO_CALL_VARARG)
2583                 rmb.call_conv = (rmb.call_conv & 0x60) | MONO_CALL_DEFAULT;
2584
2585         sig = method_builder_encode_signature (assembly, &rmb);
2586
2587         if (tb->generic_params)
2588                 parent = create_generic_typespec (assembly, tb);
2589         else
2590                 parent = mono_image_typedef_or_ref (assembly, mono_reflection_type_get_handle ((MonoReflectionType*)rmb.type));
2591
2592         token = mono_image_add_memberef_row (assembly, parent, name, sig);
2593
2594         g_free (name);
2595         g_hash_table_insert (assembly->handleref, method, GUINT_TO_POINTER(token));
2596         return token;
2597 }
2598
2599 static guint32
2600 mono_image_get_varargs_method_token (MonoDynamicImage *assembly, guint32 original,
2601                                      const gchar *name, guint32 sig)
2602 {
2603         MonoDynamicTable *table;
2604         guint32 token;
2605         guint32 *values;
2606         
2607         table = &assembly->tables [MONO_TABLE_MEMBERREF];
2608
2609         if (assembly->save) {
2610                 alloc_table (table, table->rows + 1);
2611                 values = table->values + table->next_idx * MONO_MEMBERREF_SIZE;
2612                 values [MONO_MEMBERREF_CLASS] = original;
2613                 values [MONO_MEMBERREF_NAME] = string_heap_insert (&assembly->sheap, name);
2614                 values [MONO_MEMBERREF_SIGNATURE] = sig;
2615         }
2616
2617         token = MONO_TOKEN_MEMBER_REF | table->next_idx;
2618         table->next_idx ++;
2619
2620         return token;
2621 }
2622
2623 static guint32
2624 encode_generic_method_definition_sig (MonoDynamicImage *assembly, MonoReflectionMethodBuilder *mb)
2625 {
2626         SigBuffer buf;
2627         int i;
2628         guint32 nparams = mono_array_length (mb->generic_params);
2629         guint32 idx;
2630
2631         if (!assembly->save)
2632                 return 0;
2633
2634         sigbuffer_init (&buf, 32);
2635
2636         sigbuffer_add_value (&buf, 0xa);
2637         sigbuffer_add_value (&buf, nparams);
2638
2639         for (i = 0; i < nparams; i++) {
2640                 sigbuffer_add_value (&buf, MONO_TYPE_MVAR);
2641                 sigbuffer_add_value (&buf, i);
2642         }
2643
2644         idx = sigbuffer_add_to_blob_cached (assembly, &buf);
2645         sigbuffer_free (&buf);
2646         return idx;
2647 }
2648
2649 static guint32
2650 mono_image_get_methodspec_token_for_generic_method_definition (MonoDynamicImage *assembly, MonoReflectionMethodBuilder *mb)
2651 {
2652         MonoDynamicTable *table;
2653         guint32 *values;
2654         guint32 token, mtoken = 0;
2655
2656         token = GPOINTER_TO_UINT (mono_g_hash_table_lookup (assembly->methodspec, mb));
2657         if (token)
2658                 return token;
2659
2660         table = &assembly->tables [MONO_TABLE_METHODSPEC];
2661
2662         mtoken = mono_image_get_methodref_token_for_methodbuilder (assembly, mb);
2663         switch (mono_metadata_token_table (mtoken)) {
2664         case MONO_TABLE_MEMBERREF:
2665                 mtoken = (mono_metadata_token_index (mtoken) << MONO_METHODDEFORREF_BITS) | MONO_METHODDEFORREF_METHODREF;
2666                 break;
2667         case MONO_TABLE_METHOD:
2668                 mtoken = (mono_metadata_token_index (mtoken) << MONO_METHODDEFORREF_BITS) | MONO_METHODDEFORREF_METHODDEF;
2669                 break;
2670         default:
2671                 g_assert_not_reached ();
2672         }
2673
2674         if (assembly->save) {
2675                 alloc_table (table, table->rows + 1);
2676                 values = table->values + table->next_idx * MONO_METHODSPEC_SIZE;
2677                 values [MONO_METHODSPEC_METHOD] = mtoken;
2678                 values [MONO_METHODSPEC_SIGNATURE] = encode_generic_method_definition_sig (assembly, mb);
2679         }
2680
2681         token = MONO_TOKEN_METHOD_SPEC | table->next_idx;
2682         table->next_idx ++;
2683
2684         mono_g_hash_table_insert (assembly->methodspec, mb, GUINT_TO_POINTER(token));
2685         return token;
2686 }
2687
2688 static guint32
2689 mono_image_get_methodbuilder_token (MonoDynamicImage *assembly, MonoReflectionMethodBuilder *mb, gboolean create_methodspec)
2690 {
2691         guint32 token;
2692
2693         if (mb->generic_params && create_methodspec) 
2694                 return mono_image_get_methodspec_token_for_generic_method_definition (assembly, mb);
2695
2696         token = GPOINTER_TO_UINT (mono_g_hash_table_lookup (assembly->handleref_managed, mb));
2697         if (token)
2698                 return token;
2699
2700         token = mono_image_get_methodref_token_for_methodbuilder (assembly, mb);
2701         mono_g_hash_table_insert (assembly->handleref_managed, mb, GUINT_TO_POINTER(token));
2702         return token;
2703 }
2704
2705 static guint32
2706 mono_image_get_ctorbuilder_token (MonoDynamicImage *assembly, MonoReflectionCtorBuilder *mb)
2707 {
2708         guint32 token, parent, sig;
2709         ReflectionMethodBuilder rmb;
2710         char *name;
2711         MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder *)mb->type;
2712         
2713         token = GPOINTER_TO_UINT (mono_g_hash_table_lookup (assembly->handleref_managed, mb));
2714         if (token)
2715                 return token;
2716
2717         reflection_methodbuilder_from_ctor_builder (&rmb, mb);
2718
2719         if (tb->generic_params)
2720                 parent = create_generic_typespec (assembly, tb);
2721         else
2722                 parent = mono_image_typedef_or_ref (assembly, mono_reflection_type_get_handle ((MonoReflectionType*)tb));
2723         
2724         name = mono_string_to_utf8 (rmb.name);
2725         sig = method_builder_encode_signature (assembly, &rmb);
2726
2727         token = mono_image_add_memberef_row (assembly, parent, name, sig);
2728
2729         g_free (name);
2730         mono_g_hash_table_insert (assembly->handleref_managed, mb, GUINT_TO_POINTER(token));
2731         return token;
2732 }
2733 #endif
2734
2735 static gboolean
2736 is_field_on_inst (MonoClassField *field)
2737 {
2738         return (field->parent->generic_class && field->parent->generic_class->is_dynamic && ((MonoDynamicGenericClass*)field->parent->generic_class)->fields);
2739 }
2740
2741 /*
2742  * If FIELD is a field of a MonoDynamicGenericClass, return its non-inflated type.
2743  */
2744 static MonoType*
2745 get_field_on_inst_generic_type (MonoClassField *field)
2746 {
2747         MonoClass *class, *gtd;
2748         MonoDynamicGenericClass *dgclass;
2749         int field_index;
2750
2751         g_assert (is_field_on_inst (field));
2752
2753         dgclass = (MonoDynamicGenericClass*)field->parent->generic_class;
2754
2755         if (field >= dgclass->fields && field - dgclass->fields < dgclass->count_fields) {
2756                 field_index = field - dgclass->fields;
2757                 return dgclass->field_generic_types [field_index];              
2758         }
2759
2760         class = field->parent;
2761         gtd = class->generic_class->container_class;
2762
2763         if (field >= class->fields && field - class->fields < class->field.count) {
2764                 field_index = field - class->fields;
2765                 return gtd->fields [field_index].type;
2766         }
2767
2768         g_assert_not_reached ();
2769         return 0;
2770 }
2771
2772 #ifndef DISABLE_REFLECTION_EMIT
2773 static guint32
2774 mono_image_get_fieldref_token (MonoDynamicImage *assembly, MonoObject *f, MonoClassField *field)
2775 {
2776         MonoType *type;
2777         guint32 token;
2778
2779         g_assert (field);
2780         g_assert (field->parent);
2781
2782         token = GPOINTER_TO_UINT (mono_g_hash_table_lookup (assembly->handleref_managed, f));
2783         if (token)
2784                 return token;
2785
2786         if (field->parent->generic_class && field->parent->generic_class->container_class && field->parent->generic_class->container_class->fields) {
2787                 int index = field - field->parent->fields;
2788                 type = mono_field_get_type (&field->parent->generic_class->container_class->fields [index]);
2789         } else {
2790                 if (is_field_on_inst (field))
2791                         type = get_field_on_inst_generic_type (field);
2792                 else
2793                         type = mono_field_get_type (field);
2794         }
2795         token = mono_image_get_memberref_token (assembly, &field->parent->byval_arg,
2796                                                                                         mono_field_get_name (field),
2797                                                                                         fieldref_encode_signature (assembly, field->parent->image, type));
2798         mono_g_hash_table_insert (assembly->handleref_managed, f, GUINT_TO_POINTER(token));
2799         return token;
2800 }
2801
2802 static guint32
2803 mono_image_get_field_on_inst_token (MonoDynamicImage *assembly, MonoReflectionFieldOnTypeBuilderInst *f)
2804 {
2805         guint32 token;
2806         MonoClass *klass;
2807         MonoGenericClass *gclass;
2808         MonoType *type;
2809         char *name;
2810
2811         token = GPOINTER_TO_UINT (mono_g_hash_table_lookup (assembly->handleref_managed, f));
2812         if (token)
2813                 return token;
2814         if (is_sre_field_builder (mono_object_class (f->fb))) {
2815                 MonoReflectionFieldBuilder *fb = (MonoReflectionFieldBuilder *)f->fb;
2816                 type = mono_reflection_type_get_handle ((MonoReflectionType*)f->inst);
2817                 klass = mono_class_from_mono_type (type);
2818                 gclass = type->data.generic_class;
2819                 g_assert (gclass->is_dynamic);
2820
2821                 name = mono_string_to_utf8 (fb->name);
2822                 token = mono_image_get_memberref_token (assembly, &klass->byval_arg, name, 
2823                                                                                                 field_encode_signature (assembly, fb));
2824                 g_free (name);          
2825         } else if (is_sr_mono_field (mono_object_class (f->fb))) {
2826                 guint32 sig;
2827                 MonoClassField *field = ((MonoReflectionField *)f->fb)->field;
2828
2829                 type = mono_reflection_type_get_handle ((MonoReflectionType*)f->inst);
2830                 klass = mono_class_from_mono_type (type);
2831
2832                 sig = fieldref_encode_signature (assembly, field->parent->image, field->type);
2833                 token = mono_image_get_memberref_token (assembly, &klass->byval_arg, field->name, sig);
2834         } else {
2835                 char *name = mono_type_get_full_name (mono_object_class (f->fb));
2836                 g_error ("mono_image_get_field_on_inst_token: don't know how to handle %s", name);
2837         }
2838
2839         mono_g_hash_table_insert (assembly->handleref_managed, f, GUINT_TO_POINTER (token));
2840         return token;
2841 }
2842
2843 static guint32
2844 mono_image_get_ctor_on_inst_token (MonoDynamicImage *assembly, MonoReflectionCtorOnTypeBuilderInst *c, gboolean create_methodspec)
2845 {
2846         guint32 sig, token;
2847         MonoClass *klass;
2848         MonoGenericClass *gclass;
2849         MonoType *type;
2850
2851         /* A ctor cannot be a generic method, so we can ignore create_methodspec */
2852
2853         token = GPOINTER_TO_UINT (mono_g_hash_table_lookup (assembly->handleref_managed, c));
2854         if (token)
2855                 return token;
2856
2857         if (is_sre_ctor_builder (mono_object_class (c->cb))) {
2858                 MonoReflectionCtorBuilder *cb = (MonoReflectionCtorBuilder *)c->cb;
2859                 ReflectionMethodBuilder rmb;
2860                 char *name;
2861
2862                 type = mono_reflection_type_get_handle ((MonoReflectionType*)c->inst);
2863                 klass = mono_class_from_mono_type (type);
2864
2865                 gclass = type->data.generic_class;
2866                 g_assert (gclass->is_dynamic);
2867
2868                 reflection_methodbuilder_from_ctor_builder (&rmb, cb);
2869
2870                 name = mono_string_to_utf8 (rmb.name);
2871
2872                 sig = method_builder_encode_signature (assembly, &rmb);
2873
2874                 token = mono_image_get_memberref_token (assembly, &klass->byval_arg, name, sig);
2875                 g_free (name);
2876         } else if (is_sr_mono_cmethod (mono_object_class (c->cb))) {
2877                 MonoMethod *mm = ((MonoReflectionMethod *)c->cb)->method;
2878
2879                 type = mono_reflection_type_get_handle ((MonoReflectionType*)c->inst);
2880                 klass = mono_class_from_mono_type (type);
2881
2882                 sig = method_encode_signature (assembly, mono_method_signature (mm));
2883                 token = mono_image_get_memberref_token (assembly, &klass->byval_arg, mm->name, sig);
2884         } else {
2885                 char *name = mono_type_get_full_name (mono_object_class (c->cb));
2886                 g_error ("mono_image_get_method_on_inst_token: don't know how to handle %s", name);
2887         }
2888
2889
2890         mono_g_hash_table_insert (assembly->handleref_managed, c, GUINT_TO_POINTER (token));
2891         return token;
2892 }
2893
2894 static MonoMethod*
2895 mono_reflection_method_on_tb_inst_get_handle (MonoReflectionMethodOnTypeBuilderInst *m)
2896 {
2897         MonoError error;
2898         MonoClass *klass;
2899         MonoGenericContext tmp_context;
2900         MonoType **type_argv;
2901         MonoGenericInst *ginst;
2902         MonoMethod *method, *inflated;
2903         int count, i;
2904
2905         init_type_builder_generics ((MonoObject*)m->inst);
2906
2907         method = inflate_method (m->inst, (MonoObject*)m->mb);
2908
2909         klass = method->klass;
2910
2911         if (m->method_args == NULL)
2912                 return method;
2913
2914         if (method->is_inflated)
2915                 method = ((MonoMethodInflated *) method)->declaring;
2916
2917         count = mono_array_length (m->method_args);
2918
2919         type_argv = g_new0 (MonoType *, count);
2920         for (i = 0; i < count; i++) {
2921                 MonoReflectionType *garg = mono_array_get (m->method_args, gpointer, i);
2922                 type_argv [i] = mono_reflection_type_get_handle (garg);
2923         }
2924         ginst = mono_metadata_get_generic_inst (count, type_argv);
2925         g_free (type_argv);
2926
2927         tmp_context.class_inst = klass->generic_class ? klass->generic_class->context.class_inst : NULL;
2928         tmp_context.method_inst = ginst;
2929
2930         inflated = mono_class_inflate_generic_method_checked (method, &tmp_context, &error);
2931         g_assert (mono_error_ok (&error)); /* FIXME don't swallow the error */
2932         return inflated;
2933 }
2934
2935 static guint32
2936 mono_image_get_method_on_inst_token (MonoDynamicImage *assembly, MonoReflectionMethodOnTypeBuilderInst *m, gboolean create_methodspec)
2937 {
2938         guint32 sig, token = 0;
2939         MonoType *type;
2940         MonoClass *klass;
2941
2942         if (m->method_args) {
2943                 MonoMethod *inflated;
2944
2945                 inflated = mono_reflection_method_on_tb_inst_get_handle (m);
2946                 if (create_methodspec)
2947                         token = mono_image_get_methodspec_token (assembly, inflated);
2948                 else
2949                         token = mono_image_get_inflated_method_token (assembly, inflated);
2950                 return token;
2951         }
2952
2953         token = GPOINTER_TO_UINT (mono_g_hash_table_lookup (assembly->handleref_managed, m));
2954         if (token)
2955                 return token;
2956
2957         if (is_sre_method_builder (mono_object_class (m->mb))) {
2958                 MonoReflectionMethodBuilder *mb = (MonoReflectionMethodBuilder *)m->mb;
2959                 MonoGenericClass *gclass;
2960                 ReflectionMethodBuilder rmb;
2961                 char *name;
2962
2963                 type = mono_reflection_type_get_handle ((MonoReflectionType*)m->inst);
2964                 klass = mono_class_from_mono_type (type);
2965                 gclass = type->data.generic_class;
2966                 g_assert (gclass->is_dynamic);
2967
2968                 reflection_methodbuilder_from_method_builder (&rmb, mb);
2969
2970                 name = mono_string_to_utf8 (rmb.name);
2971
2972                 sig = method_builder_encode_signature (assembly, &rmb);
2973
2974                 token = mono_image_get_memberref_token (assembly, &klass->byval_arg, name, sig);
2975                 g_free (name);          
2976         } else if (is_sr_mono_method (mono_object_class (m->mb))) {
2977                 MonoMethod *mm = ((MonoReflectionMethod *)m->mb)->method;
2978
2979                 type = mono_reflection_type_get_handle ((MonoReflectionType*)m->inst);
2980                 klass = mono_class_from_mono_type (type);
2981
2982                 sig = method_encode_signature (assembly, mono_method_signature (mm));
2983                 token = mono_image_get_memberref_token (assembly, &klass->byval_arg, mm->name, sig);
2984         } else {
2985                 char *name = mono_type_get_full_name (mono_object_class (m->mb));
2986                 g_error ("mono_image_get_method_on_inst_token: don't know how to handle %s", name);
2987         }
2988
2989         mono_g_hash_table_insert (assembly->handleref_managed, m, GUINT_TO_POINTER (token));
2990         return token;
2991 }
2992
2993 static guint32
2994 encode_generic_method_sig (MonoDynamicImage *assembly, MonoGenericContext *context)
2995 {
2996         SigBuffer buf;
2997         int i;
2998         guint32 nparams = context->method_inst->type_argc;
2999         guint32 idx;
3000
3001         if (!assembly->save)
3002                 return 0;
3003
3004         sigbuffer_init (&buf, 32);
3005         /*
3006          * FIXME: vararg, explicit_this, differenc call_conv values...
3007          */
3008         sigbuffer_add_value (&buf, 0xa); /* FIXME FIXME FIXME */
3009         sigbuffer_add_value (&buf, nparams);
3010
3011         for (i = 0; i < nparams; i++)
3012                 encode_type (assembly, context->method_inst->type_argv [i], &buf);
3013
3014         idx = sigbuffer_add_to_blob_cached (assembly, &buf);
3015         sigbuffer_free (&buf);
3016         return idx;
3017 }
3018
3019 static guint32
3020 method_encode_methodspec (MonoDynamicImage *assembly, MonoMethod *method)
3021 {
3022         MonoDynamicTable *table;
3023         guint32 *values;
3024         guint32 token, mtoken = 0, sig;
3025         MonoMethodInflated *imethod;
3026         MonoMethod *declaring;
3027
3028         table = &assembly->tables [MONO_TABLE_METHODSPEC];
3029
3030         g_assert (method->is_inflated);
3031         imethod = (MonoMethodInflated *) method;
3032         declaring = imethod->declaring;
3033
3034         sig = method_encode_signature (assembly, mono_method_signature (declaring));
3035         mtoken = mono_image_get_memberref_token (assembly, &method->klass->byval_arg, declaring->name, sig);
3036
3037         if (!mono_method_signature (declaring)->generic_param_count)
3038                 return mtoken;
3039
3040         switch (mono_metadata_token_table (mtoken)) {
3041         case MONO_TABLE_MEMBERREF:
3042                 mtoken = (mono_metadata_token_index (mtoken) << MONO_METHODDEFORREF_BITS) | MONO_METHODDEFORREF_METHODREF;
3043                 break;
3044         case MONO_TABLE_METHOD:
3045                 mtoken = (mono_metadata_token_index (mtoken) << MONO_METHODDEFORREF_BITS) | MONO_METHODDEFORREF_METHODDEF;
3046                 break;
3047         default:
3048                 g_assert_not_reached ();
3049         }
3050
3051         sig = encode_generic_method_sig (assembly, mono_method_get_context (method));
3052
3053         if (assembly->save) {
3054                 alloc_table (table, table->rows + 1);
3055                 values = table->values + table->next_idx * MONO_METHODSPEC_SIZE;
3056                 values [MONO_METHODSPEC_METHOD] = mtoken;
3057                 values [MONO_METHODSPEC_SIGNATURE] = sig;
3058         }
3059
3060         token = MONO_TOKEN_METHOD_SPEC | table->next_idx;
3061         table->next_idx ++;
3062
3063         return token;
3064 }
3065
3066 static guint32
3067 mono_image_get_methodspec_token (MonoDynamicImage *assembly, MonoMethod *method)
3068 {
3069         MonoMethodInflated *imethod;
3070         guint32 token;
3071         
3072         token = GPOINTER_TO_UINT (g_hash_table_lookup (assembly->handleref, method));
3073         if (token)
3074                 return token;
3075
3076         g_assert (method->is_inflated);
3077         imethod = (MonoMethodInflated *) method;
3078
3079         if (mono_method_signature (imethod->declaring)->generic_param_count) {
3080                 token = method_encode_methodspec (assembly, method);
3081         } else {
3082                 guint32 sig = method_encode_signature (
3083                         assembly, mono_method_signature (imethod->declaring));
3084                 token = mono_image_get_memberref_token (
3085                         assembly, &method->klass->byval_arg, method->name, sig);
3086         }
3087
3088         g_hash_table_insert (assembly->handleref, method, GUINT_TO_POINTER(token));
3089         return token;
3090 }
3091
3092 static guint32
3093 mono_image_get_inflated_method_token (MonoDynamicImage *assembly, MonoMethod *m)
3094 {
3095         MonoMethodInflated *imethod = (MonoMethodInflated *) m;
3096         guint32 sig, token;
3097
3098         sig = method_encode_signature (assembly, mono_method_signature (imethod->declaring));
3099         token = mono_image_get_memberref_token (
3100                 assembly, &m->klass->byval_arg, m->name, sig);
3101
3102         return token;
3103 }
3104
3105 static guint32
3106 create_generic_typespec (MonoDynamicImage *assembly, MonoReflectionTypeBuilder *tb)
3107 {
3108         MonoDynamicTable *table;
3109         MonoClass *klass;
3110         MonoType *type;
3111         guint32 *values;
3112         guint32 token;
3113         SigBuffer buf;
3114         int count, i;
3115
3116         /*
3117          * We're creating a TypeSpec for the TypeBuilder of a generic type declaration,
3118          * ie. what we'd normally use as the generic type in a TypeSpec signature.
3119          * Because of this, we must not insert it into the `typeref' hash table.
3120          */
3121         type = mono_reflection_type_get_handle ((MonoReflectionType*)tb);
3122         token = GPOINTER_TO_UINT (g_hash_table_lookup (assembly->typespec, type));
3123         if (token)
3124                 return token;
3125
3126         sigbuffer_init (&buf, 32);
3127
3128         g_assert (tb->generic_params);
3129         klass = mono_class_from_mono_type (type);
3130
3131         if (tb->generic_container)
3132                 mono_reflection_create_generic_class (tb);
3133
3134         sigbuffer_add_value (&buf, MONO_TYPE_GENERICINST);
3135         g_assert (klass->generic_container);
3136         sigbuffer_add_value (&buf, klass->byval_arg.type);
3137         sigbuffer_add_value (&buf, mono_image_typedef_or_ref_full (assembly, &klass->byval_arg, FALSE));
3138
3139         count = mono_array_length (tb->generic_params);
3140         sigbuffer_add_value (&buf, count);
3141         for (i = 0; i < count; i++) {
3142                 MonoReflectionGenericParam *gparam;
3143
3144                 gparam = mono_array_get (tb->generic_params, MonoReflectionGenericParam *, i);
3145
3146                 encode_type (assembly, mono_reflection_type_get_handle ((MonoReflectionType*)gparam), &buf);
3147         }
3148
3149         table = &assembly->tables [MONO_TABLE_TYPESPEC];
3150
3151         if (assembly->save) {
3152                 token = sigbuffer_add_to_blob_cached (assembly, &buf);
3153                 alloc_table (table, table->rows + 1);
3154                 values = table->values + table->next_idx * MONO_TYPESPEC_SIZE;
3155                 values [MONO_TYPESPEC_SIGNATURE] = token;
3156         }
3157         sigbuffer_free (&buf);
3158
3159         token = MONO_TYPEDEFORREF_TYPESPEC | (table->next_idx << MONO_TYPEDEFORREF_BITS);
3160         g_hash_table_insert (assembly->typespec, type, GUINT_TO_POINTER(token));
3161         table->next_idx ++;
3162         return token;
3163 }
3164
3165 /*
3166  * Return a copy of TYPE, adding the custom modifiers in MODREQ and MODOPT.
3167  */
3168 static MonoType*
3169 add_custom_modifiers (MonoDynamicImage *assembly, MonoType *type, MonoArray *modreq, MonoArray *modopt)
3170 {
3171         int i, count, len, pos;
3172         MonoType *t;
3173
3174         count = 0;
3175         if (modreq)
3176                 count += mono_array_length (modreq);
3177         if (modopt)
3178                 count += mono_array_length (modopt);
3179
3180         if (count == 0)
3181                 return mono_metadata_type_dup (NULL, type);
3182
3183         len = MONO_SIZEOF_TYPE + ((gint32)count) * sizeof (MonoCustomMod);
3184         t = g_malloc (len);
3185         memcpy (t, type, MONO_SIZEOF_TYPE);
3186
3187         t->num_mods = count;
3188         pos = 0;
3189         if (modreq) {
3190                 for (i = 0; i < mono_array_length (modreq); ++i) {
3191                         MonoType *mod = mono_type_array_get_and_resolve (modreq, i);
3192                         t->modifiers [pos].required = 1;
3193                         t->modifiers [pos].token = mono_image_typedef_or_ref (assembly, mod);
3194                         pos ++;
3195                 }
3196         }
3197         if (modopt) {
3198                 for (i = 0; i < mono_array_length (modopt); ++i) {
3199                         MonoType *mod = mono_type_array_get_and_resolve (modopt, i);
3200                         t->modifiers [pos].required = 0;
3201                         t->modifiers [pos].token = mono_image_typedef_or_ref (assembly, mod);
3202                         pos ++;
3203                 }
3204         }
3205
3206         return t;
3207 }
3208
3209 static void
3210 init_type_builder_generics (MonoObject *type)
3211 {
3212         MonoReflectionTypeBuilder *tb;
3213
3214         if (!is_sre_type_builder(mono_object_class (type)))
3215                 return;
3216         tb = (MonoReflectionTypeBuilder *)type;
3217
3218         if (tb && tb->generic_container)
3219                 mono_reflection_create_generic_class (tb);
3220 }
3221
3222 static guint32
3223 mono_image_get_generic_field_token (MonoDynamicImage *assembly, MonoReflectionFieldBuilder *fb)
3224 {
3225         MonoDynamicTable *table;
3226         MonoType *custom = NULL, *type;
3227         guint32 *values;
3228         guint32 token, pclass, parent, sig;
3229         gchar *name;
3230
3231         token = GPOINTER_TO_UINT (mono_g_hash_table_lookup (assembly->handleref_managed, fb));
3232         if (token)
3233                 return token;
3234
3235         /* FIXME: is this call necessary? */
3236         mono_class_from_mono_type (mono_reflection_type_get_handle (fb->typeb));
3237         name = mono_string_to_utf8 (fb->name);
3238
3239         /*FIXME this is one more layer of ugliness due how types are created.*/
3240         init_type_builder_generics (fb->type);
3241
3242         /* fb->type does not include the custom modifiers */
3243         /* FIXME: We should do this in one place when a fieldbuilder is created */
3244         type = mono_reflection_type_get_handle ((MonoReflectionType*)fb->type);
3245         if (fb->modreq || fb->modopt)
3246                 type = custom = add_custom_modifiers (assembly, type, fb->modreq, fb->modopt);
3247
3248         sig = fieldref_encode_signature (assembly, NULL, type);
3249         g_free (custom);
3250
3251         parent = create_generic_typespec (assembly, (MonoReflectionTypeBuilder *) fb->typeb);
3252         g_assert ((parent & MONO_TYPEDEFORREF_MASK) == MONO_TYPEDEFORREF_TYPESPEC);
3253         
3254         pclass = MONO_MEMBERREF_PARENT_TYPESPEC;
3255         parent >>= MONO_TYPEDEFORREF_BITS;
3256
3257         table = &assembly->tables [MONO_TABLE_MEMBERREF];
3258
3259         if (assembly->save) {
3260                 alloc_table (table, table->rows + 1);
3261                 values = table->values + table->next_idx * MONO_MEMBERREF_SIZE;
3262                 values [MONO_MEMBERREF_CLASS] = pclass | (parent << MONO_MEMBERREF_PARENT_BITS);
3263                 values [MONO_MEMBERREF_NAME] = string_heap_insert (&assembly->sheap, name);
3264                 values [MONO_MEMBERREF_SIGNATURE] = sig;
3265         }
3266
3267         token = MONO_TOKEN_MEMBER_REF | table->next_idx;
3268         table->next_idx ++;
3269         mono_g_hash_table_insert (assembly->handleref_managed, fb, GUINT_TO_POINTER(token));
3270         g_free (name);
3271         return token;
3272 }
3273
3274 static guint32
3275 mono_reflection_encode_sighelper (MonoDynamicImage *assembly, MonoReflectionSigHelper *helper)
3276 {
3277         SigBuffer buf;
3278         guint32 nargs;
3279         guint32 i, idx;
3280
3281         if (!assembly->save)
3282                 return 0;
3283
3284         /* FIXME: this means SignatureHelper.SignatureHelpType.HELPER_METHOD */
3285         g_assert (helper->type == 2);
3286
3287         if (helper->arguments)
3288                 nargs = mono_array_length (helper->arguments);
3289         else
3290                 nargs = 0;
3291
3292         sigbuffer_init (&buf, 32);
3293
3294         /* Encode calling convention */
3295         /* Change Any to Standard */
3296         if ((helper->call_conv & 0x03) == 0x03)
3297                 helper->call_conv = 0x01;
3298         /* explicit_this implies has_this */
3299         if (helper->call_conv & 0x40)
3300                 helper->call_conv &= 0x20;
3301
3302         if (helper->call_conv == 0) { /* Unmanaged */
3303                 idx = helper->unmanaged_call_conv - 1;
3304         } else {
3305                 /* Managed */
3306                 idx = helper->call_conv & 0x60; /* has_this + explicit_this */
3307                 if (helper->call_conv & 0x02) /* varargs */
3308                         idx += 0x05;
3309         }
3310
3311         sigbuffer_add_byte (&buf, idx);
3312         sigbuffer_add_value (&buf, nargs);
3313         encode_reflection_type (assembly, helper->return_type, &buf);
3314         for (i = 0; i < nargs; ++i) {
3315                 MonoArray *modreqs = NULL;
3316                 MonoArray *modopts = NULL;
3317                 MonoReflectionType *pt;
3318
3319                 if (helper->modreqs && (i < mono_array_length (helper->modreqs)))
3320                         modreqs = mono_array_get (helper->modreqs, MonoArray*, i);
3321                 if (helper->modopts && (i < mono_array_length (helper->modopts)))
3322                         modopts = mono_array_get (helper->modopts, MonoArray*, i);
3323
3324                 encode_custom_modifiers (assembly, modreqs, modopts, &buf);
3325                 pt = mono_array_get (helper->arguments, MonoReflectionType*, i);
3326                 encode_reflection_type (assembly, pt, &buf);
3327         }
3328         idx = sigbuffer_add_to_blob_cached (assembly, &buf);
3329         sigbuffer_free (&buf);
3330
3331         return idx;
3332 }
3333
3334 static guint32 
3335 mono_image_get_sighelper_token (MonoDynamicImage *assembly, MonoReflectionSigHelper *helper)
3336 {
3337         guint32 idx;
3338         MonoDynamicTable *table;
3339         guint32 *values;
3340
3341         table = &assembly->tables [MONO_TABLE_STANDALONESIG];
3342         idx = table->next_idx ++;
3343         table->rows ++;
3344         alloc_table (table, table->rows);
3345         values = table->values + idx * MONO_STAND_ALONE_SIGNATURE_SIZE;
3346
3347         values [MONO_STAND_ALONE_SIGNATURE] =
3348                 mono_reflection_encode_sighelper (assembly, helper);
3349
3350         return idx;
3351 }
3352
3353 static int
3354 reflection_cc_to_file (int call_conv) {
3355         switch (call_conv & 0x3) {
3356         case 0:
3357         case 1: return MONO_CALL_DEFAULT;
3358         case 2: return MONO_CALL_VARARG;
3359         default:
3360                 g_assert_not_reached ();
3361         }
3362         return 0;
3363 }
3364 #endif /* !DISABLE_REFLECTION_EMIT */
3365
3366 typedef struct {
3367         MonoType *parent;
3368         MonoMethodSignature *sig;
3369         char *name;
3370         guint32 token;
3371 } ArrayMethod;
3372
3373 #ifndef DISABLE_REFLECTION_EMIT
3374 static guint32
3375 mono_image_get_array_token (MonoDynamicImage *assembly, MonoReflectionArrayMethod *m)
3376 {
3377         guint32 nparams, i;
3378         GList *tmp;
3379         char *name;
3380         MonoMethodSignature *sig;
3381         ArrayMethod *am;
3382         MonoType *mtype;
3383
3384         name = mono_string_to_utf8 (m->name);
3385         nparams = mono_array_length (m->parameters);
3386         sig = g_malloc0 (MONO_SIZEOF_METHOD_SIGNATURE + sizeof (MonoType*) * nparams);
3387         sig->hasthis = 1;
3388         sig->sentinelpos = -1;
3389         sig->call_convention = reflection_cc_to_file (m->call_conv);
3390         sig->param_count = nparams;
3391         sig->ret = m->ret ? mono_reflection_type_get_handle (m->ret): &mono_defaults.void_class->byval_arg;
3392         mtype = mono_reflection_type_get_handle (m->parent);
3393         for (i = 0; i < nparams; ++i)
3394                 sig->params [i] = mono_type_array_get_and_resolve (m->parameters, i);
3395
3396         for (tmp = assembly->array_methods; tmp; tmp = tmp->next) {
3397                 am = tmp->data;
3398                 if (strcmp (name, am->name) == 0 && 
3399                                 mono_metadata_type_equal (am->parent, mtype) &&
3400                                 mono_metadata_signature_equal (am->sig, sig)) {
3401                         g_free (name);
3402                         g_free (sig);
3403                         m->table_idx = am->token & 0xffffff;
3404                         return am->token;
3405                 }
3406         }
3407         am = g_new0 (ArrayMethod, 1);
3408         am->name = name;
3409         am->sig = sig;
3410         am->parent = mtype;
3411         am->token = mono_image_get_memberref_token (assembly, am->parent, name,
3412                 method_encode_signature (assembly, sig));
3413         assembly->array_methods = g_list_prepend (assembly->array_methods, am);
3414         m->table_idx = am->token & 0xffffff;
3415         return am->token;
3416 }
3417
3418 /*
3419  * Insert into the metadata tables all the info about the TypeBuilder tb.
3420  * Data in the tables is inserted in a predefined order, since some tables need to be sorted.
3421  */
3422 static void
3423 mono_image_get_type_info (MonoDomain *domain, MonoReflectionTypeBuilder *tb, MonoDynamicImage *assembly)
3424 {
3425         MonoDynamicTable *table;
3426         guint *values;
3427         int i, is_object = 0, is_system = 0;
3428         char *n;
3429
3430         table = &assembly->tables [MONO_TABLE_TYPEDEF];
3431         values = table->values + tb->table_idx * MONO_TYPEDEF_SIZE;
3432         values [MONO_TYPEDEF_FLAGS] = tb->attrs;
3433         n = mono_string_to_utf8 (tb->name);
3434         if (strcmp (n, "Object") == 0)
3435                 is_object++;
3436         values [MONO_TYPEDEF_NAME] = string_heap_insert (&assembly->sheap, n);
3437         g_free (n);
3438         n = mono_string_to_utf8 (tb->nspace);
3439         if (strcmp (n, "System") == 0)
3440                 is_system++;
3441         values [MONO_TYPEDEF_NAMESPACE] = string_heap_insert (&assembly->sheap, n);
3442         g_free (n);
3443         if (tb->parent && !(is_system && is_object) && 
3444                         !(tb->attrs & TYPE_ATTRIBUTE_INTERFACE)) { /* interfaces don't have a parent */
3445                 values [MONO_TYPEDEF_EXTENDS] = mono_image_typedef_or_ref (assembly, mono_reflection_type_get_handle ((MonoReflectionType*)tb->parent));
3446         } else {
3447                 values [MONO_TYPEDEF_EXTENDS] = 0;
3448         }
3449         values [MONO_TYPEDEF_FIELD_LIST] = assembly->tables [MONO_TABLE_FIELD].next_idx;
3450         values [MONO_TYPEDEF_METHOD_LIST] = assembly->tables [MONO_TABLE_METHOD].next_idx;
3451
3452         /*
3453          * if we have explicitlayout or sequentiallayouts, output data in the
3454          * ClassLayout table.
3455          */
3456         if (((tb->attrs & TYPE_ATTRIBUTE_LAYOUT_MASK) != TYPE_ATTRIBUTE_AUTO_LAYOUT) &&
3457                         ((tb->class_size > 0) || (tb->packing_size > 0))) {
3458                 table = &assembly->tables [MONO_TABLE_CLASSLAYOUT];
3459                 table->rows++;
3460                 alloc_table (table, table->rows);
3461                 values = table->values + table->rows * MONO_CLASS_LAYOUT_SIZE;
3462                 values [MONO_CLASS_LAYOUT_PARENT] = tb->table_idx;
3463                 values [MONO_CLASS_LAYOUT_CLASS_SIZE] = tb->class_size;
3464                 values [MONO_CLASS_LAYOUT_PACKING_SIZE] = tb->packing_size;
3465         }
3466
3467         /* handle interfaces */
3468         if (tb->interfaces) {
3469                 table = &assembly->tables [MONO_TABLE_INTERFACEIMPL];
3470                 i = table->rows;
3471                 table->rows += mono_array_length (tb->interfaces);
3472                 alloc_table (table, table->rows);
3473                 values = table->values + (i + 1) * MONO_INTERFACEIMPL_SIZE;
3474                 for (i = 0; i < mono_array_length (tb->interfaces); ++i) {
3475                         MonoReflectionType* iface = (MonoReflectionType*) mono_array_get (tb->interfaces, gpointer, i);
3476                         values [MONO_INTERFACEIMPL_CLASS] = tb->table_idx;
3477                         values [MONO_INTERFACEIMPL_INTERFACE] = mono_image_typedef_or_ref (assembly, mono_reflection_type_get_handle (iface));
3478                         values += MONO_INTERFACEIMPL_SIZE;
3479                 }
3480         }
3481
3482         /* handle fields */
3483         if (tb->fields) {
3484                 table = &assembly->tables [MONO_TABLE_FIELD];
3485                 table->rows += tb->num_fields;
3486                 alloc_table (table, table->rows);
3487                 for (i = 0; i < tb->num_fields; ++i)
3488                         mono_image_get_field_info (
3489                                 mono_array_get (tb->fields, MonoReflectionFieldBuilder*, i), assembly);
3490         }
3491
3492         /* handle constructors */
3493         if (tb->ctors) {
3494                 table = &assembly->tables [MONO_TABLE_METHOD];
3495                 table->rows += mono_array_length (tb->ctors);
3496                 alloc_table (table, table->rows);
3497                 for (i = 0; i < mono_array_length (tb->ctors); ++i)
3498                         mono_image_get_ctor_info (domain,
3499                                 mono_array_get (tb->ctors, MonoReflectionCtorBuilder*, i), assembly);
3500         }
3501
3502         /* handle methods */
3503         if (tb->methods) {
3504                 table = &assembly->tables [MONO_TABLE_METHOD];
3505                 table->rows += tb->num_methods;
3506                 alloc_table (table, table->rows);
3507                 for (i = 0; i < tb->num_methods; ++i)
3508                         mono_image_get_method_info (
3509                                 mono_array_get (tb->methods, MonoReflectionMethodBuilder*, i), assembly);
3510         }
3511
3512         /* Do the same with properties etc.. */
3513         if (tb->events && mono_array_length (tb->events)) {
3514                 table = &assembly->tables [MONO_TABLE_EVENT];
3515                 table->rows += mono_array_length (tb->events);
3516                 alloc_table (table, table->rows);
3517                 table = &assembly->tables [MONO_TABLE_EVENTMAP];
3518                 table->rows ++;
3519                 alloc_table (table, table->rows);
3520                 values = table->values + table->rows * MONO_EVENT_MAP_SIZE;
3521                 values [MONO_EVENT_MAP_PARENT] = tb->table_idx;
3522                 values [MONO_EVENT_MAP_EVENTLIST] = assembly->tables [MONO_TABLE_EVENT].next_idx;
3523                 for (i = 0; i < mono_array_length (tb->events); ++i)
3524                         mono_image_get_event_info (
3525                                 mono_array_get (tb->events, MonoReflectionEventBuilder*, i), assembly);
3526         }
3527         if (tb->properties && mono_array_length (tb->properties)) {
3528                 table = &assembly->tables [MONO_TABLE_PROPERTY];
3529                 table->rows += mono_array_length (tb->properties);
3530                 alloc_table (table, table->rows);
3531                 table = &assembly->tables [MONO_TABLE_PROPERTYMAP];
3532                 table->rows ++;
3533                 alloc_table (table, table->rows);
3534                 values = table->values + table->rows * MONO_PROPERTY_MAP_SIZE;
3535                 values [MONO_PROPERTY_MAP_PARENT] = tb->table_idx;
3536                 values [MONO_PROPERTY_MAP_PROPERTY_LIST] = assembly->tables [MONO_TABLE_PROPERTY].next_idx;
3537                 for (i = 0; i < mono_array_length (tb->properties); ++i)
3538                         mono_image_get_property_info (
3539                                 mono_array_get (tb->properties, MonoReflectionPropertyBuilder*, i), assembly);
3540         }
3541
3542         /* handle generic parameters */
3543         if (tb->generic_params) {
3544                 table = &assembly->tables [MONO_TABLE_GENERICPARAM];
3545                 table->rows += mono_array_length (tb->generic_params);
3546                 alloc_table (table, table->rows);
3547                 for (i = 0; i < mono_array_length (tb->generic_params); ++i) {
3548                         guint32 owner = MONO_TYPEORMETHOD_TYPE | (tb->table_idx << MONO_TYPEORMETHOD_BITS);
3549
3550                         mono_image_get_generic_param_info (
3551                                 mono_array_get (tb->generic_params, MonoReflectionGenericParam*, i), owner, assembly);
3552                 }
3553         }
3554
3555         mono_image_add_decl_security (assembly, 
3556                 mono_metadata_make_token (MONO_TABLE_TYPEDEF, tb->table_idx), tb->permissions);
3557
3558         if (tb->subtypes) {
3559                 MonoDynamicTable *ntable;
3560                 
3561                 ntable = &assembly->tables [MONO_TABLE_NESTEDCLASS];
3562                 ntable->rows += mono_array_length (tb->subtypes);
3563                 alloc_table (ntable, ntable->rows);
3564                 values = ntable->values + ntable->next_idx * MONO_NESTED_CLASS_SIZE;
3565
3566                 for (i = 0; i < mono_array_length (tb->subtypes); ++i) {
3567                         MonoReflectionTypeBuilder *subtype = mono_array_get (tb->subtypes, MonoReflectionTypeBuilder*, i);
3568
3569                         values [MONO_NESTED_CLASS_NESTED] = subtype->table_idx;
3570                         values [MONO_NESTED_CLASS_ENCLOSING] = tb->table_idx;
3571                         /*g_print ("nesting %s (%d) in %s (%d) (rows %d/%d)\n",
3572                                 mono_string_to_utf8 (subtype->name), subtype->table_idx,
3573                                 mono_string_to_utf8 (tb->name), tb->table_idx,
3574                                 ntable->next_idx, ntable->rows);*/
3575                         values += MONO_NESTED_CLASS_SIZE;
3576                         ntable->next_idx++;
3577                 }
3578         }
3579 }
3580 #endif
3581
3582 static void
3583 collect_types (MonoPtrArray *types, MonoReflectionTypeBuilder *type)
3584 {
3585         int i;
3586
3587         mono_ptr_array_append (*types, type);
3588
3589         if (!type->subtypes)
3590                 return;
3591
3592         for (i = 0; i < mono_array_length (type->subtypes); ++i) {
3593                 MonoReflectionTypeBuilder *subtype = mono_array_get (type->subtypes, MonoReflectionTypeBuilder*, i);
3594                 collect_types (types, subtype);
3595         }
3596 }
3597
3598 static gint
3599 compare_types_by_table_idx (MonoReflectionTypeBuilder **type1, MonoReflectionTypeBuilder **type2)
3600 {
3601         if ((*type1)->table_idx < (*type2)->table_idx)
3602                 return -1;
3603         else
3604                 if ((*type1)->table_idx > (*type2)->table_idx)
3605                         return 1;
3606         else
3607                 return 0;
3608 }
3609
3610 static void
3611 params_add_cattrs (MonoDynamicImage *assembly, MonoArray *pinfo) {
3612         int i;
3613
3614         if (!pinfo)
3615                 return;
3616         for (i = 0; i < mono_array_length (pinfo); ++i) {
3617                 MonoReflectionParamBuilder *pb;
3618                 pb = mono_array_get (pinfo, MonoReflectionParamBuilder *, i);
3619                 if (!pb)
3620                         continue;
3621                 mono_image_add_cattrs (assembly, pb->table_idx, MONO_CUSTOM_ATTR_PARAMDEF, pb->cattrs);
3622         }
3623 }
3624
3625 static void
3626 type_add_cattrs (MonoDynamicImage *assembly, MonoReflectionTypeBuilder *tb) {
3627         int i;
3628         
3629         mono_image_add_cattrs (assembly, tb->table_idx, MONO_CUSTOM_ATTR_TYPEDEF, tb->cattrs);
3630         if (tb->fields) {
3631                 for (i = 0; i < tb->num_fields; ++i) {
3632                         MonoReflectionFieldBuilder* fb;
3633                         fb = mono_array_get (tb->fields, MonoReflectionFieldBuilder*, i);
3634                         mono_image_add_cattrs (assembly, fb->table_idx, MONO_CUSTOM_ATTR_FIELDDEF, fb->cattrs);
3635                 }
3636         }
3637         if (tb->events) {
3638                 for (i = 0; i < mono_array_length (tb->events); ++i) {
3639                         MonoReflectionEventBuilder* eb;
3640                         eb = mono_array_get (tb->events, MonoReflectionEventBuilder*, i);
3641                         mono_image_add_cattrs (assembly, eb->table_idx, MONO_CUSTOM_ATTR_EVENT, eb->cattrs);
3642                 }
3643         }
3644         if (tb->properties) {
3645                 for (i = 0; i < mono_array_length (tb->properties); ++i) {
3646                         MonoReflectionPropertyBuilder* pb;
3647                         pb = mono_array_get (tb->properties, MonoReflectionPropertyBuilder*, i);
3648                         mono_image_add_cattrs (assembly, pb->table_idx, MONO_CUSTOM_ATTR_PROPERTY, pb->cattrs);
3649                 }
3650         }
3651         if (tb->ctors) {
3652                 for (i = 0; i < mono_array_length (tb->ctors); ++i) {
3653                         MonoReflectionCtorBuilder* cb;
3654                         cb = mono_array_get (tb->ctors, MonoReflectionCtorBuilder*, i);
3655                         mono_image_add_cattrs (assembly, cb->table_idx, MONO_CUSTOM_ATTR_METHODDEF, cb->cattrs);
3656                         params_add_cattrs (assembly, cb->pinfo);
3657                 }
3658         }
3659
3660         if (tb->methods) {
3661                 for (i = 0; i < tb->num_methods; ++i) {
3662                         MonoReflectionMethodBuilder* mb;
3663                         mb = mono_array_get (tb->methods, MonoReflectionMethodBuilder*, i);
3664                         mono_image_add_cattrs (assembly, mb->table_idx, MONO_CUSTOM_ATTR_METHODDEF, mb->cattrs);
3665                         params_add_cattrs (assembly, mb->pinfo);
3666                 }
3667         }
3668
3669         if (tb->subtypes) {
3670                 for (i = 0; i < mono_array_length (tb->subtypes); ++i)
3671                         type_add_cattrs (assembly, mono_array_get (tb->subtypes, MonoReflectionTypeBuilder*, i));
3672         }
3673 }
3674
3675 static void
3676 module_add_cattrs (MonoDynamicImage *assembly, MonoReflectionModuleBuilder *moduleb)
3677 {
3678         int i;
3679         
3680         mono_image_add_cattrs (assembly, moduleb->table_idx, MONO_CUSTOM_ATTR_MODULE, moduleb->cattrs);
3681
3682         if (moduleb->global_methods) {
3683                 for (i = 0; i < mono_array_length (moduleb->global_methods); ++i) {
3684                         MonoReflectionMethodBuilder* mb = mono_array_get (moduleb->global_methods, MonoReflectionMethodBuilder*, i);
3685                         mono_image_add_cattrs (assembly, mb->table_idx, MONO_CUSTOM_ATTR_METHODDEF, mb->cattrs);
3686                         params_add_cattrs (assembly, mb->pinfo);
3687                 }
3688         }
3689
3690         if (moduleb->global_fields) {
3691                 for (i = 0; i < mono_array_length (moduleb->global_fields); ++i) {
3692                         MonoReflectionFieldBuilder *fb = mono_array_get (moduleb->global_fields, MonoReflectionFieldBuilder*, i);
3693                         mono_image_add_cattrs (assembly, fb->table_idx, MONO_CUSTOM_ATTR_FIELDDEF, fb->cattrs);
3694                 }
3695         }
3696         
3697         if (moduleb->types) {
3698                 for (i = 0; i < moduleb->num_types; ++i)
3699                         type_add_cattrs (assembly, mono_array_get (moduleb->types, MonoReflectionTypeBuilder*, i));
3700         }
3701 }
3702
3703 static void
3704 mono_image_fill_file_table (MonoDomain *domain, MonoReflectionModule *module, MonoDynamicImage *assembly)
3705 {
3706         MonoDynamicTable *table;
3707         guint32 *values;
3708         char blob_size [6];
3709         guchar hash [20];
3710         char *b = blob_size;
3711         char *dir, *path;
3712
3713         table = &assembly->tables [MONO_TABLE_FILE];
3714         table->rows++;
3715         alloc_table (table, table->rows);
3716         values = table->values + table->next_idx * MONO_FILE_SIZE;
3717         values [MONO_FILE_FLAGS] = FILE_CONTAINS_METADATA;
3718         values [MONO_FILE_NAME] = string_heap_insert (&assembly->sheap, module->image->module_name);
3719         if (image_is_dynamic (module->image)) {
3720                 /* This depends on the fact that the main module is emitted last */
3721                 dir = mono_string_to_utf8 (((MonoReflectionModuleBuilder*)module)->assemblyb->dir);
3722                 path = g_strdup_printf ("%s%c%s", dir, G_DIR_SEPARATOR, module->image->module_name);
3723         } else {
3724                 dir = NULL;
3725                 path = g_strdup (module->image->name);
3726         }
3727         mono_sha1_get_digest_from_file (path, hash);
3728         g_free (dir);
3729         g_free (path);
3730         mono_metadata_encode_value (20, b, &b);
3731         values [MONO_FILE_HASH_VALUE] = mono_image_add_stream_data (&assembly->blob, blob_size, b-blob_size);
3732         mono_image_add_stream_data (&assembly->blob, (char*)hash, 20);
3733         table->next_idx ++;
3734 }
3735
3736 static void
3737 mono_image_fill_module_table (MonoDomain *domain, MonoReflectionModuleBuilder *mb, MonoDynamicImage *assembly)
3738 {
3739         MonoDynamicTable *table;
3740         int i;
3741
3742         table = &assembly->tables [MONO_TABLE_MODULE];
3743         mb->table_idx = table->next_idx ++;
3744         table->values [mb->table_idx * MONO_MODULE_SIZE + MONO_MODULE_NAME] = string_heap_insert_mstring (&assembly->sheap, mb->module.name);
3745         i = mono_image_add_stream_data (&assembly->guid, mono_array_addr (mb->guid, char, 0), 16);
3746         i /= 16;
3747         ++i;
3748         table->values [mb->table_idx * MONO_MODULE_SIZE + MONO_MODULE_GENERATION] = 0;
3749         table->values [mb->table_idx * MONO_MODULE_SIZE + MONO_MODULE_MVID] = i;
3750         table->values [mb->table_idx * MONO_MODULE_SIZE + MONO_MODULE_ENC] = 0;
3751         table->values [mb->table_idx * MONO_MODULE_SIZE + MONO_MODULE_ENCBASE] = 0;
3752 }
3753
3754 static guint32
3755 mono_image_fill_export_table_from_class (MonoDomain *domain, MonoClass *klass,
3756         guint32 module_index, guint32 parent_index, MonoDynamicImage *assembly)
3757 {
3758         MonoDynamicTable *table;
3759         guint32 *values;
3760         guint32 visib, res;
3761
3762         visib = klass->flags & TYPE_ATTRIBUTE_VISIBILITY_MASK;
3763         if (! ((visib & TYPE_ATTRIBUTE_PUBLIC) || (visib & TYPE_ATTRIBUTE_NESTED_PUBLIC)))
3764                 return 0;
3765
3766         table = &assembly->tables [MONO_TABLE_EXPORTEDTYPE];
3767         table->rows++;
3768         alloc_table (table, table->rows);
3769         values = table->values + table->next_idx * MONO_EXP_TYPE_SIZE;
3770
3771         values [MONO_EXP_TYPE_FLAGS] = klass->flags;
3772         values [MONO_EXP_TYPE_TYPEDEF] = klass->type_token;
3773         if (klass->nested_in)
3774                 values [MONO_EXP_TYPE_IMPLEMENTATION] = (parent_index << MONO_IMPLEMENTATION_BITS) + MONO_IMPLEMENTATION_EXP_TYPE;
3775         else
3776                 values [MONO_EXP_TYPE_IMPLEMENTATION] = (module_index << MONO_IMPLEMENTATION_BITS) + MONO_IMPLEMENTATION_FILE;
3777         values [MONO_EXP_TYPE_NAME] = string_heap_insert (&assembly->sheap, klass->name);
3778         values [MONO_EXP_TYPE_NAMESPACE] = string_heap_insert (&assembly->sheap, klass->name_space);
3779
3780         res = table->next_idx;
3781
3782         table->next_idx ++;
3783
3784         /* Emit nested types */
3785         if (klass->ext && klass->ext->nested_classes) {
3786                 GList *tmp;
3787
3788                 for (tmp = klass->ext->nested_classes; tmp; tmp = tmp->next)
3789                         mono_image_fill_export_table_from_class (domain, tmp->data, module_index, table->next_idx - 1, assembly);
3790         }
3791
3792         return res;
3793 }
3794
3795 static void
3796 mono_image_fill_export_table (MonoDomain *domain, MonoReflectionTypeBuilder *tb,
3797         guint32 module_index, guint32 parent_index, MonoDynamicImage *assembly)
3798 {
3799         MonoClass *klass;
3800         guint32 idx, i;
3801
3802         klass = mono_class_from_mono_type (mono_reflection_type_get_handle ((MonoReflectionType*)tb));
3803
3804         klass->type_token = mono_metadata_make_token (MONO_TABLE_TYPEDEF, tb->table_idx);
3805
3806         idx = mono_image_fill_export_table_from_class (domain, klass, module_index, 
3807                                                                                                    parent_index, assembly);
3808
3809         /* 
3810          * Emit nested types
3811          * We need to do this ourselves since klass->nested_classes is not set up.
3812          */
3813         if (tb->subtypes) {
3814                 for (i = 0; i < mono_array_length (tb->subtypes); ++i)
3815                         mono_image_fill_export_table (domain, mono_array_get (tb->subtypes, MonoReflectionTypeBuilder*, i), module_index, idx, assembly);
3816         }
3817 }
3818
3819 static void
3820 mono_image_fill_export_table_from_module (MonoDomain *domain, MonoReflectionModule *module,
3821         guint32 module_index, MonoDynamicImage *assembly)
3822 {
3823         MonoImage *image = module->image;
3824         MonoTableInfo  *t;
3825         guint32 i;
3826
3827         t = &image->tables [MONO_TABLE_TYPEDEF];
3828
3829         for (i = 0; i < t->rows; ++i) {
3830                 MonoError error;
3831                 MonoClass *klass = mono_class_get_checked (image, mono_metadata_make_token (MONO_TABLE_TYPEDEF, i + 1), &error);
3832                 g_assert (mono_error_ok (&error)); /* FIXME don't swallow the error */
3833
3834                 if (klass->flags & TYPE_ATTRIBUTE_PUBLIC)
3835                         mono_image_fill_export_table_from_class (domain, klass, module_index, 0, assembly);
3836         }
3837 }
3838
3839 static void
3840 add_exported_type (MonoReflectionAssemblyBuilder *assemblyb, MonoDynamicImage *assembly, MonoClass *klass, guint32 parent_index)
3841 {
3842         MonoDynamicTable *table;
3843         guint32 *values;
3844         guint32 scope, scope_idx, impl, current_idx;
3845         gboolean forwarder = TRUE;
3846         gpointer iter = NULL;
3847         MonoClass *nested;
3848
3849         if (klass->nested_in) {
3850                 impl = (parent_index << MONO_IMPLEMENTATION_BITS) + MONO_IMPLEMENTATION_EXP_TYPE;
3851                 forwarder = FALSE;
3852         } else {
3853                 scope = resolution_scope_from_image (assembly, klass->image);
3854                 g_assert ((scope & MONO_RESOLUTION_SCOPE_MASK) == MONO_RESOLUTION_SCOPE_ASSEMBLYREF);
3855                 scope_idx = scope >> MONO_RESOLUTION_SCOPE_BITS;
3856                 impl = (scope_idx << MONO_IMPLEMENTATION_BITS) + MONO_IMPLEMENTATION_ASSEMBLYREF;
3857         }
3858
3859         table = &assembly->tables [MONO_TABLE_EXPORTEDTYPE];
3860
3861         table->rows++;
3862         alloc_table (table, table->rows);
3863         current_idx = table->next_idx;
3864         values = table->values + current_idx * MONO_EXP_TYPE_SIZE;
3865
3866         values [MONO_EXP_TYPE_FLAGS] = forwarder ? TYPE_ATTRIBUTE_FORWARDER : 0;
3867         values [MONO_EXP_TYPE_TYPEDEF] = 0;
3868         values [MONO_EXP_TYPE_IMPLEMENTATION] = impl;
3869         values [MONO_EXP_TYPE_NAME] = string_heap_insert (&assembly->sheap, klass->name);
3870         values [MONO_EXP_TYPE_NAMESPACE] = string_heap_insert (&assembly->sheap, klass->name_space);
3871
3872         table->next_idx++;
3873
3874         while ((nested = mono_class_get_nested_types (klass, &iter)))
3875                 add_exported_type (assemblyb, assembly, nested, current_idx);
3876 }
3877
3878 static void
3879 mono_image_fill_export_table_from_type_forwarders (MonoReflectionAssemblyBuilder *assemblyb, MonoDynamicImage *assembly)
3880 {
3881         MonoClass *klass;
3882         int i;
3883
3884         if (!assemblyb->type_forwarders)
3885                 return;
3886
3887         for (i = 0; i < mono_array_length (assemblyb->type_forwarders); ++i) {
3888                 MonoReflectionType *t = mono_array_get (assemblyb->type_forwarders, MonoReflectionType *, i);
3889                 MonoType *type;
3890                 if (!t)
3891                         continue;
3892
3893                 type = mono_reflection_type_get_handle (t);
3894                 g_assert (type);
3895
3896                 klass = mono_class_from_mono_type (type);
3897
3898                 add_exported_type (assemblyb, assembly, klass, 0);
3899         }
3900 }
3901
3902 #define align_pointer(base,p)\
3903         do {\
3904                 guint32 __diff = (unsigned char*)(p)-(unsigned char*)(base);\
3905                 if (__diff & 3)\
3906                         (p) += 4 - (__diff & 3);\
3907         } while (0)
3908
3909 static int
3910 compare_constants (const void *a, const void *b)
3911 {
3912         const guint32 *a_values = a;
3913         const guint32 *b_values = b;
3914         return a_values [MONO_CONSTANT_PARENT] - b_values [MONO_CONSTANT_PARENT];
3915 }
3916
3917 static int
3918 compare_semantics (const void *a, const void *b)
3919 {
3920         const guint32 *a_values = a;
3921         const guint32 *b_values = b;
3922         int assoc = a_values [MONO_METHOD_SEMA_ASSOCIATION] - b_values [MONO_METHOD_SEMA_ASSOCIATION];
3923         if (assoc)
3924                 return assoc;
3925         return a_values [MONO_METHOD_SEMA_SEMANTICS] - b_values [MONO_METHOD_SEMA_SEMANTICS];
3926 }
3927
3928 static int
3929 compare_custom_attrs (const void *a, const void *b)
3930 {
3931         const guint32 *a_values = a;
3932         const guint32 *b_values = b;
3933
3934         return a_values [MONO_CUSTOM_ATTR_PARENT] - b_values [MONO_CUSTOM_ATTR_PARENT];
3935 }
3936
3937 static int
3938 compare_field_marshal (const void *a, const void *b)
3939 {
3940         const guint32 *a_values = a;
3941         const guint32 *b_values = b;
3942
3943         return a_values [MONO_FIELD_MARSHAL_PARENT] - b_values [MONO_FIELD_MARSHAL_PARENT];
3944 }
3945
3946 static int
3947 compare_nested (const void *a, const void *b)
3948 {
3949         const guint32 *a_values = a;
3950         const guint32 *b_values = b;
3951
3952         return a_values [MONO_NESTED_CLASS_NESTED] - b_values [MONO_NESTED_CLASS_NESTED];
3953 }
3954
3955 static int
3956 compare_genericparam (const void *a, const void *b)
3957 {
3958         const GenericParamTableEntry **a_entry = (const GenericParamTableEntry **) a;
3959         const GenericParamTableEntry **b_entry = (const GenericParamTableEntry **) b;
3960
3961         if ((*b_entry)->owner == (*a_entry)->owner)
3962                 return 
3963                         mono_type_get_generic_param_num (mono_reflection_type_get_handle ((MonoReflectionType*)(*a_entry)->gparam)) -
3964                         mono_type_get_generic_param_num (mono_reflection_type_get_handle ((MonoReflectionType*)(*b_entry)->gparam));
3965         else
3966                 return (*a_entry)->owner - (*b_entry)->owner;
3967 }
3968
3969 static int
3970 compare_declsecurity_attrs (const void *a, const void *b)
3971 {
3972         const guint32 *a_values = a;
3973         const guint32 *b_values = b;
3974
3975         return a_values [MONO_DECL_SECURITY_PARENT] - b_values [MONO_DECL_SECURITY_PARENT];
3976 }
3977
3978 static int
3979 compare_interface_impl (const void *a, const void *b)
3980 {
3981         const guint32 *a_values = a;
3982         const guint32 *b_values = b;
3983
3984         int klass = a_values [MONO_INTERFACEIMPL_CLASS] - b_values [MONO_INTERFACEIMPL_CLASS];
3985         if (klass)
3986                 return klass;
3987
3988         return a_values [MONO_INTERFACEIMPL_INTERFACE] - b_values [MONO_INTERFACEIMPL_INTERFACE];
3989 }
3990
3991 static void
3992 pad_heap (MonoDynamicStream *sh)
3993 {
3994         if (sh->index & 3) {
3995                 int sz = 4 - (sh->index & 3);
3996                 memset (sh->data + sh->index, 0, sz);
3997                 sh->index += sz;
3998         }
3999 }
4000
4001 struct StreamDesc {
4002         const char *name;
4003         MonoDynamicStream *stream;
4004 };
4005
4006 /*
4007  * build_compressed_metadata() fills in the blob of data that represents the 
4008  * raw metadata as it will be saved in the PE file. The five streams are output 
4009  * and the metadata tables are comnpressed from the guint32 array representation, 
4010  * to the compressed on-disk format.
4011  */
4012 static void
4013 build_compressed_metadata (MonoDynamicImage *assembly)
4014 {
4015         MonoDynamicTable *table;
4016         int i;
4017         guint64 valid_mask = 0;
4018         guint64 sorted_mask;
4019         guint32 heapt_size = 0;
4020         guint32 meta_size = 256; /* allow for header and other stuff */
4021         guint32 table_offset;
4022         guint32 ntables = 0;
4023         guint64 *int64val;
4024         guint32 *int32val;
4025         guint16 *int16val;
4026         MonoImage *meta;
4027         unsigned char *p;
4028         struct StreamDesc stream_desc [5];
4029
4030         qsort (assembly->gen_params->pdata, assembly->gen_params->len, sizeof (gpointer), compare_genericparam);
4031         for (i = 0; i < assembly->gen_params->len; i++){
4032                 GenericParamTableEntry *entry = g_ptr_array_index (assembly->gen_params, i);
4033                 write_generic_param_entry (assembly, entry);
4034         }
4035
4036         stream_desc [0].name  = "#~";
4037         stream_desc [0].stream = &assembly->tstream;
4038         stream_desc [1].name  = "#Strings";
4039         stream_desc [1].stream = &assembly->sheap;
4040         stream_desc [2].name  = "#US";
4041         stream_desc [2].stream = &assembly->us;
4042         stream_desc [3].name  = "#Blob";
4043         stream_desc [3].stream = &assembly->blob;
4044         stream_desc [4].name  = "#GUID";
4045         stream_desc [4].stream = &assembly->guid;
4046         
4047         /* tables that are sorted */
4048         sorted_mask = ((guint64)1 << MONO_TABLE_CONSTANT) | ((guint64)1 << MONO_TABLE_FIELDMARSHAL)
4049                 | ((guint64)1 << MONO_TABLE_METHODSEMANTICS) | ((guint64)1 << MONO_TABLE_CLASSLAYOUT)
4050                 | ((guint64)1 << MONO_TABLE_FIELDLAYOUT) | ((guint64)1 << MONO_TABLE_FIELDRVA)
4051                 | ((guint64)1 << MONO_TABLE_IMPLMAP) | ((guint64)1 << MONO_TABLE_NESTEDCLASS)
4052                 | ((guint64)1 << MONO_TABLE_METHODIMPL) | ((guint64)1 << MONO_TABLE_CUSTOMATTRIBUTE)
4053                 | ((guint64)1 << MONO_TABLE_DECLSECURITY) | ((guint64)1 << MONO_TABLE_GENERICPARAM)
4054                 | ((guint64)1 << MONO_TABLE_INTERFACEIMPL);
4055         
4056         /* Compute table sizes */
4057         /* the MonoImage has already been created in mono_image_basic_init() */
4058         meta = &assembly->image;
4059
4060         /* sizes should be multiple of 4 */
4061         pad_heap (&assembly->blob);
4062         pad_heap (&assembly->guid);
4063         pad_heap (&assembly->sheap);
4064         pad_heap (&assembly->us);
4065
4066         /* Setup the info used by compute_sizes () */
4067         meta->idx_blob_wide = assembly->blob.index >= 65536 ? 1 : 0;
4068         meta->idx_guid_wide = assembly->guid.index >= 65536 ? 1 : 0;
4069         meta->idx_string_wide = assembly->sheap.index >= 65536 ? 1 : 0;
4070
4071         meta_size += assembly->blob.index;
4072         meta_size += assembly->guid.index;
4073         meta_size += assembly->sheap.index;
4074         meta_size += assembly->us.index;
4075
4076         for (i=0; i < MONO_TABLE_NUM; ++i)
4077                 meta->tables [i].rows = assembly->tables [i].rows;
4078         
4079         for (i = 0; i < MONO_TABLE_NUM; i++){
4080                 if (meta->tables [i].rows == 0)
4081                         continue;
4082                 valid_mask |= (guint64)1 << i;
4083                 ntables ++;
4084                 meta->tables [i].row_size = mono_metadata_compute_size (
4085                         meta, i, &meta->tables [i].size_bitfield);
4086                 heapt_size += meta->tables [i].row_size * meta->tables [i].rows;
4087         }
4088         heapt_size += 24; /* #~ header size */
4089         heapt_size += ntables * 4;
4090         /* make multiple of 4 */
4091         heapt_size += 3;
4092         heapt_size &= ~3;
4093         meta_size += heapt_size;
4094         meta->raw_metadata = g_malloc0 (meta_size);
4095         p = (unsigned char*)meta->raw_metadata;
4096         /* the metadata signature */
4097         *p++ = 'B'; *p++ = 'S'; *p++ = 'J'; *p++ = 'B';
4098         /* version numbers and 4 bytes reserved */
4099         int16val = (guint16*)p;
4100         *int16val++ = GUINT16_TO_LE (meta->md_version_major);
4101         *int16val = GUINT16_TO_LE (meta->md_version_minor);
4102         p += 8;
4103         /* version string */
4104         int32val = (guint32*)p;
4105         *int32val = GUINT32_TO_LE ((strlen (meta->version) + 3) & (~3)); /* needs to be multiple of 4 */
4106         p += 4;
4107         memcpy (p, meta->version, strlen (meta->version));
4108         p += GUINT32_FROM_LE (*int32val);
4109         align_pointer (meta->raw_metadata, p);
4110         int16val = (guint16*)p;
4111         *int16val++ = GUINT16_TO_LE (0); /* flags must be 0 */
4112         *int16val = GUINT16_TO_LE (5); /* number of streams */
4113         p += 4;
4114
4115         /*
4116          * write the stream info.
4117          */
4118         table_offset = (p - (unsigned char*)meta->raw_metadata) + 5 * 8 + 40; /* room needed for stream headers */
4119         table_offset += 3; table_offset &= ~3;
4120
4121         assembly->tstream.index = heapt_size;
4122         for (i = 0; i < 5; ++i) {
4123                 int32val = (guint32*)p;
4124                 stream_desc [i].stream->offset = table_offset;
4125                 *int32val++ = GUINT32_TO_LE (table_offset);
4126                 *int32val = GUINT32_TO_LE (stream_desc [i].stream->index);
4127                 table_offset += GUINT32_FROM_LE (*int32val);
4128                 table_offset += 3; table_offset &= ~3;
4129                 p += 8;
4130                 strcpy ((char*)p, stream_desc [i].name);
4131                 p += strlen (stream_desc [i].name) + 1;
4132                 align_pointer (meta->raw_metadata, p);
4133         }
4134         /* 
4135          * now copy the data, the table stream header and contents goes first.
4136          */
4137         g_assert ((p - (unsigned char*)meta->raw_metadata) < assembly->tstream.offset);
4138         p = (guchar*)meta->raw_metadata + assembly->tstream.offset;
4139         int32val = (guint32*)p;
4140         *int32val = GUINT32_TO_LE (0); /* reserved */
4141         p += 4;
4142
4143         *p++ = 2; /* version */
4144         *p++ = 0;
4145
4146         if (meta->idx_string_wide)
4147                 *p |= 0x01;
4148         if (meta->idx_guid_wide)
4149                 *p |= 0x02;
4150         if (meta->idx_blob_wide)
4151                 *p |= 0x04;
4152         ++p;
4153         *p++ = 1; /* reserved */
4154         int64val = (guint64*)p;
4155         *int64val++ = GUINT64_TO_LE (valid_mask);
4156         *int64val++ = GUINT64_TO_LE (valid_mask & sorted_mask); /* bitvector of sorted tables  */
4157         p += 16;
4158         int32val = (guint32*)p;
4159         for (i = 0; i < MONO_TABLE_NUM; i++){
4160                 if (meta->tables [i].rows == 0)
4161                         continue;
4162                 *int32val++ = GUINT32_TO_LE (meta->tables [i].rows);
4163         }
4164         p = (unsigned char*)int32val;
4165
4166         /* sort the tables that still need sorting */
4167         table = &assembly->tables [MONO_TABLE_CONSTANT];
4168         if (table->rows)
4169                 qsort (table->values + MONO_CONSTANT_SIZE, table->rows, sizeof (guint32) * MONO_CONSTANT_SIZE, compare_constants);
4170         table = &assembly->tables [MONO_TABLE_METHODSEMANTICS];
4171         if (table->rows)
4172                 qsort (table->values + MONO_METHOD_SEMA_SIZE, table->rows, sizeof (guint32) * MONO_METHOD_SEMA_SIZE, compare_semantics);
4173         table = &assembly->tables [MONO_TABLE_CUSTOMATTRIBUTE];
4174         if (table->rows)
4175                 qsort (table->values + MONO_CUSTOM_ATTR_SIZE, table->rows, sizeof (guint32) * MONO_CUSTOM_ATTR_SIZE, compare_custom_attrs);
4176         table = &assembly->tables [MONO_TABLE_FIELDMARSHAL];
4177         if (table->rows)
4178                 qsort (table->values + MONO_FIELD_MARSHAL_SIZE, table->rows, sizeof (guint32) * MONO_FIELD_MARSHAL_SIZE, compare_field_marshal);
4179         table = &assembly->tables [MONO_TABLE_NESTEDCLASS];
4180         if (table->rows)
4181                 qsort (table->values + MONO_NESTED_CLASS_SIZE, table->rows, sizeof (guint32) * MONO_NESTED_CLASS_SIZE, compare_nested);
4182         /* Section 21.11 DeclSecurity in Partition II doesn't specify this to be sorted by MS implementation requires it */
4183         table = &assembly->tables [MONO_TABLE_DECLSECURITY];
4184         if (table->rows)
4185                 qsort (table->values + MONO_DECL_SECURITY_SIZE, table->rows, sizeof (guint32) * MONO_DECL_SECURITY_SIZE, compare_declsecurity_attrs);
4186         table = &assembly->tables [MONO_TABLE_INTERFACEIMPL];
4187         if (table->rows)
4188                 qsort (table->values + MONO_INTERFACEIMPL_SIZE, table->rows, sizeof (guint32) * MONO_INTERFACEIMPL_SIZE, compare_interface_impl);
4189
4190         /* compress the tables */
4191         for (i = 0; i < MONO_TABLE_NUM; i++){
4192                 int row, col;
4193                 guint32 *values;
4194                 guint32 bitfield = meta->tables [i].size_bitfield;
4195                 if (!meta->tables [i].rows)
4196                         continue;
4197                 if (assembly->tables [i].columns != mono_metadata_table_count (bitfield))
4198                         g_error ("col count mismatch in %d: %d %d", i, assembly->tables [i].columns, mono_metadata_table_count (bitfield));
4199                 meta->tables [i].base = (char*)p;
4200                 for (row = 1; row <= meta->tables [i].rows; ++row) {
4201                         values = assembly->tables [i].values + row * assembly->tables [i].columns;
4202                         for (col = 0; col < assembly->tables [i].columns; ++col) {
4203                                 switch (mono_metadata_table_size (bitfield, col)) {
4204                                 case 1:
4205                                         *p++ = values [col];
4206                                         break;
4207                                 case 2:
4208                                         *p++ = values [col] & 0xff;
4209                                         *p++ = (values [col] >> 8) & 0xff;
4210                                         break;
4211                                 case 4:
4212                                         *p++ = values [col] & 0xff;
4213                                         *p++ = (values [col] >> 8) & 0xff;
4214                                         *p++ = (values [col] >> 16) & 0xff;
4215                                         *p++ = (values [col] >> 24) & 0xff;
4216                                         break;
4217                                 default:
4218                                         g_assert_not_reached ();
4219                                 }
4220                         }
4221                 }
4222                 g_assert ((p - (const unsigned char*)meta->tables [i].base) == (meta->tables [i].rows * meta->tables [i].row_size));
4223         }
4224         
4225         g_assert (assembly->guid.offset + assembly->guid.index < meta_size);
4226         memcpy (meta->raw_metadata + assembly->sheap.offset, assembly->sheap.data, assembly->sheap.index);
4227         memcpy (meta->raw_metadata + assembly->us.offset, assembly->us.data, assembly->us.index);
4228         memcpy (meta->raw_metadata + assembly->blob.offset, assembly->blob.data, assembly->blob.index);
4229         memcpy (meta->raw_metadata + assembly->guid.offset, assembly->guid.data, assembly->guid.index);
4230
4231         assembly->meta_size = assembly->guid.offset + assembly->guid.index;
4232 }
4233
4234 /*
4235  * Some tables in metadata need to be sorted according to some criteria, but
4236  * when methods and fields are first created with reflection, they may be assigned a token
4237  * that doesn't correspond to the final token they will get assigned after the sorting.
4238  * ILGenerator.cs keeps a fixup table that maps the position of tokens in the IL code stream
4239  * with the reflection objects that represent them. Once all the tables are set up, the 
4240  * reflection objects will contains the correct table index. fixup_method() will fixup the
4241  * tokens for the method with ILGenerator @ilgen.
4242  */
4243 static void
4244 fixup_method (MonoReflectionILGen *ilgen, gpointer value, MonoDynamicImage *assembly)
4245 {
4246         guint32 code_idx = GPOINTER_TO_UINT (value);
4247         MonoReflectionILTokenInfo *iltoken;
4248         MonoReflectionFieldBuilder *field;
4249         MonoReflectionCtorBuilder *ctor;
4250         MonoReflectionMethodBuilder *method;
4251         MonoReflectionTypeBuilder *tb;
4252         MonoReflectionArrayMethod *am;
4253         guint32 i, idx = 0;
4254         unsigned char *target;
4255
4256         for (i = 0; i < ilgen->num_token_fixups; ++i) {
4257                 iltoken = (MonoReflectionILTokenInfo *)mono_array_addr_with_size (ilgen->token_fixups, sizeof (MonoReflectionILTokenInfo), i);
4258                 target = (guchar*)assembly->code.data + code_idx + iltoken->code_pos;
4259                 switch (target [3]) {
4260                 case MONO_TABLE_FIELD:
4261                         if (!strcmp (iltoken->member->vtable->klass->name, "FieldBuilder")) {
4262                                 field = (MonoReflectionFieldBuilder *)iltoken->member;
4263                                 idx = field->table_idx;
4264                         } else if (!strcmp (iltoken->member->vtable->klass->name, "MonoField")) {
4265                                 MonoClassField *f = ((MonoReflectionField*)iltoken->member)->field;
4266                                 idx = GPOINTER_TO_UINT (g_hash_table_lookup (assembly->field_to_table_idx, f));
4267                         } else {
4268                                 g_assert_not_reached ();
4269                         }
4270                         break;
4271                 case MONO_TABLE_METHOD:
4272                         if (!strcmp (iltoken->member->vtable->klass->name, "MethodBuilder")) {
4273                                 method = (MonoReflectionMethodBuilder *)iltoken->member;
4274                                 idx = method->table_idx;
4275                         } else if (!strcmp (iltoken->member->vtable->klass->name, "ConstructorBuilder")) {
4276                                 ctor = (MonoReflectionCtorBuilder *)iltoken->member;
4277                                 idx = ctor->table_idx;
4278                         } else if (!strcmp (iltoken->member->vtable->klass->name, "MonoMethod") || 
4279                                            !strcmp (iltoken->member->vtable->klass->name, "MonoCMethod")) {
4280                                 MonoMethod *m = ((MonoReflectionMethod*)iltoken->member)->method;
4281                                 idx = GPOINTER_TO_UINT (g_hash_table_lookup (assembly->method_to_table_idx, m));
4282                         } else {
4283                                 g_assert_not_reached ();
4284                         }
4285                         break;
4286                 case MONO_TABLE_TYPEDEF:
4287                         if (strcmp (iltoken->member->vtable->klass->name, "TypeBuilder"))
4288                                 g_assert_not_reached ();
4289                         tb = (MonoReflectionTypeBuilder *)iltoken->member;
4290                         idx = tb->table_idx;
4291                         break;
4292                 case MONO_TABLE_MEMBERREF:
4293                         if (!strcmp (iltoken->member->vtable->klass->name, "MonoArrayMethod")) {
4294                                 am = (MonoReflectionArrayMethod*)iltoken->member;
4295                                 idx = am->table_idx;
4296                         } else if (!strcmp (iltoken->member->vtable->klass->name, "MonoMethod") ||
4297                                    !strcmp (iltoken->member->vtable->klass->name, "MonoCMethod") ||
4298                                    !strcmp (iltoken->member->vtable->klass->name, "MonoGenericMethod") ||
4299                                    !strcmp (iltoken->member->vtable->klass->name, "MonoGenericCMethod")) {
4300                                 MonoMethod *m = ((MonoReflectionMethod*)iltoken->member)->method;
4301                                 g_assert (m->klass->generic_class || m->klass->generic_container);
4302                                 continue;
4303                         } else if (!strcmp (iltoken->member->vtable->klass->name, "FieldBuilder")) {
4304                                 continue;
4305                         } else if (!strcmp (iltoken->member->vtable->klass->name, "MonoField")) {
4306                                 MonoClassField *f = ((MonoReflectionField*)iltoken->member)->field;
4307                                 g_assert (is_field_on_inst (f));
4308                                 continue;
4309                         } else if (!strcmp (iltoken->member->vtable->klass->name, "MethodBuilder") ||
4310                                         !strcmp (iltoken->member->vtable->klass->name, "ConstructorBuilder")) {
4311                                 continue;
4312                         } else if (!strcmp (iltoken->member->vtable->klass->name, "FieldOnTypeBuilderInst")) {
4313                                 continue;
4314                         } else if (!strcmp (iltoken->member->vtable->klass->name, "MethodOnTypeBuilderInst")) {
4315                                 continue;
4316                         } else if (!strcmp (iltoken->member->vtable->klass->name, "ConstructorOnTypeBuilderInst")) {
4317                                 continue;
4318                         } else {
4319                                 g_assert_not_reached ();
4320                         }
4321                         break;
4322                 case MONO_TABLE_METHODSPEC:
4323                         if (!strcmp (iltoken->member->vtable->klass->name, "MonoGenericMethod")) {
4324                                 MonoMethod *m = ((MonoReflectionMethod*)iltoken->member)->method;
4325                                 g_assert (mono_method_signature (m)->generic_param_count);
4326                                 continue;
4327                         } else if (!strcmp (iltoken->member->vtable->klass->name, "MethodBuilder")) {
4328                                 continue;
4329                         } else if (!strcmp (iltoken->member->vtable->klass->name, "MethodOnTypeBuilderInst")) {
4330                                 continue;
4331                         } else {
4332                                 g_assert_not_reached ();
4333                         }
4334                         break;
4335                 default:
4336                         g_error ("got unexpected table 0x%02x in fixup", target [3]);
4337                 }
4338                 target [0] = idx & 0xff;
4339                 target [1] = (idx >> 8) & 0xff;
4340                 target [2] = (idx >> 16) & 0xff;
4341         }
4342 }
4343
4344 /*
4345  * fixup_cattrs:
4346  *
4347  *   The CUSTOM_ATTRIBUTE table might contain METHODDEF tokens whose final
4348  * value is not known when the table is emitted.
4349  */
4350 static void
4351 fixup_cattrs (MonoDynamicImage *assembly)
4352 {
4353         MonoDynamicTable *table;
4354         guint32 *values;
4355         guint32 type, i, idx, token;
4356         MonoObject *ctor;
4357
4358         table = &assembly->tables [MONO_TABLE_CUSTOMATTRIBUTE];
4359
4360         for (i = 0; i < table->rows; ++i) {
4361                 values = table->values + ((i + 1) * MONO_CUSTOM_ATTR_SIZE);
4362
4363                 type = values [MONO_CUSTOM_ATTR_TYPE];
4364                 if ((type & MONO_CUSTOM_ATTR_TYPE_MASK) == MONO_CUSTOM_ATTR_TYPE_METHODDEF) {
4365                         idx = type >> MONO_CUSTOM_ATTR_TYPE_BITS;
4366                         token = mono_metadata_make_token (MONO_TABLE_METHOD, idx);
4367                         ctor = mono_g_hash_table_lookup (assembly->remapped_tokens, GUINT_TO_POINTER (token));
4368                         g_assert (ctor);
4369
4370                         if (!strcmp (ctor->vtable->klass->name, "MonoCMethod")) {
4371                                 MonoMethod *m = ((MonoReflectionMethod*)ctor)->method;
4372                                 idx = GPOINTER_TO_UINT (g_hash_table_lookup (assembly->method_to_table_idx, m));
4373                                 values [MONO_CUSTOM_ATTR_TYPE] = (idx << MONO_CUSTOM_ATTR_TYPE_BITS) | MONO_CUSTOM_ATTR_TYPE_METHODDEF;
4374                         } else if (!strcmp (ctor->vtable->klass->name, "ConstructorBuilder")) {
4375                                 MonoMethod *m = ((MonoReflectionCtorBuilder*)ctor)->mhandle;
4376                                 idx = GPOINTER_TO_UINT (g_hash_table_lookup (assembly->method_to_table_idx, m));
4377                                 values [MONO_CUSTOM_ATTR_TYPE] = (idx << MONO_CUSTOM_ATTR_TYPE_BITS) | MONO_CUSTOM_ATTR_TYPE_METHODDEF;
4378                         }
4379                 }
4380         }
4381 }
4382
4383 static void
4384 assembly_add_resource_manifest (MonoReflectionModuleBuilder *mb, MonoDynamicImage *assembly, MonoReflectionResource *rsrc, guint32 implementation)
4385 {
4386         MonoDynamicTable *table;
4387         guint32 *values;
4388
4389         table = &assembly->tables [MONO_TABLE_MANIFESTRESOURCE];
4390         table->rows++;
4391         alloc_table (table, table->rows);
4392         values = table->values + table->next_idx * MONO_MANIFEST_SIZE;
4393         values [MONO_MANIFEST_OFFSET] = rsrc->offset;
4394         values [MONO_MANIFEST_FLAGS] = rsrc->attrs;
4395         values [MONO_MANIFEST_NAME] = string_heap_insert_mstring (&assembly->sheap, rsrc->name);
4396         values [MONO_MANIFEST_IMPLEMENTATION] = implementation;
4397         table->next_idx++;
4398 }
4399
4400 static void
4401 assembly_add_resource (MonoReflectionModuleBuilder *mb, MonoDynamicImage *assembly, MonoReflectionResource *rsrc)
4402 {
4403         MonoDynamicTable *table;
4404         guint32 *values;
4405         char blob_size [6];
4406         guchar hash [20];
4407         char *b = blob_size;
4408         char *name, *sname;
4409         guint32 idx, offset;
4410
4411         if (rsrc->filename) {
4412                 name = mono_string_to_utf8 (rsrc->filename);
4413                 sname = g_path_get_basename (name);
4414         
4415                 table = &assembly->tables [MONO_TABLE_FILE];
4416                 table->rows++;
4417                 alloc_table (table, table->rows);
4418                 values = table->values + table->next_idx * MONO_FILE_SIZE;
4419                 values [MONO_FILE_FLAGS] = FILE_CONTAINS_NO_METADATA;
4420                 values [MONO_FILE_NAME] = string_heap_insert (&assembly->sheap, sname);
4421                 g_free (sname);
4422
4423                 mono_sha1_get_digest_from_file (name, hash);
4424                 mono_metadata_encode_value (20, b, &b);
4425                 values [MONO_FILE_HASH_VALUE] = mono_image_add_stream_data (&assembly->blob, blob_size, b-blob_size);
4426                 mono_image_add_stream_data (&assembly->blob, (char*)hash, 20);
4427                 g_free (name);
4428                 idx = table->next_idx++;
4429                 rsrc->offset = 0;
4430                 idx = MONO_IMPLEMENTATION_FILE | (idx << MONO_IMPLEMENTATION_BITS);
4431         } else {
4432                 char sizebuf [4];
4433                 char *data;
4434                 guint len;
4435                 if (rsrc->data) {
4436                         data = mono_array_addr (rsrc->data, char, 0);
4437                         len = mono_array_length (rsrc->data);
4438                 } else {
4439                         data = NULL;
4440                         len = 0;
4441                 }
4442                 offset = len;
4443                 sizebuf [0] = offset; sizebuf [1] = offset >> 8;
4444                 sizebuf [2] = offset >> 16; sizebuf [3] = offset >> 24;
4445                 rsrc->offset = mono_image_add_stream_data (&assembly->resources, sizebuf, 4);
4446                 mono_image_add_stream_data (&assembly->resources, data, len);
4447
4448                 if (!mb->is_main)
4449                         /* 
4450                          * The entry should be emitted into the MANIFESTRESOURCE table of 
4451                          * the main module, but that needs to reference the FILE table
4452                          * which isn't emitted yet.
4453                          */
4454                         return;
4455                 else
4456                         idx = 0;
4457         }
4458
4459         assembly_add_resource_manifest (mb, assembly, rsrc, idx);
4460 }
4461
4462 static void
4463 set_version_from_string (MonoString *version, guint32 *values)
4464 {
4465         gchar *ver, *p, *str;
4466         guint32 i;
4467         
4468         values [MONO_ASSEMBLY_MAJOR_VERSION] = 0;
4469         values [MONO_ASSEMBLY_MINOR_VERSION] = 0;
4470         values [MONO_ASSEMBLY_REV_NUMBER] = 0;
4471         values [MONO_ASSEMBLY_BUILD_NUMBER] = 0;
4472         if (!version)
4473                 return;
4474         ver = str = mono_string_to_utf8 (version);
4475         for (i = 0; i < 4; ++i) {
4476                 values [MONO_ASSEMBLY_MAJOR_VERSION + i] = strtol (ver, &p, 10);
4477                 switch (*p) {
4478                 case '.':
4479                         p++;
4480                         break;
4481                 case '*':
4482                         /* handle Revision and Build */
4483                         p++;
4484                         break;
4485                 }
4486                 ver = p;
4487         }
4488         g_free (str);
4489 }
4490
4491 static guint32
4492 load_public_key (MonoArray *pkey, MonoDynamicImage *assembly) {
4493         gsize len;
4494         guint32 token = 0;
4495         char blob_size [6];
4496         char *b = blob_size;
4497
4498         if (!pkey)
4499                 return token;
4500
4501         len = mono_array_length (pkey);
4502         mono_metadata_encode_value (len, b, &b);
4503         token = mono_image_add_stream_data (&assembly->blob, blob_size, b - blob_size);
4504         mono_image_add_stream_data (&assembly->blob, mono_array_addr (pkey, char, 0), len);
4505
4506         assembly->public_key = g_malloc (len);
4507         memcpy (assembly->public_key, mono_array_addr (pkey, char, 0), len);
4508         assembly->public_key_len = len;
4509
4510         /* Special case: check for ECMA key (16 bytes) */
4511         if ((len == MONO_ECMA_KEY_LENGTH) && mono_is_ecma_key (mono_array_addr (pkey, char, 0), len)) {
4512                 /* In this case we must reserve 128 bytes (1024 bits) for the signature */
4513                 assembly->strong_name_size = MONO_DEFAULT_PUBLIC_KEY_LENGTH;
4514         } else if (len >= MONO_PUBLIC_KEY_HEADER_LENGTH + MONO_MINIMUM_PUBLIC_KEY_LENGTH) {
4515                 /* minimum key size (in 2.0) is 384 bits */
4516                 assembly->strong_name_size = len - MONO_PUBLIC_KEY_HEADER_LENGTH;
4517         } else {
4518                 /* FIXME - verifier */
4519                 g_warning ("Invalid public key length: %d bits (total: %d)", (int)MONO_PUBLIC_KEY_BIT_SIZE (len), (int)len);
4520                 assembly->strong_name_size = MONO_DEFAULT_PUBLIC_KEY_LENGTH; /* to be safe */
4521         }
4522         assembly->strong_name = g_malloc0 (assembly->strong_name_size);
4523
4524         return token;
4525 }
4526
4527 static void
4528 mono_image_emit_manifest (MonoReflectionModuleBuilder *moduleb)
4529 {
4530         MonoDynamicTable *table;
4531         MonoDynamicImage *assembly;
4532         MonoReflectionAssemblyBuilder *assemblyb;
4533         MonoDomain *domain;
4534         guint32 *values;
4535         int i;
4536         guint32 module_index;
4537
4538         assemblyb = moduleb->assemblyb;
4539         assembly = moduleb->dynamic_image;
4540         domain = mono_object_domain (assemblyb);
4541
4542         /* Emit ASSEMBLY table */
4543         table = &assembly->tables [MONO_TABLE_ASSEMBLY];
4544         alloc_table (table, 1);
4545         values = table->values + MONO_ASSEMBLY_SIZE;
4546         values [MONO_ASSEMBLY_HASH_ALG] = assemblyb->algid? assemblyb->algid: ASSEMBLY_HASH_SHA1;
4547         values [MONO_ASSEMBLY_NAME] = string_heap_insert_mstring (&assembly->sheap, assemblyb->name);
4548         if (assemblyb->culture) {
4549                 values [MONO_ASSEMBLY_CULTURE] = string_heap_insert_mstring (&assembly->sheap, assemblyb->culture);
4550         } else {
4551                 values [MONO_ASSEMBLY_CULTURE] = string_heap_insert (&assembly->sheap, "");
4552         }
4553         values [MONO_ASSEMBLY_PUBLIC_KEY] = load_public_key (assemblyb->public_key, assembly);
4554         values [MONO_ASSEMBLY_FLAGS] = assemblyb->flags;
4555         set_version_from_string (assemblyb->version, values);
4556
4557         /* Emit FILE + EXPORTED_TYPE table */
4558         module_index = 0;
4559         for (i = 0; i < mono_array_length (assemblyb->modules); ++i) {
4560                 int j;
4561                 MonoReflectionModuleBuilder *file_module = 
4562                         mono_array_get (assemblyb->modules, MonoReflectionModuleBuilder*, i);
4563                 if (file_module != moduleb) {
4564                         mono_image_fill_file_table (domain, (MonoReflectionModule*)file_module, assembly);
4565                         module_index ++;
4566                         if (file_module->types) {
4567                                 for (j = 0; j < file_module->num_types; ++j) {
4568                                         MonoReflectionTypeBuilder *tb = mono_array_get (file_module->types, MonoReflectionTypeBuilder*, j);
4569                                         mono_image_fill_export_table (domain, tb, module_index, 0, assembly);
4570                                 }
4571                         }
4572                 }
4573         }
4574         if (assemblyb->loaded_modules) {
4575                 for (i = 0; i < mono_array_length (assemblyb->loaded_modules); ++i) {
4576                         MonoReflectionModule *file_module = 
4577                                 mono_array_get (assemblyb->loaded_modules, MonoReflectionModule*, i);
4578                         mono_image_fill_file_table (domain, file_module, assembly);
4579                         module_index ++;
4580                         mono_image_fill_export_table_from_module (domain, file_module, module_index, assembly);
4581                 }
4582         }
4583         if (assemblyb->type_forwarders)
4584                 mono_image_fill_export_table_from_type_forwarders (assemblyb, assembly);
4585
4586         /* Emit MANIFESTRESOURCE table */
4587         module_index = 0;
4588         for (i = 0; i < mono_array_length (assemblyb->modules); ++i) {
4589                 int j;
4590                 MonoReflectionModuleBuilder *file_module = 
4591                         mono_array_get (assemblyb->modules, MonoReflectionModuleBuilder*, i);
4592                 /* The table for the main module is emitted later */
4593                 if (file_module != moduleb) {
4594                         module_index ++;
4595                         if (file_module->resources) {
4596                                 int len = mono_array_length (file_module->resources);
4597                                 for (j = 0; j < len; ++j) {
4598                                         MonoReflectionResource* res = (MonoReflectionResource*)mono_array_addr (file_module->resources, MonoReflectionResource, j);
4599                                         assembly_add_resource_manifest (file_module, assembly, res, MONO_IMPLEMENTATION_FILE | (module_index << MONO_IMPLEMENTATION_BITS));
4600                                 }
4601                         }
4602                 }
4603         }               
4604 }
4605
4606 #ifndef DISABLE_REFLECTION_EMIT_SAVE
4607
4608 /*
4609  * mono_image_build_metadata() will fill the info in all the needed metadata tables
4610  * for the modulebuilder @moduleb.
4611  * At the end of the process, method and field tokens are fixed up and the 
4612  * on-disk compressed metadata representation is created.
4613  */
4614 void
4615 mono_image_build_metadata (MonoReflectionModuleBuilder *moduleb)
4616 {
4617         MonoDynamicTable *table;
4618         MonoDynamicImage *assembly;
4619         MonoReflectionAssemblyBuilder *assemblyb;
4620         MonoDomain *domain;
4621         MonoPtrArray types;
4622         guint32 *values;
4623         int i, j;
4624
4625         assemblyb = moduleb->assemblyb;
4626         assembly = moduleb->dynamic_image;
4627         domain = mono_object_domain (assemblyb);
4628
4629         if (assembly->text_rva)
4630                 return;
4631
4632         assembly->text_rva = START_TEXT_RVA;
4633
4634         if (moduleb->is_main) {
4635                 mono_image_emit_manifest (moduleb);
4636         }
4637
4638         table = &assembly->tables [MONO_TABLE_TYPEDEF];
4639         table->rows = 1; /* .<Module> */
4640         table->next_idx++;
4641         alloc_table (table, table->rows);
4642         /*
4643          * Set the first entry.
4644          */
4645         values = table->values + table->columns;
4646         values [MONO_TYPEDEF_FLAGS] = 0;
4647         values [MONO_TYPEDEF_NAME] = string_heap_insert (&assembly->sheap, "<Module>") ;
4648         values [MONO_TYPEDEF_NAMESPACE] = string_heap_insert (&assembly->sheap, "") ;
4649         values [MONO_TYPEDEF_EXTENDS] = 0;
4650         values [MONO_TYPEDEF_FIELD_LIST] = 1;
4651         values [MONO_TYPEDEF_METHOD_LIST] = 1;
4652
4653         /* 
4654          * handle global methods 
4655          * FIXME: test what to do when global methods are defined in multiple modules.
4656          */
4657         if (moduleb->global_methods) {
4658                 table = &assembly->tables [MONO_TABLE_METHOD];
4659                 table->rows += mono_array_length (moduleb->global_methods);
4660                 alloc_table (table, table->rows);
4661                 for (i = 0; i < mono_array_length (moduleb->global_methods); ++i)
4662                         mono_image_get_method_info (
4663                                 mono_array_get (moduleb->global_methods, MonoReflectionMethodBuilder*, i), assembly);
4664         }
4665         if (moduleb->global_fields) {
4666                 table = &assembly->tables [MONO_TABLE_FIELD];
4667                 table->rows += mono_array_length (moduleb->global_fields);
4668                 alloc_table (table, table->rows);
4669                 for (i = 0; i < mono_array_length (moduleb->global_fields); ++i)
4670                         mono_image_get_field_info (
4671                                 mono_array_get (moduleb->global_fields, MonoReflectionFieldBuilder*, i), assembly);
4672         }
4673
4674         table = &assembly->tables [MONO_TABLE_MODULE];
4675         alloc_table (table, 1);
4676         mono_image_fill_module_table (domain, moduleb, assembly);
4677
4678         /* Collect all types into a list sorted by their table_idx */
4679         mono_ptr_array_init (types, moduleb->num_types);
4680
4681         if (moduleb->types)
4682                 for (i = 0; i < moduleb->num_types; ++i) {
4683                         MonoReflectionTypeBuilder *type = mono_array_get (moduleb->types, MonoReflectionTypeBuilder*, i);
4684                         collect_types (&types, type);
4685                 }
4686
4687         mono_ptr_array_sort (types, (gpointer)compare_types_by_table_idx);
4688         table = &assembly->tables [MONO_TABLE_TYPEDEF];
4689         table->rows += mono_ptr_array_size (types);
4690         alloc_table (table, table->rows);
4691
4692         /*
4693          * Emit type names + namespaces at one place inside the string heap,
4694          * so load_class_names () needs to touch fewer pages.
4695          */
4696         for (i = 0; i < mono_ptr_array_size (types); ++i) {
4697                 MonoReflectionTypeBuilder *tb = mono_ptr_array_get (types, i);
4698                 string_heap_insert_mstring (&assembly->sheap, tb->nspace);
4699         }
4700         for (i = 0; i < mono_ptr_array_size (types); ++i) {
4701                 MonoReflectionTypeBuilder *tb = mono_ptr_array_get (types, i);
4702                 string_heap_insert_mstring (&assembly->sheap, tb->name);
4703         }
4704
4705         for (i = 0; i < mono_ptr_array_size (types); ++i) {
4706                 MonoReflectionTypeBuilder *type = mono_ptr_array_get (types, i);
4707                 mono_image_get_type_info (domain, type, assembly);
4708         }
4709
4710         /* 
4711          * table->rows is already set above and in mono_image_fill_module_table.
4712          */
4713         /* add all the custom attributes at the end, once all the indexes are stable */
4714         mono_image_add_cattrs (assembly, 1, MONO_CUSTOM_ATTR_ASSEMBLY, assemblyb->cattrs);
4715
4716         /* CAS assembly permissions */
4717         if (assemblyb->permissions_minimum)
4718                 mono_image_add_decl_security (assembly, mono_metadata_make_token (MONO_TABLE_ASSEMBLY, 1), assemblyb->permissions_minimum);
4719         if (assemblyb->permissions_optional)
4720                 mono_image_add_decl_security (assembly, mono_metadata_make_token (MONO_TABLE_ASSEMBLY, 1), assemblyb->permissions_optional);
4721         if (assemblyb->permissions_refused)
4722                 mono_image_add_decl_security (assembly, mono_metadata_make_token (MONO_TABLE_ASSEMBLY, 1), assemblyb->permissions_refused);
4723
4724         module_add_cattrs (assembly, moduleb);
4725
4726         /* fixup tokens */
4727         mono_g_hash_table_foreach (assembly->token_fixups, (GHFunc)fixup_method, assembly);
4728
4729         /* Create the MethodImpl table.  We do this after emitting all methods so we already know
4730          * the final tokens and don't need another fixup pass. */
4731
4732         if (moduleb->global_methods) {
4733                 for (i = 0; i < mono_array_length (moduleb->global_methods); ++i) {
4734                         MonoReflectionMethodBuilder *mb = mono_array_get (
4735                                 moduleb->global_methods, MonoReflectionMethodBuilder*, i);
4736                         mono_image_add_methodimpl (assembly, mb);
4737                 }
4738         }
4739
4740         for (i = 0; i < mono_ptr_array_size (types); ++i) {
4741                 MonoReflectionTypeBuilder *type = mono_ptr_array_get (types, i);
4742                 if (type->methods) {
4743                         for (j = 0; j < type->num_methods; ++j) {
4744                                 MonoReflectionMethodBuilder *mb = mono_array_get (
4745                                         type->methods, MonoReflectionMethodBuilder*, j);
4746
4747                                 mono_image_add_methodimpl (assembly, mb);
4748                         }
4749                 }
4750         }
4751
4752         mono_ptr_array_destroy (types);
4753
4754         fixup_cattrs (assembly);
4755 }
4756
4757 #else /* DISABLE_REFLECTION_EMIT_SAVE */
4758
4759 void
4760 mono_image_build_metadata (MonoReflectionModuleBuilder *moduleb)
4761 {
4762         g_error ("This mono runtime was configured with --enable-minimal=reflection_emit_save, so saving of dynamic assemblies is not supported.");
4763 }
4764
4765 #endif /* DISABLE_REFLECTION_EMIT_SAVE */
4766
4767
4768 typedef struct {
4769         guint32 import_lookup_table;
4770         guint32 timestamp;
4771         guint32 forwarder;
4772         guint32 name_rva;
4773         guint32 import_address_table_rva;
4774 } MonoIDT;
4775
4776 typedef struct {
4777         guint32 name_rva;
4778         guint32 flags;
4779 } MonoILT;
4780
4781 #ifndef DISABLE_REFLECTION_EMIT
4782
4783 /*
4784  * mono_image_insert_string:
4785  * @module: module builder object
4786  * @str: a string
4787  *
4788  * Insert @str into the user string stream of @module.
4789  */
4790 guint32
4791 mono_image_insert_string (MonoReflectionModuleBuilder *module, MonoString *str)
4792 {
4793         MonoDynamicImage *assembly;
4794         guint32 idx;
4795         char buf [16];
4796         char *b = buf;
4797         
4798         if (!module->dynamic_image)
4799                 mono_image_module_basic_init (module);
4800
4801         assembly = module->dynamic_image;
4802         
4803         if (assembly->save) {
4804                 mono_metadata_encode_value (1 | (str->length * 2), b, &b);
4805                 idx = mono_image_add_stream_data (&assembly->us, buf, b-buf);
4806 #if G_BYTE_ORDER != G_LITTLE_ENDIAN
4807         {
4808                 char *swapped = g_malloc (2 * mono_string_length (str));
4809                 const char *p = (const char*)mono_string_chars (str);
4810
4811                 swap_with_size (swapped, p, 2, mono_string_length (str));
4812                 mono_image_add_stream_data (&assembly->us, swapped, str->length * 2);
4813                 g_free (swapped);
4814         }
4815 #else
4816                 mono_image_add_stream_data (&assembly->us, (const char*)mono_string_chars (str), str->length * 2);
4817 #endif
4818                 mono_image_add_stream_data (&assembly->us, "", 1);
4819         } else {
4820                 idx = assembly->us.index ++;
4821         }
4822
4823         register_dyn_token (assembly, MONO_TOKEN_STRING | idx, (MonoObject*)str);
4824
4825         return MONO_TOKEN_STRING | idx;
4826 }
4827
4828 guint32
4829 mono_image_create_method_token (MonoDynamicImage *assembly, MonoObject *obj, MonoArray *opt_param_types)
4830 {
4831         MonoClass *klass;
4832         guint32 token = 0;
4833         MonoMethodSignature *sig;
4834
4835         klass = obj->vtable->klass;
4836         if (strcmp (klass->name, "MonoMethod") == 0 || strcmp (klass->name, "MonoCMethod") == 0) {
4837                 MonoMethod *method = ((MonoReflectionMethod *)obj)->method;
4838                 MonoMethodSignature *old;
4839                 guint32 sig_token, parent;
4840                 int nargs, i;
4841
4842                 g_assert (opt_param_types && (mono_method_signature (method)->sentinelpos >= 0));
4843
4844                 nargs = mono_array_length (opt_param_types);
4845                 old = mono_method_signature (method);
4846                 sig = mono_metadata_signature_alloc ( &assembly->image, old->param_count + nargs);
4847
4848                 sig->hasthis = old->hasthis;
4849                 sig->explicit_this = old->explicit_this;
4850                 sig->call_convention = old->call_convention;
4851                 sig->generic_param_count = old->generic_param_count;
4852                 sig->param_count = old->param_count + nargs;
4853                 sig->sentinelpos = old->param_count;
4854                 sig->ret = old->ret;
4855
4856                 for (i = 0; i < old->param_count; i++)
4857                         sig->params [i] = old->params [i];
4858
4859                 for (i = 0; i < nargs; i++) {
4860                         MonoReflectionType *rt = mono_array_get (opt_param_types, MonoReflectionType *, i);
4861                         sig->params [old->param_count + i] = mono_reflection_type_get_handle (rt);
4862                 }
4863
4864                 parent = mono_image_typedef_or_ref (assembly, &method->klass->byval_arg);
4865                 g_assert ((parent & MONO_TYPEDEFORREF_MASK) == MONO_MEMBERREF_PARENT_TYPEREF);
4866                 parent >>= MONO_TYPEDEFORREF_BITS;
4867
4868                 parent <<= MONO_MEMBERREF_PARENT_BITS;
4869                 parent |= MONO_MEMBERREF_PARENT_TYPEREF;
4870
4871                 sig_token = method_encode_signature (assembly, sig);
4872                 token = mono_image_get_varargs_method_token (assembly, parent, method->name, sig_token);
4873         } else if (strcmp (klass->name, "MethodBuilder") == 0) {
4874                 MonoReflectionMethodBuilder *mb = (MonoReflectionMethodBuilder *)obj;
4875                 ReflectionMethodBuilder rmb;
4876                 guint32 parent, sig_token;
4877                 int nopt_args, nparams, ngparams, i;
4878                 char *name;
4879
4880                 reflection_methodbuilder_from_method_builder (&rmb, mb);
4881                 rmb.opt_types = opt_param_types;
4882                 nopt_args = mono_array_length (opt_param_types);
4883
4884                 nparams = rmb.parameters ? mono_array_length (rmb.parameters): 0;
4885                 ngparams = rmb.generic_params ? mono_array_length (rmb.generic_params): 0;
4886                 sig = mono_metadata_signature_alloc (&assembly->image, nparams + nopt_args);
4887
4888                 sig->hasthis = !(rmb.attrs & METHOD_ATTRIBUTE_STATIC);
4889                 sig->explicit_this = (rmb.call_conv & 0x40) == 0x40;
4890                 sig->call_convention = rmb.call_conv;
4891                 sig->generic_param_count = ngparams;
4892                 sig->param_count = nparams + nopt_args;
4893                 sig->sentinelpos = nparams;
4894                 sig->ret = mono_reflection_type_get_handle (rmb.rtype);
4895
4896                 for (i = 0; i < nparams; i++) {
4897                         MonoReflectionType *rt = mono_array_get (rmb.parameters, MonoReflectionType *, i);
4898                         sig->params [i] = mono_reflection_type_get_handle (rt);
4899                 }
4900
4901                 for (i = 0; i < nopt_args; i++) {
4902                         MonoReflectionType *rt = mono_array_get (opt_param_types, MonoReflectionType *, i);
4903                         sig->params [nparams + i] = mono_reflection_type_get_handle (rt);
4904                 }
4905
4906                 sig_token = method_builder_encode_signature (assembly, &rmb);
4907
4908                 parent = mono_image_create_token (assembly, obj, TRUE, TRUE);
4909                 g_assert (mono_metadata_token_table (parent) == MONO_TABLE_METHOD);
4910
4911                 parent = mono_metadata_token_index (parent) << MONO_MEMBERREF_PARENT_BITS;
4912                 parent |= MONO_MEMBERREF_PARENT_METHODDEF;
4913
4914                 name = mono_string_to_utf8 (rmb.name);
4915                 token = mono_image_get_varargs_method_token (
4916                         assembly, parent, name, sig_token);
4917                 g_free (name);
4918         } else {
4919                 g_error ("requested method token for %s\n", klass->name);
4920         }
4921
4922         g_hash_table_insert (assembly->vararg_aux_hash, GUINT_TO_POINTER (token), sig);
4923         register_dyn_token (assembly, token, obj);
4924         return token;
4925 }
4926
4927 /*
4928  * mono_image_create_token:
4929  * @assembly: a dynamic assembly
4930  * @obj:
4931  * @register_token: Whenever to register the token in the assembly->tokens hash. 
4932  *
4933  * Get a token to insert in the IL code stream for the given MemberInfo.
4934  * The metadata emission routines need to pass FALSE as REGISTER_TOKEN, since by that time, 
4935  * the table_idx-es were recomputed, so registering the token would overwrite an existing 
4936  * entry.
4937  */
4938 guint32
4939 mono_image_create_token (MonoDynamicImage *assembly, MonoObject *obj, 
4940                                                  gboolean create_open_instance, gboolean register_token)
4941 {
4942         MonoClass *klass;
4943         guint32 token = 0;
4944
4945         klass = obj->vtable->klass;
4946
4947         /* Check for user defined reflection objects */
4948         /* TypeDelegator is the only corlib type which doesn't look like a MonoReflectionType */
4949         if (klass->image != mono_defaults.corlib || (strcmp (klass->name, "TypeDelegator") == 0))
4950                 mono_raise_exception (mono_get_exception_not_supported ("User defined subclasses of System.Type are not yet supported")); \
4951
4952         if (strcmp (klass->name, "MethodBuilder") == 0) {
4953                 MonoReflectionMethodBuilder *mb = (MonoReflectionMethodBuilder *)obj;
4954                 MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder*)mb->type;
4955
4956                 if (tb->module->dynamic_image == assembly && !tb->generic_params && !mb->generic_params)
4957                         token = mb->table_idx | MONO_TOKEN_METHOD_DEF;
4958                 else
4959                         token = mono_image_get_methodbuilder_token (assembly, mb, create_open_instance);
4960                 /*g_print ("got token 0x%08x for %s\n", token, mono_string_to_utf8 (mb->name));*/
4961         } else if (strcmp (klass->name, "ConstructorBuilder") == 0) {
4962                 MonoReflectionCtorBuilder *mb = (MonoReflectionCtorBuilder *)obj;
4963                 MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder*)mb->type;
4964
4965                 if (tb->module->dynamic_image == assembly && !tb->generic_params)
4966                         token = mb->table_idx | MONO_TOKEN_METHOD_DEF;
4967                 else
4968                         token = mono_image_get_ctorbuilder_token (assembly, mb);
4969                 /*g_print ("got token 0x%08x for %s\n", token, mono_string_to_utf8 (mb->name));*/
4970         } else if (strcmp (klass->name, "FieldBuilder") == 0) {
4971                 MonoReflectionFieldBuilder *fb = (MonoReflectionFieldBuilder *)obj;
4972                 MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder *)fb->typeb;
4973                 if (tb->generic_params) {
4974                         token = mono_image_get_generic_field_token (assembly, fb);
4975                 } else {
4976                         if (tb->module->dynamic_image == assembly) {
4977                                 token = fb->table_idx | MONO_TOKEN_FIELD_DEF;
4978                         } else {
4979                                 token = mono_image_get_fieldref_token (assembly, (MonoObject*)fb, fb->handle);
4980                         }
4981                 }
4982         } else if (strcmp (klass->name, "TypeBuilder") == 0) {
4983                 MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder *)obj;
4984                 if (create_open_instance && tb->generic_params) {
4985                         MonoType *type;
4986                         init_type_builder_generics (obj);
4987                         type = mono_reflection_type_get_handle ((MonoReflectionType *)obj);
4988                         token = mono_image_typedef_or_ref_full (assembly, type, TRUE);
4989                         token = mono_metadata_token_from_dor (token);
4990                 } else if (tb->module->dynamic_image == assembly) {
4991                         token = tb->table_idx | MONO_TOKEN_TYPE_DEF;
4992                 } else {
4993                         MonoType *type;
4994                         type = mono_reflection_type_get_handle ((MonoReflectionType *)obj);
4995                         token = mono_metadata_token_from_dor (mono_image_typedef_or_ref (assembly, type));
4996                 }
4997         } else if (strcmp (klass->name, "MonoType") == 0) {
4998                 MonoType *type = mono_reflection_type_get_handle ((MonoReflectionType *)obj);
4999                 MonoClass *mc = mono_class_from_mono_type (type);
5000                 token = mono_metadata_token_from_dor (
5001                         mono_image_typedef_or_ref_full (assembly, type, mc->generic_container == NULL || create_open_instance));
5002         } else if (strcmp (klass->name, "GenericTypeParameterBuilder") == 0) {
5003                 MonoType *type = mono_reflection_type_get_handle ((MonoReflectionType *)obj);
5004                 token = mono_metadata_token_from_dor (
5005                         mono_image_typedef_or_ref (assembly, type));
5006         } else if (strcmp (klass->name, "MonoGenericClass") == 0) {
5007                 MonoType *type = mono_reflection_type_get_handle ((MonoReflectionType *)obj);
5008                 token = mono_metadata_token_from_dor (
5009                         mono_image_typedef_or_ref (assembly, type));
5010         } else if (strcmp (klass->name, "MonoCMethod") == 0 ||
5011                    strcmp (klass->name, "MonoMethod") == 0 ||
5012                    strcmp (klass->name, "MonoGenericMethod") == 0 ||
5013                    strcmp (klass->name, "MonoGenericCMethod") == 0) {
5014                 MonoReflectionMethod *m = (MonoReflectionMethod *)obj;
5015                 if (m->method->is_inflated) {
5016                         if (create_open_instance)
5017                                 token = mono_image_get_methodspec_token (assembly, m->method);
5018                         else
5019                                 token = mono_image_get_inflated_method_token (assembly, m->method);
5020                 } else if ((m->method->klass->image == &assembly->image) &&
5021                          !m->method->klass->generic_class) {
5022                         static guint32 method_table_idx = 0xffffff;
5023                         if (m->method->klass->wastypebuilder) {
5024                                 /* we use the same token as the one that was assigned
5025                                  * to the Methodbuilder.
5026                                  * FIXME: do the equivalent for Fields.
5027                                  */
5028                                 token = m->method->token;
5029                         } else {
5030                                 /*
5031                                  * Each token should have a unique index, but the indexes are
5032                                  * assigned by managed code, so we don't know about them. An
5033                                  * easy solution is to count backwards...
5034                                  */
5035                                 method_table_idx --;
5036                                 token = MONO_TOKEN_METHOD_DEF | method_table_idx;
5037                         }
5038                 } else {
5039                         token = mono_image_get_methodref_token (assembly, m->method, create_open_instance);
5040                 }
5041                 /*g_print ("got token 0x%08x for %s\n", token, m->method->name);*/
5042         } else if (strcmp (klass->name, "MonoField") == 0) {
5043                 MonoReflectionField *f = (MonoReflectionField *)obj;
5044                 if ((f->field->parent->image == &assembly->image) && !is_field_on_inst (f->field)) {
5045                         static guint32 field_table_idx = 0xffffff;
5046                         field_table_idx --;
5047                         token = MONO_TOKEN_FIELD_DEF | field_table_idx;
5048                 } else {
5049                         token = mono_image_get_fieldref_token (assembly, (MonoObject*)f, f->field);
5050                 }
5051                 /*g_print ("got token 0x%08x for %s\n", token, f->field->name);*/
5052         } else if (strcmp (klass->name, "MonoArrayMethod") == 0) {
5053                 MonoReflectionArrayMethod *m = (MonoReflectionArrayMethod *)obj;
5054                 token = mono_image_get_array_token (assembly, m);
5055         } else if (strcmp (klass->name, "SignatureHelper") == 0) {
5056                 MonoReflectionSigHelper *s = (MonoReflectionSigHelper*)obj;
5057                 token = MONO_TOKEN_SIGNATURE | mono_image_get_sighelper_token (assembly, s);
5058         } else if (strcmp (klass->name, "EnumBuilder") == 0) {
5059                 MonoType *type = mono_reflection_type_get_handle ((MonoReflectionType *)obj);
5060                 token = mono_metadata_token_from_dor (
5061                         mono_image_typedef_or_ref (assembly, type));
5062         } else if (strcmp (klass->name, "FieldOnTypeBuilderInst") == 0) {
5063                 MonoReflectionFieldOnTypeBuilderInst *f = (MonoReflectionFieldOnTypeBuilderInst*)obj;
5064                 token = mono_image_get_field_on_inst_token (assembly, f);
5065         } else if (strcmp (klass->name, "ConstructorOnTypeBuilderInst") == 0) {
5066                 MonoReflectionCtorOnTypeBuilderInst *c = (MonoReflectionCtorOnTypeBuilderInst*)obj;
5067                 token = mono_image_get_ctor_on_inst_token (assembly, c, create_open_instance);
5068         } else if (strcmp (klass->name, "MethodOnTypeBuilderInst") == 0) {
5069                 MonoReflectionMethodOnTypeBuilderInst *m = (MonoReflectionMethodOnTypeBuilderInst*)obj;
5070                 token = mono_image_get_method_on_inst_token (assembly, m, create_open_instance);
5071         } else if (is_sre_array (klass) || is_sre_byref (klass) || is_sre_pointer (klass)) {
5072                 MonoReflectionType *type = (MonoReflectionType *)obj;
5073                 token = mono_metadata_token_from_dor (
5074                                 mono_image_typedef_or_ref (assembly, mono_reflection_type_get_handle (type)));
5075         } else {
5076                 g_error ("requested token for %s\n", klass->name);
5077         }
5078
5079         if (register_token)
5080                 mono_image_register_token (assembly, token, obj);
5081
5082         return token;
5083 }
5084
5085 /*
5086  * mono_image_register_token:
5087  *
5088  *   Register the TOKEN->OBJ mapping in the mapping table in ASSEMBLY. This is required for
5089  * the Module.ResolveXXXToken () methods to work.
5090  */
5091 void
5092 mono_image_register_token (MonoDynamicImage *assembly, guint32 token, MonoObject *obj)
5093 {
5094         MonoObject *prev;
5095
5096         dynamic_image_lock (assembly);
5097         prev = mono_g_hash_table_lookup (assembly->tokens, GUINT_TO_POINTER (token));
5098         if (prev) {
5099                 /* There could be multiple MethodInfo objects with the same token */
5100                 //g_assert (prev == obj);
5101         } else {
5102                 mono_g_hash_table_insert (assembly->tokens, GUINT_TO_POINTER (token), obj);
5103         }
5104         dynamic_image_unlock (assembly);
5105 }
5106
5107 static MonoDynamicImage*
5108 create_dynamic_mono_image (MonoDynamicAssembly *assembly, char *assembly_name, char *module_name)
5109 {
5110         static const guchar entrycode [16] = {0xff, 0x25, 0};
5111         MonoDynamicImage *image;
5112         int i;
5113
5114         const char *version;
5115
5116         if (!strcmp (mono_get_runtime_info ()->framework_version, "2.1"))
5117                 version = "v2.0.50727"; /* HACK: SL 2 enforces the .net 2 metadata version */
5118         else
5119                 version = mono_get_runtime_info ()->runtime_version;
5120
5121 #if HAVE_BOEHM_GC
5122         /* The MonoGHashTable's need GC tracking */
5123         image = GC_MALLOC (sizeof (MonoDynamicImage));
5124 #else
5125         image = g_new0 (MonoDynamicImage, 1);
5126 #endif
5127
5128         mono_profiler_module_event (&image->image, MONO_PROFILE_START_LOAD);
5129         
5130         /*g_print ("created image %p\n", image);*/
5131         /* keep in sync with image.c */
5132         image->image.name = assembly_name;
5133         image->image.assembly_name = image->image.name; /* they may be different */
5134         image->image.module_name = module_name;
5135         image->image.version = g_strdup (version);
5136         image->image.md_version_major = 1;
5137         image->image.md_version_minor = 1;
5138         image->image.dynamic = TRUE;
5139
5140         image->image.references = g_new0 (MonoAssembly*, 1);
5141         image->image.references [0] = NULL;
5142
5143         mono_image_init (&image->image);
5144
5145         image->token_fixups = mono_g_hash_table_new_type ((GHashFunc)mono_object_hash, NULL, MONO_HASH_KEY_GC);
5146         image->method_to_table_idx = g_hash_table_new (NULL, NULL);
5147         image->field_to_table_idx = g_hash_table_new (NULL, NULL);
5148         image->method_aux_hash = g_hash_table_new (NULL, NULL);
5149         image->vararg_aux_hash = g_hash_table_new (NULL, NULL);
5150         image->handleref = g_hash_table_new (NULL, NULL);
5151         image->handleref_managed = mono_g_hash_table_new_type ((GHashFunc)mono_object_hash, NULL, MONO_HASH_KEY_GC);
5152         image->tokens = mono_g_hash_table_new_type (NULL, NULL, MONO_HASH_VALUE_GC);
5153         image->generic_def_objects = mono_g_hash_table_new_type (NULL, NULL, MONO_HASH_VALUE_GC);
5154         image->methodspec = mono_g_hash_table_new_type ((GHashFunc)mono_object_hash, NULL, MONO_HASH_KEY_GC);
5155         image->typespec = g_hash_table_new ((GHashFunc)mono_metadata_type_hash, (GCompareFunc)mono_metadata_type_equal);
5156         image->typeref = g_hash_table_new ((GHashFunc)mono_metadata_type_hash, (GCompareFunc)mono_metadata_type_equal);
5157         image->blob_cache = g_hash_table_new ((GHashFunc)mono_blob_entry_hash, (GCompareFunc)mono_blob_entry_equal);
5158         image->gen_params = g_ptr_array_new ();
5159         image->remapped_tokens = mono_g_hash_table_new_type (NULL, NULL, MONO_HASH_VALUE_GC);
5160
5161         /*g_print ("string heap create for image %p (%s)\n", image, module_name);*/
5162         string_heap_init (&image->sheap);
5163         mono_image_add_stream_data (&image->us, "", 1);
5164         add_to_blob_cached (image, (char*) "", 1, NULL, 0);
5165         /* import tables... */
5166         mono_image_add_stream_data (&image->code, (char*)entrycode, sizeof (entrycode));
5167         image->iat_offset = mono_image_add_stream_zero (&image->code, 8); /* two IAT entries */
5168         image->idt_offset = mono_image_add_stream_zero (&image->code, 2 * sizeof (MonoIDT)); /* two IDT entries */
5169         image->imp_names_offset = mono_image_add_stream_zero (&image->code, 2); /* flags for name entry */
5170         mono_image_add_stream_data (&image->code, "_CorExeMain", 12);
5171         mono_image_add_stream_data (&image->code, "mscoree.dll", 12);
5172         image->ilt_offset = mono_image_add_stream_zero (&image->code, 8); /* two ILT entries */
5173         stream_data_align (&image->code);
5174
5175         image->cli_header_offset = mono_image_add_stream_zero (&image->code, sizeof (MonoCLIHeader));
5176
5177         for (i=0; i < MONO_TABLE_NUM; ++i) {
5178                 image->tables [i].next_idx = 1;
5179                 image->tables [i].columns = table_sizes [i];
5180         }
5181
5182         image->image.assembly = (MonoAssembly*)assembly;
5183         image->run = assembly->run;
5184         image->save = assembly->save;
5185         image->pe_kind = 0x1; /* ILOnly */
5186         image->machine = 0x14c; /* I386 */
5187         
5188         mono_profiler_module_loaded (&image->image, MONO_PROFILE_OK);
5189
5190         return image;
5191 }
5192 #endif
5193
5194 static void
5195 free_blob_cache_entry (gpointer key, gpointer val, gpointer user_data)
5196 {
5197         g_free (key);
5198 }
5199
5200 static void
5201 release_hashtable (MonoGHashTable **hash)
5202 {
5203         if (*hash) {
5204                 mono_g_hash_table_destroy (*hash);
5205                 *hash = NULL;
5206         }
5207 }
5208
5209 void
5210 mono_dynamic_image_release_gc_roots (MonoDynamicImage *image)
5211 {
5212         release_hashtable (&image->token_fixups);
5213         release_hashtable (&image->handleref_managed);
5214         release_hashtable (&image->tokens);
5215         release_hashtable (&image->remapped_tokens);
5216         release_hashtable (&image->generic_def_objects);
5217         release_hashtable (&image->methodspec);
5218 }
5219
5220 void
5221 mono_dynamic_image_free (MonoDynamicImage *image)
5222 {
5223         MonoDynamicImage *di = image;
5224         GList *list;
5225         int i;
5226
5227         if (di->methodspec)
5228                 mono_g_hash_table_destroy (di->methodspec);
5229         if (di->typespec)
5230                 g_hash_table_destroy (di->typespec);
5231         if (di->typeref)
5232                 g_hash_table_destroy (di->typeref);
5233         if (di->handleref)
5234                 g_hash_table_destroy (di->handleref);
5235         if (di->handleref_managed)
5236                 mono_g_hash_table_destroy (di->handleref_managed);
5237         if (di->tokens)
5238                 mono_g_hash_table_destroy (di->tokens);
5239         if (di->remapped_tokens)
5240                 mono_g_hash_table_destroy (di->remapped_tokens);
5241         if (di->generic_def_objects)
5242                 mono_g_hash_table_destroy (di->generic_def_objects);
5243         if (di->blob_cache) {
5244                 g_hash_table_foreach (di->blob_cache, free_blob_cache_entry, NULL);
5245                 g_hash_table_destroy (di->blob_cache);
5246         }
5247         if (di->standalonesig_cache)
5248                 g_hash_table_destroy (di->standalonesig_cache);
5249         for (list = di->array_methods; list; list = list->next) {
5250                 ArrayMethod *am = (ArrayMethod *)list->data;
5251                 g_free (am->sig);
5252                 g_free (am->name);
5253                 g_free (am);
5254         }
5255         g_list_free (di->array_methods);
5256         if (di->gen_params) {
5257                 for (i = 0; i < di->gen_params->len; i++) {
5258                         GenericParamTableEntry *entry = g_ptr_array_index (di->gen_params, i);
5259                         mono_gc_deregister_root ((char*) &entry->gparam);
5260                         g_free (entry);
5261                 }
5262                 g_ptr_array_free (di->gen_params, TRUE);
5263         }
5264         if (di->token_fixups)
5265                 mono_g_hash_table_destroy (di->token_fixups);
5266         if (di->method_to_table_idx)
5267                 g_hash_table_destroy (di->method_to_table_idx);
5268         if (di->field_to_table_idx)
5269                 g_hash_table_destroy (di->field_to_table_idx);
5270         if (di->method_aux_hash)
5271                 g_hash_table_destroy (di->method_aux_hash);
5272         if (di->vararg_aux_hash)
5273                 g_hash_table_destroy (di->vararg_aux_hash);
5274         g_free (di->strong_name);
5275         g_free (di->win32_res);
5276         if (di->public_key)
5277                 g_free (di->public_key);
5278
5279         /*g_print ("string heap destroy for image %p\n", di);*/
5280         mono_dynamic_stream_reset (&di->sheap);
5281         mono_dynamic_stream_reset (&di->code);
5282         mono_dynamic_stream_reset (&di->resources);
5283         mono_dynamic_stream_reset (&di->us);
5284         mono_dynamic_stream_reset (&di->blob);
5285         mono_dynamic_stream_reset (&di->tstream);
5286         mono_dynamic_stream_reset (&di->guid);
5287         for (i = 0; i < MONO_TABLE_NUM; ++i) {
5288                 g_free (di->tables [i].values);
5289         }
5290 }       
5291
5292 void
5293 mono_dynamic_image_free_image (MonoDynamicImage *image)
5294 {
5295         /* See create_dynamic_mono_image () */
5296 #if HAVE_BOEHM_GC
5297         /* Allocated using GC_MALLOC */
5298 #else
5299         g_free (image);
5300 #endif
5301 }
5302
5303 #ifndef DISABLE_REFLECTION_EMIT
5304
5305 /*
5306  * mono_image_basic_init:
5307  * @assembly: an assembly builder object
5308  *
5309  * Create the MonoImage that represents the assembly builder and setup some
5310  * of the helper hash table and the basic metadata streams.
5311  */
5312 void
5313 mono_image_basic_init (MonoReflectionAssemblyBuilder *assemblyb)
5314 {
5315         MonoDynamicAssembly *assembly;
5316         MonoDynamicImage *image;
5317         MonoDomain *domain = mono_object_domain (assemblyb);
5318         
5319         if (assemblyb->dynamic_assembly)
5320                 return;
5321
5322 #if HAVE_BOEHM_GC
5323         /* assembly->assembly.image might be GC allocated */
5324         assembly = assemblyb->dynamic_assembly = GC_MALLOC (sizeof (MonoDynamicAssembly));
5325 #else
5326         assembly = assemblyb->dynamic_assembly = g_new0 (MonoDynamicAssembly, 1);
5327 #endif
5328
5329         mono_profiler_assembly_event (&assembly->assembly, MONO_PROFILE_START_LOAD);
5330         
5331         assembly->assembly.ref_count = 1;
5332         assembly->assembly.dynamic = TRUE;
5333         assembly->assembly.corlib_internal = assemblyb->corlib_internal;
5334         assemblyb->assembly.assembly = (MonoAssembly*)assembly;
5335         assembly->assembly.basedir = mono_string_to_utf8 (assemblyb->dir);
5336         if (assemblyb->culture)
5337                 assembly->assembly.aname.culture = mono_string_to_utf8 (assemblyb->culture);
5338         else
5339                 assembly->assembly.aname.culture = g_strdup ("");
5340
5341         if (assemblyb->version) {
5342                         char *vstr = mono_string_to_utf8 (assemblyb->version);
5343                         char **version = g_strsplit (vstr, ".", 4);
5344                         char **parts = version;
5345                         assembly->assembly.aname.major = atoi (*parts++);
5346                         assembly->assembly.aname.minor = atoi (*parts++);
5347                         assembly->assembly.aname.build = *parts != NULL ? atoi (*parts++) : 0;
5348                         assembly->assembly.aname.revision = *parts != NULL ? atoi (*parts) : 0;
5349
5350                         g_strfreev (version);
5351                         g_free (vstr);
5352         } else {
5353                         assembly->assembly.aname.major = 0;
5354                         assembly->assembly.aname.minor = 0;
5355                         assembly->assembly.aname.build = 0;
5356                         assembly->assembly.aname.revision = 0;
5357         }
5358
5359         assembly->run = assemblyb->access != 2;
5360         assembly->save = assemblyb->access != 1;
5361         assembly->domain = domain;
5362
5363         image = create_dynamic_mono_image (assembly, mono_string_to_utf8 (assemblyb->name), g_strdup ("RefEmit_YouForgotToDefineAModule"));
5364         image->initial_image = TRUE;
5365         assembly->assembly.aname.name = image->image.name;
5366         assembly->assembly.image = &image->image;
5367         if (assemblyb->pktoken && assemblyb->pktoken->max_length) {
5368                 /* -1 to correct for the trailing NULL byte */
5369                 if (assemblyb->pktoken->max_length != MONO_PUBLIC_KEY_TOKEN_LENGTH - 1) {
5370                         g_error ("Public key token length invalid for assembly %s: %i", assembly->assembly.aname.name, assemblyb->pktoken->max_length);
5371                 }
5372                 memcpy (&assembly->assembly.aname.public_key_token, mono_array_addr (assemblyb->pktoken, guint8, 0), assemblyb->pktoken->max_length);           
5373         }
5374
5375         mono_domain_assemblies_lock (domain);
5376         domain->domain_assemblies = g_slist_append (domain->domain_assemblies, assembly);
5377         mono_domain_assemblies_unlock (domain);
5378
5379         register_assembly (mono_object_domain (assemblyb), &assemblyb->assembly, &assembly->assembly);
5380         
5381         mono_profiler_assembly_loaded (&assembly->assembly, MONO_PROFILE_OK);
5382         
5383         mono_assembly_invoke_load_hook ((MonoAssembly*)assembly);
5384 }
5385
5386 #endif /* !DISABLE_REFLECTION_EMIT */
5387
5388 #ifndef DISABLE_REFLECTION_EMIT_SAVE
5389
5390 static int
5391 calc_section_size (MonoDynamicImage *assembly)
5392 {
5393         int nsections = 0;
5394
5395         /* alignment constraints */
5396         mono_image_add_stream_zero (&assembly->code, 4 - (assembly->code.index % 4));
5397         g_assert ((assembly->code.index % 4) == 0);
5398         assembly->meta_size += 3;
5399         assembly->meta_size &= ~3;
5400         mono_image_add_stream_zero (&assembly->resources, 4 - (assembly->resources.index % 4));
5401         g_assert ((assembly->resources.index % 4) == 0);
5402
5403         assembly->sections [MONO_SECTION_TEXT].size = assembly->meta_size + assembly->code.index + assembly->resources.index + assembly->strong_name_size;
5404         assembly->sections [MONO_SECTION_TEXT].attrs = SECT_FLAGS_HAS_CODE | SECT_FLAGS_MEM_EXECUTE | SECT_FLAGS_MEM_READ;
5405         nsections++;
5406
5407         if (assembly->win32_res) {
5408                 guint32 res_size = (assembly->win32_res_size + 3) & ~3;
5409
5410                 assembly->sections [MONO_SECTION_RSRC].size = res_size;
5411                 assembly->sections [MONO_SECTION_RSRC].attrs = SECT_FLAGS_HAS_INITIALIZED_DATA | SECT_FLAGS_MEM_READ;
5412                 nsections++;
5413         }
5414
5415         assembly->sections [MONO_SECTION_RELOC].size = 12;
5416         assembly->sections [MONO_SECTION_RELOC].attrs = SECT_FLAGS_MEM_READ | SECT_FLAGS_MEM_DISCARDABLE | SECT_FLAGS_HAS_INITIALIZED_DATA;
5417         nsections++;
5418
5419         return nsections;
5420 }
5421
5422 typedef struct {
5423         guint32 id;
5424         guint32 offset;
5425         GSList *children;
5426         MonoReflectionWin32Resource *win32_res; /* Only for leaf nodes */
5427 } ResTreeNode;
5428
5429 static int
5430 resource_tree_compare_by_id (gconstpointer a, gconstpointer b)
5431 {
5432         ResTreeNode *t1 = (ResTreeNode*)a;
5433         ResTreeNode *t2 = (ResTreeNode*)b;
5434
5435         return t1->id - t2->id;
5436 }
5437
5438 /*
5439  * resource_tree_create:
5440  *
5441  *  Organize the resources into a resource tree.
5442  */
5443 static ResTreeNode *
5444 resource_tree_create (MonoArray *win32_resources)
5445 {
5446         ResTreeNode *tree, *res_node, *type_node, *lang_node;
5447         GSList *l;
5448         int i;
5449
5450         tree = g_new0 (ResTreeNode, 1);
5451         
5452         for (i = 0; i < mono_array_length (win32_resources); ++i) {
5453                 MonoReflectionWin32Resource *win32_res =
5454                         (MonoReflectionWin32Resource*)mono_array_addr (win32_resources, MonoReflectionWin32Resource, i);
5455
5456                 /* Create node */
5457
5458                 /* FIXME: BUG: this stores managed references in unmanaged memory */
5459                 lang_node = g_new0 (ResTreeNode, 1);
5460                 lang_node->id = win32_res->lang_id;
5461                 lang_node->win32_res = win32_res;
5462
5463                 /* Create type node if neccesary */
5464                 type_node = NULL;
5465                 for (l = tree->children; l; l = l->next)
5466                         if (((ResTreeNode*)(l->data))->id == win32_res->res_type) {
5467                                 type_node = (ResTreeNode*)l->data;
5468                                 break;
5469                         }
5470
5471                 if (!type_node) {
5472                         type_node = g_new0 (ResTreeNode, 1);
5473                         type_node->id = win32_res->res_type;
5474
5475                         /* 
5476                          * The resource types have to be sorted otherwise
5477                          * Windows Explorer can't display the version information.
5478                          */
5479                         tree->children = g_slist_insert_sorted (tree->children, 
5480                                 type_node, resource_tree_compare_by_id);
5481                 }
5482
5483                 /* Create res node if neccesary */
5484                 res_node = NULL;
5485                 for (l = type_node->children; l; l = l->next)
5486                         if (((ResTreeNode*)(l->data))->id == win32_res->res_id) {
5487                                 res_node = (ResTreeNode*)l->data;
5488                                 break;
5489                         }
5490
5491                 if (!res_node) {
5492                         res_node = g_new0 (ResTreeNode, 1);
5493                         res_node->id = win32_res->res_id;
5494                         type_node->children = g_slist_append (type_node->children, res_node);
5495                 }
5496
5497                 res_node->children = g_slist_append (res_node->children, lang_node);
5498         }
5499
5500         return tree;
5501 }
5502
5503 /*
5504  * resource_tree_encode:
5505  * 
5506  *   Encode the resource tree into the format used in the PE file.
5507  */
5508 static void
5509 resource_tree_encode (ResTreeNode *node, char *begin, char *p, char **endbuf)
5510 {
5511         char *entries;
5512         MonoPEResourceDir dir;
5513         MonoPEResourceDirEntry dir_entry;
5514         MonoPEResourceDataEntry data_entry;
5515         GSList *l;
5516         guint32 res_id_entries;
5517
5518         /*
5519          * For the format of the resource directory, see the article
5520          * "An In-Depth Look into the Win32 Portable Executable File Format" by
5521          * Matt Pietrek
5522          */
5523
5524         memset (&dir, 0, sizeof (dir));
5525         memset (&dir_entry, 0, sizeof (dir_entry));
5526         memset (&data_entry, 0, sizeof (data_entry));
5527
5528         g_assert (sizeof (dir) == 16);
5529         g_assert (sizeof (dir_entry) == 8);
5530         g_assert (sizeof (data_entry) == 16);
5531
5532         node->offset = p - begin;
5533
5534         /* IMAGE_RESOURCE_DIRECTORY */
5535         res_id_entries = g_slist_length (node->children);
5536         dir.res_id_entries = GUINT16_TO_LE (res_id_entries);
5537
5538         memcpy (p, &dir, sizeof (dir));
5539         p += sizeof (dir);
5540
5541         /* Reserve space for entries */
5542         entries = p;
5543         p += sizeof (dir_entry) * res_id_entries;
5544
5545         /* Write children */
5546         for (l = node->children; l; l = l->next) {
5547                 ResTreeNode *child = (ResTreeNode*)l->data;
5548
5549                 if (child->win32_res) {
5550                         guint32 size;
5551
5552                         child->offset = p - begin;
5553
5554                         /* IMAGE_RESOURCE_DATA_ENTRY */
5555                         data_entry.rde_data_offset = GUINT32_TO_LE (p - begin + sizeof (data_entry));
5556                         size = mono_array_length (child->win32_res->res_data);
5557                         data_entry.rde_size = GUINT32_TO_LE (size);
5558
5559                         memcpy (p, &data_entry, sizeof (data_entry));
5560                         p += sizeof (data_entry);
5561
5562                         memcpy (p, mono_array_addr (child->win32_res->res_data, char, 0), size);
5563                         p += size;
5564                 } else {
5565                         resource_tree_encode (child, begin, p, &p);
5566                 }
5567         }
5568
5569         /* IMAGE_RESOURCE_ENTRY */
5570         for (l = node->children; l; l = l->next) {
5571                 ResTreeNode *child = (ResTreeNode*)l->data;
5572
5573                 MONO_PE_RES_DIR_ENTRY_SET_NAME (dir_entry, FALSE, child->id);
5574                 MONO_PE_RES_DIR_ENTRY_SET_DIR (dir_entry, !child->win32_res, child->offset);
5575
5576                 memcpy (entries, &dir_entry, sizeof (dir_entry));
5577                 entries += sizeof (dir_entry);
5578         }
5579
5580         *endbuf = p;
5581 }
5582
5583 static void
5584 resource_tree_free (ResTreeNode * node)
5585 {
5586         GSList * list;
5587         for (list = node->children; list; list = list->next)
5588                 resource_tree_free ((ResTreeNode*)list->data);
5589         g_slist_free(node->children);
5590         g_free (node);
5591 }
5592
5593 static void
5594 assembly_add_win32_resources (MonoDynamicImage *assembly, MonoReflectionAssemblyBuilder *assemblyb)
5595 {
5596         char *buf;
5597         char *p;
5598         guint32 size, i;
5599         MonoReflectionWin32Resource *win32_res;
5600         ResTreeNode *tree;
5601
5602         if (!assemblyb->win32_resources)
5603                 return;
5604
5605         /*
5606          * Resources are stored in a three level tree inside the PE file.
5607          * - level one contains a node for each type of resource
5608          * - level two contains a node for each resource
5609          * - level three contains a node for each instance of a resource for a
5610          *   specific language.
5611          */
5612
5613         tree = resource_tree_create (assemblyb->win32_resources);
5614
5615         /* Estimate the size of the encoded tree */
5616         size = 0;
5617         for (i = 0; i < mono_array_length (assemblyb->win32_resources); ++i) {
5618                 win32_res = (MonoReflectionWin32Resource*)mono_array_addr (assemblyb->win32_resources, MonoReflectionWin32Resource, i);
5619                 size += mono_array_length (win32_res->res_data);
5620         }
5621         /* Directory structure */
5622         size += mono_array_length (assemblyb->win32_resources) * 256;
5623         p = buf = g_malloc (size);
5624
5625         resource_tree_encode (tree, p, p, &p);
5626
5627         g_assert (p - buf <= size);
5628
5629         assembly->win32_res = g_malloc (p - buf);
5630         assembly->win32_res_size = p - buf;
5631         memcpy (assembly->win32_res, buf, p - buf);
5632
5633         g_free (buf);
5634         resource_tree_free (tree);
5635 }
5636
5637 static void
5638 fixup_resource_directory (char *res_section, char *p, guint32 rva)
5639 {
5640         MonoPEResourceDir *dir = (MonoPEResourceDir*)p;
5641         int i;
5642
5643         p += sizeof (MonoPEResourceDir);
5644         for (i = 0; i < GUINT16_FROM_LE (dir->res_named_entries) + GUINT16_FROM_LE (dir->res_id_entries); ++i) {
5645                 MonoPEResourceDirEntry *dir_entry = (MonoPEResourceDirEntry*)p;
5646                 char *child = res_section + MONO_PE_RES_DIR_ENTRY_DIR_OFFSET (*dir_entry);
5647                 if (MONO_PE_RES_DIR_ENTRY_IS_DIR (*dir_entry)) {
5648                         fixup_resource_directory (res_section, child, rva);
5649                 } else {
5650                         MonoPEResourceDataEntry *data_entry = (MonoPEResourceDataEntry*)child;
5651                         data_entry->rde_data_offset = GUINT32_TO_LE (GUINT32_FROM_LE (data_entry->rde_data_offset) + rva);
5652                 }
5653
5654                 p += sizeof (MonoPEResourceDirEntry);
5655         }
5656 }
5657
5658 static void
5659 checked_write_file (HANDLE f, gconstpointer buffer, guint32 numbytes)
5660 {
5661         guint32 dummy;
5662         if (!WriteFile (f, buffer, numbytes, &dummy, NULL))
5663                 g_error ("WriteFile returned %d\n", GetLastError ());
5664 }
5665
5666 /*
5667  * mono_image_create_pefile:
5668  * @mb: a module builder object
5669  * 
5670  * This function creates the PE-COFF header, the image sections, the CLI header  * etc. all the data is written in
5671  * assembly->pefile where it can be easily retrieved later in chunks.
5672  */
5673 void
5674 mono_image_create_pefile (MonoReflectionModuleBuilder *mb, HANDLE file)
5675 {
5676         MonoMSDOSHeader *msdos;
5677         MonoDotNetHeader *header;
5678         MonoSectionTable *section;
5679         MonoCLIHeader *cli_header;
5680         guint32 size, image_size, virtual_base, text_offset;
5681         guint32 header_start, section_start, file_offset, virtual_offset;
5682         MonoDynamicImage *assembly;
5683         MonoReflectionAssemblyBuilder *assemblyb;
5684         MonoDynamicStream pefile_stream = {0};
5685         MonoDynamicStream *pefile = &pefile_stream;
5686         int i, nsections;
5687         guint32 *rva, value;
5688         guchar *p;
5689         static const unsigned char msheader[] = {
5690                 0x4d, 0x5a, 0x90, 0x00, 0x03, 0x00, 0x00, 0x00,  0x04, 0x00, 0x00, 0x00, 0xff, 0xff, 0x00, 0x00,
5691                 0xb8, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,  0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
5692                 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
5693                 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,  0x00, 0x00, 0x00, 0x00, 0x80, 0x00, 0x00, 0x00,
5694                 0x0e, 0x1f, 0xba, 0x0e, 0x00, 0xb4, 0x09, 0xcd,  0x21, 0xb8, 0x01, 0x4c, 0xcd, 0x21, 0x54, 0x68,
5695                 0x69, 0x73, 0x20, 0x70, 0x72, 0x6f, 0x67, 0x72,  0x61, 0x6d, 0x20, 0x63, 0x61, 0x6e, 0x6e, 0x6f,
5696                 0x74, 0x20, 0x62, 0x65, 0x20, 0x72, 0x75, 0x6e,  0x20, 0x69, 0x6e, 0x20, 0x44, 0x4f, 0x53, 0x20,
5697                 0x6d, 0x6f, 0x64, 0x65, 0x2e, 0x0d, 0x0d, 0x0a,  0x24, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
5698         };
5699
5700         assemblyb = mb->assemblyb;
5701
5702         mono_image_basic_init (assemblyb);
5703         assembly = mb->dynamic_image;
5704
5705         assembly->pe_kind = assemblyb->pe_kind;
5706         assembly->machine = assemblyb->machine;
5707         ((MonoDynamicImage*)assemblyb->dynamic_assembly->assembly.image)->pe_kind = assemblyb->pe_kind;
5708         ((MonoDynamicImage*)assemblyb->dynamic_assembly->assembly.image)->machine = assemblyb->machine;
5709         
5710         mono_image_build_metadata (mb);
5711
5712         if (mb->is_main && assemblyb->resources) {
5713                 int len = mono_array_length (assemblyb->resources);
5714                 for (i = 0; i < len; ++i)
5715                         assembly_add_resource (mb, assembly, (MonoReflectionResource*)mono_array_addr (assemblyb->resources, MonoReflectionResource, i));
5716         }
5717
5718         if (mb->resources) {
5719                 int len = mono_array_length (mb->resources);
5720                 for (i = 0; i < len; ++i)
5721                         assembly_add_resource (mb, assembly, (MonoReflectionResource*)mono_array_addr (mb->resources, MonoReflectionResource, i));
5722         }
5723
5724         build_compressed_metadata (assembly);
5725
5726         if (mb->is_main)
5727                 assembly_add_win32_resources (assembly, assemblyb);
5728
5729         nsections = calc_section_size (assembly);
5730         
5731         /* The DOS header and stub */
5732         g_assert (sizeof (MonoMSDOSHeader) == sizeof (msheader));
5733         mono_image_add_stream_data (pefile, (char*)msheader, sizeof (msheader));
5734
5735         /* the dotnet header */
5736         header_start = mono_image_add_stream_zero (pefile, sizeof (MonoDotNetHeader));
5737
5738         /* the section tables */
5739         section_start = mono_image_add_stream_zero (pefile, sizeof (MonoSectionTable) * nsections);
5740
5741         file_offset = section_start + sizeof (MonoSectionTable) * nsections;
5742         virtual_offset = VIRT_ALIGN;
5743         image_size = 0;
5744
5745         for (i = 0; i < MONO_SECTION_MAX; ++i) {
5746                 if (!assembly->sections [i].size)
5747                         continue;
5748                 /* align offsets */
5749                 file_offset += FILE_ALIGN - 1;
5750                 file_offset &= ~(FILE_ALIGN - 1);
5751                 virtual_offset += VIRT_ALIGN - 1;
5752                 virtual_offset &= ~(VIRT_ALIGN - 1);
5753
5754                 assembly->sections [i].offset = file_offset;
5755                 assembly->sections [i].rva = virtual_offset;
5756
5757                 file_offset += assembly->sections [i].size;
5758                 virtual_offset += assembly->sections [i].size;
5759                 image_size += (assembly->sections [i].size + VIRT_ALIGN - 1) & ~(VIRT_ALIGN - 1);
5760         }
5761
5762         file_offset += FILE_ALIGN - 1;
5763         file_offset &= ~(FILE_ALIGN - 1);
5764
5765         image_size += section_start + sizeof (MonoSectionTable) * nsections;
5766
5767         /* back-patch info */
5768         msdos = (MonoMSDOSHeader*)pefile->data;
5769         msdos->pe_offset = GUINT32_FROM_LE (sizeof (MonoMSDOSHeader));
5770
5771         header = (MonoDotNetHeader*)(pefile->data + header_start);
5772         header->pesig [0] = 'P';
5773         header->pesig [1] = 'E';
5774         
5775         header->coff.coff_machine = GUINT16_FROM_LE (assemblyb->machine);
5776         header->coff.coff_sections = GUINT16_FROM_LE (nsections);
5777         header->coff.coff_time = GUINT32_FROM_LE (time (NULL));
5778         header->coff.coff_opt_header_size = GUINT16_FROM_LE (sizeof (MonoDotNetHeader) - sizeof (MonoCOFFHeader) - 4);
5779         if (assemblyb->pekind == 1) {
5780                 /* it's a dll */
5781                 header->coff.coff_attributes = GUINT16_FROM_LE (0x210e);
5782         } else {
5783                 /* it's an exe */
5784                 header->coff.coff_attributes = GUINT16_FROM_LE (0x010e);
5785         }
5786
5787         virtual_base = 0x400000; /* FIXME: 0x10000000 if a DLL */
5788
5789         header->pe.pe_magic = GUINT16_FROM_LE (0x10B);
5790         header->pe.pe_major = 6;
5791         header->pe.pe_minor = 0;
5792         size = assembly->sections [MONO_SECTION_TEXT].size;
5793         size += FILE_ALIGN - 1;
5794         size &= ~(FILE_ALIGN - 1);
5795         header->pe.pe_code_size = GUINT32_FROM_LE(size);
5796         size = assembly->sections [MONO_SECTION_RSRC].size;
5797         size += FILE_ALIGN - 1;
5798         size &= ~(FILE_ALIGN - 1);
5799         header->pe.pe_data_size = GUINT32_FROM_LE(size);
5800         g_assert (START_TEXT_RVA == assembly->sections [MONO_SECTION_TEXT].rva);
5801         header->pe.pe_rva_code_base = GUINT32_FROM_LE (assembly->sections [MONO_SECTION_TEXT].rva);
5802         header->pe.pe_rva_data_base = GUINT32_FROM_LE (assembly->sections [MONO_SECTION_RSRC].rva);
5803         /* pe_rva_entry_point always at the beginning of the text section */
5804         header->pe.pe_rva_entry_point = GUINT32_FROM_LE (assembly->sections [MONO_SECTION_TEXT].rva);
5805
5806         header->nt.pe_image_base = GUINT32_FROM_LE (virtual_base);
5807         header->nt.pe_section_align = GUINT32_FROM_LE (VIRT_ALIGN);
5808         header->nt.pe_file_alignment = GUINT32_FROM_LE (FILE_ALIGN);
5809         header->nt.pe_os_major = GUINT16_FROM_LE (4);
5810         header->nt.pe_os_minor = GUINT16_FROM_LE (0);
5811         header->nt.pe_subsys_major = GUINT16_FROM_LE (4);
5812         size = section_start;
5813         size += FILE_ALIGN - 1;
5814         size &= ~(FILE_ALIGN - 1);
5815         header->nt.pe_header_size = GUINT32_FROM_LE (size);
5816         size = image_size;
5817         size += VIRT_ALIGN - 1;
5818         size &= ~(VIRT_ALIGN - 1);
5819         header->nt.pe_image_size = GUINT32_FROM_LE (size);
5820
5821         /*
5822         // Translate the PEFileKind value to the value expected by the Windows loader
5823         */
5824         {
5825                 short kind;
5826
5827                 /*
5828                 // PEFileKinds.Dll == 1
5829                 // PEFileKinds.ConsoleApplication == 2
5830                 // PEFileKinds.WindowApplication == 3
5831                 //
5832                 // need to get:
5833                 //     IMAGE_SUBSYSTEM_WINDOWS_GUI 2 // Image runs in the Windows GUI subsystem.
5834                 //     IMAGE_SUBSYSTEM_WINDOWS_CUI 3 // Image runs in the Windows character subsystem.
5835                 */
5836                 if (assemblyb->pekind == 3)
5837                         kind = 2;
5838                 else
5839                         kind = 3;
5840                 
5841                 header->nt.pe_subsys_required = GUINT16_FROM_LE (kind);
5842         }    
5843         header->nt.pe_stack_reserve = GUINT32_FROM_LE (0x00100000);
5844         header->nt.pe_stack_commit = GUINT32_FROM_LE (0x00001000);
5845         header->nt.pe_heap_reserve = GUINT32_FROM_LE (0x00100000);
5846         header->nt.pe_heap_commit = GUINT32_FROM_LE (0x00001000);
5847         header->nt.pe_loader_flags = GUINT32_FROM_LE (0);
5848         header->nt.pe_data_dir_count = GUINT32_FROM_LE (16);
5849
5850         /* fill data directory entries */
5851
5852         header->datadir.pe_resource_table.size = GUINT32_FROM_LE (assembly->sections [MONO_SECTION_RSRC].size);
5853         header->datadir.pe_resource_table.rva = GUINT32_FROM_LE (assembly->sections [MONO_SECTION_RSRC].rva);
5854
5855         header->datadir.pe_reloc_table.size = GUINT32_FROM_LE (assembly->sections [MONO_SECTION_RELOC].size);
5856         header->datadir.pe_reloc_table.rva = GUINT32_FROM_LE (assembly->sections [MONO_SECTION_RELOC].rva);
5857
5858         header->datadir.pe_cli_header.size = GUINT32_FROM_LE (72);
5859         header->datadir.pe_cli_header.rva = GUINT32_FROM_LE (assembly->text_rva + assembly->cli_header_offset);
5860         header->datadir.pe_iat.size = GUINT32_FROM_LE (8);
5861         header->datadir.pe_iat.rva = GUINT32_FROM_LE (assembly->text_rva + assembly->iat_offset);
5862         /* patch entrypoint name */
5863         if (assemblyb->pekind == 1)
5864                 memcpy (assembly->code.data + assembly->imp_names_offset + 2, "_CorDllMain", 12);
5865         else
5866                 memcpy (assembly->code.data + assembly->imp_names_offset + 2, "_CorExeMain", 12);
5867         /* patch imported function RVA name */
5868         rva = (guint32*)(assembly->code.data + assembly->iat_offset);
5869         *rva = GUINT32_FROM_LE (assembly->text_rva + assembly->imp_names_offset);
5870
5871         /* the import table */
5872         header->datadir.pe_import_table.size = GUINT32_FROM_LE (79); /* FIXME: magic number? */
5873         header->datadir.pe_import_table.rva = GUINT32_FROM_LE (assembly->text_rva + assembly->idt_offset);
5874         /* patch imported dll RVA name and other entries in the dir */
5875         rva = (guint32*)(assembly->code.data + assembly->idt_offset + G_STRUCT_OFFSET (MonoIDT, name_rva));
5876         *rva = GUINT32_FROM_LE (assembly->text_rva + assembly->imp_names_offset + 14); /* 14 is hint+strlen+1 of func name */
5877         rva = (guint32*)(assembly->code.data + assembly->idt_offset + G_STRUCT_OFFSET (MonoIDT, import_address_table_rva));
5878         *rva = GUINT32_FROM_LE (assembly->text_rva + assembly->iat_offset);
5879         rva = (guint32*)(assembly->code.data + assembly->idt_offset + G_STRUCT_OFFSET (MonoIDT, import_lookup_table));
5880         *rva = GUINT32_FROM_LE (assembly->text_rva + assembly->ilt_offset);
5881
5882         p = (guchar*)(assembly->code.data + assembly->ilt_offset);
5883         value = (assembly->text_rva + assembly->imp_names_offset);
5884         *p++ = (value) & 0xff;
5885         *p++ = (value >> 8) & (0xff);
5886         *p++ = (value >> 16) & (0xff);
5887         *p++ = (value >> 24) & (0xff);
5888
5889         /* the CLI header info */
5890         cli_header = (MonoCLIHeader*)(assembly->code.data + assembly->cli_header_offset);
5891         cli_header->ch_size = GUINT32_FROM_LE (72);
5892         cli_header->ch_runtime_major = GUINT16_FROM_LE (2);
5893         cli_header->ch_runtime_minor = GUINT16_FROM_LE (5);
5894         cli_header->ch_flags = GUINT32_FROM_LE (assemblyb->pe_kind);
5895         if (assemblyb->entry_point) {
5896                 guint32 table_idx = 0;
5897                 if (!strcmp (assemblyb->entry_point->object.vtable->klass->name, "MethodBuilder")) {
5898                         MonoReflectionMethodBuilder *methodb = (MonoReflectionMethodBuilder*)assemblyb->entry_point;
5899                         table_idx = methodb->table_idx;
5900                 } else {
5901                         table_idx = GPOINTER_TO_UINT (g_hash_table_lookup (assembly->method_to_table_idx, assemblyb->entry_point->method));
5902                 }
5903                 cli_header->ch_entry_point = GUINT32_FROM_LE (table_idx | MONO_TOKEN_METHOD_DEF);
5904         } else {
5905                 cli_header->ch_entry_point = GUINT32_FROM_LE (0);
5906         }
5907         /* The embedded managed resources */
5908         text_offset = assembly->text_rva + assembly->code.index;
5909         cli_header->ch_resources.rva = GUINT32_FROM_LE (text_offset);
5910         cli_header->ch_resources.size = GUINT32_FROM_LE (assembly->resources.index);
5911         text_offset += assembly->resources.index;
5912         cli_header->ch_metadata.rva = GUINT32_FROM_LE (text_offset);
5913         cli_header->ch_metadata.size = GUINT32_FROM_LE (assembly->meta_size);
5914         text_offset += assembly->meta_size;
5915         if (assembly->strong_name_size) {
5916                 cli_header->ch_strong_name.rva = GUINT32_FROM_LE (text_offset);
5917                 cli_header->ch_strong_name.size = GUINT32_FROM_LE (assembly->strong_name_size);
5918                 text_offset += assembly->strong_name_size;
5919         }
5920
5921         /* write the section tables and section content */
5922         section = (MonoSectionTable*)(pefile->data + section_start);
5923         for (i = 0; i < MONO_SECTION_MAX; ++i) {
5924                 static const char section_names [][7] = {
5925                         ".text", ".rsrc", ".reloc"
5926                 };
5927                 if (!assembly->sections [i].size)
5928                         continue;
5929                 strcpy (section->st_name, section_names [i]);
5930                 /*g_print ("output section %s (%d), size: %d\n", section->st_name, i, assembly->sections [i].size);*/
5931                 section->st_virtual_address = GUINT32_FROM_LE (assembly->sections [i].rva);
5932                 section->st_virtual_size = GUINT32_FROM_LE (assembly->sections [i].size);
5933                 section->st_raw_data_size = GUINT32_FROM_LE (GUINT32_TO_LE (section->st_virtual_size) + (FILE_ALIGN - 1));
5934                 section->st_raw_data_size &= GUINT32_FROM_LE (~(FILE_ALIGN - 1));
5935                 section->st_raw_data_ptr = GUINT32_FROM_LE (assembly->sections [i].offset);
5936                 section->st_flags = GUINT32_FROM_LE (assembly->sections [i].attrs);
5937                 section ++;
5938         }
5939         
5940         checked_write_file (file, pefile->data, pefile->index);
5941         
5942         mono_dynamic_stream_reset (pefile);
5943         
5944         for (i = 0; i < MONO_SECTION_MAX; ++i) {
5945                 if (!assembly->sections [i].size)
5946                         continue;
5947                 
5948                 if (SetFilePointer (file, assembly->sections [i].offset, NULL, FILE_BEGIN) == INVALID_SET_FILE_POINTER)
5949                         g_error ("SetFilePointer returned %d\n", GetLastError ());
5950                 
5951                 switch (i) {
5952                 case MONO_SECTION_TEXT:
5953                         /* patch entry point */
5954                         p = (guchar*)(assembly->code.data + 2);
5955                         value = (virtual_base + assembly->text_rva + assembly->iat_offset);
5956                         *p++ = (value) & 0xff;
5957                         *p++ = (value >> 8) & 0xff;
5958                         *p++ = (value >> 16) & 0xff;
5959                         *p++ = (value >> 24) & 0xff;
5960                 
5961                         checked_write_file (file, assembly->code.data, assembly->code.index);
5962                         checked_write_file (file, assembly->resources.data, assembly->resources.index);
5963                         checked_write_file (file, assembly->image.raw_metadata, assembly->meta_size);
5964                         checked_write_file (file, assembly->strong_name, assembly->strong_name_size);
5965                                 
5966
5967                         g_free (assembly->image.raw_metadata);
5968                         break;
5969                 case MONO_SECTION_RELOC: {
5970                         struct {
5971                                 guint32 page_rva;
5972                                 guint32 block_size;
5973                                 guint16 type_and_offset;
5974                                 guint16 term;
5975                         } reloc;
5976                         
5977                         g_assert (sizeof (reloc) == 12);
5978                         
5979                         reloc.page_rva = GUINT32_FROM_LE (assembly->text_rva);
5980                         reloc.block_size = GUINT32_FROM_LE (12);
5981                         
5982                         /* 
5983                          * the entrypoint is always at the start of the text section 
5984                          * 3 is IMAGE_REL_BASED_HIGHLOW
5985                          * 2 is patch_size_rva - text_rva
5986                          */
5987                         reloc.type_and_offset = GUINT16_FROM_LE ((3 << 12) + (2));
5988                         reloc.term = 0;
5989                         
5990                         checked_write_file (file, &reloc, sizeof (reloc));
5991                         
5992                         break;
5993                 }
5994                 case MONO_SECTION_RSRC:
5995                         if (assembly->win32_res) {
5996
5997                                 /* Fixup the offsets in the IMAGE_RESOURCE_DATA_ENTRY structures */
5998                                 fixup_resource_directory (assembly->win32_res, assembly->win32_res, assembly->sections [i].rva);
5999                                 checked_write_file (file, assembly->win32_res, assembly->win32_res_size);
6000                         }
6001                         break;
6002                 default:
6003                         g_assert_not_reached ();
6004                 }
6005         }
6006         
6007         /* check that the file is properly padded */
6008         if (SetFilePointer (file, file_offset, NULL, FILE_BEGIN) == INVALID_SET_FILE_POINTER)
6009                 g_error ("SetFilePointer returned %d\n", GetLastError ());
6010         if (! SetEndOfFile (file))
6011                 g_error ("SetEndOfFile returned %d\n", GetLastError ());
6012         
6013         mono_dynamic_stream_reset (&assembly->code);
6014         mono_dynamic_stream_reset (&assembly->us);
6015         mono_dynamic_stream_reset (&assembly->blob);
6016         mono_dynamic_stream_reset (&assembly->guid);
6017         mono_dynamic_stream_reset (&assembly->sheap);
6018
6019         g_hash_table_foreach (assembly->blob_cache, (GHFunc)g_free, NULL);
6020         g_hash_table_destroy (assembly->blob_cache);
6021         assembly->blob_cache = NULL;
6022 }
6023
6024 #else /* DISABLE_REFLECTION_EMIT_SAVE */
6025
6026 void
6027 mono_image_create_pefile (MonoReflectionModuleBuilder *mb, HANDLE file)
6028 {
6029         g_assert_not_reached ();
6030 }
6031
6032 #endif /* DISABLE_REFLECTION_EMIT_SAVE */
6033
6034 #ifndef DISABLE_REFLECTION_EMIT
6035
6036 MonoReflectionModule *
6037 mono_image_load_module_dynamic (MonoReflectionAssemblyBuilder *ab, MonoString *fileName)
6038 {
6039         char *name;
6040         MonoImage *image;
6041         MonoImageOpenStatus status;
6042         MonoDynamicAssembly *assembly;
6043         guint32 module_count;
6044         MonoImage **new_modules;
6045         gboolean *new_modules_loaded;
6046         
6047         name = mono_string_to_utf8 (fileName);
6048
6049         image = mono_image_open (name, &status);
6050         if (!image) {
6051                 MonoException *exc;
6052                 if (status == MONO_IMAGE_ERROR_ERRNO)
6053                         exc = mono_get_exception_file_not_found (fileName);
6054                 else
6055                         exc = mono_get_exception_bad_image_format (name);
6056                 g_free (name);
6057                 mono_raise_exception (exc);
6058         }
6059
6060         g_free (name);
6061
6062         assembly = ab->dynamic_assembly;
6063         image->assembly = (MonoAssembly*)assembly;
6064
6065         module_count = image->assembly->image->module_count;
6066         new_modules = g_new0 (MonoImage *, module_count + 1);
6067         new_modules_loaded = g_new0 (gboolean, module_count + 1);
6068
6069         if (image->assembly->image->modules)
6070                 memcpy (new_modules, image->assembly->image->modules, module_count * sizeof (MonoImage *));
6071         if (image->assembly->image->modules_loaded)
6072                 memcpy (new_modules_loaded, image->assembly->image->modules_loaded, module_count * sizeof (gboolean));
6073         new_modules [module_count] = image;
6074         new_modules_loaded [module_count] = TRUE;
6075         mono_image_addref (image);
6076
6077         g_free (image->assembly->image->modules);
6078         image->assembly->image->modules = new_modules;
6079         image->assembly->image->modules_loaded = new_modules_loaded;
6080         image->assembly->image->module_count ++;
6081
6082         mono_assembly_load_references (image, &status);
6083         if (status) {
6084                 mono_image_close (image);
6085                 mono_raise_exception (mono_get_exception_file_not_found (fileName));
6086         }
6087
6088         return mono_module_get_object (mono_domain_get (), image);
6089 }
6090
6091 #endif /* DISABLE_REFLECTION_EMIT */
6092
6093 /*
6094  * We need to return always the same object for MethodInfo, FieldInfo etc..
6095  * but we need to consider the reflected type.
6096  * type uses a different hash, since it uses custom hash/equal functions.
6097  */
6098
6099 typedef struct {
6100         gpointer item;
6101         MonoClass *refclass;
6102 } ReflectedEntry;
6103
6104 static gboolean
6105 reflected_equal (gconstpointer a, gconstpointer b) {
6106         const ReflectedEntry *ea = a;
6107         const ReflectedEntry *eb = b;
6108
6109         return (ea->item == eb->item) && (ea->refclass == eb->refclass);
6110 }
6111
6112 static guint
6113 reflected_hash (gconstpointer a) {
6114         const ReflectedEntry *ea = a;
6115         return mono_aligned_addr_hash (ea->item);
6116 }
6117
6118 #define CHECK_OBJECT(t,p,k)     \
6119         do {    \
6120                 t _obj; \
6121                 ReflectedEntry e;       \
6122                 e.item = (p);   \
6123                 e.refclass = (k);       \
6124                 mono_domain_lock (domain);      \
6125                 if (!domain->refobject_hash)    \
6126                         domain->refobject_hash = mono_g_hash_table_new_type (reflected_hash, reflected_equal, MONO_HASH_VALUE_GC);      \
6127                 if ((_obj = mono_g_hash_table_lookup (domain->refobject_hash, &e))) {   \
6128                         mono_domain_unlock (domain);    \
6129                         return _obj;    \
6130                 }       \
6131         mono_domain_unlock (domain); \
6132         } while (0)
6133
6134 #ifdef HAVE_BOEHM_GC
6135 /* ReflectedEntry doesn't need to be GC tracked */
6136 #define ALLOC_REFENTRY g_new0 (ReflectedEntry, 1)
6137 #define FREE_REFENTRY(entry) g_free ((entry))
6138 #define REFENTRY_REQUIRES_CLEANUP
6139 #else
6140 #define ALLOC_REFENTRY mono_mempool_alloc (domain->mp, sizeof (ReflectedEntry))
6141 /* FIXME: */
6142 #define FREE_REFENTRY(entry)
6143 #endif
6144
6145 #define CACHE_OBJECT(t,p,o,k)   \
6146         do {    \
6147                 t _obj; \
6148         ReflectedEntry pe; \
6149         pe.item = (p); \
6150         pe.refclass = (k); \
6151         mono_domain_lock (domain); \
6152                 if (!domain->refobject_hash)    \
6153                         domain->refobject_hash = mono_g_hash_table_new_type (reflected_hash, reflected_equal, MONO_HASH_VALUE_GC);      \
6154         _obj = mono_g_hash_table_lookup (domain->refobject_hash, &pe); \
6155         if (!_obj) { \
6156                     ReflectedEntry *e = ALLOC_REFENTRY;         \
6157                     e->item = (p);      \
6158                     e->refclass = (k);  \
6159                     mono_g_hash_table_insert (domain->refobject_hash, e,o);     \
6160             _obj = o; \
6161         } \
6162                 mono_domain_unlock (domain);    \
6163         return _obj; \
6164         } while (0)
6165
6166 static void
6167 clear_cached_object (MonoDomain *domain, gpointer o, MonoClass *klass)
6168 {
6169         mono_domain_lock (domain);
6170         if (domain->refobject_hash) {
6171         ReflectedEntry pe;
6172                 gpointer orig_pe, orig_value;
6173
6174                 pe.item = o;
6175                 pe.refclass = klass;
6176                 if (mono_g_hash_table_lookup_extended (domain->refobject_hash, &pe, &orig_pe, &orig_value)) {
6177                         mono_g_hash_table_remove (domain->refobject_hash, &pe);
6178                         FREE_REFENTRY (orig_pe);
6179                 }
6180         }
6181         mono_domain_unlock (domain);
6182 }
6183
6184 #ifdef REFENTRY_REQUIRES_CLEANUP
6185 static void
6186 cleanup_refobject_hash (gpointer key, gpointer value, gpointer user_data)
6187 {
6188         FREE_REFENTRY (key);
6189 }
6190 #endif
6191
6192 void
6193 mono_reflection_cleanup_domain (MonoDomain *domain)
6194 {
6195         if (domain->refobject_hash) {
6196 /*let's avoid scanning the whole hashtable if not needed*/
6197 #ifdef REFENTRY_REQUIRES_CLEANUP
6198                 mono_g_hash_table_foreach (domain->refobject_hash, cleanup_refobject_hash, NULL);
6199 #endif
6200                 mono_g_hash_table_destroy (domain->refobject_hash);
6201                 domain->refobject_hash = NULL;
6202         }
6203 }
6204
6205 #ifndef DISABLE_REFLECTION_EMIT
6206 static gpointer
6207 register_assembly (MonoDomain *domain, MonoReflectionAssembly *res, MonoAssembly *assembly)
6208 {
6209         CACHE_OBJECT (MonoReflectionAssembly *, assembly, res, NULL);
6210 }
6211
6212 static gpointer
6213 register_module (MonoDomain *domain, MonoReflectionModuleBuilder *res, MonoDynamicImage *module)
6214 {
6215         CACHE_OBJECT (MonoReflectionModuleBuilder *, module, res, NULL);
6216 }
6217
6218 void
6219 mono_image_module_basic_init (MonoReflectionModuleBuilder *moduleb)
6220 {
6221         MonoDynamicImage *image = moduleb->dynamic_image;
6222         MonoReflectionAssemblyBuilder *ab = moduleb->assemblyb;
6223         if (!image) {
6224                 MonoError error;
6225                 int module_count;
6226                 MonoImage **new_modules;
6227                 MonoImage *ass;
6228                 char *name, *fqname;
6229                 /*
6230                  * FIXME: we already created an image in mono_image_basic_init (), but
6231                  * we don't know which module it belongs to, since that is only 
6232                  * determined at assembly save time.
6233                  */
6234                 /*image = (MonoDynamicImage*)ab->dynamic_assembly->assembly.image; */
6235                 name = mono_string_to_utf8 (ab->name);
6236                 fqname = mono_string_to_utf8_checked (moduleb->module.fqname, &error);
6237                 if (!mono_error_ok (&error)) {
6238                         g_free (name);
6239                         mono_error_raise_exception (&error);
6240                 }
6241                 image = create_dynamic_mono_image (ab->dynamic_assembly, name, fqname);
6242
6243                 moduleb->module.image = &image->image;
6244                 moduleb->dynamic_image = image;
6245                 register_module (mono_object_domain (moduleb), moduleb, image);
6246
6247                 /* register the module with the assembly */
6248                 ass = ab->dynamic_assembly->assembly.image;
6249                 module_count = ass->module_count;
6250                 new_modules = g_new0 (MonoImage *, module_count + 1);
6251
6252                 if (ass->modules)
6253                         memcpy (new_modules, ass->modules, module_count * sizeof (MonoImage *));
6254                 new_modules [module_count] = &image->image;
6255                 mono_image_addref (&image->image);
6256
6257                 g_free (ass->modules);
6258                 ass->modules = new_modules;
6259                 ass->module_count ++;
6260         }
6261 }
6262
6263 void
6264 mono_image_set_wrappers_type (MonoReflectionModuleBuilder *moduleb, MonoReflectionType *type)
6265 {
6266         MonoDynamicImage *image = moduleb->dynamic_image;
6267
6268         g_assert (type->type);
6269         image->wrappers_type = mono_class_from_mono_type (type->type);
6270 }
6271
6272 #endif
6273
6274 /*
6275  * mono_assembly_get_object:
6276  * @domain: an app domain
6277  * @assembly: an assembly
6278  *
6279  * Return an System.Reflection.Assembly object representing the MonoAssembly @assembly.
6280  */
6281 MonoReflectionAssembly*
6282 mono_assembly_get_object (MonoDomain *domain, MonoAssembly *assembly)
6283 {
6284         static MonoClass *assembly_type;
6285         MonoReflectionAssembly *res;
6286         
6287         CHECK_OBJECT (MonoReflectionAssembly *, assembly, NULL);
6288         if (!assembly_type) {
6289                 MonoClass *class = mono_class_from_name (mono_defaults.corlib, "System.Reflection", "MonoAssembly");
6290                 if (class == NULL)
6291                         class = mono_class_from_name (mono_defaults.corlib, "System.Reflection", "Assembly");
6292                 g_assert (class);
6293                 assembly_type = class;
6294         }
6295         res = (MonoReflectionAssembly *)mono_object_new (domain, assembly_type);
6296         res->assembly = assembly;
6297
6298         CACHE_OBJECT (MonoReflectionAssembly *, assembly, res, NULL);
6299 }
6300
6301
6302
6303 MonoReflectionModule*   
6304 mono_module_get_object   (MonoDomain *domain, MonoImage *image)
6305 {
6306         static MonoClass *module_type;
6307         MonoReflectionModule *res;
6308         char* basename;
6309         
6310         CHECK_OBJECT (MonoReflectionModule *, image, NULL);
6311         if (!module_type) {
6312                 MonoClass *class = mono_class_from_name (mono_defaults.corlib, "System.Reflection", "MonoModule");
6313                 if (class == NULL)
6314                         class = mono_class_from_name (mono_defaults.corlib, "System.Reflection", "Module");
6315                 g_assert (class);
6316                 module_type = class;
6317         }
6318         res = (MonoReflectionModule *)mono_object_new (domain, module_type);
6319
6320         res->image = image;
6321         MONO_OBJECT_SETREF (res, assembly, (MonoReflectionAssembly *) mono_assembly_get_object(domain, image->assembly));
6322
6323         MONO_OBJECT_SETREF (res, fqname, mono_string_new (domain, image->name));
6324         basename = g_path_get_basename (image->name);
6325         MONO_OBJECT_SETREF (res, name, mono_string_new (domain, basename));
6326         MONO_OBJECT_SETREF (res, scopename, mono_string_new (domain, image->module_name));
6327         
6328         g_free (basename);
6329
6330         if (image->assembly->image == image) {
6331                 res->token = mono_metadata_make_token (MONO_TABLE_MODULE, 1);
6332         } else {
6333                 int i;
6334                 res->token = 0;
6335                 if (image->assembly->image->modules) {
6336                         for (i = 0; i < image->assembly->image->module_count; i++) {
6337                                 if (image->assembly->image->modules [i] == image)
6338                                         res->token = mono_metadata_make_token (MONO_TABLE_MODULEREF, i + 1);
6339                         }
6340                         g_assert (res->token);
6341                 }
6342         }
6343
6344         CACHE_OBJECT (MonoReflectionModule *, image, res, NULL);
6345 }
6346
6347 MonoReflectionModule*   
6348 mono_module_file_get_object (MonoDomain *domain, MonoImage *image, int table_index)
6349 {
6350         static MonoClass *module_type;
6351         MonoReflectionModule *res;
6352         MonoTableInfo *table;
6353         guint32 cols [MONO_FILE_SIZE];
6354         const char *name;
6355         guint32 i, name_idx;
6356         const char *val;
6357         
6358         if (!module_type) {
6359                 MonoClass *class = mono_class_from_name (mono_defaults.corlib, "System.Reflection", "MonoModule");
6360                 if (class == NULL)
6361                         class = mono_class_from_name (mono_defaults.corlib, "System.Reflection", "Module");
6362                 g_assert (class);
6363                 module_type = class;
6364         }
6365         res = (MonoReflectionModule *)mono_object_new (domain, module_type);
6366
6367         table = &image->tables [MONO_TABLE_FILE];
6368         g_assert (table_index < table->rows);
6369         mono_metadata_decode_row (table, table_index, cols, MONO_FILE_SIZE);
6370
6371         res->image = NULL;
6372         MONO_OBJECT_SETREF (res, assembly, (MonoReflectionAssembly *) mono_assembly_get_object(domain, image->assembly));
6373         name = mono_metadata_string_heap (image, cols [MONO_FILE_NAME]);
6374
6375         /* Check whenever the row has a corresponding row in the moduleref table */
6376         table = &image->tables [MONO_TABLE_MODULEREF];
6377         for (i = 0; i < table->rows; ++i) {
6378                 name_idx = mono_metadata_decode_row_col (table, i, MONO_MODULEREF_NAME);
6379                 val = mono_metadata_string_heap (image, name_idx);
6380                 if (strcmp (val, name) == 0)
6381                         res->image = image->modules [i];
6382         }
6383
6384         MONO_OBJECT_SETREF (res, fqname, mono_string_new (domain, name));
6385         MONO_OBJECT_SETREF (res, name, mono_string_new (domain, name));
6386         MONO_OBJECT_SETREF (res, scopename, mono_string_new (domain, name));
6387         res->is_resource = cols [MONO_FILE_FLAGS] && FILE_CONTAINS_NO_METADATA;
6388         res->token = mono_metadata_make_token (MONO_TABLE_FILE, table_index + 1);
6389
6390         return res;
6391 }
6392
6393 static gboolean
6394 verify_safe_for_managed_space (MonoType *type)
6395 {
6396         switch (type->type) {
6397 #ifdef DEBUG_HARDER
6398         case MONO_TYPE_ARRAY:
6399                 return verify_safe_for_managed_space (&type->data.array->eklass->byval_arg);
6400         case MONO_TYPE_PTR:
6401                 return verify_safe_for_managed_space (type->data.type);
6402         case MONO_TYPE_SZARRAY:
6403                 return verify_safe_for_managed_space (&type->data.klass->byval_arg);
6404         case MONO_TYPE_GENERICINST: {
6405                 MonoGenericInst *inst = type->data.generic_class->inst;
6406                 int i;
6407                 if (!inst->is_open)
6408                         break;
6409                 for (i = 0; i < inst->type_argc; ++i)
6410                         if (!verify_safe_for_managed_space (inst->type_argv [i]))
6411                                 return FALSE;
6412                 return TRUE;
6413         }
6414 #endif
6415         case MONO_TYPE_VAR:
6416         case MONO_TYPE_MVAR:
6417                 return TRUE;
6418         default:
6419                 return TRUE;
6420         }
6421 }
6422
6423 static MonoType*
6424 mono_type_normalize (MonoType *type)
6425 {
6426         int i;
6427         MonoGenericClass *gclass;
6428         MonoGenericInst *ginst;
6429         MonoClass *gtd;
6430         MonoGenericContainer *gcontainer;
6431         MonoType **argv = NULL;
6432         gboolean is_denorm_gtd = TRUE, requires_rebind = FALSE;
6433
6434         if (type->type != MONO_TYPE_GENERICINST)
6435                 return type;
6436
6437         gclass = type->data.generic_class;
6438         ginst = gclass->context.class_inst;
6439         if (!ginst->is_open)
6440                 return type;
6441
6442         gtd = gclass->container_class;
6443         gcontainer = gtd->generic_container;
6444         argv = g_newa (MonoType*, ginst->type_argc);
6445
6446         for (i = 0; i < ginst->type_argc; ++i) {
6447                 MonoType *t = ginst->type_argv [i], *norm;
6448                 if (t->type != MONO_TYPE_VAR || t->data.generic_param->num != i || t->data.generic_param->owner != gcontainer)
6449                         is_denorm_gtd = FALSE;
6450                 norm = mono_type_normalize (t);
6451                 argv [i] = norm;
6452                 if (norm != t)
6453                         requires_rebind = TRUE;
6454         }
6455
6456         if (is_denorm_gtd)
6457                 return type->byref == gtd->byval_arg.byref ? &gtd->byval_arg : &gtd->this_arg;
6458
6459         if (requires_rebind) {
6460                 MonoClass *klass = mono_class_bind_generic_parameters (gtd, ginst->type_argc, argv, gclass->is_dynamic);
6461                 return type->byref == klass->byval_arg.byref ? &klass->byval_arg : &klass->this_arg;
6462         }
6463
6464         return type;
6465 }
6466 /*
6467  * mono_type_get_object:
6468  * @domain: an app domain
6469  * @type: a type
6470  *
6471  * Return an System.MonoType object representing the type @type.
6472  */
6473 MonoReflectionType*
6474 mono_type_get_object (MonoDomain *domain, MonoType *type)
6475 {
6476         MonoType *norm_type;
6477         MonoReflectionType *res;
6478         MonoClass *klass = mono_class_from_mono_type (type);
6479
6480         /*we must avoid using @type as it might have come
6481          * from a mono_metadata_type_dup and the caller
6482          * expects that is can be freed.
6483          * Using the right type from 
6484          */
6485         type = klass->byval_arg.byref == type->byref ? &klass->byval_arg : &klass->this_arg;
6486
6487         /* void is very common */
6488         if (type->type == MONO_TYPE_VOID && domain->typeof_void)
6489                 return (MonoReflectionType*)domain->typeof_void;
6490
6491         /*
6492          * If the vtable of the given class was already created, we can use
6493          * the MonoType from there and avoid all locking and hash table lookups.
6494          * 
6495          * We cannot do this for TypeBuilders as mono_reflection_create_runtime_class expects
6496          * that the resulting object is different.   
6497          */
6498         if (type == &klass->byval_arg && !image_is_dynamic (klass->image)) {
6499                 MonoVTable *vtable = mono_class_try_get_vtable (domain, klass);
6500                 if (vtable && vtable->type)
6501                         return vtable->type;
6502         }
6503
6504         mono_loader_lock (); /*FIXME mono_class_init and mono_class_vtable acquire it*/
6505         mono_domain_lock (domain);
6506         if (!domain->type_hash)
6507                 domain->type_hash = mono_g_hash_table_new_type ((GHashFunc)mono_metadata_type_hash, 
6508                                 (GCompareFunc)mono_metadata_type_equal, MONO_HASH_VALUE_GC);
6509         if ((res = mono_g_hash_table_lookup (domain->type_hash, type))) {
6510                 mono_domain_unlock (domain);
6511                 mono_loader_unlock ();
6512                 return res;
6513         }
6514
6515         /*Types must be normalized so a generic instance of the GTD get's the same inner type.
6516          * For example in: Foo<A,B>; Bar<A> : Foo<A, Bar<A>>
6517          * The second Bar will be encoded a generic instance of Bar with <A> as parameter.
6518          * On all other places, Bar<A> will be encoded as the GTD itself. This is an implementation
6519          * artifact of how generics are encoded and should be transparent to managed code so we
6520          * need to weed out this diference when retrieving managed System.Type objects.
6521          */
6522         norm_type = mono_type_normalize (type);
6523         if (norm_type != type) {
6524                 res = mono_type_get_object (domain, norm_type);
6525                 mono_g_hash_table_insert (domain->type_hash, type, res);
6526                 mono_domain_unlock (domain);
6527                 mono_loader_unlock ();
6528                 return res;
6529         }
6530
6531         /* This MonoGenericClass hack is no longer necessary. Let's leave it here until we finish with the 2-stage type-builder setup.*/
6532         if ((type->type == MONO_TYPE_GENERICINST) && type->data.generic_class->is_dynamic && !type->data.generic_class->container_class->wastypebuilder)
6533                 g_assert (0);
6534
6535         if (!verify_safe_for_managed_space (type)) {
6536                 mono_domain_unlock (domain);
6537                 mono_loader_unlock ();
6538                 mono_raise_exception (mono_get_exception_invalid_operation ("This type cannot be propagated to managed space"));
6539         }
6540
6541         if (mono_class_get_ref_info (klass) && !klass->wastypebuilder) {
6542                 gboolean is_type_done = TRUE;
6543                 /* Generic parameters have reflection_info set but they are not finished together with their enclosing type.
6544                  * We must ensure that once a type is finished we don't return a GenericTypeParameterBuilder.
6545                  * We can't simply close the types as this will interfere with other parts of the generics machinery.
6546                 */
6547                 if (klass->byval_arg.type == MONO_TYPE_MVAR || klass->byval_arg.type == MONO_TYPE_VAR) {
6548                         MonoGenericParam *gparam = klass->byval_arg.data.generic_param;
6549
6550                         if (gparam->owner && gparam->owner->is_method) {
6551                                 MonoMethod *method = gparam->owner->owner.method;
6552                                 if (method && mono_class_get_generic_type_definition (method->klass)->wastypebuilder)
6553                                         is_type_done = FALSE;
6554                         } else if (gparam->owner && !gparam->owner->is_method) {
6555                                 MonoClass *klass = gparam->owner->owner.klass;
6556                                 if (klass && mono_class_get_generic_type_definition (klass)->wastypebuilder)
6557                                         is_type_done = FALSE;
6558                         }
6559                 } 
6560
6561                 /* g_assert_not_reached (); */
6562                 /* should this be considered an error condition? */
6563                 if (is_type_done && !type->byref) {
6564                         mono_domain_unlock (domain);
6565                         mono_loader_unlock ();
6566                         return mono_class_get_ref_info (klass);
6567                 }
6568         }
6569         /* This is stored in vtables/JITted code so it has to be pinned */
6570         res = (MonoReflectionType *)mono_object_new_pinned (domain, mono_defaults.monotype_class);
6571         res->type = type;
6572         mono_g_hash_table_insert (domain->type_hash, type, res);
6573
6574         if (type->type == MONO_TYPE_VOID)
6575                 domain->typeof_void = (MonoObject*)res;
6576
6577         mono_domain_unlock (domain);
6578         mono_loader_unlock ();
6579         return res;
6580 }
6581
6582 /*
6583  * mono_method_get_object:
6584  * @domain: an app domain
6585  * @method: a method
6586  * @refclass: the reflected type (can be NULL)
6587  *
6588  * Return an System.Reflection.MonoMethod object representing the method @method.
6589  */
6590 MonoReflectionMethod*
6591 mono_method_get_object (MonoDomain *domain, MonoMethod *method, MonoClass *refclass)
6592 {
6593         /*
6594          * We use the same C representation for methods and constructors, but the type 
6595          * name in C# is different.
6596          */
6597         static MonoClass *System_Reflection_MonoMethod = NULL;
6598         static MonoClass *System_Reflection_MonoCMethod = NULL;
6599         static MonoClass *System_Reflection_MonoGenericMethod = NULL;
6600         static MonoClass *System_Reflection_MonoGenericCMethod = NULL;
6601         MonoClass *klass;
6602         MonoReflectionMethod *ret;
6603
6604         if (method->is_inflated) {
6605                 MonoReflectionGenericMethod *gret;
6606
6607                 refclass = method->klass;
6608                 CHECK_OBJECT (MonoReflectionMethod *, method, refclass);
6609                 if ((*method->name == '.') && (!strcmp (method->name, ".ctor") || !strcmp (method->name, ".cctor"))) {
6610                         if (!System_Reflection_MonoGenericCMethod)
6611                                 System_Reflection_MonoGenericCMethod = mono_class_from_name (mono_defaults.corlib, "System.Reflection", "MonoGenericCMethod");
6612                         klass = System_Reflection_MonoGenericCMethod;
6613                 } else {
6614                         if (!System_Reflection_MonoGenericMethod)
6615                                 System_Reflection_MonoGenericMethod = mono_class_from_name (mono_defaults.corlib, "System.Reflection", "MonoGenericMethod");
6616                         klass = System_Reflection_MonoGenericMethod;
6617                 }
6618                 gret = (MonoReflectionGenericMethod*)mono_object_new (domain, klass);
6619                 gret->method.method = method;
6620                 MONO_OBJECT_SETREF (gret, method.name, mono_string_new (domain, method->name));
6621                 MONO_OBJECT_SETREF (gret, method.reftype, mono_type_get_object (domain, &refclass->byval_arg));
6622                 CACHE_OBJECT (MonoReflectionMethod *, method, (MonoReflectionMethod*)gret, refclass);
6623         }
6624
6625         if (!refclass)
6626                 refclass = method->klass;
6627
6628         CHECK_OBJECT (MonoReflectionMethod *, method, refclass);
6629         if (*method->name == '.' && (strcmp (method->name, ".ctor") == 0 || strcmp (method->name, ".cctor") == 0)) {
6630                 if (!System_Reflection_MonoCMethod)
6631                         System_Reflection_MonoCMethod = mono_class_from_name (mono_defaults.corlib, "System.Reflection", "MonoCMethod");
6632                 klass = System_Reflection_MonoCMethod;
6633         }
6634         else {
6635                 if (!System_Reflection_MonoMethod)
6636                         System_Reflection_MonoMethod = mono_class_from_name (mono_defaults.corlib, "System.Reflection", "MonoMethod");
6637                 klass = System_Reflection_MonoMethod;
6638         }
6639         ret = (MonoReflectionMethod*)mono_object_new (domain, klass);
6640         ret->method = method;
6641         MONO_OBJECT_SETREF (ret, reftype, mono_type_get_object (domain, &refclass->byval_arg));
6642         CACHE_OBJECT (MonoReflectionMethod *, method, ret, refclass);
6643 }
6644
6645 /*
6646  * mono_method_clear_object:
6647  *
6648  *   Clear the cached reflection objects for the dynamic method METHOD.
6649  */
6650 void
6651 mono_method_clear_object (MonoDomain *domain, MonoMethod *method)
6652 {
6653         MonoClass *klass;
6654         g_assert (method_is_dynamic (method));
6655
6656         klass = method->klass;
6657         while (klass) {
6658                 clear_cached_object (domain, method, klass);
6659                 klass = klass->parent;
6660         }
6661         /* Added by mono_param_get_objects () */
6662         clear_cached_object (domain, &(method->signature), NULL);
6663         klass = method->klass;
6664         while (klass) {
6665                 clear_cached_object (domain, &(method->signature), klass);
6666                 klass = klass->parent;
6667         }
6668 }
6669
6670 /*
6671  * mono_field_get_object:
6672  * @domain: an app domain
6673  * @klass: a type
6674  * @field: a field
6675  *
6676  * Return an System.Reflection.MonoField object representing the field @field
6677  * in class @klass.
6678  */
6679 MonoReflectionField*
6680 mono_field_get_object (MonoDomain *domain, MonoClass *klass, MonoClassField *field)
6681 {
6682         MonoReflectionField *res;
6683         static MonoClass *monofield_klass;
6684
6685         CHECK_OBJECT (MonoReflectionField *, field, klass);
6686         if (!monofield_klass)
6687                 monofield_klass = mono_class_from_name (mono_defaults.corlib, "System.Reflection", "MonoField");
6688         res = (MonoReflectionField *)mono_object_new (domain, monofield_klass);
6689         res->klass = klass;
6690         res->field = field;
6691         MONO_OBJECT_SETREF (res, name, mono_string_new (domain, mono_field_get_name (field)));
6692
6693         if (is_field_on_inst (field)) {
6694                 res->attrs = get_field_on_inst_generic_type (field)->attrs;
6695                 MONO_OBJECT_SETREF (res, type, mono_type_get_object (domain, field->type));
6696         } else {
6697                 if (field->type)
6698                         MONO_OBJECT_SETREF (res, type, mono_type_get_object (domain, field->type));
6699                 res->attrs = mono_field_get_flags (field);
6700         }
6701         CACHE_OBJECT (MonoReflectionField *, field, res, klass);
6702 }
6703
6704 /*
6705  * mono_property_get_object:
6706  * @domain: an app domain
6707  * @klass: a type
6708  * @property: a property
6709  *
6710  * Return an System.Reflection.MonoProperty object representing the property @property
6711  * in class @klass.
6712  */
6713 MonoReflectionProperty*
6714 mono_property_get_object (MonoDomain *domain, MonoClass *klass, MonoProperty *property)
6715 {
6716         MonoReflectionProperty *res;
6717         static MonoClass *monoproperty_klass;
6718
6719         CHECK_OBJECT (MonoReflectionProperty *, property, klass);
6720         if (!monoproperty_klass)
6721                 monoproperty_klass = mono_class_from_name (mono_defaults.corlib, "System.Reflection", "MonoProperty");
6722         res = (MonoReflectionProperty *)mono_object_new (domain, monoproperty_klass);
6723         res->klass = klass;
6724         res->property = property;
6725         CACHE_OBJECT (MonoReflectionProperty *, property, res, klass);
6726 }
6727
6728 /*
6729  * mono_event_get_object:
6730  * @domain: an app domain
6731  * @klass: a type
6732  * @event: a event
6733  *
6734  * Return an System.Reflection.MonoEvent object representing the event @event
6735  * in class @klass.
6736  */
6737 MonoReflectionEvent*
6738 mono_event_get_object (MonoDomain *domain, MonoClass *klass, MonoEvent *event)
6739 {
6740         MonoReflectionEvent *res;
6741         MonoReflectionMonoEvent *mono_event;
6742         static MonoClass *monoevent_klass;
6743
6744         CHECK_OBJECT (MonoReflectionEvent *, event, klass);
6745         if (!monoevent_klass)
6746                 monoevent_klass = mono_class_from_name (mono_defaults.corlib, "System.Reflection", "MonoEvent");
6747         mono_event = (MonoReflectionMonoEvent *)mono_object_new (domain, monoevent_klass);
6748         mono_event->klass = klass;
6749         mono_event->event = event;
6750         res = (MonoReflectionEvent*)mono_event;
6751         CACHE_OBJECT (MonoReflectionEvent *, event, res, klass);
6752 }
6753
6754 /**
6755  * mono_get_reflection_missing_object:
6756  * @domain: Domain where the object lives
6757  *
6758  * Returns the System.Reflection.Missing.Value singleton object
6759  * (of type System.Reflection.Missing).
6760  *
6761  * Used as the value for ParameterInfo.DefaultValue when Optional
6762  * is present
6763  */
6764 static MonoObject *
6765 mono_get_reflection_missing_object (MonoDomain *domain)
6766 {
6767         MonoObject *obj;
6768         static MonoClassField *missing_value_field = NULL;
6769         
6770         if (!missing_value_field) {
6771                 MonoClass *missing_klass;
6772                 missing_klass = mono_class_from_name (mono_defaults.corlib, "System.Reflection", "Missing");
6773                 mono_class_init (missing_klass);
6774                 missing_value_field = mono_class_get_field_from_name (missing_klass, "Value");
6775                 g_assert (missing_value_field);
6776         }
6777         obj = mono_field_get_value_object (domain, missing_value_field, NULL); 
6778         g_assert (obj);
6779         return obj;
6780 }
6781
6782 static MonoObject*
6783 get_dbnull (MonoDomain *domain, MonoObject **dbnull)
6784 {
6785         if (!*dbnull)
6786                 *dbnull = mono_get_dbnull_object (domain);
6787         return *dbnull;
6788 }
6789
6790 static MonoObject*
6791 get_reflection_missing (MonoDomain *domain, MonoObject **reflection_missing)
6792 {
6793         if (!*reflection_missing)
6794                 *reflection_missing = mono_get_reflection_missing_object (domain);
6795         return *reflection_missing;
6796 }
6797
6798 /*
6799  * mono_param_get_objects:
6800  * @domain: an app domain
6801  * @method: a method
6802  *
6803  * Return an System.Reflection.ParameterInfo array object representing the parameters
6804  * in the method @method.
6805  */
6806 MonoArray*
6807 mono_param_get_objects_internal (MonoDomain *domain, MonoMethod *method, MonoClass *refclass)
6808 {
6809         static MonoClass *System_Reflection_ParameterInfo;
6810         static MonoClass *System_Reflection_ParameterInfo_array;
6811         MonoError error;
6812         MonoArray *res = NULL;
6813         MonoReflectionMethod *member = NULL;
6814         MonoReflectionParameter *param = NULL;
6815         char **names, **blobs = NULL;
6816         guint32 *types = NULL;
6817         MonoType *type = NULL;
6818         MonoObject *dbnull = NULL;
6819         MonoObject *missing = NULL;
6820         MonoMarshalSpec **mspecs;
6821         MonoMethodSignature *sig;
6822         MonoVTable *pinfo_vtable;
6823         int i;
6824
6825         if (!System_Reflection_ParameterInfo_array) {
6826                 MonoClass *klass;
6827
6828                 klass = mono_class_from_name (mono_defaults.corlib, "System.Reflection", "MonoParameterInfo");
6829                 if (!klass)
6830                         klass = mono_class_from_name (mono_defaults.corlib, "System.Reflection", "ParameterInfo");
6831
6832                 mono_memory_barrier ();
6833                 System_Reflection_ParameterInfo = klass; 
6834
6835         
6836                 klass = mono_array_class_get (klass, 1);
6837                 mono_memory_barrier ();
6838                 System_Reflection_ParameterInfo_array = klass;
6839         }
6840
6841         sig = mono_method_signature_checked (method, &error);
6842         if (!mono_error_ok (&error))
6843                 mono_error_raise_exception (&error);
6844
6845         if (!sig->param_count)
6846                 return mono_array_new_specific (mono_class_vtable (domain, System_Reflection_ParameterInfo_array), 0);
6847
6848         /* Note: the cache is based on the address of the signature into the method
6849          * since we already cache MethodInfos with the method as keys.
6850          */
6851         CHECK_OBJECT (MonoArray*, &(method->signature), refclass);
6852
6853         member = mono_method_get_object (domain, method, refclass);
6854         names = g_new (char *, sig->param_count);
6855         mono_method_get_param_names (method, (const char **) names);
6856
6857         mspecs = g_new (MonoMarshalSpec*, sig->param_count + 1);
6858         mono_method_get_marshal_info (method, mspecs);
6859
6860         res = mono_array_new_specific (mono_class_vtable (domain, System_Reflection_ParameterInfo_array), sig->param_count);
6861         pinfo_vtable = mono_class_vtable (domain, System_Reflection_ParameterInfo);
6862         for (i = 0; i < sig->param_count; ++i) {
6863                 param = (MonoReflectionParameter *)mono_object_new_specific (pinfo_vtable);
6864                 MONO_OBJECT_SETREF (param, ClassImpl, mono_type_get_object (domain, sig->params [i]));
6865                 MONO_OBJECT_SETREF (param, MemberImpl, (MonoObject*)member);
6866                 MONO_OBJECT_SETREF (param, NameImpl, mono_string_new (domain, names [i]));
6867                 param->PositionImpl = i;
6868                 param->AttrsImpl = sig->params [i]->attrs;
6869
6870                 if (!(param->AttrsImpl & PARAM_ATTRIBUTE_HAS_DEFAULT)) {
6871                         if (param->AttrsImpl & PARAM_ATTRIBUTE_OPTIONAL)
6872                                 MONO_OBJECT_SETREF (param, DefaultValueImpl, get_reflection_missing (domain, &missing));
6873                         else
6874                                 MONO_OBJECT_SETREF (param, DefaultValueImpl, get_dbnull (domain, &dbnull));
6875                 } else {
6876
6877                         if (!blobs) {
6878                                 blobs = g_new0 (char *, sig->param_count);
6879                                 types = g_new0 (guint32, sig->param_count);
6880                                 get_default_param_value_blobs (method, blobs, types); 
6881                         }
6882
6883                         /* Build MonoType for the type from the Constant Table */
6884                         if (!type)
6885                                 type = g_new0 (MonoType, 1);
6886                         type->type = types [i];
6887                         type->data.klass = NULL;
6888                         if (types [i] == MONO_TYPE_CLASS)
6889                                 type->data.klass = mono_defaults.object_class;
6890                         else if ((sig->params [i]->type == MONO_TYPE_VALUETYPE) && sig->params [i]->data.klass->enumtype) {
6891                                 /* For enums, types [i] contains the base type */
6892
6893                                         type->type = MONO_TYPE_VALUETYPE;
6894                                         type->data.klass = mono_class_from_mono_type (sig->params [i]);
6895                         } else
6896                                 type->data.klass = mono_class_from_mono_type (type);
6897
6898                         MONO_OBJECT_SETREF (param, DefaultValueImpl, mono_get_object_from_blob (domain, type, blobs [i]));
6899
6900                         /* Type in the Constant table is MONO_TYPE_CLASS for nulls */
6901                         if (types [i] != MONO_TYPE_CLASS && !param->DefaultValueImpl) {
6902                                 if (param->AttrsImpl & PARAM_ATTRIBUTE_OPTIONAL)
6903                                         MONO_OBJECT_SETREF (param, DefaultValueImpl, get_reflection_missing (domain, &missing));
6904                                 else
6905                                         MONO_OBJECT_SETREF (param, DefaultValueImpl, get_dbnull (domain, &dbnull));
6906                         }
6907                         
6908                 }
6909
6910                 if (mspecs [i + 1])
6911                         MONO_OBJECT_SETREF (param, MarshalAsImpl, (MonoObject*)mono_reflection_marshal_as_attribute_from_marshal_spec (domain, method->klass, mspecs [i + 1]));
6912                 
6913                 mono_array_setref (res, i, param);
6914         }
6915         g_free (names);
6916         g_free (blobs);
6917         g_free (types);
6918         g_free (type);
6919
6920         for (i = mono_method_signature (method)->param_count; i >= 0; i--)
6921                 if (mspecs [i])
6922                         mono_metadata_free_marshal_spec (mspecs [i]);
6923         g_free (mspecs);
6924         
6925         CACHE_OBJECT (MonoArray *, &(method->signature), res, refclass);
6926 }
6927
6928 MonoArray*
6929 mono_param_get_objects (MonoDomain *domain, MonoMethod *method)
6930 {
6931         return mono_param_get_objects_internal (domain, method, NULL);
6932 }
6933
6934 /*
6935  * mono_method_body_get_object:
6936  * @domain: an app domain
6937  * @method: a method
6938  *
6939  * Return an System.Reflection.MethodBody object representing the method @method.
6940  */
6941 MonoReflectionMethodBody*
6942 mono_method_body_get_object (MonoDomain *domain, MonoMethod *method)
6943 {
6944         static MonoClass *System_Reflection_MethodBody = NULL;
6945         static MonoClass *System_Reflection_LocalVariableInfo = NULL;
6946         static MonoClass *System_Reflection_ExceptionHandlingClause = NULL;
6947         MonoReflectionMethodBody *ret;
6948         MonoMethodHeader *header;
6949         MonoImage *image;
6950         guint32 method_rva, local_var_sig_token;
6951     char *ptr;
6952         unsigned char format, flags;
6953         int i;
6954
6955         /* for compatibility with .net */
6956     if (method_is_dynamic (method))
6957         mono_raise_exception (mono_get_exception_invalid_operation (NULL));
6958
6959         if (!System_Reflection_MethodBody)
6960                 System_Reflection_MethodBody = mono_class_from_name (mono_defaults.corlib, "System.Reflection", "MethodBody");
6961         if (!System_Reflection_LocalVariableInfo)
6962                 System_Reflection_LocalVariableInfo = mono_class_from_name (mono_defaults.corlib, "System.Reflection", "LocalVariableInfo");
6963         if (!System_Reflection_ExceptionHandlingClause)
6964                 System_Reflection_ExceptionHandlingClause = mono_class_from_name (mono_defaults.corlib, "System.Reflection", "ExceptionHandlingClause");
6965
6966         CHECK_OBJECT (MonoReflectionMethodBody *, method, NULL);
6967
6968         if ((method->flags & METHOD_ATTRIBUTE_PINVOKE_IMPL) ||
6969                 (method->flags & METHOD_ATTRIBUTE_ABSTRACT) ||
6970             (method->iflags & METHOD_IMPL_ATTRIBUTE_INTERNAL_CALL) ||
6971             (method->iflags & METHOD_IMPL_ATTRIBUTE_RUNTIME))
6972                 return NULL;
6973
6974         image = method->klass->image;
6975         header = mono_method_get_header (method);
6976
6977         if (!image_is_dynamic (image)) {
6978                 /* Obtain local vars signature token */
6979                 method_rva = mono_metadata_decode_row_col (&image->tables [MONO_TABLE_METHOD], mono_metadata_token_index (method->token) - 1, MONO_METHOD_RVA);
6980                 ptr = mono_image_rva_map (image, method_rva);
6981                 flags = *(const unsigned char *) ptr;
6982                 format = flags & METHOD_HEADER_FORMAT_MASK;
6983                 switch (format){
6984                 case METHOD_HEADER_TINY_FORMAT:
6985                         local_var_sig_token = 0;
6986                         break;
6987                 case METHOD_HEADER_FAT_FORMAT:
6988                         ptr += 2;
6989                         ptr += 2;
6990                         ptr += 4;
6991                         local_var_sig_token = read32 (ptr);
6992                         break;
6993                 default:
6994                         g_assert_not_reached ();
6995                 }
6996         } else
6997                 local_var_sig_token = 0; //FIXME
6998
6999         ret = (MonoReflectionMethodBody*)mono_object_new (domain, System_Reflection_MethodBody);
7000
7001         ret->init_locals = header->init_locals;
7002         ret->max_stack = header->max_stack;
7003         ret->local_var_sig_token = local_var_sig_token;
7004         MONO_OBJECT_SETREF (ret, il, mono_array_new_cached (domain, mono_defaults.byte_class, header->code_size));
7005         memcpy (mono_array_addr (ret->il, guint8, 0), header->code, header->code_size);
7006
7007         /* Locals */
7008         MONO_OBJECT_SETREF (ret, locals, mono_array_new_cached (domain, System_Reflection_LocalVariableInfo, header->num_locals));
7009         for (i = 0; i < header->num_locals; ++i) {
7010                 MonoReflectionLocalVariableInfo *info = (MonoReflectionLocalVariableInfo*)mono_object_new (domain, System_Reflection_LocalVariableInfo);
7011                 MONO_OBJECT_SETREF (info, local_type, mono_type_get_object (domain, header->locals [i]));
7012                 info->is_pinned = header->locals [i]->pinned;
7013                 info->local_index = i;
7014                 mono_array_setref (ret->locals, i, info);
7015         }
7016
7017         /* Exceptions */
7018         MONO_OBJECT_SETREF (ret, clauses, mono_array_new_cached (domain, System_Reflection_ExceptionHandlingClause, header->num_clauses));
7019         for (i = 0; i < header->num_clauses; ++i) {
7020                 MonoReflectionExceptionHandlingClause *info = (MonoReflectionExceptionHandlingClause*)mono_object_new (domain, System_Reflection_ExceptionHandlingClause);
7021                 MonoExceptionClause *clause = &header->clauses [i];
7022
7023                 info->flags = clause->flags;
7024                 info->try_offset = clause->try_offset;
7025                 info->try_length = clause->try_len;
7026                 info->handler_offset = clause->handler_offset;
7027                 info->handler_length = clause->handler_len;
7028                 if (clause->flags == MONO_EXCEPTION_CLAUSE_FILTER)
7029                         info->filter_offset = clause->data.filter_offset;
7030                 else if (clause->data.catch_class)
7031                         MONO_OBJECT_SETREF (info, catch_type, mono_type_get_object (mono_domain_get (), &clause->data.catch_class->byval_arg));
7032
7033                 mono_array_setref (ret->clauses, i, info);
7034         }
7035
7036         mono_metadata_free_mh (header);
7037         CACHE_OBJECT (MonoReflectionMethodBody *, method, ret, NULL);
7038         return ret;
7039 }
7040
7041 /**
7042  * mono_get_dbnull_object:
7043  * @domain: Domain where the object lives
7044  *
7045  * Returns the System.DBNull.Value singleton object
7046  *
7047  * Used as the value for ParameterInfo.DefaultValue 
7048  */
7049 MonoObject *
7050 mono_get_dbnull_object (MonoDomain *domain)
7051 {
7052         MonoObject *obj;
7053         static MonoClassField *dbnull_value_field = NULL;
7054         
7055         if (!dbnull_value_field) {
7056                 MonoClass *dbnull_klass;
7057                 dbnull_klass = mono_class_from_name (mono_defaults.corlib, "System", "DBNull");
7058                 mono_class_init (dbnull_klass);
7059                 dbnull_value_field = mono_class_get_field_from_name (dbnull_klass, "Value");
7060                 g_assert (dbnull_value_field);
7061         }
7062         obj = mono_field_get_value_object (domain, dbnull_value_field, NULL); 
7063         g_assert (obj);
7064         return obj;
7065 }
7066
7067 static void
7068 get_default_param_value_blobs (MonoMethod *method, char **blobs, guint32 *types)
7069 {
7070         guint32 param_index, i, lastp, crow = 0;
7071         guint32 param_cols [MONO_PARAM_SIZE], const_cols [MONO_CONSTANT_SIZE];
7072         gint32 idx;
7073
7074         MonoClass *klass = method->klass;
7075         MonoImage *image = klass->image;
7076         MonoMethodSignature *methodsig = mono_method_signature (method);
7077
7078         MonoTableInfo *constt;
7079         MonoTableInfo *methodt;
7080         MonoTableInfo *paramt;
7081
7082         if (!methodsig->param_count)
7083                 return;
7084
7085         mono_class_init (klass);
7086
7087         if (image_is_dynamic (klass->image)) {
7088                 MonoReflectionMethodAux *aux;
7089                 if (method->is_inflated)
7090                         method = ((MonoMethodInflated*)method)->declaring;
7091                 aux = g_hash_table_lookup (((MonoDynamicImage*)method->klass->image)->method_aux_hash, method);
7092                 if (aux && aux->param_defaults) {
7093                         memcpy (blobs, &(aux->param_defaults [1]), methodsig->param_count * sizeof (char*));
7094                         memcpy (types, &(aux->param_default_types [1]), methodsig->param_count * sizeof (guint32));
7095                 }
7096                 return;
7097         }
7098
7099         methodt = &klass->image->tables [MONO_TABLE_METHOD];
7100         paramt = &klass->image->tables [MONO_TABLE_PARAM];
7101         constt = &image->tables [MONO_TABLE_CONSTANT];
7102
7103         idx = mono_method_get_index (method) - 1;
7104         g_assert (idx != -1);
7105
7106         param_index = mono_metadata_decode_row_col (methodt, idx, MONO_METHOD_PARAMLIST);
7107         if (idx + 1 < methodt->rows)
7108                 lastp = mono_metadata_decode_row_col (methodt, idx + 1, MONO_METHOD_PARAMLIST);
7109         else
7110                 lastp = paramt->rows + 1;
7111
7112         for (i = param_index; i < lastp; ++i) {
7113                 guint32 paramseq;
7114
7115                 mono_metadata_decode_row (paramt, i - 1, param_cols, MONO_PARAM_SIZE);
7116                 paramseq = param_cols [MONO_PARAM_SEQUENCE];
7117
7118                 if (!(param_cols [MONO_PARAM_FLAGS] & PARAM_ATTRIBUTE_HAS_DEFAULT))
7119                         continue;
7120
7121                 crow = mono_metadata_get_constant_index (image, MONO_TOKEN_PARAM_DEF | i, crow + 1);
7122                 if (!crow) {
7123                         continue;
7124                 }
7125         
7126                 mono_metadata_decode_row (constt, crow - 1, const_cols, MONO_CONSTANT_SIZE);
7127                 blobs [paramseq - 1] = (gpointer) mono_metadata_blob_heap (image, const_cols [MONO_CONSTANT_VALUE]);
7128                 types [paramseq - 1] = const_cols [MONO_CONSTANT_TYPE];
7129         }
7130
7131         return;
7132 }
7133
7134 MonoObject *
7135 mono_get_object_from_blob (MonoDomain *domain, MonoType *type, const char *blob)
7136 {
7137         void *retval;
7138         MonoClass *klass;
7139         MonoObject *object;
7140         MonoType *basetype = type;
7141
7142         if (!blob)
7143                 return NULL;
7144         
7145         klass = mono_class_from_mono_type (type);
7146         if (klass->valuetype) {
7147                 object = mono_object_new (domain, klass);
7148                 retval = ((gchar *) object + sizeof (MonoObject));
7149                 if (klass->enumtype)
7150                         basetype = mono_class_enum_basetype (klass);
7151         } else {
7152                 retval = &object;
7153         }
7154                         
7155         if (!mono_get_constant_value_from_blob (domain, basetype->type,  blob, retval))
7156                 return object;
7157         else
7158                 return NULL;
7159 }
7160
7161 static int
7162 assembly_name_to_aname (MonoAssemblyName *assembly, char *p) {
7163         int found_sep;
7164         char *s;
7165         gboolean quoted = FALSE;
7166
7167         memset (assembly, 0, sizeof (MonoAssemblyName));
7168         assembly->culture = "";
7169         memset (assembly->public_key_token, 0, MONO_PUBLIC_KEY_TOKEN_LENGTH);
7170
7171         if (*p == '"') {
7172                 quoted = TRUE;
7173                 p++;
7174         }
7175         assembly->name = p;
7176         while (*p && (isalnum (*p) || *p == '.' || *p == '-' || *p == '_' || *p == '$' || *p == '@' || g_ascii_isspace (*p)))
7177                 p++;
7178         if (quoted) {
7179                 if (*p != '"')
7180                         return 1;
7181                 *p = 0;
7182                 p++;
7183         }
7184         if (*p != ',')
7185                 return 1;
7186         *p = 0;
7187         /* Remove trailing whitespace */
7188         s = p - 1;
7189         while (*s && g_ascii_isspace (*s))
7190                 *s-- = 0;
7191         p ++;
7192         while (g_ascii_isspace (*p))
7193                 p++;
7194         while (*p) {
7195                 if (*p == 'V' && g_ascii_strncasecmp (p, "Version=", 8) == 0) {
7196                         p += 8;
7197                         assembly->major = strtoul (p, &s, 10);
7198                         if (s == p || *s != '.')
7199                                 return 1;
7200                         p = ++s;
7201                         assembly->minor = strtoul (p, &s, 10);
7202                         if (s == p || *s != '.')
7203                                 return 1;
7204                         p = ++s;
7205                         assembly->build = strtoul (p, &s, 10);
7206                         if (s == p || *s != '.')
7207                                 return 1;
7208                         p = ++s;
7209                         assembly->revision = strtoul (p, &s, 10);
7210                         if (s == p)
7211                                 return 1;
7212                         p = s;
7213                 } else if (*p == 'C' && g_ascii_strncasecmp (p, "Culture=", 8) == 0) {
7214                         p += 8;
7215                         if (g_ascii_strncasecmp (p, "neutral", 7) == 0) {
7216                                 assembly->culture = "";
7217                                 p += 7;
7218                         } else {
7219                                 assembly->culture = p;
7220                                 while (*p && *p != ',') {
7221                                         p++;
7222                                 }
7223                         }
7224                 } else if (*p == 'P' && g_ascii_strncasecmp (p, "PublicKeyToken=", 15) == 0) {
7225                         p += 15;
7226                         if (strncmp (p, "null", 4) == 0) {
7227                                 p += 4;
7228                         } else {
7229                                 int len;
7230                                 gchar *start = p;
7231                                 while (*p && *p != ',') {
7232                                         p++;
7233                                 }
7234                                 len = (p - start + 1);
7235                                 if (len > MONO_PUBLIC_KEY_TOKEN_LENGTH)
7236                                         len = MONO_PUBLIC_KEY_TOKEN_LENGTH;
7237                                 g_strlcpy ((char*)assembly->public_key_token, start, len);
7238                         }
7239                 } else {
7240                         while (*p && *p != ',')
7241                                 p++;
7242                 }
7243                 found_sep = 0;
7244                 while (g_ascii_isspace (*p) || *p == ',') {
7245                         *p++ = 0;
7246                         found_sep = 1;
7247                         continue;
7248                 }
7249                 /* failed */
7250                 if (!found_sep)
7251                         return 1;
7252         }
7253
7254         return 0;
7255 }
7256
7257 /*
7258  * mono_reflection_parse_type:
7259  * @name: type name
7260  *
7261  * Parse a type name as accepted by the GetType () method and output the info
7262  * extracted in the info structure.
7263  * the name param will be mangled, so, make a copy before passing it to this function.
7264  * The fields in info will be valid until the memory pointed to by name is valid.
7265  *
7266  * See also mono_type_get_name () below.
7267  *
7268  * Returns: 0 on parse error.
7269  */
7270 static int
7271 _mono_reflection_parse_type (char *name, char **endptr, gboolean is_recursed,
7272                              MonoTypeNameParse *info)
7273 {
7274         char *start, *p, *w, *last_point, *startn;
7275         int in_modifiers = 0;
7276         int isbyref = 0, rank = 0;
7277
7278         start = p = w = name;
7279
7280         //FIXME could we just zero the whole struct? memset (&info, 0, sizeof (MonoTypeNameParse))
7281         memset (&info->assembly, 0, sizeof (MonoAssemblyName));
7282         info->name = info->name_space = NULL;
7283         info->nested = NULL;
7284         info->modifiers = NULL;
7285         info->type_arguments = NULL;
7286
7287         /* last_point separates the namespace from the name */
7288         last_point = NULL;
7289         /* Skips spaces */
7290         while (*p == ' ') p++, start++, w++, name++;
7291
7292         while (*p) {
7293                 switch (*p) {
7294                 case '+':
7295                         *p = 0; /* NULL terminate the name */
7296                         startn = p + 1;
7297                         info->nested = g_list_append (info->nested, startn);
7298                         /* we have parsed the nesting namespace + name */
7299                         if (info->name)
7300                                 break;
7301                         if (last_point) {
7302                                 info->name_space = start;
7303                                 *last_point = 0;
7304                                 info->name = last_point + 1;
7305                         } else {
7306                                 info->name_space = (char *)"";
7307                                 info->name = start;
7308                         }
7309                         break;
7310                 case '.':
7311                         last_point = p;
7312                         break;
7313                 case '\\':
7314                         ++p;
7315                         break;
7316                 case '&':
7317                 case '*':
7318                 case '[':
7319                 case ',':
7320                 case ']':
7321                         in_modifiers = 1;
7322                         break;
7323                 default:
7324                         break;
7325                 }
7326                 if (in_modifiers)
7327                         break;
7328                 // *w++ = *p++;
7329                 p++;
7330         }
7331         
7332         if (!info->name) {
7333                 if (last_point) {
7334                         info->name_space = start;
7335                         *last_point = 0;
7336                         info->name = last_point + 1;
7337                 } else {
7338                         info->name_space = (char *)"";
7339                         info->name = start;
7340                 }
7341         }
7342         while (*p) {
7343                 switch (*p) {
7344                 case '&':
7345                         if (isbyref) /* only one level allowed by the spec */
7346                                 return 0;
7347                         isbyref = 1;
7348                         info->modifiers = g_list_append (info->modifiers, GUINT_TO_POINTER (0));
7349                         *p++ = 0;
7350                         break;
7351                 case '*':
7352                         info->modifiers = g_list_append (info->modifiers, GUINT_TO_POINTER (-1));
7353                         *p++ = 0;
7354                         break;
7355                 case '[':
7356                         //Decide if it's an array of a generic argument list
7357                         *p++ = 0;
7358
7359                         if (!*p) //XXX test
7360                                 return 0;
7361                         if (*p  == ',' || *p == '*' || *p == ']') { //array
7362                                 rank = 1;
7363                                 while (*p) {
7364                                         if (*p == ']')
7365                                                 break;
7366                                         if (*p == ',')
7367                                                 rank++;
7368                                         else if (*p == '*') /* '*' means unknown lower bound */
7369                                                 info->modifiers = g_list_append (info->modifiers, GUINT_TO_POINTER (-2));
7370                                         else
7371                                                 return 0;
7372                                         ++p;
7373                                 }
7374                                 if (*p++ != ']')
7375                                         return 0;
7376                                 info->modifiers = g_list_append (info->modifiers, GUINT_TO_POINTER (rank));
7377                         } else {
7378                                 if (rank) /* generic args after array spec*/ //XXX test
7379                                         return 0;
7380                                 info->type_arguments = g_ptr_array_new ();
7381                                 while (*p) {
7382                                         MonoTypeNameParse *subinfo = g_new0 (MonoTypeNameParse, 1);
7383                                         gboolean fqname = FALSE;
7384
7385                                         g_ptr_array_add (info->type_arguments, subinfo);
7386
7387                                         while (*p == ' ') p++;
7388                                         if (*p == '[') {
7389                                                 p++;
7390                                                 fqname = TRUE;
7391                                         }
7392
7393                                         if (!_mono_reflection_parse_type (p, &p, TRUE, subinfo))
7394                                                 return 0;
7395
7396                                         /*MS is lenient on [] delimited parameters that aren't fqn - and F# uses them.*/
7397                                         if (fqname && (*p != ']')) {
7398                                                 char *aname;
7399
7400                                                 if (*p != ',')
7401                                                         return 0;
7402                                                 *p++ = 0;
7403
7404                                                 aname = p;
7405                                                 while (*p && (*p != ']'))
7406                                                         p++;
7407
7408                                                 if (*p != ']')
7409                                                         return 0;
7410
7411                                                 *p++ = 0;
7412                                                 while (*aname) {
7413                                                         if (g_ascii_isspace (*aname)) {
7414                                                                 ++aname;
7415                                                                 continue;
7416                                                         }
7417                                                         break;
7418                                                 }
7419                                                 if (!*aname ||
7420                                                     !assembly_name_to_aname (&subinfo->assembly, aname))
7421                                                         return 0;
7422                                         } else if (fqname && (*p == ']')) {
7423                                                 *p++ = 0;
7424                                         }
7425                                         if (*p == ']') {
7426                                                 *p++ = 0;
7427                                                 break;
7428                                         } else if (!*p) {
7429                                                 return 0;
7430                                         }
7431                                         *p++ = 0;
7432                                 }
7433                         }
7434                         break;
7435                 case ']':
7436                         if (is_recursed)
7437                                 goto end;
7438                         return 0;
7439                 case ',':
7440                         if (is_recursed)
7441                                 goto end;
7442                         *p++ = 0;
7443                         while (*p) {
7444                                 if (g_ascii_isspace (*p)) {
7445                                         ++p;
7446                                         continue;
7447                                 }
7448                                 break;
7449                         }
7450                         if (!*p)
7451                                 return 0; /* missing assembly name */
7452                         if (!assembly_name_to_aname (&info->assembly, p))
7453                                 return 0;
7454                         break;
7455                 default:
7456                         return 0;
7457                 }
7458                 if (info->assembly.name)
7459                         break;
7460         }
7461         // *w = 0; /* terminate class name */
7462  end:
7463         if (!info->name || !*info->name)
7464                 return 0;
7465         if (endptr)
7466                 *endptr = p;
7467         /* add other consistency checks */
7468         return 1;
7469 }
7470
7471 int
7472 mono_reflection_parse_type (char *name, MonoTypeNameParse *info)
7473 {
7474         return _mono_reflection_parse_type (name, NULL, FALSE, info);
7475 }
7476
7477 static MonoType*
7478 _mono_reflection_get_type_from_info (MonoTypeNameParse *info, MonoImage *image, gboolean ignorecase)
7479 {
7480         gboolean type_resolve = FALSE;
7481         MonoType *type;
7482         MonoImage *rootimage = image;
7483
7484         if (info->assembly.name) {
7485                 MonoAssembly *assembly = mono_assembly_loaded (&info->assembly);
7486                 if (!assembly && image && image->assembly && mono_assembly_names_equal (&info->assembly, &image->assembly->aname))
7487                         /* 
7488                          * This could happen in the AOT compiler case when the search hook is not
7489                          * installed.
7490                          */
7491                         assembly = image->assembly;
7492                 if (!assembly) {
7493                         /* then we must load the assembly ourselve - see #60439 */
7494                         assembly = mono_assembly_load (&info->assembly, image->assembly->basedir, NULL);
7495                         if (!assembly)
7496                                 return NULL;
7497                 }
7498                 image = assembly->image;
7499         } else if (!image) {
7500                 image = mono_defaults.corlib;
7501         }
7502
7503         type = mono_reflection_get_type_with_rootimage (rootimage, image, info, ignorecase, &type_resolve);
7504         if (type == NULL && !info->assembly.name && image != mono_defaults.corlib) {
7505                 image = mono_defaults.corlib;
7506                 type = mono_reflection_get_type_with_rootimage (rootimage, image, info, ignorecase, &type_resolve);
7507         }
7508
7509         return type;
7510 }
7511
7512 static MonoType*
7513 mono_reflection_get_type_internal (MonoImage *rootimage, MonoImage* image, MonoTypeNameParse *info, gboolean ignorecase)
7514 {
7515         MonoClass *klass;
7516         GList *mod;
7517         int modval;
7518         gboolean bounded = FALSE;
7519         
7520         if (!image)
7521                 image = mono_defaults.corlib;
7522
7523         if (!rootimage)
7524                 rootimage = mono_defaults.corlib;
7525
7526         if (ignorecase) {
7527                 MonoError error;
7528                 klass = mono_class_from_name_case_checked (image, info->name_space, info->name, &error);
7529                 g_assert (mono_error_ok (&error)); /* FIXME Don't swallow the error */
7530         } else {
7531                 klass = mono_class_from_name (image, info->name_space, info->name);
7532         }
7533         if (!klass)
7534                 return NULL;
7535         for (mod = info->nested; mod; mod = mod->next) {
7536                 gpointer iter = NULL;
7537                 MonoClass *parent;
7538
7539                 parent = klass;
7540                 mono_class_init (parent);
7541
7542                 while ((klass = mono_class_get_nested_types (parent, &iter))) {
7543                         char *lastp;
7544                         char *nested_name, *nested_nspace;
7545                         gboolean match = TRUE;
7546
7547                         lastp = strrchr (mod->data, '.');
7548                         if (lastp) {
7549                                 /* Nested classes can have namespaces */
7550                                 int nspace_len;
7551
7552                                 nested_name = g_strdup (lastp + 1);
7553                                 nspace_len = lastp - (char*)mod->data;
7554                                 nested_nspace = g_malloc (nspace_len + 1);
7555                                 memcpy (nested_nspace, mod->data, nspace_len);
7556                                 nested_nspace [nspace_len] = '\0';
7557
7558                         } else {
7559                                 nested_name = mod->data;
7560                                 nested_nspace = NULL;
7561                         }
7562
7563                         if (nested_nspace) {
7564                                 if (ignorecase) {
7565                                         if (!(klass->name_space && mono_utf8_strcasecmp (klass->name_space, nested_nspace) == 0))
7566                                                 match = FALSE;
7567                                 } else {
7568                                         if (!(klass->name_space && strcmp (klass->name_space, nested_nspace) == 0))
7569                                                 match = FALSE;
7570                                 }
7571                         }
7572                         if (match) {
7573                                 if (ignorecase) {
7574                                         if (mono_utf8_strcasecmp (klass->name, nested_name) != 0)
7575                                                 match = FALSE;
7576                                 } else {
7577                                         if (strcmp (klass->name, nested_name) != 0)
7578                                                 match = FALSE;
7579                                 }
7580                         }
7581                         if (lastp) {
7582                                 g_free (nested_name);
7583                                 g_free (nested_nspace);
7584                         }
7585                         if (match)
7586                                 break;
7587                 }
7588
7589                 if (!klass)
7590                         break;
7591         }
7592         if (!klass)
7593                 return NULL;
7594
7595         if (info->type_arguments) {
7596                 MonoType **type_args = g_new0 (MonoType *, info->type_arguments->len);
7597                 MonoReflectionType *the_type;
7598                 MonoType *instance;
7599                 int i;
7600
7601                 for (i = 0; i < info->type_arguments->len; i++) {
7602                         MonoTypeNameParse *subinfo = g_ptr_array_index (info->type_arguments, i);
7603
7604                         type_args [i] = _mono_reflection_get_type_from_info (subinfo, rootimage, ignorecase);
7605                         if (!type_args [i]) {
7606                                 g_free (type_args);
7607                                 return NULL;
7608                         }
7609                 }
7610
7611                 the_type = mono_type_get_object (mono_domain_get (), &klass->byval_arg);
7612
7613                 instance = mono_reflection_bind_generic_parameters (
7614                         the_type, info->type_arguments->len, type_args);
7615
7616                 g_free (type_args);
7617                 if (!instance)
7618                         return NULL;
7619
7620                 klass = mono_class_from_mono_type (instance);
7621         }
7622
7623         for (mod = info->modifiers; mod; mod = mod->next) {
7624                 modval = GPOINTER_TO_UINT (mod->data);
7625                 if (!modval) { /* byref: must be last modifier */
7626                         return &klass->this_arg;
7627                 } else if (modval == -1) {
7628                         klass = mono_ptr_class_get (&klass->byval_arg);
7629                 } else if (modval == -2) {
7630                         bounded = TRUE;
7631                 } else { /* array rank */
7632                         klass = mono_bounded_array_class_get (klass, modval, bounded);
7633                 }
7634         }
7635
7636         return &klass->byval_arg;
7637 }
7638
7639 /*
7640  * mono_reflection_get_type:
7641  * @image: a metadata context
7642  * @info: type description structure
7643  * @ignorecase: flag for case-insensitive string compares
7644  * @type_resolve: whenever type resolve was already tried
7645  *
7646  * Build a MonoType from the type description in @info.
7647  * 
7648  */
7649
7650 MonoType*
7651 mono_reflection_get_type (MonoImage* image, MonoTypeNameParse *info, gboolean ignorecase, gboolean *type_resolve) {
7652         return mono_reflection_get_type_with_rootimage(image, image, info, ignorecase, type_resolve);
7653 }
7654
7655 static MonoType*
7656 mono_reflection_get_type_internal_dynamic (MonoImage *rootimage, MonoAssembly *assembly, MonoTypeNameParse *info, gboolean ignorecase)
7657 {
7658         MonoReflectionAssemblyBuilder *abuilder;
7659         MonoType *type;
7660         int i;
7661
7662         g_assert (assembly_is_dynamic (assembly));
7663         abuilder = (MonoReflectionAssemblyBuilder*)mono_assembly_get_object (((MonoDynamicAssembly*)assembly)->domain, assembly);
7664
7665         /* Enumerate all modules */
7666
7667         type = NULL;
7668         if (abuilder->modules) {
7669                 for (i = 0; i < mono_array_length (abuilder->modules); ++i) {
7670                         MonoReflectionModuleBuilder *mb = mono_array_get (abuilder->modules, MonoReflectionModuleBuilder*, i);
7671                         type = mono_reflection_get_type_internal (rootimage, &mb->dynamic_image->image, info, ignorecase);
7672                         if (type)
7673                                 break;
7674                 }
7675         }
7676
7677         if (!type && abuilder->loaded_modules) {
7678                 for (i = 0; i < mono_array_length (abuilder->loaded_modules); ++i) {
7679                         MonoReflectionModule *mod = mono_array_get (abuilder->loaded_modules, MonoReflectionModule*, i);
7680                         type = mono_reflection_get_type_internal (rootimage, mod->image, info, ignorecase);
7681                         if (type)
7682                                 break;
7683                 }
7684         }
7685
7686         return type;
7687 }
7688         
7689 MonoType*
7690 mono_reflection_get_type_with_rootimage (MonoImage *rootimage, MonoImage* image, MonoTypeNameParse *info, gboolean ignorecase, gboolean *type_resolve)
7691 {
7692         MonoType *type;
7693         MonoReflectionAssembly *assembly;
7694         GString *fullName;
7695         GList *mod;
7696
7697         if (image && image_is_dynamic (image))
7698                 type = mono_reflection_get_type_internal_dynamic (rootimage, image->assembly, info, ignorecase);
7699         else
7700                 type = mono_reflection_get_type_internal (rootimage, image, info, ignorecase);
7701         if (type)
7702                 return type;
7703         if (!mono_domain_has_type_resolve (mono_domain_get ()))
7704                 return NULL;
7705
7706         if (type_resolve) {
7707                 if (*type_resolve) 
7708                         return NULL;
7709                 else
7710                         *type_resolve = TRUE;
7711         }
7712         
7713         /* Reconstruct the type name */
7714         fullName = g_string_new ("");
7715         if (info->name_space && (info->name_space [0] != '\0'))
7716                 g_string_printf (fullName, "%s.%s", info->name_space, info->name);
7717         else
7718                 g_string_printf (fullName, "%s", info->name);
7719         for (mod = info->nested; mod; mod = mod->next)
7720                 g_string_append_printf (fullName, "+%s", (char*)mod->data);
7721
7722         assembly = mono_domain_try_type_resolve ( mono_domain_get (), fullName->str, NULL);
7723         if (assembly) {
7724                 if (assembly_is_dynamic (assembly->assembly))
7725                         type = mono_reflection_get_type_internal_dynamic (rootimage, assembly->assembly, info, ignorecase);
7726                 else
7727                         type = mono_reflection_get_type_internal (rootimage, assembly->assembly->image, 
7728                                                                                                           info, ignorecase);
7729         }
7730         g_string_free (fullName, TRUE);
7731         return type;
7732 }
7733
7734 void
7735 mono_reflection_free_type_info (MonoTypeNameParse *info)
7736 {
7737         g_list_free (info->modifiers);
7738         g_list_free (info->nested);
7739
7740         if (info->type_arguments) {
7741                 int i;
7742
7743                 for (i = 0; i < info->type_arguments->len; i++) {
7744                         MonoTypeNameParse *subinfo = g_ptr_array_index (info->type_arguments, i);
7745
7746                         mono_reflection_free_type_info (subinfo);
7747                         /*We free the subinfo since it is allocated by _mono_reflection_parse_type*/
7748                         g_free (subinfo);
7749                 }
7750
7751                 g_ptr_array_free (info->type_arguments, TRUE);
7752         }
7753 }
7754
7755 /*
7756  * mono_reflection_type_from_name:
7757  * @name: type name.
7758  * @image: a metadata context (can be NULL).
7759  *
7760  * Retrieves a MonoType from its @name. If the name is not fully qualified,
7761  * it defaults to get the type from @image or, if @image is NULL or loading
7762  * from it fails, uses corlib.
7763  * 
7764  */
7765 MonoType*
7766 mono_reflection_type_from_name (char *name, MonoImage *image)
7767 {
7768         MonoType *type = NULL;
7769         MonoTypeNameParse info;
7770         char *tmp;
7771
7772         /* Make a copy since parse_type modifies its argument */
7773         tmp = g_strdup (name);
7774         
7775         /*g_print ("requested type %s\n", str);*/
7776         if (mono_reflection_parse_type (tmp, &info)) {
7777                 type = _mono_reflection_get_type_from_info (&info, image, FALSE);
7778         }
7779
7780         g_free (tmp);
7781         mono_reflection_free_type_info (&info);
7782         return type;
7783 }
7784
7785 /*
7786  * mono_reflection_get_token:
7787  *
7788  *   Return the metadata token of OBJ which should be an object
7789  * representing a metadata element.
7790  */
7791 guint32
7792 mono_reflection_get_token (MonoObject *obj)
7793 {
7794         MonoClass *klass;
7795         guint32 token = 0;
7796
7797         klass = obj->vtable->klass;
7798
7799         if (strcmp (klass->name, "MethodBuilder") == 0) {
7800                 MonoReflectionMethodBuilder *mb = (MonoReflectionMethodBuilder *)obj;
7801
7802                 token = mb->table_idx | MONO_TOKEN_METHOD_DEF;
7803         } else if (strcmp (klass->name, "ConstructorBuilder") == 0) {
7804                 MonoReflectionCtorBuilder *mb = (MonoReflectionCtorBuilder *)obj;
7805
7806                 token = mb->table_idx | MONO_TOKEN_METHOD_DEF;
7807         } else if (strcmp (klass->name, "FieldBuilder") == 0) {
7808                 MonoReflectionFieldBuilder *fb = (MonoReflectionFieldBuilder *)obj;
7809
7810                 token = fb->table_idx | MONO_TOKEN_FIELD_DEF;
7811         } else if (strcmp (klass->name, "TypeBuilder") == 0) {
7812                 MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder *)obj;
7813                 token = tb->table_idx | MONO_TOKEN_TYPE_DEF;
7814         } else if (strcmp (klass->name, "MonoType") == 0) {
7815                 MonoType *type = mono_reflection_type_get_handle ((MonoReflectionType*)obj);
7816                 MonoClass *mc = mono_class_from_mono_type (type);
7817                 if (!mono_class_init (mc))
7818                         mono_raise_exception (mono_class_get_exception_for_failure (mc));
7819
7820                 token = mc->type_token;
7821         } else if (strcmp (klass->name, "MonoCMethod") == 0 ||
7822                    strcmp (klass->name, "MonoMethod") == 0 ||
7823                    strcmp (klass->name, "MonoGenericMethod") == 0 ||
7824                    strcmp (klass->name, "MonoGenericCMethod") == 0) {
7825                 MonoReflectionMethod *m = (MonoReflectionMethod *)obj;
7826                 if (m->method->is_inflated) {
7827                         MonoMethodInflated *inflated = (MonoMethodInflated *) m->method;
7828                         return inflated->declaring->token;
7829                 } else {
7830                         token = m->method->token;
7831                 }
7832         } else if (strcmp (klass->name, "MonoField") == 0) {
7833                 MonoReflectionField *f = (MonoReflectionField*)obj;
7834
7835                 if (is_field_on_inst (f->field)) {
7836                         MonoDynamicGenericClass *dgclass = (MonoDynamicGenericClass*)f->field->parent->generic_class;
7837
7838                         if (f->field >= dgclass->fields && f->field < dgclass->fields + dgclass->count_fields) {
7839                                 int field_index = f->field - dgclass->fields;
7840                                 MonoObject *obj;
7841
7842                                 g_assert (field_index >= 0 && field_index < dgclass->count_fields);
7843                                 obj = dgclass->field_objects [field_index];
7844                                 return mono_reflection_get_token (obj);
7845                         }
7846                 }
7847                 token = mono_class_get_field_token (f->field);
7848         } else if (strcmp (klass->name, "MonoProperty") == 0) {
7849                 MonoReflectionProperty *p = (MonoReflectionProperty*)obj;
7850
7851                 token = mono_class_get_property_token (p->property);
7852         } else if (strcmp (klass->name, "MonoEvent") == 0) {
7853                 MonoReflectionMonoEvent *p = (MonoReflectionMonoEvent*)obj;
7854
7855                 token = mono_class_get_event_token (p->event);
7856         } else if (strcmp (klass->name, "ParameterInfo") == 0 || strcmp (klass->name, "MonoParameterInfo") == 0) {
7857                 MonoReflectionParameter *p = (MonoReflectionParameter*)obj;
7858                 MonoClass *member_class = mono_object_class (p->MemberImpl);
7859                 g_assert (mono_class_is_reflection_method_or_constructor (member_class));
7860
7861                 token = mono_method_get_param_token (((MonoReflectionMethod*)p->MemberImpl)->method, p->PositionImpl);
7862         } else if (strcmp (klass->name, "Module") == 0 || strcmp (klass->name, "MonoModule") == 0) {
7863                 MonoReflectionModule *m = (MonoReflectionModule*)obj;
7864
7865                 token = m->token;
7866         } else if (strcmp (klass->name, "Assembly") == 0 || strcmp (klass->name, "MonoAssembly") == 0) {
7867                 token = mono_metadata_make_token (MONO_TABLE_ASSEMBLY, 1);
7868         } else {
7869                 gchar *msg = g_strdup_printf ("MetadataToken is not supported for type '%s.%s'", klass->name_space, klass->name);
7870                 MonoException *ex = mono_get_exception_not_implemented (msg);
7871                 g_free (msg);
7872                 mono_raise_exception (ex);
7873         }
7874
7875         return token;
7876 }
7877
7878 static MonoClass*
7879 load_cattr_enum_type (MonoImage *image, const char *p, const char **end, MonoError *error)
7880 {
7881         char *n;
7882         MonoType *t;
7883         int slen = mono_metadata_decode_value (p, &p);
7884
7885         mono_error_init (error);
7886
7887         n = g_memdup (p, slen + 1);
7888         n [slen] = 0;
7889         t = mono_reflection_type_from_name (n, image);
7890         if (!t) {
7891                 /* FIXME the error should come from mono_reflection_type_from_name as it will have type/assembly names split */
7892                 /* We don't free n, it's consumed by mono_error */
7893                 mono_error_set_type_load_name (error, n, NULL, "Could not load enum type %s while decoding custom attribute", n);
7894                 return NULL;
7895         }
7896         g_free (n);
7897         p += slen;
7898         *end = p;
7899         return mono_class_from_mono_type (t);
7900 }
7901
7902 static void*
7903 load_cattr_value (MonoImage *image, MonoType *t, const char *p, const char **end, MonoError *error)
7904 {
7905         int slen, type = t->type;
7906         MonoClass *tklass = t->data.klass;
7907
7908         mono_error_init (error);
7909
7910 handle_enum:
7911         switch (type) {
7912         case MONO_TYPE_U1:
7913         case MONO_TYPE_I1:
7914         case MONO_TYPE_BOOLEAN: {
7915                 MonoBoolean *bval = g_malloc (sizeof (MonoBoolean));
7916                 *bval = *p;
7917                 *end = p + 1;
7918                 return bval;
7919         }
7920         case MONO_TYPE_CHAR:
7921         case MONO_TYPE_U2:
7922         case MONO_TYPE_I2: {
7923                 guint16 *val = g_malloc (sizeof (guint16));
7924                 *val = read16 (p);
7925                 *end = p + 2;
7926                 return val;
7927         }
7928 #if SIZEOF_VOID_P == 4
7929         case MONO_TYPE_U:
7930         case MONO_TYPE_I:
7931 #endif
7932         case MONO_TYPE_R4:
7933         case MONO_TYPE_U4:
7934         case MONO_TYPE_I4: {
7935                 guint32 *val = g_malloc (sizeof (guint32));
7936                 *val = read32 (p);
7937                 *end = p + 4;
7938                 return val;
7939         }
7940 #if SIZEOF_VOID_P == 8
7941         case MONO_TYPE_U: /* error out instead? this should probably not happen */
7942         case MONO_TYPE_I:
7943 #endif
7944         case MONO_TYPE_U8:
7945         case MONO_TYPE_I8: {
7946                 guint64 *val = g_malloc (sizeof (guint64));
7947                 *val = read64 (p);
7948                 *end = p + 8;
7949                 return val;
7950         }
7951         case MONO_TYPE_R8: {
7952                 double *val = g_malloc (sizeof (double));
7953                 readr8 (p, val);
7954                 *end = p + 8;
7955                 return val;
7956         }
7957         case MONO_TYPE_VALUETYPE:
7958                 if (t->data.klass->enumtype) {
7959                         type = mono_class_enum_basetype (t->data.klass)->type;
7960                         goto handle_enum;
7961                 } else {
7962                         MonoClass *k =  t->data.klass;
7963                         
7964                         if (mono_is_corlib_image (k->image) && strcmp (k->name_space, "System") == 0 && strcmp (k->name, "DateTime") == 0){
7965                                 guint64 *val = g_malloc (sizeof (guint64));
7966                                 *val = read64 (p);
7967                                 *end = p + 8;
7968                                 return val;
7969                         }
7970                 }
7971                 g_error ("generic valutype %s not handled in custom attr value decoding", t->data.klass->name);
7972                 break;
7973                 
7974         case MONO_TYPE_STRING:
7975                 if (*p == (char)0xFF) {
7976                         *end = p + 1;
7977                         return NULL;
7978                 }
7979                 slen = mono_metadata_decode_value (p, &p);
7980                 *end = p + slen;
7981                 return mono_string_new_len (mono_domain_get (), p, slen);
7982         case MONO_TYPE_CLASS: {
7983                 char *n;
7984                 MonoType *t;
7985                 if (*p == (char)0xFF) {
7986                         *end = p + 1;
7987                         return NULL;
7988                 }
7989 handle_type:
7990                 slen = mono_metadata_decode_value (p, &p);
7991                 n = g_memdup (p, slen + 1);
7992                 n [slen] = 0;
7993                 t = mono_reflection_type_from_name (n, image);
7994                 if (!t) {
7995                         /* FIXME the error should come from mono_reflection_type_from_name as it will have type/assembly names split */
7996                         /* We don't free n, it's consumed by mono_error */
7997                         mono_error_set_type_load_name (error, n, NULL, "Could not load type %s while decoding custom attribute", n);
7998                         return NULL;
7999                 }
8000                 g_free (n);
8001                 *end = p + slen;
8002                 return mono_type_get_object (mono_domain_get (), t);
8003         }
8004         case MONO_TYPE_OBJECT: {
8005                 char subt = *p++;
8006                 MonoObject *obj;
8007                 MonoClass *subc = NULL;
8008                 void *val;
8009
8010                 if (subt == 0x50) {
8011                         goto handle_type;
8012                 } else if (subt == 0x0E) {
8013                         type = MONO_TYPE_STRING;
8014                         goto handle_enum;
8015                 } else if (subt == 0x1D) {
8016                         MonoType simple_type = {{0}};
8017                         int etype = *p;
8018                         p ++;
8019
8020                         type = MONO_TYPE_SZARRAY;
8021                         if (etype == 0x50) {
8022                                 tklass = mono_defaults.systemtype_class;
8023                         } else if (etype == 0x55) {
8024                                 tklass = load_cattr_enum_type (image, p, &p, error);
8025                                 if (!mono_error_ok (error))
8026                                         return NULL;
8027                         } else {
8028                                 if (etype == 0x51)
8029                                         /* See Partition II, Appendix B3 */
8030                                         etype = MONO_TYPE_OBJECT;
8031                                 simple_type.type = etype;
8032                                 tklass = mono_class_from_mono_type (&simple_type);
8033                         }
8034                         goto handle_enum;
8035                 } else if (subt == 0x55) {
8036                         char *n;
8037                         MonoType *t;
8038                         slen = mono_metadata_decode_value (p, &p);
8039                         n = g_memdup (p, slen + 1);
8040                         n [slen] = 0;
8041                         t = mono_reflection_type_from_name (n, image);
8042                         if (!t) {
8043                                 /* FIXME the error should come from mono_reflection_type_from_name as it will have type/assembly names split */
8044                                 /* We don't free n, it's consumed by mono_error */
8045                                 mono_error_set_type_load_name (error, n, NULL, "Could not load type %s while decoding custom attribute", n);
8046                                 return NULL;
8047                         }
8048                         g_free (n);
8049                         p += slen;
8050                         subc = mono_class_from_mono_type (t);
8051                 } else if (subt >= MONO_TYPE_BOOLEAN && subt <= MONO_TYPE_R8) {
8052                         MonoType simple_type = {{0}};
8053                         simple_type.type = subt;
8054                         subc = mono_class_from_mono_type (&simple_type);
8055                 } else {
8056                         g_error ("Unknown type 0x%02x for object type encoding in custom attr", subt);
8057                 }
8058                 val = load_cattr_value (image, &subc->byval_arg, p, end, error);
8059                 obj = NULL;
8060                 if (mono_error_ok (error)) {
8061                         obj = mono_object_new (mono_domain_get (), subc);
8062                         g_assert (!subc->has_references);
8063                         mono_gc_memmove_atomic ((char*)obj + sizeof (MonoObject), val, mono_class_value_size (subc, NULL));
8064                 }
8065
8066                 g_free (val);
8067                 return obj;
8068         }
8069         case MONO_TYPE_SZARRAY: {
8070                 MonoArray *arr;
8071                 guint32 i, alen, basetype;
8072                 alen = read32 (p);
8073                 p += 4;
8074                 if (alen == 0xffffffff) {
8075                         *end = p;
8076                         return NULL;
8077                 }
8078                 arr = mono_array_new (mono_domain_get(), tklass, alen);
8079                 basetype = tklass->byval_arg.type;
8080                 if (basetype == MONO_TYPE_VALUETYPE && tklass->enumtype)
8081                         basetype = mono_class_enum_basetype (tklass)->type;
8082                 switch (basetype)
8083                 {
8084                         case MONO_TYPE_U1:
8085                         case MONO_TYPE_I1:
8086                         case MONO_TYPE_BOOLEAN:
8087                                 for (i = 0; i < alen; i++) {
8088                                         MonoBoolean val = *p++;
8089                                         mono_array_set (arr, MonoBoolean, i, val);
8090                                 }
8091                                 break;
8092                         case MONO_TYPE_CHAR:
8093                         case MONO_TYPE_U2:
8094                         case MONO_TYPE_I2:
8095                                 for (i = 0; i < alen; i++) {
8096                                         guint16 val = read16 (p);
8097                                         mono_array_set (arr, guint16, i, val);
8098                                         p += 2;
8099                                 }
8100                                 break;
8101                         case MONO_TYPE_R4:
8102                         case MONO_TYPE_U4:
8103                         case MONO_TYPE_I4:
8104                                 for (i = 0; i < alen; i++) {
8105                                         guint32 val = read32 (p);
8106                                         mono_array_set (arr, guint32, i, val);
8107                                         p += 4;
8108                                 }
8109                                 break;
8110                         case MONO_TYPE_R8:
8111                                 for (i = 0; i < alen; i++) {
8112                                         double val;
8113                                         readr8 (p, &val);
8114                                         mono_array_set (arr, double, i, val);
8115                                         p += 8;
8116                                 }
8117                                 break;
8118                         case MONO_TYPE_U8:
8119                         case MONO_TYPE_I8:
8120                                 for (i = 0; i < alen; i++) {
8121                                         guint64 val = read64 (p);
8122                                         mono_array_set (arr, guint64, i, val);
8123                                         p += 8;
8124                                 }
8125                                 break;
8126                         case MONO_TYPE_CLASS:
8127                         case MONO_TYPE_OBJECT:
8128                         case MONO_TYPE_STRING:
8129                         case MONO_TYPE_SZARRAY:
8130                                 for (i = 0; i < alen; i++) {
8131                                         MonoObject *item = load_cattr_value (image, &tklass->byval_arg, p, &p, error);
8132                                         if (!mono_error_ok (error))
8133                                                 return NULL;
8134                                         mono_array_setref (arr, i, item);
8135                                 }
8136                                 break;
8137                         default:
8138                                 g_error ("Type 0x%02x not handled in custom attr array decoding", basetype);
8139                 }
8140                 *end=p;
8141                 return arr;
8142         }
8143         default:
8144                 g_error ("Type 0x%02x not handled in custom attr value decoding", type);
8145         }
8146         return NULL;
8147 }
8148
8149 static MonoObject*
8150 create_cattr_typed_arg (MonoType *t, MonoObject *val)
8151 {
8152         static MonoClass *klass;
8153         static MonoMethod *ctor;
8154         MonoObject *retval;
8155         void *params [2], *unboxed;
8156
8157         if (!klass)
8158                 klass = mono_class_from_name (mono_defaults.corlib, "System.Reflection", "CustomAttributeTypedArgument");
8159         if (!ctor)
8160                 ctor = mono_class_get_method_from_name (klass, ".ctor", 2);
8161         
8162         params [0] = mono_type_get_object (mono_domain_get (), t);
8163         params [1] = val;
8164         retval = mono_object_new (mono_domain_get (), klass);
8165         unboxed = mono_object_unbox (retval);
8166         mono_runtime_invoke (ctor, unboxed, params, NULL);
8167
8168         return retval;
8169 }
8170
8171 static MonoObject*
8172 create_cattr_named_arg (void *minfo, MonoObject *typedarg)
8173 {
8174         static MonoClass *klass;
8175         static MonoMethod *ctor;
8176         MonoObject *retval;
8177         void *unboxed, *params [2];
8178
8179         if (!klass)
8180                 klass = mono_class_from_name (mono_defaults.corlib, "System.Reflection", "CustomAttributeNamedArgument");
8181         if (!ctor)
8182                 ctor = mono_class_get_method_from_name (klass, ".ctor", 2);
8183
8184         params [0] = minfo;
8185         params [1] = typedarg;
8186         retval = mono_object_new (mono_domain_get (), klass);
8187         unboxed = mono_object_unbox (retval);
8188         mono_runtime_invoke (ctor, unboxed, params, NULL);
8189
8190         return retval;
8191 }
8192
8193 static gboolean
8194 type_is_reference (MonoType *type)
8195 {
8196         switch (type->type) {
8197         case MONO_TYPE_BOOLEAN:
8198         case MONO_TYPE_CHAR:
8199         case MONO_TYPE_U:
8200         case MONO_TYPE_I:
8201         case MONO_TYPE_U1:
8202         case MONO_TYPE_I1:
8203         case MONO_TYPE_U2:
8204         case MONO_TYPE_I2:
8205         case MONO_TYPE_U4:
8206         case MONO_TYPE_I4:
8207         case MONO_TYPE_U8:
8208         case MONO_TYPE_I8:
8209         case MONO_TYPE_R8:
8210         case MONO_TYPE_R4:
8211         case MONO_TYPE_VALUETYPE:
8212                 return FALSE;
8213         default:
8214                 return TRUE;
8215         }
8216 }
8217
8218 static void
8219 free_param_data (MonoMethodSignature *sig, void **params) {
8220         int i;
8221         for (i = 0; i < sig->param_count; ++i) {
8222                 if (!type_is_reference (sig->params [i]))
8223                         g_free (params [i]);
8224         }
8225 }
8226
8227 /*
8228  * Find the field index in the metadata FieldDef table.
8229  */
8230 static guint32
8231 find_field_index (MonoClass *klass, MonoClassField *field) {
8232         int i;
8233
8234         for (i = 0; i < klass->field.count; ++i) {
8235                 if (field == &klass->fields [i])
8236                         return klass->field.first + 1 + i;
8237         }
8238         return 0;
8239 }
8240
8241 /*
8242  * Find the property index in the metadata Property table.
8243  */
8244 static guint32
8245 find_property_index (MonoClass *klass, MonoProperty *property) {
8246         int i;
8247
8248         for (i = 0; i < klass->ext->property.count; ++i) {
8249                 if (property == &klass->ext->properties [i])
8250                         return klass->ext->property.first + 1 + i;
8251         }
8252         return 0;
8253 }
8254
8255 /*
8256  * Find the event index in the metadata Event table.
8257  */
8258 static guint32
8259 find_event_index (MonoClass *klass, MonoEvent *event) {
8260         int i;
8261
8262         for (i = 0; i < klass->ext->event.count; ++i) {
8263                 if (event == &klass->ext->events [i])
8264                         return klass->ext->event.first + 1 + i;
8265         }
8266         return 0;
8267 }
8268
8269 static MonoObject*
8270 create_custom_attr (MonoImage *image, MonoMethod *method, const guchar *data, guint32 len, MonoError *error)
8271 {
8272         const char *p = (const char*)data;
8273         const char *named;
8274         guint32 i, j, num_named;
8275         MonoObject *attr;
8276         void *params_buf [32];
8277         void **params = NULL;
8278         MonoMethodSignature *sig;
8279         MonoObject *exc = NULL;
8280
8281         mono_error_init (error);
8282
8283         mono_class_init (method->klass);
8284
8285         if (!mono_verifier_verify_cattr_content (image, method, data, len, NULL)) {
8286                 mono_error_set_generic_error (error, "System.Reflection", "CustomAttributeFormatException", "Binary format of the specified custom attribute was invalid.");
8287                 return NULL;
8288         }
8289
8290         if (len == 0) {
8291                 attr = mono_object_new (mono_domain_get (), method->klass);
8292                 mono_runtime_invoke (method, attr, NULL, NULL);
8293                 return attr;
8294         }
8295
8296         if (len < 2 || read16 (p) != 0x0001) /* Prolog */
8297                 return NULL;
8298
8299         /*g_print ("got attr %s\n", method->klass->name);*/
8300
8301         sig = mono_method_signature (method);
8302         if (sig->param_count < 32) {
8303                 params = params_buf;
8304                 memset (params, 0, sizeof (void*) * sig->param_count);
8305         } else {
8306                 /* Allocate using GC so it gets GC tracking */
8307                 params = mono_gc_alloc_fixed (sig->param_count * sizeof (void*), NULL);
8308         }
8309
8310         /* skip prolog */
8311         p += 2;
8312         for (i = 0; i < mono_method_signature (method)->param_count; ++i) {
8313                 params [i] = load_cattr_value (image, mono_method_signature (method)->params [i], p, &p, error);
8314                 if (!mono_error_ok (error))
8315                         goto fail;
8316         }
8317
8318         named = p;
8319         attr = mono_object_new (mono_domain_get (), method->klass);
8320
8321         mono_runtime_invoke (method, attr, params, &exc);
8322         if (exc)
8323                 goto fail;
8324         num_named = read16 (named);
8325         named += 2;
8326         for (j = 0; j < num_named; j++) {
8327                 gint name_len;
8328                 char *name, named_type, data_type;
8329                 named_type = *named++;
8330                 data_type = *named++; /* type of data */
8331                 if (data_type == MONO_TYPE_SZARRAY)
8332                         data_type = *named++;
8333                 if (data_type == MONO_TYPE_ENUM) {
8334                         gint type_len;
8335                         char *type_name;
8336                         type_len = mono_metadata_decode_blob_size (named, &named);
8337                         type_name = g_malloc (type_len + 1);
8338                         memcpy (type_name, named, type_len);
8339                         type_name [type_len] = 0;
8340                         named += type_len;
8341                         /* FIXME: lookup the type and check type consistency */
8342                         g_free (type_name);
8343                 }
8344                 name_len = mono_metadata_decode_blob_size (named, &named);
8345                 name = g_malloc (name_len + 1);
8346                 memcpy (name, named, name_len);
8347                 name [name_len] = 0;
8348                 named += name_len;
8349                 if (named_type == 0x53) {
8350                         MonoClassField *field;
8351                         void *val;
8352
8353                         /* how this fail is a blackbox */
8354                         field = mono_class_get_field_from_name (mono_object_class (attr), name);
8355                         if (!field) {
8356                                 mono_error_set_generic_error (error, "System.Reflection", "CustomAttributeFormatException", "Could not find a field with name %s", name);
8357                                 g_free (name);
8358                                 goto fail;
8359                         }
8360
8361                         val = load_cattr_value (image, field->type, named, &named, error);
8362                         if (!mono_error_ok (error)) {
8363                                 g_free (name);
8364                                 if (!type_is_reference (field->type))
8365                                         g_free (val);
8366                                 goto fail;
8367                         }
8368
8369                         mono_field_set_value (attr, field, val);
8370                         if (!type_is_reference (field->type))
8371                                 g_free (val);
8372                 } else if (named_type == 0x54) {
8373                         MonoProperty *prop;
8374                         void *pparams [1];
8375                         MonoType *prop_type;
8376
8377                         prop = mono_class_get_property_from_name (mono_object_class (attr), name);
8378
8379                         if (!prop) {
8380                                 mono_error_set_generic_error (error, "System.Reflection", "CustomAttributeFormatException", "Could not find a property with name %s", name);
8381                                 g_free (name);
8382                                 goto fail;
8383                         }
8384
8385                         if (!prop->set) {
8386                                 mono_error_set_generic_error (error, "System.Reflection", "CustomAttributeFormatException", "Could not find the setter for %s", name);
8387                                 g_free (name);
8388                                 goto fail;
8389                         }
8390
8391                         /* can we have more that 1 arg in a custom attr named property? */
8392                         prop_type = prop->get? mono_method_signature (prop->get)->ret :
8393                              mono_method_signature (prop->set)->params [mono_method_signature (prop->set)->param_count - 1];
8394
8395                         pparams [0] = load_cattr_value (image, prop_type, named, &named, error);
8396                         if (!mono_error_ok (error)) {
8397                                 g_free (name);
8398                                 if (!type_is_reference (prop_type))
8399                                         g_free (pparams [0]);
8400                                 goto fail;
8401                         }
8402
8403
8404                         mono_property_set_value (prop, attr, pparams, NULL);
8405                         if (!type_is_reference (prop_type))
8406                                 g_free (pparams [0]);
8407                 }
8408                 g_free (name);
8409         }
8410
8411         free_param_data (method->signature, params);
8412         if (params != params_buf)
8413                 mono_gc_free_fixed (params);
8414
8415         return attr;
8416
8417 fail:
8418         free_param_data (method->signature, params);
8419         if (params != params_buf)
8420                 mono_gc_free_fixed (params);
8421         if (exc)
8422                 mono_raise_exception ((MonoException*)exc);
8423         return NULL;
8424 }
8425         
8426 /*
8427  * mono_reflection_create_custom_attr_data_args:
8428  *
8429  *   Create an array of typed and named arguments from the cattr blob given by DATA.
8430  * TYPED_ARGS and NAMED_ARGS will contain the objects representing the arguments,
8431  * NAMED_ARG_INFO will contain information about the named arguments.
8432  */
8433 void
8434 mono_reflection_create_custom_attr_data_args (MonoImage *image, MonoMethod *method, const guchar *data, guint32 len, MonoArray **typed_args, MonoArray **named_args, CattrNamedArg **named_arg_info, MonoError *error)
8435 {
8436         MonoArray *typedargs, *namedargs;
8437         MonoClass *attrklass;
8438         MonoDomain *domain;
8439         const char *p = (const char*)data;
8440         const char *named;
8441         guint32 i, j, num_named;
8442         CattrNamedArg *arginfo = NULL;
8443
8444         *typed_args = NULL;
8445         *named_args = NULL;
8446         *named_arg_info = NULL;
8447
8448         mono_error_init (error);
8449
8450         if (!mono_verifier_verify_cattr_content (image, method, data, len, NULL)) {
8451                 mono_error_set_generic_error (error, "System.Reflection", "CustomAttributeFormatException", "Binary format of the specified custom attribute was invalid.");
8452                 return;
8453         }
8454
8455         mono_class_init (method->klass);
8456         
8457         domain = mono_domain_get ();
8458
8459         if (len < 2 || read16 (p) != 0x0001) /* Prolog */
8460                 return;
8461
8462         typedargs = mono_array_new (domain, mono_get_object_class (), mono_method_signature (method)->param_count);
8463         
8464         /* skip prolog */
8465         p += 2;
8466         for (i = 0; i < mono_method_signature (method)->param_count; ++i) {
8467                 MonoObject *obj;
8468                 void *val;
8469
8470                 val = load_cattr_value (image, mono_method_signature (method)->params [i], p, &p, error);
8471                 if (!mono_error_ok (error)) {
8472                         if (!type_is_reference (mono_method_signature (method)->params [i]))
8473                                 g_free (val);
8474                         return;
8475                 }
8476
8477                 obj = type_is_reference (mono_method_signature (method)->params [i]) ? 
8478                         val : mono_value_box (domain, mono_class_from_mono_type (mono_method_signature (method)->params [i]), val);
8479                 mono_array_setref (typedargs, i, obj);
8480
8481                 if (!type_is_reference (mono_method_signature (method)->params [i]))
8482                         g_free (val);
8483         }
8484
8485         named = p;
8486         num_named = read16 (named);
8487         namedargs = mono_array_new (domain, mono_get_object_class (), num_named);
8488         named += 2;
8489         attrklass = method->klass;
8490
8491         arginfo = g_new0 (CattrNamedArg, num_named);
8492         *named_arg_info = arginfo;
8493
8494         for (j = 0; j < num_named; j++) {
8495                 gint name_len;
8496                 char *name, named_type, data_type;
8497                 named_type = *named++;
8498                 data_type = *named++; /* type of data */
8499                 if (data_type == MONO_TYPE_SZARRAY)
8500                         data_type = *named++;
8501                 if (data_type == MONO_TYPE_ENUM) {
8502                         gint type_len;
8503                         char *type_name;
8504                         type_len = mono_metadata_decode_blob_size (named, &named);
8505                         if (ADDP_IS_GREATER_OR_OVF ((const guchar*)named, type_len, data + len))
8506                                 goto fail;
8507
8508                         type_name = g_malloc (type_len + 1);
8509                         memcpy (type_name, named, type_len);
8510                         type_name [type_len] = 0;
8511                         named += type_len;
8512                         /* FIXME: lookup the type and check type consistency */
8513                         g_free (type_name);
8514                 }
8515                 name_len = mono_metadata_decode_blob_size (named, &named);
8516                 if (ADDP_IS_GREATER_OR_OVF ((const guchar*)named, name_len, data + len))
8517                         goto fail;
8518                 name = g_malloc (name_len + 1);
8519                 memcpy (name, named, name_len);
8520                 name [name_len] = 0;
8521                 named += name_len;
8522                 if (named_type == 0x53) {
8523                         MonoObject *obj;
8524                         MonoClassField *field = mono_class_get_field_from_name (attrklass, name);
8525                         void *val;
8526
8527                         if (!field) {
8528                                 g_free (name);
8529                                 goto fail;
8530                         }
8531
8532                         arginfo [j].type = field->type;
8533                         arginfo [j].field = field;
8534
8535                         val = load_cattr_value (image, field->type, named, &named, error);
8536                         if (!mono_error_ok (error)) {
8537                                 if (!type_is_reference (field->type))
8538                                         g_free (val);
8539                                 g_free (name);
8540                                 return;
8541                         }
8542
8543                         obj = type_is_reference (field->type) ? val : mono_value_box (domain, mono_class_from_mono_type (field->type), val);
8544                         mono_array_setref (namedargs, j, obj);
8545                         if (!type_is_reference (field->type))
8546                                 g_free (val);
8547                 } else if (named_type == 0x54) {
8548                         MonoObject *obj;
8549                         MonoType *prop_type;
8550                         MonoProperty *prop = mono_class_get_property_from_name (attrklass, name);
8551                         void *val;
8552
8553                         if (!prop || !prop->set) {
8554                                 g_free (name);
8555                                 goto fail;
8556                         }
8557
8558                         prop_type = prop->get? mono_method_signature (prop->get)->ret :
8559                              mono_method_signature (prop->set)->params [mono_method_signature (prop->set)->param_count - 1];
8560
8561                         arginfo [j].type = prop_type;
8562                         arginfo [j].prop = prop;
8563
8564                         val = load_cattr_value (image, prop_type, named, &named, error);
8565                         if (!mono_error_ok (error)) {
8566                                 if (!type_is_reference (prop_type))
8567                                         g_free (val);
8568                                 g_free (name);
8569                                 return;
8570                         }
8571
8572                         obj = type_is_reference (prop_type) ? val : mono_value_box (domain, mono_class_from_mono_type (prop_type), val);
8573                         mono_array_setref (namedargs, j, obj);
8574                         if (!type_is_reference (prop_type))
8575                                 g_free (val);
8576                 }
8577                 g_free (name);
8578         }
8579
8580         *typed_args = typedargs;
8581         *named_args = namedargs;
8582         return;
8583 fail:
8584         mono_error_set_generic_error (error, "System.Reflection", "CustomAttributeFormatException", "Binary format of the specified custom attribute was invalid.");
8585         g_free (arginfo);
8586         *named_arg_info = NULL;
8587 }
8588
8589 void
8590 mono_reflection_resolve_custom_attribute_data (MonoReflectionMethod *ref_method, MonoReflectionAssembly *assembly, gpointer data, guint32 len, MonoArray **ctor_args, MonoArray **named_args)
8591 {
8592         MonoDomain *domain;
8593         MonoArray *typedargs, *namedargs;
8594         MonoImage *image;
8595         MonoMethod *method;
8596         CattrNamedArg *arginfo = NULL;
8597         MonoError error;
8598         int i;
8599
8600         *ctor_args = NULL;
8601         *named_args = NULL;
8602
8603         if (len == 0)
8604                 return;
8605
8606         image = assembly->assembly->image;
8607         method = ref_method->method;
8608         domain = mono_object_domain (ref_method);
8609
8610         if (!mono_class_init (method->klass))
8611                 mono_raise_exception (mono_class_get_exception_for_failure (method->klass));
8612
8613         mono_reflection_create_custom_attr_data_args (image, method, data, len, &typedargs, &namedargs, &arginfo, &error);
8614         if (!mono_error_ok (&error))
8615                 mono_error_raise_exception (&error);
8616         if (mono_loader_get_last_error ())
8617                 mono_raise_exception (mono_loader_error_prepare_exception (mono_loader_get_last_error ()));
8618
8619         if (!typedargs || !namedargs) {
8620                 g_free (arginfo);
8621                 return;
8622         }
8623
8624         for (i = 0; i < mono_method_signature (method)->param_count; ++i) {
8625                 MonoObject *obj = mono_array_get (typedargs, MonoObject*, i);
8626                 MonoObject *typedarg;
8627
8628                 typedarg = create_cattr_typed_arg (mono_method_signature (method)->params [i], obj);
8629                 mono_array_setref (typedargs, i, typedarg);
8630         }
8631
8632         for (i = 0; i < mono_array_length (namedargs); ++i) {
8633                 MonoObject *obj = mono_array_get (namedargs, MonoObject*, i);
8634                 MonoObject *typedarg, *namedarg, *minfo;
8635
8636                 if (arginfo [i].prop)
8637                         minfo = (MonoObject*)mono_property_get_object (domain, NULL, arginfo [i].prop);
8638                 else
8639                         minfo = (MonoObject*)mono_field_get_object (domain, NULL, arginfo [i].field);
8640
8641                 typedarg = create_cattr_typed_arg (arginfo [i].type, obj);
8642                 namedarg = create_cattr_named_arg (minfo, typedarg);
8643
8644                 mono_array_setref (namedargs, i, namedarg);
8645         }
8646
8647         *ctor_args = typedargs;
8648         *named_args = namedargs;
8649         g_free (arginfo);
8650 }
8651
8652 static MonoObject*
8653 create_custom_attr_data (MonoImage *image, MonoCustomAttrEntry *cattr)
8654 {
8655         static MonoMethod *ctor;
8656         MonoDomain *domain;
8657         MonoObject *attr;
8658         void *params [4];
8659
8660         g_assert (image->assembly);
8661
8662         if (!ctor)
8663                 ctor = mono_class_get_method_from_name (mono_defaults.customattribute_data_class, ".ctor", 4);
8664
8665         domain = mono_domain_get ();
8666         attr = mono_object_new (domain, mono_defaults.customattribute_data_class);
8667         params [0] = mono_method_get_object (domain, cattr->ctor, NULL);
8668         params [1] = mono_assembly_get_object (domain, image->assembly);
8669         params [2] = (gpointer)&cattr->data;
8670         params [3] = &cattr->data_size;
8671         mono_runtime_invoke (ctor, attr, params, NULL);
8672         return attr;
8673 }
8674
8675 static MonoArray*
8676 mono_custom_attrs_construct_by_type (MonoCustomAttrInfo *cinfo, MonoClass *attr_klass, MonoError *error)
8677 {
8678         MonoArray *result;
8679         MonoObject *attr;
8680         int i, n;
8681
8682         mono_error_init (error);
8683
8684         n = 0;
8685         for (i = 0; i < cinfo->num_attrs; ++i) {
8686                 if (!attr_klass || mono_class_is_assignable_from (attr_klass, cinfo->attrs [i].ctor->klass))
8687                         n ++;
8688         }
8689
8690         result = mono_array_new_cached (mono_domain_get (), mono_defaults.attribute_class, n);
8691         n = 0;
8692         for (i = 0; i < cinfo->num_attrs; ++i) {
8693                 if (!cinfo->attrs [i].ctor)
8694                         /* The cattr type is not finished yet */
8695                         /* We should include the type name but cinfo doesn't contain it */
8696                         mono_raise_exception (mono_get_exception_type_load (NULL, NULL));
8697                 if (!attr_klass || mono_class_is_assignable_from (attr_klass, cinfo->attrs [i].ctor->klass)) {
8698                         attr = create_custom_attr (cinfo->image, cinfo->attrs [i].ctor, cinfo->attrs [i].data, cinfo->attrs [i].data_size, error);
8699                         if (!mono_error_ok (error))
8700                                 return result;
8701                         mono_array_setref (result, n, attr);
8702                         n ++;
8703                 }
8704         }
8705         return result;
8706 }
8707
8708 MonoArray*
8709 mono_custom_attrs_construct (MonoCustomAttrInfo *cinfo)
8710 {
8711         MonoError error;
8712         MonoArray *result = mono_custom_attrs_construct_by_type (cinfo, NULL, &error);
8713         g_assert (mono_error_ok (&error)); /*FIXME proper error handling*/
8714
8715         return result;
8716 }
8717
8718 static MonoArray*
8719 mono_custom_attrs_data_construct (MonoCustomAttrInfo *cinfo)
8720 {
8721         MonoArray *result;
8722         MonoObject *attr;
8723         int i;
8724         
8725         result = mono_array_new (mono_domain_get (), mono_defaults.customattribute_data_class, cinfo->num_attrs);
8726         for (i = 0; i < cinfo->num_attrs; ++i) {
8727                 attr = create_custom_attr_data (cinfo->image, &cinfo->attrs [i]);
8728                 mono_array_setref (result, i, attr);
8729         }
8730         return result;
8731 }
8732
8733 /**
8734  * mono_custom_attrs_from_index:
8735  *
8736  * Returns: NULL if no attributes are found or if a loading error occurs.
8737  */
8738 MonoCustomAttrInfo*
8739 mono_custom_attrs_from_index (MonoImage *image, guint32 idx)
8740 {
8741         guint32 mtoken, i, len;
8742         guint32 cols [MONO_CUSTOM_ATTR_SIZE];
8743         MonoTableInfo *ca;
8744         MonoCustomAttrInfo *ainfo;
8745         GList *tmp, *list = NULL;
8746         const char *data;
8747         MonoCustomAttrEntry* attr;
8748
8749         ca = &image->tables [MONO_TABLE_CUSTOMATTRIBUTE];
8750
8751         i = mono_metadata_custom_attrs_from_index (image, idx);
8752         if (!i)
8753                 return NULL;
8754         i --;
8755         while (i < ca->rows) {
8756                 if (mono_metadata_decode_row_col (ca, i, MONO_CUSTOM_ATTR_PARENT) != idx)
8757                         break;
8758                 list = g_list_prepend (list, GUINT_TO_POINTER (i));
8759                 ++i;
8760         }
8761         len = g_list_length (list);
8762         if (!len)
8763                 return NULL;
8764         ainfo = g_malloc0 (MONO_SIZEOF_CUSTOM_ATTR_INFO + sizeof (MonoCustomAttrEntry) * len);
8765         ainfo->num_attrs = len;
8766         ainfo->image = image;
8767         for (i = len, tmp = list; i != 0; --i, tmp = tmp->next) {
8768                 mono_metadata_decode_row (ca, GPOINTER_TO_UINT (tmp->data), cols, MONO_CUSTOM_ATTR_SIZE);
8769                 mtoken = cols [MONO_CUSTOM_ATTR_TYPE] >> MONO_CUSTOM_ATTR_TYPE_BITS;
8770                 switch (cols [MONO_CUSTOM_ATTR_TYPE] & MONO_CUSTOM_ATTR_TYPE_MASK) {
8771                 case MONO_CUSTOM_ATTR_TYPE_METHODDEF:
8772                         mtoken |= MONO_TOKEN_METHOD_DEF;
8773                         break;
8774                 case MONO_CUSTOM_ATTR_TYPE_MEMBERREF:
8775                         mtoken |= MONO_TOKEN_MEMBER_REF;
8776                         break;
8777                 default:
8778                         g_error ("Unknown table for custom attr type %08x", cols [MONO_CUSTOM_ATTR_TYPE]);
8779                         break;
8780                 }
8781                 attr = &ainfo->attrs [i - 1];
8782                 attr->ctor = mono_get_method (image, mtoken, NULL);
8783                 if (!attr->ctor) {
8784                         g_warning ("Can't find custom attr constructor image: %s mtoken: 0x%08x", image->name, mtoken);
8785                         g_list_free (list);
8786                         g_free (ainfo);
8787                         return NULL;
8788                 }
8789
8790                 if (!mono_verifier_verify_cattr_blob (image, cols [MONO_CUSTOM_ATTR_VALUE], NULL)) {
8791                         /*FIXME raising an exception here doesn't make any sense*/
8792                         g_warning ("Invalid custom attribute blob on image %s for index %x", image->name, idx);
8793                         g_list_free (list);
8794                         g_free (ainfo);
8795                         return NULL;
8796                 }
8797                 data = mono_metadata_blob_heap (image, cols [MONO_CUSTOM_ATTR_VALUE]);
8798                 attr->data_size = mono_metadata_decode_value (data, &data);
8799                 attr->data = (guchar*)data;
8800         }
8801         g_list_free (list);
8802
8803         return ainfo;
8804 }
8805
8806 MonoCustomAttrInfo*
8807 mono_custom_attrs_from_method (MonoMethod *method)
8808 {
8809         guint32 idx;
8810
8811         /*
8812          * An instantiated method has the same cattrs as the generic method definition.
8813          *
8814          * LAMESPEC: The .NET SRE throws an exception for instantiations of generic method builders
8815          *           Note that this stanza is not necessary for non-SRE types, but it's a micro-optimization
8816          */
8817         if (method->is_inflated)
8818                 method = ((MonoMethodInflated *) method)->declaring;
8819         
8820         if (method_is_dynamic (method) || image_is_dynamic (method->klass->image))
8821                 return lookup_custom_attr (method->klass->image, method);
8822
8823         if (!method->token)
8824                 /* Synthetic methods */
8825                 return NULL;
8826
8827         idx = mono_method_get_index (method);
8828         idx <<= MONO_CUSTOM_ATTR_BITS;
8829         idx |= MONO_CUSTOM_ATTR_METHODDEF;
8830         return mono_custom_attrs_from_index (method->klass->image, idx);
8831 }
8832
8833 MonoCustomAttrInfo*
8834 mono_custom_attrs_from_class (MonoClass *klass)
8835 {
8836         guint32 idx;
8837
8838         if (klass->generic_class)
8839                 klass = klass->generic_class->container_class;
8840
8841         if (image_is_dynamic (klass->image))
8842                 return lookup_custom_attr (klass->image, klass);
8843
8844         if (klass->byval_arg.type == MONO_TYPE_VAR || klass->byval_arg.type == MONO_TYPE_MVAR) {
8845                 idx = mono_metadata_token_index (klass->sizes.generic_param_token);
8846                 idx <<= MONO_CUSTOM_ATTR_BITS;
8847                 idx |= MONO_CUSTOM_ATTR_GENERICPAR;
8848         } else {
8849                 idx = mono_metadata_token_index (klass->type_token);
8850                 idx <<= MONO_CUSTOM_ATTR_BITS;
8851                 idx |= MONO_CUSTOM_ATTR_TYPEDEF;
8852         }
8853         return mono_custom_attrs_from_index (klass->image, idx);
8854 }
8855
8856 MonoCustomAttrInfo*
8857 mono_custom_attrs_from_assembly (MonoAssembly *assembly)
8858 {
8859         guint32 idx;
8860         
8861         if (image_is_dynamic (assembly->image))
8862                 return lookup_custom_attr (assembly->image, assembly);
8863         idx = 1; /* there is only one assembly */
8864         idx <<= MONO_CUSTOM_ATTR_BITS;
8865         idx |= MONO_CUSTOM_ATTR_ASSEMBLY;
8866         return mono_custom_attrs_from_index (assembly->image, idx);
8867 }
8868
8869 static MonoCustomAttrInfo*
8870 mono_custom_attrs_from_module (MonoImage *image)
8871 {
8872         guint32 idx;
8873         
8874         if (image_is_dynamic (image))
8875                 return lookup_custom_attr (image, image);
8876         idx = 1; /* there is only one module */
8877         idx <<= MONO_CUSTOM_ATTR_BITS;
8878         idx |= MONO_CUSTOM_ATTR_MODULE;
8879         return mono_custom_attrs_from_index (image, idx);
8880 }
8881
8882 MonoCustomAttrInfo*
8883 mono_custom_attrs_from_property (MonoClass *klass, MonoProperty *property)
8884 {
8885         guint32 idx;
8886         
8887         if (image_is_dynamic (klass->image)) {
8888                 property = mono_metadata_get_corresponding_property_from_generic_type_definition (property);
8889                 return lookup_custom_attr (klass->image, property);
8890         }
8891         idx = find_property_index (klass, property);
8892         idx <<= MONO_CUSTOM_ATTR_BITS;
8893         idx |= MONO_CUSTOM_ATTR_PROPERTY;
8894         return mono_custom_attrs_from_index (klass->image, idx);
8895 }
8896
8897 MonoCustomAttrInfo*
8898 mono_custom_attrs_from_event (MonoClass *klass, MonoEvent *event)
8899 {
8900         guint32 idx;
8901         
8902         if (image_is_dynamic (klass->image)) {
8903                 event = mono_metadata_get_corresponding_event_from_generic_type_definition (event);
8904                 return lookup_custom_attr (klass->image, event);
8905         }
8906         idx = find_event_index (klass, event);
8907         idx <<= MONO_CUSTOM_ATTR_BITS;
8908         idx |= MONO_CUSTOM_ATTR_EVENT;
8909         return mono_custom_attrs_from_index (klass->image, idx);
8910 }
8911
8912 MonoCustomAttrInfo*
8913 mono_custom_attrs_from_field (MonoClass *klass, MonoClassField *field)
8914 {
8915         guint32 idx;
8916         if (image_is_dynamic (klass->image)) {
8917                 field = mono_metadata_get_corresponding_field_from_generic_type_definition (field);
8918                 return lookup_custom_attr (klass->image, field);
8919         }
8920         idx = find_field_index (klass, field);
8921         idx <<= MONO_CUSTOM_ATTR_BITS;
8922         idx |= MONO_CUSTOM_ATTR_FIELDDEF;
8923         return mono_custom_attrs_from_index (klass->image, idx);
8924 }
8925
8926 /**
8927  * mono_custom_attrs_from_param:
8928  * @method: handle to the method that we want to retrieve custom parameter information from
8929  * @param: parameter number, where zero represent the return value, and one is the first parameter in the method
8930  *
8931  * The result must be released with mono_custom_attrs_free().
8932  *
8933  * Returns: the custom attribute object for the specified parameter, or NULL if there are none.
8934  */
8935 MonoCustomAttrInfo*
8936 mono_custom_attrs_from_param (MonoMethod *method, guint32 param)
8937 {
8938         MonoTableInfo *ca;
8939         guint32 i, idx, method_index;
8940         guint32 param_list, param_last, param_pos, found;
8941         MonoImage *image;
8942         MonoReflectionMethodAux *aux;
8943
8944         /*
8945          * An instantiated method has the same cattrs as the generic method definition.
8946          *
8947          * LAMESPEC: The .NET SRE throws an exception for instantiations of generic method builders
8948          *           Note that this stanza is not necessary for non-SRE types, but it's a micro-optimization
8949          */
8950         if (method->is_inflated)
8951                 method = ((MonoMethodInflated *) method)->declaring;
8952
8953         if (image_is_dynamic (method->klass->image)) {
8954                 MonoCustomAttrInfo *res, *ainfo;
8955                 int size;
8956
8957                 aux = g_hash_table_lookup (((MonoDynamicImage*)method->klass->image)->method_aux_hash, method);
8958                 if (!aux || !aux->param_cattr)
8959                         return NULL;
8960
8961                 /* Need to copy since it will be freed later */
8962                 ainfo = aux->param_cattr [param];
8963                 if (!ainfo)
8964                         return NULL;
8965                 size = MONO_SIZEOF_CUSTOM_ATTR_INFO + sizeof (MonoCustomAttrEntry) * ainfo->num_attrs;
8966                 res = g_malloc0 (size);
8967                 memcpy (res, ainfo, size);
8968                 return res;
8969         }
8970
8971         image = method->klass->image;
8972         method_index = mono_method_get_index (method);
8973         if (!method_index)
8974                 return NULL;
8975         ca = &image->tables [MONO_TABLE_METHOD];
8976
8977         param_list = mono_metadata_decode_row_col (ca, method_index - 1, MONO_METHOD_PARAMLIST);
8978         if (method_index == ca->rows) {
8979                 ca = &image->tables [MONO_TABLE_PARAM];
8980                 param_last = ca->rows + 1;
8981         } else {
8982                 param_last = mono_metadata_decode_row_col (ca, method_index, MONO_METHOD_PARAMLIST);
8983                 ca = &image->tables [MONO_TABLE_PARAM];
8984         }
8985         found = FALSE;
8986         for (i = param_list; i < param_last; ++i) {
8987                 param_pos = mono_metadata_decode_row_col (ca, i - 1, MONO_PARAM_SEQUENCE);
8988                 if (param_pos == param) {
8989                         found = TRUE;
8990                         break;
8991                 }
8992         }
8993         if (!found)
8994                 return NULL;
8995         idx = i;
8996         idx <<= MONO_CUSTOM_ATTR_BITS;
8997         idx |= MONO_CUSTOM_ATTR_PARAMDEF;
8998         return mono_custom_attrs_from_index (image, idx);
8999 }
9000
9001 gboolean
9002 mono_custom_attrs_has_attr (MonoCustomAttrInfo *ainfo, MonoClass *attr_klass)
9003 {
9004         int i;
9005         MonoClass *klass;
9006         for (i = 0; i < ainfo->num_attrs; ++i) {
9007                 klass = ainfo->attrs [i].ctor->klass;
9008                 if (mono_class_has_parent (klass, attr_klass) || (MONO_CLASS_IS_INTERFACE (attr_klass) && mono_class_is_assignable_from (attr_klass, klass)))
9009                         return TRUE;
9010         }
9011         return FALSE;
9012 }
9013
9014 MonoObject*
9015 mono_custom_attrs_get_attr (MonoCustomAttrInfo *ainfo, MonoClass *attr_klass)
9016 {
9017         MonoError error;
9018         MonoObject *res = mono_custom_attrs_get_attr_checked (ainfo, attr_klass, &error);
9019         g_assert (mono_error_ok (&error)); /*FIXME proper error handling*/
9020         return res;
9021 }
9022
9023 MonoObject*
9024 mono_custom_attrs_get_attr_checked (MonoCustomAttrInfo *ainfo, MonoClass *attr_klass, MonoError *error)
9025 {
9026         int i, attr_index;
9027         MonoClass *klass;
9028         MonoArray *attrs;
9029
9030         mono_error_init (error);
9031
9032         attr_index = -1;
9033         for (i = 0; i < ainfo->num_attrs; ++i) {
9034                 klass = ainfo->attrs [i].ctor->klass;
9035                 if (mono_class_has_parent (klass, attr_klass)) {
9036                         attr_index = i;
9037                         break;
9038                 }
9039         }
9040         if (attr_index == -1)
9041                 return NULL;
9042
9043         attrs = mono_custom_attrs_construct_by_type (ainfo, NULL, error);
9044         if (!mono_error_ok (error))
9045                 return NULL;
9046         return mono_array_get (attrs, MonoObject*, attr_index);
9047 }
9048
9049 /*
9050  * mono_reflection_get_custom_attrs_info:
9051  * @obj: a reflection object handle
9052  *
9053  * Return the custom attribute info for attributes defined for the
9054  * reflection handle @obj. The objects.
9055  *
9056  * FIXME this function leaks like a sieve for SRE objects.
9057  */
9058 MonoCustomAttrInfo*
9059 mono_reflection_get_custom_attrs_info (MonoObject *obj)
9060 {
9061         MonoClass *klass;
9062         MonoCustomAttrInfo *cinfo = NULL;
9063         
9064         klass = obj->vtable->klass;
9065         if (klass == mono_defaults.monotype_class) {
9066                 MonoType *type = mono_reflection_type_get_handle ((MonoReflectionType *)obj);
9067                 klass = mono_class_from_mono_type (type);
9068                 /*We cannot mono_class_init the class from which we'll load the custom attributes since this must work with broken types.*/
9069                 cinfo = mono_custom_attrs_from_class (klass);
9070         } else if (strcmp ("Assembly", klass->name) == 0 || strcmp ("MonoAssembly", klass->name) == 0) {
9071                 MonoReflectionAssembly *rassembly = (MonoReflectionAssembly*)obj;
9072                 cinfo = mono_custom_attrs_from_assembly (rassembly->assembly);
9073         } else if (strcmp ("Module", klass->name) == 0 || strcmp ("MonoModule", klass->name) == 0) {
9074                 MonoReflectionModule *module = (MonoReflectionModule*)obj;
9075                 cinfo = mono_custom_attrs_from_module (module->image);
9076         } else if (strcmp ("MonoProperty", klass->name) == 0) {
9077                 MonoReflectionProperty *rprop = (MonoReflectionProperty*)obj;
9078                 cinfo = mono_custom_attrs_from_property (rprop->property->parent, rprop->property);
9079         } else if (strcmp ("MonoEvent", klass->name) == 0) {
9080                 MonoReflectionMonoEvent *revent = (MonoReflectionMonoEvent*)obj;
9081                 cinfo = mono_custom_attrs_from_event (revent->event->parent, revent->event);
9082         } else if (strcmp ("MonoField", klass->name) == 0) {
9083                 MonoReflectionField *rfield = (MonoReflectionField*)obj;
9084                 cinfo = mono_custom_attrs_from_field (rfield->field->parent, rfield->field);
9085         } else if ((strcmp ("MonoMethod", klass->name) == 0) || (strcmp ("MonoCMethod", klass->name) == 0)) {
9086                 MonoReflectionMethod *rmethod = (MonoReflectionMethod*)obj;
9087                 cinfo = mono_custom_attrs_from_method (rmethod->method);
9088         } else if ((strcmp ("MonoGenericMethod", klass->name) == 0) || (strcmp ("MonoGenericCMethod", klass->name) == 0)) {
9089                 MonoReflectionMethod *rmethod = (MonoReflectionMethod*)obj;
9090                 cinfo = mono_custom_attrs_from_method (rmethod->method);
9091         } else if (strcmp ("ParameterInfo", klass->name) == 0 || strcmp ("MonoParameterInfo", klass->name) == 0) {
9092                 MonoReflectionParameter *param = (MonoReflectionParameter*)obj;
9093                 MonoClass *member_class = mono_object_class (param->MemberImpl);
9094                 if (mono_class_is_reflection_method_or_constructor (member_class)) {
9095                         MonoReflectionMethod *rmethod = (MonoReflectionMethod*)param->MemberImpl;
9096                         cinfo = mono_custom_attrs_from_param (rmethod->method, param->PositionImpl + 1);
9097                 } else if (is_sr_mono_property (member_class)) {
9098                         MonoReflectionProperty *prop = (MonoReflectionProperty *)param->MemberImpl;
9099                         MonoMethod *method;
9100                         if (!(method = prop->property->get))
9101                                 method = prop->property->set;
9102                         g_assert (method);
9103
9104                         cinfo = mono_custom_attrs_from_param (method, param->PositionImpl + 1);
9105                 } 
9106 #ifndef DISABLE_REFLECTION_EMIT
9107                 else if (is_sre_method_on_tb_inst (member_class)) {/*XXX This is a workaround for Compiler Context*/
9108                         MonoMethod *method = mono_reflection_method_on_tb_inst_get_handle ((MonoReflectionMethodOnTypeBuilderInst*)param->MemberImpl);
9109                         cinfo = mono_custom_attrs_from_param (method, param->PositionImpl + 1);
9110                 } else if (is_sre_ctor_on_tb_inst (member_class)) { /*XX This is a workaround for Compiler Context*/
9111                         MonoReflectionCtorOnTypeBuilderInst *c = (MonoReflectionCtorOnTypeBuilderInst*)param->MemberImpl;
9112                         MonoMethod *method = NULL;
9113                         if (is_sre_ctor_builder (mono_object_class (c->cb)))
9114                                 method = ((MonoReflectionCtorBuilder *)c->cb)->mhandle;
9115                         else if (is_sr_mono_cmethod (mono_object_class (c->cb)))
9116                                 method = ((MonoReflectionMethod *)c->cb)->method;
9117                         else
9118                                 g_error ("mono_reflection_get_custom_attrs_info:: can't handle a CTBI with base_method of type %s", mono_type_get_full_name (member_class));
9119
9120                         cinfo = mono_custom_attrs_from_param (method, param->PositionImpl + 1);
9121                 } 
9122 #endif
9123                 else {
9124                         char *type_name = mono_type_get_full_name (member_class);
9125                         char *msg = g_strdup_printf ("Custom attributes on a ParamInfo with member %s are not supported", type_name);
9126                         MonoException *ex = mono_get_exception_not_supported  (msg);
9127                         g_free (type_name);
9128                         g_free (msg);
9129                         mono_raise_exception (ex);
9130                 }
9131         } else if (strcmp ("AssemblyBuilder", klass->name) == 0) {
9132                 MonoReflectionAssemblyBuilder *assemblyb = (MonoReflectionAssemblyBuilder*)obj;
9133                 cinfo = mono_custom_attrs_from_builders (NULL, assemblyb->assembly.assembly->image, assemblyb->cattrs);
9134         } else if (strcmp ("TypeBuilder", klass->name) == 0) {
9135                 MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder*)obj;
9136                 cinfo = mono_custom_attrs_from_builders (NULL, &tb->module->dynamic_image->image, tb->cattrs);
9137         } else if (strcmp ("ModuleBuilder", klass->name) == 0) {
9138                 MonoReflectionModuleBuilder *mb = (MonoReflectionModuleBuilder*)obj;
9139                 cinfo = mono_custom_attrs_from_builders (NULL, &mb->dynamic_image->image, mb->cattrs);
9140         } else if (strcmp ("ConstructorBuilder", klass->name) == 0) {
9141                 MonoReflectionCtorBuilder *cb = (MonoReflectionCtorBuilder*)obj;
9142                 cinfo = mono_custom_attrs_from_builders (NULL, cb->mhandle->klass->image, cb->cattrs);
9143         } else if (strcmp ("MethodBuilder", klass->name) == 0) {
9144                 MonoReflectionMethodBuilder *mb = (MonoReflectionMethodBuilder*)obj;
9145                 cinfo = mono_custom_attrs_from_builders (NULL, mb->mhandle->klass->image, mb->cattrs);
9146         } else if (strcmp ("FieldBuilder", klass->name) == 0) {
9147                 MonoReflectionFieldBuilder *fb = (MonoReflectionFieldBuilder*)obj;
9148                 cinfo = mono_custom_attrs_from_builders (NULL, &((MonoReflectionTypeBuilder*)fb->typeb)->module->dynamic_image->image, fb->cattrs);
9149         } else if (strcmp ("MonoGenericClass", klass->name) == 0) {
9150                 MonoReflectionGenericClass *gclass = (MonoReflectionGenericClass*)obj;
9151                 cinfo = mono_reflection_get_custom_attrs_info ((MonoObject*)gclass->generic_type);
9152         } else { /* handle other types here... */
9153                 g_error ("get custom attrs not yet supported for %s", klass->name);
9154         }
9155
9156         return cinfo;
9157 }
9158
9159 /*
9160  * mono_reflection_get_custom_attrs_by_type:
9161  * @obj: a reflection object handle
9162  *
9163  * Return an array with all the custom attributes defined of the
9164  * reflection handle @obj. If @attr_klass is non-NULL, only custom attributes 
9165  * of that type are returned. The objects are fully build. Return NULL if a loading error
9166  * occurs.
9167  */
9168 MonoArray*
9169 mono_reflection_get_custom_attrs_by_type (MonoObject *obj, MonoClass *attr_klass, MonoError *error)
9170 {
9171         MonoArray *result;
9172         MonoCustomAttrInfo *cinfo;
9173
9174         mono_error_init (error);
9175
9176         cinfo = mono_reflection_get_custom_attrs_info (obj);
9177         if (cinfo) {
9178                 result = mono_custom_attrs_construct_by_type (cinfo, attr_klass, error);
9179                 if (!cinfo->cached)
9180                         mono_custom_attrs_free (cinfo);
9181         } else {
9182                 /* FIXME add MonoError to mono_reflection_get_custom_attrs_info */
9183                 if (mono_loader_get_last_error ())
9184                         return NULL;
9185                 result = mono_array_new_cached (mono_domain_get (), mono_defaults.attribute_class, 0);
9186         }
9187
9188         return result;
9189 }
9190
9191 /*
9192  * mono_reflection_get_custom_attrs:
9193  * @obj: a reflection object handle
9194  *
9195  * Return an array with all the custom attributes defined of the
9196  * reflection handle @obj. The objects are fully build. Return NULL if a loading error
9197  * occurs.
9198  */
9199 MonoArray*
9200 mono_reflection_get_custom_attrs (MonoObject *obj)
9201 {
9202         MonoError error;
9203
9204         return mono_reflection_get_custom_attrs_by_type (obj, NULL, &error);
9205 }
9206
9207 /*
9208  * mono_reflection_get_custom_attrs_data:
9209  * @obj: a reflection obj handle
9210  *
9211  * Returns an array of System.Reflection.CustomAttributeData,
9212  * which include information about attributes reflected on
9213  * types loaded using the Reflection Only methods
9214  */
9215 MonoArray*
9216 mono_reflection_get_custom_attrs_data (MonoObject *obj)
9217 {
9218         MonoArray *result;
9219         MonoCustomAttrInfo *cinfo;
9220
9221         cinfo = mono_reflection_get_custom_attrs_info (obj);
9222         if (cinfo) {
9223                 result = mono_custom_attrs_data_construct (cinfo);
9224                 if (!cinfo->cached)
9225                         mono_custom_attrs_free (cinfo);
9226         } else
9227                 result = mono_array_new (mono_domain_get (), mono_defaults.customattribute_data_class, 0);
9228
9229         return result;
9230 }
9231
9232 static MonoReflectionType*
9233 mono_reflection_type_get_underlying_system_type (MonoReflectionType* t)
9234 {
9235         static MonoMethod *method_get_underlying_system_type = NULL;
9236         MonoMethod *usertype_method;
9237
9238         if (!method_get_underlying_system_type)
9239                 method_get_underlying_system_type = mono_class_get_method_from_name (mono_defaults.systemtype_class, "get_UnderlyingSystemType", 0);
9240         usertype_method = mono_object_get_virtual_method ((MonoObject *) t, method_get_underlying_system_type);
9241         return (MonoReflectionType *) mono_runtime_invoke (usertype_method, t, NULL, NULL);
9242 }
9243
9244
9245 static gboolean
9246 is_corlib_type (MonoClass *class)
9247 {
9248         return class->image == mono_defaults.corlib;
9249 }
9250
9251 #define check_corlib_type_cached(_class, _namespace, _name) do { \
9252         static MonoClass *cached_class; \
9253         if (cached_class) \
9254                 return cached_class == _class; \
9255         if (is_corlib_type (_class) && !strcmp (_name, _class->name) && !strcmp (_namespace, _class->name_space)) { \
9256                 cached_class = _class; \
9257                 return TRUE; \
9258         } \
9259         return FALSE; \
9260 } while (0) \
9261
9262
9263 #ifndef DISABLE_REFLECTION_EMIT
9264 static gboolean
9265 is_sre_array (MonoClass *class)
9266 {
9267         check_corlib_type_cached (class, "System.Reflection.Emit", "ArrayType");
9268 }
9269
9270 static gboolean
9271 is_sre_byref (MonoClass *class)
9272 {
9273         check_corlib_type_cached (class, "System.Reflection.Emit", "ByRefType");
9274 }
9275
9276 static gboolean
9277 is_sre_pointer (MonoClass *class)
9278 {
9279         check_corlib_type_cached (class, "System.Reflection.Emit", "PointerType");
9280 }
9281
9282 static gboolean
9283 is_sre_generic_instance (MonoClass *class)
9284 {
9285         check_corlib_type_cached (class, "System.Reflection", "MonoGenericClass");
9286 }
9287
9288 static gboolean
9289 is_sre_type_builder (MonoClass *class)
9290 {
9291         check_corlib_type_cached (class, "System.Reflection.Emit", "TypeBuilder");
9292 }
9293
9294 static gboolean
9295 is_sre_method_builder (MonoClass *class)
9296 {
9297         check_corlib_type_cached (class, "System.Reflection.Emit", "MethodBuilder");
9298 }
9299
9300 static gboolean
9301 is_sre_ctor_builder (MonoClass *class)
9302 {
9303         check_corlib_type_cached (class, "System.Reflection.Emit", "ConstructorBuilder");
9304 }
9305
9306 static gboolean
9307 is_sre_field_builder (MonoClass *class)
9308 {
9309         check_corlib_type_cached (class, "System.Reflection.Emit", "FieldBuilder");
9310 }
9311
9312 static gboolean
9313 is_sre_method_on_tb_inst (MonoClass *class)
9314 {
9315         check_corlib_type_cached (class, "System.Reflection.Emit", "MethodOnTypeBuilderInst");
9316 }
9317
9318 static gboolean
9319 is_sre_ctor_on_tb_inst (MonoClass *class)
9320 {
9321         check_corlib_type_cached (class, "System.Reflection.Emit", "ConstructorOnTypeBuilderInst");
9322 }
9323
9324 MonoType*
9325 mono_reflection_type_get_handle (MonoReflectionType* ref)
9326 {
9327         MonoClass *class;
9328         if (!ref)
9329                 return NULL;
9330         if (ref->type)
9331                 return ref->type;
9332
9333         if (is_usertype (ref)) {
9334                 ref = mono_reflection_type_get_underlying_system_type (ref);
9335                 if (ref == NULL || is_usertype (ref))
9336                         return NULL;
9337                 if (ref->type)
9338                         return ref->type;
9339         }
9340
9341         class = mono_object_class (ref);
9342
9343         if (is_sre_array (class)) {
9344                 MonoType *res;
9345                 MonoReflectionArrayType *sre_array = (MonoReflectionArrayType*)ref;
9346                 MonoType *base = mono_reflection_type_get_handle (sre_array->element_type);
9347                 g_assert (base);
9348                 if (sre_array->rank == 0) //single dimentional array
9349                         res = &mono_array_class_get (mono_class_from_mono_type (base), 1)->byval_arg;
9350                 else
9351                         res = &mono_bounded_array_class_get (mono_class_from_mono_type (base), sre_array->rank, TRUE)->byval_arg;
9352                 sre_array->type.type = res;
9353                 return res;
9354         } else if (is_sre_byref (class)) {
9355                 MonoType *res;
9356                 MonoReflectionDerivedType *sre_byref = (MonoReflectionDerivedType*)ref;
9357                 MonoType *base = mono_reflection_type_get_handle (sre_byref->element_type);
9358                 g_assert (base);
9359                 res = &mono_class_from_mono_type (base)->this_arg;
9360                 sre_byref->type.type = res;
9361                 return res;
9362         } else if (is_sre_pointer (class)) {
9363                 MonoType *res;
9364                 MonoReflectionDerivedType *sre_pointer = (MonoReflectionDerivedType*)ref;
9365                 MonoType *base = mono_reflection_type_get_handle (sre_pointer->element_type);
9366                 g_assert (base);
9367                 res = &mono_ptr_class_get (base)->byval_arg;
9368                 sre_pointer->type.type = res;
9369                 return res;
9370         } else if (is_sre_generic_instance (class)) {
9371                 MonoType *res, **types;
9372                 MonoReflectionGenericClass *gclass = (MonoReflectionGenericClass*)ref;
9373                 int i, count;
9374
9375                 count = mono_array_length (gclass->type_arguments);
9376                 types = g_new0 (MonoType*, count);
9377                 for (i = 0; i < count; ++i) {
9378                         MonoReflectionType *t = mono_array_get (gclass->type_arguments, gpointer, i);
9379                         types [i] = mono_reflection_type_get_handle (t);
9380                         if (!types[i]) {
9381                                 g_free (types);
9382                                 return NULL;
9383                         }
9384                 }
9385
9386                 res = mono_reflection_bind_generic_parameters (gclass->generic_type, count, types);
9387                 g_free (types);
9388                 g_assert (res);
9389                 gclass->type.type = res;
9390                 return res;
9391         }
9392
9393         g_error ("Cannot handle corlib user type %s", mono_type_full_name (&mono_object_class(ref)->byval_arg));
9394         return NULL;
9395 }
9396
9397
9398
9399 void
9400 mono_reflection_create_unmanaged_type (MonoReflectionType *type)
9401 {
9402         mono_reflection_type_get_handle (type);
9403 }
9404
9405 void
9406 mono_reflection_register_with_runtime (MonoReflectionType *type)
9407 {
9408         MonoType *res = mono_reflection_type_get_handle (type);
9409         MonoDomain *domain = mono_object_domain ((MonoObject*)type);
9410         MonoClass *class;
9411
9412         if (!res)
9413                 mono_raise_exception (mono_get_exception_argument (NULL, "Invalid generic instantiation, one or more arguments are not proper user types"));
9414
9415         class = mono_class_from_mono_type (res);
9416
9417         mono_loader_lock (); /*same locking as mono_type_get_object*/
9418         mono_domain_lock (domain);
9419
9420         if (!image_is_dynamic (class->image)) {
9421                 mono_class_setup_supertypes (class);
9422         } else {
9423                 if (!domain->type_hash)
9424                         domain->type_hash = mono_g_hash_table_new_type ((GHashFunc)mono_metadata_type_hash, 
9425                                         (GCompareFunc)mono_metadata_type_equal, MONO_HASH_VALUE_GC);
9426                 mono_g_hash_table_insert (domain->type_hash, res, type);
9427         }
9428         mono_domain_unlock (domain);
9429         mono_loader_unlock ();
9430 }
9431
9432 /**
9433  * LOCKING: Assumes the loader lock is held.
9434  */
9435 static MonoMethodSignature*
9436 parameters_to_signature (MonoImage *image, MonoArray *parameters) {
9437         MonoMethodSignature *sig;
9438         int count, i;
9439
9440         count = parameters? mono_array_length (parameters): 0;
9441
9442         sig = image_g_malloc0 (image, MONO_SIZEOF_METHOD_SIGNATURE + sizeof (MonoType*) * count);
9443         sig->param_count = count;
9444         sig->sentinelpos = -1; /* FIXME */
9445         for (i = 0; i < count; ++i)
9446                 sig->params [i] = mono_type_array_get_and_resolve (parameters, i);
9447         return sig;
9448 }
9449
9450 /**
9451  * LOCKING: Assumes the loader lock is held.
9452  */
9453 static MonoMethodSignature*
9454 ctor_builder_to_signature (MonoImage *image, MonoReflectionCtorBuilder *ctor) {
9455         MonoMethodSignature *sig;
9456
9457         sig = parameters_to_signature (image, ctor->parameters);
9458         sig->hasthis = ctor->attrs & METHOD_ATTRIBUTE_STATIC? 0: 1;
9459         sig->ret = &mono_defaults.void_class->byval_arg;
9460         return sig;
9461 }
9462
9463 /**
9464  * LOCKING: Assumes the loader lock is held.
9465  */
9466 static MonoMethodSignature*
9467 method_builder_to_signature (MonoImage *image, MonoReflectionMethodBuilder *method) {
9468         MonoMethodSignature *sig;
9469
9470         sig = parameters_to_signature (image, method->parameters);
9471         sig->hasthis = method->attrs & METHOD_ATTRIBUTE_STATIC? 0: 1;
9472         sig->ret = method->rtype? mono_reflection_type_get_handle ((MonoReflectionType*)method->rtype): &mono_defaults.void_class->byval_arg;
9473         sig->generic_param_count = method->generic_params ? mono_array_length (method->generic_params) : 0;
9474         return sig;
9475 }
9476
9477 static MonoMethodSignature*
9478 dynamic_method_to_signature (MonoReflectionDynamicMethod *method) {
9479         MonoMethodSignature *sig;
9480
9481         sig = parameters_to_signature (NULL, method->parameters);
9482         sig->hasthis = method->attrs & METHOD_ATTRIBUTE_STATIC? 0: 1;
9483         sig->ret = method->rtype? mono_reflection_type_get_handle (method->rtype): &mono_defaults.void_class->byval_arg;
9484         sig->generic_param_count = 0;
9485         return sig;
9486 }
9487
9488 static void
9489 get_prop_name_and_type (MonoObject *prop, char **name, MonoType **type)
9490 {
9491         MonoClass *klass = mono_object_class (prop);
9492         if (strcmp (klass->name, "PropertyBuilder") == 0) {
9493                 MonoReflectionPropertyBuilder *pb = (MonoReflectionPropertyBuilder *)prop;
9494                 *name = mono_string_to_utf8 (pb->name);
9495                 *type = mono_reflection_type_get_handle ((MonoReflectionType*)pb->type);
9496         } else {
9497                 MonoReflectionProperty *p = (MonoReflectionProperty *)prop;
9498                 *name = g_strdup (p->property->name);
9499                 if (p->property->get)
9500                         *type = mono_method_signature (p->property->get)->ret;
9501                 else
9502                         *type = mono_method_signature (p->property->set)->params [mono_method_signature (p->property->set)->param_count - 1];
9503         }
9504 }
9505
9506 static void
9507 get_field_name_and_type (MonoObject *field, char **name, MonoType **type)
9508 {
9509         MonoClass *klass = mono_object_class (field);
9510         if (strcmp (klass->name, "FieldBuilder") == 0) {
9511                 MonoReflectionFieldBuilder *fb = (MonoReflectionFieldBuilder *)field;
9512                 *name = mono_string_to_utf8 (fb->name);
9513                 *type = mono_reflection_type_get_handle ((MonoReflectionType*)fb->type);
9514         } else {
9515                 MonoReflectionField *f = (MonoReflectionField *)field;
9516                 *name = g_strdup (mono_field_get_name (f->field));
9517                 *type = f->field->type;
9518         }
9519 }
9520
9521 #else /* DISABLE_REFLECTION_EMIT */
9522
9523 void
9524 mono_reflection_register_with_runtime (MonoReflectionType *type)
9525 {
9526         /* This is empty */
9527 }
9528
9529 static gboolean
9530 is_sre_type_builder (MonoClass *class)
9531 {
9532         return FALSE;
9533 }
9534
9535 static gboolean
9536 is_sre_generic_instance (MonoClass *class)
9537 {
9538         return FALSE;
9539 }
9540
9541 static void
9542 init_type_builder_generics (MonoObject *type)
9543 {
9544 }
9545
9546 #endif /* !DISABLE_REFLECTION_EMIT */
9547
9548
9549 static gboolean
9550 is_sr_mono_field (MonoClass *class)
9551 {
9552         check_corlib_type_cached (class, "System.Reflection", "MonoField");
9553 }
9554
9555 static gboolean
9556 is_sr_mono_property (MonoClass *class)
9557 {
9558         check_corlib_type_cached (class, "System.Reflection", "MonoProperty");
9559 }
9560
9561 static gboolean
9562 is_sr_mono_method (MonoClass *class)
9563 {
9564         check_corlib_type_cached (class, "System.Reflection", "MonoMethod");
9565 }
9566
9567 static gboolean
9568 is_sr_mono_cmethod (MonoClass *class)
9569 {
9570         check_corlib_type_cached (class, "System.Reflection", "MonoCMethod");
9571 }
9572
9573 static gboolean
9574 is_sr_mono_generic_method (MonoClass *class)
9575 {
9576         check_corlib_type_cached (class, "System.Reflection", "MonoGenericMethod");
9577 }
9578
9579 static gboolean
9580 is_sr_mono_generic_cmethod (MonoClass *class)
9581 {
9582         check_corlib_type_cached (class, "System.Reflection", "MonoGenericCMethod");
9583 }
9584
9585 gboolean
9586 mono_class_is_reflection_method_or_constructor (MonoClass *class)
9587 {
9588         return is_sr_mono_method (class) || is_sr_mono_cmethod (class) || is_sr_mono_generic_method (class) || is_sr_mono_generic_cmethod (class);
9589 }
9590
9591 static gboolean
9592 is_usertype (MonoReflectionType *ref)
9593 {
9594         MonoClass *class = mono_object_class (ref);
9595         return class->image != mono_defaults.corlib || strcmp ("TypeDelegator", class->name) == 0;
9596 }
9597
9598 static MonoReflectionType*
9599 mono_reflection_type_resolve_user_types (MonoReflectionType *type)
9600 {
9601         if (!type || type->type)
9602                 return type;
9603
9604         if (is_usertype (type)) {
9605                 type = mono_reflection_type_get_underlying_system_type (type);
9606                 if (is_usertype (type))
9607                         mono_raise_exception (mono_get_exception_not_supported ("User defined subclasses of System.Type are not yet supported22"));
9608         }
9609
9610         return type;
9611 }
9612 /*
9613  * Encode a value in a custom attribute stream of bytes.
9614  * The value to encode is either supplied as an object in argument val
9615  * (valuetypes are boxed), or as a pointer to the data in the
9616  * argument argval.
9617  * @type represents the type of the value
9618  * @buffer is the start of the buffer
9619  * @p the current position in the buffer
9620  * @buflen contains the size of the buffer and is used to return the new buffer size
9621  * if this needs to be realloced.
9622  * @retbuffer and @retp return the start and the position of the buffer
9623  */
9624 static void
9625 encode_cattr_value (MonoAssembly *assembly, char *buffer, char *p, char **retbuffer, char **retp, guint32 *buflen, MonoType *type, MonoObject *arg, char *argval)
9626 {
9627         MonoTypeEnum simple_type;
9628         
9629         if ((p-buffer) + 10 >= *buflen) {
9630                 char *newbuf;
9631                 *buflen *= 2;
9632                 newbuf = g_realloc (buffer, *buflen);
9633                 p = newbuf + (p-buffer);
9634                 buffer = newbuf;
9635         }
9636         if (!argval)
9637                 argval = ((char*)arg + sizeof (MonoObject));
9638         simple_type = type->type;
9639 handle_enum:
9640         switch (simple_type) {
9641         case MONO_TYPE_BOOLEAN:
9642         case MONO_TYPE_U1:
9643         case MONO_TYPE_I1:
9644                 *p++ = *argval;
9645                 break;
9646         case MONO_TYPE_CHAR:
9647         case MONO_TYPE_U2:
9648         case MONO_TYPE_I2:
9649                 swap_with_size (p, argval, 2, 1);
9650                 p += 2;
9651                 break;
9652         case MONO_TYPE_U4:
9653         case MONO_TYPE_I4:
9654         case MONO_TYPE_R4:
9655                 swap_with_size (p, argval, 4, 1);
9656                 p += 4;
9657                 break;
9658         case MONO_TYPE_R8:
9659                 swap_with_size (p, argval, 8, 1);
9660                 p += 8;
9661                 break;
9662         case MONO_TYPE_U8:
9663         case MONO_TYPE_I8:
9664                 swap_with_size (p, argval, 8, 1);
9665                 p += 8;
9666                 break;
9667         case MONO_TYPE_VALUETYPE:
9668                 if (type->data.klass->enumtype) {
9669                         simple_type = mono_class_enum_basetype (type->data.klass)->type;
9670                         goto handle_enum;
9671                 } else {
9672                         g_warning ("generic valutype %s not handled in custom attr value decoding", type->data.klass->name);
9673                 }
9674                 break;
9675         case MONO_TYPE_STRING: {
9676                 char *str;
9677                 guint32 slen;
9678                 if (!arg) {
9679                         *p++ = 0xFF;
9680                         break;
9681                 }
9682                 str = mono_string_to_utf8 ((MonoString*)arg);
9683                 slen = strlen (str);
9684                 if ((p-buffer) + 10 + slen >= *buflen) {
9685                         char *newbuf;
9686                         *buflen *= 2;
9687                         *buflen += slen;
9688                         newbuf = g_realloc (buffer, *buflen);
9689                         p = newbuf + (p-buffer);
9690                         buffer = newbuf;
9691                 }
9692                 mono_metadata_encode_value (slen, p, &p);
9693                 memcpy (p, str, slen);
9694                 p += slen;
9695                 g_free (str);
9696                 break;
9697         }
9698         case MONO_TYPE_CLASS: {
9699                 char *str;
9700                 guint32 slen;
9701                 if (!arg) {
9702                         *p++ = 0xFF;
9703                         break;
9704                 }
9705 handle_type:
9706                 str = type_get_qualified_name (mono_reflection_type_get_handle ((MonoReflectionType*)arg), NULL);
9707                 slen = strlen (str);
9708                 if ((p-buffer) + 10 + slen >= *buflen) {
9709                         char *newbuf;
9710                         *buflen *= 2;
9711                         *buflen += slen;
9712                         newbuf = g_realloc (buffer, *buflen);
9713                         p = newbuf + (p-buffer);
9714                         buffer = newbuf;
9715                 }
9716                 mono_metadata_encode_value (slen, p, &p);
9717                 memcpy (p, str, slen);
9718                 p += slen;
9719                 g_free (str);
9720                 break;
9721         }
9722         case MONO_TYPE_SZARRAY: {
9723                 int len, i;
9724                 MonoClass *eclass, *arg_eclass;
9725
9726                 if (!arg) {
9727                         *p++ = 0xff; *p++ = 0xff; *p++ = 0xff; *p++ = 0xff;
9728                         break;
9729                 }
9730                 len = mono_array_length ((MonoArray*)arg);
9731                 *p++ = len & 0xff;
9732                 *p++ = (len >> 8) & 0xff;
9733                 *p++ = (len >> 16) & 0xff;
9734                 *p++ = (len >> 24) & 0xff;
9735                 *retp = p;
9736                 *retbuffer = buffer;
9737                 eclass = type->data.klass;
9738                 arg_eclass = mono_object_class (arg)->element_class;
9739
9740                 if (!eclass) {
9741                         /* Happens when we are called from the MONO_TYPE_OBJECT case below */
9742                         eclass = mono_defaults.object_class;
9743                 }
9744                 if (eclass == mono_defaults.object_class && arg_eclass->valuetype) {
9745                         char *elptr = mono_array_addr ((MonoArray*)arg, char, 0);
9746                         int elsize = mono_class_array_element_size (arg_eclass);
9747                         for (i = 0; i < len; ++i) {
9748                                 encode_cattr_value (assembly, buffer, p, &buffer, &p, buflen, &arg_eclass->byval_arg, NULL, elptr);
9749                                 elptr += elsize;
9750                         }
9751                 } else if (eclass->valuetype && arg_eclass->valuetype) {
9752                         char *elptr = mono_array_addr ((MonoArray*)arg, char, 0);
9753                         int elsize = mono_class_array_element_size (eclass);
9754                         for (i = 0; i < len; ++i) {
9755                                 encode_cattr_value (assembly, buffer, p, &buffer, &p, buflen, &eclass->byval_arg, NULL, elptr);
9756                                 elptr += elsize;
9757                         }
9758                 } else {
9759                         for (i = 0; i < len; ++i) {
9760                                 encode_cattr_value (assembly, buffer, p, &buffer, &p, buflen, &eclass->byval_arg, mono_array_get ((MonoArray*)arg, MonoObject*, i), NULL);
9761                         }
9762                 }
9763                 break;
9764         }
9765         case MONO_TYPE_OBJECT: {
9766                 MonoClass *klass;
9767                 char *str;
9768                 guint32 slen;
9769
9770                 /*
9771                  * The parameter type is 'object' but the type of the actual
9772                  * argument is not. So we have to add type information to the blob
9773                  * too. This is completely undocumented in the spec.
9774                  */
9775
9776                 if (arg == NULL) {
9777                         *p++ = MONO_TYPE_STRING;        // It's same hack as MS uses
9778                         *p++ = 0xFF;
9779                         break;
9780                 }
9781                 
9782                 klass = mono_object_class (arg);
9783
9784                 if (mono_object_isinst (arg, mono_defaults.systemtype_class)) {
9785                         *p++ = 0x50;
9786                         goto handle_type;
9787                 } else if (klass->enumtype) {
9788                         *p++ = 0x55;
9789                 } else if (klass == mono_defaults.string_class) {
9790                         simple_type = MONO_TYPE_STRING;
9791                         *p++ = 0x0E;
9792                         goto handle_enum;
9793                 } else if (klass->rank == 1) {
9794                         *p++ = 0x1D;
9795                         if (klass->element_class->byval_arg.type == MONO_TYPE_OBJECT)
9796                                 /* See Partition II, Appendix B3 */
9797                                 *p++ = 0x51;
9798                         else
9799                                 *p++ = klass->element_class->byval_arg.type;
9800                         encode_cattr_value (assembly, buffer, p, &buffer, &p, buflen, &klass->byval_arg, arg, NULL);
9801                         break;
9802                 } else if (klass->byval_arg.type >= MONO_TYPE_BOOLEAN && klass->byval_arg.type <= MONO_TYPE_R8) {
9803                         *p++ = simple_type = klass->byval_arg.type;
9804                         goto handle_enum;
9805                 } else {
9806                         g_error ("unhandled type in custom attr");
9807                 }
9808                 str = type_get_qualified_name (mono_class_get_type(klass), NULL);
9809                 slen = strlen (str);
9810                 if ((p-buffer) + 10 + slen >= *buflen) {
9811                         char *newbuf;
9812                         *buflen *= 2;
9813                         *buflen += slen;
9814                         newbuf = g_realloc (buffer, *buflen);
9815                         p = newbuf + (p-buffer);
9816                         buffer = newbuf;
9817                 }
9818                 mono_metadata_encode_value (slen, p, &p);
9819                 memcpy (p, str, slen);
9820                 p += slen;
9821                 g_free (str);
9822                 simple_type = mono_class_enum_basetype (klass)->type;
9823                 goto handle_enum;
9824         }
9825         default:
9826                 g_error ("type 0x%02x not yet supported in custom attr encoder", simple_type);
9827         }
9828         *retp = p;
9829         *retbuffer = buffer;
9830 }
9831
9832 static void
9833 encode_field_or_prop_type (MonoType *type, char *p, char **retp)
9834 {
9835         if (type->type == MONO_TYPE_VALUETYPE && type->data.klass->enumtype) {
9836                 char *str = type_get_qualified_name (type, NULL);
9837                 int slen = strlen (str);
9838
9839                 *p++ = 0x55;
9840                 /*
9841                  * This seems to be optional...
9842                  * *p++ = 0x80;
9843                  */
9844                 mono_metadata_encode_value (slen, p, &p);
9845                 memcpy (p, str, slen);
9846                 p += slen;
9847                 g_free (str);
9848         } else if (type->type == MONO_TYPE_OBJECT) {
9849                 *p++ = 0x51;
9850         } else if (type->type == MONO_TYPE_CLASS) {
9851                 /* it should be a type: encode_cattr_value () has the check */
9852                 *p++ = 0x50;
9853         } else {
9854                 mono_metadata_encode_value (type->type, p, &p);
9855                 if (type->type == MONO_TYPE_SZARRAY)
9856                         /* See the examples in Partition VI, Annex B */
9857                         encode_field_or_prop_type (&type->data.klass->byval_arg, p, &p);
9858         }
9859
9860         *retp = p;
9861 }
9862
9863 #ifndef DISABLE_REFLECTION_EMIT
9864 static void
9865 encode_named_val (MonoReflectionAssembly *assembly, char *buffer, char *p, char **retbuffer, char **retp, guint32 *buflen, MonoType *type, char *name, MonoObject *value)
9866 {
9867         int len;
9868         /* Preallocate a large enough buffer */
9869         if (type->type == MONO_TYPE_VALUETYPE && type->data.klass->enumtype) {
9870                 char *str = type_get_qualified_name (type, NULL);
9871                 len = strlen (str);
9872                 g_free (str);
9873         } else if (type->type == MONO_TYPE_SZARRAY && type->data.klass->enumtype) {
9874                 char *str = type_get_qualified_name (&type->data.klass->byval_arg, NULL);
9875                 len = strlen (str);
9876                 g_free (str);
9877         } else {
9878                 len = 0;
9879         }
9880         len += strlen (name);
9881
9882         if ((p-buffer) + 20 + len >= *buflen) {
9883                 char *newbuf;
9884                 *buflen *= 2;
9885                 *buflen += len;
9886                 newbuf = g_realloc (buffer, *buflen);
9887                 p = newbuf + (p-buffer);
9888                 buffer = newbuf;
9889         }
9890
9891         encode_field_or_prop_type (type, p, &p);
9892
9893         len = strlen (name);
9894         mono_metadata_encode_value (len, p, &p);
9895         memcpy (p, name, len);
9896         p += len;
9897         encode_cattr_value (assembly->assembly, buffer, p, &buffer, &p, buflen, type, value, NULL);
9898         *retp = p;
9899         *retbuffer = buffer;
9900 }
9901
9902 /*
9903  * mono_reflection_get_custom_attrs_blob:
9904  * @ctor: custom attribute constructor
9905  * @ctorArgs: arguments o the constructor
9906  * @properties:
9907  * @propValues:
9908  * @fields:
9909  * @fieldValues:
9910  * 
9911  * Creates the blob of data that needs to be saved in the metadata and that represents
9912  * the custom attributed described by @ctor, @ctorArgs etc.
9913  * Returns: a Byte array representing the blob of data.
9914  */
9915 MonoArray*
9916 mono_reflection_get_custom_attrs_blob (MonoReflectionAssembly *assembly, MonoObject *ctor, MonoArray *ctorArgs, MonoArray *properties, MonoArray *propValues, MonoArray *fields, MonoArray* fieldValues) 
9917 {
9918         MonoArray *result;
9919         MonoMethodSignature *sig;
9920         MonoObject *arg;
9921         char *buffer, *p;
9922         guint32 buflen, i;
9923
9924         if (strcmp (ctor->vtable->klass->name, "MonoCMethod")) {
9925                 /* sig is freed later so allocate it in the heap */
9926                 sig = ctor_builder_to_signature (NULL, (MonoReflectionCtorBuilder*)ctor);
9927         } else {
9928                 sig = mono_method_signature (((MonoReflectionMethod*)ctor)->method);
9929         }
9930
9931         g_assert (mono_array_length (ctorArgs) == sig->param_count);
9932         buflen = 256;
9933         p = buffer = g_malloc (buflen);
9934         /* write the prolog */
9935         *p++ = 1;
9936         *p++ = 0;
9937         for (i = 0; i < sig->param_count; ++i) {
9938                 arg = mono_array_get (ctorArgs, MonoObject*, i);
9939                 encode_cattr_value (assembly->assembly, buffer, p, &buffer, &p, &buflen, sig->params [i], arg, NULL);
9940         }
9941         i = 0;
9942         if (properties)
9943                 i += mono_array_length (properties);
9944         if (fields)
9945                 i += mono_array_length (fields);
9946         *p++ = i & 0xff;
9947         *p++ = (i >> 8) & 0xff;
9948         if (properties) {
9949                 MonoObject *prop;
9950                 for (i = 0; i < mono_array_length (properties); ++i) {
9951                         MonoType *ptype;
9952                         char *pname;
9953
9954                         prop = mono_array_get (properties, gpointer, i);
9955                         get_prop_name_and_type (prop, &pname, &ptype);
9956                         *p++ = 0x54; /* PROPERTY signature */
9957                         encode_named_val (assembly, buffer, p, &buffer, &p, &buflen, ptype, pname, (MonoObject*)mono_array_get (propValues, gpointer, i));
9958                         g_free (pname);
9959                 }
9960         }
9961
9962         if (fields) {
9963                 MonoObject *field;
9964                 for (i = 0; i < mono_array_length (fields); ++i) {
9965                         MonoType *ftype;
9966                         char *fname;
9967
9968                         field = mono_array_get (fields, gpointer, i);
9969                         get_field_name_and_type (field, &fname, &ftype);
9970                         *p++ = 0x53; /* FIELD signature */
9971                         encode_named_val (assembly, buffer, p, &buffer, &p, &buflen, ftype, fname, (MonoObject*)mono_array_get (fieldValues, gpointer, i));
9972                         g_free (fname);
9973                 }
9974         }
9975
9976         g_assert (p - buffer <= buflen);
9977         buflen = p - buffer;
9978         result = mono_array_new (mono_domain_get (), mono_defaults.byte_class, buflen);
9979         p = mono_array_addr (result, char, 0);
9980         memcpy (p, buffer, buflen);
9981         g_free (buffer);
9982         if (strcmp (ctor->vtable->klass->name, "MonoCMethod"))
9983                 g_free (sig);
9984         return result;
9985 }
9986
9987 /*
9988  * mono_reflection_setup_internal_class:
9989  * @tb: a TypeBuilder object
9990  *
9991  * Creates a MonoClass that represents the TypeBuilder.
9992  * This is a trick that lets us simplify a lot of reflection code
9993  * (and will allow us to support Build and Run assemblies easier).
9994  */
9995 void
9996 mono_reflection_setup_internal_class (MonoReflectionTypeBuilder *tb)
9997 {
9998         MonoError error;
9999         MonoClass *klass, *parent;
10000
10001         RESOLVE_TYPE (tb->parent);
10002
10003         mono_loader_lock ();
10004
10005         if (tb->parent) {
10006                 /* check so we can compile corlib correctly */
10007                 if (strcmp (mono_object_class (tb->parent)->name, "TypeBuilder") == 0) {
10008                         /* mono_class_setup_mono_type () guaranteess type->data.klass is valid */
10009                         parent = mono_reflection_type_get_handle ((MonoReflectionType*)tb->parent)->data.klass;
10010                 } else {
10011                         parent = mono_class_from_mono_type (mono_reflection_type_get_handle ((MonoReflectionType*)tb->parent));
10012                 }
10013         } else {
10014                 parent = NULL;
10015         }
10016         
10017         /* the type has already being created: it means we just have to change the parent */
10018         if (tb->type.type) {
10019                 klass = mono_class_from_mono_type (tb->type.type);
10020                 klass->parent = NULL;
10021                 /* fool mono_class_setup_parent */
10022                 klass->supertypes = NULL;
10023                 mono_class_setup_parent (klass, parent);
10024                 mono_class_setup_mono_type (klass);
10025                 mono_loader_unlock ();
10026                 return;
10027         }
10028
10029         klass = mono_image_alloc0 (&tb->module->dynamic_image->image, sizeof (MonoClass));
10030
10031         klass->image = &tb->module->dynamic_image->image;
10032
10033         klass->inited = 1; /* we lie to the runtime */
10034         klass->name = mono_string_to_utf8_image (klass->image, tb->name, &error);
10035         if (!mono_error_ok (&error))
10036                 goto failure;
10037         klass->name_space = mono_string_to_utf8_image (klass->image, tb->nspace, &error);
10038         if (!mono_error_ok (&error))
10039                 goto failure;
10040         klass->type_token = MONO_TOKEN_TYPE_DEF | tb->table_idx;
10041         klass->flags = tb->attrs;
10042         
10043         mono_profiler_class_event (klass, MONO_PROFILE_START_LOAD);
10044
10045         klass->element_class = klass;
10046
10047         if (mono_class_get_ref_info (klass) == NULL) {
10048
10049                 mono_class_set_ref_info (klass, tb);
10050
10051                 /* Put into cache so mono_class_get_checked () will find it.
10052                 Skip nested types as those should not be available on the global scope. */
10053                 if (!tb->nesting_type)
10054                         mono_image_add_to_name_cache (klass->image, klass->name_space, klass->name, tb->table_idx);
10055
10056                 /*
10057                 We must register all types as we cannot rely on the name_cache hashtable since we find the class
10058                 by performing a mono_class_get which does the full resolution.
10059
10060                 Working around this semantics would require us to write a lot of code for no clear advantage.
10061                 */
10062                 mono_image_append_class_to_reflection_info_set (klass);
10063         } else {
10064                 g_assert (mono_class_get_ref_info (klass) == tb);
10065         }
10066
10067         register_dyn_token (tb->module->dynamic_image, MONO_TOKEN_TYPE_DEF | tb->table_idx, (MonoObject*)tb);
10068
10069         if (parent != NULL) {
10070                 mono_class_setup_parent (klass, parent);
10071         } else if (strcmp (klass->name, "Object") == 0 && strcmp (klass->name_space, "System") == 0) {
10072                 const char *old_n = klass->name;
10073                 /* trick to get relative numbering right when compiling corlib */
10074                 klass->name = "BuildingObject";
10075                 mono_class_setup_parent (klass, mono_defaults.object_class);
10076                 klass->name = old_n;
10077         }
10078
10079         if ((!strcmp (klass->name, "ValueType") && !strcmp (klass->name_space, "System")) ||
10080                         (!strcmp (klass->name, "Object") && !strcmp (klass->name_space, "System")) ||
10081                         (!strcmp (klass->name, "Enum") && !strcmp (klass->name_space, "System"))) {
10082                 klass->instance_size = sizeof (MonoObject);
10083                 klass->size_inited = 1;
10084                 mono_class_setup_vtable_general (klass, NULL, 0, NULL);
10085         }
10086
10087         mono_class_setup_mono_type (klass);
10088
10089         mono_class_setup_supertypes (klass);
10090
10091         /*
10092          * FIXME: handle interfaces.
10093          */
10094
10095         tb->type.type = &klass->byval_arg;
10096
10097         if (tb->nesting_type) {
10098                 g_assert (tb->nesting_type->type);
10099                 klass->nested_in = mono_class_from_mono_type (mono_reflection_type_get_handle (tb->nesting_type));
10100         }
10101
10102         /*g_print ("setup %s as %s (%p)\n", klass->name, ((MonoObject*)tb)->vtable->klass->name, tb);*/
10103
10104         mono_profiler_class_loaded (klass, MONO_PROFILE_OK);
10105         
10106         mono_loader_unlock ();
10107         return;
10108
10109 failure:
10110         mono_loader_unlock ();
10111         mono_error_raise_exception (&error);
10112 }
10113
10114 /*
10115  * mono_reflection_setup_generic_class:
10116  * @tb: a TypeBuilder object
10117  *
10118  * Setup the generic class before adding the first generic parameter.
10119  */
10120 void
10121 mono_reflection_setup_generic_class (MonoReflectionTypeBuilder *tb)
10122 {
10123 }
10124
10125 /*
10126  * mono_reflection_create_generic_class:
10127  * @tb: a TypeBuilder object
10128  *
10129  * Creates the generic class after all generic parameters have been added.
10130  */
10131 void
10132 mono_reflection_create_generic_class (MonoReflectionTypeBuilder *tb)
10133 {
10134         MonoClass *klass;
10135         int count, i;
10136
10137         klass = mono_class_from_mono_type (tb->type.type);
10138
10139         count = tb->generic_params ? mono_array_length (tb->generic_params) : 0;
10140
10141         if (klass->generic_container || (count == 0))
10142                 return;
10143
10144         g_assert (tb->generic_container && (tb->generic_container->owner.klass == klass));
10145
10146         klass->generic_container = mono_image_alloc0 (klass->image, sizeof (MonoGenericContainer));
10147
10148         klass->generic_container->owner.klass = klass;
10149         klass->generic_container->type_argc = count;
10150         klass->generic_container->type_params = mono_image_alloc0 (klass->image, sizeof (MonoGenericParamFull) * count);
10151
10152         klass->is_generic = 1;
10153
10154         for (i = 0; i < count; i++) {
10155                 MonoReflectionGenericParam *gparam = mono_array_get (tb->generic_params, gpointer, i);
10156                 MonoGenericParamFull *param = (MonoGenericParamFull *) mono_reflection_type_get_handle ((MonoReflectionType*)gparam)->data.generic_param;
10157                 klass->generic_container->type_params [i] = *param;
10158                 /*Make sure we are a diferent type instance */
10159                 klass->generic_container->type_params [i].param.owner = klass->generic_container;
10160                 klass->generic_container->type_params [i].info.pklass = NULL;
10161                 klass->generic_container->type_params [i].info.flags = gparam->attrs;
10162
10163                 g_assert (klass->generic_container->type_params [i].param.owner);
10164         }
10165
10166         klass->generic_container->context.class_inst = mono_get_shared_generic_inst (klass->generic_container);
10167 }
10168
10169 /*
10170  * mono_reflection_create_internal_class:
10171  * @tb: a TypeBuilder object
10172  *
10173  * Actually create the MonoClass that is associated with the TypeBuilder.
10174  */
10175 void
10176 mono_reflection_create_internal_class (MonoReflectionTypeBuilder *tb)
10177 {
10178         MonoClass *klass;
10179
10180         klass = mono_class_from_mono_type (tb->type.type);
10181
10182         mono_loader_lock ();
10183         if (klass->enumtype && mono_class_enum_basetype (klass) == NULL) {
10184                 MonoReflectionFieldBuilder *fb;
10185                 MonoClass *ec;
10186                 MonoType *enum_basetype;
10187
10188                 g_assert (tb->fields != NULL);
10189                 g_assert (mono_array_length (tb->fields) >= 1);
10190
10191                 fb = mono_array_get (tb->fields, MonoReflectionFieldBuilder*, 0);
10192
10193                 if (!mono_type_is_valid_enum_basetype (mono_reflection_type_get_handle ((MonoReflectionType*)fb->type))) {
10194                         mono_loader_unlock ();
10195                         return;
10196                 }
10197
10198                 enum_basetype = mono_reflection_type_get_handle ((MonoReflectionType*)fb->type);
10199                 klass->element_class = mono_class_from_mono_type (enum_basetype);
10200                 if (!klass->element_class)
10201                         klass->element_class = mono_class_from_mono_type (enum_basetype);
10202
10203                 /*
10204                  * get the element_class from the current corlib.
10205                  */
10206                 ec = default_class_from_mono_type (enum_basetype);
10207                 klass->instance_size = ec->instance_size;
10208                 klass->size_inited = 1;
10209                 /* 
10210                  * this is almost safe to do with enums and it's needed to be able
10211                  * to create objects of the enum type (for use in SetConstant).
10212                  */
10213                 /* FIXME: Does this mean enums can't have method overrides ? */
10214                 mono_class_setup_vtable_general (klass, NULL, 0, NULL);
10215         }
10216         mono_loader_unlock ();
10217 }
10218
10219 static MonoMarshalSpec*
10220 mono_marshal_spec_from_builder (MonoImage *image, MonoAssembly *assembly,
10221                                                                 MonoReflectionMarshal *minfo)
10222 {
10223         MonoMarshalSpec *res;
10224
10225         res = image_g_new0 (image, MonoMarshalSpec, 1);
10226         res->native = minfo->type;
10227
10228         switch (minfo->type) {
10229         case MONO_NATIVE_LPARRAY:
10230                 res->data.array_data.elem_type = minfo->eltype;
10231                 if (minfo->has_size) {
10232                         res->data.array_data.param_num = minfo->param_num;
10233                         res->data.array_data.num_elem = minfo->count;
10234                         res->data.array_data.elem_mult = minfo->param_num == -1 ? 0 : 1;
10235                 }
10236                 else {
10237                         res->data.array_data.param_num = -1;
10238                         res->data.array_data.num_elem = -1;
10239                         res->data.array_data.elem_mult = -1;
10240                 }
10241                 break;
10242
10243         case MONO_NATIVE_BYVALTSTR:
10244         case MONO_NATIVE_BYVALARRAY:
10245                 res->data.array_data.num_elem = minfo->count;
10246                 break;
10247
10248         case MONO_NATIVE_CUSTOM:
10249                 if (minfo->marshaltyperef)
10250                         res->data.custom_data.custom_name =
10251                                 type_get_fully_qualified_name (mono_reflection_type_get_handle ((MonoReflectionType*)minfo->marshaltyperef));
10252                 if (minfo->mcookie)
10253                         res->data.custom_data.cookie = mono_string_to_utf8 (minfo->mcookie);
10254                 break;
10255
10256         default:
10257                 break;
10258         }
10259
10260         return res;
10261 }
10262 #endif /* !DISABLE_REFLECTION_EMIT */
10263
10264 MonoReflectionMarshalAsAttribute*
10265 mono_reflection_marshal_as_attribute_from_marshal_spec (MonoDomain *domain, MonoClass *klass,
10266                                                                                    MonoMarshalSpec *spec)
10267 {
10268         static MonoClass *System_Reflection_Emit_MarshalAsAttribute;
10269         MonoReflectionMarshalAsAttribute *minfo;
10270         MonoType *mtype;
10271
10272         if (!System_Reflection_Emit_MarshalAsAttribute) {
10273                 System_Reflection_Emit_MarshalAsAttribute = mono_class_from_name (
10274                    mono_defaults.corlib, "System.Runtime.InteropServices", "MarshalAsAttribute");
10275                 g_assert (System_Reflection_Emit_MarshalAsAttribute);
10276         }
10277
10278         minfo = (MonoReflectionMarshalAsAttribute*)mono_object_new (domain, System_Reflection_Emit_MarshalAsAttribute);
10279         minfo->utype = spec->native;
10280
10281         switch (minfo->utype) {
10282         case MONO_NATIVE_LPARRAY:
10283                 minfo->array_subtype = spec->data.array_data.elem_type;
10284                 minfo->size_const = spec->data.array_data.num_elem;
10285                 if (spec->data.array_data.param_num != -1)
10286                         minfo->size_param_index = spec->data.array_data.param_num;
10287                 break;
10288
10289         case MONO_NATIVE_BYVALTSTR:
10290         case MONO_NATIVE_BYVALARRAY:
10291                 minfo->size_const = spec->data.array_data.num_elem;
10292                 break;
10293
10294         case MONO_NATIVE_CUSTOM:
10295                 if (spec->data.custom_data.custom_name) {
10296                         mtype = mono_reflection_type_from_name (spec->data.custom_data.custom_name, klass->image);
10297                         if (mtype)
10298                                 MONO_OBJECT_SETREF (minfo, marshal_type_ref, mono_type_get_object (domain, mtype));
10299
10300                         MONO_OBJECT_SETREF (minfo, marshal_type, mono_string_new (domain, spec->data.custom_data.custom_name));
10301                 }
10302                 if (spec->data.custom_data.cookie)
10303                         MONO_OBJECT_SETREF (minfo, marshal_cookie, mono_string_new (domain, spec->data.custom_data.cookie));
10304                 break;
10305
10306         default:
10307                 break;
10308         }
10309
10310         return minfo;
10311 }
10312
10313 #ifndef DISABLE_REFLECTION_EMIT
10314 static MonoMethod*
10315 reflection_methodbuilder_to_mono_method (MonoClass *klass,
10316                                          ReflectionMethodBuilder *rmb,
10317                                          MonoMethodSignature *sig)
10318 {
10319         MonoError error;
10320         MonoMethod *m;
10321         MonoMethodWrapper *wrapperm;
10322         MonoMarshalSpec **specs;
10323         MonoReflectionMethodAux *method_aux;
10324         MonoImage *image;
10325         gboolean dynamic;
10326         int i;
10327
10328         mono_error_init (&error);
10329         /*
10330          * Methods created using a MethodBuilder should have their memory allocated
10331          * inside the image mempool, while dynamic methods should have their memory
10332          * malloc'd.
10333          */
10334         dynamic = rmb->refs != NULL;
10335         image = dynamic ? NULL : klass->image;
10336
10337         if (!dynamic)
10338                 g_assert (!klass->generic_class);
10339
10340         mono_loader_lock ();
10341
10342         if ((rmb->attrs & METHOD_ATTRIBUTE_PINVOKE_IMPL) ||
10343                         (rmb->iattrs & METHOD_IMPL_ATTRIBUTE_INTERNAL_CALL))
10344                 m = (MonoMethod *)image_g_new0 (image, MonoMethodPInvoke, 1);
10345         else
10346                 m = (MonoMethod *)image_g_new0 (image, MonoMethodWrapper, 1);
10347
10348         wrapperm = (MonoMethodWrapper*)m;
10349
10350         m->dynamic = dynamic;
10351         m->slot = -1;
10352         m->flags = rmb->attrs;
10353         m->iflags = rmb->iattrs;
10354         m->name = mono_string_to_utf8_image_ignore (image, rmb->name);
10355         m->klass = klass;
10356         m->signature = sig;
10357         m->sre_method = TRUE;
10358         m->skip_visibility = rmb->skip_visibility;
10359         if (rmb->table_idx)
10360                 m->token = MONO_TOKEN_METHOD_DEF | (*rmb->table_idx);
10361
10362         if (m->iflags & METHOD_IMPL_ATTRIBUTE_INTERNAL_CALL) {
10363                 if (klass == mono_defaults.string_class && !strcmp (m->name, ".ctor"))
10364                         m->string_ctor = 1;
10365
10366                 m->signature->pinvoke = 1;
10367         } else if (m->flags & METHOD_ATTRIBUTE_PINVOKE_IMPL) {
10368                 m->signature->pinvoke = 1;
10369
10370                 method_aux = image_g_new0 (image, MonoReflectionMethodAux, 1);
10371
10372                 method_aux->dllentry = rmb->dllentry ? mono_string_to_utf8_image (image, rmb->dllentry, &error) : image_strdup (image, m->name);
10373                 g_assert (mono_error_ok (&error));
10374                 method_aux->dll = mono_string_to_utf8_image (image, rmb->dll, &error);
10375                 g_assert (mono_error_ok (&error));
10376                 
10377                 ((MonoMethodPInvoke*)m)->piflags = (rmb->native_cc << 8) | (rmb->charset ? (rmb->charset - 1) * 2 : 0) | rmb->extra_flags;
10378
10379                 if (image_is_dynamic (klass->image))
10380                         g_hash_table_insert (((MonoDynamicImage*)klass->image)->method_aux_hash, m, method_aux);
10381
10382                 mono_loader_unlock ();
10383
10384                 return m;
10385         } else if (!(m->flags & METHOD_ATTRIBUTE_ABSTRACT) &&
10386                            !(m->iflags & METHOD_IMPL_ATTRIBUTE_RUNTIME)) {
10387                 MonoMethodHeader *header;
10388                 guint32 code_size;
10389                 gint32 max_stack, i;
10390                 gint32 num_locals = 0;
10391                 gint32 num_clauses = 0;
10392                 guint8 *code;
10393
10394                 if (rmb->ilgen) {
10395                         code = mono_array_addr (rmb->ilgen->code, guint8, 0);
10396                         code_size = rmb->ilgen->code_len;
10397                         max_stack = rmb->ilgen->max_stack;
10398                         num_locals = rmb->ilgen->locals ? mono_array_length (rmb->ilgen->locals) : 0;
10399                         if (rmb->ilgen->ex_handlers)
10400                                 num_clauses = method_count_clauses (rmb->ilgen);
10401                 } else {
10402                         if (rmb->code) {
10403                                 code = mono_array_addr (rmb->code, guint8, 0);
10404                                 code_size = mono_array_length (rmb->code);
10405                                 /* we probably need to run a verifier on the code... */
10406                                 max_stack = 8; 
10407                         }
10408                         else {
10409                                 code = NULL;
10410                                 code_size = 0;
10411                                 max_stack = 8;
10412                         }
10413                 }
10414
10415                 header = image_g_malloc0 (image, MONO_SIZEOF_METHOD_HEADER + num_locals * sizeof (MonoType*));
10416                 header->code_size = code_size;
10417                 header->code = image_g_malloc (image, code_size);
10418                 memcpy ((char*)header->code, code, code_size);
10419                 header->max_stack = max_stack;
10420                 header->init_locals = rmb->init_locals;
10421                 header->num_locals = num_locals;
10422
10423                 for (i = 0; i < num_locals; ++i) {
10424                         MonoReflectionLocalBuilder *lb = 
10425                                 mono_array_get (rmb->ilgen->locals, MonoReflectionLocalBuilder*, i);
10426
10427                         header->locals [i] = image_g_new0 (image, MonoType, 1);
10428                         memcpy (header->locals [i], mono_reflection_type_get_handle ((MonoReflectionType*)lb->type), MONO_SIZEOF_TYPE);
10429                 }
10430
10431                 header->num_clauses = num_clauses;
10432                 if (num_clauses) {
10433                         header->clauses = method_encode_clauses (image, (MonoDynamicImage*)klass->image,
10434                                  rmb->ilgen, num_clauses);
10435                 }
10436
10437                 wrapperm->header = header;
10438         }
10439
10440         if (rmb->generic_params) {
10441                 int count = mono_array_length (rmb->generic_params);
10442                 MonoGenericContainer *container = rmb->generic_container;
10443
10444                 g_assert (container);
10445
10446                 container->type_argc = count;
10447                 container->type_params = image_g_new0 (image, MonoGenericParamFull, count);
10448                 container->owner.method = m;
10449
10450                 m->is_generic = TRUE;
10451                 mono_method_set_generic_container (m, container);
10452
10453                 for (i = 0; i < count; i++) {
10454                         MonoReflectionGenericParam *gp =
10455                                 mono_array_get (rmb->generic_params, MonoReflectionGenericParam*, i);
10456                         MonoGenericParamFull *param = (MonoGenericParamFull *) mono_reflection_type_get_handle ((MonoReflectionType*)gp)->data.generic_param;
10457                         container->type_params [i] = *param;
10458                 }
10459
10460                 /*
10461                  * The method signature might have pointers to generic parameters that belong to other methods.
10462                  * This is a valid SRE case, but the resulting method signature must be encoded using the proper
10463                  * generic parameters.
10464                  */
10465                 for (i = 0; i < m->signature->param_count; ++i) {
10466                         MonoType *t = m->signature->params [i];
10467                         if (t->type == MONO_TYPE_MVAR) {
10468                                 MonoGenericParam *gparam =  t->data.generic_param;
10469                                 if (gparam->num < count) {
10470                                         m->signature->params [i] = mono_metadata_type_dup (image, m->signature->params [i]);
10471                                         m->signature->params [i]->data.generic_param = mono_generic_container_get_param (container, gparam->num);
10472                                 }
10473
10474                         }
10475                 }
10476
10477                 if (klass->generic_container) {
10478                         container->parent = klass->generic_container;
10479                         container->context.class_inst = klass->generic_container->context.class_inst;
10480                 }
10481                 container->context.method_inst = mono_get_shared_generic_inst (container);
10482         }
10483
10484         if (rmb->refs) {
10485                 MonoMethodWrapper *mw = (MonoMethodWrapper*)m;
10486                 int i;
10487                 void **data;
10488
10489                 m->wrapper_type = MONO_WRAPPER_DYNAMIC_METHOD;
10490
10491                 mw->method_data = data = image_g_new (image, gpointer, rmb->nrefs + 1);
10492                 data [0] = GUINT_TO_POINTER (rmb->nrefs);
10493                 for (i = 0; i < rmb->nrefs; ++i)
10494                         data [i + 1] = rmb->refs [i];
10495         }
10496
10497         method_aux = NULL;
10498
10499         /* Parameter info */
10500         if (rmb->pinfo) {
10501                 if (!method_aux)
10502                         method_aux = image_g_new0 (image, MonoReflectionMethodAux, 1);
10503                 method_aux->param_names = image_g_new0 (image, char *, mono_method_signature (m)->param_count + 1);
10504                 for (i = 0; i <= m->signature->param_count; ++i) {
10505                         MonoReflectionParamBuilder *pb;
10506                         if ((pb = mono_array_get (rmb->pinfo, MonoReflectionParamBuilder*, i))) {
10507                                 if ((i > 0) && (pb->attrs)) {
10508                                         /* Make a copy since it might point to a shared type structure */
10509                                         m->signature->params [i - 1] = mono_metadata_type_dup (klass->image, m->signature->params [i - 1]);
10510                                         m->signature->params [i - 1]->attrs = pb->attrs;
10511                                 }
10512
10513                                 if (pb->attrs & PARAM_ATTRIBUTE_HAS_DEFAULT) {
10514                                         MonoDynamicImage *assembly;
10515                                         guint32 idx, def_type, len;
10516                                         char *p;
10517                                         const char *p2;
10518
10519                                         if (!method_aux->param_defaults) {
10520                                                 method_aux->param_defaults = image_g_new0 (image, guint8*, m->signature->param_count + 1);
10521                                                 method_aux->param_default_types = image_g_new0 (image, guint32, m->signature->param_count + 1);
10522                                         }
10523                                         assembly = (MonoDynamicImage*)klass->image;
10524                                         idx = encode_constant (assembly, pb->def_value, &def_type);
10525                                         /* Copy the data from the blob since it might get realloc-ed */
10526                                         p = assembly->blob.data + idx;
10527                                         len = mono_metadata_decode_blob_size (p, &p2);
10528                                         len += p2 - p;
10529                                         method_aux->param_defaults [i] = image_g_malloc (image, len);
10530                                         method_aux->param_default_types [i] = def_type;
10531                                         memcpy ((gpointer)method_aux->param_defaults [i], p, len);
10532                                 }
10533
10534                                 if (pb->name) {
10535                                         method_aux->param_names [i] = mono_string_to_utf8_image (image, pb->name, &error);
10536                                         g_assert (mono_error_ok (&error));
10537                                 }
10538                                 if (pb->cattrs) {
10539                                         if (!method_aux->param_cattr)
10540                                                 method_aux->param_cattr = image_g_new0 (image, MonoCustomAttrInfo*, m->signature->param_count + 1);
10541                                         method_aux->param_cattr [i] = mono_custom_attrs_from_builders (image, klass->image, pb->cattrs);
10542                                 }
10543                         }
10544                 }
10545         }
10546
10547         /* Parameter marshalling */
10548         specs = NULL;
10549         if (rmb->pinfo)         
10550                 for (i = 0; i < mono_array_length (rmb->pinfo); ++i) {
10551                         MonoReflectionParamBuilder *pb;
10552                         if ((pb = mono_array_get (rmb->pinfo, MonoReflectionParamBuilder*, i))) {
10553                                 if (pb->marshal_info) {
10554                                         if (specs == NULL)
10555                                                 specs = image_g_new0 (image, MonoMarshalSpec*, sig->param_count + 1);
10556                                         specs [pb->position] = 
10557                                                 mono_marshal_spec_from_builder (image, klass->image->assembly, pb->marshal_info);
10558                                 }
10559                         }
10560                 }
10561         if (specs != NULL) {
10562                 if (!method_aux)
10563                         method_aux = image_g_new0 (image, MonoReflectionMethodAux, 1);
10564                 method_aux->param_marshall = specs;
10565         }
10566
10567         if (image_is_dynamic (klass->image) && method_aux)
10568                 g_hash_table_insert (((MonoDynamicImage*)klass->image)->method_aux_hash, m, method_aux);
10569
10570         mono_loader_unlock ();
10571
10572         return m;
10573 }       
10574
10575 static MonoMethod*
10576 ctorbuilder_to_mono_method (MonoClass *klass, MonoReflectionCtorBuilder* mb)
10577 {
10578         ReflectionMethodBuilder rmb;
10579         MonoMethodSignature *sig;
10580
10581         mono_loader_lock ();
10582         sig = ctor_builder_to_signature (klass->image, mb);
10583         mono_loader_unlock ();
10584
10585         reflection_methodbuilder_from_ctor_builder (&rmb, mb);
10586
10587         mb->mhandle = reflection_methodbuilder_to_mono_method (klass, &rmb, sig);
10588         mono_save_custom_attrs (klass->image, mb->mhandle, mb->cattrs);
10589
10590         /* If we are in a generic class, we might be called multiple times from inflate_method */
10591         if (!((MonoDynamicImage*)(MonoDynamicImage*)klass->image)->save && !klass->generic_container) {
10592                 /* ilgen is no longer needed */
10593                 mb->ilgen = NULL;
10594         }
10595
10596         return mb->mhandle;
10597 }
10598
10599 static MonoMethod*
10600 methodbuilder_to_mono_method (MonoClass *klass, MonoReflectionMethodBuilder* mb)
10601 {
10602         ReflectionMethodBuilder rmb;
10603         MonoMethodSignature *sig;
10604
10605         mono_loader_lock ();
10606         sig = method_builder_to_signature (klass->image, mb);
10607         mono_loader_unlock ();
10608
10609         reflection_methodbuilder_from_method_builder (&rmb, mb);
10610
10611         mb->mhandle = reflection_methodbuilder_to_mono_method (klass, &rmb, sig);
10612         mono_save_custom_attrs (klass->image, mb->mhandle, mb->cattrs);
10613
10614         /* If we are in a generic class, we might be called multiple times from inflate_method */
10615         if (!((MonoDynamicImage*)(MonoDynamicImage*)klass->image)->save && !klass->generic_container) {
10616                 /* ilgen is no longer needed */
10617                 mb->ilgen = NULL;
10618         }
10619         return mb->mhandle;
10620 }
10621
10622 static MonoClassField*
10623 fieldbuilder_to_mono_class_field (MonoClass *klass, MonoReflectionFieldBuilder* fb)
10624 {
10625         MonoClassField *field;
10626         MonoType *custom;
10627         MonoError error;
10628
10629         field = g_new0 (MonoClassField, 1);
10630
10631         field->name = mono_string_to_utf8_image (klass->image, fb->name, &error);
10632         g_assert (mono_error_ok (&error));
10633         if (fb->attrs || fb->modreq || fb->modopt) {
10634                 field->type = mono_metadata_type_dup (NULL, mono_reflection_type_get_handle ((MonoReflectionType*)fb->type));
10635                 field->type->attrs = fb->attrs;
10636
10637                 g_assert (image_is_dynamic (klass->image));
10638                 custom = add_custom_modifiers ((MonoDynamicImage*)klass->image, field->type, fb->modreq, fb->modopt);
10639                 g_free (field->type);
10640                 field->type = mono_metadata_type_dup (klass->image, custom);
10641                 g_free (custom);
10642         } else {
10643                 field->type = mono_reflection_type_get_handle ((MonoReflectionType*)fb->type);
10644         }
10645         if (fb->offset != -1)
10646                 field->offset = fb->offset;
10647         field->parent = klass;
10648         mono_save_custom_attrs (klass->image, field, fb->cattrs);
10649
10650         // FIXME: Can't store fb->def_value/RVA, is it needed for field_on_insts ?
10651
10652         return field;
10653 }
10654 #endif
10655
10656 MonoType*
10657 mono_reflection_bind_generic_parameters (MonoReflectionType *type, int type_argc, MonoType **types)
10658 {
10659         MonoClass *klass;
10660         MonoReflectionTypeBuilder *tb = NULL;
10661         gboolean is_dynamic = FALSE;
10662         MonoClass *geninst;
10663
10664         mono_loader_lock ();
10665
10666         if (is_sre_type_builder (mono_object_class (type))) {
10667                 tb = (MonoReflectionTypeBuilder *) type;
10668
10669                 is_dynamic = TRUE;
10670         } else if (is_sre_generic_instance (mono_object_class (type))) {
10671                 MonoReflectionGenericClass *rgi = (MonoReflectionGenericClass *) type;
10672                 MonoReflectionType *gtd = rgi->generic_type;
10673
10674                 if (is_sre_type_builder (mono_object_class (gtd))) {
10675                         tb = (MonoReflectionTypeBuilder *)gtd;
10676                         is_dynamic = TRUE;
10677                 }
10678         }
10679
10680         /* FIXME: fix the CreateGenericParameters protocol to avoid the two stage setup of TypeBuilders */
10681         if (tb && tb->generic_container)
10682                 mono_reflection_create_generic_class (tb);
10683
10684         klass = mono_class_from_mono_type (mono_reflection_type_get_handle (type));
10685         if (!klass->generic_container) {
10686                 mono_loader_unlock ();
10687                 return NULL;
10688         }
10689
10690         if (klass->wastypebuilder) {
10691                 tb = (MonoReflectionTypeBuilder *) mono_class_get_ref_info (klass);
10692
10693                 is_dynamic = TRUE;
10694         }
10695
10696         mono_loader_unlock ();
10697
10698         geninst = mono_class_bind_generic_parameters (klass, type_argc, types, is_dynamic);
10699
10700         return &geninst->byval_arg;
10701 }
10702
10703 MonoClass*
10704 mono_class_bind_generic_parameters (MonoClass *klass, int type_argc, MonoType **types, gboolean is_dynamic)
10705 {
10706         MonoGenericClass *gclass;
10707         MonoGenericInst *inst;
10708
10709         g_assert (klass->generic_container);
10710
10711         inst = mono_metadata_get_generic_inst (type_argc, types);
10712         gclass = mono_metadata_lookup_generic_class (klass, inst, is_dynamic);
10713
10714         return mono_generic_class_get_class (gclass);
10715 }
10716
10717 MonoReflectionMethod*
10718 mono_reflection_bind_generic_method_parameters (MonoReflectionMethod *rmethod, MonoArray *types)
10719 {
10720         MonoError error;
10721         MonoClass *klass;
10722         MonoMethod *method, *inflated;
10723         MonoMethodInflated *imethod;
10724         MonoGenericContext tmp_context;
10725         MonoGenericInst *ginst;
10726         MonoType **type_argv;
10727         int count, i;
10728
10729         /*FIXME but this no longer should happen*/
10730         if (!strcmp (rmethod->object.vtable->klass->name, "MethodBuilder")) {
10731 #ifndef DISABLE_REFLECTION_EMIT
10732                 MonoReflectionMethodBuilder *mb = NULL;
10733                 MonoReflectionTypeBuilder *tb;
10734                 MonoClass *klass;
10735
10736                 mb = (MonoReflectionMethodBuilder *) rmethod;
10737                 tb = (MonoReflectionTypeBuilder *) mb->type;
10738                 klass = mono_class_from_mono_type (mono_reflection_type_get_handle ((MonoReflectionType*)tb));
10739
10740                 method = methodbuilder_to_mono_method (klass, mb);
10741 #else
10742                 g_assert_not_reached ();
10743                 method = NULL;
10744 #endif
10745         } else {
10746                 method = rmethod->method;
10747         }
10748
10749         klass = method->klass;
10750
10751         if (method->is_inflated)
10752                 method = ((MonoMethodInflated *) method)->declaring;
10753
10754         count = mono_method_signature (method)->generic_param_count;
10755         if (count != mono_array_length (types))
10756                 return NULL;
10757
10758         type_argv = g_new0 (MonoType *, count);
10759         for (i = 0; i < count; i++) {
10760                 MonoReflectionType *garg = mono_array_get (types, gpointer, i);
10761                 type_argv [i] = mono_reflection_type_get_handle (garg);
10762         }
10763         ginst = mono_metadata_get_generic_inst (count, type_argv);
10764         g_free (type_argv);
10765
10766         tmp_context.class_inst = klass->generic_class ? klass->generic_class->context.class_inst : NULL;
10767         tmp_context.method_inst = ginst;
10768
10769         inflated = mono_class_inflate_generic_method_checked (method, &tmp_context, &error);
10770         g_assert (mono_error_ok (&error)); /* FIXME don't swallow the error */
10771         imethod = (MonoMethodInflated *) inflated;
10772
10773         /*FIXME but I think this is no longer necessary*/
10774         if (image_is_dynamic (method->klass->image)) {
10775                 MonoDynamicImage *image = (MonoDynamicImage*)method->klass->image;
10776                 /*
10777                  * This table maps metadata structures representing inflated methods/fields
10778                  * to the reflection objects representing their generic definitions.
10779                  */
10780                 mono_image_lock ((MonoImage*)image);
10781                 mono_g_hash_table_insert (image->generic_def_objects, imethod, rmethod);
10782                 mono_image_unlock ((MonoImage*)image);
10783         }
10784
10785         if (!mono_verifier_is_method_valid_generic_instantiation (inflated))
10786                 mono_raise_exception (mono_get_exception_argument ("typeArguments", "Invalid generic arguments"));
10787         
10788         return mono_method_get_object (mono_object_domain (rmethod), inflated, NULL);
10789 }
10790
10791 #ifndef DISABLE_REFLECTION_EMIT
10792
10793 static MonoMethod *
10794 inflate_mono_method (MonoClass *klass, MonoMethod *method, MonoObject *obj)
10795 {
10796         MonoMethodInflated *imethod;
10797         MonoGenericContext *context;
10798         int i;
10799
10800         /*
10801          * With generic code sharing the klass might not be inflated.
10802          * This can happen because classes inflated with their own
10803          * type arguments are "normalized" to the uninflated class.
10804          */
10805         if (!klass->generic_class)
10806                 return method;
10807
10808         context = mono_class_get_context (klass);
10809
10810         if (klass->method.count && klass->methods) {
10811                 /* Find the already created inflated method */
10812                 for (i = 0; i < klass->method.count; ++i) {
10813                         g_assert (klass->methods [i]->is_inflated);
10814                         if (((MonoMethodInflated*)klass->methods [i])->declaring == method)
10815                                 break;
10816                 }
10817                 g_assert (i < klass->method.count);
10818                 imethod = (MonoMethodInflated*)klass->methods [i];
10819         } else {
10820                 MonoError error;
10821                 imethod = (MonoMethodInflated *) mono_class_inflate_generic_method_full_checked (method, klass, context, &error);
10822                 g_assert (mono_error_ok (&error)); /* FIXME don't swallow the error */
10823         }
10824
10825         if (method->is_generic && image_is_dynamic (method->klass->image)) {
10826                 MonoDynamicImage *image = (MonoDynamicImage*)method->klass->image;
10827
10828                 mono_image_lock ((MonoImage*)image);
10829                 mono_g_hash_table_insert (image->generic_def_objects, imethod, obj);
10830                 mono_image_unlock ((MonoImage*)image);
10831         }
10832         return (MonoMethod *) imethod;
10833 }
10834
10835 static MonoMethod *
10836 inflate_method (MonoReflectionType *type, MonoObject *obj)
10837 {
10838         MonoMethod *method;
10839         MonoClass *gklass;
10840
10841         MonoClass *type_class = mono_object_class (type);
10842
10843         if (is_sre_generic_instance (type_class)) {
10844                 MonoReflectionGenericClass *mgc = (MonoReflectionGenericClass*)type;
10845                 gklass = mono_class_from_mono_type (mono_reflection_type_get_handle ((MonoReflectionType*)mgc->generic_type));
10846         } else if (is_sre_type_builder (type_class)) {
10847                 gklass = mono_class_from_mono_type (mono_reflection_type_get_handle (type));
10848         } else if (type->type) {
10849                 gklass = mono_class_from_mono_type (type->type);
10850                 gklass = mono_class_get_generic_type_definition (gklass);
10851         } else {
10852                 g_error ("Can't handle type %s", mono_type_get_full_name (mono_object_class (type)));
10853         }
10854
10855         if (!strcmp (obj->vtable->klass->name, "MethodBuilder"))
10856                 if (((MonoReflectionMethodBuilder*)obj)->mhandle)
10857                         method = ((MonoReflectionMethodBuilder*)obj)->mhandle;
10858                 else
10859                         method = methodbuilder_to_mono_method (gklass, (MonoReflectionMethodBuilder *) obj);
10860         else if (!strcmp (obj->vtable->klass->name, "ConstructorBuilder"))
10861                 method = ctorbuilder_to_mono_method (gklass, (MonoReflectionCtorBuilder *) obj);
10862         else if (!strcmp (obj->vtable->klass->name, "MonoMethod") || !strcmp (obj->vtable->klass->name, "MonoCMethod"))
10863                 method = ((MonoReflectionMethod *) obj)->method;
10864         else {
10865                 method = NULL; /* prevent compiler warning */
10866                 g_error ("can't handle type %s", obj->vtable->klass->name);
10867         }
10868
10869         return inflate_mono_method (mono_class_from_mono_type (mono_reflection_type_get_handle ((MonoReflectionType*)type)), method, obj);
10870 }
10871
10872 /*TODO avoid saving custom attrs for generic classes as it's enough to have them on the generic type definition.*/
10873 void
10874 mono_reflection_generic_class_initialize (MonoReflectionGenericClass *type, MonoArray *fields)
10875 {
10876         MonoGenericClass *gclass;
10877         MonoDynamicGenericClass *dgclass;
10878         MonoClass *klass, *gklass;
10879         MonoType *gtype;
10880         int i;
10881
10882         gtype = mono_reflection_type_get_handle ((MonoReflectionType*)type);
10883         klass = mono_class_from_mono_type (gtype);
10884         g_assert (gtype->type == MONO_TYPE_GENERICINST);
10885         gclass = gtype->data.generic_class;
10886
10887         if (!gclass->is_dynamic)
10888                 return;
10889
10890         dgclass = (MonoDynamicGenericClass *) gclass;
10891
10892         if (dgclass->initialized)
10893                 return;
10894
10895         gklass = gclass->container_class;
10896         mono_class_init (gklass);
10897
10898         dgclass->count_fields = fields ? mono_array_length (fields) : 0;
10899
10900         dgclass->fields = mono_image_set_new0 (gclass->owner, MonoClassField, dgclass->count_fields);
10901         dgclass->field_objects = mono_image_set_new0 (gclass->owner, MonoObject*, dgclass->count_fields);
10902         dgclass->field_generic_types = mono_image_set_new0 (gclass->owner, MonoType*, dgclass->count_fields);
10903
10904         for (i = 0; i < dgclass->count_fields; i++) {
10905                 MonoObject *obj = mono_array_get (fields, gpointer, i);
10906                 MonoClassField *field, *inflated_field = NULL;
10907
10908                 if (!strcmp (obj->vtable->klass->name, "FieldBuilder"))
10909                         inflated_field = field = fieldbuilder_to_mono_class_field (klass, (MonoReflectionFieldBuilder *) obj);
10910                 else if (!strcmp (obj->vtable->klass->name, "MonoField"))
10911                         field = ((MonoReflectionField *) obj)->field;
10912                 else {
10913                         field = NULL; /* prevent compiler warning */
10914                         g_assert_not_reached ();
10915                 }
10916
10917                 dgclass->fields [i] = *field;
10918                 dgclass->fields [i].parent = klass;
10919                 dgclass->fields [i].type = mono_class_inflate_generic_type (
10920                         field->type, mono_generic_class_get_context ((MonoGenericClass *) dgclass));
10921                 dgclass->field_generic_types [i] = field->type;
10922                 MONO_GC_REGISTER_ROOT_IF_MOVING (dgclass->field_objects [i]);
10923                 dgclass->field_objects [i] = obj;
10924
10925                 if (inflated_field) {
10926                         g_free (inflated_field);
10927                 } else {
10928                         dgclass->fields [i].name = mono_image_set_strdup (gclass->owner, dgclass->fields [i].name);
10929                 }
10930         }
10931
10932         dgclass->initialized = TRUE;
10933 }
10934
10935 void
10936 mono_reflection_free_dynamic_generic_class (MonoGenericClass *gclass)
10937 {
10938         MonoDynamicGenericClass *dgclass;
10939         int i;
10940
10941         g_assert (gclass->is_dynamic);
10942
10943         dgclass = (MonoDynamicGenericClass *)gclass;
10944
10945         for (i = 0; i < dgclass->count_fields; ++i) {
10946                 MonoClassField *field = dgclass->fields + i;
10947                 mono_metadata_free_type (field->type);
10948                 MONO_GC_UNREGISTER_ROOT_IF_MOVING (dgclass->field_objects [i]);
10949         }
10950 }
10951
10952 static void
10953 fix_partial_generic_class (MonoClass *klass)
10954 {
10955         MonoClass *gklass = klass->generic_class->container_class;
10956         MonoDynamicGenericClass *dgclass;
10957         int i;
10958
10959         if (klass->wastypebuilder)
10960                 return;
10961
10962         dgclass = (MonoDynamicGenericClass *)  klass->generic_class;
10963         if (klass->parent != gklass->parent) {
10964                 MonoError error;
10965                 MonoType *parent_type = mono_class_inflate_generic_type_checked (&gklass->parent->byval_arg, &klass->generic_class->context, &error);
10966                 if (mono_error_ok (&error)) {
10967                         MonoClass *parent = mono_class_from_mono_type (parent_type);
10968                         mono_metadata_free_type (parent_type);
10969                         if (parent != klass->parent) {
10970                                 /*fool mono_class_setup_parent*/
10971                                 klass->supertypes = NULL;
10972                                 mono_class_setup_parent (klass, parent);
10973                         }
10974                 } else {
10975                         mono_class_set_failure (klass, MONO_EXCEPTION_TYPE_LOAD, NULL);
10976                         mono_error_cleanup (&error);
10977                         if (gklass->wastypebuilder)
10978                                 klass->wastypebuilder = TRUE;
10979                         return;
10980                 }
10981         }
10982
10983         if (!dgclass->initialized)
10984                 return;
10985
10986         if (klass->method.count != gklass->method.count) {
10987                 klass->method.count = gklass->method.count;
10988                 klass->methods = mono_image_alloc (klass->image, sizeof (MonoMethod*) * (klass->method.count + 1));
10989
10990                 for (i = 0; i < klass->method.count; i++) {
10991                         MonoError error;
10992                         klass->methods [i] = mono_class_inflate_generic_method_full_checked (
10993                                 gklass->methods [i], klass, mono_class_get_context (klass), &error);
10994                         g_assert (mono_error_ok (&error)); /* FIXME don't swallow the error */
10995                 }
10996         }
10997
10998         if (klass->interface_count && klass->interface_count != gklass->interface_count) {
10999                 klass->interface_count = gklass->interface_count;
11000                 klass->interfaces = mono_image_alloc (klass->image, sizeof (MonoClass*) * gklass->interface_count);
11001                 klass->interfaces_packed = NULL; /*make setup_interface_offsets happy*/
11002
11003                 for (i = 0; i < gklass->interface_count; ++i) {
11004                         MonoType *iface_type = mono_class_inflate_generic_type (&gklass->interfaces [i]->byval_arg, mono_class_get_context (klass));
11005                         klass->interfaces [i] = mono_class_from_mono_type (iface_type);
11006                         mono_metadata_free_type (iface_type);
11007
11008                         ensure_runtime_vtable (klass->interfaces [i]);
11009                 }
11010                 klass->interfaces_inited = 1;
11011         }
11012
11013         if (klass->field.count != gklass->field.count) {
11014                 klass->field.count = gklass->field.count;
11015                 klass->fields = image_g_new0 (klass->image, MonoClassField, klass->field.count);
11016
11017                 for (i = 0; i < klass->field.count; i++) {
11018                         klass->fields [i] = gklass->fields [i];
11019                         klass->fields [i].parent = klass;
11020                         klass->fields [i].type = mono_class_inflate_generic_type (gklass->fields [i].type, mono_class_get_context (klass));
11021                 }
11022         }
11023
11024         /*We can only finish with this klass once it's parent has as well*/
11025         if (gklass->wastypebuilder)
11026                 klass->wastypebuilder = TRUE;
11027         return;
11028 }
11029
11030 static void
11031 ensure_generic_class_runtime_vtable (MonoClass *klass)
11032 {
11033         MonoClass *gklass = klass->generic_class->container_class;
11034
11035         ensure_runtime_vtable (gklass); 
11036
11037         fix_partial_generic_class (klass);
11038 }
11039
11040 static void
11041 ensure_runtime_vtable (MonoClass *klass)
11042 {
11043         MonoReflectionTypeBuilder *tb = mono_class_get_ref_info (klass);
11044         int i, num, j;
11045
11046         if (!image_is_dynamic (klass->image) || (!tb && !klass->generic_class) || klass->wastypebuilder)
11047                 return;
11048         if (klass->parent)
11049                 ensure_runtime_vtable (klass->parent);
11050
11051         if (tb) {
11052                 num = tb->ctors? mono_array_length (tb->ctors): 0;
11053                 num += tb->num_methods;
11054                 klass->method.count = num;
11055                 klass->methods = mono_image_alloc (klass->image, sizeof (MonoMethod*) * num);
11056                 num = tb->ctors? mono_array_length (tb->ctors): 0;
11057                 for (i = 0; i < num; ++i)
11058                         klass->methods [i] = ctorbuilder_to_mono_method (klass, mono_array_get (tb->ctors, MonoReflectionCtorBuilder*, i));
11059                 num = tb->num_methods;
11060                 j = i;
11061                 for (i = 0; i < num; ++i)
11062                         klass->methods [j++] = methodbuilder_to_mono_method (klass, mono_array_get (tb->methods, MonoReflectionMethodBuilder*, i));
11063         
11064                 if (tb->interfaces) {
11065                         klass->interface_count = mono_array_length (tb->interfaces);
11066                         klass->interfaces = mono_image_alloc (klass->image, sizeof (MonoClass*) * klass->interface_count);
11067                         for (i = 0; i < klass->interface_count; ++i) {
11068                                 MonoType *iface = mono_type_array_get_and_resolve (tb->interfaces, i);
11069                                 klass->interfaces [i] = mono_class_from_mono_type (iface);
11070                                 ensure_runtime_vtable (klass->interfaces [i]);
11071                         }
11072                         klass->interfaces_inited = 1;
11073                 }
11074         } else if (klass->generic_class){
11075                 ensure_generic_class_runtime_vtable (klass);
11076         }
11077
11078         if (klass->flags & TYPE_ATTRIBUTE_INTERFACE) {
11079                 int slot_num = 0;
11080                 for (i = 0; i < klass->method.count; ++i) {
11081                         MonoMethod *im = klass->methods [i];
11082                         if (!(im->flags & METHOD_ATTRIBUTE_STATIC))
11083                                 im->slot = slot_num++;
11084                 }
11085                 
11086                 klass->interfaces_packed = NULL; /*make setup_interface_offsets happy*/
11087                 mono_class_setup_interface_offsets (klass);
11088                 mono_class_setup_interface_id (klass);
11089         }
11090
11091         /*
11092          * The generic vtable is needed even if image->run is not set since some
11093          * runtime code like ves_icall_Type_GetMethodsByName depends on 
11094          * method->slot being defined.
11095          */
11096
11097         /* 
11098          * tb->methods could not be freed since it is used for determining 
11099          * overrides during dynamic vtable construction.
11100          */
11101 }
11102
11103 static MonoMethod*
11104 mono_reflection_method_get_handle (MonoObject *method)
11105 {
11106         MonoClass *class = mono_object_class (method);
11107         if (is_sr_mono_method (class) || is_sr_mono_generic_method (class)) {
11108                 MonoReflectionMethod *sr_method = (MonoReflectionMethod*)method;
11109                 return sr_method->method;
11110         }
11111         if (is_sre_method_builder (class)) {
11112                 MonoReflectionMethodBuilder *mb = (MonoReflectionMethodBuilder*)method;
11113                 return mb->mhandle;
11114         }
11115         if (is_sre_method_on_tb_inst (class)) {
11116                 MonoReflectionMethodOnTypeBuilderInst *m = (MonoReflectionMethodOnTypeBuilderInst*)method;
11117                 MonoMethod *result;
11118                 /*FIXME move this to a proper method and unify with resolve_object*/
11119                 if (m->method_args) {
11120                         result = mono_reflection_method_on_tb_inst_get_handle (m);
11121                 } else {
11122                         MonoType *type = mono_reflection_type_get_handle ((MonoReflectionType*)m->inst);
11123                         MonoClass *inflated_klass = mono_class_from_mono_type (type);
11124                         MonoMethod *mono_method;
11125
11126                         if (is_sre_method_builder (mono_object_class (m->mb)))
11127                                 mono_method = ((MonoReflectionMethodBuilder *)m->mb)->mhandle;
11128                         else if (is_sr_mono_method (mono_object_class (m->mb)))
11129                                 mono_method = ((MonoReflectionMethod *)m->mb)->method;
11130                         else
11131                                 g_error ("resolve_object:: can't handle a MTBI with base_method of type %s", mono_type_get_full_name (mono_object_class (m->mb)));
11132
11133                         result = inflate_mono_method (inflated_klass, mono_method, (MonoObject*)m->mb);
11134                 }
11135                 return result;
11136         }
11137
11138         g_error ("Can't handle methods of type %s:%s", class->name_space, class->name);
11139         return NULL;
11140 }
11141
11142 void
11143 mono_reflection_get_dynamic_overrides (MonoClass *klass, MonoMethod ***overrides, int *num_overrides)
11144 {
11145         MonoReflectionTypeBuilder *tb;
11146         int i, j, onum;
11147         MonoReflectionMethod *m;
11148
11149         *overrides = NULL;
11150         *num_overrides = 0;
11151
11152         g_assert (image_is_dynamic (klass->image));
11153
11154         if (!mono_class_get_ref_info (klass))
11155                 return;
11156
11157         g_assert (strcmp (((MonoObject*)mono_class_get_ref_info (klass))->vtable->klass->name, "TypeBuilder") == 0);
11158
11159         tb = (MonoReflectionTypeBuilder*)mono_class_get_ref_info (klass);
11160
11161         onum = 0;
11162         if (tb->methods) {
11163                 for (i = 0; i < tb->num_methods; ++i) {
11164                         MonoReflectionMethodBuilder *mb = 
11165                                 mono_array_get (tb->methods, MonoReflectionMethodBuilder*, i);
11166                         if (mb->override_methods)
11167                                 onum += mono_array_length (mb->override_methods);
11168                 }
11169         }
11170
11171         if (onum) {
11172                 *overrides = g_new0 (MonoMethod*, onum * 2);
11173
11174                 onum = 0;
11175                 for (i = 0; i < tb->num_methods; ++i) {
11176                         MonoReflectionMethodBuilder *mb = 
11177                                 mono_array_get (tb->methods, MonoReflectionMethodBuilder*, i);
11178                         if (mb->override_methods) {
11179                                 for (j = 0; j < mono_array_length (mb->override_methods); ++j) {
11180                                         m = mono_array_get (mb->override_methods, MonoReflectionMethod*, j);
11181
11182                                         (*overrides) [onum * 2] = mono_reflection_method_get_handle ((MonoObject*)m);
11183                                         (*overrides) [onum * 2 + 1] = mb->mhandle;
11184
11185                                         g_assert (mb->mhandle);
11186
11187                                         onum ++;
11188                                 }
11189                         }
11190                 }
11191         }
11192
11193         *num_overrides = onum;
11194 }
11195
11196 static void
11197 typebuilder_setup_fields (MonoClass *klass, MonoError *error)
11198 {
11199         MonoReflectionTypeBuilder *tb = mono_class_get_ref_info (klass);
11200         MonoReflectionFieldBuilder *fb;
11201         MonoClassField *field;
11202         MonoImage *image = klass->image;
11203         const char *p, *p2;
11204         int i;
11205         guint32 len, idx, real_size = 0;
11206
11207         klass->field.count = tb->num_fields;
11208         klass->field.first = 0;
11209
11210         mono_error_init (error);
11211
11212         if (tb->class_size) {
11213                 if ((tb->packing_size & 0xffffff00) != 0) {
11214                         char *err_msg = g_strdup_printf ("Could not load struct '%s' with packing size %d >= 256", klass->name, tb->packing_size);
11215                         mono_class_set_failure (klass, MONO_EXCEPTION_TYPE_LOAD, err_msg);
11216                         return;
11217                 }
11218                 klass->packing_size = tb->packing_size;
11219                 real_size = klass->instance_size + tb->class_size;
11220         }
11221
11222         if (!klass->field.count) {
11223                 klass->instance_size = MAX (klass->instance_size, real_size);
11224                 return;
11225         }
11226         
11227         klass->fields = image_g_new0 (image, MonoClassField, klass->field.count);
11228         mono_class_alloc_ext (klass);
11229         klass->ext->field_def_values = image_g_new0 (image, MonoFieldDefaultValue, klass->field.count);
11230         /*
11231         This is, guess what, a hack.
11232         The issue is that the runtime doesn't know how to setup the fields of a typebuider and crash.
11233         On the static path no field class is resolved, only types are built. This is the right thing to do
11234         but we suck.
11235         Setting size_inited is harmless because we're doing the same job as mono_class_setup_fields anyway.
11236         */
11237         klass->size_inited = 1;
11238
11239         for (i = 0; i < klass->field.count; ++i) {
11240                 MonoArray *rva_data;
11241                 fb = mono_array_get (tb->fields, gpointer, i);
11242                 field = &klass->fields [i];
11243                 field->name = mono_string_to_utf8_image (image, fb->name, error);
11244                 if (!mono_error_ok (error))
11245                         return;
11246                 if (fb->attrs) {
11247                         field->type = mono_metadata_type_dup (klass->image, mono_reflection_type_get_handle ((MonoReflectionType*)fb->type));
11248                         field->type->attrs = fb->attrs;
11249                 } else {
11250                         field->type = mono_reflection_type_get_handle ((MonoReflectionType*)fb->type);
11251                 }
11252
11253                 if ((fb->attrs & FIELD_ATTRIBUTE_HAS_FIELD_RVA) && (rva_data = fb->rva_data)) {
11254                         char *base = mono_array_addr (rva_data, char, 0);
11255                         size_t size = mono_array_length (rva_data);
11256                         char *data = mono_image_alloc (klass->image, size);
11257                         memcpy (data, base, size);
11258                         klass->ext->field_def_values [i].data = data;
11259                 }
11260                 if (fb->offset != -1)
11261                         field->offset = fb->offset;
11262                 field->parent = klass;
11263                 fb->handle = field;
11264                 mono_save_custom_attrs (klass->image, field, fb->cattrs);
11265
11266                 if (klass->enumtype && !(field->type->attrs & FIELD_ATTRIBUTE_STATIC)) {
11267                         klass->cast_class = klass->element_class = mono_class_from_mono_type (field->type);
11268                 }
11269                 if (fb->def_value) {
11270                         MonoDynamicImage *assembly = (MonoDynamicImage*)klass->image;
11271                         field->type->attrs |= FIELD_ATTRIBUTE_HAS_DEFAULT;
11272                         idx = encode_constant (assembly, fb->def_value, &klass->ext->field_def_values [i].def_type);
11273                         /* Copy the data from the blob since it might get realloc-ed */
11274                         p = assembly->blob.data + idx;
11275                         len = mono_metadata_decode_blob_size (p, &p2);
11276                         len += p2 - p;
11277                         klass->ext->field_def_values [i].data = mono_image_alloc (image, len);
11278                         memcpy ((gpointer)klass->ext->field_def_values [i].data, p, len);
11279                 }
11280         }
11281
11282         klass->instance_size = MAX (klass->instance_size, real_size);
11283         mono_class_layout_fields (klass);
11284 }
11285
11286 static void
11287 typebuilder_setup_properties (MonoClass *klass, MonoError *error)
11288 {
11289         MonoReflectionTypeBuilder *tb = mono_class_get_ref_info (klass);
11290         MonoReflectionPropertyBuilder *pb;
11291         MonoImage *image = klass->image;
11292         MonoProperty *properties;
11293         int i;
11294
11295         mono_error_init (error);
11296
11297         if (!klass->ext)
11298                 klass->ext = image_g_new0 (image, MonoClassExt, 1);
11299
11300         klass->ext->property.count = tb->properties ? mono_array_length (tb->properties) : 0;
11301         klass->ext->property.first = 0;
11302
11303         properties = image_g_new0 (image, MonoProperty, klass->ext->property.count);
11304         klass->ext->properties = properties;
11305         for (i = 0; i < klass->ext->property.count; ++i) {
11306                 pb = mono_array_get (tb->properties, MonoReflectionPropertyBuilder*, i);
11307                 properties [i].parent = klass;
11308                 properties [i].attrs = pb->attrs;
11309                 properties [i].name = mono_string_to_utf8_image (image, pb->name, error);
11310                 if (!mono_error_ok (error))
11311                         return;
11312                 if (pb->get_method)
11313                         properties [i].get = pb->get_method->mhandle;
11314                 if (pb->set_method)
11315                         properties [i].set = pb->set_method->mhandle;
11316
11317                 mono_save_custom_attrs (klass->image, &properties [i], pb->cattrs);
11318                 if (pb->def_value) {
11319                         guint32 len, idx;
11320                         const char *p, *p2;
11321                         MonoDynamicImage *assembly = (MonoDynamicImage*)klass->image;
11322                         if (!klass->ext->prop_def_values)
11323                                 klass->ext->prop_def_values = image_g_new0 (image, MonoFieldDefaultValue, klass->ext->property.count);
11324                         properties [i].attrs |= PROPERTY_ATTRIBUTE_HAS_DEFAULT;
11325                         idx = encode_constant (assembly, pb->def_value, &klass->ext->prop_def_values [i].def_type);
11326                         /* Copy the data from the blob since it might get realloc-ed */
11327                         p = assembly->blob.data + idx;
11328                         len = mono_metadata_decode_blob_size (p, &p2);
11329                         len += p2 - p;
11330                         klass->ext->prop_def_values [i].data = mono_image_alloc (image, len);
11331                         memcpy ((gpointer)klass->ext->prop_def_values [i].data, p, len);
11332                 }
11333         }
11334 }
11335
11336 MonoReflectionEvent *
11337 mono_reflection_event_builder_get_event_info (MonoReflectionTypeBuilder *tb, MonoReflectionEventBuilder *eb)
11338 {
11339         MonoEvent *event = g_new0 (MonoEvent, 1);
11340         MonoClass *klass;
11341
11342         klass = mono_class_from_mono_type (mono_reflection_type_get_handle ((MonoReflectionType*)tb));
11343
11344         event->parent = klass;
11345         event->attrs = eb->attrs;
11346         event->name = mono_string_to_utf8 (eb->name);
11347         if (eb->add_method)
11348                 event->add = eb->add_method->mhandle;
11349         if (eb->remove_method)
11350                 event->remove = eb->remove_method->mhandle;
11351         if (eb->raise_method)
11352                 event->raise = eb->raise_method->mhandle;
11353
11354 #ifndef MONO_SMALL_CONFIG
11355         if (eb->other_methods) {
11356                 int j;
11357                 event->other = g_new0 (MonoMethod*, mono_array_length (eb->other_methods) + 1);
11358                 for (j = 0; j < mono_array_length (eb->other_methods); ++j) {
11359                         MonoReflectionMethodBuilder *mb = 
11360                                 mono_array_get (eb->other_methods,
11361                                                 MonoReflectionMethodBuilder*, j);
11362                         event->other [j] = mb->mhandle;
11363                 }
11364         }
11365 #endif
11366
11367         return mono_event_get_object (mono_object_domain (tb), klass, event);
11368 }
11369
11370 static void
11371 typebuilder_setup_events (MonoClass *klass, MonoError *error)
11372 {
11373         MonoReflectionTypeBuilder *tb = mono_class_get_ref_info (klass);
11374         MonoReflectionEventBuilder *eb;
11375         MonoImage *image = klass->image;
11376         MonoEvent *events;
11377         int i;
11378
11379         mono_error_init (error);
11380
11381         if (!klass->ext)
11382                 klass->ext = image_g_new0 (image, MonoClassExt, 1);
11383
11384         klass->ext->event.count = tb->events ? mono_array_length (tb->events) : 0;
11385         klass->ext->event.first = 0;
11386
11387         events = image_g_new0 (image, MonoEvent, klass->ext->event.count);
11388         klass->ext->events = events;
11389         for (i = 0; i < klass->ext->event.count; ++i) {
11390                 eb = mono_array_get (tb->events, MonoReflectionEventBuilder*, i);
11391                 events [i].parent = klass;
11392                 events [i].attrs = eb->attrs;
11393                 events [i].name = mono_string_to_utf8_image (image, eb->name, error);
11394                 if (!mono_error_ok (error))
11395                         return;
11396                 if (eb->add_method)
11397                         events [i].add = eb->add_method->mhandle;
11398                 if (eb->remove_method)
11399                         events [i].remove = eb->remove_method->mhandle;
11400                 if (eb->raise_method)
11401                         events [i].raise = eb->raise_method->mhandle;
11402
11403 #ifndef MONO_SMALL_CONFIG
11404                 if (eb->other_methods) {
11405                         int j;
11406                         events [i].other = image_g_new0 (image, MonoMethod*, mono_array_length (eb->other_methods) + 1);
11407                         for (j = 0; j < mono_array_length (eb->other_methods); ++j) {
11408                                 MonoReflectionMethodBuilder *mb = 
11409                                         mono_array_get (eb->other_methods,
11410                                                                         MonoReflectionMethodBuilder*, j);
11411                                 events [i].other [j] = mb->mhandle;
11412                         }
11413                 }
11414 #endif
11415                 mono_save_custom_attrs (klass->image, &events [i], eb->cattrs);
11416         }
11417 }
11418
11419 static gboolean
11420 remove_instantiations_of_and_ensure_contents (gpointer key,
11421                                                   gpointer value,
11422                                                   gpointer user_data)
11423 {
11424         MonoType *type = (MonoType*)key;
11425         MonoClass *klass = (MonoClass*)user_data;
11426
11427         if ((type->type == MONO_TYPE_GENERICINST) && (type->data.generic_class->container_class == klass)) {
11428                 fix_partial_generic_class (mono_class_from_mono_type (type)); //Ensure it's safe to use it.
11429                 return TRUE;
11430         } else
11431                 return FALSE;
11432 }
11433
11434 static void
11435 check_array_for_usertypes (MonoArray *arr)
11436 {
11437         int i;
11438
11439         if (!arr)
11440                 return;
11441
11442         for (i = 0; i < mono_array_length (arr); ++i)
11443                 RESOLVE_ARRAY_TYPE_ELEMENT (arr, i);
11444 }
11445
11446 MonoReflectionType*
11447 mono_reflection_create_runtime_class (MonoReflectionTypeBuilder *tb)
11448 {
11449         MonoError error;
11450         MonoClass *klass;
11451         MonoDomain* domain;
11452         MonoReflectionType* res;
11453         int i, j;
11454
11455         domain = mono_object_domain (tb);
11456         klass = mono_class_from_mono_type (tb->type.type);
11457
11458         /*
11459          * Check for user defined Type subclasses.
11460          */
11461         RESOLVE_TYPE (tb->parent);
11462         check_array_for_usertypes (tb->interfaces);
11463         if (tb->fields) {
11464                 for (i = 0; i < mono_array_length (tb->fields); ++i) {
11465                         MonoReflectionFieldBuilder *fb = mono_array_get (tb->fields, gpointer, i);
11466                         if (fb) {
11467                                 RESOLVE_TYPE (fb->type);
11468                                 check_array_for_usertypes (fb->modreq);
11469                                 check_array_for_usertypes (fb->modopt);
11470                                 if (fb->marshal_info && fb->marshal_info->marshaltyperef)
11471                                         RESOLVE_TYPE (fb->marshal_info->marshaltyperef);
11472                         }
11473                 }
11474         }
11475         if (tb->methods) {
11476                 for (i = 0; i < mono_array_length (tb->methods); ++i) {
11477                         MonoReflectionMethodBuilder *mb = mono_array_get (tb->methods, gpointer, i);
11478                         if (mb) {
11479                                 RESOLVE_TYPE (mb->rtype);
11480                                 check_array_for_usertypes (mb->return_modreq);
11481                                 check_array_for_usertypes (mb->return_modopt);
11482                                 check_array_for_usertypes (mb->parameters);
11483                                 if (mb->param_modreq)
11484                                         for (j = 0; j < mono_array_length (mb->param_modreq); ++j)
11485                                                 check_array_for_usertypes (mono_array_get (mb->param_modreq, MonoArray*, j));
11486                                 if (mb->param_modopt)
11487                                         for (j = 0; j < mono_array_length (mb->param_modopt); ++j)
11488                                                 check_array_for_usertypes (mono_array_get (mb->param_modopt, MonoArray*, j));
11489                         }
11490                 }
11491         }
11492         if (tb->ctors) {
11493                 for (i = 0; i < mono_array_length (tb->ctors); ++i) {
11494                         MonoReflectionCtorBuilder *mb = mono_array_get (tb->ctors, gpointer, i);
11495                         if (mb) {
11496                                 check_array_for_usertypes (mb->parameters);
11497                                 if (mb->param_modreq)
11498                                         for (j = 0; j < mono_array_length (mb->param_modreq); ++j)
11499                                                 check_array_for_usertypes (mono_array_get (mb->param_modreq, MonoArray*, j));
11500                                 if (mb->param_modopt)
11501                                         for (j = 0; j < mono_array_length (mb->param_modopt); ++j)
11502                                                 check_array_for_usertypes (mono_array_get (mb->param_modopt, MonoArray*, j));
11503                         }
11504                 }
11505         }
11506
11507         mono_save_custom_attrs (klass->image, klass, tb->cattrs);
11508
11509         /* 
11510          * we need to lock the domain because the lock will be taken inside
11511          * So, we need to keep the locking order correct.
11512          */
11513         mono_loader_lock ();
11514         mono_domain_lock (domain);
11515         if (klass->wastypebuilder) {
11516                 mono_domain_unlock (domain);
11517                 mono_loader_unlock ();
11518                 return mono_type_get_object (mono_object_domain (tb), &klass->byval_arg);
11519         }
11520         /*
11521          * Fields to set in klass:
11522          * the various flags: delegate/unicode/contextbound etc.
11523          */
11524         klass->flags = tb->attrs;
11525         klass->has_cctor = 1;
11526         klass->has_finalize = 1;
11527         klass->has_finalize_inited = 1;
11528
11529         mono_class_setup_parent (klass, klass->parent);
11530         /* fool mono_class_setup_supertypes */
11531         klass->supertypes = NULL;
11532         mono_class_setup_supertypes (klass);
11533         mono_class_setup_mono_type (klass);
11534
11535 #if 0
11536         if (!((MonoDynamicImage*)klass->image)->run) {
11537                 if (klass->generic_container) {
11538                         /* FIXME: The code below can't handle generic classes */
11539                         klass->wastypebuilder = TRUE;
11540                         mono_loader_unlock ();
11541                         mono_domain_unlock (domain);
11542                         return mono_type_get_object (mono_object_domain (tb), &klass->byval_arg);
11543                 }
11544         }
11545 #endif
11546
11547         /* enums are done right away */
11548         if (!klass->enumtype)
11549                 ensure_runtime_vtable (klass);
11550
11551         if (tb->subtypes) {
11552                 for (i = 0; i < mono_array_length (tb->subtypes); ++i) {
11553                         MonoReflectionTypeBuilder *subtb = mono_array_get (tb->subtypes, MonoReflectionTypeBuilder*, i);
11554                         mono_class_alloc_ext (klass);
11555                         klass->ext->nested_classes = g_list_prepend_image (klass->image, klass->ext->nested_classes, mono_class_from_mono_type (mono_reflection_type_get_handle ((MonoReflectionType*)subtb)));
11556                 }
11557         }
11558
11559         klass->nested_classes_inited = TRUE;
11560
11561         /* fields and object layout */
11562         if (klass->parent) {
11563                 if (!klass->parent->size_inited)
11564                         mono_class_init (klass->parent);
11565                 klass->instance_size = klass->parent->instance_size;
11566                 klass->sizes.class_size = 0;
11567                 klass->min_align = klass->parent->min_align;
11568                 /* if the type has no fields we won't call the field_setup
11569                  * routine which sets up klass->has_references.
11570                  */
11571                 klass->has_references |= klass->parent->has_references;
11572         } else {
11573                 klass->instance_size = sizeof (MonoObject);
11574                 klass->min_align = 1;
11575         }
11576
11577         /* FIXME: handle packing_size and instance_size */
11578         typebuilder_setup_fields (klass, &error);
11579         if (!mono_error_ok (&error))
11580                 goto failure;
11581         typebuilder_setup_properties (klass, &error);
11582         if (!mono_error_ok (&error))
11583                 goto failure;
11584
11585         typebuilder_setup_events (klass, &error);
11586         if (!mono_error_ok (&error))
11587                 goto failure;
11588
11589         klass->wastypebuilder = TRUE;
11590
11591         /* 
11592          * If we are a generic TypeBuilder, there might be instantiations in the type cache
11593          * which have type System.Reflection.MonoGenericClass, but after the type is created, 
11594          * we want to return normal System.MonoType objects, so clear these out from the cache.
11595          *
11596          * Together with this we must ensure the contents of all instances to match the created type.
11597          */
11598         if (domain->type_hash && klass->generic_container)
11599                 mono_g_hash_table_foreach_remove (domain->type_hash, remove_instantiations_of_and_ensure_contents, klass);
11600
11601         mono_domain_unlock (domain);
11602         mono_loader_unlock ();
11603
11604         if (klass->enumtype && !mono_class_is_valid_enum (klass)) {
11605                 mono_class_set_failure (klass, MONO_EXCEPTION_TYPE_LOAD, NULL);
11606                 mono_raise_exception (mono_get_exception_type_load (tb->name, NULL));
11607         }
11608
11609         res = mono_type_get_object (mono_object_domain (tb), &klass->byval_arg);
11610         g_assert (res != (MonoReflectionType*)tb);
11611
11612         return res;
11613
11614 failure:
11615         mono_class_set_failure (klass, MONO_EXCEPTION_TYPE_LOAD, NULL);
11616         klass->wastypebuilder = TRUE;
11617         mono_domain_unlock (domain);
11618         mono_loader_unlock ();
11619         mono_error_raise_exception (&error);
11620         return NULL;
11621 }
11622
11623 void
11624 mono_reflection_initialize_generic_parameter (MonoReflectionGenericParam *gparam)
11625 {
11626         MonoGenericParamFull *param;
11627         MonoImage *image;
11628         MonoClass *pklass;
11629         MonoError error;
11630
11631         image = &gparam->tbuilder->module->dynamic_image->image;
11632
11633         param = mono_image_new0 (image, MonoGenericParamFull, 1);
11634
11635         param->info.name = mono_string_to_utf8_image (image, gparam->name, &error);
11636         g_assert (mono_error_ok (&error));
11637         param->param.num = gparam->index;
11638
11639         if (gparam->mbuilder) {
11640                 if (!gparam->mbuilder->generic_container) {
11641                         MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder *)gparam->mbuilder->type;
11642                         MonoClass *klass = mono_class_from_mono_type (mono_reflection_type_get_handle ((MonoReflectionType*)tb));
11643                         gparam->mbuilder->generic_container = mono_image_alloc0 (klass->image, sizeof (MonoGenericContainer));
11644                         gparam->mbuilder->generic_container->is_method = TRUE;
11645                         /* 
11646                          * Cannot set owner.method, since the MonoMethod is not created yet.
11647                          * Set the image field instead, so type_in_image () works.
11648                          */
11649                         gparam->mbuilder->generic_container->image = klass->image;
11650                 }
11651                 param->param.owner = gparam->mbuilder->generic_container;
11652         } else if (gparam->tbuilder) {
11653                 if (!gparam->tbuilder->generic_container) {
11654                         MonoClass *klass = mono_class_from_mono_type (mono_reflection_type_get_handle ((MonoReflectionType*)gparam->tbuilder));
11655                         gparam->tbuilder->generic_container = mono_image_alloc0 (klass->image, sizeof (MonoGenericContainer));
11656                         gparam->tbuilder->generic_container->owner.klass = klass;
11657                 }
11658                 param->param.owner = gparam->tbuilder->generic_container;
11659         }
11660
11661         pklass = mono_class_from_generic_parameter ((MonoGenericParam *) param, image, gparam->mbuilder != NULL);
11662
11663         gparam->type.type = &pklass->byval_arg;
11664
11665         mono_class_set_ref_info (pklass, gparam);
11666         mono_image_append_class_to_reflection_info_set (pklass);
11667 }
11668
11669 MonoArray *
11670 mono_reflection_sighelper_get_signature_local (MonoReflectionSigHelper *sig)
11671 {
11672         MonoReflectionModuleBuilder *module = sig->module;
11673         MonoDynamicImage *assembly = module != NULL ? module->dynamic_image : NULL;
11674         guint32 na = sig->arguments ? mono_array_length (sig->arguments) : 0;
11675         guint32 buflen, i;
11676         MonoArray *result;
11677         SigBuffer buf;
11678
11679         check_array_for_usertypes (sig->arguments);
11680
11681         sigbuffer_init (&buf, 32);
11682
11683         sigbuffer_add_value (&buf, 0x07);
11684         sigbuffer_add_value (&buf, na);
11685         if (assembly != NULL){
11686                 for (i = 0; i < na; ++i) {
11687                         MonoReflectionType *type = mono_array_get (sig->arguments, MonoReflectionType*, i);
11688                         encode_reflection_type (assembly, type, &buf);
11689                 }
11690         }
11691
11692         buflen = buf.p - buf.buf;
11693         result = mono_array_new (mono_domain_get (), mono_defaults.byte_class, buflen);
11694         memcpy (mono_array_addr (result, char, 0), buf.buf, buflen);
11695         sigbuffer_free (&buf);
11696
11697         return result;
11698 }
11699
11700 MonoArray *
11701 mono_reflection_sighelper_get_signature_field (MonoReflectionSigHelper *sig)
11702 {
11703         MonoDynamicImage *assembly = sig->module->dynamic_image;
11704         guint32 na = sig->arguments ? mono_array_length (sig->arguments) : 0;
11705         guint32 buflen, i;
11706         MonoArray *result;
11707         SigBuffer buf;
11708
11709         check_array_for_usertypes (sig->arguments);
11710
11711         sigbuffer_init (&buf, 32);
11712
11713         sigbuffer_add_value (&buf, 0x06);
11714         for (i = 0; i < na; ++i) {
11715                 MonoReflectionType *type = mono_array_get (sig->arguments, MonoReflectionType*, i);
11716                 encode_reflection_type (assembly, type, &buf);
11717         }
11718
11719         buflen = buf.p - buf.buf;
11720         result = mono_array_new (mono_domain_get (), mono_defaults.byte_class, buflen);
11721         memcpy (mono_array_addr (result, char, 0), buf.buf, buflen);
11722         sigbuffer_free (&buf);
11723
11724         return result;
11725 }
11726
11727 typedef struct {
11728         MonoMethod *handle;
11729         MonoDomain *domain;
11730 } DynamicMethodReleaseData;
11731
11732 /*
11733  * The runtime automatically clean up those after finalization.
11734 */      
11735 static MonoReferenceQueue *dynamic_method_queue;
11736
11737 static void
11738 free_dynamic_method (void *dynamic_method)
11739 {
11740         DynamicMethodReleaseData *data = dynamic_method;
11741
11742         mono_runtime_free_method (data->domain, data->handle);
11743         g_free (data);
11744 }
11745
11746 void 
11747 mono_reflection_create_dynamic_method (MonoReflectionDynamicMethod *mb)
11748 {
11749         MonoReferenceQueue *queue;
11750         MonoMethod *handle;
11751         DynamicMethodReleaseData *release_data;
11752         ReflectionMethodBuilder rmb;
11753         MonoMethodSignature *sig;
11754         MonoClass *klass;
11755         GSList *l;
11756         int i;
11757
11758         if (mono_runtime_is_shutting_down ())
11759                 mono_raise_exception (mono_get_exception_invalid_operation (""));
11760
11761         if (!(queue = dynamic_method_queue)) {
11762                 mono_loader_lock ();
11763                 if (!(queue = dynamic_method_queue))
11764                         queue = dynamic_method_queue = mono_gc_reference_queue_new (free_dynamic_method);
11765                 mono_loader_unlock ();
11766         }
11767
11768         sig = dynamic_method_to_signature (mb);
11769
11770         reflection_methodbuilder_from_dynamic_method (&rmb, mb);
11771
11772         /*
11773          * Resolve references.
11774          */
11775         /* 
11776          * Every second entry in the refs array is reserved for storing handle_class,
11777          * which is needed by the ldtoken implementation in the JIT.
11778          */
11779         rmb.nrefs = mb->nrefs;
11780         rmb.refs = g_new0 (gpointer, mb->nrefs + 1);
11781         for (i = 0; i < mb->nrefs; i += 2) {
11782                 MonoClass *handle_class;
11783                 gpointer ref;
11784                 MonoObject *obj = mono_array_get (mb->refs, MonoObject*, i);
11785
11786                 if (strcmp (obj->vtable->klass->name, "DynamicMethod") == 0) {
11787                         MonoReflectionDynamicMethod *method = (MonoReflectionDynamicMethod*)obj;
11788                         /*
11789                          * The referenced DynamicMethod should already be created by the managed
11790                          * code, except in the case of circular references. In that case, we store
11791                          * method in the refs array, and fix it up later when the referenced 
11792                          * DynamicMethod is created.
11793                          */
11794                         if (method->mhandle) {
11795                                 ref = method->mhandle;
11796                         } else {
11797                                 /* FIXME: GC object stored in unmanaged memory */
11798                                 ref = method;
11799
11800                                 /* FIXME: GC object stored in unmanaged memory */
11801                                 method->referenced_by = g_slist_append (method->referenced_by, mb);
11802                         }
11803                         handle_class = mono_defaults.methodhandle_class;
11804                 } else {
11805                         MonoException *ex = NULL;
11806                         ref = resolve_object (mb->module->image, obj, &handle_class, NULL);
11807                         if (!ref)
11808                                 ex = mono_get_exception_type_load (NULL, NULL);
11809                         else if (mono_security_core_clr_enabled ())
11810                                 ex = mono_security_core_clr_ensure_dynamic_method_resolved_object (ref, handle_class);
11811
11812                         if (ex) {
11813                                 g_free (rmb.refs);
11814                                 mono_raise_exception (ex);
11815                                 return;
11816                         }
11817                 }
11818
11819                 rmb.refs [i] = ref; /* FIXME: GC object stored in unmanaged memory (change also resolve_object() signature) */
11820                 rmb.refs [i + 1] = handle_class;
11821         }               
11822
11823         klass = mb->owner ? mono_class_from_mono_type (mono_reflection_type_get_handle ((MonoReflectionType*)mb->owner)) : mono_defaults.object_class;
11824
11825         mb->mhandle = handle = reflection_methodbuilder_to_mono_method (klass, &rmb, sig);
11826         release_data = g_new (DynamicMethodReleaseData, 1);
11827         release_data->handle = handle;
11828         release_data->domain = mono_object_get_domain ((MonoObject*)mb);
11829         if (!mono_gc_reference_queue_add (queue, (MonoObject*)mb, release_data))
11830                 g_free (release_data);
11831
11832         /* Fix up refs entries pointing at us */
11833         for (l = mb->referenced_by; l; l = l->next) {
11834                 MonoReflectionDynamicMethod *method = (MonoReflectionDynamicMethod*)l->data;
11835                 MonoMethodWrapper *wrapper = (MonoMethodWrapper*)method->mhandle;
11836                 gpointer *data;
11837                 
11838                 g_assert (method->mhandle);
11839
11840                 data = (gpointer*)wrapper->method_data;
11841                 for (i = 0; i < GPOINTER_TO_UINT (data [0]); i += 2) {
11842                         if ((data [i + 1] == mb) && (data [i + 1 + 1] == mono_defaults.methodhandle_class))
11843                                 data [i + 1] = mb->mhandle;
11844                 }
11845         }
11846         g_slist_free (mb->referenced_by);
11847
11848         g_free (rmb.refs);
11849
11850         /* ilgen is no longer needed */
11851         mb->ilgen = NULL;
11852 }
11853
11854 #endif /* DISABLE_REFLECTION_EMIT */
11855
11856 /**
11857  * 
11858  * mono_reflection_is_valid_dynamic_token:
11859  * 
11860  * Returns TRUE if token is valid.
11861  * 
11862  */
11863 gboolean
11864 mono_reflection_is_valid_dynamic_token (MonoDynamicImage *image, guint32 token)
11865 {
11866         return lookup_dyn_token (image, token) != NULL;
11867 }
11868
11869 MonoMethodSignature *
11870 mono_reflection_lookup_signature (MonoImage *image, MonoMethod *method, guint32 token, MonoError *error)
11871 {
11872         MonoMethodSignature *sig;
11873         g_assert (image_is_dynamic (image));
11874
11875         mono_error_init (error);
11876
11877         sig = g_hash_table_lookup (((MonoDynamicImage*)image)->vararg_aux_hash, GUINT_TO_POINTER (token));
11878         if (sig)
11879                 return sig;
11880
11881         return mono_method_signature_checked (method, error);
11882 }
11883
11884 #ifndef DISABLE_REFLECTION_EMIT
11885
11886 /**
11887  * mono_reflection_lookup_dynamic_token:
11888  *
11889  * Finish the Builder object pointed to by TOKEN and return the corresponding
11890  * runtime structure. If HANDLE_CLASS is not NULL, it is set to the class required by 
11891  * mono_ldtoken. If valid_token is TRUE, assert if it is not found in the token->object
11892  * mapping table.
11893  *
11894  * LOCKING: Take the loader lock
11895  */
11896 gpointer
11897 mono_reflection_lookup_dynamic_token (MonoImage *image, guint32 token, gboolean valid_token, MonoClass **handle_class, MonoGenericContext *context)
11898 {
11899         MonoDynamicImage *assembly = (MonoDynamicImage*)image;
11900         MonoObject *obj;
11901         MonoClass *klass;
11902
11903         obj = lookup_dyn_token (assembly, token);
11904         if (!obj) {
11905                 if (valid_token)
11906                         g_error ("Could not find required dynamic token 0x%08x", token);
11907                 else
11908                         return NULL;
11909         }
11910
11911         if (!handle_class)
11912                 handle_class = &klass;
11913         return resolve_object (image, obj, handle_class, context);
11914 }
11915
11916 /*
11917  * ensure_complete_type:
11918  *
11919  *   Ensure that KLASS is completed if it is a dynamic type, or references
11920  * dynamic types.
11921  */
11922 static void
11923 ensure_complete_type (MonoClass *klass)
11924 {
11925         if (image_is_dynamic (klass->image) && !klass->wastypebuilder && mono_class_get_ref_info (klass)) {
11926                 MonoReflectionTypeBuilder *tb = mono_class_get_ref_info (klass);
11927
11928                 mono_domain_try_type_resolve (mono_domain_get (), NULL, (MonoObject*)tb);
11929
11930                 // Asserting here could break a lot of code
11931                 //g_assert (klass->wastypebuilder);
11932         }
11933
11934         if (klass->generic_class) {
11935                 MonoGenericInst *inst = klass->generic_class->context.class_inst;
11936                 int i;
11937
11938                 for (i = 0; i < inst->type_argc; ++i) {
11939                         ensure_complete_type (mono_class_from_mono_type (inst->type_argv [i]));
11940                 }
11941         }
11942 }
11943
11944 static gpointer
11945 resolve_object (MonoImage *image, MonoObject *obj, MonoClass **handle_class, MonoGenericContext *context)
11946 {
11947         gpointer result = NULL;
11948
11949         if (strcmp (obj->vtable->klass->name, "String") == 0) {
11950                 result = mono_string_intern ((MonoString*)obj);
11951                 *handle_class = mono_defaults.string_class;
11952                 g_assert (result);
11953         } else if (strcmp (obj->vtable->klass->name, "MonoType") == 0) {
11954                 MonoType *type = mono_reflection_type_get_handle ((MonoReflectionType*)obj);
11955                 MonoClass *mc = mono_class_from_mono_type (type);
11956                 if (!mono_class_init (mc))
11957                         mono_raise_exception (mono_class_get_exception_for_failure (mc));
11958
11959                 if (context) {
11960                         MonoType *inflated = mono_class_inflate_generic_type (type, context);
11961                         result = mono_class_from_mono_type (inflated);
11962                         mono_metadata_free_type (inflated);
11963                 } else {
11964                         result = mono_class_from_mono_type (type);
11965                 }
11966                 *handle_class = mono_defaults.typehandle_class;
11967                 g_assert (result);
11968         } else if (strcmp (obj->vtable->klass->name, "MonoMethod") == 0 ||
11969                    strcmp (obj->vtable->klass->name, "MonoCMethod") == 0 ||
11970                    strcmp (obj->vtable->klass->name, "MonoGenericCMethod") == 0 ||
11971                    strcmp (obj->vtable->klass->name, "MonoGenericMethod") == 0) {
11972                 result = ((MonoReflectionMethod*)obj)->method;
11973                 if (context) {
11974                         MonoError error;
11975                         result = mono_class_inflate_generic_method_checked (result, context, &error);
11976                         g_assert (mono_error_ok (&error)); /* FIXME don't swallow the error */
11977                 }
11978                 *handle_class = mono_defaults.methodhandle_class;
11979                 g_assert (result);
11980         } else if (strcmp (obj->vtable->klass->name, "MethodBuilder") == 0) {
11981                 MonoReflectionMethodBuilder *mb = (MonoReflectionMethodBuilder*)obj;
11982                 result = mb->mhandle;
11983                 if (!result) {
11984                         /* Type is not yet created */
11985                         MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder*)mb->type;
11986
11987                         mono_domain_try_type_resolve (mono_domain_get (), NULL, (MonoObject*)tb);
11988
11989                         /*
11990                          * Hopefully this has been filled in by calling CreateType() on the
11991                          * TypeBuilder.
11992                          */
11993                         /*
11994                          * TODO: This won't work if the application finishes another 
11995                          * TypeBuilder instance instead of this one.
11996                          */
11997                         result = mb->mhandle;
11998                 }
11999                 if (context) {
12000                         MonoError error;
12001                         result = mono_class_inflate_generic_method_checked (result, context, &error);
12002                         g_assert (mono_error_ok (&error)); /* FIXME don't swallow the error */
12003                 }
12004                 *handle_class = mono_defaults.methodhandle_class;
12005         } else if (strcmp (obj->vtable->klass->name, "ConstructorBuilder") == 0) {
12006                 MonoReflectionCtorBuilder *cb = (MonoReflectionCtorBuilder*)obj;
12007
12008                 result = cb->mhandle;
12009                 if (!result) {
12010                         MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder*)cb->type;
12011
12012                         mono_domain_try_type_resolve (mono_domain_get (), NULL, (MonoObject*)tb);
12013                         result = cb->mhandle;
12014                 }
12015                 if (context) {
12016                         MonoError error;
12017                         result = mono_class_inflate_generic_method_checked (result, context, &error);
12018                         g_assert (mono_error_ok (&error)); /* FIXME don't swallow the error */
12019                 }
12020                 *handle_class = mono_defaults.methodhandle_class;
12021         } else if (strcmp (obj->vtable->klass->name, "MonoField") == 0) {
12022                 MonoClassField *field = ((MonoReflectionField*)obj)->field;
12023
12024                 ensure_complete_type (field->parent);
12025                 if (context) {
12026                         MonoType *inflated = mono_class_inflate_generic_type (&field->parent->byval_arg, context);
12027                         MonoClass *class = mono_class_from_mono_type (inflated);
12028                         MonoClassField *inflated_field;
12029                         gpointer iter = NULL;
12030                         mono_metadata_free_type (inflated);
12031                         while ((inflated_field = mono_class_get_fields (class, &iter))) {
12032                                 if (!strcmp (field->name, inflated_field->name))
12033                                         break;
12034                         }
12035                         g_assert (inflated_field && !strcmp (field->name, inflated_field->name));
12036                         result = inflated_field;
12037                 } else {
12038                         result = field;
12039                 }
12040                 *handle_class = mono_defaults.fieldhandle_class;
12041                 g_assert (result);
12042         } else if (strcmp (obj->vtable->klass->name, "FieldBuilder") == 0) {
12043                 MonoReflectionFieldBuilder *fb = (MonoReflectionFieldBuilder*)obj;
12044                 result = fb->handle;
12045
12046                 if (!result) {
12047                         MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder*)fb->typeb;
12048
12049                         mono_domain_try_type_resolve (mono_domain_get (), NULL, (MonoObject*)tb);
12050                         result = fb->handle;
12051                 }
12052
12053                 if (fb->handle && fb->handle->parent->generic_container) {
12054                         MonoClass *klass = fb->handle->parent;
12055                         MonoType *type = mono_class_inflate_generic_type (&klass->byval_arg, context);
12056                         MonoClass *inflated = mono_class_from_mono_type (type);
12057
12058                         result = mono_class_get_field_from_name (inflated, mono_field_get_name (fb->handle));
12059                         g_assert (result);
12060                         mono_metadata_free_type (type);
12061                 }
12062                 *handle_class = mono_defaults.fieldhandle_class;
12063         } else if (strcmp (obj->vtable->klass->name, "TypeBuilder") == 0) {
12064                 MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder*)obj;
12065                 MonoType *type = mono_reflection_type_get_handle ((MonoReflectionType*)tb); 
12066                 MonoClass *klass;
12067
12068                 klass = type->data.klass;
12069                 if (klass->wastypebuilder) {
12070                         /* Already created */
12071                         result = klass;
12072                 }
12073                 else {
12074                         mono_domain_try_type_resolve (mono_domain_get (), NULL, (MonoObject*)tb);
12075                         result = type->data.klass;
12076                         g_assert (result);
12077                 }
12078                 *handle_class = mono_defaults.typehandle_class;
12079         } else if (strcmp (obj->vtable->klass->name, "SignatureHelper") == 0) {
12080                 MonoReflectionSigHelper *helper = (MonoReflectionSigHelper*)obj;
12081                 MonoMethodSignature *sig;
12082                 int nargs, i;
12083
12084                 if (helper->arguments)
12085                         nargs = mono_array_length (helper->arguments);
12086                 else
12087                         nargs = 0;
12088
12089                 sig = mono_metadata_signature_alloc (image, nargs);
12090                 sig->explicit_this = helper->call_conv & 64 ? 1 : 0;
12091                 sig->hasthis = helper->call_conv & 32 ? 1 : 0;
12092
12093                 if (helper->unmanaged_call_conv) { /* unmanaged */
12094                         sig->call_convention = helper->unmanaged_call_conv - 1;
12095                         sig->pinvoke = TRUE;
12096                 } else if (helper->call_conv & 0x02) {
12097                         sig->call_convention = MONO_CALL_VARARG;
12098                 } else {
12099                         sig->call_convention = MONO_CALL_DEFAULT;
12100                 }
12101
12102                 sig->param_count = nargs;
12103                 /* TODO: Copy type ? */
12104                 sig->ret = helper->return_type->type;
12105                 for (i = 0; i < nargs; ++i)
12106                         sig->params [i] = mono_type_array_get_and_resolve (helper->arguments, i);
12107
12108                 result = sig;
12109                 *handle_class = NULL;
12110         } else if (strcmp (obj->vtable->klass->name, "DynamicMethod") == 0) {
12111                 MonoReflectionDynamicMethod *method = (MonoReflectionDynamicMethod*)obj;
12112                 /* Already created by the managed code */
12113                 g_assert (method->mhandle);
12114                 result = method->mhandle;
12115                 *handle_class = mono_defaults.methodhandle_class;
12116         } else if (strcmp (obj->vtable->klass->name, "GenericTypeParameterBuilder") == 0) {
12117                 MonoType *type = mono_reflection_type_get_handle ((MonoReflectionType*)obj);
12118                 type = mono_class_inflate_generic_type (type, context);
12119                 result = mono_class_from_mono_type (type);
12120                 *handle_class = mono_defaults.typehandle_class;
12121                 g_assert (result);
12122                 mono_metadata_free_type (type);
12123         } else if (strcmp (obj->vtable->klass->name, "MonoGenericClass") == 0) {
12124                 MonoType *type = mono_reflection_type_get_handle ((MonoReflectionType*)obj);
12125                 type = mono_class_inflate_generic_type (type, context);
12126                 result = mono_class_from_mono_type (type);
12127                 *handle_class = mono_defaults.typehandle_class;
12128                 g_assert (result);
12129                 mono_metadata_free_type (type);
12130         } else if (strcmp (obj->vtable->klass->name, "FieldOnTypeBuilderInst") == 0) {
12131                 MonoReflectionFieldOnTypeBuilderInst *f = (MonoReflectionFieldOnTypeBuilderInst*)obj;
12132                 MonoClass *inflated;
12133                 MonoType *type;
12134                 MonoClassField *field;
12135
12136                 if (is_sre_field_builder (mono_object_class (f->fb)))
12137                         field = ((MonoReflectionFieldBuilder*)f->fb)->handle;
12138                 else if (is_sr_mono_field (mono_object_class (f->fb)))
12139                         field = ((MonoReflectionField*)f->fb)->field;
12140                 else
12141                         g_error ("resolve_object:: can't handle a FTBI with base_method of type %s", mono_type_get_full_name (mono_object_class (f->fb)));
12142
12143                 type = mono_class_inflate_generic_type (mono_reflection_type_get_handle ((MonoReflectionType*)f->inst), context);
12144                 inflated = mono_class_from_mono_type (type);
12145
12146                 result = field = mono_class_get_field_from_name (inflated, mono_field_get_name (field));
12147                 ensure_complete_type (field->parent);
12148                 g_assert (result);
12149                 mono_metadata_free_type (type);
12150                 *handle_class = mono_defaults.fieldhandle_class;
12151         } else if (strcmp (obj->vtable->klass->name, "ConstructorOnTypeBuilderInst") == 0) {
12152                 MonoReflectionCtorOnTypeBuilderInst *c = (MonoReflectionCtorOnTypeBuilderInst*)obj;
12153                 MonoType *type = mono_class_inflate_generic_type (mono_reflection_type_get_handle ((MonoReflectionType*)c->inst), context);
12154                 MonoClass *inflated_klass = mono_class_from_mono_type (type);
12155                 MonoMethod *method;
12156
12157                 if (is_sre_ctor_builder (mono_object_class (c->cb)))
12158                         method = ((MonoReflectionCtorBuilder *)c->cb)->mhandle;
12159                 else if (is_sr_mono_cmethod (mono_object_class (c->cb)))
12160                         method = ((MonoReflectionMethod *)c->cb)->method;
12161                 else
12162                         g_error ("resolve_object:: can't handle a CTBI with base_method of type %s", mono_type_get_full_name (mono_object_class (c->cb)));
12163
12164                 result = inflate_mono_method (inflated_klass, method, (MonoObject*)c->cb);
12165                 *handle_class = mono_defaults.methodhandle_class;
12166                 mono_metadata_free_type (type);
12167         } else if (strcmp (obj->vtable->klass->name, "MethodOnTypeBuilderInst") == 0) {
12168                 MonoReflectionMethodOnTypeBuilderInst *m = (MonoReflectionMethodOnTypeBuilderInst*)obj;
12169                 if (m->method_args) {
12170                         result = mono_reflection_method_on_tb_inst_get_handle (m);
12171                         if (context) {
12172                                 MonoError error;
12173                                 result = mono_class_inflate_generic_method_checked (result, context, &error);
12174                                 g_assert (mono_error_ok (&error)); /* FIXME don't swallow the error */
12175                         }
12176                 } else {
12177                         MonoType *type = mono_class_inflate_generic_type (mono_reflection_type_get_handle ((MonoReflectionType*)m->inst), context);
12178                         MonoClass *inflated_klass = mono_class_from_mono_type (type);
12179                         MonoMethod *method;
12180
12181                         if (is_sre_method_builder (mono_object_class (m->mb)))
12182                                 method = ((MonoReflectionMethodBuilder *)m->mb)->mhandle;
12183                         else if (is_sr_mono_method (mono_object_class (m->mb)))
12184                                 method = ((MonoReflectionMethod *)m->mb)->method;
12185                         else
12186                                 g_error ("resolve_object:: can't handle a MTBI with base_method of type %s", mono_type_get_full_name (mono_object_class (m->mb)));
12187
12188                         result = inflate_mono_method (inflated_klass, method, (MonoObject*)m->mb);
12189                         mono_metadata_free_type (type);
12190                 }
12191                 *handle_class = mono_defaults.methodhandle_class;
12192         } else if (strcmp (obj->vtable->klass->name, "MonoArrayMethod") == 0) {
12193                 MonoReflectionArrayMethod *m = (MonoReflectionArrayMethod*)obj;
12194                 MonoType *mtype;
12195                 MonoClass *klass;
12196                 MonoMethod *method;
12197                 gpointer iter;
12198                 char *name;
12199
12200                 mtype = mono_reflection_type_get_handle (m->parent);
12201                 klass = mono_class_from_mono_type (mtype);
12202
12203                 /* Find the method */
12204
12205                 name = mono_string_to_utf8 (m->name);
12206                 iter = NULL;
12207                 while ((method = mono_class_get_methods (klass, &iter))) {
12208                         if (!strcmp (method->name, name))
12209                                 break;
12210                 }
12211                 g_free (name);
12212
12213                 // FIXME:
12214                 g_assert (method);
12215                 // FIXME: Check parameters/return value etc. match
12216
12217                 result = method;
12218                 *handle_class = mono_defaults.methodhandle_class;
12219         } else if (is_sre_array (mono_object_get_class(obj)) ||
12220                                 is_sre_byref (mono_object_get_class(obj)) ||
12221                                 is_sre_pointer (mono_object_get_class(obj))) {
12222                 MonoReflectionType *ref_type = (MonoReflectionType *)obj;
12223                 MonoType *type = mono_reflection_type_get_handle (ref_type);
12224
12225                 if (context) {
12226                         MonoType *inflated = mono_class_inflate_generic_type (type, context);
12227                         result = mono_class_from_mono_type (inflated);
12228                         mono_metadata_free_type (inflated);
12229                 } else {
12230                         result = mono_class_from_mono_type (type);
12231                 }
12232                 *handle_class = mono_defaults.typehandle_class;
12233         } else {
12234                 g_print ("%s\n", obj->vtable->klass->name);
12235                 g_assert_not_reached ();
12236         }
12237         return result;
12238 }
12239
12240 #else /* DISABLE_REFLECTION_EMIT */
12241
12242 MonoArray*
12243 mono_reflection_get_custom_attrs_blob (MonoReflectionAssembly *assembly, MonoObject *ctor, MonoArray *ctorArgs, MonoArray *properties, MonoArray *propValues, MonoArray *fields, MonoArray* fieldValues) 
12244 {
12245         g_assert_not_reached ();
12246         return NULL;
12247 }
12248
12249 void
12250 mono_reflection_setup_internal_class (MonoReflectionTypeBuilder *tb)
12251 {
12252         g_assert_not_reached ();
12253 }
12254
12255 void
12256 mono_reflection_setup_generic_class (MonoReflectionTypeBuilder *tb)
12257 {
12258         g_assert_not_reached ();
12259 }
12260
12261 void
12262 mono_reflection_create_generic_class (MonoReflectionTypeBuilder *tb)
12263 {
12264         g_assert_not_reached ();
12265 }
12266
12267 void
12268 mono_reflection_create_internal_class (MonoReflectionTypeBuilder *tb)
12269 {
12270         g_assert_not_reached ();
12271 }
12272
12273 void
12274 mono_image_basic_init (MonoReflectionAssemblyBuilder *assemblyb)
12275 {
12276         g_error ("This mono runtime was configured with --enable-minimal=reflection_emit, so System.Reflection.Emit is not supported.");
12277 }
12278
12279 void
12280 mono_image_module_basic_init (MonoReflectionModuleBuilder *moduleb)
12281 {
12282         g_assert_not_reached ();
12283 }
12284
12285 void
12286 mono_image_set_wrappers_type (MonoReflectionModuleBuilder *moduleb, MonoReflectionType *type)
12287 {
12288         g_assert_not_reached ();
12289 }
12290
12291 MonoReflectionModule *
12292 mono_image_load_module_dynamic (MonoReflectionAssemblyBuilder *ab, MonoString *fileName)
12293 {
12294         g_assert_not_reached ();
12295         return NULL;
12296 }
12297
12298 guint32
12299 mono_image_insert_string (MonoReflectionModuleBuilder *module, MonoString *str)
12300 {
12301         g_assert_not_reached ();
12302         return 0;
12303 }
12304
12305 guint32
12306 mono_image_create_method_token (MonoDynamicImage *assembly, MonoObject *obj, MonoArray *opt_param_types)
12307 {
12308         g_assert_not_reached ();
12309         return 0;
12310 }
12311
12312 guint32
12313 mono_image_create_token (MonoDynamicImage *assembly, MonoObject *obj, 
12314                                                  gboolean create_open_instance, gboolean register_token)
12315 {
12316         g_assert_not_reached ();
12317         return 0;
12318 }
12319
12320 void
12321 mono_image_register_token (MonoDynamicImage *assembly, guint32 token, MonoObject *obj)
12322 {
12323 }
12324
12325 void
12326 mono_reflection_generic_class_initialize (MonoReflectionGenericClass *type, MonoArray *fields)
12327 {
12328         g_assert_not_reached ();
12329 }
12330
12331 void
12332 mono_reflection_get_dynamic_overrides (MonoClass *klass, MonoMethod ***overrides, int *num_overrides)
12333 {
12334         *overrides = NULL;
12335         *num_overrides = 0;
12336 }
12337
12338 MonoReflectionEvent *
12339 mono_reflection_event_builder_get_event_info (MonoReflectionTypeBuilder *tb, MonoReflectionEventBuilder *eb)
12340 {
12341         g_assert_not_reached ();
12342         return NULL;
12343 }
12344
12345 MonoReflectionType*
12346 mono_reflection_create_runtime_class (MonoReflectionTypeBuilder *tb)
12347 {
12348         g_assert_not_reached ();
12349         return NULL;
12350 }
12351
12352 void
12353 mono_reflection_initialize_generic_parameter (MonoReflectionGenericParam *gparam)
12354 {
12355         g_assert_not_reached ();
12356 }
12357
12358 MonoArray *
12359 mono_reflection_sighelper_get_signature_local (MonoReflectionSigHelper *sig)
12360 {
12361         g_assert_not_reached ();
12362         return NULL;
12363 }
12364
12365 MonoArray *
12366 mono_reflection_sighelper_get_signature_field (MonoReflectionSigHelper *sig)
12367 {
12368         g_assert_not_reached ();
12369         return NULL;
12370 }
12371
12372 void 
12373 mono_reflection_create_dynamic_method (MonoReflectionDynamicMethod *mb)
12374 {
12375 }
12376
12377 gpointer
12378 mono_reflection_lookup_dynamic_token (MonoImage *image, guint32 token, gboolean valid_token, MonoClass **handle_class, MonoGenericContext *context)
12379 {
12380         return NULL;
12381 }
12382
12383 MonoType*
12384 mono_reflection_type_get_handle (MonoReflectionType* ref)
12385 {
12386         if (!ref)
12387                 return NULL;
12388         return ref->type;
12389 }
12390
12391 void
12392 mono_reflection_free_dynamic_generic_class (MonoGenericClass *gclass)
12393 {
12394         g_assert_not_reached ();
12395 }
12396
12397 #endif /* DISABLE_REFLECTION_EMIT */
12398
12399 /* SECURITY_ACTION_* are defined in mono/metadata/tabledefs.h */
12400 const static guint32 declsec_flags_map[] = {
12401         0x00000000,                                     /* empty */
12402         MONO_DECLSEC_FLAG_REQUEST,                      /* SECURITY_ACTION_REQUEST                      (x01) */
12403         MONO_DECLSEC_FLAG_DEMAND,                       /* SECURITY_ACTION_DEMAND                       (x02) */
12404         MONO_DECLSEC_FLAG_ASSERT,                       /* SECURITY_ACTION_ASSERT                       (x03) */
12405         MONO_DECLSEC_FLAG_DENY,                         /* SECURITY_ACTION_DENY                         (x04) */
12406         MONO_DECLSEC_FLAG_PERMITONLY,                   /* SECURITY_ACTION_PERMITONLY                   (x05) */
12407         MONO_DECLSEC_FLAG_LINKDEMAND,                   /* SECURITY_ACTION_LINKDEMAND                   (x06) */
12408         MONO_DECLSEC_FLAG_INHERITANCEDEMAND,            /* SECURITY_ACTION_INHERITANCEDEMAND            (x07) */
12409         MONO_DECLSEC_FLAG_REQUEST_MINIMUM,              /* SECURITY_ACTION_REQUEST_MINIMUM              (x08) */
12410         MONO_DECLSEC_FLAG_REQUEST_OPTIONAL,             /* SECURITY_ACTION_REQUEST_OPTIONAL             (x09) */
12411         MONO_DECLSEC_FLAG_REQUEST_REFUSE,               /* SECURITY_ACTION_REQUEST_REFUSE               (x0A) */
12412         MONO_DECLSEC_FLAG_PREJIT_GRANT,                 /* SECURITY_ACTION_PREJIT_GRANT                 (x0B) */
12413         MONO_DECLSEC_FLAG_PREJIT_DENY,                  /* SECURITY_ACTION_PREJIT_DENY                  (x0C) */
12414         MONO_DECLSEC_FLAG_NONCAS_DEMAND,                /* SECURITY_ACTION_NONCAS_DEMAND                (x0D) */
12415         MONO_DECLSEC_FLAG_NONCAS_LINKDEMAND,            /* SECURITY_ACTION_NONCAS_LINKDEMAND            (x0E) */
12416         MONO_DECLSEC_FLAG_NONCAS_INHERITANCEDEMAND,     /* SECURITY_ACTION_NONCAS_INHERITANCEDEMAND     (x0F) */
12417         MONO_DECLSEC_FLAG_LINKDEMAND_CHOICE,            /* SECURITY_ACTION_LINKDEMAND_CHOICE            (x10) */
12418         MONO_DECLSEC_FLAG_INHERITANCEDEMAND_CHOICE,     /* SECURITY_ACTION_INHERITANCEDEMAND_CHOICE     (x11) */
12419         MONO_DECLSEC_FLAG_DEMAND_CHOICE,                /* SECURITY_ACTION_DEMAND_CHOICE                (x12) */
12420 };
12421
12422 /*
12423  * Returns flags that includes all available security action associated to the handle.
12424  * @token: metadata token (either for a class or a method)
12425  * @image: image where resides the metadata.
12426  */
12427 static guint32
12428 mono_declsec_get_flags (MonoImage *image, guint32 token)
12429 {
12430         int index = mono_metadata_declsec_from_index (image, token);
12431         MonoTableInfo *t = &image->tables [MONO_TABLE_DECLSECURITY];
12432         guint32 result = 0;
12433         guint32 action;
12434         int i;
12435
12436         /* HasSecurity can be present for other, not specially encoded, attributes,
12437            e.g. SuppressUnmanagedCodeSecurityAttribute */
12438         if (index < 0)
12439                 return 0;
12440
12441         for (i = index; i < t->rows; i++) {
12442                 guint32 cols [MONO_DECL_SECURITY_SIZE];
12443
12444                 mono_metadata_decode_row (t, i, cols, MONO_DECL_SECURITY_SIZE);
12445                 if (cols [MONO_DECL_SECURITY_PARENT] != token)
12446                         break;
12447
12448                 action = cols [MONO_DECL_SECURITY_ACTION];
12449                 if ((action >= MONO_DECLSEC_ACTION_MIN) && (action <= MONO_DECLSEC_ACTION_MAX)) {
12450                         result |= declsec_flags_map [action];
12451                 } else {
12452                         g_assert_not_reached ();
12453                 }
12454         }
12455         return result;
12456 }
12457
12458 /*
12459  * Get the security actions (in the form of flags) associated with the specified method.
12460  *
12461  * @method: The method for which we want the declarative security flags.
12462  * Return the declarative security flags for the method (only).
12463  *
12464  * Note: To keep MonoMethod size down we do not cache the declarative security flags
12465  *       (except for the stack modifiers which are kept in the MonoJitInfo structure)
12466  */
12467 guint32
12468 mono_declsec_flags_from_method (MonoMethod *method)
12469 {
12470         if (method->flags & METHOD_ATTRIBUTE_HAS_SECURITY) {
12471                 /* FIXME: No cache (for the moment) */
12472                 guint32 idx = mono_method_get_index (method);
12473                 idx <<= MONO_HAS_DECL_SECURITY_BITS;
12474                 idx |= MONO_HAS_DECL_SECURITY_METHODDEF;
12475                 return mono_declsec_get_flags (method->klass->image, idx);
12476         }
12477         return 0;
12478 }
12479
12480 /*
12481  * Get the security actions (in the form of flags) associated with the specified class.
12482  *
12483  * @klass: The class for which we want the declarative security flags.
12484  * Return the declarative security flags for the class.
12485  *
12486  * Note: We cache the flags inside the MonoClass structure as this will get 
12487  *       called very often (at least for each method).
12488  */
12489 guint32
12490 mono_declsec_flags_from_class (MonoClass *klass)
12491 {
12492         if (klass->flags & TYPE_ATTRIBUTE_HAS_SECURITY) {
12493                 if (!klass->ext || !klass->ext->declsec_flags) {
12494                         guint32 idx;
12495
12496                         idx = mono_metadata_token_index (klass->type_token);
12497                         idx <<= MONO_HAS_DECL_SECURITY_BITS;
12498                         idx |= MONO_HAS_DECL_SECURITY_TYPEDEF;
12499                         mono_loader_lock ();
12500                         mono_class_alloc_ext (klass);
12501                         mono_loader_unlock ();
12502                         /* we cache the flags on classes */
12503                         klass->ext->declsec_flags = mono_declsec_get_flags (klass->image, idx);
12504                 }
12505                 return klass->ext->declsec_flags;
12506         }
12507         return 0;
12508 }
12509
12510 /*
12511  * Get the security actions (in the form of flags) associated with the specified assembly.
12512  *
12513  * @assembly: The assembly for which we want the declarative security flags.
12514  * Return the declarative security flags for the assembly.
12515  */
12516 guint32
12517 mono_declsec_flags_from_assembly (MonoAssembly *assembly)
12518 {
12519         guint32 idx = 1; /* there is only one assembly */
12520         idx <<= MONO_HAS_DECL_SECURITY_BITS;
12521         idx |= MONO_HAS_DECL_SECURITY_ASSEMBLY;
12522         return mono_declsec_get_flags (assembly->image, idx);
12523 }
12524
12525
12526 /*
12527  * Fill actions for the specific index (which may either be an encoded class token or
12528  * an encoded method token) from the metadata image.
12529  * Returns TRUE if some actions requiring code generation are present, FALSE otherwise.
12530  */
12531 static MonoBoolean
12532 fill_actions_from_index (MonoImage *image, guint32 token, MonoDeclSecurityActions* actions,
12533         guint32 id_std, guint32 id_noncas, guint32 id_choice)
12534 {
12535         MonoBoolean result = FALSE;
12536         MonoTableInfo *t;
12537         guint32 cols [MONO_DECL_SECURITY_SIZE];
12538         int index = mono_metadata_declsec_from_index (image, token);
12539         int i;
12540
12541         t  = &image->tables [MONO_TABLE_DECLSECURITY];
12542         for (i = index; i < t->rows; i++) {
12543                 mono_metadata_decode_row (t, i, cols, MONO_DECL_SECURITY_SIZE);
12544
12545                 if (cols [MONO_DECL_SECURITY_PARENT] != token)
12546                         return result;
12547
12548                 /* if present only replace (class) permissions with method permissions */
12549                 /* if empty accept either class or method permissions */
12550                 if (cols [MONO_DECL_SECURITY_ACTION] == id_std) {
12551                         if (!actions->demand.blob) {
12552                                 const char *blob = mono_metadata_blob_heap (image, cols [MONO_DECL_SECURITY_PERMISSIONSET]);
12553                                 actions->demand.index = cols [MONO_DECL_SECURITY_PERMISSIONSET];
12554                                 actions->demand.blob = (char*) (blob + 2);
12555                                 actions->demand.size = mono_metadata_decode_blob_size (blob, &blob);
12556                                 result = TRUE;
12557                         }
12558                 } else if (cols [MONO_DECL_SECURITY_ACTION] == id_noncas) {
12559                         if (!actions->noncasdemand.blob) {
12560                                 const char *blob = mono_metadata_blob_heap (image, cols [MONO_DECL_SECURITY_PERMISSIONSET]);
12561                                 actions->noncasdemand.index = cols [MONO_DECL_SECURITY_PERMISSIONSET];
12562                                 actions->noncasdemand.blob = (char*) (blob + 2);
12563                                 actions->noncasdemand.size = mono_metadata_decode_blob_size (blob, &blob);
12564                                 result = TRUE;
12565                         }
12566                 } else if (cols [MONO_DECL_SECURITY_ACTION] == id_choice) {
12567                         if (!actions->demandchoice.blob) {
12568                                 const char *blob = mono_metadata_blob_heap (image, cols [MONO_DECL_SECURITY_PERMISSIONSET]);
12569                                 actions->demandchoice.index = cols [MONO_DECL_SECURITY_PERMISSIONSET];
12570                                 actions->demandchoice.blob = (char*) (blob + 2);
12571                                 actions->demandchoice.size = mono_metadata_decode_blob_size (blob, &blob);
12572                                 result = TRUE;
12573                         }
12574                 }
12575         }
12576
12577         return result;
12578 }
12579
12580 static MonoBoolean
12581 mono_declsec_get_class_demands_params (MonoClass *klass, MonoDeclSecurityActions* demands, 
12582         guint32 id_std, guint32 id_noncas, guint32 id_choice)
12583 {
12584         guint32 idx = mono_metadata_token_index (klass->type_token);
12585         idx <<= MONO_HAS_DECL_SECURITY_BITS;
12586         idx |= MONO_HAS_DECL_SECURITY_TYPEDEF;
12587         return fill_actions_from_index (klass->image, idx, demands, id_std, id_noncas, id_choice);
12588 }
12589
12590 static MonoBoolean
12591 mono_declsec_get_method_demands_params (MonoMethod *method, MonoDeclSecurityActions* demands, 
12592         guint32 id_std, guint32 id_noncas, guint32 id_choice)
12593 {
12594         guint32 idx = mono_method_get_index (method);
12595         idx <<= MONO_HAS_DECL_SECURITY_BITS;
12596         idx |= MONO_HAS_DECL_SECURITY_METHODDEF;
12597         return fill_actions_from_index (method->klass->image, idx, demands, id_std, id_noncas, id_choice);
12598 }
12599
12600 /*
12601  * Collect all actions (that requires to generate code in mini) assigned for
12602  * the specified method.
12603  * Note: Don't use the content of actions if the function return FALSE.
12604  */
12605 MonoBoolean
12606 mono_declsec_get_demands (MonoMethod *method, MonoDeclSecurityActions* demands)
12607 {
12608         guint32 mask = MONO_DECLSEC_FLAG_DEMAND | MONO_DECLSEC_FLAG_NONCAS_DEMAND | 
12609                 MONO_DECLSEC_FLAG_DEMAND_CHOICE;
12610         MonoBoolean result = FALSE;
12611         guint32 flags;
12612
12613         /* quick exit if no declarative security is present in the metadata */
12614         if (!method->klass->image->tables [MONO_TABLE_DECLSECURITY].rows)
12615                 return FALSE;
12616
12617         /* we want the original as the wrapper is "free" of the security informations */
12618         if (method->wrapper_type == MONO_WRAPPER_MANAGED_TO_NATIVE || method->wrapper_type == MONO_WRAPPER_MANAGED_TO_MANAGED) {
12619                 method = mono_marshal_method_from_wrapper (method);
12620                 if (!method)
12621                         return FALSE;
12622         }
12623
12624         /* First we look for method-level attributes */
12625         if (method->flags & METHOD_ATTRIBUTE_HAS_SECURITY) {
12626                 mono_class_init (method->klass);
12627                 memset (demands, 0, sizeof (MonoDeclSecurityActions));
12628
12629                 result = mono_declsec_get_method_demands_params (method, demands, 
12630                         SECURITY_ACTION_DEMAND, SECURITY_ACTION_NONCASDEMAND, SECURITY_ACTION_DEMANDCHOICE);
12631         }
12632
12633         /* Here we use (or create) the class declarative cache to look for demands */
12634         flags = mono_declsec_flags_from_class (method->klass);
12635         if (flags & mask) {
12636                 if (!result) {
12637                         mono_class_init (method->klass);
12638                         memset (demands, 0, sizeof (MonoDeclSecurityActions));
12639                 }
12640                 result |= mono_declsec_get_class_demands_params (method->klass, demands, 
12641                         SECURITY_ACTION_DEMAND, SECURITY_ACTION_NONCASDEMAND, SECURITY_ACTION_DEMANDCHOICE);
12642         }
12643
12644         /* The boolean return value is used as a shortcut in case nothing needs to
12645            be generated (e.g. LinkDemand[Choice] and InheritanceDemand[Choice]) */
12646         return result;
12647 }
12648
12649
12650 /*
12651  * Collect all Link actions: LinkDemand, NonCasLinkDemand and LinkDemandChoice (2.0).
12652  *
12653  * Note: Don't use the content of actions if the function return FALSE.
12654  */
12655 MonoBoolean
12656 mono_declsec_get_linkdemands (MonoMethod *method, MonoDeclSecurityActions* klass, MonoDeclSecurityActions *cmethod)
12657 {
12658         MonoBoolean result = FALSE;
12659         guint32 flags;
12660
12661         /* quick exit if no declarative security is present in the metadata */
12662         if (!method->klass->image->tables [MONO_TABLE_DECLSECURITY].rows)
12663                 return FALSE;
12664
12665         /* we want the original as the wrapper is "free" of the security informations */
12666         if (method->wrapper_type == MONO_WRAPPER_MANAGED_TO_NATIVE || method->wrapper_type == MONO_WRAPPER_MANAGED_TO_MANAGED) {
12667                 method = mono_marshal_method_from_wrapper (method);
12668                 if (!method)
12669                         return FALSE;
12670         }
12671
12672         /* results are independant - zeroize both */
12673         memset (cmethod, 0, sizeof (MonoDeclSecurityActions));
12674         memset (klass, 0, sizeof (MonoDeclSecurityActions));
12675
12676         /* First we look for method-level attributes */
12677         if (method->flags & METHOD_ATTRIBUTE_HAS_SECURITY) {
12678                 mono_class_init (method->klass);
12679
12680                 result = mono_declsec_get_method_demands_params (method, cmethod, 
12681                         SECURITY_ACTION_LINKDEMAND, SECURITY_ACTION_NONCASLINKDEMAND, SECURITY_ACTION_LINKDEMANDCHOICE);
12682         }
12683
12684         /* Here we use (or create) the class declarative cache to look for demands */
12685         flags = mono_declsec_flags_from_class (method->klass);
12686         if (flags & (MONO_DECLSEC_FLAG_LINKDEMAND | MONO_DECLSEC_FLAG_NONCAS_LINKDEMAND | MONO_DECLSEC_FLAG_LINKDEMAND_CHOICE)) {
12687                 mono_class_init (method->klass);
12688
12689                 result |= mono_declsec_get_class_demands_params (method->klass, klass, 
12690                         SECURITY_ACTION_LINKDEMAND, SECURITY_ACTION_NONCASLINKDEMAND, SECURITY_ACTION_LINKDEMANDCHOICE);
12691         }
12692
12693         return result;
12694 }
12695
12696 /*
12697  * Collect all Inherit actions: InheritanceDemand, NonCasInheritanceDemand and InheritanceDemandChoice (2.0).
12698  *
12699  * @klass       The inherited class - this is the class that provides the security check (attributes)
12700  * @demans      
12701  * return TRUE if inheritance demands (any kind) are present, FALSE otherwise.
12702  * 
12703  * Note: Don't use the content of actions if the function return FALSE.
12704  */
12705 MonoBoolean
12706 mono_declsec_get_inheritdemands_class (MonoClass *klass, MonoDeclSecurityActions* demands)
12707 {
12708         MonoBoolean result = FALSE;
12709         guint32 flags;
12710
12711         /* quick exit if no declarative security is present in the metadata */
12712         if (!klass->image->tables [MONO_TABLE_DECLSECURITY].rows)
12713                 return FALSE;
12714
12715         /* Here we use (or create) the class declarative cache to look for demands */
12716         flags = mono_declsec_flags_from_class (klass);
12717         if (flags & (MONO_DECLSEC_FLAG_INHERITANCEDEMAND | MONO_DECLSEC_FLAG_NONCAS_INHERITANCEDEMAND | MONO_DECLSEC_FLAG_INHERITANCEDEMAND_CHOICE)) {
12718                 mono_class_init (klass);
12719                 memset (demands, 0, sizeof (MonoDeclSecurityActions));
12720
12721                 result |= mono_declsec_get_class_demands_params (klass, demands, 
12722                         SECURITY_ACTION_INHERITDEMAND, SECURITY_ACTION_NONCASINHERITANCE, SECURITY_ACTION_INHERITDEMANDCHOICE);
12723         }
12724
12725         return result;
12726 }
12727
12728 /*
12729  * Collect all Inherit actions: InheritanceDemand, NonCasInheritanceDemand and InheritanceDemandChoice (2.0).
12730  *
12731  * Note: Don't use the content of actions if the function return FALSE.
12732  */
12733 MonoBoolean
12734 mono_declsec_get_inheritdemands_method (MonoMethod *method, MonoDeclSecurityActions* demands)
12735 {
12736         /* quick exit if no declarative security is present in the metadata */
12737         if (!method->klass->image->tables [MONO_TABLE_DECLSECURITY].rows)
12738                 return FALSE;
12739
12740         /* we want the original as the wrapper is "free" of the security informations */
12741         if (method->wrapper_type == MONO_WRAPPER_MANAGED_TO_NATIVE || method->wrapper_type == MONO_WRAPPER_MANAGED_TO_MANAGED) {
12742                 method = mono_marshal_method_from_wrapper (method);
12743                 if (!method)
12744                         return FALSE;
12745         }
12746
12747         if (method->flags & METHOD_ATTRIBUTE_HAS_SECURITY) {
12748                 mono_class_init (method->klass);
12749                 memset (demands, 0, sizeof (MonoDeclSecurityActions));
12750
12751                 return mono_declsec_get_method_demands_params (method, demands, 
12752                         SECURITY_ACTION_INHERITDEMAND, SECURITY_ACTION_NONCASINHERITANCE, SECURITY_ACTION_INHERITDEMANDCHOICE);
12753         }
12754         return FALSE;
12755 }
12756
12757
12758 static MonoBoolean
12759 get_declsec_action (MonoImage *image, guint32 token, guint32 action, MonoDeclSecurityEntry *entry)
12760 {
12761         guint32 cols [MONO_DECL_SECURITY_SIZE];
12762         MonoTableInfo *t;
12763         int i;
12764
12765         int index = mono_metadata_declsec_from_index (image, token);
12766         if (index == -1)
12767                 return FALSE;
12768
12769         t =  &image->tables [MONO_TABLE_DECLSECURITY];
12770         for (i = index; i < t->rows; i++) {
12771                 mono_metadata_decode_row (t, i, cols, MONO_DECL_SECURITY_SIZE);
12772
12773                 /* shortcut - index are ordered */
12774                 if (token != cols [MONO_DECL_SECURITY_PARENT])
12775                         return FALSE;
12776
12777                 if (cols [MONO_DECL_SECURITY_ACTION] == action) {
12778                         const char *metadata = mono_metadata_blob_heap (image, cols [MONO_DECL_SECURITY_PERMISSIONSET]);
12779                         entry->blob = (char*) (metadata + 2);
12780                         entry->size = mono_metadata_decode_blob_size (metadata, &metadata);
12781                         return TRUE;
12782                 }
12783         }
12784
12785         return FALSE;
12786 }
12787
12788 MonoBoolean
12789 mono_declsec_get_method_action (MonoMethod *method, guint32 action, MonoDeclSecurityEntry *entry)
12790 {
12791         if (method->flags & METHOD_ATTRIBUTE_HAS_SECURITY) {
12792                 guint32 idx = mono_method_get_index (method);
12793                 idx <<= MONO_HAS_DECL_SECURITY_BITS;
12794                 idx |= MONO_HAS_DECL_SECURITY_METHODDEF;
12795                 return get_declsec_action (method->klass->image, idx, action, entry);
12796         }
12797         return FALSE;
12798 }
12799
12800 MonoBoolean
12801 mono_declsec_get_class_action (MonoClass *klass, guint32 action, MonoDeclSecurityEntry *entry)
12802 {
12803         /* use cache */
12804         guint32 flags = mono_declsec_flags_from_class (klass);
12805         if (declsec_flags_map [action] & flags) {
12806                 guint32 idx = mono_metadata_token_index (klass->type_token);
12807                 idx <<= MONO_HAS_DECL_SECURITY_BITS;
12808                 idx |= MONO_HAS_DECL_SECURITY_TYPEDEF;
12809                 return get_declsec_action (klass->image, idx, action, entry);
12810         }
12811         return FALSE;
12812 }
12813
12814 MonoBoolean
12815 mono_declsec_get_assembly_action (MonoAssembly *assembly, guint32 action, MonoDeclSecurityEntry *entry)
12816 {
12817         guint32 idx = 1; /* there is only one assembly */
12818         idx <<= MONO_HAS_DECL_SECURITY_BITS;
12819         idx |= MONO_HAS_DECL_SECURITY_ASSEMBLY;
12820
12821         return get_declsec_action (assembly->image, idx, action, entry);
12822 }
12823
12824 gboolean
12825 mono_reflection_call_is_assignable_to (MonoClass *klass, MonoClass *oklass)
12826 {
12827         MonoObject *res, *exc;
12828         void *params [1];
12829         static MonoClass *System_Reflection_Emit_TypeBuilder = NULL;
12830         static MonoMethod *method = NULL;
12831
12832         if (!System_Reflection_Emit_TypeBuilder) {
12833                 System_Reflection_Emit_TypeBuilder = mono_class_from_name (mono_defaults.corlib, "System.Reflection.Emit", "TypeBuilder");
12834                 g_assert (System_Reflection_Emit_TypeBuilder);
12835         }
12836         if (method == NULL) {
12837                 method = mono_class_get_method_from_name (System_Reflection_Emit_TypeBuilder, "IsAssignableTo", 1);
12838                 g_assert (method);
12839         }
12840
12841         /* 
12842          * The result of mono_type_get_object () might be a System.MonoType but we
12843          * need a TypeBuilder so use mono_class_get_ref_info (klass).
12844          */
12845         g_assert (mono_class_get_ref_info (klass));
12846         g_assert (!strcmp (((MonoObject*)(mono_class_get_ref_info (klass)))->vtable->klass->name, "TypeBuilder"));
12847
12848         params [0] = mono_type_get_object (mono_domain_get (), &oklass->byval_arg);
12849
12850         res = mono_runtime_invoke (method, (MonoObject*)(mono_class_get_ref_info (klass)), params, &exc);
12851         if (exc)
12852                 return FALSE;
12853         else
12854                 return *(MonoBoolean*)mono_object_unbox (res);
12855 }
12856
12857 /**
12858  * mono_reflection_type_get_type:
12859  * @reftype: the System.Type object
12860  *
12861  * Returns the MonoType* associated with the C# System.Type object @reftype.
12862  */
12863 MonoType*
12864 mono_reflection_type_get_type (MonoReflectionType *reftype)
12865 {
12866         g_assert (reftype);
12867
12868         return mono_reflection_type_get_handle (reftype);
12869 }
12870
12871 /**
12872  * mono_reflection_assembly_get_assembly:
12873  * @refassembly: the System.Reflection.Assembly object
12874  *
12875  * Returns the MonoAssembly* associated with the C# System.Reflection.Assembly object @refassembly.
12876  */
12877 MonoAssembly*
12878 mono_reflection_assembly_get_assembly (MonoReflectionAssembly *refassembly)
12879 {
12880         g_assert (refassembly);
12881
12882         return refassembly->assembly;
12883 }
12884