52d66d143c8303ca2cbfc78712fc0ab64740a854
[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-internals.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-internals.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 #include <mono/utils/checked-build.h>
47
48 static gboolean is_usertype (MonoReflectionType *ref);
49 static MonoReflectionType *mono_reflection_type_resolve_user_types (MonoReflectionType *type, MonoError *error);
50
51 typedef struct {
52         char *p;
53         char *buf;
54         char *end;
55 } SigBuffer;
56
57 #define TEXT_OFFSET 512
58 #define CLI_H_SIZE 136
59 #define FILE_ALIGN 512
60 #define VIRT_ALIGN 8192
61 #define START_TEXT_RVA  0x00002000
62
63 typedef struct {
64         MonoReflectionILGen *ilgen;
65         MonoReflectionType *rtype;
66         MonoArray *parameters;
67         MonoArray *generic_params;
68         MonoGenericContainer *generic_container;
69         MonoArray *pinfo;
70         MonoArray *opt_types;
71         guint32 attrs;
72         guint32 iattrs;
73         guint32 call_conv;
74         guint32 *table_idx; /* note: it's a pointer */
75         MonoArray *code;
76         MonoObject *type;
77         MonoString *name;
78         MonoBoolean init_locals;
79         MonoBoolean skip_visibility;
80         MonoArray *return_modreq;
81         MonoArray *return_modopt;
82         MonoArray *param_modreq;
83         MonoArray *param_modopt;
84         MonoArray *permissions;
85         MonoMethod *mhandle;
86         guint32 nrefs;
87         gpointer *refs;
88         /* for PInvoke */
89         int charset, extra_flags, native_cc;
90         MonoString *dll, *dllentry;
91 } ReflectionMethodBuilder;
92
93 typedef struct {
94         guint32 owner;
95         MonoReflectionGenericParam *gparam;
96 } GenericParamTableEntry;
97
98 const unsigned char table_sizes [MONO_TABLE_NUM] = {
99         MONO_MODULE_SIZE,
100         MONO_TYPEREF_SIZE,
101         MONO_TYPEDEF_SIZE,
102         0,
103         MONO_FIELD_SIZE,
104         0,
105         MONO_METHOD_SIZE,
106         0,
107         MONO_PARAM_SIZE,
108         MONO_INTERFACEIMPL_SIZE,
109         MONO_MEMBERREF_SIZE,    /* 0x0A */
110         MONO_CONSTANT_SIZE,
111         MONO_CUSTOM_ATTR_SIZE,
112         MONO_FIELD_MARSHAL_SIZE,
113         MONO_DECL_SECURITY_SIZE,
114         MONO_CLASS_LAYOUT_SIZE,
115         MONO_FIELD_LAYOUT_SIZE, /* 0x10 */
116         MONO_STAND_ALONE_SIGNATURE_SIZE,
117         MONO_EVENT_MAP_SIZE,
118         0,
119         MONO_EVENT_SIZE,
120         MONO_PROPERTY_MAP_SIZE,
121         0,
122         MONO_PROPERTY_SIZE,
123         MONO_METHOD_SEMA_SIZE,
124         MONO_METHODIMPL_SIZE,
125         MONO_MODULEREF_SIZE,    /* 0x1A */
126         MONO_TYPESPEC_SIZE,
127         MONO_IMPLMAP_SIZE,      
128         MONO_FIELD_RVA_SIZE,
129         0,
130         0,
131         MONO_ASSEMBLY_SIZE,     /* 0x20 */
132         MONO_ASSEMBLY_PROCESSOR_SIZE,
133         MONO_ASSEMBLYOS_SIZE,
134         MONO_ASSEMBLYREF_SIZE,
135         MONO_ASSEMBLYREFPROC_SIZE,
136         MONO_ASSEMBLYREFOS_SIZE,
137         MONO_FILE_SIZE,
138         MONO_EXP_TYPE_SIZE,
139         MONO_MANIFEST_SIZE,
140         MONO_NESTED_CLASS_SIZE,
141
142         MONO_GENERICPARAM_SIZE, /* 0x2A */
143         MONO_METHODSPEC_SIZE,
144         MONO_GENPARCONSTRAINT_SIZE
145
146 };
147
148 #ifndef DISABLE_REFLECTION_EMIT
149 static guint32 mono_image_get_methodref_token (MonoDynamicImage *assembly, MonoMethod *method, gboolean create_typespec);
150 static guint32 mono_image_get_methodbuilder_token (MonoDynamicImage *assembly, MonoReflectionMethodBuilder *mb, gboolean create_open_instance, MonoError *error);
151 static guint32 mono_image_get_ctorbuilder_token (MonoDynamicImage *assembly, MonoReflectionCtorBuilder *cb, MonoError *error);
152 static guint32 mono_image_get_sighelper_token (MonoDynamicImage *assembly, MonoReflectionSigHelper *helper);
153 static gboolean ensure_runtime_vtable (MonoClass *klass, MonoError  *error);
154 static gpointer resolve_object (MonoImage *image, MonoObject *obj, MonoClass **handle_class, MonoGenericContext *context);
155 static guint32 mono_image_get_methodref_token_for_methodbuilder (MonoDynamicImage *assembly, MonoReflectionMethodBuilder *method, MonoError *error);
156 static guint32 encode_generic_method_sig (MonoDynamicImage *assembly, MonoGenericContext *context);
157 static gpointer register_assembly (MonoDomain *domain, MonoReflectionAssembly *res, MonoAssembly *assembly);
158 static gboolean reflection_methodbuilder_from_method_builder (ReflectionMethodBuilder *rmb, MonoReflectionMethodBuilder *mb, MonoError *error);
159 static gboolean reflection_methodbuilder_from_ctor_builder (ReflectionMethodBuilder *rmb, MonoReflectionCtorBuilder *mb, MonoError *error);
160 static guint32 create_generic_typespec (MonoDynamicImage *assembly, MonoReflectionTypeBuilder *tb);
161 #endif
162
163 static guint32 mono_image_typedef_or_ref (MonoDynamicImage *assembly, MonoType *type);
164 static guint32 mono_image_typedef_or_ref_full (MonoDynamicImage *assembly, MonoType *type, gboolean try_typespec);
165 static void    mono_image_get_generic_param_info (MonoReflectionGenericParam *gparam, guint32 owner, MonoDynamicImage *assembly);
166 static guint32 encode_marshal_blob (MonoDynamicImage *assembly, MonoReflectionMarshal *minfo);
167 static guint32 encode_constant (MonoDynamicImage *assembly, MonoObject *val, guint32 *ret_type);
168 static char*   type_get_qualified_name (MonoType *type, MonoAssembly *ass);
169 static void    encode_type (MonoDynamicImage *assembly, MonoType *type, SigBuffer *buf);
170 static void get_default_param_value_blobs (MonoMethod *method, char **blobs, guint32 *types);
171 static MonoReflectionType *mono_reflection_type_get_underlying_system_type (MonoReflectionType* t, MonoError *error);
172 static MonoType* mono_reflection_get_type_with_rootimage (MonoImage *rootimage, MonoImage* image, MonoTypeNameParse *info, gboolean ignorecase, gboolean *type_resolve);
173 static MonoReflectionType* mono_reflection_type_resolve_user_types (MonoReflectionType *type, MonoError *error);
174 static gboolean is_sre_array (MonoClass *klass);
175 static gboolean is_sre_byref (MonoClass *klass);
176 static gboolean is_sre_pointer (MonoClass *klass);
177 static gboolean is_sre_type_builder (MonoClass *klass);
178 static gboolean is_sre_method_builder (MonoClass *klass);
179 static gboolean is_sre_ctor_builder (MonoClass *klass);
180 static gboolean is_sre_field_builder (MonoClass *klass);
181 static gboolean is_sr_mono_method (MonoClass *klass);
182 static gboolean is_sr_mono_cmethod (MonoClass *klass);
183 static gboolean is_sr_mono_generic_method (MonoClass *klass);
184 static gboolean is_sr_mono_generic_cmethod (MonoClass *klass);
185 static gboolean is_sr_mono_field (MonoClass *klass);
186 static gboolean is_sr_mono_property (MonoClass *klass);
187 static gboolean is_sre_method_on_tb_inst (MonoClass *klass);
188 static gboolean is_sre_ctor_on_tb_inst (MonoClass *klass);
189
190 static guint32 mono_image_get_methodspec_token (MonoDynamicImage *assembly, MonoMethod *method);
191 static guint32 mono_image_get_inflated_method_token (MonoDynamicImage *assembly, MonoMethod *m);
192 static MonoMethod * inflate_method (MonoReflectionType *type, MonoObject *obj, MonoError *error);
193
194 static guint32 create_typespec (MonoDynamicImage *assembly, MonoType *type);
195 static void init_type_builder_generics (MonoObject *type);
196
197 #define RESOLVE_TYPE(type, error) do {                                  \
198         type = (MonoObject *)mono_reflection_type_resolve_user_types ((MonoReflectionType*)type, error); \
199 } while (0)
200 #define RESOLVE_ARRAY_TYPE_ELEMENT(array, index, error) do {            \
201         MonoReflectionType *__type = mono_array_get (array, MonoReflectionType*, index); \
202         __type = mono_reflection_type_resolve_user_types (__type, error); \
203         if (mono_error_ok (error))                                      \
204                 mono_array_set (arr, MonoReflectionType*, index, __type); \
205 } while (0)
206
207 #define mono_type_array_get_and_resolve(array, index) mono_reflection_type_get_handle ((MonoReflectionType*)mono_array_get (array, gpointer, index))
208
209 #define CHECK_ADD4_OVERFLOW_UN(a, b) ((guint32)(0xFFFFFFFFU) - (guint32)(b) < (guint32)(a))
210 #define CHECK_ADD8_OVERFLOW_UN(a, b) ((guint64)(0xFFFFFFFFFFFFFFFFUL) - (guint64)(b) < (guint64)(a))
211
212 #if SIZEOF_VOID_P == 4
213 #define CHECK_ADDP_OVERFLOW_UN(a,b) CHECK_ADD4_OVERFLOW_UN(a, b)
214 #else
215 #define CHECK_ADDP_OVERFLOW_UN(a,b) CHECK_ADD8_OVERFLOW_UN(a, b)
216 #endif
217
218 #define ADDP_IS_GREATER_OR_OVF(a, b, c) (((a) + (b) > (c)) || CHECK_ADDP_OVERFLOW_UN (a, b))
219 #define ADD_IS_GREATER_OR_OVF(a, b, c) (((a) + (b) > (c)) || CHECK_ADD4_OVERFLOW_UN (a, b))
220
221 /* Class lazy loading functions */
222 static GENERATE_GET_CLASS_WITH_CACHE (mono_assembly, System.Reflection, MonoAssembly)
223 static GENERATE_GET_CLASS_WITH_CACHE (mono_module, System.Reflection, MonoModule)
224 static GENERATE_GET_CLASS_WITH_CACHE (mono_generic_method, System.Reflection, MonoGenericMethod);
225 static GENERATE_GET_CLASS_WITH_CACHE (mono_generic_cmethod, System.Reflection, MonoGenericCMethod);
226 static GENERATE_GET_CLASS_WITH_CACHE (mono_method, System.Reflection, MonoMethod);
227 static GENERATE_GET_CLASS_WITH_CACHE (mono_cmethod, System.Reflection, MonoCMethod);
228 static GENERATE_GET_CLASS_WITH_CACHE (mono_field, System.Reflection, MonoField);
229 static GENERATE_GET_CLASS_WITH_CACHE (mono_event, System.Reflection, MonoEvent);
230 static GENERATE_GET_CLASS_WITH_CACHE (mono_property, System.Reflection, MonoProperty);
231 static GENERATE_GET_CLASS_WITH_CACHE (mono_parameter_info, System.Reflection, MonoParameterInfo);
232 static GENERATE_GET_CLASS_WITH_CACHE (missing, System.Reflection, Missing);
233 static GENERATE_GET_CLASS_WITH_CACHE (method_body, System.Reflection, MethodBody);
234 static GENERATE_GET_CLASS_WITH_CACHE (local_variable_info, System.Reflection, LocalVariableInfo);
235 static GENERATE_GET_CLASS_WITH_CACHE (exception_handling_clause, System.Reflection, ExceptionHandlingClause);
236 static GENERATE_GET_CLASS_WITH_CACHE (custom_attribute_typed_argument, System.Reflection, CustomAttributeTypedArgument);
237 static GENERATE_GET_CLASS_WITH_CACHE (custom_attribute_named_argument, System.Reflection, CustomAttributeNamedArgument);
238 static GENERATE_GET_CLASS_WITH_CACHE (type_builder, System.Reflection.Emit, TypeBuilder);
239 static GENERATE_GET_CLASS_WITH_CACHE (marshal_as_attribute, System.Runtime.InteropServices, MarshalAsAttribute);
240 static GENERATE_GET_CLASS_WITH_CACHE (dbnull, System, DBNull);
241
242 // The dynamic images list is only needed to support the mempool reference tracking feature in checked-build.
243 static GPtrArray *dynamic_images;
244 static mono_mutex_t dynamic_images_mutex;
245
246 static inline void
247 dynamic_images_lock (void)
248 {
249         mono_os_mutex_lock (&dynamic_images_mutex);
250 }
251
252 static inline void
253 dynamic_images_unlock (void)
254 {
255         mono_os_mutex_unlock (&dynamic_images_mutex);
256 }
257
258 /**
259  * mono_find_dynamic_image_owner:
260  *
261  * Find the dynamic image, if any, which a given pointer is located in the memory of.
262  */
263 MonoImage *
264 mono_find_dynamic_image_owner (void *ptr)
265 {
266         MonoImage *owner = NULL;
267         int i;
268
269         dynamic_images_lock ();
270
271         if (dynamic_images)
272         {
273                 for (i = 0; !owner && i < dynamic_images->len; ++i) {
274                         MonoImage *image = (MonoImage *)g_ptr_array_index (dynamic_images, i);
275                         if (mono_mempool_contains_addr (image->mempool, ptr))
276                                 owner = image;
277                 }
278         }
279
280         dynamic_images_unlock ();
281
282         return owner;
283 }
284
285 void
286 mono_reflection_init (void)
287 {
288         mono_os_mutex_init (&dynamic_images_mutex);
289 }
290
291 static inline void
292 dynamic_image_lock (MonoDynamicImage *image)
293 {
294         MONO_PREPARE_BLOCKING;
295         mono_image_lock ((MonoImage*)image);
296         MONO_FINISH_BLOCKING;
297 }
298
299 static inline void
300 dynamic_image_unlock (MonoDynamicImage *image)
301 {
302         mono_image_unlock ((MonoImage*)image);
303 }
304
305 static void
306 register_dyn_token (MonoDynamicImage *assembly, guint32 token, MonoObject *obj)
307 {
308         MONO_REQ_GC_UNSAFE_MODE;
309
310         dynamic_image_lock (assembly);
311         mono_g_hash_table_insert (assembly->tokens, GUINT_TO_POINTER (token), obj);
312         dynamic_image_unlock (assembly);
313 }
314
315 static MonoObject*
316 lookup_dyn_token (MonoDynamicImage *assembly, guint32 token)
317 {
318         MONO_REQ_GC_UNSAFE_MODE;
319
320         MonoObject *obj;
321
322         dynamic_image_lock (assembly);
323         obj = (MonoObject *)mono_g_hash_table_lookup (assembly->tokens, GUINT_TO_POINTER (token));
324         dynamic_image_unlock (assembly);
325
326         return obj;
327 }
328
329 static void
330 sigbuffer_init (SigBuffer *buf, int size)
331 {
332         MONO_REQ_GC_NEUTRAL_MODE;
333
334         buf->buf = (char *)g_malloc (size);
335         buf->p = buf->buf;
336         buf->end = buf->buf + size;
337 }
338
339 static void
340 sigbuffer_make_room (SigBuffer *buf, int size)
341 {
342         MONO_REQ_GC_NEUTRAL_MODE;
343
344         if (buf->end - buf->p < size) {
345                 int new_size = buf->end - buf->buf + size + 32;
346                 char *p = (char *)g_realloc (buf->buf, new_size);
347                 size = buf->p - buf->buf;
348                 buf->buf = p;
349                 buf->p = p + size;
350                 buf->end = buf->buf + new_size;
351         }
352 }
353
354 static void
355 sigbuffer_add_value (SigBuffer *buf, guint32 val)
356 {
357         MONO_REQ_GC_NEUTRAL_MODE;
358
359         sigbuffer_make_room (buf, 6);
360         mono_metadata_encode_value (val, buf->p, &buf->p);
361 }
362
363 static void
364 sigbuffer_add_byte (SigBuffer *buf, guint8 val)
365 {
366         MONO_REQ_GC_NEUTRAL_MODE;
367
368         sigbuffer_make_room (buf, 1);
369         buf->p [0] = val;
370         buf->p++;
371 }
372
373 static void
374 sigbuffer_add_mem (SigBuffer *buf, char *p, guint32 size)
375 {
376         MONO_REQ_GC_NEUTRAL_MODE;
377
378         sigbuffer_make_room (buf, size);
379         memcpy (buf->p, p, size);
380         buf->p += size;
381 }
382
383 static void
384 sigbuffer_free (SigBuffer *buf)
385 {
386         MONO_REQ_GC_NEUTRAL_MODE;
387
388         g_free (buf->buf);
389 }
390
391 #ifndef DISABLE_REFLECTION_EMIT
392 /**
393  * mp_g_alloc:
394  *
395  * Allocate memory from the @image mempool if it is non-NULL. Otherwise, allocate memory
396  * from the C heap.
397  */
398 static gpointer
399 image_g_malloc (MonoImage *image, guint size)
400 {
401         MONO_REQ_GC_NEUTRAL_MODE;
402
403         if (image)
404                 return mono_image_alloc (image, size);
405         else
406                 return g_malloc (size);
407 }
408 #endif /* !DISABLE_REFLECTION_EMIT */
409
410 /**
411  * image_g_alloc0:
412  *
413  * Allocate memory from the @image mempool if it is non-NULL. Otherwise, allocate memory
414  * from the C heap.
415  */
416 static gpointer
417 image_g_malloc0 (MonoImage *image, guint size)
418 {
419         MONO_REQ_GC_NEUTRAL_MODE;
420
421         if (image)
422                 return mono_image_alloc0 (image, size);
423         else
424                 return g_malloc0 (size);
425 }
426
427 #ifndef DISABLE_REFLECTION_EMIT
428 static char*
429 image_strdup (MonoImage *image, const char *s)
430 {
431         MONO_REQ_GC_NEUTRAL_MODE;
432
433         if (image)
434                 return mono_image_strdup (image, s);
435         else
436                 return g_strdup (s);
437 }
438 #endif
439
440 #define image_g_new(image,struct_type, n_structs)               \
441     ((struct_type *) image_g_malloc (image, ((gsize) sizeof (struct_type)) * ((gsize) (n_structs))))
442
443 #define image_g_new0(image,struct_type, n_structs)              \
444     ((struct_type *) image_g_malloc0 (image, ((gsize) sizeof (struct_type)) * ((gsize) (n_structs))))
445
446
447 static void
448 alloc_table (MonoDynamicTable *table, guint nrows)
449 {
450         MONO_REQ_GC_NEUTRAL_MODE;
451
452         table->rows = nrows;
453         g_assert (table->columns);
454         if (nrows + 1 >= table->alloc_rows) {
455                 while (nrows + 1 >= table->alloc_rows) {
456                         if (table->alloc_rows == 0)
457                                 table->alloc_rows = 16;
458                         else
459                                 table->alloc_rows *= 2;
460                 }
461
462                 table->values = (guint32 *)g_renew (guint32, table->values, (table->alloc_rows) * table->columns);
463         }
464 }
465
466 static void
467 make_room_in_stream (MonoDynamicStream *stream, int size)
468 {
469         MONO_REQ_GC_NEUTRAL_MODE;
470
471         if (size <= stream->alloc_size)
472                 return;
473         
474         while (stream->alloc_size <= size) {
475                 if (stream->alloc_size < 4096)
476                         stream->alloc_size = 4096;
477                 else
478                         stream->alloc_size *= 2;
479         }
480         
481         stream->data = (char *)g_realloc (stream->data, stream->alloc_size);
482 }
483
484 static guint32
485 string_heap_insert (MonoDynamicStream *sh, const char *str)
486 {
487         MONO_REQ_GC_NEUTRAL_MODE;
488
489         guint32 idx;
490         guint32 len;
491         gpointer oldkey, oldval;
492
493         if (g_hash_table_lookup_extended (sh->hash, str, &oldkey, &oldval))
494                 return GPOINTER_TO_UINT (oldval);
495
496         len = strlen (str) + 1;
497         idx = sh->index;
498         
499         make_room_in_stream (sh, idx + len);
500
501         /*
502          * We strdup the string even if we already copy them in sh->data
503          * so that the string pointers in the hash remain valid even if
504          * we need to realloc sh->data. We may want to avoid that later.
505          */
506         g_hash_table_insert (sh->hash, g_strdup (str), GUINT_TO_POINTER (idx));
507         memcpy (sh->data + idx, str, len);
508         sh->index += len;
509         return idx;
510 }
511
512 static guint32
513 string_heap_insert_mstring (MonoDynamicStream *sh, MonoString *str)
514 {
515         MONO_REQ_GC_UNSAFE_MODE;
516
517         char *name = mono_string_to_utf8 (str);
518         guint32 idx;
519         idx = string_heap_insert (sh, name);
520         g_free (name);
521         return idx;
522 }
523
524 #ifndef DISABLE_REFLECTION_EMIT
525 static void
526 string_heap_init (MonoDynamicStream *sh)
527 {
528         MONO_REQ_GC_NEUTRAL_MODE;
529
530         sh->index = 0;
531         sh->alloc_size = 4096;
532         sh->data = (char *)g_malloc (4096);
533         sh->hash = g_hash_table_new_full (g_str_hash, g_str_equal, g_free, NULL);
534         string_heap_insert (sh, "");
535 }
536 #endif
537
538 static guint32
539 mono_image_add_stream_data (MonoDynamicStream *stream, const char *data, guint32 len)
540 {
541         MONO_REQ_GC_NEUTRAL_MODE;
542
543         guint32 idx;
544         
545         make_room_in_stream (stream, stream->index + len);
546         memcpy (stream->data + stream->index, data, len);
547         idx = stream->index;
548         stream->index += len;
549         /* 
550          * align index? Not without adding an additional param that controls it since
551          * we may store a blob value in pieces.
552          */
553         return idx;
554 }
555
556 static guint32
557 mono_image_add_stream_zero (MonoDynamicStream *stream, guint32 len)
558 {
559         MONO_REQ_GC_NEUTRAL_MODE;
560
561         guint32 idx;
562         
563         make_room_in_stream (stream, stream->index + len);
564         memset (stream->data + stream->index, 0, len);
565         idx = stream->index;
566         stream->index += len;
567         return idx;
568 }
569
570 static void
571 stream_data_align (MonoDynamicStream *stream)
572 {
573         MONO_REQ_GC_NEUTRAL_MODE;
574
575         char buf [4] = {0};
576         guint32 count = stream->index % 4;
577
578         /* we assume the stream data will be aligned */
579         if (count)
580                 mono_image_add_stream_data (stream, buf, 4 - count);
581 }
582
583 #ifndef DISABLE_REFLECTION_EMIT
584 static int
585 mono_blob_entry_hash (const char* str)
586 {
587         MONO_REQ_GC_NEUTRAL_MODE;
588
589         guint len, h;
590         const char *end;
591         len = mono_metadata_decode_blob_size (str, &str);
592         if (len > 0) {
593                 end = str + len;
594                 h = *str;
595                 for (str += 1; str < end; str++)
596                         h = (h << 5) - h + *str;
597                 return h;
598         } else {
599                 return 0;
600         }
601 }
602
603 static gboolean
604 mono_blob_entry_equal (const char *str1, const char *str2) {
605         MONO_REQ_GC_NEUTRAL_MODE;
606
607         int len, len2;
608         const char *end1;
609         const char *end2;
610         len = mono_metadata_decode_blob_size (str1, &end1);
611         len2 = mono_metadata_decode_blob_size (str2, &end2);
612         if (len != len2)
613                 return 0;
614         return memcmp (end1, end2, len) == 0;
615 }
616 #endif
617 static guint32
618 add_to_blob_cached (MonoDynamicImage *assembly, char *b1, int s1, char *b2, int s2)
619 {
620         MONO_REQ_GC_NEUTRAL_MODE;
621
622         guint32 idx;
623         char *copy;
624         gpointer oldkey, oldval;
625
626         copy = (char *)g_malloc (s1+s2);
627         memcpy (copy, b1, s1);
628         memcpy (copy + s1, b2, s2);
629         if (g_hash_table_lookup_extended (assembly->blob_cache, copy, &oldkey, &oldval)) {
630                 g_free (copy);
631                 idx = GPOINTER_TO_UINT (oldval);
632         } else {
633                 idx = mono_image_add_stream_data (&assembly->blob, b1, s1);
634                 mono_image_add_stream_data (&assembly->blob, b2, s2);
635                 g_hash_table_insert (assembly->blob_cache, copy, GUINT_TO_POINTER (idx));
636         }
637         return idx;
638 }
639
640 static guint32
641 sigbuffer_add_to_blob_cached (MonoDynamicImage *assembly, SigBuffer *buf)
642 {
643         MONO_REQ_GC_NEUTRAL_MODE;
644
645         char blob_size [8];
646         char *b = blob_size;
647         guint32 size = buf->p - buf->buf;
648         /* store length */
649         g_assert (size <= (buf->end - buf->buf));
650         mono_metadata_encode_value (size, b, &b);
651         return add_to_blob_cached (assembly, blob_size, b-blob_size, buf->buf, size);
652 }
653
654 /*
655  * Copy len * nelem bytes from val to dest, swapping bytes to LE if necessary.
656  * dest may be misaligned.
657  */
658 static void
659 swap_with_size (char *dest, const char* val, int len, int nelem) {
660         MONO_REQ_GC_NEUTRAL_MODE;
661 #if G_BYTE_ORDER != G_LITTLE_ENDIAN
662         int elem;
663
664         for (elem = 0; elem < nelem; ++elem) {
665                 switch (len) {
666                 case 1:
667                         *dest = *val;
668                         break;
669                 case 2:
670                         dest [0] = val [1];
671                         dest [1] = val [0];
672                         break;
673                 case 4:
674                         dest [0] = val [3];
675                         dest [1] = val [2];
676                         dest [2] = val [1];
677                         dest [3] = val [0];
678                         break;
679                 case 8:
680                         dest [0] = val [7];
681                         dest [1] = val [6];
682                         dest [2] = val [5];
683                         dest [3] = val [4];
684                         dest [4] = val [3];
685                         dest [5] = val [2];
686                         dest [6] = val [1];
687                         dest [7] = val [0];
688                         break;
689                 default:
690                         g_assert_not_reached ();
691                 }
692                 dest += len;
693                 val += len;
694         }
695 #else
696         memcpy (dest, val, len * nelem);
697 #endif
698 }
699
700 static guint32
701 add_mono_string_to_blob_cached (MonoDynamicImage *assembly, MonoString *str)
702 {
703         MONO_REQ_GC_UNSAFE_MODE;
704         
705         char blob_size [64];
706         char *b = blob_size;
707         guint32 idx = 0, len;
708
709         len = str->length * 2;
710         mono_metadata_encode_value (len, b, &b);
711 #if G_BYTE_ORDER != G_LITTLE_ENDIAN
712         {
713                 char *swapped = g_malloc (2 * mono_string_length (str));
714                 const char *p = (const char*)mono_string_chars (str);
715
716                 swap_with_size (swapped, p, 2, mono_string_length (str));
717                 idx = add_to_blob_cached (assembly, blob_size, b-blob_size, swapped, len);
718                 g_free (swapped);
719         }
720 #else
721         idx = add_to_blob_cached (assembly, blob_size, b-blob_size, (char*)mono_string_chars (str), len);
722 #endif
723         return idx;
724 }
725
726 #ifndef DISABLE_REFLECTION_EMIT
727 static MonoClass *
728 default_class_from_mono_type (MonoType *type)
729 {
730         MONO_REQ_GC_NEUTRAL_MODE;
731
732         switch (type->type) {
733         case MONO_TYPE_OBJECT:
734                 return mono_defaults.object_class;
735         case MONO_TYPE_VOID:
736                 return mono_defaults.void_class;
737         case MONO_TYPE_BOOLEAN:
738                 return mono_defaults.boolean_class;
739         case MONO_TYPE_CHAR:
740                 return mono_defaults.char_class;
741         case MONO_TYPE_I1:
742                 return mono_defaults.sbyte_class;
743         case MONO_TYPE_U1:
744                 return mono_defaults.byte_class;
745         case MONO_TYPE_I2:
746                 return mono_defaults.int16_class;
747         case MONO_TYPE_U2:
748                 return mono_defaults.uint16_class;
749         case MONO_TYPE_I4:
750                 return mono_defaults.int32_class;
751         case MONO_TYPE_U4:
752                 return mono_defaults.uint32_class;
753         case MONO_TYPE_I:
754                 return mono_defaults.int_class;
755         case MONO_TYPE_U:
756                 return mono_defaults.uint_class;
757         case MONO_TYPE_I8:
758                 return mono_defaults.int64_class;
759         case MONO_TYPE_U8:
760                 return mono_defaults.uint64_class;
761         case MONO_TYPE_R4:
762                 return mono_defaults.single_class;
763         case MONO_TYPE_R8:
764                 return mono_defaults.double_class;
765         case MONO_TYPE_STRING:
766                 return mono_defaults.string_class;
767         default:
768                 g_warning ("default_class_from_mono_type: implement me 0x%02x\n", type->type);
769                 g_assert_not_reached ();
770         }
771         
772         return NULL;
773 }
774 #endif
775
776 /*
777  * mono_class_get_ref_info:
778  *
779  *   Return the type builder/generic param builder corresponding to KLASS, if it exists.
780  */
781 gpointer
782 mono_class_get_ref_info (MonoClass *klass)
783 {
784         MONO_REQ_GC_UNSAFE_MODE;
785
786         if (klass->ref_info_handle == 0)
787                 return NULL;
788         else
789                 return mono_gchandle_get_target (klass->ref_info_handle);
790 }
791
792 void
793 mono_class_set_ref_info (MonoClass *klass, gpointer obj)
794 {
795         MONO_REQ_GC_UNSAFE_MODE;
796
797         klass->ref_info_handle = mono_gchandle_new ((MonoObject*)obj, FALSE);
798         g_assert (klass->ref_info_handle != 0);
799 }
800
801 void
802 mono_class_free_ref_info (MonoClass *klass)
803 {
804         MONO_REQ_GC_NEUTRAL_MODE;
805
806         if (klass->ref_info_handle) {
807                 mono_gchandle_free (klass->ref_info_handle);
808                 klass->ref_info_handle = 0;
809         }
810 }
811
812 static void
813 encode_generic_class (MonoDynamicImage *assembly, MonoGenericClass *gclass, SigBuffer *buf)
814 {
815         MONO_REQ_GC_NEUTRAL_MODE;
816
817         int i;
818         MonoGenericInst *class_inst;
819         MonoClass *klass;
820
821         g_assert (gclass);
822
823         class_inst = gclass->context.class_inst;
824
825         sigbuffer_add_value (buf, MONO_TYPE_GENERICINST);
826         klass = gclass->container_class;
827         sigbuffer_add_value (buf, klass->byval_arg.type);
828         sigbuffer_add_value (buf, mono_image_typedef_or_ref_full (assembly, &klass->byval_arg, FALSE));
829
830         sigbuffer_add_value (buf, class_inst->type_argc);
831         for (i = 0; i < class_inst->type_argc; ++i)
832                 encode_type (assembly, class_inst->type_argv [i], buf);
833
834 }
835
836 static void
837 encode_type (MonoDynamicImage *assembly, MonoType *type, SigBuffer *buf)
838 {
839         MONO_REQ_GC_NEUTRAL_MODE;
840
841         if (!type) {
842                 g_assert_not_reached ();
843                 return;
844         }
845                 
846         if (type->byref)
847                 sigbuffer_add_value (buf, MONO_TYPE_BYREF);
848
849         switch (type->type){
850         case MONO_TYPE_VOID:
851         case MONO_TYPE_BOOLEAN:
852         case MONO_TYPE_CHAR:
853         case MONO_TYPE_I1:
854         case MONO_TYPE_U1:
855         case MONO_TYPE_I2:
856         case MONO_TYPE_U2:
857         case MONO_TYPE_I4:
858         case MONO_TYPE_U4:
859         case MONO_TYPE_I8:
860         case MONO_TYPE_U8:
861         case MONO_TYPE_R4:
862         case MONO_TYPE_R8:
863         case MONO_TYPE_I:
864         case MONO_TYPE_U:
865         case MONO_TYPE_STRING:
866         case MONO_TYPE_OBJECT:
867         case MONO_TYPE_TYPEDBYREF:
868                 sigbuffer_add_value (buf, type->type);
869                 break;
870         case MONO_TYPE_PTR:
871                 sigbuffer_add_value (buf, type->type);
872                 encode_type (assembly, type->data.type, buf);
873                 break;
874         case MONO_TYPE_SZARRAY:
875                 sigbuffer_add_value (buf, type->type);
876                 encode_type (assembly, &type->data.klass->byval_arg, buf);
877                 break;
878         case MONO_TYPE_VALUETYPE:
879         case MONO_TYPE_CLASS: {
880                 MonoClass *k = mono_class_from_mono_type (type);
881
882                 if (k->generic_container) {
883                         MonoGenericClass *gclass = mono_metadata_lookup_generic_class (k, k->generic_container->context.class_inst, TRUE);
884                         encode_generic_class (assembly, gclass, buf);
885                 } else {
886                         /*
887                          * Make sure we use the correct type.
888                          */
889                         sigbuffer_add_value (buf, k->byval_arg.type);
890                         /*
891                          * ensure only non-byref gets passed to mono_image_typedef_or_ref(),
892                          * otherwise two typerefs could point to the same type, leading to
893                          * verification errors.
894                          */
895                         sigbuffer_add_value (buf, mono_image_typedef_or_ref (assembly, &k->byval_arg));
896                 }
897                 break;
898         }
899         case MONO_TYPE_ARRAY:
900                 sigbuffer_add_value (buf, type->type);
901                 encode_type (assembly, &type->data.array->eklass->byval_arg, buf);
902                 sigbuffer_add_value (buf, type->data.array->rank);
903                 sigbuffer_add_value (buf, 0); /* FIXME: set to 0 for now */
904                 sigbuffer_add_value (buf, 0);
905                 break;
906         case MONO_TYPE_GENERICINST:
907                 encode_generic_class (assembly, type->data.generic_class, buf);
908                 break;
909         case MONO_TYPE_VAR:
910         case MONO_TYPE_MVAR:
911                 sigbuffer_add_value (buf, type->type);
912                 sigbuffer_add_value (buf, mono_type_get_generic_param_num (type));
913                 break;
914         default:
915                 g_error ("need to encode type %x", type->type);
916         }
917 }
918
919 static void
920 encode_reflection_type (MonoDynamicImage *assembly, MonoReflectionType *type, SigBuffer *buf)
921 {
922         MONO_REQ_GC_UNSAFE_MODE;
923
924         if (!type) {
925                 sigbuffer_add_value (buf, MONO_TYPE_VOID);
926                 return;
927         }
928
929         encode_type (assembly, mono_reflection_type_get_handle (type), buf);
930 }
931
932 static void
933 encode_custom_modifiers (MonoDynamicImage *assembly, MonoArray *modreq, MonoArray *modopt, SigBuffer *buf)
934 {
935         MONO_REQ_GC_UNSAFE_MODE;
936
937         int i;
938
939         if (modreq) {
940                 for (i = 0; i < mono_array_length (modreq); ++i) {
941                         MonoType *mod = mono_type_array_get_and_resolve (modreq, i);
942                         sigbuffer_add_byte (buf, MONO_TYPE_CMOD_REQD);
943                         sigbuffer_add_value (buf, mono_image_typedef_or_ref (assembly, mod));
944                 }
945         }
946         if (modopt) {
947                 for (i = 0; i < mono_array_length (modopt); ++i) {
948                         MonoType *mod = mono_type_array_get_and_resolve (modopt, i);
949                         sigbuffer_add_byte (buf, MONO_TYPE_CMOD_OPT);
950                         sigbuffer_add_value (buf, mono_image_typedef_or_ref (assembly, mod));
951                 }
952         }
953 }
954
955 #ifndef DISABLE_REFLECTION_EMIT
956 static guint32
957 method_encode_signature (MonoDynamicImage *assembly, MonoMethodSignature *sig)
958 {
959         MONO_REQ_GC_UNSAFE_MODE;
960
961         SigBuffer buf;
962         int i;
963         guint32 nparams =  sig->param_count;
964         guint32 idx;
965
966         if (!assembly->save)
967                 return 0;
968
969         sigbuffer_init (&buf, 32);
970         /*
971          * FIXME: vararg, explicit_this, differenc call_conv values...
972          */
973         idx = sig->call_convention;
974         if (sig->hasthis)
975                 idx |= 0x20; /* hasthis */
976         if (sig->generic_param_count)
977                 idx |= 0x10; /* generic */
978         sigbuffer_add_byte (&buf, idx);
979         if (sig->generic_param_count)
980                 sigbuffer_add_value (&buf, sig->generic_param_count);
981         sigbuffer_add_value (&buf, nparams);
982         encode_type (assembly, sig->ret, &buf);
983         for (i = 0; i < nparams; ++i) {
984                 if (i == sig->sentinelpos)
985                         sigbuffer_add_byte (&buf, MONO_TYPE_SENTINEL);
986                 encode_type (assembly, sig->params [i], &buf);
987         }
988         idx = sigbuffer_add_to_blob_cached (assembly, &buf);
989         sigbuffer_free (&buf);
990         return idx;
991 }
992 #endif
993
994 static guint32
995 method_builder_encode_signature (MonoDynamicImage *assembly, ReflectionMethodBuilder *mb)
996 {
997         MONO_REQ_GC_UNSAFE_MODE;
998
999         /*
1000          * FIXME: reuse code from method_encode_signature().
1001          */
1002         SigBuffer buf;
1003         int i;
1004         guint32 nparams =  mb->parameters ? mono_array_length (mb->parameters): 0;
1005         guint32 ngparams = mb->generic_params ? mono_array_length (mb->generic_params): 0;
1006         guint32 notypes = mb->opt_types ? mono_array_length (mb->opt_types): 0;
1007         guint32 idx;
1008
1009         sigbuffer_init (&buf, 32);
1010         /* LAMESPEC: all the call conv spec is foobared */
1011         idx = mb->call_conv & 0x60; /* has-this, explicit-this */
1012         if (mb->call_conv & 2)
1013                 idx |= 0x5; /* vararg */
1014         if (!(mb->attrs & METHOD_ATTRIBUTE_STATIC))
1015                 idx |= 0x20; /* hasthis */
1016         if (ngparams)
1017                 idx |= 0x10; /* generic */
1018         sigbuffer_add_byte (&buf, idx);
1019         if (ngparams)
1020                 sigbuffer_add_value (&buf, ngparams);
1021         sigbuffer_add_value (&buf, nparams + notypes);
1022         encode_custom_modifiers (assembly, mb->return_modreq, mb->return_modopt, &buf);
1023         encode_reflection_type (assembly, mb->rtype, &buf);
1024         for (i = 0; i < nparams; ++i) {
1025                 MonoArray *modreq = NULL;
1026                 MonoArray *modopt = NULL;
1027                 MonoReflectionType *pt;
1028
1029                 if (mb->param_modreq && (i < mono_array_length (mb->param_modreq)))
1030                         modreq = mono_array_get (mb->param_modreq, MonoArray*, i);
1031                 if (mb->param_modopt && (i < mono_array_length (mb->param_modopt)))
1032                         modopt = mono_array_get (mb->param_modopt, MonoArray*, i);
1033                 encode_custom_modifiers (assembly, modreq, modopt, &buf);
1034                 pt = mono_array_get (mb->parameters, MonoReflectionType*, i);
1035                 encode_reflection_type (assembly, pt, &buf);
1036         }
1037         if (notypes)
1038                 sigbuffer_add_byte (&buf, MONO_TYPE_SENTINEL);
1039         for (i = 0; i < notypes; ++i) {
1040                 MonoReflectionType *pt;
1041
1042                 pt = mono_array_get (mb->opt_types, MonoReflectionType*, i);
1043                 encode_reflection_type (assembly, pt, &buf);
1044         }
1045
1046         idx = sigbuffer_add_to_blob_cached (assembly, &buf);
1047         sigbuffer_free (&buf);
1048         return idx;
1049 }
1050
1051 static guint32
1052 encode_locals (MonoDynamicImage *assembly, MonoReflectionILGen *ilgen)
1053 {
1054         MONO_REQ_GC_UNSAFE_MODE;
1055
1056         MonoDynamicTable *table;
1057         guint32 *values;
1058         guint32 idx, sig_idx;
1059         guint nl = mono_array_length (ilgen->locals);
1060         SigBuffer buf;
1061         int i;
1062
1063         sigbuffer_init (&buf, 32);
1064         sigbuffer_add_value (&buf, 0x07);
1065         sigbuffer_add_value (&buf, nl);
1066         for (i = 0; i < nl; ++i) {
1067                 MonoReflectionLocalBuilder *lb = mono_array_get (ilgen->locals, MonoReflectionLocalBuilder*, i);
1068                 
1069                 if (lb->is_pinned)
1070                         sigbuffer_add_value (&buf, MONO_TYPE_PINNED);
1071                 
1072                 encode_reflection_type (assembly, (MonoReflectionType*)lb->type, &buf);
1073         }
1074         sig_idx = sigbuffer_add_to_blob_cached (assembly, &buf);
1075         sigbuffer_free (&buf);
1076
1077         if (assembly->standalonesig_cache == NULL)
1078                 assembly->standalonesig_cache = g_hash_table_new (NULL, NULL);
1079         idx = GPOINTER_TO_UINT (g_hash_table_lookup (assembly->standalonesig_cache, GUINT_TO_POINTER (sig_idx)));
1080         if (idx)
1081                 return idx;
1082
1083         table = &assembly->tables [MONO_TABLE_STANDALONESIG];
1084         idx = table->next_idx ++;
1085         table->rows ++;
1086         alloc_table (table, table->rows);
1087         values = table->values + idx * MONO_STAND_ALONE_SIGNATURE_SIZE;
1088
1089         values [MONO_STAND_ALONE_SIGNATURE] = sig_idx;
1090
1091         g_hash_table_insert (assembly->standalonesig_cache, GUINT_TO_POINTER (sig_idx), GUINT_TO_POINTER (idx));
1092
1093         return idx;
1094 }
1095
1096 static guint32
1097 method_count_clauses (MonoReflectionILGen *ilgen)
1098 {
1099         MONO_REQ_GC_UNSAFE_MODE;
1100
1101         guint32 num_clauses = 0;
1102         int i;
1103
1104         MonoILExceptionInfo *ex_info;
1105         for (i = 0; i < mono_array_length (ilgen->ex_handlers); ++i) {
1106                 ex_info = (MonoILExceptionInfo*)mono_array_addr (ilgen->ex_handlers, MonoILExceptionInfo, i);
1107                 if (ex_info->handlers)
1108                         num_clauses += mono_array_length (ex_info->handlers);
1109                 else
1110                         num_clauses++;
1111         }
1112
1113         return num_clauses;
1114 }
1115
1116 #ifndef DISABLE_REFLECTION_EMIT
1117 static MonoExceptionClause*
1118 method_encode_clauses (MonoImage *image, MonoDynamicImage *assembly, MonoReflectionILGen *ilgen, guint32 num_clauses)
1119 {
1120         MONO_REQ_GC_UNSAFE_MODE;
1121
1122         MonoExceptionClause *clauses;
1123         MonoExceptionClause *clause;
1124         MonoILExceptionInfo *ex_info;
1125         MonoILExceptionBlock *ex_block;
1126         guint32 finally_start;
1127         int i, j, clause_index;;
1128
1129         clauses = image_g_new0 (image, MonoExceptionClause, num_clauses);
1130
1131         clause_index = 0;
1132         for (i = mono_array_length (ilgen->ex_handlers) - 1; i >= 0; --i) {
1133                 ex_info = (MonoILExceptionInfo*)mono_array_addr (ilgen->ex_handlers, MonoILExceptionInfo, i);
1134                 finally_start = ex_info->start + ex_info->len;
1135                 if (!ex_info->handlers)
1136                         continue;
1137                 for (j = 0; j < mono_array_length (ex_info->handlers); ++j) {
1138                         ex_block = (MonoILExceptionBlock*)mono_array_addr (ex_info->handlers, MonoILExceptionBlock, j);
1139                         clause = &(clauses [clause_index]);
1140
1141                         clause->flags = ex_block->type;
1142                         clause->try_offset = ex_info->start;
1143
1144                         if (ex_block->type == MONO_EXCEPTION_CLAUSE_FINALLY)
1145                                 clause->try_len = finally_start - ex_info->start;
1146                         else
1147                                 clause->try_len = ex_info->len;
1148                         clause->handler_offset = ex_block->start;
1149                         clause->handler_len = ex_block->len;
1150                         if (ex_block->extype) {
1151                                 clause->data.catch_class = mono_class_from_mono_type (mono_reflection_type_get_handle ((MonoReflectionType*)ex_block->extype));
1152                         } else {
1153                                 if (ex_block->type == MONO_EXCEPTION_CLAUSE_FILTER)
1154                                         clause->data.filter_offset = ex_block->filter_offset;
1155                                 else
1156                                         clause->data.filter_offset = 0;
1157                         }
1158                         finally_start = ex_block->start + ex_block->len;
1159
1160                         clause_index ++;
1161                 }
1162         }
1163
1164         return clauses;
1165 }
1166 #endif /* !DISABLE_REFLECTION_EMIT */
1167
1168 /**
1169  * method_encode_code:
1170  *
1171  * @assembly the assembly
1172  * @mb the managed MethodBuilder
1173  * @error set on error
1174  *
1175  * Note that the return value is not sensible if @error is set.
1176  */
1177 static guint32
1178 method_encode_code (MonoDynamicImage *assembly, ReflectionMethodBuilder *mb, MonoError *error)
1179 {
1180         MONO_REQ_GC_UNSAFE_MODE;
1181
1182         char flags = 0;
1183         guint32 idx;
1184         guint32 code_size;
1185         gint32 max_stack, i;
1186         gint32 num_locals = 0;
1187         gint32 num_exception = 0;
1188         gint maybe_small;
1189         guint32 fat_flags;
1190         char fat_header [12];
1191         guint32 int_value;
1192         guint16 short_value;
1193         guint32 local_sig = 0;
1194         guint32 header_size = 12;
1195         MonoArray *code;
1196
1197         mono_error_init (error);
1198
1199         if ((mb->attrs & (METHOD_ATTRIBUTE_PINVOKE_IMPL | METHOD_ATTRIBUTE_ABSTRACT)) ||
1200                         (mb->iattrs & (METHOD_IMPL_ATTRIBUTE_INTERNAL_CALL | METHOD_IMPL_ATTRIBUTE_RUNTIME)))
1201                 return 0;
1202
1203         /*if (mb->name)
1204                 g_print ("Encode method %s\n", mono_string_to_utf8 (mb->name));*/
1205         if (mb->ilgen) {
1206                 code = mb->ilgen->code;
1207                 code_size = mb->ilgen->code_len;
1208                 max_stack = mb->ilgen->max_stack;
1209                 num_locals = mb->ilgen->locals ? mono_array_length (mb->ilgen->locals) : 0;
1210                 if (mb->ilgen->ex_handlers)
1211                         num_exception = method_count_clauses (mb->ilgen);
1212         } else {
1213                 code = mb->code;
1214                 if (code == NULL){
1215                         char *name = mono_string_to_utf8 (mb->name);
1216                         char *str = g_strdup_printf ("Method %s does not have any IL associated", name);
1217                         mono_error_set_argument (error, NULL, "a method does not have any IL associated");
1218                         g_free (str);
1219                         g_free (name);
1220                         return 0;
1221                 }
1222
1223                 code_size = mono_array_length (code);
1224                 max_stack = 8; /* we probably need to run a verifier on the code... */
1225         }
1226
1227         stream_data_align (&assembly->code);
1228
1229         /* check for exceptions, maxstack, locals */
1230         maybe_small = (max_stack <= 8) && (!num_locals) && (!num_exception);
1231         if (maybe_small) {
1232                 if (code_size < 64 && !(code_size & 1)) {
1233                         flags = (code_size << 2) | 0x2;
1234                 } else if (code_size < 32 && (code_size & 1)) {
1235                         flags = (code_size << 2) | 0x6; /* LAMESPEC: see metadata.c */
1236                 } else {
1237                         goto fat_header;
1238                 }
1239                 idx = mono_image_add_stream_data (&assembly->code, &flags, 1);
1240                 /* add to the fixup todo list */
1241                 if (mb->ilgen && mb->ilgen->num_token_fixups)
1242                         mono_g_hash_table_insert (assembly->token_fixups, mb->ilgen, GUINT_TO_POINTER (idx + 1));
1243                 mono_image_add_stream_data (&assembly->code, mono_array_addr (code, char, 0), code_size);
1244                 return assembly->text_rva + idx;
1245         } 
1246 fat_header:
1247         if (num_locals)
1248                 local_sig = MONO_TOKEN_SIGNATURE | encode_locals (assembly, mb->ilgen);
1249         /* 
1250          * FIXME: need to set also the header size in fat_flags.
1251          * (and more sects and init locals flags)
1252          */
1253         fat_flags =  0x03;
1254         if (num_exception)
1255                 fat_flags |= METHOD_HEADER_MORE_SECTS;
1256         if (mb->init_locals)
1257                 fat_flags |= METHOD_HEADER_INIT_LOCALS;
1258         fat_header [0] = fat_flags;
1259         fat_header [1] = (header_size / 4 ) << 4;
1260         short_value = GUINT16_TO_LE (max_stack);
1261         memcpy (fat_header + 2, &short_value, 2);
1262         int_value = GUINT32_TO_LE (code_size);
1263         memcpy (fat_header + 4, &int_value, 4);
1264         int_value = GUINT32_TO_LE (local_sig);
1265         memcpy (fat_header + 8, &int_value, 4);
1266         idx = mono_image_add_stream_data (&assembly->code, fat_header, 12);
1267         /* add to the fixup todo list */
1268         if (mb->ilgen && mb->ilgen->num_token_fixups)
1269                 mono_g_hash_table_insert (assembly->token_fixups, mb->ilgen, GUINT_TO_POINTER (idx + 12));
1270         
1271         mono_image_add_stream_data (&assembly->code, mono_array_addr (code, char, 0), code_size);
1272         if (num_exception) {
1273                 unsigned char sheader [4];
1274                 MonoILExceptionInfo * ex_info;
1275                 MonoILExceptionBlock * ex_block;
1276                 int j;
1277
1278                 stream_data_align (&assembly->code);
1279                 /* always use fat format for now */
1280                 sheader [0] = METHOD_HEADER_SECTION_FAT_FORMAT | METHOD_HEADER_SECTION_EHTABLE;
1281                 num_exception *= 6 * sizeof (guint32);
1282                 num_exception += 4; /* include the size of the header */
1283                 sheader [1] = num_exception & 0xff;
1284                 sheader [2] = (num_exception >> 8) & 0xff;
1285                 sheader [3] = (num_exception >> 16) & 0xff;
1286                 mono_image_add_stream_data (&assembly->code, (char*)sheader, 4);
1287                 /* fat header, so we are already aligned */
1288                 /* reverse order */
1289                 for (i = mono_array_length (mb->ilgen->ex_handlers) - 1; i >= 0; --i) {
1290                         ex_info = (MonoILExceptionInfo *)mono_array_addr (mb->ilgen->ex_handlers, MonoILExceptionInfo, i);
1291                         if (ex_info->handlers) {
1292                                 int finally_start = ex_info->start + ex_info->len;
1293                                 for (j = 0; j < mono_array_length (ex_info->handlers); ++j) {
1294                                         guint32 val;
1295                                         ex_block = (MonoILExceptionBlock*)mono_array_addr (ex_info->handlers, MonoILExceptionBlock, j);
1296                                         /* the flags */
1297                                         val = GUINT32_TO_LE (ex_block->type);
1298                                         mono_image_add_stream_data (&assembly->code, (char*)&val, sizeof (guint32));
1299                                         /* try offset */
1300                                         val = GUINT32_TO_LE (ex_info->start);
1301                                         mono_image_add_stream_data (&assembly->code, (char*)&val, sizeof (guint32));
1302                                         /* need fault, too, probably */
1303                                         if (ex_block->type == MONO_EXCEPTION_CLAUSE_FINALLY)
1304                                                 val = GUINT32_TO_LE (finally_start - ex_info->start);
1305                                         else
1306                                                 val = GUINT32_TO_LE (ex_info->len);
1307                                         mono_image_add_stream_data (&assembly->code, (char*)&val, sizeof (guint32));
1308                                         /* handler offset */
1309                                         val = GUINT32_TO_LE (ex_block->start);
1310                                         mono_image_add_stream_data (&assembly->code, (char*)&val, sizeof (guint32));
1311                                         /* handler len */
1312                                         val = GUINT32_TO_LE (ex_block->len);
1313                                         mono_image_add_stream_data (&assembly->code, (char*)&val, sizeof (guint32));
1314                                         finally_start = ex_block->start + ex_block->len;
1315                                         if (ex_block->extype) {
1316                                                 val = mono_metadata_token_from_dor (mono_image_typedef_or_ref (assembly, mono_reflection_type_get_handle ((MonoReflectionType*)ex_block->extype)));
1317                                         } else {
1318                                                 if (ex_block->type == MONO_EXCEPTION_CLAUSE_FILTER)
1319                                                         val = ex_block->filter_offset;
1320                                                 else
1321                                                         val = 0;
1322                                         }
1323                                         val = GUINT32_TO_LE (val);
1324                                         mono_image_add_stream_data (&assembly->code, (char*)&val, sizeof (guint32));
1325                                         /*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", 
1326                                                         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);*/
1327                                 }
1328                         } else {
1329                                 g_error ("No clauses for ex info block %d", i);
1330                         }
1331                 }
1332         }
1333         return assembly->text_rva + idx;
1334 }
1335
1336 static guint32
1337 find_index_in_table (MonoDynamicImage *assembly, int table_idx, int col, guint32 token)
1338 {
1339         MONO_REQ_GC_NEUTRAL_MODE;
1340
1341         int i;
1342         MonoDynamicTable *table;
1343         guint32 *values;
1344         
1345         table = &assembly->tables [table_idx];
1346
1347         g_assert (col < table->columns);
1348
1349         values = table->values + table->columns;
1350         for (i = 1; i <= table->rows; ++i) {
1351                 if (values [col] == token)
1352                         return i;
1353                 values += table->columns;
1354         }
1355         return 0;
1356 }
1357
1358 /*
1359  * LOCKING: Acquires the loader lock. 
1360  */
1361 static MonoCustomAttrInfo*
1362 lookup_custom_attr (MonoImage *image, gpointer member)
1363 {
1364         MONO_REQ_GC_NEUTRAL_MODE;
1365
1366         MonoCustomAttrInfo* res;
1367
1368         res = (MonoCustomAttrInfo *)mono_image_property_lookup (image, member, MONO_PROP_DYNAMIC_CATTR);
1369
1370         if (!res)
1371                 return NULL;
1372
1373         res = (MonoCustomAttrInfo *)g_memdup (res, MONO_SIZEOF_CUSTOM_ATTR_INFO + sizeof (MonoCustomAttrEntry) * res->num_attrs);
1374         res->cached = 0;
1375         return res;
1376 }
1377
1378 static gboolean
1379 custom_attr_visible (MonoImage *image, MonoReflectionCustomAttr *cattr)
1380 {
1381         MONO_REQ_GC_UNSAFE_MODE;
1382
1383         /* FIXME: Need to do more checks */
1384         if (cattr->ctor->method && (cattr->ctor->method->klass->image != image)) {
1385                 int visibility = cattr->ctor->method->klass->flags & TYPE_ATTRIBUTE_VISIBILITY_MASK;
1386
1387                 if ((visibility != TYPE_ATTRIBUTE_PUBLIC) && (visibility != TYPE_ATTRIBUTE_NESTED_PUBLIC))
1388                         return FALSE;
1389         }
1390
1391         return TRUE;
1392 }
1393
1394 static MonoCustomAttrInfo*
1395 mono_custom_attrs_from_builders (MonoImage *alloc_img, MonoImage *image, MonoArray *cattrs)
1396 {
1397         MONO_REQ_GC_UNSAFE_MODE;
1398
1399         int i, index, count, not_visible;
1400         MonoCustomAttrInfo *ainfo;
1401         MonoReflectionCustomAttr *cattr;
1402
1403         if (!cattrs)
1404                 return NULL;
1405         /* FIXME: check in assembly the Run flag is set */
1406
1407         count = mono_array_length (cattrs);
1408
1409         /* Skip nonpublic attributes since MS.NET seems to do the same */
1410         /* FIXME: This needs to be done more globally */
1411         not_visible = 0;
1412         for (i = 0; i < count; ++i) {
1413                 cattr = (MonoReflectionCustomAttr*)mono_array_get (cattrs, gpointer, i);
1414                 if (!custom_attr_visible (image, cattr))
1415                         not_visible ++;
1416         }
1417         count -= not_visible;
1418
1419         ainfo = (MonoCustomAttrInfo *)image_g_malloc0 (alloc_img, MONO_SIZEOF_CUSTOM_ATTR_INFO + sizeof (MonoCustomAttrEntry) * count);
1420
1421         ainfo->image = image;
1422         ainfo->num_attrs = count;
1423         ainfo->cached = alloc_img != NULL;
1424         index = 0;
1425         for (i = 0; i < count; ++i) {
1426                 cattr = (MonoReflectionCustomAttr*)mono_array_get (cattrs, gpointer, i);
1427                 if (custom_attr_visible (image, cattr)) {
1428                         unsigned char *saved = (unsigned char *)mono_image_alloc (image, mono_array_length (cattr->data));
1429                         memcpy (saved, mono_array_addr (cattr->data, char, 0), mono_array_length (cattr->data));
1430                         ainfo->attrs [index].ctor = cattr->ctor->method;
1431                         ainfo->attrs [index].data = saved;
1432                         ainfo->attrs [index].data_size = mono_array_length (cattr->data);
1433                         index ++;
1434                 }
1435         }
1436
1437         return ainfo;
1438 }
1439
1440 #ifndef DISABLE_REFLECTION_EMIT
1441 /*
1442  * LOCKING: Acquires the loader lock. 
1443  */
1444 static void
1445 mono_save_custom_attrs (MonoImage *image, void *obj, MonoArray *cattrs)
1446 {
1447         MONO_REQ_GC_UNSAFE_MODE;
1448
1449         MonoCustomAttrInfo *ainfo, *tmp;
1450
1451         if (!cattrs || !mono_array_length (cattrs))
1452                 return;
1453
1454         ainfo = mono_custom_attrs_from_builders (image, image, cattrs);
1455
1456         mono_loader_lock ();
1457         tmp = (MonoCustomAttrInfo *)mono_image_property_lookup (image, obj, MONO_PROP_DYNAMIC_CATTR);
1458         if (tmp)
1459                 mono_custom_attrs_free (tmp);
1460         mono_image_property_insert (image, obj, MONO_PROP_DYNAMIC_CATTR, ainfo);
1461         mono_loader_unlock ();
1462
1463 }
1464 #endif
1465
1466 void
1467 mono_custom_attrs_free (MonoCustomAttrInfo *ainfo)
1468 {
1469         MONO_REQ_GC_NEUTRAL_MODE;
1470
1471         if (ainfo && !ainfo->cached)
1472                 g_free (ainfo);
1473 }
1474
1475 /*
1476  * idx is the table index of the object
1477  * type is one of MONO_CUSTOM_ATTR_*
1478  */
1479 static gboolean
1480 mono_image_add_cattrs (MonoDynamicImage *assembly, guint32 idx, guint32 type, MonoArray *cattrs, MonoError *error)
1481 {
1482         MONO_REQ_GC_UNSAFE_MODE;
1483
1484         MonoDynamicTable *table;
1485         MonoReflectionCustomAttr *cattr;
1486         guint32 *values;
1487         guint32 count, i, token;
1488         char blob_size [6];
1489         char *p = blob_size;
1490         
1491         mono_error_init (error);
1492
1493         /* it is legal to pass a NULL cattrs: we avoid to use the if in a lot of places */
1494         if (!cattrs)
1495                 return TRUE;
1496         count = mono_array_length (cattrs);
1497         table = &assembly->tables [MONO_TABLE_CUSTOMATTRIBUTE];
1498         table->rows += count;
1499         alloc_table (table, table->rows);
1500         values = table->values + table->next_idx * MONO_CUSTOM_ATTR_SIZE;
1501         idx <<= MONO_CUSTOM_ATTR_BITS;
1502         idx |= type;
1503         for (i = 0; i < count; ++i) {
1504                 cattr = (MonoReflectionCustomAttr*)mono_array_get (cattrs, gpointer, i);
1505                 values [MONO_CUSTOM_ATTR_PARENT] = idx;
1506                 token = mono_image_create_token (assembly, (MonoObject*)cattr->ctor, FALSE, FALSE, error);
1507                 if (!mono_error_ok (error)) goto fail;
1508                 type = mono_metadata_token_index (token);
1509                 type <<= MONO_CUSTOM_ATTR_TYPE_BITS;
1510                 switch (mono_metadata_token_table (token)) {
1511                 case MONO_TABLE_METHOD:
1512                         type |= MONO_CUSTOM_ATTR_TYPE_METHODDEF;
1513                         /*
1514                          * fixup_cattrs () needs to fix this up. We can't use image->tokens, since it contains the old token for the
1515                          * method, not the one returned by mono_image_create_token ().
1516                          */
1517                         mono_g_hash_table_insert (assembly->remapped_tokens, GUINT_TO_POINTER (token), cattr->ctor);
1518                         break;
1519                 case MONO_TABLE_MEMBERREF:
1520                         type |= MONO_CUSTOM_ATTR_TYPE_MEMBERREF;
1521                         break;
1522                 default:
1523                         g_warning ("got wrong token in custom attr");
1524                         continue;
1525                 }
1526                 values [MONO_CUSTOM_ATTR_TYPE] = type;
1527                 p = blob_size;
1528                 mono_metadata_encode_value (mono_array_length (cattr->data), p, &p);
1529                 values [MONO_CUSTOM_ATTR_VALUE] = add_to_blob_cached (assembly, blob_size, p - blob_size,
1530                         mono_array_addr (cattr->data, char, 0), mono_array_length (cattr->data));
1531                 values += MONO_CUSTOM_ATTR_SIZE;
1532                 ++table->next_idx;
1533         }
1534
1535         return TRUE;
1536
1537 fail:
1538         return FALSE;
1539 }
1540
1541 static void
1542 mono_image_add_decl_security (MonoDynamicImage *assembly, guint32 parent_token, MonoArray *permissions)
1543 {
1544         MONO_REQ_GC_UNSAFE_MODE;
1545
1546         MonoDynamicTable *table;
1547         guint32 *values;
1548         guint32 count, i, idx;
1549         MonoReflectionPermissionSet *perm;
1550
1551         if (!permissions)
1552                 return;
1553
1554         count = mono_array_length (permissions);
1555         table = &assembly->tables [MONO_TABLE_DECLSECURITY];
1556         table->rows += count;
1557         alloc_table (table, table->rows);
1558
1559         for (i = 0; i < mono_array_length (permissions); ++i) {
1560                 perm = (MonoReflectionPermissionSet*)mono_array_addr (permissions, MonoReflectionPermissionSet, i);
1561
1562                 values = table->values + table->next_idx * MONO_DECL_SECURITY_SIZE;
1563
1564                 idx = mono_metadata_token_index (parent_token);
1565                 idx <<= MONO_HAS_DECL_SECURITY_BITS;
1566                 switch (mono_metadata_token_table (parent_token)) {
1567                 case MONO_TABLE_TYPEDEF:
1568                         idx |= MONO_HAS_DECL_SECURITY_TYPEDEF;
1569                         break;
1570                 case MONO_TABLE_METHOD:
1571                         idx |= MONO_HAS_DECL_SECURITY_METHODDEF;
1572                         break;
1573                 case MONO_TABLE_ASSEMBLY:
1574                         idx |= MONO_HAS_DECL_SECURITY_ASSEMBLY;
1575                         break;
1576                 default:
1577                         g_assert_not_reached ();
1578                 }
1579
1580                 values [MONO_DECL_SECURITY_ACTION] = perm->action;
1581                 values [MONO_DECL_SECURITY_PARENT] = idx;
1582                 values [MONO_DECL_SECURITY_PERMISSIONSET] = add_mono_string_to_blob_cached (assembly, perm->pset);
1583
1584                 ++table->next_idx;
1585         }
1586 }
1587
1588 /*
1589  * Fill in the MethodDef and ParamDef tables for a method.
1590  * This is used for both normal methods and constructors.
1591  */
1592 static gboolean
1593 mono_image_basic_method (ReflectionMethodBuilder *mb, MonoDynamicImage *assembly, MonoError *error)
1594 {
1595         MONO_REQ_GC_UNSAFE_MODE;
1596
1597         MonoDynamicTable *table;
1598         guint32 *values;
1599         guint i, count;
1600
1601         mono_error_init (error);
1602
1603         /* room in this table is already allocated */
1604         table = &assembly->tables [MONO_TABLE_METHOD];
1605         *mb->table_idx = table->next_idx ++;
1606         g_hash_table_insert (assembly->method_to_table_idx, mb->mhandle, GUINT_TO_POINTER ((*mb->table_idx)));
1607         values = table->values + *mb->table_idx * MONO_METHOD_SIZE;
1608         values [MONO_METHOD_NAME] = string_heap_insert_mstring (&assembly->sheap, mb->name);
1609         values [MONO_METHOD_FLAGS] = mb->attrs;
1610         values [MONO_METHOD_IMPLFLAGS] = mb->iattrs;
1611         values [MONO_METHOD_SIGNATURE] = method_builder_encode_signature (assembly, mb);
1612         values [MONO_METHOD_RVA] = method_encode_code (assembly, mb, error);
1613         if (!mono_error_ok (error))
1614                 return FALSE;
1615
1616         table = &assembly->tables [MONO_TABLE_PARAM];
1617         values [MONO_METHOD_PARAMLIST] = table->next_idx;
1618
1619         mono_image_add_decl_security (assembly, 
1620                 mono_metadata_make_token (MONO_TABLE_METHOD, *mb->table_idx), mb->permissions);
1621
1622         if (mb->pinfo) {
1623                 MonoDynamicTable *mtable;
1624                 guint32 *mvalues;
1625                 
1626                 mtable = &assembly->tables [MONO_TABLE_FIELDMARSHAL];
1627                 mvalues = mtable->values + mtable->next_idx * MONO_FIELD_MARSHAL_SIZE;
1628                 
1629                 count = 0;
1630                 for (i = 0; i < mono_array_length (mb->pinfo); ++i) {
1631                         if (mono_array_get (mb->pinfo, gpointer, i))
1632                                 count++;
1633                 }
1634                 table->rows += count;
1635                 alloc_table (table, table->rows);
1636                 values = table->values + table->next_idx * MONO_PARAM_SIZE;
1637                 for (i = 0; i < mono_array_length (mb->pinfo); ++i) {
1638                         MonoReflectionParamBuilder *pb;
1639                         if ((pb = mono_array_get (mb->pinfo, MonoReflectionParamBuilder*, i))) {
1640                                 values [MONO_PARAM_FLAGS] = pb->attrs;
1641                                 values [MONO_PARAM_SEQUENCE] = i;
1642                                 if (pb->name != NULL) {
1643                                         values [MONO_PARAM_NAME] = string_heap_insert_mstring (&assembly->sheap, pb->name);
1644                                 } else {
1645                                         values [MONO_PARAM_NAME] = 0;
1646                                 }
1647                                 values += MONO_PARAM_SIZE;
1648                                 if (pb->marshal_info) {
1649                                         mtable->rows++;
1650                                         alloc_table (mtable, mtable->rows);
1651                                         mvalues = mtable->values + mtable->rows * MONO_FIELD_MARSHAL_SIZE;
1652                                         mvalues [MONO_FIELD_MARSHAL_PARENT] = (table->next_idx << MONO_HAS_FIELD_MARSHAL_BITS) | MONO_HAS_FIELD_MARSHAL_PARAMDEF;
1653                                         mvalues [MONO_FIELD_MARSHAL_NATIVE_TYPE] = encode_marshal_blob (assembly, pb->marshal_info);
1654                                 }
1655                                 pb->table_idx = table->next_idx++;
1656                                 if (pb->attrs & PARAM_ATTRIBUTE_HAS_DEFAULT) {
1657                                         guint32 field_type = 0;
1658                                         mtable = &assembly->tables [MONO_TABLE_CONSTANT];
1659                                         mtable->rows ++;
1660                                         alloc_table (mtable, mtable->rows);
1661                                         mvalues = mtable->values + mtable->rows * MONO_CONSTANT_SIZE;
1662                                         mvalues [MONO_CONSTANT_PARENT] = MONO_HASCONSTANT_PARAM | (pb->table_idx << MONO_HASCONSTANT_BITS);
1663                                         mvalues [MONO_CONSTANT_VALUE] = encode_constant (assembly, pb->def_value, &field_type);
1664                                         mvalues [MONO_CONSTANT_TYPE] = field_type;
1665                                         mvalues [MONO_CONSTANT_PADDING] = 0;
1666                                 }
1667                         }
1668                 }
1669         }
1670
1671         return TRUE;
1672 }
1673
1674 #ifndef DISABLE_REFLECTION_EMIT
1675 static gboolean
1676 reflection_methodbuilder_from_method_builder (ReflectionMethodBuilder *rmb, MonoReflectionMethodBuilder *mb, MonoError *error)
1677 {
1678         MONO_REQ_GC_UNSAFE_MODE;
1679
1680         mono_error_init (error);
1681         memset (rmb, 0, sizeof (ReflectionMethodBuilder));
1682
1683         rmb->ilgen = mb->ilgen;
1684         rmb->rtype = mono_reflection_type_resolve_user_types ((MonoReflectionType*)mb->rtype, error);
1685         return_val_if_nok (error, FALSE);
1686         rmb->parameters = mb->parameters;
1687         rmb->generic_params = mb->generic_params;
1688         rmb->generic_container = mb->generic_container;
1689         rmb->opt_types = NULL;
1690         rmb->pinfo = mb->pinfo;
1691         rmb->attrs = mb->attrs;
1692         rmb->iattrs = mb->iattrs;
1693         rmb->call_conv = mb->call_conv;
1694         rmb->code = mb->code;
1695         rmb->type = mb->type;
1696         rmb->name = mb->name;
1697         rmb->table_idx = &mb->table_idx;
1698         rmb->init_locals = mb->init_locals;
1699         rmb->skip_visibility = FALSE;
1700         rmb->return_modreq = mb->return_modreq;
1701         rmb->return_modopt = mb->return_modopt;
1702         rmb->param_modreq = mb->param_modreq;
1703         rmb->param_modopt = mb->param_modopt;
1704         rmb->permissions = mb->permissions;
1705         rmb->mhandle = mb->mhandle;
1706         rmb->nrefs = 0;
1707         rmb->refs = NULL;
1708
1709         if (mb->dll) {
1710                 rmb->charset = mb->charset;
1711                 rmb->extra_flags = mb->extra_flags;
1712                 rmb->native_cc = mb->native_cc;
1713                 rmb->dllentry = mb->dllentry;
1714                 rmb->dll = mb->dll;
1715         }
1716
1717         return TRUE;
1718 }
1719
1720 static gboolean
1721 reflection_methodbuilder_from_ctor_builder (ReflectionMethodBuilder *rmb, MonoReflectionCtorBuilder *mb, MonoError *error)
1722 {
1723         MONO_REQ_GC_UNSAFE_MODE;
1724
1725         const char *name = mb->attrs & METHOD_ATTRIBUTE_STATIC ? ".cctor": ".ctor";
1726
1727         mono_error_init (error);
1728
1729         memset (rmb, 0, sizeof (ReflectionMethodBuilder));
1730
1731         rmb->ilgen = mb->ilgen;
1732         rmb->rtype = mono_type_get_object_checked (mono_domain_get (), &mono_defaults.void_class->byval_arg, error);
1733         return_val_if_nok (error, FALSE);
1734         rmb->parameters = mb->parameters;
1735         rmb->generic_params = NULL;
1736         rmb->generic_container = NULL;
1737         rmb->opt_types = NULL;
1738         rmb->pinfo = mb->pinfo;
1739         rmb->attrs = mb->attrs;
1740         rmb->iattrs = mb->iattrs;
1741         rmb->call_conv = mb->call_conv;
1742         rmb->code = NULL;
1743         rmb->type = mb->type;
1744         rmb->name = mono_string_new (mono_domain_get (), name);
1745         rmb->table_idx = &mb->table_idx;
1746         rmb->init_locals = mb->init_locals;
1747         rmb->skip_visibility = FALSE;
1748         rmb->return_modreq = NULL;
1749         rmb->return_modopt = NULL;
1750         rmb->param_modreq = mb->param_modreq;
1751         rmb->param_modopt = mb->param_modopt;
1752         rmb->permissions = mb->permissions;
1753         rmb->mhandle = mb->mhandle;
1754         rmb->nrefs = 0;
1755         rmb->refs = NULL;
1756
1757         return TRUE;
1758 }
1759
1760 static void
1761 reflection_methodbuilder_from_dynamic_method (ReflectionMethodBuilder *rmb, MonoReflectionDynamicMethod *mb)
1762 {
1763         MONO_REQ_GC_UNSAFE_MODE;
1764
1765         memset (rmb, 0, sizeof (ReflectionMethodBuilder));
1766
1767         rmb->ilgen = mb->ilgen;
1768         rmb->rtype = mb->rtype;
1769         rmb->parameters = mb->parameters;
1770         rmb->generic_params = NULL;
1771         rmb->generic_container = NULL;
1772         rmb->opt_types = NULL;
1773         rmb->pinfo = NULL;
1774         rmb->attrs = mb->attrs;
1775         rmb->iattrs = 0;
1776         rmb->call_conv = mb->call_conv;
1777         rmb->code = NULL;
1778         rmb->type = (MonoObject *) mb->owner;
1779         rmb->name = mb->name;
1780         rmb->table_idx = NULL;
1781         rmb->init_locals = mb->init_locals;
1782         rmb->skip_visibility = mb->skip_visibility;
1783         rmb->return_modreq = NULL;
1784         rmb->return_modopt = NULL;
1785         rmb->param_modreq = NULL;
1786         rmb->param_modopt = NULL;
1787         rmb->permissions = NULL;
1788         rmb->mhandle = mb->mhandle;
1789         rmb->nrefs = 0;
1790         rmb->refs = NULL;
1791 }       
1792 #endif
1793
1794 static gboolean
1795 mono_image_add_methodimpl (MonoDynamicImage *assembly, MonoReflectionMethodBuilder *mb, MonoError *error)
1796 {
1797         MONO_REQ_GC_UNSAFE_MODE;
1798
1799         MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder *)mb->type;
1800         MonoDynamicTable *table;
1801         guint32 *values;
1802         guint32 tok;
1803         MonoReflectionMethod *m;
1804         int i;
1805
1806         mono_error_init (error);
1807
1808         if (!mb->override_methods)
1809                 return TRUE;
1810
1811         for (i = 0; i < mono_array_length (mb->override_methods); ++i) {
1812                 m = mono_array_get (mb->override_methods, MonoReflectionMethod*, i);
1813
1814                 table = &assembly->tables [MONO_TABLE_METHODIMPL];
1815                 table->rows ++;
1816                 alloc_table (table, table->rows);
1817                 values = table->values + table->rows * MONO_METHODIMPL_SIZE;
1818                 values [MONO_METHODIMPL_CLASS] = tb->table_idx;
1819                 values [MONO_METHODIMPL_BODY] = MONO_METHODDEFORREF_METHODDEF | (mb->table_idx << MONO_METHODDEFORREF_BITS);
1820
1821                 tok = mono_image_create_token (assembly, (MonoObject*)m, FALSE, FALSE, error);
1822                 return_val_if_nok (error, FALSE);
1823
1824                 switch (mono_metadata_token_table (tok)) {
1825                 case MONO_TABLE_MEMBERREF:
1826                         tok = (mono_metadata_token_index (tok) << MONO_METHODDEFORREF_BITS ) | MONO_METHODDEFORREF_METHODREF;
1827                         break;
1828                 case MONO_TABLE_METHOD:
1829                         tok = (mono_metadata_token_index (tok) << MONO_METHODDEFORREF_BITS ) | MONO_METHODDEFORREF_METHODDEF;
1830                         break;
1831                 default:
1832                         g_assert_not_reached ();
1833                 }
1834                 values [MONO_METHODIMPL_DECLARATION] = tok;
1835         }
1836
1837         return TRUE;
1838 }
1839
1840 #ifndef DISABLE_REFLECTION_EMIT
1841 static gboolean
1842 mono_image_get_method_info (MonoReflectionMethodBuilder *mb, MonoDynamicImage *assembly, MonoError *error)
1843 {
1844         MONO_REQ_GC_UNSAFE_MODE;
1845
1846         MonoDynamicTable *table;
1847         guint32 *values;
1848         ReflectionMethodBuilder rmb;
1849         int i;
1850
1851         mono_error_init (error);
1852
1853         if (!reflection_methodbuilder_from_method_builder (&rmb, mb, error) ||
1854             !mono_image_basic_method (&rmb, assembly, error))
1855                 return FALSE;
1856
1857         mb->table_idx = *rmb.table_idx;
1858
1859         if (mb->dll) { /* It's a P/Invoke method */
1860                 guint32 moduleref;
1861                 /* map CharSet values to on-disk values */
1862                 int ncharset = (mb->charset ? (mb->charset - 1) * 2 : 0);
1863                 int extra_flags = mb->extra_flags;
1864                 table = &assembly->tables [MONO_TABLE_IMPLMAP];
1865                 table->rows ++;
1866                 alloc_table (table, table->rows);
1867                 values = table->values + table->rows * MONO_IMPLMAP_SIZE;
1868                 
1869                 values [MONO_IMPLMAP_FLAGS] = (mb->native_cc << 8) | ncharset | extra_flags;
1870                 values [MONO_IMPLMAP_MEMBER] = (mb->table_idx << 1) | 1; /* memberforwarded: method */
1871                 if (mb->dllentry)
1872                         values [MONO_IMPLMAP_NAME] = string_heap_insert_mstring (&assembly->sheap, mb->dllentry);
1873                 else
1874                         values [MONO_IMPLMAP_NAME] = string_heap_insert_mstring (&assembly->sheap, mb->name);
1875                 moduleref = string_heap_insert_mstring (&assembly->sheap, mb->dll);
1876                 if (!(values [MONO_IMPLMAP_SCOPE] = find_index_in_table (assembly, MONO_TABLE_MODULEREF, MONO_MODULEREF_NAME, moduleref))) {
1877                         table = &assembly->tables [MONO_TABLE_MODULEREF];
1878                         table->rows ++;
1879                         alloc_table (table, table->rows);
1880                         table->values [table->rows * MONO_MODULEREF_SIZE + MONO_MODULEREF_NAME] = moduleref;
1881                         values [MONO_IMPLMAP_SCOPE] = table->rows;
1882                 }
1883         }
1884
1885         if (mb->generic_params) {
1886                 table = &assembly->tables [MONO_TABLE_GENERICPARAM];
1887                 table->rows += mono_array_length (mb->generic_params);
1888                 alloc_table (table, table->rows);
1889                 for (i = 0; i < mono_array_length (mb->generic_params); ++i) {
1890                         guint32 owner = MONO_TYPEORMETHOD_METHOD | (mb->table_idx << MONO_TYPEORMETHOD_BITS);
1891
1892                         mono_image_get_generic_param_info (
1893                                 (MonoReflectionGenericParam *)mono_array_get (mb->generic_params, gpointer, i), owner, assembly);
1894                 }
1895         }
1896
1897         return TRUE;
1898 }
1899
1900 static gboolean
1901 mono_image_get_ctor_info (MonoDomain *domain, MonoReflectionCtorBuilder *mb, MonoDynamicImage *assembly, MonoError *error)
1902 {
1903         MONO_REQ_GC_UNSAFE_MODE;
1904
1905         ReflectionMethodBuilder rmb;
1906
1907         if (!reflection_methodbuilder_from_ctor_builder (&rmb, mb, error))
1908                 return FALSE;
1909
1910         if (!mono_image_basic_method (&rmb, assembly, error))
1911                 return FALSE;
1912
1913         mb->table_idx = *rmb.table_idx;
1914
1915         return TRUE;
1916 }
1917 #endif
1918
1919 static char*
1920 type_get_fully_qualified_name (MonoType *type)
1921 {
1922         MONO_REQ_GC_NEUTRAL_MODE;
1923
1924         return mono_type_get_name_full (type, MONO_TYPE_NAME_FORMAT_ASSEMBLY_QUALIFIED);
1925 }
1926
1927 static char*
1928 type_get_qualified_name (MonoType *type, MonoAssembly *ass)
1929 {
1930         MONO_REQ_GC_UNSAFE_MODE;
1931
1932         MonoClass *klass;
1933         MonoAssembly *ta;
1934
1935         klass = mono_class_from_mono_type (type);
1936         if (!klass) 
1937                 return mono_type_get_name_full (type, MONO_TYPE_NAME_FORMAT_REFLECTION);
1938         ta = klass->image->assembly;
1939         if (assembly_is_dynamic (ta) || (ta == ass)) {
1940                 if (klass->generic_class || klass->generic_container)
1941                         /* For generic type definitions, we want T, while REFLECTION returns T<K> */
1942                         return mono_type_get_name_full (type, MONO_TYPE_NAME_FORMAT_FULL_NAME);
1943                 else
1944                         return mono_type_get_name_full (type, MONO_TYPE_NAME_FORMAT_REFLECTION);
1945         }
1946
1947         return mono_type_get_name_full (type, MONO_TYPE_NAME_FORMAT_ASSEMBLY_QUALIFIED);
1948 }
1949
1950 #ifndef DISABLE_REFLECTION_EMIT
1951 /*field_image is the image to which the eventual custom mods have been encoded against*/
1952 static guint32
1953 fieldref_encode_signature (MonoDynamicImage *assembly, MonoImage *field_image, MonoType *type)
1954 {
1955         MONO_REQ_GC_NEUTRAL_MODE;
1956
1957         SigBuffer buf;
1958         guint32 idx, i, token;
1959
1960         if (!assembly->save)
1961                 return 0;
1962
1963         sigbuffer_init (&buf, 32);
1964         
1965         sigbuffer_add_value (&buf, 0x06);
1966         /* encode custom attributes before the type */
1967         if (type->num_mods) {
1968                 for (i = 0; i < type->num_mods; ++i) {
1969                         if (field_image) {
1970                                 MonoError error;
1971                                 MonoClass *klass = mono_class_get_checked (field_image, type->modifiers [i].token, &error);
1972                                 g_assert (mono_error_ok (&error)); /* FIXME don't swallow the error */
1973
1974                                 token = mono_image_typedef_or_ref (assembly, &klass->byval_arg);
1975                         } else {
1976                                 token = type->modifiers [i].token;
1977                         }
1978
1979                         if (type->modifiers [i].required)
1980                                 sigbuffer_add_byte (&buf, MONO_TYPE_CMOD_REQD);
1981                         else
1982                                 sigbuffer_add_byte (&buf, MONO_TYPE_CMOD_OPT);
1983
1984                         sigbuffer_add_value (&buf, token);
1985                 }
1986         }
1987         encode_type (assembly, type, &buf);
1988         idx = sigbuffer_add_to_blob_cached (assembly, &buf);
1989         sigbuffer_free (&buf);
1990         return idx;
1991 }
1992 #endif
1993
1994 static guint32
1995 field_encode_signature (MonoDynamicImage *assembly, MonoReflectionFieldBuilder *fb)
1996 {
1997         MONO_REQ_GC_UNSAFE_MODE;
1998
1999         SigBuffer buf;
2000         guint32 idx;
2001         guint32 typespec = 0;
2002         MonoType *type;
2003         MonoClass *klass;
2004
2005         init_type_builder_generics (fb->type);
2006
2007         type = mono_reflection_type_get_handle ((MonoReflectionType*)fb->type);
2008         klass = mono_class_from_mono_type (type);
2009
2010         sigbuffer_init (&buf, 32);
2011         
2012         sigbuffer_add_value (&buf, 0x06);
2013         encode_custom_modifiers (assembly, fb->modreq, fb->modopt, &buf);
2014         /* encode custom attributes before the type */
2015
2016         if (klass->generic_container)
2017                 typespec = create_typespec (assembly, type);
2018
2019         if (typespec) {
2020                 MonoGenericClass *gclass;
2021                 gclass = mono_metadata_lookup_generic_class (klass, klass->generic_container->context.class_inst, TRUE);
2022                 encode_generic_class (assembly, gclass, &buf);
2023         } else {
2024                 encode_type (assembly, type, &buf);
2025         }
2026         idx = sigbuffer_add_to_blob_cached (assembly, &buf);
2027         sigbuffer_free (&buf);
2028         return idx;
2029 }
2030
2031 static guint32
2032 encode_constant (MonoDynamicImage *assembly, MonoObject *val, MonoTypeEnum *ret_type)
2033 {
2034         MONO_REQ_GC_UNSAFE_MODE;
2035
2036         char blob_size [64];
2037         char *b = blob_size;
2038         char *box_val;
2039         char* buf;
2040         guint32 idx = 0, len = 0, dummy = 0;
2041
2042         buf = (char *)g_malloc (64);
2043         if (!val) {
2044                 *ret_type = MONO_TYPE_CLASS;
2045                 len = 4;
2046                 box_val = (char*)&dummy;
2047         } else {
2048                 box_val = ((char*)val) + sizeof (MonoObject);
2049                 *ret_type = val->vtable->klass->byval_arg.type;
2050         }
2051 handle_enum:
2052         switch (*ret_type) {
2053         case MONO_TYPE_BOOLEAN:
2054         case MONO_TYPE_U1:
2055         case MONO_TYPE_I1:
2056                 len = 1;
2057                 break;
2058         case MONO_TYPE_CHAR:
2059         case MONO_TYPE_U2:
2060         case MONO_TYPE_I2:
2061                 len = 2;
2062                 break;
2063         case MONO_TYPE_U4:
2064         case MONO_TYPE_I4:
2065         case MONO_TYPE_R4:
2066                 len = 4;
2067                 break;
2068         case MONO_TYPE_U8:
2069         case MONO_TYPE_I8:
2070                 len = 8;
2071                 break;
2072         case MONO_TYPE_R8:
2073                 len = 8;
2074                 break;
2075         case MONO_TYPE_VALUETYPE: {
2076                 MonoClass *klass = val->vtable->klass;
2077                 
2078                 if (klass->enumtype) {
2079                         *ret_type = mono_class_enum_basetype (klass)->type;
2080                         goto handle_enum;
2081                 } else if (mono_is_corlib_image (klass->image) && strcmp (klass->name_space, "System") == 0 && strcmp (klass->name, "DateTime") == 0) {
2082                         len = 8;
2083                 } else 
2084                         g_error ("we can't encode valuetypes, we should have never reached this line");
2085                 break;
2086         }
2087         case MONO_TYPE_CLASS:
2088                 break;
2089         case MONO_TYPE_STRING: {
2090                 MonoString *str = (MonoString*)val;
2091                 /* there is no signature */
2092                 len = str->length * 2;
2093                 mono_metadata_encode_value (len, b, &b);
2094 #if G_BYTE_ORDER != G_LITTLE_ENDIAN
2095                 {
2096                         char *swapped = g_malloc (2 * mono_string_length (str));
2097                         const char *p = (const char*)mono_string_chars (str);
2098
2099                         swap_with_size (swapped, p, 2, mono_string_length (str));
2100                         idx = add_to_blob_cached (assembly, blob_size, b-blob_size, swapped, len);
2101                         g_free (swapped);
2102                 }
2103 #else
2104                 idx = add_to_blob_cached (assembly, blob_size, b-blob_size, (char*)mono_string_chars (str), len);
2105 #endif
2106
2107                 g_free (buf);
2108                 return idx;
2109         }
2110         case MONO_TYPE_GENERICINST:
2111                 *ret_type = val->vtable->klass->generic_class->container_class->byval_arg.type;
2112                 goto handle_enum;
2113         default:
2114                 g_error ("we don't encode constant type 0x%02x yet", *ret_type);
2115         }
2116
2117         /* there is no signature */
2118         mono_metadata_encode_value (len, b, &b);
2119 #if G_BYTE_ORDER != G_LITTLE_ENDIAN
2120         idx = mono_image_add_stream_data (&assembly->blob, blob_size, b-blob_size);
2121         swap_with_size (blob_size, box_val, len, 1);
2122         mono_image_add_stream_data (&assembly->blob, blob_size, len);
2123 #else
2124         idx = add_to_blob_cached (assembly, blob_size, b-blob_size, box_val, len);
2125 #endif
2126
2127         g_free (buf);
2128         return idx;
2129 }
2130
2131 static guint32
2132 encode_marshal_blob (MonoDynamicImage *assembly, MonoReflectionMarshal *minfo)
2133 {
2134         MONO_REQ_GC_UNSAFE_MODE;
2135
2136         char *str;
2137         SigBuffer buf;
2138         guint32 idx, len;
2139
2140         sigbuffer_init (&buf, 32);
2141
2142         sigbuffer_add_value (&buf, minfo->type);
2143
2144         switch (minfo->type) {
2145         case MONO_NATIVE_BYVALTSTR:
2146         case MONO_NATIVE_BYVALARRAY:
2147                 sigbuffer_add_value (&buf, minfo->count);
2148                 break;
2149         case MONO_NATIVE_LPARRAY:
2150                 if (minfo->eltype || minfo->has_size) {
2151                         sigbuffer_add_value (&buf, minfo->eltype);
2152                         if (minfo->has_size) {
2153                                 sigbuffer_add_value (&buf, minfo->param_num != -1? minfo->param_num: 0);
2154                                 sigbuffer_add_value (&buf, minfo->count != -1? minfo->count: 0);
2155
2156                                 /* LAMESPEC: ElemMult is undocumented */
2157                                 sigbuffer_add_value (&buf, minfo->param_num != -1? 1: 0);
2158                         }
2159                 }
2160                 break;
2161         case MONO_NATIVE_SAFEARRAY:
2162                 if (minfo->eltype)
2163                         sigbuffer_add_value (&buf, minfo->eltype);
2164                 break;
2165         case MONO_NATIVE_CUSTOM:
2166                 if (minfo->guid) {
2167                         str = mono_string_to_utf8 (minfo->guid);
2168                         len = strlen (str);
2169                         sigbuffer_add_value (&buf, len);
2170                         sigbuffer_add_mem (&buf, str, len);
2171                         g_free (str);
2172                 } else {
2173                         sigbuffer_add_value (&buf, 0);
2174                 }
2175                 /* native type name */
2176                 sigbuffer_add_value (&buf, 0);
2177                 /* custom marshaler type name */
2178                 if (minfo->marshaltype || minfo->marshaltyperef) {
2179                         if (minfo->marshaltyperef)
2180                                 str = type_get_fully_qualified_name (mono_reflection_type_get_handle ((MonoReflectionType*)minfo->marshaltyperef));
2181                         else
2182                                 str = mono_string_to_utf8 (minfo->marshaltype);
2183                         len = strlen (str);
2184                         sigbuffer_add_value (&buf, len);
2185                         sigbuffer_add_mem (&buf, str, len);
2186                         g_free (str);
2187                 } else {
2188                         /* FIXME: Actually a bug, since this field is required.  Punting for now ... */
2189                         sigbuffer_add_value (&buf, 0);
2190                 }
2191                 if (minfo->mcookie) {
2192                         str = mono_string_to_utf8 (minfo->mcookie);
2193                         len = strlen (str);
2194                         sigbuffer_add_value (&buf, len);
2195                         sigbuffer_add_mem (&buf, str, len);
2196                         g_free (str);
2197                 } else {
2198                         sigbuffer_add_value (&buf, 0);
2199                 }
2200                 break;
2201         default:
2202                 break;
2203         }
2204         idx = sigbuffer_add_to_blob_cached (assembly, &buf);
2205         sigbuffer_free (&buf);
2206         return idx;
2207 }
2208
2209 static void
2210 mono_image_get_field_info (MonoReflectionFieldBuilder *fb, MonoDynamicImage *assembly)
2211 {
2212         MONO_REQ_GC_UNSAFE_MODE;
2213
2214         MonoDynamicTable *table;
2215         guint32 *values;
2216
2217         /* maybe this fixup should be done in the C# code */
2218         if (fb->attrs & FIELD_ATTRIBUTE_LITERAL)
2219                 fb->attrs |= FIELD_ATTRIBUTE_HAS_DEFAULT;
2220         table = &assembly->tables [MONO_TABLE_FIELD];
2221         fb->table_idx = table->next_idx ++;
2222         g_hash_table_insert (assembly->field_to_table_idx, fb->handle, GUINT_TO_POINTER (fb->table_idx));
2223         values = table->values + fb->table_idx * MONO_FIELD_SIZE;
2224         values [MONO_FIELD_NAME] = string_heap_insert_mstring (&assembly->sheap, fb->name);
2225         values [MONO_FIELD_FLAGS] = fb->attrs;
2226         values [MONO_FIELD_SIGNATURE] = field_encode_signature (assembly, fb);
2227
2228         if (fb->offset != -1) {
2229                 table = &assembly->tables [MONO_TABLE_FIELDLAYOUT];
2230                 table->rows ++;
2231                 alloc_table (table, table->rows);
2232                 values = table->values + table->rows * MONO_FIELD_LAYOUT_SIZE;
2233                 values [MONO_FIELD_LAYOUT_FIELD] = fb->table_idx;
2234                 values [MONO_FIELD_LAYOUT_OFFSET] = fb->offset;
2235         }
2236         if (fb->attrs & FIELD_ATTRIBUTE_LITERAL) {
2237                 MonoTypeEnum field_type = (MonoTypeEnum)0;
2238                 table = &assembly->tables [MONO_TABLE_CONSTANT];
2239                 table->rows ++;
2240                 alloc_table (table, table->rows);
2241                 values = table->values + table->rows * MONO_CONSTANT_SIZE;
2242                 values [MONO_CONSTANT_PARENT] = MONO_HASCONSTANT_FIEDDEF | (fb->table_idx << MONO_HASCONSTANT_BITS);
2243                 values [MONO_CONSTANT_VALUE] = encode_constant (assembly, fb->def_value, &field_type);
2244                 values [MONO_CONSTANT_TYPE] = field_type;
2245                 values [MONO_CONSTANT_PADDING] = 0;
2246         }
2247         if (fb->attrs & FIELD_ATTRIBUTE_HAS_FIELD_RVA) {
2248                 guint32 rva_idx;
2249                 table = &assembly->tables [MONO_TABLE_FIELDRVA];
2250                 table->rows ++;
2251                 alloc_table (table, table->rows);
2252                 values = table->values + table->rows * MONO_FIELD_RVA_SIZE;
2253                 values [MONO_FIELD_RVA_FIELD] = fb->table_idx;
2254                 /*
2255                  * We store it in the code section because it's simpler for now.
2256                  */
2257                 if (fb->rva_data) {
2258                         if (mono_array_length (fb->rva_data) >= 10)
2259                                 stream_data_align (&assembly->code);
2260                         rva_idx = mono_image_add_stream_data (&assembly->code, mono_array_addr (fb->rva_data, char, 0), mono_array_length (fb->rva_data));
2261                 } else
2262                         rva_idx = mono_image_add_stream_zero (&assembly->code, mono_class_value_size (fb->handle->parent, NULL));
2263                 values [MONO_FIELD_RVA_RVA] = rva_idx + assembly->text_rva;
2264         }
2265         if (fb->marshal_info) {
2266                 table = &assembly->tables [MONO_TABLE_FIELDMARSHAL];
2267                 table->rows ++;
2268                 alloc_table (table, table->rows);
2269                 values = table->values + table->rows * MONO_FIELD_MARSHAL_SIZE;
2270                 values [MONO_FIELD_MARSHAL_PARENT] = (fb->table_idx << MONO_HAS_FIELD_MARSHAL_BITS) | MONO_HAS_FIELD_MARSHAL_FIELDSREF;
2271                 values [MONO_FIELD_MARSHAL_NATIVE_TYPE] = encode_marshal_blob (assembly, fb->marshal_info);
2272         }
2273 }
2274
2275 static guint32
2276 property_encode_signature (MonoDynamicImage *assembly, MonoReflectionPropertyBuilder *fb)
2277 {
2278         MONO_REQ_GC_UNSAFE_MODE;
2279
2280         SigBuffer buf;
2281         guint32 nparams = 0;
2282         MonoReflectionMethodBuilder *mb = fb->get_method;
2283         MonoReflectionMethodBuilder *smb = fb->set_method;
2284         guint32 idx, i;
2285
2286         if (mb && mb->parameters)
2287                 nparams = mono_array_length (mb->parameters);
2288         if (!mb && smb && smb->parameters)
2289                 nparams = mono_array_length (smb->parameters) - 1;
2290         sigbuffer_init (&buf, 32);
2291         if (fb->call_conv & 0x20)
2292                 sigbuffer_add_byte (&buf, 0x28);
2293         else
2294                 sigbuffer_add_byte (&buf, 0x08);
2295         sigbuffer_add_value (&buf, nparams);
2296         if (mb) {
2297                 encode_reflection_type (assembly, (MonoReflectionType*)mb->rtype, &buf);
2298                 for (i = 0; i < nparams; ++i) {
2299                         MonoReflectionType *pt = mono_array_get (mb->parameters, MonoReflectionType*, i);
2300                         encode_reflection_type (assembly, pt, &buf);
2301                 }
2302         } else if (smb && smb->parameters) {
2303                 /* the property type is the last param */
2304                 encode_reflection_type (assembly, mono_array_get (smb->parameters, MonoReflectionType*, nparams), &buf);
2305                 for (i = 0; i < nparams; ++i) {
2306                         MonoReflectionType *pt = mono_array_get (smb->parameters, MonoReflectionType*, i);
2307                         encode_reflection_type (assembly, pt, &buf);
2308                 }
2309         } else {
2310                 encode_reflection_type (assembly, (MonoReflectionType*)fb->type, &buf);
2311         }
2312
2313         idx = sigbuffer_add_to_blob_cached (assembly, &buf);
2314         sigbuffer_free (&buf);
2315         return idx;
2316 }
2317
2318 static void
2319 mono_image_get_property_info (MonoReflectionPropertyBuilder *pb, MonoDynamicImage *assembly)
2320 {
2321         MONO_REQ_GC_UNSAFE_MODE;
2322
2323         MonoDynamicTable *table;
2324         guint32 *values;
2325         guint num_methods = 0;
2326         guint32 semaidx;
2327
2328         /* 
2329          * we need to set things in the following tables:
2330          * PROPERTYMAP (info already filled in _get_type_info ())
2331          * PROPERTY    (rows already preallocated in _get_type_info ())
2332          * METHOD      (method info already done with the generic method code)
2333          * METHODSEMANTICS
2334          * CONSTANT
2335          */
2336         table = &assembly->tables [MONO_TABLE_PROPERTY];
2337         pb->table_idx = table->next_idx ++;
2338         values = table->values + pb->table_idx * MONO_PROPERTY_SIZE;
2339         values [MONO_PROPERTY_NAME] = string_heap_insert_mstring (&assembly->sheap, pb->name);
2340         values [MONO_PROPERTY_FLAGS] = pb->attrs;
2341         values [MONO_PROPERTY_TYPE] = property_encode_signature (assembly, pb);
2342
2343         /* FIXME: we still don't handle 'other' methods */
2344         if (pb->get_method) num_methods ++;
2345         if (pb->set_method) num_methods ++;
2346
2347         table = &assembly->tables [MONO_TABLE_METHODSEMANTICS];
2348         table->rows += num_methods;
2349         alloc_table (table, table->rows);
2350
2351         if (pb->get_method) {
2352                 semaidx = table->next_idx ++;
2353                 values = table->values + semaidx * MONO_METHOD_SEMA_SIZE;
2354                 values [MONO_METHOD_SEMA_SEMANTICS] = METHOD_SEMANTIC_GETTER;
2355                 values [MONO_METHOD_SEMA_METHOD] = pb->get_method->table_idx;
2356                 values [MONO_METHOD_SEMA_ASSOCIATION] = (pb->table_idx << MONO_HAS_SEMANTICS_BITS) | MONO_HAS_SEMANTICS_PROPERTY;
2357         }
2358         if (pb->set_method) {
2359                 semaidx = table->next_idx ++;
2360                 values = table->values + semaidx * MONO_METHOD_SEMA_SIZE;
2361                 values [MONO_METHOD_SEMA_SEMANTICS] = METHOD_SEMANTIC_SETTER;
2362                 values [MONO_METHOD_SEMA_METHOD] = pb->set_method->table_idx;
2363                 values [MONO_METHOD_SEMA_ASSOCIATION] = (pb->table_idx << MONO_HAS_SEMANTICS_BITS) | MONO_HAS_SEMANTICS_PROPERTY;
2364         }
2365         if (pb->attrs & PROPERTY_ATTRIBUTE_HAS_DEFAULT) {
2366                 MonoTypeEnum field_type = (MonoTypeEnum)0;
2367                 table = &assembly->tables [MONO_TABLE_CONSTANT];
2368                 table->rows ++;
2369                 alloc_table (table, table->rows);
2370                 values = table->values + table->rows * MONO_CONSTANT_SIZE;
2371                 values [MONO_CONSTANT_PARENT] = MONO_HASCONSTANT_PROPERTY | (pb->table_idx << MONO_HASCONSTANT_BITS);
2372                 values [MONO_CONSTANT_VALUE] = encode_constant (assembly, pb->def_value, &field_type);
2373                 values [MONO_CONSTANT_TYPE] = field_type;
2374                 values [MONO_CONSTANT_PADDING] = 0;
2375         }
2376 }
2377
2378 static void
2379 mono_image_get_event_info (MonoReflectionEventBuilder *eb, MonoDynamicImage *assembly)
2380 {
2381         MONO_REQ_GC_UNSAFE_MODE;
2382
2383         MonoDynamicTable *table;
2384         guint32 *values;
2385         guint num_methods = 0;
2386         guint32 semaidx;
2387
2388         /* 
2389          * we need to set things in the following tables:
2390          * EVENTMAP (info already filled in _get_type_info ())
2391          * EVENT    (rows already preallocated in _get_type_info ())
2392          * METHOD      (method info already done with the generic method code)
2393          * METHODSEMANTICS
2394          */
2395         table = &assembly->tables [MONO_TABLE_EVENT];
2396         eb->table_idx = table->next_idx ++;
2397         values = table->values + eb->table_idx * MONO_EVENT_SIZE;
2398         values [MONO_EVENT_NAME] = string_heap_insert_mstring (&assembly->sheap, eb->name);
2399         values [MONO_EVENT_FLAGS] = eb->attrs;
2400         values [MONO_EVENT_TYPE] = mono_image_typedef_or_ref (assembly, mono_reflection_type_get_handle (eb->type));
2401
2402         /*
2403          * FIXME: we still don't handle 'other' methods 
2404          */
2405         if (eb->add_method) num_methods ++;
2406         if (eb->remove_method) num_methods ++;
2407         if (eb->raise_method) num_methods ++;
2408
2409         table = &assembly->tables [MONO_TABLE_METHODSEMANTICS];
2410         table->rows += num_methods;
2411         alloc_table (table, table->rows);
2412
2413         if (eb->add_method) {
2414                 semaidx = table->next_idx ++;
2415                 values = table->values + semaidx * MONO_METHOD_SEMA_SIZE;
2416                 values [MONO_METHOD_SEMA_SEMANTICS] = METHOD_SEMANTIC_ADD_ON;
2417                 values [MONO_METHOD_SEMA_METHOD] = eb->add_method->table_idx;
2418                 values [MONO_METHOD_SEMA_ASSOCIATION] = (eb->table_idx << MONO_HAS_SEMANTICS_BITS) | MONO_HAS_SEMANTICS_EVENT;
2419         }
2420         if (eb->remove_method) {
2421                 semaidx = table->next_idx ++;
2422                 values = table->values + semaidx * MONO_METHOD_SEMA_SIZE;
2423                 values [MONO_METHOD_SEMA_SEMANTICS] = METHOD_SEMANTIC_REMOVE_ON;
2424                 values [MONO_METHOD_SEMA_METHOD] = eb->remove_method->table_idx;
2425                 values [MONO_METHOD_SEMA_ASSOCIATION] = (eb->table_idx << MONO_HAS_SEMANTICS_BITS) | MONO_HAS_SEMANTICS_EVENT;
2426         }
2427         if (eb->raise_method) {
2428                 semaidx = table->next_idx ++;
2429                 values = table->values + semaidx * MONO_METHOD_SEMA_SIZE;
2430                 values [MONO_METHOD_SEMA_SEMANTICS] = METHOD_SEMANTIC_FIRE;
2431                 values [MONO_METHOD_SEMA_METHOD] = eb->raise_method->table_idx;
2432                 values [MONO_METHOD_SEMA_ASSOCIATION] = (eb->table_idx << MONO_HAS_SEMANTICS_BITS) | MONO_HAS_SEMANTICS_EVENT;
2433         }
2434 }
2435
2436 static void
2437 encode_constraints (MonoReflectionGenericParam *gparam, guint32 owner, MonoDynamicImage *assembly)
2438 {
2439         MONO_REQ_GC_UNSAFE_MODE;
2440
2441         MonoDynamicTable *table;
2442         guint32 num_constraints, i;
2443         guint32 *values;
2444         guint32 table_idx;
2445
2446         table = &assembly->tables [MONO_TABLE_GENERICPARAMCONSTRAINT];
2447         num_constraints = gparam->iface_constraints ?
2448                 mono_array_length (gparam->iface_constraints) : 0;
2449         table->rows += num_constraints;
2450         if (gparam->base_type)
2451                 table->rows++;
2452         alloc_table (table, table->rows);
2453
2454         if (gparam->base_type) {
2455                 table_idx = table->next_idx ++;
2456                 values = table->values + table_idx * MONO_GENPARCONSTRAINT_SIZE;
2457
2458                 values [MONO_GENPARCONSTRAINT_GENERICPAR] = owner;
2459                 values [MONO_GENPARCONSTRAINT_CONSTRAINT] = mono_image_typedef_or_ref (
2460                         assembly, mono_reflection_type_get_handle (gparam->base_type));
2461         }
2462
2463         for (i = 0; i < num_constraints; i++) {
2464                 MonoReflectionType *constraint = (MonoReflectionType *)mono_array_get (
2465                         gparam->iface_constraints, gpointer, i);
2466
2467                 table_idx = table->next_idx ++;
2468                 values = table->values + table_idx * MONO_GENPARCONSTRAINT_SIZE;
2469
2470                 values [MONO_GENPARCONSTRAINT_GENERICPAR] = owner;
2471                 values [MONO_GENPARCONSTRAINT_CONSTRAINT] = mono_image_typedef_or_ref (
2472                         assembly, mono_reflection_type_get_handle (constraint));
2473         }
2474 }
2475
2476 static void
2477 mono_image_get_generic_param_info (MonoReflectionGenericParam *gparam, guint32 owner, MonoDynamicImage *assembly)
2478 {
2479         MONO_REQ_GC_UNSAFE_MODE;
2480
2481         GenericParamTableEntry *entry;
2482
2483         /*
2484          * The GenericParam table must be sorted according to the `owner' field.
2485          * We need to do this sorting prior to writing the GenericParamConstraint
2486          * table, since we have to use the final GenericParam table indices there
2487          * and they must also be sorted.
2488          */
2489
2490         entry = g_new0 (GenericParamTableEntry, 1);
2491         entry->owner = owner;
2492         /* FIXME: track where gen_params should be freed and remove the GC root as well */
2493         MONO_GC_REGISTER_ROOT_IF_MOVING (entry->gparam, MONO_ROOT_SOURCE_REFLECTION, "reflection generic parameter");
2494         entry->gparam = gparam;
2495         
2496         g_ptr_array_add (assembly->gen_params, entry);
2497 }
2498
2499 static gboolean
2500 write_generic_param_entry (MonoDynamicImage *assembly, GenericParamTableEntry *entry, MonoError *error)
2501 {
2502         MONO_REQ_GC_UNSAFE_MODE;
2503
2504         MonoDynamicTable *table;
2505         MonoGenericParam *param;
2506         guint32 *values;
2507         guint32 table_idx;
2508
2509         mono_error_init (error);
2510
2511         table = &assembly->tables [MONO_TABLE_GENERICPARAM];
2512         table_idx = table->next_idx ++;
2513         values = table->values + table_idx * MONO_GENERICPARAM_SIZE;
2514
2515         param = mono_reflection_type_get_handle ((MonoReflectionType*)entry->gparam)->data.generic_param;
2516
2517         values [MONO_GENERICPARAM_OWNER] = entry->owner;
2518         values [MONO_GENERICPARAM_FLAGS] = entry->gparam->attrs;
2519         values [MONO_GENERICPARAM_NUMBER] = mono_generic_param_num (param);
2520         values [MONO_GENERICPARAM_NAME] = string_heap_insert (&assembly->sheap, mono_generic_param_info (param)->name);
2521
2522         if (!mono_image_add_cattrs (assembly, table_idx, MONO_CUSTOM_ATTR_GENERICPAR, entry->gparam->cattrs, error))
2523                 return FALSE;
2524
2525         encode_constraints (entry->gparam, table_idx, assembly);
2526
2527         return TRUE;
2528 }
2529
2530 static guint32
2531 resolution_scope_from_image (MonoDynamicImage *assembly, MonoImage *image)
2532 {
2533         MONO_REQ_GC_UNSAFE_MODE;
2534
2535         MonoDynamicTable *table;
2536         guint32 token;
2537         guint32 *values;
2538         guint32 cols [MONO_ASSEMBLY_SIZE];
2539         const char *pubkey;
2540         guint32 publen;
2541
2542         if ((token = GPOINTER_TO_UINT (g_hash_table_lookup (assembly->handleref, image))))
2543                 return token;
2544
2545         if (assembly_is_dynamic (image->assembly) && (image->assembly == assembly->image.assembly)) {
2546                 table = &assembly->tables [MONO_TABLE_MODULEREF];
2547                 token = table->next_idx ++;
2548                 table->rows ++;
2549                 alloc_table (table, table->rows);
2550                 values = table->values + token * MONO_MODULEREF_SIZE;
2551                 values [MONO_MODULEREF_NAME] = string_heap_insert (&assembly->sheap, image->module_name);
2552
2553                 token <<= MONO_RESOLUTION_SCOPE_BITS;
2554                 token |= MONO_RESOLUTION_SCOPE_MODULEREF;
2555                 g_hash_table_insert (assembly->handleref, image, GUINT_TO_POINTER (token));
2556
2557                 return token;
2558         }
2559         
2560         if (assembly_is_dynamic (image->assembly))
2561                 /* FIXME: */
2562                 memset (cols, 0, sizeof (cols));
2563         else {
2564                 /* image->assembly->image is the manifest module */
2565                 image = image->assembly->image;
2566                 mono_metadata_decode_row (&image->tables [MONO_TABLE_ASSEMBLY], 0, cols, MONO_ASSEMBLY_SIZE);
2567         }
2568
2569         table = &assembly->tables [MONO_TABLE_ASSEMBLYREF];
2570         token = table->next_idx ++;
2571         table->rows ++;
2572         alloc_table (table, table->rows);
2573         values = table->values + token * MONO_ASSEMBLYREF_SIZE;
2574         values [MONO_ASSEMBLYREF_NAME] = string_heap_insert (&assembly->sheap, image->assembly_name);
2575         values [MONO_ASSEMBLYREF_MAJOR_VERSION] = cols [MONO_ASSEMBLY_MAJOR_VERSION];
2576         values [MONO_ASSEMBLYREF_MINOR_VERSION] = cols [MONO_ASSEMBLY_MINOR_VERSION];
2577         values [MONO_ASSEMBLYREF_BUILD_NUMBER] = cols [MONO_ASSEMBLY_BUILD_NUMBER];
2578         values [MONO_ASSEMBLYREF_REV_NUMBER] = cols [MONO_ASSEMBLY_REV_NUMBER];
2579         values [MONO_ASSEMBLYREF_FLAGS] = 0;
2580         values [MONO_ASSEMBLYREF_CULTURE] = 0;
2581         values [MONO_ASSEMBLYREF_HASH_VALUE] = 0;
2582
2583         if (strcmp ("", image->assembly->aname.culture)) {
2584                 values [MONO_ASSEMBLYREF_CULTURE] = string_heap_insert (&assembly->sheap,
2585                                 image->assembly->aname.culture);
2586         }
2587
2588         if ((pubkey = mono_image_get_public_key (image, &publen))) {
2589                 guchar pubtoken [9];
2590                 pubtoken [0] = 8;
2591                 mono_digest_get_public_token (pubtoken + 1, (guchar*)pubkey, publen);
2592                 values [MONO_ASSEMBLYREF_PUBLIC_KEY] = mono_image_add_stream_data (&assembly->blob, (char*)pubtoken, 9);
2593         } else {
2594                 values [MONO_ASSEMBLYREF_PUBLIC_KEY] = 0;
2595         }
2596         token <<= MONO_RESOLUTION_SCOPE_BITS;
2597         token |= MONO_RESOLUTION_SCOPE_ASSEMBLYREF;
2598         g_hash_table_insert (assembly->handleref, image, GUINT_TO_POINTER (token));
2599         return token;
2600 }
2601
2602 static guint32
2603 create_typespec (MonoDynamicImage *assembly, MonoType *type)
2604 {
2605         MONO_REQ_GC_NEUTRAL_MODE;
2606
2607         MonoDynamicTable *table;
2608         guint32 *values;
2609         guint32 token;
2610         SigBuffer buf;
2611
2612         if ((token = GPOINTER_TO_UINT (g_hash_table_lookup (assembly->typespec, type))))
2613                 return token;
2614
2615         sigbuffer_init (&buf, 32);
2616         switch (type->type) {
2617         case MONO_TYPE_FNPTR:
2618         case MONO_TYPE_PTR:
2619         case MONO_TYPE_SZARRAY:
2620         case MONO_TYPE_ARRAY:
2621         case MONO_TYPE_VAR:
2622         case MONO_TYPE_MVAR:
2623         case MONO_TYPE_GENERICINST:
2624                 encode_type (assembly, type, &buf);
2625                 break;
2626         case MONO_TYPE_CLASS:
2627         case MONO_TYPE_VALUETYPE: {
2628                 MonoClass *k = mono_class_from_mono_type (type);
2629                 if (!k || !k->generic_container) {
2630                         sigbuffer_free (&buf);
2631                         return 0;
2632                 }
2633                 encode_type (assembly, type, &buf);
2634                 break;
2635         }
2636         default:
2637                 sigbuffer_free (&buf);
2638                 return 0;
2639         }
2640
2641         table = &assembly->tables [MONO_TABLE_TYPESPEC];
2642         if (assembly->save) {
2643                 token = sigbuffer_add_to_blob_cached (assembly, &buf);
2644                 alloc_table (table, table->rows + 1);
2645                 values = table->values + table->next_idx * MONO_TYPESPEC_SIZE;
2646                 values [MONO_TYPESPEC_SIGNATURE] = token;
2647         }
2648         sigbuffer_free (&buf);
2649
2650         token = MONO_TYPEDEFORREF_TYPESPEC | (table->next_idx << MONO_TYPEDEFORREF_BITS);
2651         g_hash_table_insert (assembly->typespec, type, GUINT_TO_POINTER(token));
2652         table->next_idx ++;
2653         return token;
2654 }
2655
2656 static guint32
2657 mono_image_typedef_or_ref_full (MonoDynamicImage *assembly, MonoType *type, gboolean try_typespec)
2658 {
2659         MONO_REQ_GC_UNSAFE_MODE;
2660
2661         MonoDynamicTable *table;
2662         guint32 *values;
2663         guint32 token, scope, enclosing;
2664         MonoClass *klass;
2665
2666         /* if the type requires a typespec, we must try that first*/
2667         if (try_typespec && (token = create_typespec (assembly, type)))
2668                 return token;
2669         token = GPOINTER_TO_UINT (g_hash_table_lookup (assembly->typeref, type));
2670         if (token)
2671                 return token;
2672         klass = mono_class_from_mono_type (type);
2673         if (!klass)
2674                 klass = mono_class_from_mono_type (type);
2675
2676         /*
2677          * If it's in the same module and not a generic type parameter:
2678          */
2679         if ((klass->image == &assembly->image) && (type->type != MONO_TYPE_VAR) && 
2680                         (type->type != MONO_TYPE_MVAR)) {
2681                 MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder *)mono_class_get_ref_info (klass);
2682                 token = MONO_TYPEDEFORREF_TYPEDEF | (tb->table_idx << MONO_TYPEDEFORREF_BITS);
2683                 register_dyn_token (assembly, token, (MonoObject *)mono_class_get_ref_info (klass));
2684                 return token;
2685         }
2686
2687         if (klass->nested_in) {
2688                 enclosing = mono_image_typedef_or_ref_full (assembly, &klass->nested_in->byval_arg, FALSE);
2689                 /* get the typeref idx of the enclosing type */
2690                 enclosing >>= MONO_TYPEDEFORREF_BITS;
2691                 scope = (enclosing << MONO_RESOLUTION_SCOPE_BITS) | MONO_RESOLUTION_SCOPE_TYPEREF;
2692         } else {
2693                 scope = resolution_scope_from_image (assembly, klass->image);
2694         }
2695         table = &assembly->tables [MONO_TABLE_TYPEREF];
2696         if (assembly->save) {
2697                 alloc_table (table, table->rows + 1);
2698                 values = table->values + table->next_idx * MONO_TYPEREF_SIZE;
2699                 values [MONO_TYPEREF_SCOPE] = scope;
2700                 values [MONO_TYPEREF_NAME] = string_heap_insert (&assembly->sheap, klass->name);
2701                 values [MONO_TYPEREF_NAMESPACE] = string_heap_insert (&assembly->sheap, klass->name_space);
2702         }
2703         token = MONO_TYPEDEFORREF_TYPEREF | (table->next_idx << MONO_TYPEDEFORREF_BITS); /* typeref */
2704         g_hash_table_insert (assembly->typeref, type, GUINT_TO_POINTER(token));
2705         table->next_idx ++;
2706         register_dyn_token (assembly, token, (MonoObject *)mono_class_get_ref_info (klass));
2707         return token;
2708 }
2709
2710 /*
2711  * Despite the name, we handle also TypeSpec (with the above helper).
2712  */
2713 static guint32
2714 mono_image_typedef_or_ref (MonoDynamicImage *assembly, MonoType *type)
2715 {
2716         return mono_image_typedef_or_ref_full (assembly, type, TRUE);
2717 }
2718
2719 #ifndef DISABLE_REFLECTION_EMIT
2720 static guint32
2721 mono_image_add_memberef_row (MonoDynamicImage *assembly, guint32 parent, const char *name, guint32 sig)
2722 {
2723         MONO_REQ_GC_NEUTRAL_MODE;
2724
2725         MonoDynamicTable *table;
2726         guint32 *values;
2727         guint32 token, pclass;
2728
2729         switch (parent & MONO_TYPEDEFORREF_MASK) {
2730         case MONO_TYPEDEFORREF_TYPEREF:
2731                 pclass = MONO_MEMBERREF_PARENT_TYPEREF;
2732                 break;
2733         case MONO_TYPEDEFORREF_TYPESPEC:
2734                 pclass = MONO_MEMBERREF_PARENT_TYPESPEC;
2735                 break;
2736         case MONO_TYPEDEFORREF_TYPEDEF:
2737                 pclass = MONO_MEMBERREF_PARENT_TYPEDEF;
2738                 break;
2739         default:
2740                 g_warning ("unknown typeref or def token 0x%08x for %s", parent, name);
2741                 return 0;
2742         }
2743         /* extract the index */
2744         parent >>= MONO_TYPEDEFORREF_BITS;
2745
2746         table = &assembly->tables [MONO_TABLE_MEMBERREF];
2747
2748         if (assembly->save) {
2749                 alloc_table (table, table->rows + 1);
2750                 values = table->values + table->next_idx * MONO_MEMBERREF_SIZE;
2751                 values [MONO_MEMBERREF_CLASS] = pclass | (parent << MONO_MEMBERREF_PARENT_BITS);
2752                 values [MONO_MEMBERREF_NAME] = string_heap_insert (&assembly->sheap, name);
2753                 values [MONO_MEMBERREF_SIGNATURE] = sig;
2754         }
2755
2756         token = MONO_TOKEN_MEMBER_REF | table->next_idx;
2757         table->next_idx ++;
2758
2759         return token;
2760 }
2761
2762 /*
2763  * Insert a memberef row into the metadata: the token that point to the memberref
2764  * is returned. Caching is done in the caller (mono_image_get_methodref_token() or
2765  * mono_image_get_fieldref_token()).
2766  * The sig param is an index to an already built signature.
2767  */
2768 static guint32
2769 mono_image_get_memberref_token (MonoDynamicImage *assembly, MonoType *type, const char *name, guint32 sig)
2770 {
2771         MONO_REQ_GC_NEUTRAL_MODE;
2772
2773         guint32 parent = mono_image_typedef_or_ref (assembly, type);
2774         return mono_image_add_memberef_row (assembly, parent, name, sig);
2775 }
2776
2777
2778 static guint32
2779 mono_image_get_methodref_token (MonoDynamicImage *assembly, MonoMethod *method, gboolean create_typespec)
2780 {
2781         MONO_REQ_GC_NEUTRAL_MODE;
2782
2783         guint32 token;
2784         MonoMethodSignature *sig;
2785         
2786         create_typespec = create_typespec && method->is_generic && method->klass->image != &assembly->image;
2787
2788         if (create_typespec) {
2789                 token = GPOINTER_TO_UINT (g_hash_table_lookup (assembly->handleref, GUINT_TO_POINTER (GPOINTER_TO_UINT (method) + 1)));
2790                 if (token)
2791                         return token;
2792         } 
2793
2794         token = GPOINTER_TO_UINT (g_hash_table_lookup (assembly->handleref, method));
2795         if (token && !create_typespec)
2796                 return token;
2797
2798         g_assert (!method->is_inflated);
2799         if (!token) {
2800                 /*
2801                  * A methodref signature can't contain an unmanaged calling convention.
2802                  */
2803                 sig = mono_metadata_signature_dup (mono_method_signature (method));
2804                 if ((sig->call_convention != MONO_CALL_DEFAULT) && (sig->call_convention != MONO_CALL_VARARG))
2805                         sig->call_convention = MONO_CALL_DEFAULT;
2806                 token = mono_image_get_memberref_token (assembly, &method->klass->byval_arg,
2807                         method->name,  method_encode_signature (assembly, sig));
2808                 g_free (sig);
2809                 g_hash_table_insert (assembly->handleref, method, GUINT_TO_POINTER(token));
2810         }
2811
2812         if (create_typespec) {
2813                 MonoDynamicTable *table = &assembly->tables [MONO_TABLE_METHODSPEC];
2814                 g_assert (mono_metadata_token_table (token) == MONO_TABLE_MEMBERREF);
2815                 token = (mono_metadata_token_index (token) << MONO_METHODDEFORREF_BITS) | MONO_METHODDEFORREF_METHODREF;
2816
2817                 if (assembly->save) {
2818                         guint32 *values;
2819
2820                         alloc_table (table, table->rows + 1);
2821                         values = table->values + table->next_idx * MONO_METHODSPEC_SIZE;
2822                         values [MONO_METHODSPEC_METHOD] = token;
2823                         values [MONO_METHODSPEC_SIGNATURE] = encode_generic_method_sig (assembly, &mono_method_get_generic_container (method)->context);
2824                 }
2825
2826                 token = MONO_TOKEN_METHOD_SPEC | table->next_idx;
2827                 table->next_idx ++;
2828                 /*methodspec and memberef tokens are diferent, */
2829                 g_hash_table_insert (assembly->handleref, GUINT_TO_POINTER (GPOINTER_TO_UINT (method) + 1), GUINT_TO_POINTER (token));
2830                 return token;
2831         }
2832         return token;
2833 }
2834
2835 static guint32
2836 mono_image_get_methodref_token_for_methodbuilder (MonoDynamicImage *assembly, MonoReflectionMethodBuilder *method, MonoError *error)
2837 {
2838         guint32 token, parent, sig;
2839         ReflectionMethodBuilder rmb;
2840         MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder *)method->type;
2841         
2842         mono_error_init (error);
2843         token = GPOINTER_TO_UINT (g_hash_table_lookup (assembly->handleref, method));
2844         if (token)
2845                 return token;
2846
2847         if (!reflection_methodbuilder_from_method_builder (&rmb, method, error))
2848                 return 0;
2849
2850         /*
2851          * A methodref signature can't contain an unmanaged calling convention.
2852          * Since some flags are encoded as part of call_conv, we need to check against it.
2853         */
2854         if ((rmb.call_conv & ~0x60) != MONO_CALL_DEFAULT && (rmb.call_conv & ~0x60) != MONO_CALL_VARARG)
2855                 rmb.call_conv = (rmb.call_conv & 0x60) | MONO_CALL_DEFAULT;
2856
2857         sig = method_builder_encode_signature (assembly, &rmb);
2858
2859         if (tb->generic_params)
2860                 parent = create_generic_typespec (assembly, tb);
2861         else
2862                 parent = mono_image_typedef_or_ref (assembly, mono_reflection_type_get_handle ((MonoReflectionType*)rmb.type));
2863
2864         char *name = mono_string_to_utf8 (method->name);
2865
2866         token = mono_image_add_memberef_row (assembly, parent, name, sig);
2867         g_free (name);
2868
2869         g_hash_table_insert (assembly->handleref, method, GUINT_TO_POINTER(token));
2870
2871         return token;
2872 }
2873
2874 static guint32
2875 mono_image_get_varargs_method_token (MonoDynamicImage *assembly, guint32 original,
2876                                      const gchar *name, guint32 sig)
2877 {
2878         MonoDynamicTable *table;
2879         guint32 token;
2880         guint32 *values;
2881         
2882         table = &assembly->tables [MONO_TABLE_MEMBERREF];
2883
2884         if (assembly->save) {
2885                 alloc_table (table, table->rows + 1);
2886                 values = table->values + table->next_idx * MONO_MEMBERREF_SIZE;
2887                 values [MONO_MEMBERREF_CLASS] = original;
2888                 values [MONO_MEMBERREF_NAME] = string_heap_insert (&assembly->sheap, name);
2889                 values [MONO_MEMBERREF_SIGNATURE] = sig;
2890         }
2891
2892         token = MONO_TOKEN_MEMBER_REF | table->next_idx;
2893         table->next_idx ++;
2894
2895         return token;
2896 }
2897
2898 static guint32
2899 encode_generic_method_definition_sig (MonoDynamicImage *assembly, MonoReflectionMethodBuilder *mb)
2900 {
2901         SigBuffer buf;
2902         int i;
2903         guint32 nparams = mono_array_length (mb->generic_params);
2904         guint32 idx;
2905
2906         if (!assembly->save)
2907                 return 0;
2908
2909         sigbuffer_init (&buf, 32);
2910
2911         sigbuffer_add_value (&buf, 0xa);
2912         sigbuffer_add_value (&buf, nparams);
2913
2914         for (i = 0; i < nparams; i++) {
2915                 sigbuffer_add_value (&buf, MONO_TYPE_MVAR);
2916                 sigbuffer_add_value (&buf, i);
2917         }
2918
2919         idx = sigbuffer_add_to_blob_cached (assembly, &buf);
2920         sigbuffer_free (&buf);
2921         return idx;
2922 }
2923
2924 static guint32
2925 mono_image_get_methodspec_token_for_generic_method_definition (MonoDynamicImage *assembly, MonoReflectionMethodBuilder *mb, MonoError *error)
2926 {
2927         MonoDynamicTable *table;
2928         guint32 *values;
2929         guint32 token, mtoken = 0;
2930
2931         mono_error_init (error);
2932         token = GPOINTER_TO_UINT (mono_g_hash_table_lookup (assembly->methodspec, mb));
2933         if (token)
2934                 return token;
2935
2936         table = &assembly->tables [MONO_TABLE_METHODSPEC];
2937
2938         mtoken = mono_image_get_methodref_token_for_methodbuilder (assembly, mb, error);
2939         if (!mono_error_ok (error))
2940                 return 0;
2941
2942         switch (mono_metadata_token_table (mtoken)) {
2943         case MONO_TABLE_MEMBERREF:
2944                 mtoken = (mono_metadata_token_index (mtoken) << MONO_METHODDEFORREF_BITS) | MONO_METHODDEFORREF_METHODREF;
2945                 break;
2946         case MONO_TABLE_METHOD:
2947                 mtoken = (mono_metadata_token_index (mtoken) << MONO_METHODDEFORREF_BITS) | MONO_METHODDEFORREF_METHODDEF;
2948                 break;
2949         default:
2950                 g_assert_not_reached ();
2951         }
2952
2953         if (assembly->save) {
2954                 alloc_table (table, table->rows + 1);
2955                 values = table->values + table->next_idx * MONO_METHODSPEC_SIZE;
2956                 values [MONO_METHODSPEC_METHOD] = mtoken;
2957                 values [MONO_METHODSPEC_SIGNATURE] = encode_generic_method_definition_sig (assembly, mb);
2958         }
2959
2960         token = MONO_TOKEN_METHOD_SPEC | table->next_idx;
2961         table->next_idx ++;
2962
2963         mono_g_hash_table_insert (assembly->methodspec, mb, GUINT_TO_POINTER(token));
2964         return token;
2965 }
2966
2967 static guint32
2968 mono_image_get_methodbuilder_token (MonoDynamicImage *assembly, MonoReflectionMethodBuilder *mb, gboolean create_methodspec, MonoError *error)
2969 {
2970         guint32 token;
2971
2972         mono_error_init (error);
2973
2974         if (mb->generic_params && create_methodspec) 
2975                 return mono_image_get_methodspec_token_for_generic_method_definition (assembly, mb, error);
2976
2977         token = GPOINTER_TO_UINT (mono_g_hash_table_lookup (assembly->handleref_managed, mb));
2978         if (token)
2979                 return token;
2980
2981         token = mono_image_get_methodref_token_for_methodbuilder (assembly, mb, error);
2982         if (!mono_error_ok (error))
2983                 return 0;
2984         mono_g_hash_table_insert (assembly->handleref_managed, mb, GUINT_TO_POINTER(token));
2985         return token;
2986 }
2987
2988 static guint32
2989 mono_image_get_ctorbuilder_token (MonoDynamicImage *assembly, MonoReflectionCtorBuilder *mb, MonoError *error)
2990 {
2991         guint32 token, parent, sig;
2992         ReflectionMethodBuilder rmb;
2993         char *name;
2994         MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder *)mb->type;
2995         
2996         mono_error_init (error);
2997         
2998         token = GPOINTER_TO_UINT (mono_g_hash_table_lookup (assembly->handleref_managed, mb));
2999         if (token)
3000                 return token;
3001
3002         if (!reflection_methodbuilder_from_ctor_builder (&rmb, mb, error))
3003                 return 0;
3004
3005         if (tb->generic_params)
3006                 parent = create_generic_typespec (assembly, tb);
3007         else
3008                 parent = mono_image_typedef_or_ref (assembly, mono_reflection_type_get_handle ((MonoReflectionType*)tb));
3009         
3010         name = mono_string_to_utf8 (rmb.name);
3011         sig = method_builder_encode_signature (assembly, &rmb);
3012
3013         token = mono_image_add_memberef_row (assembly, parent, name, sig);
3014
3015         g_free (name);
3016         mono_g_hash_table_insert (assembly->handleref_managed, mb, GUINT_TO_POINTER(token));
3017         return token;
3018 }
3019 #endif
3020
3021 static gboolean
3022 is_field_on_inst (MonoClassField *field)
3023 {
3024         return (field->parent->generic_class && field->parent->generic_class->is_dynamic && ((MonoDynamicGenericClass*)field->parent->generic_class)->fields);
3025 }
3026
3027 /*
3028  * If FIELD is a field of a MonoDynamicGenericClass, return its non-inflated type.
3029  */
3030 static MonoType*
3031 get_field_on_inst_generic_type (MonoClassField *field)
3032 {
3033         MonoClass *klass, *gtd;
3034         MonoDynamicGenericClass *dgclass;
3035         int field_index;
3036
3037         g_assert (is_field_on_inst (field));
3038
3039         dgclass = (MonoDynamicGenericClass*)field->parent->generic_class;
3040
3041         if (field >= dgclass->fields && field - dgclass->fields < dgclass->count_fields) {
3042                 field_index = field - dgclass->fields;
3043                 return dgclass->field_generic_types [field_index];              
3044         }
3045
3046         klass = field->parent;
3047         gtd = klass->generic_class->container_class;
3048
3049         if (field >= klass->fields && field - klass->fields < klass->field.count) {
3050                 field_index = field - klass->fields;
3051                 return gtd->fields [field_index].type;
3052         }
3053
3054         g_assert_not_reached ();
3055         return 0;
3056 }
3057
3058 #ifndef DISABLE_REFLECTION_EMIT
3059 static guint32
3060 mono_image_get_fieldref_token (MonoDynamicImage *assembly, MonoObject *f, MonoClassField *field)
3061 {
3062         MonoType *type;
3063         guint32 token;
3064
3065         g_assert (field);
3066         g_assert (field->parent);
3067
3068         token = GPOINTER_TO_UINT (mono_g_hash_table_lookup (assembly->handleref_managed, f));
3069         if (token)
3070                 return token;
3071
3072         if (field->parent->generic_class && field->parent->generic_class->container_class && field->parent->generic_class->container_class->fields) {
3073                 int index = field - field->parent->fields;
3074                 type = mono_field_get_type (&field->parent->generic_class->container_class->fields [index]);
3075         } else {
3076                 if (is_field_on_inst (field))
3077                         type = get_field_on_inst_generic_type (field);
3078                 else
3079                         type = mono_field_get_type (field);
3080         }
3081         token = mono_image_get_memberref_token (assembly, &field->parent->byval_arg,
3082                                                                                         mono_field_get_name (field),
3083                                                                                         fieldref_encode_signature (assembly, field->parent->image, type));
3084         mono_g_hash_table_insert (assembly->handleref_managed, f, GUINT_TO_POINTER(token));
3085         return token;
3086 }
3087
3088 static guint32
3089 mono_image_get_field_on_inst_token (MonoDynamicImage *assembly, MonoReflectionFieldOnTypeBuilderInst *f)
3090 {
3091         guint32 token;
3092         MonoClass *klass;
3093         MonoGenericClass *gclass;
3094         MonoType *type;
3095         char *name;
3096
3097         token = GPOINTER_TO_UINT (mono_g_hash_table_lookup (assembly->handleref_managed, f));
3098         if (token)
3099                 return token;
3100         if (is_sre_field_builder (mono_object_class (f->fb))) {
3101                 MonoReflectionFieldBuilder *fb = (MonoReflectionFieldBuilder *)f->fb;
3102                 type = mono_reflection_type_get_handle ((MonoReflectionType*)f->inst);
3103                 klass = mono_class_from_mono_type (type);
3104                 gclass = type->data.generic_class;
3105                 g_assert (gclass->is_dynamic);
3106
3107                 name = mono_string_to_utf8 (fb->name);
3108                 token = mono_image_get_memberref_token (assembly, &klass->byval_arg, name, 
3109                                                                                                 field_encode_signature (assembly, fb));
3110                 g_free (name);          
3111         } else if (is_sr_mono_field (mono_object_class (f->fb))) {
3112                 guint32 sig;
3113                 MonoClassField *field = ((MonoReflectionField *)f->fb)->field;
3114
3115                 type = mono_reflection_type_get_handle ((MonoReflectionType*)f->inst);
3116                 klass = mono_class_from_mono_type (type);
3117
3118                 sig = fieldref_encode_signature (assembly, field->parent->image, field->type);
3119                 token = mono_image_get_memberref_token (assembly, &klass->byval_arg, field->name, sig);
3120         } else {
3121                 char *name = mono_type_get_full_name (mono_object_class (f->fb));
3122                 g_error ("mono_image_get_field_on_inst_token: don't know how to handle %s", name);
3123         }
3124
3125         mono_g_hash_table_insert (assembly->handleref_managed, f, GUINT_TO_POINTER (token));
3126         return token;
3127 }
3128
3129 static guint32
3130 mono_image_get_ctor_on_inst_token (MonoDynamicImage *assembly, MonoReflectionCtorOnTypeBuilderInst *c, gboolean create_methodspec, MonoError *error)
3131 {
3132         guint32 sig, token;
3133         MonoClass *klass;
3134         MonoGenericClass *gclass;
3135         MonoType *type;
3136
3137         mono_error_init (error);
3138
3139         /* A ctor cannot be a generic method, so we can ignore create_methodspec */
3140
3141         token = GPOINTER_TO_UINT (mono_g_hash_table_lookup (assembly->handleref_managed, c));
3142         if (token)
3143                 return token;
3144
3145         if (is_sre_ctor_builder (mono_object_class (c->cb))) {
3146                 MonoReflectionCtorBuilder *cb = (MonoReflectionCtorBuilder *)c->cb;
3147                 ReflectionMethodBuilder rmb;
3148                 char *name;
3149
3150                 type = mono_reflection_type_get_handle ((MonoReflectionType*)c->inst);
3151                 klass = mono_class_from_mono_type (type);
3152
3153                 gclass = type->data.generic_class;
3154                 g_assert (gclass->is_dynamic);
3155
3156                 if (!reflection_methodbuilder_from_ctor_builder (&rmb, cb, error))
3157                         return 0;
3158
3159                 name = mono_string_to_utf8 (rmb.name);
3160
3161                 sig = method_builder_encode_signature (assembly, &rmb);
3162
3163                 token = mono_image_get_memberref_token (assembly, &klass->byval_arg, name, sig);
3164                 g_free (name);
3165         } else if (is_sr_mono_cmethod (mono_object_class (c->cb))) {
3166                 MonoMethod *mm = ((MonoReflectionMethod *)c->cb)->method;
3167
3168                 type = mono_reflection_type_get_handle ((MonoReflectionType*)c->inst);
3169                 klass = mono_class_from_mono_type (type);
3170
3171                 sig = method_encode_signature (assembly, mono_method_signature (mm));
3172                 token = mono_image_get_memberref_token (assembly, &klass->byval_arg, mm->name, sig);
3173         } else {
3174                 char *name = mono_type_get_full_name (mono_object_class (c->cb));
3175                 g_error ("mono_image_get_method_on_inst_token: don't know how to handle %s", name);
3176         }
3177
3178
3179         mono_g_hash_table_insert (assembly->handleref_managed, c, GUINT_TO_POINTER (token));
3180         return token;
3181 }
3182
3183 static MonoMethod*
3184 mono_reflection_method_on_tb_inst_get_handle (MonoReflectionMethodOnTypeBuilderInst *m, MonoError *error)
3185 {
3186         MonoClass *klass;
3187         MonoGenericContext tmp_context;
3188         MonoType **type_argv;
3189         MonoGenericInst *ginst;
3190         MonoMethod *method, *inflated;
3191         int count, i;
3192
3193         mono_error_init (error);
3194
3195         init_type_builder_generics ((MonoObject*)m->inst);
3196
3197         method = inflate_method (m->inst, (MonoObject*)m->mb, error);
3198         return_val_if_nok (error, NULL);
3199
3200         klass = method->klass;
3201
3202         if (m->method_args == NULL)
3203                 return method;
3204
3205         if (method->is_inflated)
3206                 method = ((MonoMethodInflated *) method)->declaring;
3207
3208         count = mono_array_length (m->method_args);
3209
3210         type_argv = g_new0 (MonoType *, count);
3211         for (i = 0; i < count; i++) {
3212                 MonoReflectionType *garg = (MonoReflectionType *)mono_array_get (m->method_args, gpointer, i);
3213                 type_argv [i] = mono_reflection_type_get_handle (garg);
3214         }
3215         ginst = mono_metadata_get_generic_inst (count, type_argv);
3216         g_free (type_argv);
3217
3218         tmp_context.class_inst = klass->generic_class ? klass->generic_class->context.class_inst : NULL;
3219         tmp_context.method_inst = ginst;
3220
3221         inflated = mono_class_inflate_generic_method_checked (method, &tmp_context, error);
3222         mono_error_assert_ok (error);
3223         return inflated;
3224 }
3225
3226 static guint32
3227 mono_image_get_method_on_inst_token (MonoDynamicImage *assembly, MonoReflectionMethodOnTypeBuilderInst *m, gboolean create_methodspec, MonoError *error)
3228 {
3229         guint32 sig, token = 0;
3230         MonoType *type;
3231         MonoClass *klass;
3232
3233         mono_error_init (error);
3234
3235         if (m->method_args) {
3236                 MonoMethod *inflated;
3237
3238                 inflated = mono_reflection_method_on_tb_inst_get_handle (m, error);
3239                 return_val_if_nok (error, 0);
3240
3241                 if (create_methodspec)
3242                         token = mono_image_get_methodspec_token (assembly, inflated);
3243                 else
3244                         token = mono_image_get_inflated_method_token (assembly, inflated);
3245                 return token;
3246         }
3247
3248         token = GPOINTER_TO_UINT (mono_g_hash_table_lookup (assembly->handleref_managed, m));
3249         if (token)
3250                 return token;
3251
3252         if (is_sre_method_builder (mono_object_class (m->mb))) {
3253                 MonoReflectionMethodBuilder *mb = (MonoReflectionMethodBuilder *)m->mb;
3254                 MonoGenericClass *gclass;
3255                 ReflectionMethodBuilder rmb;
3256                 char *name;
3257
3258                 type = mono_reflection_type_get_handle ((MonoReflectionType*)m->inst);
3259                 klass = mono_class_from_mono_type (type);
3260                 gclass = type->data.generic_class;
3261                 g_assert (gclass->is_dynamic);
3262
3263                 if (!reflection_methodbuilder_from_method_builder (&rmb, mb, error))
3264                         return 0;
3265
3266                 name = mono_string_to_utf8 (rmb.name);
3267
3268                 sig = method_builder_encode_signature (assembly, &rmb);
3269
3270                 token = mono_image_get_memberref_token (assembly, &klass->byval_arg, name, sig);
3271                 g_free (name);          
3272         } else if (is_sr_mono_method (mono_object_class (m->mb))) {
3273                 MonoMethod *mm = ((MonoReflectionMethod *)m->mb)->method;
3274
3275                 type = mono_reflection_type_get_handle ((MonoReflectionType*)m->inst);
3276                 klass = mono_class_from_mono_type (type);
3277
3278                 sig = method_encode_signature (assembly, mono_method_signature (mm));
3279                 token = mono_image_get_memberref_token (assembly, &klass->byval_arg, mm->name, sig);
3280         } else {
3281                 char *name = mono_type_get_full_name (mono_object_class (m->mb));
3282                 g_error ("mono_image_get_method_on_inst_token: don't know how to handle %s", name);
3283         }
3284
3285         mono_g_hash_table_insert (assembly->handleref_managed, m, GUINT_TO_POINTER (token));
3286         return token;
3287 }
3288
3289 static guint32
3290 encode_generic_method_sig (MonoDynamicImage *assembly, MonoGenericContext *context)
3291 {
3292         SigBuffer buf;
3293         int i;
3294         guint32 nparams = context->method_inst->type_argc;
3295         guint32 idx;
3296
3297         if (!assembly->save)
3298                 return 0;
3299
3300         sigbuffer_init (&buf, 32);
3301         /*
3302          * FIXME: vararg, explicit_this, differenc call_conv values...
3303          */
3304         sigbuffer_add_value (&buf, 0xa); /* FIXME FIXME FIXME */
3305         sigbuffer_add_value (&buf, nparams);
3306
3307         for (i = 0; i < nparams; i++)
3308                 encode_type (assembly, context->method_inst->type_argv [i], &buf);
3309
3310         idx = sigbuffer_add_to_blob_cached (assembly, &buf);
3311         sigbuffer_free (&buf);
3312         return idx;
3313 }
3314
3315 static guint32
3316 method_encode_methodspec (MonoDynamicImage *assembly, MonoMethod *method)
3317 {
3318         MonoDynamicTable *table;
3319         guint32 *values;
3320         guint32 token, mtoken = 0, sig;
3321         MonoMethodInflated *imethod;
3322         MonoMethod *declaring;
3323
3324         table = &assembly->tables [MONO_TABLE_METHODSPEC];
3325
3326         g_assert (method->is_inflated);
3327         imethod = (MonoMethodInflated *) method;
3328         declaring = imethod->declaring;
3329
3330         sig = method_encode_signature (assembly, mono_method_signature (declaring));
3331         mtoken = mono_image_get_memberref_token (assembly, &method->klass->byval_arg, declaring->name, sig);
3332
3333         if (!mono_method_signature (declaring)->generic_param_count)
3334                 return mtoken;
3335
3336         switch (mono_metadata_token_table (mtoken)) {
3337         case MONO_TABLE_MEMBERREF:
3338                 mtoken = (mono_metadata_token_index (mtoken) << MONO_METHODDEFORREF_BITS) | MONO_METHODDEFORREF_METHODREF;
3339                 break;
3340         case MONO_TABLE_METHOD:
3341                 mtoken = (mono_metadata_token_index (mtoken) << MONO_METHODDEFORREF_BITS) | MONO_METHODDEFORREF_METHODDEF;
3342                 break;
3343         default:
3344                 g_assert_not_reached ();
3345         }
3346
3347         sig = encode_generic_method_sig (assembly, mono_method_get_context (method));
3348
3349         if (assembly->save) {
3350                 alloc_table (table, table->rows + 1);
3351                 values = table->values + table->next_idx * MONO_METHODSPEC_SIZE;
3352                 values [MONO_METHODSPEC_METHOD] = mtoken;
3353                 values [MONO_METHODSPEC_SIGNATURE] = sig;
3354         }
3355
3356         token = MONO_TOKEN_METHOD_SPEC | table->next_idx;
3357         table->next_idx ++;
3358
3359         return token;
3360 }
3361
3362 static guint32
3363 mono_image_get_methodspec_token (MonoDynamicImage *assembly, MonoMethod *method)
3364 {
3365         MonoMethodInflated *imethod;
3366         guint32 token;
3367         
3368         token = GPOINTER_TO_UINT (g_hash_table_lookup (assembly->handleref, method));
3369         if (token)
3370                 return token;
3371
3372         g_assert (method->is_inflated);
3373         imethod = (MonoMethodInflated *) method;
3374
3375         if (mono_method_signature (imethod->declaring)->generic_param_count) {
3376                 token = method_encode_methodspec (assembly, method);
3377         } else {
3378                 guint32 sig = method_encode_signature (
3379                         assembly, mono_method_signature (imethod->declaring));
3380                 token = mono_image_get_memberref_token (
3381                         assembly, &method->klass->byval_arg, method->name, sig);
3382         }
3383
3384         g_hash_table_insert (assembly->handleref, method, GUINT_TO_POINTER(token));
3385         return token;
3386 }
3387
3388 static guint32
3389 mono_image_get_inflated_method_token (MonoDynamicImage *assembly, MonoMethod *m)
3390 {
3391         MonoMethodInflated *imethod = (MonoMethodInflated *) m;
3392         guint32 sig, token;
3393
3394         sig = method_encode_signature (assembly, mono_method_signature (imethod->declaring));
3395         token = mono_image_get_memberref_token (
3396                 assembly, &m->klass->byval_arg, m->name, sig);
3397
3398         return token;
3399 }
3400
3401 static guint32
3402 create_generic_typespec (MonoDynamicImage *assembly, MonoReflectionTypeBuilder *tb)
3403 {
3404         MonoDynamicTable *table;
3405         MonoClass *klass;
3406         MonoType *type;
3407         guint32 *values;
3408         guint32 token;
3409         SigBuffer buf;
3410         int count, i;
3411
3412         /*
3413          * We're creating a TypeSpec for the TypeBuilder of a generic type declaration,
3414          * ie. what we'd normally use as the generic type in a TypeSpec signature.
3415          * Because of this, we must not insert it into the `typeref' hash table.
3416          */
3417         type = mono_reflection_type_get_handle ((MonoReflectionType*)tb);
3418         token = GPOINTER_TO_UINT (g_hash_table_lookup (assembly->typespec, type));
3419         if (token)
3420                 return token;
3421
3422         sigbuffer_init (&buf, 32);
3423
3424         g_assert (tb->generic_params);
3425         klass = mono_class_from_mono_type (type);
3426
3427         if (tb->generic_container)
3428                 mono_reflection_create_generic_class (tb);
3429
3430         sigbuffer_add_value (&buf, MONO_TYPE_GENERICINST);
3431         g_assert (klass->generic_container);
3432         sigbuffer_add_value (&buf, klass->byval_arg.type);
3433         sigbuffer_add_value (&buf, mono_image_typedef_or_ref_full (assembly, &klass->byval_arg, FALSE));
3434
3435         count = mono_array_length (tb->generic_params);
3436         sigbuffer_add_value (&buf, count);
3437         for (i = 0; i < count; i++) {
3438                 MonoReflectionGenericParam *gparam;
3439
3440                 gparam = mono_array_get (tb->generic_params, MonoReflectionGenericParam *, i);
3441
3442                 encode_type (assembly, mono_reflection_type_get_handle ((MonoReflectionType*)gparam), &buf);
3443         }
3444
3445         table = &assembly->tables [MONO_TABLE_TYPESPEC];
3446
3447         if (assembly->save) {
3448                 token = sigbuffer_add_to_blob_cached (assembly, &buf);
3449                 alloc_table (table, table->rows + 1);
3450                 values = table->values + table->next_idx * MONO_TYPESPEC_SIZE;
3451                 values [MONO_TYPESPEC_SIGNATURE] = token;
3452         }
3453         sigbuffer_free (&buf);
3454
3455         token = MONO_TYPEDEFORREF_TYPESPEC | (table->next_idx << MONO_TYPEDEFORREF_BITS);
3456         g_hash_table_insert (assembly->typespec, type, GUINT_TO_POINTER(token));
3457         table->next_idx ++;
3458         return token;
3459 }
3460
3461 /*
3462  * Return a copy of TYPE, adding the custom modifiers in MODREQ and MODOPT.
3463  */
3464 static MonoType*
3465 add_custom_modifiers (MonoDynamicImage *assembly, MonoType *type, MonoArray *modreq, MonoArray *modopt)
3466 {
3467         int i, count, len, pos;
3468         MonoType *t;
3469
3470         count = 0;
3471         if (modreq)
3472                 count += mono_array_length (modreq);
3473         if (modopt)
3474                 count += mono_array_length (modopt);
3475
3476         if (count == 0)
3477                 return mono_metadata_type_dup (NULL, type);
3478
3479         len = MONO_SIZEOF_TYPE + ((gint32)count) * sizeof (MonoCustomMod);
3480         t = (MonoType *)g_malloc (len);
3481         memcpy (t, type, MONO_SIZEOF_TYPE);
3482
3483         t->num_mods = count;
3484         pos = 0;
3485         if (modreq) {
3486                 for (i = 0; i < mono_array_length (modreq); ++i) {
3487                         MonoType *mod = mono_type_array_get_and_resolve (modreq, i);
3488                         t->modifiers [pos].required = 1;
3489                         t->modifiers [pos].token = mono_image_typedef_or_ref (assembly, mod);
3490                         pos ++;
3491                 }
3492         }
3493         if (modopt) {
3494                 for (i = 0; i < mono_array_length (modopt); ++i) {
3495                         MonoType *mod = mono_type_array_get_and_resolve (modopt, i);
3496                         t->modifiers [pos].required = 0;
3497                         t->modifiers [pos].token = mono_image_typedef_or_ref (assembly, mod);
3498                         pos ++;
3499                 }
3500         }
3501
3502         return t;
3503 }
3504
3505 static void
3506 init_type_builder_generics (MonoObject *type)
3507 {
3508         MonoReflectionTypeBuilder *tb;
3509
3510         if (!is_sre_type_builder(mono_object_class (type)))
3511                 return;
3512         tb = (MonoReflectionTypeBuilder *)type;
3513
3514         if (tb && tb->generic_container)
3515                 mono_reflection_create_generic_class (tb);
3516 }
3517
3518 static guint32
3519 mono_image_get_generic_field_token (MonoDynamicImage *assembly, MonoReflectionFieldBuilder *fb)
3520 {
3521         MonoDynamicTable *table;
3522         MonoType *custom = NULL, *type;
3523         guint32 *values;
3524         guint32 token, pclass, parent, sig;
3525         gchar *name;
3526
3527         token = GPOINTER_TO_UINT (mono_g_hash_table_lookup (assembly->handleref_managed, fb));
3528         if (token)
3529                 return token;
3530
3531         /* FIXME: is this call necessary? */
3532         mono_class_from_mono_type (mono_reflection_type_get_handle (fb->typeb));
3533         name = mono_string_to_utf8 (fb->name);
3534
3535         /*FIXME this is one more layer of ugliness due how types are created.*/
3536         init_type_builder_generics (fb->type);
3537
3538         /* fb->type does not include the custom modifiers */
3539         /* FIXME: We should do this in one place when a fieldbuilder is created */
3540         type = mono_reflection_type_get_handle ((MonoReflectionType*)fb->type);
3541         if (fb->modreq || fb->modopt)
3542                 type = custom = add_custom_modifiers (assembly, type, fb->modreq, fb->modopt);
3543
3544         sig = fieldref_encode_signature (assembly, NULL, type);
3545         g_free (custom);
3546
3547         parent = create_generic_typespec (assembly, (MonoReflectionTypeBuilder *) fb->typeb);
3548         g_assert ((parent & MONO_TYPEDEFORREF_MASK) == MONO_TYPEDEFORREF_TYPESPEC);
3549         
3550         pclass = MONO_MEMBERREF_PARENT_TYPESPEC;
3551         parent >>= MONO_TYPEDEFORREF_BITS;
3552
3553         table = &assembly->tables [MONO_TABLE_MEMBERREF];
3554
3555         if (assembly->save) {
3556                 alloc_table (table, table->rows + 1);
3557                 values = table->values + table->next_idx * MONO_MEMBERREF_SIZE;
3558                 values [MONO_MEMBERREF_CLASS] = pclass | (parent << MONO_MEMBERREF_PARENT_BITS);
3559                 values [MONO_MEMBERREF_NAME] = string_heap_insert (&assembly->sheap, name);
3560                 values [MONO_MEMBERREF_SIGNATURE] = sig;
3561         }
3562
3563         token = MONO_TOKEN_MEMBER_REF | table->next_idx;
3564         table->next_idx ++;
3565         mono_g_hash_table_insert (assembly->handleref_managed, fb, GUINT_TO_POINTER(token));
3566         g_free (name);
3567         return token;
3568 }
3569
3570 static guint32
3571 mono_reflection_encode_sighelper (MonoDynamicImage *assembly, MonoReflectionSigHelper *helper)
3572 {
3573         SigBuffer buf;
3574         guint32 nargs;
3575         guint32 i, idx;
3576
3577         if (!assembly->save)
3578                 return 0;
3579
3580         /* FIXME: this means SignatureHelper.SignatureHelpType.HELPER_METHOD */
3581         g_assert (helper->type == 2);
3582
3583         if (helper->arguments)
3584                 nargs = mono_array_length (helper->arguments);
3585         else
3586                 nargs = 0;
3587
3588         sigbuffer_init (&buf, 32);
3589
3590         /* Encode calling convention */
3591         /* Change Any to Standard */
3592         if ((helper->call_conv & 0x03) == 0x03)
3593                 helper->call_conv = 0x01;
3594         /* explicit_this implies has_this */
3595         if (helper->call_conv & 0x40)
3596                 helper->call_conv &= 0x20;
3597
3598         if (helper->call_conv == 0) { /* Unmanaged */
3599                 idx = helper->unmanaged_call_conv - 1;
3600         } else {
3601                 /* Managed */
3602                 idx = helper->call_conv & 0x60; /* has_this + explicit_this */
3603                 if (helper->call_conv & 0x02) /* varargs */
3604                         idx += 0x05;
3605         }
3606
3607         sigbuffer_add_byte (&buf, idx);
3608         sigbuffer_add_value (&buf, nargs);
3609         encode_reflection_type (assembly, helper->return_type, &buf);
3610         for (i = 0; i < nargs; ++i) {
3611                 MonoArray *modreqs = NULL;
3612                 MonoArray *modopts = NULL;
3613                 MonoReflectionType *pt;
3614
3615                 if (helper->modreqs && (i < mono_array_length (helper->modreqs)))
3616                         modreqs = mono_array_get (helper->modreqs, MonoArray*, i);
3617                 if (helper->modopts && (i < mono_array_length (helper->modopts)))
3618                         modopts = mono_array_get (helper->modopts, MonoArray*, i);
3619
3620                 encode_custom_modifiers (assembly, modreqs, modopts, &buf);
3621                 pt = mono_array_get (helper->arguments, MonoReflectionType*, i);
3622                 encode_reflection_type (assembly, pt, &buf);
3623         }
3624         idx = sigbuffer_add_to_blob_cached (assembly, &buf);
3625         sigbuffer_free (&buf);
3626
3627         return idx;
3628 }
3629
3630 static guint32 
3631 mono_image_get_sighelper_token (MonoDynamicImage *assembly, MonoReflectionSigHelper *helper)
3632 {
3633         guint32 idx;
3634         MonoDynamicTable *table;
3635         guint32 *values;
3636
3637         table = &assembly->tables [MONO_TABLE_STANDALONESIG];
3638         idx = table->next_idx ++;
3639         table->rows ++;
3640         alloc_table (table, table->rows);
3641         values = table->values + idx * MONO_STAND_ALONE_SIGNATURE_SIZE;
3642
3643         values [MONO_STAND_ALONE_SIGNATURE] =
3644                 mono_reflection_encode_sighelper (assembly, helper);
3645
3646         return idx;
3647 }
3648
3649 static int
3650 reflection_cc_to_file (int call_conv) {
3651         switch (call_conv & 0x3) {
3652         case 0:
3653         case 1: return MONO_CALL_DEFAULT;
3654         case 2: return MONO_CALL_VARARG;
3655         default:
3656                 g_assert_not_reached ();
3657         }
3658         return 0;
3659 }
3660 #endif /* !DISABLE_REFLECTION_EMIT */
3661
3662 typedef struct {
3663         MonoType *parent;
3664         MonoMethodSignature *sig;
3665         char *name;
3666         guint32 token;
3667 } ArrayMethod;
3668
3669 #ifndef DISABLE_REFLECTION_EMIT
3670 static guint32
3671 mono_image_get_array_token (MonoDynamicImage *assembly, MonoReflectionArrayMethod *m)
3672 {
3673         guint32 nparams, i;
3674         GList *tmp;
3675         char *name;
3676         MonoMethodSignature *sig;
3677         ArrayMethod *am;
3678         MonoType *mtype;
3679
3680         name = mono_string_to_utf8 (m->name);
3681         nparams = mono_array_length (m->parameters);
3682         sig = (MonoMethodSignature *)g_malloc0 (MONO_SIZEOF_METHOD_SIGNATURE + sizeof (MonoType*) * nparams);
3683         sig->hasthis = 1;
3684         sig->sentinelpos = -1;
3685         sig->call_convention = reflection_cc_to_file (m->call_conv);
3686         sig->param_count = nparams;
3687         sig->ret = m->ret ? mono_reflection_type_get_handle (m->ret): &mono_defaults.void_class->byval_arg;
3688         mtype = mono_reflection_type_get_handle (m->parent);
3689         for (i = 0; i < nparams; ++i)
3690                 sig->params [i] = mono_type_array_get_and_resolve (m->parameters, i);
3691
3692         for (tmp = assembly->array_methods; tmp; tmp = tmp->next) {
3693                 am = (ArrayMethod *)tmp->data;
3694                 if (strcmp (name, am->name) == 0 && 
3695                                 mono_metadata_type_equal (am->parent, mtype) &&
3696                                 mono_metadata_signature_equal (am->sig, sig)) {
3697                         g_free (name);
3698                         g_free (sig);
3699                         m->table_idx = am->token & 0xffffff;
3700                         return am->token;
3701                 }
3702         }
3703         am = g_new0 (ArrayMethod, 1);
3704         am->name = name;
3705         am->sig = sig;
3706         am->parent = mtype;
3707         am->token = mono_image_get_memberref_token (assembly, am->parent, name,
3708                 method_encode_signature (assembly, sig));
3709         assembly->array_methods = g_list_prepend (assembly->array_methods, am);
3710         m->table_idx = am->token & 0xffffff;
3711         return am->token;
3712 }
3713
3714 /*
3715  * Insert into the metadata tables all the info about the TypeBuilder tb.
3716  * Data in the tables is inserted in a predefined order, since some tables need to be sorted.
3717  */
3718 static gboolean
3719 mono_image_get_type_info (MonoDomain *domain, MonoReflectionTypeBuilder *tb, MonoDynamicImage *assembly, MonoError *error)
3720 {
3721         MonoDynamicTable *table;
3722         guint *values;
3723         int i, is_object = 0, is_system = 0;
3724         char *n;
3725
3726         mono_error_init (error);
3727
3728         table = &assembly->tables [MONO_TABLE_TYPEDEF];
3729         values = table->values + tb->table_idx * MONO_TYPEDEF_SIZE;
3730         values [MONO_TYPEDEF_FLAGS] = tb->attrs;
3731         n = mono_string_to_utf8 (tb->name);
3732         if (strcmp (n, "Object") == 0)
3733                 is_object++;
3734         values [MONO_TYPEDEF_NAME] = string_heap_insert (&assembly->sheap, n);
3735         g_free (n);
3736         n = mono_string_to_utf8 (tb->nspace);
3737         if (strcmp (n, "System") == 0)
3738                 is_system++;
3739         values [MONO_TYPEDEF_NAMESPACE] = string_heap_insert (&assembly->sheap, n);
3740         g_free (n);
3741         if (tb->parent && !(is_system && is_object) && 
3742                         !(tb->attrs & TYPE_ATTRIBUTE_INTERFACE)) { /* interfaces don't have a parent */
3743                 values [MONO_TYPEDEF_EXTENDS] = mono_image_typedef_or_ref (assembly, mono_reflection_type_get_handle ((MonoReflectionType*)tb->parent));
3744         } else {
3745                 values [MONO_TYPEDEF_EXTENDS] = 0;
3746         }
3747         values [MONO_TYPEDEF_FIELD_LIST] = assembly->tables [MONO_TABLE_FIELD].next_idx;
3748         values [MONO_TYPEDEF_METHOD_LIST] = assembly->tables [MONO_TABLE_METHOD].next_idx;
3749
3750         /*
3751          * if we have explicitlayout or sequentiallayouts, output data in the
3752          * ClassLayout table.
3753          */
3754         if (((tb->attrs & TYPE_ATTRIBUTE_LAYOUT_MASK) != TYPE_ATTRIBUTE_AUTO_LAYOUT) &&
3755                         ((tb->class_size > 0) || (tb->packing_size > 0))) {
3756                 table = &assembly->tables [MONO_TABLE_CLASSLAYOUT];
3757                 table->rows++;
3758                 alloc_table (table, table->rows);
3759                 values = table->values + table->rows * MONO_CLASS_LAYOUT_SIZE;
3760                 values [MONO_CLASS_LAYOUT_PARENT] = tb->table_idx;
3761                 values [MONO_CLASS_LAYOUT_CLASS_SIZE] = tb->class_size;
3762                 values [MONO_CLASS_LAYOUT_PACKING_SIZE] = tb->packing_size;
3763         }
3764
3765         /* handle interfaces */
3766         if (tb->interfaces) {
3767                 table = &assembly->tables [MONO_TABLE_INTERFACEIMPL];
3768                 i = table->rows;
3769                 table->rows += mono_array_length (tb->interfaces);
3770                 alloc_table (table, table->rows);
3771                 values = table->values + (i + 1) * MONO_INTERFACEIMPL_SIZE;
3772                 for (i = 0; i < mono_array_length (tb->interfaces); ++i) {
3773                         MonoReflectionType* iface = (MonoReflectionType*) mono_array_get (tb->interfaces, gpointer, i);
3774                         values [MONO_INTERFACEIMPL_CLASS] = tb->table_idx;
3775                         values [MONO_INTERFACEIMPL_INTERFACE] = mono_image_typedef_or_ref (assembly, mono_reflection_type_get_handle (iface));
3776                         values += MONO_INTERFACEIMPL_SIZE;
3777                 }
3778         }
3779
3780         /* handle fields */
3781         if (tb->fields) {
3782                 table = &assembly->tables [MONO_TABLE_FIELD];
3783                 table->rows += tb->num_fields;
3784                 alloc_table (table, table->rows);
3785                 for (i = 0; i < tb->num_fields; ++i)
3786                         mono_image_get_field_info (
3787                                 mono_array_get (tb->fields, MonoReflectionFieldBuilder*, i), assembly);
3788         }
3789
3790         /* handle constructors */
3791         if (tb->ctors) {
3792                 table = &assembly->tables [MONO_TABLE_METHOD];
3793                 table->rows += mono_array_length (tb->ctors);
3794                 alloc_table (table, table->rows);
3795                 for (i = 0; i < mono_array_length (tb->ctors); ++i) {
3796                         if (!mono_image_get_ctor_info (domain,
3797                                                        mono_array_get (tb->ctors, MonoReflectionCtorBuilder*, i),
3798                                                        assembly, error))
3799                                 return FALSE;
3800                 }
3801         }
3802
3803         /* handle methods */
3804         if (tb->methods) {
3805                 table = &assembly->tables [MONO_TABLE_METHOD];
3806                 table->rows += tb->num_methods;
3807                 alloc_table (table, table->rows);
3808                 for (i = 0; i < tb->num_methods; ++i) {
3809                         if (!mono_image_get_method_info (
3810                                     mono_array_get (tb->methods, MonoReflectionMethodBuilder*, i), assembly, error))
3811                                 return FALSE;
3812                 }
3813         }
3814
3815         /* Do the same with properties etc.. */
3816         if (tb->events && mono_array_length (tb->events)) {
3817                 table = &assembly->tables [MONO_TABLE_EVENT];
3818                 table->rows += mono_array_length (tb->events);
3819                 alloc_table (table, table->rows);
3820                 table = &assembly->tables [MONO_TABLE_EVENTMAP];
3821                 table->rows ++;
3822                 alloc_table (table, table->rows);
3823                 values = table->values + table->rows * MONO_EVENT_MAP_SIZE;
3824                 values [MONO_EVENT_MAP_PARENT] = tb->table_idx;
3825                 values [MONO_EVENT_MAP_EVENTLIST] = assembly->tables [MONO_TABLE_EVENT].next_idx;
3826                 for (i = 0; i < mono_array_length (tb->events); ++i)
3827                         mono_image_get_event_info (
3828                                 mono_array_get (tb->events, MonoReflectionEventBuilder*, i), assembly);
3829         }
3830         if (tb->properties && mono_array_length (tb->properties)) {
3831                 table = &assembly->tables [MONO_TABLE_PROPERTY];
3832                 table->rows += mono_array_length (tb->properties);
3833                 alloc_table (table, table->rows);
3834                 table = &assembly->tables [MONO_TABLE_PROPERTYMAP];
3835                 table->rows ++;
3836                 alloc_table (table, table->rows);
3837                 values = table->values + table->rows * MONO_PROPERTY_MAP_SIZE;
3838                 values [MONO_PROPERTY_MAP_PARENT] = tb->table_idx;
3839                 values [MONO_PROPERTY_MAP_PROPERTY_LIST] = assembly->tables [MONO_TABLE_PROPERTY].next_idx;
3840                 for (i = 0; i < mono_array_length (tb->properties); ++i)
3841                         mono_image_get_property_info (
3842                                 mono_array_get (tb->properties, MonoReflectionPropertyBuilder*, i), assembly);
3843         }
3844
3845         /* handle generic parameters */
3846         if (tb->generic_params) {
3847                 table = &assembly->tables [MONO_TABLE_GENERICPARAM];
3848                 table->rows += mono_array_length (tb->generic_params);
3849                 alloc_table (table, table->rows);
3850                 for (i = 0; i < mono_array_length (tb->generic_params); ++i) {
3851                         guint32 owner = MONO_TYPEORMETHOD_TYPE | (tb->table_idx << MONO_TYPEORMETHOD_BITS);
3852
3853                         mono_image_get_generic_param_info (
3854                                 mono_array_get (tb->generic_params, MonoReflectionGenericParam*, i), owner, assembly);
3855                 }
3856         }
3857
3858         mono_image_add_decl_security (assembly, 
3859                 mono_metadata_make_token (MONO_TABLE_TYPEDEF, tb->table_idx), tb->permissions);
3860
3861         if (tb->subtypes) {
3862                 MonoDynamicTable *ntable;
3863                 
3864                 ntable = &assembly->tables [MONO_TABLE_NESTEDCLASS];
3865                 ntable->rows += mono_array_length (tb->subtypes);
3866                 alloc_table (ntable, ntable->rows);
3867                 values = ntable->values + ntable->next_idx * MONO_NESTED_CLASS_SIZE;
3868
3869                 for (i = 0; i < mono_array_length (tb->subtypes); ++i) {
3870                         MonoReflectionTypeBuilder *subtype = mono_array_get (tb->subtypes, MonoReflectionTypeBuilder*, i);
3871
3872                         values [MONO_NESTED_CLASS_NESTED] = subtype->table_idx;
3873                         values [MONO_NESTED_CLASS_ENCLOSING] = tb->table_idx;
3874                         /*g_print ("nesting %s (%d) in %s (%d) (rows %d/%d)\n",
3875                                 mono_string_to_utf8 (subtype->name), subtype->table_idx,
3876                                 mono_string_to_utf8 (tb->name), tb->table_idx,
3877                                 ntable->next_idx, ntable->rows);*/
3878                         values += MONO_NESTED_CLASS_SIZE;
3879                         ntable->next_idx++;
3880                 }
3881         }
3882
3883         return TRUE;
3884 }
3885 #endif
3886
3887 static void
3888 collect_types (MonoPtrArray *types, MonoReflectionTypeBuilder *type)
3889 {
3890         int i;
3891
3892         mono_ptr_array_append (*types, type);
3893
3894         if (!type->subtypes)
3895                 return;
3896
3897         for (i = 0; i < mono_array_length (type->subtypes); ++i) {
3898                 MonoReflectionTypeBuilder *subtype = mono_array_get (type->subtypes, MonoReflectionTypeBuilder*, i);
3899                 collect_types (types, subtype);
3900         }
3901 }
3902
3903 static gint
3904 compare_types_by_table_idx (MonoReflectionTypeBuilder **type1, MonoReflectionTypeBuilder **type2)
3905 {
3906         if ((*type1)->table_idx < (*type2)->table_idx)
3907                 return -1;
3908         else
3909                 if ((*type1)->table_idx > (*type2)->table_idx)
3910                         return 1;
3911         else
3912                 return 0;
3913 }
3914
3915 static gboolean
3916 params_add_cattrs (MonoDynamicImage *assembly, MonoArray *pinfo, MonoError *error) {
3917         int i;
3918
3919         mono_error_init (error);
3920         if (!pinfo)
3921                 return TRUE;
3922         for (i = 0; i < mono_array_length (pinfo); ++i) {
3923                 MonoReflectionParamBuilder *pb;
3924                 pb = mono_array_get (pinfo, MonoReflectionParamBuilder *, i);
3925                 if (!pb)
3926                         continue;
3927                 if (!mono_image_add_cattrs (assembly, pb->table_idx, MONO_CUSTOM_ATTR_PARAMDEF, pb->cattrs, error))
3928                         return FALSE;
3929         }
3930
3931         return TRUE;
3932 }
3933
3934 static gboolean
3935 type_add_cattrs (MonoDynamicImage *assembly, MonoReflectionTypeBuilder *tb, MonoError *error) {
3936         int i;
3937
3938         mono_error_init (error);
3939         
3940         if (!mono_image_add_cattrs (assembly, tb->table_idx, MONO_CUSTOM_ATTR_TYPEDEF, tb->cattrs, error))
3941                 return FALSE;
3942         if (tb->fields) {
3943                 for (i = 0; i < tb->num_fields; ++i) {
3944                         MonoReflectionFieldBuilder* fb;
3945                         fb = mono_array_get (tb->fields, MonoReflectionFieldBuilder*, i);
3946                         if (!mono_image_add_cattrs (assembly, fb->table_idx, MONO_CUSTOM_ATTR_FIELDDEF, fb->cattrs, error))
3947                                 return FALSE;
3948                 }
3949         }
3950         if (tb->events) {
3951                 for (i = 0; i < mono_array_length (tb->events); ++i) {
3952                         MonoReflectionEventBuilder* eb;
3953                         eb = mono_array_get (tb->events, MonoReflectionEventBuilder*, i);
3954                         if (!mono_image_add_cattrs (assembly, eb->table_idx, MONO_CUSTOM_ATTR_EVENT, eb->cattrs, error))
3955                                 return FALSE;
3956                 }
3957         }
3958         if (tb->properties) {
3959                 for (i = 0; i < mono_array_length (tb->properties); ++i) {
3960                         MonoReflectionPropertyBuilder* pb;
3961                         pb = mono_array_get (tb->properties, MonoReflectionPropertyBuilder*, i);
3962                         if (!mono_image_add_cattrs (assembly, pb->table_idx, MONO_CUSTOM_ATTR_PROPERTY, pb->cattrs, error))
3963                                 return FALSE;
3964                 }
3965         }
3966         if (tb->ctors) {
3967                 for (i = 0; i < mono_array_length (tb->ctors); ++i) {
3968                         MonoReflectionCtorBuilder* cb;
3969                         cb = mono_array_get (tb->ctors, MonoReflectionCtorBuilder*, i);
3970                         if (!mono_image_add_cattrs (assembly, cb->table_idx, MONO_CUSTOM_ATTR_METHODDEF, cb->cattrs, error) ||
3971                             !params_add_cattrs (assembly, cb->pinfo, error))
3972                                 return FALSE;
3973                 }
3974         }
3975
3976         if (tb->methods) {
3977                 for (i = 0; i < tb->num_methods; ++i) {
3978                         MonoReflectionMethodBuilder* mb;
3979                         mb = mono_array_get (tb->methods, MonoReflectionMethodBuilder*, i);
3980                         if (!mono_image_add_cattrs (assembly, mb->table_idx, MONO_CUSTOM_ATTR_METHODDEF, mb->cattrs, error) ||
3981                             !params_add_cattrs (assembly, mb->pinfo, error))
3982                                 return FALSE;
3983                 }
3984         }
3985
3986         if (tb->subtypes) {
3987                 for (i = 0; i < mono_array_length (tb->subtypes); ++i) {
3988                         if (!type_add_cattrs (assembly, mono_array_get (tb->subtypes, MonoReflectionTypeBuilder*, i), error))
3989                                 return FALSE;
3990                 }
3991         }
3992
3993         return TRUE;
3994 }
3995
3996 static gboolean
3997 module_add_cattrs (MonoDynamicImage *assembly, MonoReflectionModuleBuilder *moduleb, MonoError *error)
3998 {
3999         int i;
4000         
4001         mono_error_init (error);
4002
4003         if (!mono_image_add_cattrs (assembly, moduleb->table_idx, MONO_CUSTOM_ATTR_MODULE, moduleb->cattrs, error))
4004                 return FALSE;
4005
4006         if (moduleb->global_methods) {
4007                 for (i = 0; i < mono_array_length (moduleb->global_methods); ++i) {
4008                         MonoReflectionMethodBuilder* mb = mono_array_get (moduleb->global_methods, MonoReflectionMethodBuilder*, i);
4009                         if (!mono_image_add_cattrs (assembly, mb->table_idx, MONO_CUSTOM_ATTR_METHODDEF, mb->cattrs, error) ||
4010                             !params_add_cattrs (assembly, mb->pinfo, error))
4011                                 return FALSE;
4012                 }
4013         }
4014
4015         if (moduleb->global_fields) {
4016                 for (i = 0; i < mono_array_length (moduleb->global_fields); ++i) {
4017                         MonoReflectionFieldBuilder *fb = mono_array_get (moduleb->global_fields, MonoReflectionFieldBuilder*, i);
4018                         if (!mono_image_add_cattrs (assembly, fb->table_idx, MONO_CUSTOM_ATTR_FIELDDEF, fb->cattrs, error))
4019                                 return FALSE;
4020                 }
4021         }
4022         
4023         if (moduleb->types) {
4024                 for (i = 0; i < moduleb->num_types; ++i) {
4025                         if (!type_add_cattrs (assembly, mono_array_get (moduleb->types, MonoReflectionTypeBuilder*, i), error))
4026                                 return FALSE;
4027                 }
4028         }
4029
4030         return TRUE;
4031 }
4032
4033 static void
4034 mono_image_fill_file_table (MonoDomain *domain, MonoReflectionModule *module, MonoDynamicImage *assembly)
4035 {
4036         MonoDynamicTable *table;
4037         guint32 *values;
4038         char blob_size [6];
4039         guchar hash [20];
4040         char *b = blob_size;
4041         char *dir, *path;
4042
4043         table = &assembly->tables [MONO_TABLE_FILE];
4044         table->rows++;
4045         alloc_table (table, table->rows);
4046         values = table->values + table->next_idx * MONO_FILE_SIZE;
4047         values [MONO_FILE_FLAGS] = FILE_CONTAINS_METADATA;
4048         values [MONO_FILE_NAME] = string_heap_insert (&assembly->sheap, module->image->module_name);
4049         if (image_is_dynamic (module->image)) {
4050                 /* This depends on the fact that the main module is emitted last */
4051                 dir = mono_string_to_utf8 (((MonoReflectionModuleBuilder*)module)->assemblyb->dir);
4052                 path = g_strdup_printf ("%s%c%s", dir, G_DIR_SEPARATOR, module->image->module_name);
4053         } else {
4054                 dir = NULL;
4055                 path = g_strdup (module->image->name);
4056         }
4057         mono_sha1_get_digest_from_file (path, hash);
4058         g_free (dir);
4059         g_free (path);
4060         mono_metadata_encode_value (20, b, &b);
4061         values [MONO_FILE_HASH_VALUE] = mono_image_add_stream_data (&assembly->blob, blob_size, b-blob_size);
4062         mono_image_add_stream_data (&assembly->blob, (char*)hash, 20);
4063         table->next_idx ++;
4064 }
4065
4066 static void
4067 mono_image_fill_module_table (MonoDomain *domain, MonoReflectionModuleBuilder *mb, MonoDynamicImage *assembly)
4068 {
4069         MonoDynamicTable *table;
4070         int i;
4071
4072         table = &assembly->tables [MONO_TABLE_MODULE];
4073         mb->table_idx = table->next_idx ++;
4074         table->values [mb->table_idx * MONO_MODULE_SIZE + MONO_MODULE_NAME] = string_heap_insert_mstring (&assembly->sheap, mb->module.name);
4075         i = mono_image_add_stream_data (&assembly->guid, mono_array_addr (mb->guid, char, 0), 16);
4076         i /= 16;
4077         ++i;
4078         table->values [mb->table_idx * MONO_MODULE_SIZE + MONO_MODULE_GENERATION] = 0;
4079         table->values [mb->table_idx * MONO_MODULE_SIZE + MONO_MODULE_MVID] = i;
4080         table->values [mb->table_idx * MONO_MODULE_SIZE + MONO_MODULE_ENC] = 0;
4081         table->values [mb->table_idx * MONO_MODULE_SIZE + MONO_MODULE_ENCBASE] = 0;
4082 }
4083
4084 static guint32
4085 mono_image_fill_export_table_from_class (MonoDomain *domain, MonoClass *klass,
4086         guint32 module_index, guint32 parent_index, MonoDynamicImage *assembly)
4087 {
4088         MonoDynamicTable *table;
4089         guint32 *values;
4090         guint32 visib, res;
4091
4092         visib = klass->flags & TYPE_ATTRIBUTE_VISIBILITY_MASK;
4093         if (! ((visib & TYPE_ATTRIBUTE_PUBLIC) || (visib & TYPE_ATTRIBUTE_NESTED_PUBLIC)))
4094                 return 0;
4095
4096         table = &assembly->tables [MONO_TABLE_EXPORTEDTYPE];
4097         table->rows++;
4098         alloc_table (table, table->rows);
4099         values = table->values + table->next_idx * MONO_EXP_TYPE_SIZE;
4100
4101         values [MONO_EXP_TYPE_FLAGS] = klass->flags;
4102         values [MONO_EXP_TYPE_TYPEDEF] = klass->type_token;
4103         if (klass->nested_in)
4104                 values [MONO_EXP_TYPE_IMPLEMENTATION] = (parent_index << MONO_IMPLEMENTATION_BITS) + MONO_IMPLEMENTATION_EXP_TYPE;
4105         else
4106                 values [MONO_EXP_TYPE_IMPLEMENTATION] = (module_index << MONO_IMPLEMENTATION_BITS) + MONO_IMPLEMENTATION_FILE;
4107         values [MONO_EXP_TYPE_NAME] = string_heap_insert (&assembly->sheap, klass->name);
4108         values [MONO_EXP_TYPE_NAMESPACE] = string_heap_insert (&assembly->sheap, klass->name_space);
4109
4110         res = table->next_idx;
4111
4112         table->next_idx ++;
4113
4114         /* Emit nested types */
4115         if (klass->ext && klass->ext->nested_classes) {
4116                 GList *tmp;
4117
4118                 for (tmp = klass->ext->nested_classes; tmp; tmp = tmp->next)
4119                         mono_image_fill_export_table_from_class (domain, (MonoClass *)tmp->data, module_index, table->next_idx - 1, assembly);
4120         }
4121
4122         return res;
4123 }
4124
4125 static void
4126 mono_image_fill_export_table (MonoDomain *domain, MonoReflectionTypeBuilder *tb,
4127         guint32 module_index, guint32 parent_index, MonoDynamicImage *assembly)
4128 {
4129         MonoClass *klass;
4130         guint32 idx, i;
4131
4132         klass = mono_class_from_mono_type (mono_reflection_type_get_handle ((MonoReflectionType*)tb));
4133
4134         klass->type_token = mono_metadata_make_token (MONO_TABLE_TYPEDEF, tb->table_idx);
4135
4136         idx = mono_image_fill_export_table_from_class (domain, klass, module_index, 
4137                                                                                                    parent_index, assembly);
4138
4139         /* 
4140          * Emit nested types
4141          * We need to do this ourselves since klass->nested_classes is not set up.
4142          */
4143         if (tb->subtypes) {
4144                 for (i = 0; i < mono_array_length (tb->subtypes); ++i)
4145                         mono_image_fill_export_table (domain, mono_array_get (tb->subtypes, MonoReflectionTypeBuilder*, i), module_index, idx, assembly);
4146         }
4147 }
4148
4149 static void
4150 mono_image_fill_export_table_from_module (MonoDomain *domain, MonoReflectionModule *module,
4151         guint32 module_index, MonoDynamicImage *assembly)
4152 {
4153         MonoImage *image = module->image;
4154         MonoTableInfo  *t;
4155         guint32 i;
4156
4157         t = &image->tables [MONO_TABLE_TYPEDEF];
4158
4159         for (i = 0; i < t->rows; ++i) {
4160                 MonoError error;
4161                 MonoClass *klass = mono_class_get_checked (image, mono_metadata_make_token (MONO_TABLE_TYPEDEF, i + 1), &error);
4162                 g_assert (mono_error_ok (&error)); /* FIXME don't swallow the error */
4163
4164                 if (klass->flags & TYPE_ATTRIBUTE_PUBLIC)
4165                         mono_image_fill_export_table_from_class (domain, klass, module_index, 0, assembly);
4166         }
4167 }
4168
4169 static void
4170 add_exported_type (MonoReflectionAssemblyBuilder *assemblyb, MonoDynamicImage *assembly, MonoClass *klass, guint32 parent_index)
4171 {
4172         MonoDynamicTable *table;
4173         guint32 *values;
4174         guint32 scope, scope_idx, impl, current_idx;
4175         gboolean forwarder = TRUE;
4176         gpointer iter = NULL;
4177         MonoClass *nested;
4178
4179         if (klass->nested_in) {
4180                 impl = (parent_index << MONO_IMPLEMENTATION_BITS) + MONO_IMPLEMENTATION_EXP_TYPE;
4181                 forwarder = FALSE;
4182         } else {
4183                 scope = resolution_scope_from_image (assembly, klass->image);
4184                 g_assert ((scope & MONO_RESOLUTION_SCOPE_MASK) == MONO_RESOLUTION_SCOPE_ASSEMBLYREF);
4185                 scope_idx = scope >> MONO_RESOLUTION_SCOPE_BITS;
4186                 impl = (scope_idx << MONO_IMPLEMENTATION_BITS) + MONO_IMPLEMENTATION_ASSEMBLYREF;
4187         }
4188
4189         table = &assembly->tables [MONO_TABLE_EXPORTEDTYPE];
4190
4191         table->rows++;
4192         alloc_table (table, table->rows);
4193         current_idx = table->next_idx;
4194         values = table->values + current_idx * MONO_EXP_TYPE_SIZE;
4195
4196         values [MONO_EXP_TYPE_FLAGS] = forwarder ? TYPE_ATTRIBUTE_FORWARDER : 0;
4197         values [MONO_EXP_TYPE_TYPEDEF] = 0;
4198         values [MONO_EXP_TYPE_IMPLEMENTATION] = impl;
4199         values [MONO_EXP_TYPE_NAME] = string_heap_insert (&assembly->sheap, klass->name);
4200         values [MONO_EXP_TYPE_NAMESPACE] = string_heap_insert (&assembly->sheap, klass->name_space);
4201
4202         table->next_idx++;
4203
4204         while ((nested = mono_class_get_nested_types (klass, &iter)))
4205                 add_exported_type (assemblyb, assembly, nested, current_idx);
4206 }
4207
4208 static void
4209 mono_image_fill_export_table_from_type_forwarders (MonoReflectionAssemblyBuilder *assemblyb, MonoDynamicImage *assembly)
4210 {
4211         MonoClass *klass;
4212         int i;
4213
4214         if (!assemblyb->type_forwarders)
4215                 return;
4216
4217         for (i = 0; i < mono_array_length (assemblyb->type_forwarders); ++i) {
4218                 MonoReflectionType *t = mono_array_get (assemblyb->type_forwarders, MonoReflectionType *, i);
4219                 MonoType *type;
4220                 if (!t)
4221                         continue;
4222
4223                 type = mono_reflection_type_get_handle (t);
4224                 g_assert (type);
4225
4226                 klass = mono_class_from_mono_type (type);
4227
4228                 add_exported_type (assemblyb, assembly, klass, 0);
4229         }
4230 }
4231
4232 #define align_pointer(base,p)\
4233         do {\
4234                 guint32 __diff = (unsigned char*)(p)-(unsigned char*)(base);\
4235                 if (__diff & 3)\
4236                         (p) += 4 - (__diff & 3);\
4237         } while (0)
4238
4239 static int
4240 compare_constants (const void *a, const void *b)
4241 {
4242         const guint32 *a_values = (const guint32 *)a;
4243         const guint32 *b_values = (const guint32 *)b;
4244         return a_values [MONO_CONSTANT_PARENT] - b_values [MONO_CONSTANT_PARENT];
4245 }
4246
4247 static int
4248 compare_semantics (const void *a, const void *b)
4249 {
4250         const guint32 *a_values = (const guint32 *)a;
4251         const guint32 *b_values = (const guint32 *)b;
4252         int assoc = a_values [MONO_METHOD_SEMA_ASSOCIATION] - b_values [MONO_METHOD_SEMA_ASSOCIATION];
4253         if (assoc)
4254                 return assoc;
4255         return a_values [MONO_METHOD_SEMA_SEMANTICS] - b_values [MONO_METHOD_SEMA_SEMANTICS];
4256 }
4257
4258 static int
4259 compare_custom_attrs (const void *a, const void *b)
4260 {
4261         const guint32 *a_values = (const guint32 *)a;
4262         const guint32 *b_values = (const guint32 *)b;
4263
4264         return a_values [MONO_CUSTOM_ATTR_PARENT] - b_values [MONO_CUSTOM_ATTR_PARENT];
4265 }
4266
4267 static int
4268 compare_field_marshal (const void *a, const void *b)
4269 {
4270         const guint32 *a_values = (const guint32 *)a;
4271         const guint32 *b_values = (const guint32 *)b;
4272
4273         return a_values [MONO_FIELD_MARSHAL_PARENT] - b_values [MONO_FIELD_MARSHAL_PARENT];
4274 }
4275
4276 static int
4277 compare_nested (const void *a, const void *b)
4278 {
4279         const guint32 *a_values = (const guint32 *)a;
4280         const guint32 *b_values = (const guint32 *)b;
4281
4282         return a_values [MONO_NESTED_CLASS_NESTED] - b_values [MONO_NESTED_CLASS_NESTED];
4283 }
4284
4285 static int
4286 compare_genericparam (const void *a, const void *b)
4287 {
4288         const GenericParamTableEntry **a_entry = (const GenericParamTableEntry **) a;
4289         const GenericParamTableEntry **b_entry = (const GenericParamTableEntry **) b;
4290
4291         if ((*b_entry)->owner == (*a_entry)->owner)
4292                 return 
4293                         mono_type_get_generic_param_num (mono_reflection_type_get_handle ((MonoReflectionType*)(*a_entry)->gparam)) -
4294                         mono_type_get_generic_param_num (mono_reflection_type_get_handle ((MonoReflectionType*)(*b_entry)->gparam));
4295         else
4296                 return (*a_entry)->owner - (*b_entry)->owner;
4297 }
4298
4299 static int
4300 compare_declsecurity_attrs (const void *a, const void *b)
4301 {
4302         const guint32 *a_values = (const guint32 *)a;
4303         const guint32 *b_values = (const guint32 *)b;
4304
4305         return a_values [MONO_DECL_SECURITY_PARENT] - b_values [MONO_DECL_SECURITY_PARENT];
4306 }
4307
4308 static int
4309 compare_interface_impl (const void *a, const void *b)
4310 {
4311         const guint32 *a_values = (const guint32 *)a;
4312         const guint32 *b_values = (const guint32 *)b;
4313
4314         int klass = a_values [MONO_INTERFACEIMPL_CLASS] - b_values [MONO_INTERFACEIMPL_CLASS];
4315         if (klass)
4316                 return klass;
4317
4318         return a_values [MONO_INTERFACEIMPL_INTERFACE] - b_values [MONO_INTERFACEIMPL_INTERFACE];
4319 }
4320
4321 static void
4322 pad_heap (MonoDynamicStream *sh)
4323 {
4324         if (sh->index & 3) {
4325                 int sz = 4 - (sh->index & 3);
4326                 memset (sh->data + sh->index, 0, sz);
4327                 sh->index += sz;
4328         }
4329 }
4330
4331 struct StreamDesc {
4332         const char *name;
4333         MonoDynamicStream *stream;
4334 };
4335
4336 /*
4337  * build_compressed_metadata() fills in the blob of data that represents the 
4338  * raw metadata as it will be saved in the PE file. The five streams are output 
4339  * and the metadata tables are comnpressed from the guint32 array representation, 
4340  * to the compressed on-disk format.
4341  */
4342 static gboolean
4343 build_compressed_metadata (MonoDynamicImage *assembly, MonoError *error)
4344 {
4345         MonoDynamicTable *table;
4346         int i;
4347         guint64 valid_mask = 0;
4348         guint64 sorted_mask;
4349         guint32 heapt_size = 0;
4350         guint32 meta_size = 256; /* allow for header and other stuff */
4351         guint32 table_offset;
4352         guint32 ntables = 0;
4353         guint64 *int64val;
4354         guint32 *int32val;
4355         guint16 *int16val;
4356         MonoImage *meta;
4357         unsigned char *p;
4358         struct StreamDesc stream_desc [5];
4359
4360         mono_error_init (error);
4361
4362         qsort (assembly->gen_params->pdata, assembly->gen_params->len, sizeof (gpointer), compare_genericparam);
4363         for (i = 0; i < assembly->gen_params->len; i++) {
4364                 GenericParamTableEntry *entry = (GenericParamTableEntry *)g_ptr_array_index (assembly->gen_params, i);
4365                 if (!write_generic_param_entry (assembly, entry, error))
4366                         return FALSE;
4367         }
4368
4369         stream_desc [0].name  = "#~";
4370         stream_desc [0].stream = &assembly->tstream;
4371         stream_desc [1].name  = "#Strings";
4372         stream_desc [1].stream = &assembly->sheap;
4373         stream_desc [2].name  = "#US";
4374         stream_desc [2].stream = &assembly->us;
4375         stream_desc [3].name  = "#Blob";
4376         stream_desc [3].stream = &assembly->blob;
4377         stream_desc [4].name  = "#GUID";
4378         stream_desc [4].stream = &assembly->guid;
4379         
4380         /* tables that are sorted */
4381         sorted_mask = ((guint64)1 << MONO_TABLE_CONSTANT) | ((guint64)1 << MONO_TABLE_FIELDMARSHAL)
4382                 | ((guint64)1 << MONO_TABLE_METHODSEMANTICS) | ((guint64)1 << MONO_TABLE_CLASSLAYOUT)
4383                 | ((guint64)1 << MONO_TABLE_FIELDLAYOUT) | ((guint64)1 << MONO_TABLE_FIELDRVA)
4384                 | ((guint64)1 << MONO_TABLE_IMPLMAP) | ((guint64)1 << MONO_TABLE_NESTEDCLASS)
4385                 | ((guint64)1 << MONO_TABLE_METHODIMPL) | ((guint64)1 << MONO_TABLE_CUSTOMATTRIBUTE)
4386                 | ((guint64)1 << MONO_TABLE_DECLSECURITY) | ((guint64)1 << MONO_TABLE_GENERICPARAM)
4387                 | ((guint64)1 << MONO_TABLE_INTERFACEIMPL);
4388         
4389         /* Compute table sizes */
4390         /* the MonoImage has already been created in mono_image_basic_init() */
4391         meta = &assembly->image;
4392
4393         /* sizes should be multiple of 4 */
4394         pad_heap (&assembly->blob);
4395         pad_heap (&assembly->guid);
4396         pad_heap (&assembly->sheap);
4397         pad_heap (&assembly->us);
4398
4399         /* Setup the info used by compute_sizes () */
4400         meta->idx_blob_wide = assembly->blob.index >= 65536 ? 1 : 0;
4401         meta->idx_guid_wide = assembly->guid.index >= 65536 ? 1 : 0;
4402         meta->idx_string_wide = assembly->sheap.index >= 65536 ? 1 : 0;
4403
4404         meta_size += assembly->blob.index;
4405         meta_size += assembly->guid.index;
4406         meta_size += assembly->sheap.index;
4407         meta_size += assembly->us.index;
4408
4409         for (i=0; i < MONO_TABLE_NUM; ++i)
4410                 meta->tables [i].rows = assembly->tables [i].rows;
4411         
4412         for (i = 0; i < MONO_TABLE_NUM; i++){
4413                 if (meta->tables [i].rows == 0)
4414                         continue;
4415                 valid_mask |= (guint64)1 << i;
4416                 ntables ++;
4417                 meta->tables [i].row_size = mono_metadata_compute_size (
4418                         meta, i, &meta->tables [i].size_bitfield);
4419                 heapt_size += meta->tables [i].row_size * meta->tables [i].rows;
4420         }
4421         heapt_size += 24; /* #~ header size */
4422         heapt_size += ntables * 4;
4423         /* make multiple of 4 */
4424         heapt_size += 3;
4425         heapt_size &= ~3;
4426         meta_size += heapt_size;
4427         meta->raw_metadata = (char *)g_malloc0 (meta_size);
4428         p = (unsigned char*)meta->raw_metadata;
4429         /* the metadata signature */
4430         *p++ = 'B'; *p++ = 'S'; *p++ = 'J'; *p++ = 'B';
4431         /* version numbers and 4 bytes reserved */
4432         int16val = (guint16*)p;
4433         *int16val++ = GUINT16_TO_LE (meta->md_version_major);
4434         *int16val = GUINT16_TO_LE (meta->md_version_minor);
4435         p += 8;
4436         /* version string */
4437         int32val = (guint32*)p;
4438         *int32val = GUINT32_TO_LE ((strlen (meta->version) + 3) & (~3)); /* needs to be multiple of 4 */
4439         p += 4;
4440         memcpy (p, meta->version, strlen (meta->version));
4441         p += GUINT32_FROM_LE (*int32val);
4442         align_pointer (meta->raw_metadata, p);
4443         int16val = (guint16*)p;
4444         *int16val++ = GUINT16_TO_LE (0); /* flags must be 0 */
4445         *int16val = GUINT16_TO_LE (5); /* number of streams */
4446         p += 4;
4447
4448         /*
4449          * write the stream info.
4450          */
4451         table_offset = (p - (unsigned char*)meta->raw_metadata) + 5 * 8 + 40; /* room needed for stream headers */
4452         table_offset += 3; table_offset &= ~3;
4453
4454         assembly->tstream.index = heapt_size;
4455         for (i = 0; i < 5; ++i) {
4456                 int32val = (guint32*)p;
4457                 stream_desc [i].stream->offset = table_offset;
4458                 *int32val++ = GUINT32_TO_LE (table_offset);
4459                 *int32val = GUINT32_TO_LE (stream_desc [i].stream->index);
4460                 table_offset += GUINT32_FROM_LE (*int32val);
4461                 table_offset += 3; table_offset &= ~3;
4462                 p += 8;
4463                 strcpy ((char*)p, stream_desc [i].name);
4464                 p += strlen (stream_desc [i].name) + 1;
4465                 align_pointer (meta->raw_metadata, p);
4466         }
4467         /* 
4468          * now copy the data, the table stream header and contents goes first.
4469          */
4470         g_assert ((p - (unsigned char*)meta->raw_metadata) < assembly->tstream.offset);
4471         p = (guchar*)meta->raw_metadata + assembly->tstream.offset;
4472         int32val = (guint32*)p;
4473         *int32val = GUINT32_TO_LE (0); /* reserved */
4474         p += 4;
4475
4476         *p++ = 2; /* version */
4477         *p++ = 0;
4478
4479         if (meta->idx_string_wide)
4480                 *p |= 0x01;
4481         if (meta->idx_guid_wide)
4482                 *p |= 0x02;
4483         if (meta->idx_blob_wide)
4484                 *p |= 0x04;
4485         ++p;
4486         *p++ = 1; /* reserved */
4487         int64val = (guint64*)p;
4488         *int64val++ = GUINT64_TO_LE (valid_mask);
4489         *int64val++ = GUINT64_TO_LE (valid_mask & sorted_mask); /* bitvector of sorted tables  */
4490         p += 16;
4491         int32val = (guint32*)p;
4492         for (i = 0; i < MONO_TABLE_NUM; i++){
4493                 if (meta->tables [i].rows == 0)
4494                         continue;
4495                 *int32val++ = GUINT32_TO_LE (meta->tables [i].rows);
4496         }
4497         p = (unsigned char*)int32val;
4498
4499         /* sort the tables that still need sorting */
4500         table = &assembly->tables [MONO_TABLE_CONSTANT];
4501         if (table->rows)
4502                 qsort (table->values + MONO_CONSTANT_SIZE, table->rows, sizeof (guint32) * MONO_CONSTANT_SIZE, compare_constants);
4503         table = &assembly->tables [MONO_TABLE_METHODSEMANTICS];
4504         if (table->rows)
4505                 qsort (table->values + MONO_METHOD_SEMA_SIZE, table->rows, sizeof (guint32) * MONO_METHOD_SEMA_SIZE, compare_semantics);
4506         table = &assembly->tables [MONO_TABLE_CUSTOMATTRIBUTE];
4507         if (table->rows)
4508                 qsort (table->values + MONO_CUSTOM_ATTR_SIZE, table->rows, sizeof (guint32) * MONO_CUSTOM_ATTR_SIZE, compare_custom_attrs);
4509         table = &assembly->tables [MONO_TABLE_FIELDMARSHAL];
4510         if (table->rows)
4511                 qsort (table->values + MONO_FIELD_MARSHAL_SIZE, table->rows, sizeof (guint32) * MONO_FIELD_MARSHAL_SIZE, compare_field_marshal);
4512         table = &assembly->tables [MONO_TABLE_NESTEDCLASS];
4513         if (table->rows)
4514                 qsort (table->values + MONO_NESTED_CLASS_SIZE, table->rows, sizeof (guint32) * MONO_NESTED_CLASS_SIZE, compare_nested);
4515         /* Section 21.11 DeclSecurity in Partition II doesn't specify this to be sorted by MS implementation requires it */
4516         table = &assembly->tables [MONO_TABLE_DECLSECURITY];
4517         if (table->rows)
4518                 qsort (table->values + MONO_DECL_SECURITY_SIZE, table->rows, sizeof (guint32) * MONO_DECL_SECURITY_SIZE, compare_declsecurity_attrs);
4519         table = &assembly->tables [MONO_TABLE_INTERFACEIMPL];
4520         if (table->rows)
4521                 qsort (table->values + MONO_INTERFACEIMPL_SIZE, table->rows, sizeof (guint32) * MONO_INTERFACEIMPL_SIZE, compare_interface_impl);
4522
4523         /* compress the tables */
4524         for (i = 0; i < MONO_TABLE_NUM; i++){
4525                 int row, col;
4526                 guint32 *values;
4527                 guint32 bitfield = meta->tables [i].size_bitfield;
4528                 if (!meta->tables [i].rows)
4529                         continue;
4530                 if (assembly->tables [i].columns != mono_metadata_table_count (bitfield))
4531                         g_error ("col count mismatch in %d: %d %d", i, assembly->tables [i].columns, mono_metadata_table_count (bitfield));
4532                 meta->tables [i].base = (char*)p;
4533                 for (row = 1; row <= meta->tables [i].rows; ++row) {
4534                         values = assembly->tables [i].values + row * assembly->tables [i].columns;
4535                         for (col = 0; col < assembly->tables [i].columns; ++col) {
4536                                 switch (mono_metadata_table_size (bitfield, col)) {
4537                                 case 1:
4538                                         *p++ = values [col];
4539                                         break;
4540                                 case 2:
4541                                         *p++ = values [col] & 0xff;
4542                                         *p++ = (values [col] >> 8) & 0xff;
4543                                         break;
4544                                 case 4:
4545                                         *p++ = values [col] & 0xff;
4546                                         *p++ = (values [col] >> 8) & 0xff;
4547                                         *p++ = (values [col] >> 16) & 0xff;
4548                                         *p++ = (values [col] >> 24) & 0xff;
4549                                         break;
4550                                 default:
4551                                         g_assert_not_reached ();
4552                                 }
4553                         }
4554                 }
4555                 g_assert ((p - (const unsigned char*)meta->tables [i].base) == (meta->tables [i].rows * meta->tables [i].row_size));
4556         }
4557         
4558         g_assert (assembly->guid.offset + assembly->guid.index < meta_size);
4559         memcpy (meta->raw_metadata + assembly->sheap.offset, assembly->sheap.data, assembly->sheap.index);
4560         memcpy (meta->raw_metadata + assembly->us.offset, assembly->us.data, assembly->us.index);
4561         memcpy (meta->raw_metadata + assembly->blob.offset, assembly->blob.data, assembly->blob.index);
4562         memcpy (meta->raw_metadata + assembly->guid.offset, assembly->guid.data, assembly->guid.index);
4563
4564         assembly->meta_size = assembly->guid.offset + assembly->guid.index;
4565
4566         return TRUE;
4567 }
4568
4569 /*
4570  * Some tables in metadata need to be sorted according to some criteria, but
4571  * when methods and fields are first created with reflection, they may be assigned a token
4572  * that doesn't correspond to the final token they will get assigned after the sorting.
4573  * ILGenerator.cs keeps a fixup table that maps the position of tokens in the IL code stream
4574  * with the reflection objects that represent them. Once all the tables are set up, the 
4575  * reflection objects will contains the correct table index. fixup_method() will fixup the
4576  * tokens for the method with ILGenerator @ilgen.
4577  */
4578 static void
4579 fixup_method (MonoReflectionILGen *ilgen, gpointer value, MonoDynamicImage *assembly)
4580 {
4581         guint32 code_idx = GPOINTER_TO_UINT (value);
4582         MonoReflectionILTokenInfo *iltoken;
4583         MonoReflectionFieldBuilder *field;
4584         MonoReflectionCtorBuilder *ctor;
4585         MonoReflectionMethodBuilder *method;
4586         MonoReflectionTypeBuilder *tb;
4587         MonoReflectionArrayMethod *am;
4588         guint32 i, idx = 0;
4589         unsigned char *target;
4590
4591         for (i = 0; i < ilgen->num_token_fixups; ++i) {
4592                 iltoken = (MonoReflectionILTokenInfo *)mono_array_addr_with_size (ilgen->token_fixups, sizeof (MonoReflectionILTokenInfo), i);
4593                 target = (guchar*)assembly->code.data + code_idx + iltoken->code_pos;
4594                 switch (target [3]) {
4595                 case MONO_TABLE_FIELD:
4596                         if (!strcmp (iltoken->member->vtable->klass->name, "FieldBuilder")) {
4597                                 field = (MonoReflectionFieldBuilder *)iltoken->member;
4598                                 idx = field->table_idx;
4599                         } else if (!strcmp (iltoken->member->vtable->klass->name, "MonoField")) {
4600                                 MonoClassField *f = ((MonoReflectionField*)iltoken->member)->field;
4601                                 idx = GPOINTER_TO_UINT (g_hash_table_lookup (assembly->field_to_table_idx, f));
4602                         } else {
4603                                 g_assert_not_reached ();
4604                         }
4605                         break;
4606                 case MONO_TABLE_METHOD:
4607                         if (!strcmp (iltoken->member->vtable->klass->name, "MethodBuilder")) {
4608                                 method = (MonoReflectionMethodBuilder *)iltoken->member;
4609                                 idx = method->table_idx;
4610                         } else if (!strcmp (iltoken->member->vtable->klass->name, "ConstructorBuilder")) {
4611                                 ctor = (MonoReflectionCtorBuilder *)iltoken->member;
4612                                 idx = ctor->table_idx;
4613                         } else if (!strcmp (iltoken->member->vtable->klass->name, "MonoMethod") || 
4614                                            !strcmp (iltoken->member->vtable->klass->name, "MonoCMethod")) {
4615                                 MonoMethod *m = ((MonoReflectionMethod*)iltoken->member)->method;
4616                                 idx = GPOINTER_TO_UINT (g_hash_table_lookup (assembly->method_to_table_idx, m));
4617                         } else {
4618                                 g_assert_not_reached ();
4619                         }
4620                         break;
4621                 case MONO_TABLE_TYPEDEF:
4622                         if (strcmp (iltoken->member->vtable->klass->name, "TypeBuilder"))
4623                                 g_assert_not_reached ();
4624                         tb = (MonoReflectionTypeBuilder *)iltoken->member;
4625                         idx = tb->table_idx;
4626                         break;
4627                 case MONO_TABLE_MEMBERREF:
4628                         if (!strcmp (iltoken->member->vtable->klass->name, "MonoArrayMethod")) {
4629                                 am = (MonoReflectionArrayMethod*)iltoken->member;
4630                                 idx = am->table_idx;
4631                         } else if (!strcmp (iltoken->member->vtable->klass->name, "MonoMethod") ||
4632                                    !strcmp (iltoken->member->vtable->klass->name, "MonoCMethod") ||
4633                                    !strcmp (iltoken->member->vtable->klass->name, "MonoGenericMethod") ||
4634                                    !strcmp (iltoken->member->vtable->klass->name, "MonoGenericCMethod")) {
4635                                 MonoMethod *m = ((MonoReflectionMethod*)iltoken->member)->method;
4636                                 g_assert (m->klass->generic_class || m->klass->generic_container);
4637                                 continue;
4638                         } else if (!strcmp (iltoken->member->vtable->klass->name, "FieldBuilder")) {
4639                                 continue;
4640                         } else if (!strcmp (iltoken->member->vtable->klass->name, "MonoField")) {
4641                                 MonoClassField *f = ((MonoReflectionField*)iltoken->member)->field;
4642                                 g_assert (is_field_on_inst (f));
4643                                 continue;
4644                         } else if (!strcmp (iltoken->member->vtable->klass->name, "MethodBuilder") ||
4645                                         !strcmp (iltoken->member->vtable->klass->name, "ConstructorBuilder")) {
4646                                 continue;
4647                         } else if (!strcmp (iltoken->member->vtable->klass->name, "FieldOnTypeBuilderInst")) {
4648                                 continue;
4649                         } else if (!strcmp (iltoken->member->vtable->klass->name, "MethodOnTypeBuilderInst")) {
4650                                 continue;
4651                         } else if (!strcmp (iltoken->member->vtable->klass->name, "ConstructorOnTypeBuilderInst")) {
4652                                 continue;
4653                         } else {
4654                                 g_assert_not_reached ();
4655                         }
4656                         break;
4657                 case MONO_TABLE_METHODSPEC:
4658                         if (!strcmp (iltoken->member->vtable->klass->name, "MonoGenericMethod")) {
4659                                 MonoMethod *m = ((MonoReflectionMethod*)iltoken->member)->method;
4660                                 g_assert (mono_method_signature (m)->generic_param_count);
4661                                 continue;
4662                         } else if (!strcmp (iltoken->member->vtable->klass->name, "MethodBuilder")) {
4663                                 continue;
4664                         } else if (!strcmp (iltoken->member->vtable->klass->name, "MethodOnTypeBuilderInst")) {
4665                                 continue;
4666                         } else {
4667                                 g_assert_not_reached ();
4668                         }
4669                         break;
4670                 default:
4671                         g_error ("got unexpected table 0x%02x in fixup", target [3]);
4672                 }
4673                 target [0] = idx & 0xff;
4674                 target [1] = (idx >> 8) & 0xff;
4675                 target [2] = (idx >> 16) & 0xff;
4676         }
4677 }
4678
4679 /*
4680  * fixup_cattrs:
4681  *
4682  *   The CUSTOM_ATTRIBUTE table might contain METHODDEF tokens whose final
4683  * value is not known when the table is emitted.
4684  */
4685 static void
4686 fixup_cattrs (MonoDynamicImage *assembly)
4687 {
4688         MonoDynamicTable *table;
4689         guint32 *values;
4690         guint32 type, i, idx, token;
4691         MonoObject *ctor;
4692
4693         table = &assembly->tables [MONO_TABLE_CUSTOMATTRIBUTE];
4694
4695         for (i = 0; i < table->rows; ++i) {
4696                 values = table->values + ((i + 1) * MONO_CUSTOM_ATTR_SIZE);
4697
4698                 type = values [MONO_CUSTOM_ATTR_TYPE];
4699                 if ((type & MONO_CUSTOM_ATTR_TYPE_MASK) == MONO_CUSTOM_ATTR_TYPE_METHODDEF) {
4700                         idx = type >> MONO_CUSTOM_ATTR_TYPE_BITS;
4701                         token = mono_metadata_make_token (MONO_TABLE_METHOD, idx);
4702                         ctor = (MonoObject *)mono_g_hash_table_lookup (assembly->remapped_tokens, GUINT_TO_POINTER (token));
4703                         g_assert (ctor);
4704
4705                         if (!strcmp (ctor->vtable->klass->name, "MonoCMethod")) {
4706                                 MonoMethod *m = ((MonoReflectionMethod*)ctor)->method;
4707                                 idx = GPOINTER_TO_UINT (g_hash_table_lookup (assembly->method_to_table_idx, m));
4708                                 values [MONO_CUSTOM_ATTR_TYPE] = (idx << MONO_CUSTOM_ATTR_TYPE_BITS) | MONO_CUSTOM_ATTR_TYPE_METHODDEF;
4709                         } else if (!strcmp (ctor->vtable->klass->name, "ConstructorBuilder")) {
4710                                 MonoMethod *m = ((MonoReflectionCtorBuilder*)ctor)->mhandle;
4711                                 idx = GPOINTER_TO_UINT (g_hash_table_lookup (assembly->method_to_table_idx, m));
4712                                 values [MONO_CUSTOM_ATTR_TYPE] = (idx << MONO_CUSTOM_ATTR_TYPE_BITS) | MONO_CUSTOM_ATTR_TYPE_METHODDEF;
4713                         }
4714                 }
4715         }
4716 }
4717
4718 static void
4719 assembly_add_resource_manifest (MonoReflectionModuleBuilder *mb, MonoDynamicImage *assembly, MonoReflectionResource *rsrc, guint32 implementation)
4720 {
4721         MonoDynamicTable *table;
4722         guint32 *values;
4723
4724         table = &assembly->tables [MONO_TABLE_MANIFESTRESOURCE];
4725         table->rows++;
4726         alloc_table (table, table->rows);
4727         values = table->values + table->next_idx * MONO_MANIFEST_SIZE;
4728         values [MONO_MANIFEST_OFFSET] = rsrc->offset;
4729         values [MONO_MANIFEST_FLAGS] = rsrc->attrs;
4730         values [MONO_MANIFEST_NAME] = string_heap_insert_mstring (&assembly->sheap, rsrc->name);
4731         values [MONO_MANIFEST_IMPLEMENTATION] = implementation;
4732         table->next_idx++;
4733 }
4734
4735 static void
4736 assembly_add_resource (MonoReflectionModuleBuilder *mb, MonoDynamicImage *assembly, MonoReflectionResource *rsrc)
4737 {
4738         MonoDynamicTable *table;
4739         guint32 *values;
4740         char blob_size [6];
4741         guchar hash [20];
4742         char *b = blob_size;
4743         char *name, *sname;
4744         guint32 idx, offset;
4745
4746         if (rsrc->filename) {
4747                 name = mono_string_to_utf8 (rsrc->filename);
4748                 sname = g_path_get_basename (name);
4749         
4750                 table = &assembly->tables [MONO_TABLE_FILE];
4751                 table->rows++;
4752                 alloc_table (table, table->rows);
4753                 values = table->values + table->next_idx * MONO_FILE_SIZE;
4754                 values [MONO_FILE_FLAGS] = FILE_CONTAINS_NO_METADATA;
4755                 values [MONO_FILE_NAME] = string_heap_insert (&assembly->sheap, sname);
4756                 g_free (sname);
4757
4758                 mono_sha1_get_digest_from_file (name, hash);
4759                 mono_metadata_encode_value (20, b, &b);
4760                 values [MONO_FILE_HASH_VALUE] = mono_image_add_stream_data (&assembly->blob, blob_size, b-blob_size);
4761                 mono_image_add_stream_data (&assembly->blob, (char*)hash, 20);
4762                 g_free (name);
4763                 idx = table->next_idx++;
4764                 rsrc->offset = 0;
4765                 idx = MONO_IMPLEMENTATION_FILE | (idx << MONO_IMPLEMENTATION_BITS);
4766         } else {
4767                 char sizebuf [4];
4768                 char *data;
4769                 guint len;
4770                 if (rsrc->data) {
4771                         data = mono_array_addr (rsrc->data, char, 0);
4772                         len = mono_array_length (rsrc->data);
4773                 } else {
4774                         data = NULL;
4775                         len = 0;
4776                 }
4777                 offset = len;
4778                 sizebuf [0] = offset; sizebuf [1] = offset >> 8;
4779                 sizebuf [2] = offset >> 16; sizebuf [3] = offset >> 24;
4780                 rsrc->offset = mono_image_add_stream_data (&assembly->resources, sizebuf, 4);
4781                 mono_image_add_stream_data (&assembly->resources, data, len);
4782
4783                 if (!mb->is_main)
4784                         /* 
4785                          * The entry should be emitted into the MANIFESTRESOURCE table of 
4786                          * the main module, but that needs to reference the FILE table
4787                          * which isn't emitted yet.
4788                          */
4789                         return;
4790                 else
4791                         idx = 0;
4792         }
4793
4794         assembly_add_resource_manifest (mb, assembly, rsrc, idx);
4795 }
4796
4797 static void
4798 set_version_from_string (MonoString *version, guint32 *values)
4799 {
4800         gchar *ver, *p, *str;
4801         guint32 i;
4802         
4803         values [MONO_ASSEMBLY_MAJOR_VERSION] = 0;
4804         values [MONO_ASSEMBLY_MINOR_VERSION] = 0;
4805         values [MONO_ASSEMBLY_REV_NUMBER] = 0;
4806         values [MONO_ASSEMBLY_BUILD_NUMBER] = 0;
4807         if (!version)
4808                 return;
4809         ver = str = mono_string_to_utf8 (version);
4810         for (i = 0; i < 4; ++i) {
4811                 values [MONO_ASSEMBLY_MAJOR_VERSION + i] = strtol (ver, &p, 10);
4812                 switch (*p) {
4813                 case '.':
4814                         p++;
4815                         break;
4816                 case '*':
4817                         /* handle Revision and Build */
4818                         p++;
4819                         break;
4820                 }
4821                 ver = p;
4822         }
4823         g_free (str);
4824 }
4825
4826 static guint32
4827 load_public_key (MonoArray *pkey, MonoDynamicImage *assembly) {
4828         gsize len;
4829         guint32 token = 0;
4830         char blob_size [6];
4831         char *b = blob_size;
4832
4833         if (!pkey)
4834                 return token;
4835
4836         len = mono_array_length (pkey);
4837         mono_metadata_encode_value (len, b, &b);
4838         token = mono_image_add_stream_data (&assembly->blob, blob_size, b - blob_size);
4839         mono_image_add_stream_data (&assembly->blob, mono_array_addr (pkey, char, 0), len);
4840
4841         assembly->public_key = (guint8 *)g_malloc (len);
4842         memcpy (assembly->public_key, mono_array_addr (pkey, char, 0), len);
4843         assembly->public_key_len = len;
4844
4845         /* Special case: check for ECMA key (16 bytes) */
4846         if ((len == MONO_ECMA_KEY_LENGTH) && mono_is_ecma_key (mono_array_addr (pkey, char, 0), len)) {
4847                 /* In this case we must reserve 128 bytes (1024 bits) for the signature */
4848                 assembly->strong_name_size = MONO_DEFAULT_PUBLIC_KEY_LENGTH;
4849         } else if (len >= MONO_PUBLIC_KEY_HEADER_LENGTH + MONO_MINIMUM_PUBLIC_KEY_LENGTH) {
4850                 /* minimum key size (in 2.0) is 384 bits */
4851                 assembly->strong_name_size = len - MONO_PUBLIC_KEY_HEADER_LENGTH;
4852         } else {
4853                 /* FIXME - verifier */
4854                 g_warning ("Invalid public key length: %d bits (total: %d)", (int)MONO_PUBLIC_KEY_BIT_SIZE (len), (int)len);
4855                 assembly->strong_name_size = MONO_DEFAULT_PUBLIC_KEY_LENGTH; /* to be safe */
4856         }
4857         assembly->strong_name = (char *)g_malloc0 (assembly->strong_name_size);
4858
4859         return token;
4860 }
4861
4862 static void
4863 mono_image_emit_manifest (MonoReflectionModuleBuilder *moduleb)
4864 {
4865         MonoDynamicTable *table;
4866         MonoDynamicImage *assembly;
4867         MonoReflectionAssemblyBuilder *assemblyb;
4868         MonoDomain *domain;
4869         guint32 *values;
4870         int i;
4871         guint32 module_index;
4872
4873         assemblyb = moduleb->assemblyb;
4874         assembly = moduleb->dynamic_image;
4875         domain = mono_object_domain (assemblyb);
4876
4877         /* Emit ASSEMBLY table */
4878         table = &assembly->tables [MONO_TABLE_ASSEMBLY];
4879         alloc_table (table, 1);
4880         values = table->values + MONO_ASSEMBLY_SIZE;
4881         values [MONO_ASSEMBLY_HASH_ALG] = assemblyb->algid? assemblyb->algid: ASSEMBLY_HASH_SHA1;
4882         values [MONO_ASSEMBLY_NAME] = string_heap_insert_mstring (&assembly->sheap, assemblyb->name);
4883         if (assemblyb->culture) {
4884                 values [MONO_ASSEMBLY_CULTURE] = string_heap_insert_mstring (&assembly->sheap, assemblyb->culture);
4885         } else {
4886                 values [MONO_ASSEMBLY_CULTURE] = string_heap_insert (&assembly->sheap, "");
4887         }
4888         values [MONO_ASSEMBLY_PUBLIC_KEY] = load_public_key (assemblyb->public_key, assembly);
4889         values [MONO_ASSEMBLY_FLAGS] = assemblyb->flags;
4890         set_version_from_string (assemblyb->version, values);
4891
4892         /* Emit FILE + EXPORTED_TYPE table */
4893         module_index = 0;
4894         for (i = 0; i < mono_array_length (assemblyb->modules); ++i) {
4895                 int j;
4896                 MonoReflectionModuleBuilder *file_module = 
4897                         mono_array_get (assemblyb->modules, MonoReflectionModuleBuilder*, i);
4898                 if (file_module != moduleb) {
4899                         mono_image_fill_file_table (domain, (MonoReflectionModule*)file_module, assembly);
4900                         module_index ++;
4901                         if (file_module->types) {
4902                                 for (j = 0; j < file_module->num_types; ++j) {
4903                                         MonoReflectionTypeBuilder *tb = mono_array_get (file_module->types, MonoReflectionTypeBuilder*, j);
4904                                         mono_image_fill_export_table (domain, tb, module_index, 0, assembly);
4905                                 }
4906                         }
4907                 }
4908         }
4909         if (assemblyb->loaded_modules) {
4910                 for (i = 0; i < mono_array_length (assemblyb->loaded_modules); ++i) {
4911                         MonoReflectionModule *file_module = 
4912                                 mono_array_get (assemblyb->loaded_modules, MonoReflectionModule*, i);
4913                         mono_image_fill_file_table (domain, file_module, assembly);
4914                         module_index ++;
4915                         mono_image_fill_export_table_from_module (domain, file_module, module_index, assembly);
4916                 }
4917         }
4918         if (assemblyb->type_forwarders)
4919                 mono_image_fill_export_table_from_type_forwarders (assemblyb, assembly);
4920
4921         /* Emit MANIFESTRESOURCE table */
4922         module_index = 0;
4923         for (i = 0; i < mono_array_length (assemblyb->modules); ++i) {
4924                 int j;
4925                 MonoReflectionModuleBuilder *file_module = 
4926                         mono_array_get (assemblyb->modules, MonoReflectionModuleBuilder*, i);
4927                 /* The table for the main module is emitted later */
4928                 if (file_module != moduleb) {
4929                         module_index ++;
4930                         if (file_module->resources) {
4931                                 int len = mono_array_length (file_module->resources);
4932                                 for (j = 0; j < len; ++j) {
4933                                         MonoReflectionResource* res = (MonoReflectionResource*)mono_array_addr (file_module->resources, MonoReflectionResource, j);
4934                                         assembly_add_resource_manifest (file_module, assembly, res, MONO_IMPLEMENTATION_FILE | (module_index << MONO_IMPLEMENTATION_BITS));
4935                                 }
4936                         }
4937                 }
4938         }               
4939 }
4940
4941 #ifndef DISABLE_REFLECTION_EMIT_SAVE
4942
4943 /*
4944  * mono_image_build_metadata() will fill the info in all the needed metadata tables
4945  * for the modulebuilder @moduleb.
4946  * At the end of the process, method and field tokens are fixed up and the 
4947  * on-disk compressed metadata representation is created.
4948  * Return TRUE on success, or FALSE on failure and sets @error
4949  */
4950 gboolean
4951 mono_image_build_metadata (MonoReflectionModuleBuilder *moduleb, MonoError *error)
4952 {
4953         MonoDynamicTable *table;
4954         MonoDynamicImage *assembly;
4955         MonoReflectionAssemblyBuilder *assemblyb;
4956         MonoDomain *domain;
4957         MonoPtrArray types;
4958         guint32 *values;
4959         int i, j;
4960
4961         mono_error_init (error);
4962
4963         assemblyb = moduleb->assemblyb;
4964         assembly = moduleb->dynamic_image;
4965         domain = mono_object_domain (assemblyb);
4966
4967         if (assembly->text_rva)
4968                 return TRUE;
4969
4970         assembly->text_rva = START_TEXT_RVA;
4971
4972         if (moduleb->is_main) {
4973                 mono_image_emit_manifest (moduleb);
4974         }
4975
4976         table = &assembly->tables [MONO_TABLE_TYPEDEF];
4977         table->rows = 1; /* .<Module> */
4978         table->next_idx++;
4979         alloc_table (table, table->rows);
4980         /*
4981          * Set the first entry.
4982          */
4983         values = table->values + table->columns;
4984         values [MONO_TYPEDEF_FLAGS] = 0;
4985         values [MONO_TYPEDEF_NAME] = string_heap_insert (&assembly->sheap, "<Module>") ;
4986         values [MONO_TYPEDEF_NAMESPACE] = string_heap_insert (&assembly->sheap, "") ;
4987         values [MONO_TYPEDEF_EXTENDS] = 0;
4988         values [MONO_TYPEDEF_FIELD_LIST] = 1;
4989         values [MONO_TYPEDEF_METHOD_LIST] = 1;
4990
4991         /* 
4992          * handle global methods 
4993          * FIXME: test what to do when global methods are defined in multiple modules.
4994          */
4995         if (moduleb->global_methods) {
4996                 table = &assembly->tables [MONO_TABLE_METHOD];
4997                 table->rows += mono_array_length (moduleb->global_methods);
4998                 alloc_table (table, table->rows);
4999                 for (i = 0; i < mono_array_length (moduleb->global_methods); ++i) {
5000                         if (!mono_image_get_method_info (
5001                                     mono_array_get (moduleb->global_methods, MonoReflectionMethodBuilder*, i), assembly, error))
5002                                 goto leave;
5003                 }
5004         }
5005         if (moduleb->global_fields) {
5006                 table = &assembly->tables [MONO_TABLE_FIELD];
5007                 table->rows += mono_array_length (moduleb->global_fields);
5008                 alloc_table (table, table->rows);
5009                 for (i = 0; i < mono_array_length (moduleb->global_fields); ++i)
5010                         mono_image_get_field_info (
5011                                 mono_array_get (moduleb->global_fields, MonoReflectionFieldBuilder*, i), assembly);
5012         }
5013
5014         table = &assembly->tables [MONO_TABLE_MODULE];
5015         alloc_table (table, 1);
5016         mono_image_fill_module_table (domain, moduleb, assembly);
5017
5018         /* Collect all types into a list sorted by their table_idx */
5019         mono_ptr_array_init (types, moduleb->num_types, MONO_ROOT_SOURCE_REFLECTION, "dynamic module types list");
5020
5021         if (moduleb->types)
5022                 for (i = 0; i < moduleb->num_types; ++i) {
5023                         MonoReflectionTypeBuilder *type = mono_array_get (moduleb->types, MonoReflectionTypeBuilder*, i);
5024                         collect_types (&types, type);
5025                 }
5026
5027         mono_ptr_array_sort (types, (int (*)(const void *, const void *))compare_types_by_table_idx);
5028         table = &assembly->tables [MONO_TABLE_TYPEDEF];
5029         table->rows += mono_ptr_array_size (types);
5030         alloc_table (table, table->rows);
5031
5032         /*
5033          * Emit type names + namespaces at one place inside the string heap,
5034          * so load_class_names () needs to touch fewer pages.
5035          */
5036         for (i = 0; i < mono_ptr_array_size (types); ++i) {
5037                 MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder *)mono_ptr_array_get (types, i);
5038                 string_heap_insert_mstring (&assembly->sheap, tb->nspace);
5039         }
5040         for (i = 0; i < mono_ptr_array_size (types); ++i) {
5041                 MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder *)mono_ptr_array_get (types, i);
5042                 string_heap_insert_mstring (&assembly->sheap, tb->name);
5043         }
5044
5045         for (i = 0; i < mono_ptr_array_size (types); ++i) {
5046                 MonoReflectionTypeBuilder *type = (MonoReflectionTypeBuilder *)mono_ptr_array_get (types, i);
5047                 if (!mono_image_get_type_info (domain, type, assembly, error))
5048                         goto leave_types;
5049         }
5050
5051         /* 
5052          * table->rows is already set above and in mono_image_fill_module_table.
5053          */
5054         /* add all the custom attributes at the end, once all the indexes are stable */
5055         if (!mono_image_add_cattrs (assembly, 1, MONO_CUSTOM_ATTR_ASSEMBLY, assemblyb->cattrs, error))
5056                 goto leave_types;
5057
5058         /* CAS assembly permissions */
5059         if (assemblyb->permissions_minimum)
5060                 mono_image_add_decl_security (assembly, mono_metadata_make_token (MONO_TABLE_ASSEMBLY, 1), assemblyb->permissions_minimum);
5061         if (assemblyb->permissions_optional)
5062                 mono_image_add_decl_security (assembly, mono_metadata_make_token (MONO_TABLE_ASSEMBLY, 1), assemblyb->permissions_optional);
5063         if (assemblyb->permissions_refused)
5064                 mono_image_add_decl_security (assembly, mono_metadata_make_token (MONO_TABLE_ASSEMBLY, 1), assemblyb->permissions_refused);
5065
5066         if (!module_add_cattrs (assembly, moduleb, error))
5067                 goto leave_types;
5068
5069         /* fixup tokens */
5070         mono_g_hash_table_foreach (assembly->token_fixups, (GHFunc)fixup_method, assembly);
5071
5072         /* Create the MethodImpl table.  We do this after emitting all methods so we already know
5073          * the final tokens and don't need another fixup pass. */
5074
5075         if (moduleb->global_methods) {
5076                 for (i = 0; i < mono_array_length (moduleb->global_methods); ++i) {
5077                         MonoReflectionMethodBuilder *mb = mono_array_get (
5078                                 moduleb->global_methods, MonoReflectionMethodBuilder*, i);
5079                         if (!mono_image_add_methodimpl (assembly, mb, error))
5080                                 goto leave_types;
5081                 }
5082         }
5083
5084         for (i = 0; i < mono_ptr_array_size (types); ++i) {
5085                 MonoReflectionTypeBuilder *type = (MonoReflectionTypeBuilder *)mono_ptr_array_get (types, i);
5086                 if (type->methods) {
5087                         for (j = 0; j < type->num_methods; ++j) {
5088                                 MonoReflectionMethodBuilder *mb = mono_array_get (
5089                                         type->methods, MonoReflectionMethodBuilder*, j);
5090
5091                                 if (!mono_image_add_methodimpl (assembly, mb, error))
5092                                         goto leave_types;
5093                         }
5094                 }
5095         }
5096
5097         fixup_cattrs (assembly);
5098
5099 leave_types:
5100         mono_ptr_array_destroy (types);
5101 leave:
5102
5103         return mono_error_ok (error);
5104 }
5105
5106 #else /* DISABLE_REFLECTION_EMIT_SAVE */
5107
5108 gboolean
5109 mono_image_build_metadata (MonoReflectionModuleBuilder *moduleb, MonoError *error)
5110 {
5111         g_error ("This mono runtime was configured with --enable-minimal=reflection_emit_save, so saving of dynamic assemblies is not supported.");
5112 }
5113
5114 #endif /* DISABLE_REFLECTION_EMIT_SAVE */
5115
5116
5117 typedef struct {
5118         guint32 import_lookup_table;
5119         guint32 timestamp;
5120         guint32 forwarder;
5121         guint32 name_rva;
5122         guint32 import_address_table_rva;
5123 } MonoIDT;
5124
5125 typedef struct {
5126         guint32 name_rva;
5127         guint32 flags;
5128 } MonoILT;
5129
5130 #ifndef DISABLE_REFLECTION_EMIT
5131
5132 /*
5133  * mono_image_insert_string:
5134  * @module: module builder object
5135  * @str: a string
5136  *
5137  * Insert @str into the user string stream of @module.
5138  */
5139 guint32
5140 mono_image_insert_string (MonoReflectionModuleBuilder *module, MonoString *str)
5141 {
5142         MonoDynamicImage *assembly;
5143         guint32 idx;
5144         char buf [16];
5145         char *b = buf;
5146         
5147         if (!module->dynamic_image)
5148                 mono_image_module_basic_init (module);
5149
5150         assembly = module->dynamic_image;
5151         
5152         if (assembly->save) {
5153                 mono_metadata_encode_value (1 | (str->length * 2), b, &b);
5154                 idx = mono_image_add_stream_data (&assembly->us, buf, b-buf);
5155 #if G_BYTE_ORDER != G_LITTLE_ENDIAN
5156         {
5157                 char *swapped = g_malloc (2 * mono_string_length (str));
5158                 const char *p = (const char*)mono_string_chars (str);
5159
5160                 swap_with_size (swapped, p, 2, mono_string_length (str));
5161                 mono_image_add_stream_data (&assembly->us, swapped, str->length * 2);
5162                 g_free (swapped);
5163         }
5164 #else
5165                 mono_image_add_stream_data (&assembly->us, (const char*)mono_string_chars (str), str->length * 2);
5166 #endif
5167                 mono_image_add_stream_data (&assembly->us, "", 1);
5168         } else {
5169                 idx = assembly->us.index ++;
5170         }
5171
5172         register_dyn_token (assembly, MONO_TOKEN_STRING | idx, (MonoObject*)str);
5173
5174         return MONO_TOKEN_STRING | idx;
5175 }
5176
5177 guint32
5178 mono_image_create_method_token (MonoDynamicImage *assembly, MonoObject *obj, MonoArray *opt_param_types, MonoError *error)
5179 {
5180         MonoClass *klass;
5181         guint32 token = 0;
5182         MonoMethodSignature *sig;
5183
5184         mono_error_init (error);
5185
5186         klass = obj->vtable->klass;
5187         if (strcmp (klass->name, "MonoMethod") == 0 || strcmp (klass->name, "MonoCMethod") == 0) {
5188                 MonoMethod *method = ((MonoReflectionMethod *)obj)->method;
5189                 MonoMethodSignature *old;
5190                 guint32 sig_token, parent;
5191                 int nargs, i;
5192
5193                 g_assert (opt_param_types && (mono_method_signature (method)->sentinelpos >= 0));
5194
5195                 nargs = mono_array_length (opt_param_types);
5196                 old = mono_method_signature (method);
5197                 sig = mono_metadata_signature_alloc ( &assembly->image, old->param_count + nargs);
5198
5199                 sig->hasthis = old->hasthis;
5200                 sig->explicit_this = old->explicit_this;
5201                 sig->call_convention = old->call_convention;
5202                 sig->generic_param_count = old->generic_param_count;
5203                 sig->param_count = old->param_count + nargs;
5204                 sig->sentinelpos = old->param_count;
5205                 sig->ret = old->ret;
5206
5207                 for (i = 0; i < old->param_count; i++)
5208                         sig->params [i] = old->params [i];
5209
5210                 for (i = 0; i < nargs; i++) {
5211                         MonoReflectionType *rt = mono_array_get (opt_param_types, MonoReflectionType *, i);
5212                         sig->params [old->param_count + i] = mono_reflection_type_get_handle (rt);
5213                 }
5214
5215                 parent = mono_image_typedef_or_ref (assembly, &method->klass->byval_arg);
5216                 g_assert ((parent & MONO_TYPEDEFORREF_MASK) == MONO_MEMBERREF_PARENT_TYPEREF);
5217                 parent >>= MONO_TYPEDEFORREF_BITS;
5218
5219                 parent <<= MONO_MEMBERREF_PARENT_BITS;
5220                 parent |= MONO_MEMBERREF_PARENT_TYPEREF;
5221
5222                 sig_token = method_encode_signature (assembly, sig);
5223                 token = mono_image_get_varargs_method_token (assembly, parent, method->name, sig_token);
5224         } else if (strcmp (klass->name, "MethodBuilder") == 0) {
5225                 MonoReflectionMethodBuilder *mb = (MonoReflectionMethodBuilder *)obj;
5226                 ReflectionMethodBuilder rmb;
5227                 guint32 parent, sig_token;
5228                 int nopt_args, nparams, ngparams, i;
5229
5230                 if (!reflection_methodbuilder_from_method_builder (&rmb, mb, error))
5231                         goto fail;
5232                 
5233                 rmb.opt_types = opt_param_types;
5234                 nopt_args = mono_array_length (opt_param_types);
5235
5236                 nparams = rmb.parameters ? mono_array_length (rmb.parameters): 0;
5237                 ngparams = rmb.generic_params ? mono_array_length (rmb.generic_params): 0;
5238                 sig = mono_metadata_signature_alloc (&assembly->image, nparams + nopt_args);
5239
5240                 sig->hasthis = !(rmb.attrs & METHOD_ATTRIBUTE_STATIC);
5241                 sig->explicit_this = (rmb.call_conv & 0x40) == 0x40;
5242                 sig->call_convention = rmb.call_conv;
5243                 sig->generic_param_count = ngparams;
5244                 sig->param_count = nparams + nopt_args;
5245                 sig->sentinelpos = nparams;
5246                 sig->ret = mono_reflection_type_get_handle (rmb.rtype);
5247
5248                 for (i = 0; i < nparams; i++) {
5249                         MonoReflectionType *rt = mono_array_get (rmb.parameters, MonoReflectionType *, i);
5250                         sig->params [i] = mono_reflection_type_get_handle (rt);
5251                 }
5252
5253                 for (i = 0; i < nopt_args; i++) {
5254                         MonoReflectionType *rt = mono_array_get (opt_param_types, MonoReflectionType *, i);
5255                         sig->params [nparams + i] = mono_reflection_type_get_handle (rt);
5256                 }
5257
5258                 sig_token = method_builder_encode_signature (assembly, &rmb);
5259
5260                 parent = mono_image_create_token (assembly, obj, TRUE, TRUE, error);
5261                 if (!mono_error_ok (error))
5262                         goto fail;
5263                 g_assert (mono_metadata_token_table (parent) == MONO_TABLE_METHOD);
5264
5265                 parent = mono_metadata_token_index (parent) << MONO_MEMBERREF_PARENT_BITS;
5266                 parent |= MONO_MEMBERREF_PARENT_METHODDEF;
5267
5268                 char *name = mono_string_to_utf8 (rmb.name);
5269                 token = mono_image_get_varargs_method_token (
5270                         assembly, parent, name, sig_token);
5271                 g_free (name);
5272         } else {
5273                 g_error ("requested method token for %s\n", klass->name);
5274         }
5275
5276         g_hash_table_insert (assembly->vararg_aux_hash, GUINT_TO_POINTER (token), sig);
5277         register_dyn_token (assembly, token, obj);
5278         return token;
5279 fail:
5280         g_assert (!mono_error_ok (error));
5281         return 0;
5282 }
5283
5284 /*
5285  * mono_image_create_token:
5286  * @assembly: a dynamic assembly
5287  * @obj:
5288  * @register_token: Whenever to register the token in the assembly->tokens hash. 
5289  *
5290  * Get a token to insert in the IL code stream for the given MemberInfo.
5291  * The metadata emission routines need to pass FALSE as REGISTER_TOKEN, since by that time, 
5292  * the table_idx-es were recomputed, so registering the token would overwrite an existing 
5293  * entry.
5294  */
5295 guint32
5296 mono_image_create_token (MonoDynamicImage *assembly, MonoObject *obj, 
5297                          gboolean create_open_instance, gboolean register_token,
5298                          MonoError *error)
5299 {
5300         MonoClass *klass;
5301         guint32 token = 0;
5302
5303         mono_error_init (error);
5304
5305         klass = obj->vtable->klass;
5306
5307         /* Check for user defined reflection objects */
5308         /* TypeDelegator is the only corlib type which doesn't look like a MonoReflectionType */
5309         if (klass->image != mono_defaults.corlib || (strcmp (klass->name, "TypeDelegator") == 0)) {
5310                 mono_error_set_generic_error (error, "System", "NotSupportedException", "User defined subclasses of System.Type are not yet supported");
5311                 return 0;
5312         }
5313
5314         if (strcmp (klass->name, "MethodBuilder") == 0) {
5315                 MonoReflectionMethodBuilder *mb = (MonoReflectionMethodBuilder *)obj;
5316                 MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder*)mb->type;
5317
5318                 if (tb->module->dynamic_image == assembly && !tb->generic_params && !mb->generic_params)
5319                         token = mb->table_idx | MONO_TOKEN_METHOD_DEF;
5320                 else {
5321                         token = mono_image_get_methodbuilder_token (assembly, mb, create_open_instance, error);
5322                         if (!mono_error_ok (error))
5323                                 return 0;
5324                 }
5325                 /*g_print ("got token 0x%08x for %s\n", token, mono_string_to_utf8 (mb->name));*/
5326         } else if (strcmp (klass->name, "ConstructorBuilder") == 0) {
5327                 MonoReflectionCtorBuilder *mb = (MonoReflectionCtorBuilder *)obj;
5328                 MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder*)mb->type;
5329
5330                 if (tb->module->dynamic_image == assembly && !tb->generic_params)
5331                         token = mb->table_idx | MONO_TOKEN_METHOD_DEF;
5332                 else {
5333                         token = mono_image_get_ctorbuilder_token (assembly, mb, error);
5334                         if (!mono_error_ok (error))
5335                                 return 0;
5336                 }
5337                 /*g_print ("got token 0x%08x for %s\n", token, mono_string_to_utf8 (mb->name));*/
5338         } else if (strcmp (klass->name, "FieldBuilder") == 0) {
5339                 MonoReflectionFieldBuilder *fb = (MonoReflectionFieldBuilder *)obj;
5340                 MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder *)fb->typeb;
5341                 if (tb->generic_params) {
5342                         token = mono_image_get_generic_field_token (assembly, fb);
5343                 } else {
5344                         if (tb->module->dynamic_image == assembly) {
5345                                 token = fb->table_idx | MONO_TOKEN_FIELD_DEF;
5346                         } else {
5347                                 token = mono_image_get_fieldref_token (assembly, (MonoObject*)fb, fb->handle);
5348                         }
5349                 }
5350         } else if (strcmp (klass->name, "TypeBuilder") == 0) {
5351                 MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder *)obj;
5352                 if (create_open_instance && tb->generic_params) {
5353                         MonoType *type;
5354                         init_type_builder_generics (obj);
5355                         type = mono_reflection_type_get_handle ((MonoReflectionType *)obj);
5356                         token = mono_image_typedef_or_ref_full (assembly, type, TRUE);
5357                         token = mono_metadata_token_from_dor (token);
5358                 } else if (tb->module->dynamic_image == assembly) {
5359                         token = tb->table_idx | MONO_TOKEN_TYPE_DEF;
5360                 } else {
5361                         MonoType *type;
5362                         type = mono_reflection_type_get_handle ((MonoReflectionType *)obj);
5363                         token = mono_metadata_token_from_dor (mono_image_typedef_or_ref (assembly, type));
5364                 }
5365         } else if (strcmp (klass->name, "MonoType") == 0) {
5366                 MonoType *type = mono_reflection_type_get_handle ((MonoReflectionType *)obj);
5367                 MonoClass *mc = mono_class_from_mono_type (type);
5368                 token = mono_metadata_token_from_dor (
5369                         mono_image_typedef_or_ref_full (assembly, type, mc->generic_container == NULL || create_open_instance));
5370         } else if (strcmp (klass->name, "GenericTypeParameterBuilder") == 0) {
5371                 MonoType *type = mono_reflection_type_get_handle ((MonoReflectionType *)obj);
5372                 token = mono_metadata_token_from_dor (
5373                         mono_image_typedef_or_ref (assembly, type));
5374         } else if (strcmp (klass->name, "MonoGenericClass") == 0) {
5375                 MonoType *type = mono_reflection_type_get_handle ((MonoReflectionType *)obj);
5376                 token = mono_metadata_token_from_dor (
5377                         mono_image_typedef_or_ref (assembly, type));
5378         } else if (strcmp (klass->name, "MonoCMethod") == 0 ||
5379                    strcmp (klass->name, "MonoMethod") == 0 ||
5380                    strcmp (klass->name, "MonoGenericMethod") == 0 ||
5381                    strcmp (klass->name, "MonoGenericCMethod") == 0) {
5382                 MonoReflectionMethod *m = (MonoReflectionMethod *)obj;
5383                 if (m->method->is_inflated) {
5384                         if (create_open_instance)
5385                                 token = mono_image_get_methodspec_token (assembly, m->method);
5386                         else
5387                                 token = mono_image_get_inflated_method_token (assembly, m->method);
5388                 } else if ((m->method->klass->image == &assembly->image) &&
5389                          !m->method->klass->generic_class) {
5390                         static guint32 method_table_idx = 0xffffff;
5391                         if (m->method->klass->wastypebuilder) {
5392                                 /* we use the same token as the one that was assigned
5393                                  * to the Methodbuilder.
5394                                  * FIXME: do the equivalent for Fields.
5395                                  */
5396                                 token = m->method->token;
5397                         } else {
5398                                 /*
5399                                  * Each token should have a unique index, but the indexes are
5400                                  * assigned by managed code, so we don't know about them. An
5401                                  * easy solution is to count backwards...
5402                                  */
5403                                 method_table_idx --;
5404                                 token = MONO_TOKEN_METHOD_DEF | method_table_idx;
5405                         }
5406                 } else {
5407                         token = mono_image_get_methodref_token (assembly, m->method, create_open_instance);
5408                 }
5409                 /*g_print ("got token 0x%08x for %s\n", token, m->method->name);*/
5410         } else if (strcmp (klass->name, "MonoField") == 0) {
5411                 MonoReflectionField *f = (MonoReflectionField *)obj;
5412                 if ((f->field->parent->image == &assembly->image) && !is_field_on_inst (f->field)) {
5413                         static guint32 field_table_idx = 0xffffff;
5414                         field_table_idx --;
5415                         token = MONO_TOKEN_FIELD_DEF | field_table_idx;
5416                 } else {
5417                         token = mono_image_get_fieldref_token (assembly, (MonoObject*)f, f->field);
5418                 }
5419                 /*g_print ("got token 0x%08x for %s\n", token, f->field->name);*/
5420         } else if (strcmp (klass->name, "MonoArrayMethod") == 0) {
5421                 MonoReflectionArrayMethod *m = (MonoReflectionArrayMethod *)obj;
5422                 token = mono_image_get_array_token (assembly, m);
5423         } else if (strcmp (klass->name, "SignatureHelper") == 0) {
5424                 MonoReflectionSigHelper *s = (MonoReflectionSigHelper*)obj;
5425                 token = MONO_TOKEN_SIGNATURE | mono_image_get_sighelper_token (assembly, s);
5426         } else if (strcmp (klass->name, "EnumBuilder") == 0) {
5427                 MonoType *type = mono_reflection_type_get_handle ((MonoReflectionType *)obj);
5428                 token = mono_metadata_token_from_dor (
5429                         mono_image_typedef_or_ref (assembly, type));
5430         } else if (strcmp (klass->name, "FieldOnTypeBuilderInst") == 0) {
5431                 MonoReflectionFieldOnTypeBuilderInst *f = (MonoReflectionFieldOnTypeBuilderInst*)obj;
5432                 token = mono_image_get_field_on_inst_token (assembly, f);
5433         } else if (strcmp (klass->name, "ConstructorOnTypeBuilderInst") == 0) {
5434                 MonoReflectionCtorOnTypeBuilderInst *c = (MonoReflectionCtorOnTypeBuilderInst*)obj;
5435                 token = mono_image_get_ctor_on_inst_token (assembly, c, create_open_instance, error);
5436                 if (!mono_error_ok (error))
5437                         return 0;
5438         } else if (strcmp (klass->name, "MethodOnTypeBuilderInst") == 0) {
5439                 MonoReflectionMethodOnTypeBuilderInst *m = (MonoReflectionMethodOnTypeBuilderInst*)obj;
5440                 token = mono_image_get_method_on_inst_token (assembly, m, create_open_instance, error);
5441                 if (!mono_error_ok (error))
5442                         return 0;
5443         } else if (is_sre_array (klass) || is_sre_byref (klass) || is_sre_pointer (klass)) {
5444                 MonoReflectionType *type = (MonoReflectionType *)obj;
5445                 token = mono_metadata_token_from_dor (
5446                                 mono_image_typedef_or_ref (assembly, mono_reflection_type_get_handle (type)));
5447         } else {
5448                 g_error ("requested token for %s\n", klass->name);
5449         }
5450
5451         if (register_token)
5452                 mono_image_register_token (assembly, token, obj);
5453
5454         return token;
5455 }
5456
5457 /*
5458  * mono_image_register_token:
5459  *
5460  *   Register the TOKEN->OBJ mapping in the mapping table in ASSEMBLY. This is required for
5461  * the Module.ResolveXXXToken () methods to work.
5462  */
5463 void
5464 mono_image_register_token (MonoDynamicImage *assembly, guint32 token, MonoObject *obj)
5465 {
5466         MonoObject *prev;
5467
5468         dynamic_image_lock (assembly);
5469         prev = (MonoObject *)mono_g_hash_table_lookup (assembly->tokens, GUINT_TO_POINTER (token));
5470         if (prev) {
5471                 /* There could be multiple MethodInfo objects with the same token */
5472                 //g_assert (prev == obj);
5473         } else {
5474                 mono_g_hash_table_insert (assembly->tokens, GUINT_TO_POINTER (token), obj);
5475         }
5476         dynamic_image_unlock (assembly);
5477 }
5478
5479 static MonoDynamicImage*
5480 create_dynamic_mono_image (MonoDynamicAssembly *assembly, char *assembly_name, char *module_name)
5481 {
5482         static const guchar entrycode [16] = {0xff, 0x25, 0};
5483         MonoDynamicImage *image;
5484         int i;
5485
5486         const char *version;
5487
5488         if (!strcmp (mono_get_runtime_info ()->framework_version, "2.1"))
5489                 version = "v2.0.50727"; /* HACK: SL 2 enforces the .net 2 metadata version */
5490         else
5491                 version = mono_get_runtime_info ()->runtime_version;
5492
5493 #if HAVE_BOEHM_GC
5494         /* The MonoGHashTable's need GC tracking */
5495         image = (MonoDynamicImage *)GC_MALLOC (sizeof (MonoDynamicImage));
5496 #else
5497         image = g_new0 (MonoDynamicImage, 1);
5498 #endif
5499
5500         mono_profiler_module_event (&image->image, MONO_PROFILE_START_LOAD);
5501         
5502         /*g_print ("created image %p\n", image);*/
5503         /* keep in sync with image.c */
5504         image->image.name = assembly_name;
5505         image->image.assembly_name = image->image.name; /* they may be different */
5506         image->image.module_name = module_name;
5507         image->image.version = g_strdup (version);
5508         image->image.md_version_major = 1;
5509         image->image.md_version_minor = 1;
5510         image->image.dynamic = TRUE;
5511
5512         image->image.references = g_new0 (MonoAssembly*, 1);
5513         image->image.references [0] = NULL;
5514
5515         mono_image_init (&image->image);
5516
5517         image->token_fixups = mono_g_hash_table_new_type ((GHashFunc)mono_object_hash, NULL, MONO_HASH_KEY_GC, MONO_ROOT_SOURCE_REFLECTION, "dynamic module token fixups table");
5518         image->method_to_table_idx = g_hash_table_new (NULL, NULL);
5519         image->field_to_table_idx = g_hash_table_new (NULL, NULL);
5520         image->method_aux_hash = g_hash_table_new (NULL, NULL);
5521         image->vararg_aux_hash = g_hash_table_new (NULL, NULL);
5522         image->handleref = g_hash_table_new (NULL, NULL);
5523         image->handleref_managed = mono_g_hash_table_new_type ((GHashFunc)mono_object_hash, NULL, MONO_HASH_KEY_GC, MONO_ROOT_SOURCE_REFLECTION, "dynamic module reference-to-token table");
5524         image->tokens = mono_g_hash_table_new_type (NULL, NULL, MONO_HASH_VALUE_GC, MONO_ROOT_SOURCE_REFLECTION, "dynamic module tokens table");
5525         image->generic_def_objects = mono_g_hash_table_new_type (NULL, NULL, MONO_HASH_VALUE_GC, MONO_ROOT_SOURCE_REFLECTION, "dynamic module generic definitions table");
5526         image->methodspec = mono_g_hash_table_new_type ((GHashFunc)mono_object_hash, NULL, MONO_HASH_KEY_GC, MONO_ROOT_SOURCE_REFLECTION, "dynamic module method specifications table");
5527         image->typespec = g_hash_table_new ((GHashFunc)mono_metadata_type_hash, (GCompareFunc)mono_metadata_type_equal);
5528         image->typeref = g_hash_table_new ((GHashFunc)mono_metadata_type_hash, (GCompareFunc)mono_metadata_type_equal);
5529         image->blob_cache = g_hash_table_new ((GHashFunc)mono_blob_entry_hash, (GCompareFunc)mono_blob_entry_equal);
5530         image->gen_params = g_ptr_array_new ();
5531         image->remapped_tokens = mono_g_hash_table_new_type (NULL, NULL, MONO_HASH_VALUE_GC, MONO_ROOT_SOURCE_REFLECTION, "dynamic module remapped tokens table");
5532
5533         /*g_print ("string heap create for image %p (%s)\n", image, module_name);*/
5534         string_heap_init (&image->sheap);
5535         mono_image_add_stream_data (&image->us, "", 1);
5536         add_to_blob_cached (image, (char*) "", 1, NULL, 0);
5537         /* import tables... */
5538         mono_image_add_stream_data (&image->code, (char*)entrycode, sizeof (entrycode));
5539         image->iat_offset = mono_image_add_stream_zero (&image->code, 8); /* two IAT entries */
5540         image->idt_offset = mono_image_add_stream_zero (&image->code, 2 * sizeof (MonoIDT)); /* two IDT entries */
5541         image->imp_names_offset = mono_image_add_stream_zero (&image->code, 2); /* flags for name entry */
5542         mono_image_add_stream_data (&image->code, "_CorExeMain", 12);
5543         mono_image_add_stream_data (&image->code, "mscoree.dll", 12);
5544         image->ilt_offset = mono_image_add_stream_zero (&image->code, 8); /* two ILT entries */
5545         stream_data_align (&image->code);
5546
5547         image->cli_header_offset = mono_image_add_stream_zero (&image->code, sizeof (MonoCLIHeader));
5548
5549         for (i=0; i < MONO_TABLE_NUM; ++i) {
5550                 image->tables [i].next_idx = 1;
5551                 image->tables [i].columns = table_sizes [i];
5552         }
5553
5554         image->image.assembly = (MonoAssembly*)assembly;
5555         image->run = assembly->run;
5556         image->save = assembly->save;
5557         image->pe_kind = 0x1; /* ILOnly */
5558         image->machine = 0x14c; /* I386 */
5559         
5560         mono_profiler_module_loaded (&image->image, MONO_PROFILE_OK);
5561
5562         dynamic_images_lock ();
5563
5564         if (!dynamic_images)
5565                 dynamic_images = g_ptr_array_new ();
5566
5567         g_ptr_array_add (dynamic_images, image);
5568
5569         dynamic_images_unlock ();
5570
5571         return image;
5572 }
5573 #endif
5574
5575 static void
5576 free_blob_cache_entry (gpointer key, gpointer val, gpointer user_data)
5577 {
5578         g_free (key);
5579 }
5580
5581 static void
5582 release_hashtable (MonoGHashTable **hash)
5583 {
5584         if (*hash) {
5585                 mono_g_hash_table_destroy (*hash);
5586                 *hash = NULL;
5587         }
5588 }
5589
5590 void
5591 mono_dynamic_image_release_gc_roots (MonoDynamicImage *image)
5592 {
5593         release_hashtable (&image->token_fixups);
5594         release_hashtable (&image->handleref_managed);
5595         release_hashtable (&image->tokens);
5596         release_hashtable (&image->remapped_tokens);
5597         release_hashtable (&image->generic_def_objects);
5598         release_hashtable (&image->methodspec);
5599 }
5600
5601 // Free dynamic image pass one: Free resources but not image itself
5602 void
5603 mono_dynamic_image_free (MonoDynamicImage *image)
5604 {
5605         MonoDynamicImage *di = image;
5606         GList *list;
5607         int i;
5608
5609         if (di->methodspec)
5610                 mono_g_hash_table_destroy (di->methodspec);
5611         if (di->typespec)
5612                 g_hash_table_destroy (di->typespec);
5613         if (di->typeref)
5614                 g_hash_table_destroy (di->typeref);
5615         if (di->handleref)
5616                 g_hash_table_destroy (di->handleref);
5617         if (di->handleref_managed)
5618                 mono_g_hash_table_destroy (di->handleref_managed);
5619         if (di->tokens)
5620                 mono_g_hash_table_destroy (di->tokens);
5621         if (di->remapped_tokens)
5622                 mono_g_hash_table_destroy (di->remapped_tokens);
5623         if (di->generic_def_objects)
5624                 mono_g_hash_table_destroy (di->generic_def_objects);
5625         if (di->blob_cache) {
5626                 g_hash_table_foreach (di->blob_cache, free_blob_cache_entry, NULL);
5627                 g_hash_table_destroy (di->blob_cache);
5628         }
5629         if (di->standalonesig_cache)
5630                 g_hash_table_destroy (di->standalonesig_cache);
5631         for (list = di->array_methods; list; list = list->next) {
5632                 ArrayMethod *am = (ArrayMethod *)list->data;
5633                 g_free (am->sig);
5634                 g_free (am->name);
5635                 g_free (am);
5636         }
5637         g_list_free (di->array_methods);
5638         if (di->gen_params) {
5639                 for (i = 0; i < di->gen_params->len; i++) {
5640                         GenericParamTableEntry *entry = (GenericParamTableEntry *)g_ptr_array_index (di->gen_params, i);
5641                         mono_gc_deregister_root ((char*) &entry->gparam);
5642                         g_free (entry);
5643                 }
5644                 g_ptr_array_free (di->gen_params, TRUE);
5645         }
5646         if (di->token_fixups)
5647                 mono_g_hash_table_destroy (di->token_fixups);
5648         if (di->method_to_table_idx)
5649                 g_hash_table_destroy (di->method_to_table_idx);
5650         if (di->field_to_table_idx)
5651                 g_hash_table_destroy (di->field_to_table_idx);
5652         if (di->method_aux_hash)
5653                 g_hash_table_destroy (di->method_aux_hash);
5654         if (di->vararg_aux_hash)
5655                 g_hash_table_destroy (di->vararg_aux_hash);
5656         g_free (di->strong_name);
5657         g_free (di->win32_res);
5658         if (di->public_key)
5659                 g_free (di->public_key);
5660
5661         /*g_print ("string heap destroy for image %p\n", di);*/
5662         mono_dynamic_stream_reset (&di->sheap);
5663         mono_dynamic_stream_reset (&di->code);
5664         mono_dynamic_stream_reset (&di->resources);
5665         mono_dynamic_stream_reset (&di->us);
5666         mono_dynamic_stream_reset (&di->blob);
5667         mono_dynamic_stream_reset (&di->tstream);
5668         mono_dynamic_stream_reset (&di->guid);
5669         for (i = 0; i < MONO_TABLE_NUM; ++i) {
5670                 g_free (di->tables [i].values);
5671         }
5672
5673         dynamic_images_lock ();
5674
5675         if (dynamic_images)
5676                 g_ptr_array_remove (dynamic_images, di);
5677
5678         dynamic_images_unlock ();
5679 }
5680
5681 // Free dynamic image pass two: Free image itself (might never get called in some debug modes)
5682 void
5683 mono_dynamic_image_free_image (MonoDynamicImage *image)
5684 {
5685         /* See create_dynamic_mono_image () */
5686 #if HAVE_BOEHM_GC
5687         /* Allocated using GC_MALLOC */
5688 #else
5689         g_free (image);
5690 #endif
5691 }
5692
5693 #ifndef DISABLE_REFLECTION_EMIT
5694
5695 /*
5696  * mono_image_basic_init:
5697  * @assembly: an assembly builder object
5698  *
5699  * Create the MonoImage that represents the assembly builder and setup some
5700  * of the helper hash table and the basic metadata streams.
5701  */
5702 void
5703 mono_image_basic_init (MonoReflectionAssemblyBuilder *assemblyb)
5704 {
5705         MonoDynamicAssembly *assembly;
5706         MonoDynamicImage *image;
5707         MonoDomain *domain = mono_object_domain (assemblyb);
5708         
5709         if (assemblyb->dynamic_assembly)
5710                 return;
5711
5712 #if HAVE_BOEHM_GC
5713         /* assembly->assembly.image might be GC allocated */
5714         assembly = assemblyb->dynamic_assembly = (MonoDynamicAssembly *)GC_MALLOC (sizeof (MonoDynamicAssembly));
5715 #else
5716         assembly = assemblyb->dynamic_assembly = g_new0 (MonoDynamicAssembly, 1);
5717 #endif
5718
5719         mono_profiler_assembly_event (&assembly->assembly, MONO_PROFILE_START_LOAD);
5720         
5721         assembly->assembly.ref_count = 1;
5722         assembly->assembly.dynamic = TRUE;
5723         assembly->assembly.corlib_internal = assemblyb->corlib_internal;
5724         assemblyb->assembly.assembly = (MonoAssembly*)assembly;
5725         assembly->assembly.basedir = mono_string_to_utf8 (assemblyb->dir);
5726         if (assemblyb->culture)
5727                 assembly->assembly.aname.culture = mono_string_to_utf8 (assemblyb->culture);
5728         else
5729                 assembly->assembly.aname.culture = g_strdup ("");
5730
5731         if (assemblyb->version) {
5732                         char *vstr = mono_string_to_utf8 (assemblyb->version);
5733                         char **version = g_strsplit (vstr, ".", 4);
5734                         char **parts = version;
5735                         assembly->assembly.aname.major = atoi (*parts++);
5736                         assembly->assembly.aname.minor = atoi (*parts++);
5737                         assembly->assembly.aname.build = *parts != NULL ? atoi (*parts++) : 0;
5738                         assembly->assembly.aname.revision = *parts != NULL ? atoi (*parts) : 0;
5739
5740                         g_strfreev (version);
5741                         g_free (vstr);
5742         } else {
5743                         assembly->assembly.aname.major = 0;
5744                         assembly->assembly.aname.minor = 0;
5745                         assembly->assembly.aname.build = 0;
5746                         assembly->assembly.aname.revision = 0;
5747         }
5748
5749         assembly->run = assemblyb->access != 2;
5750         assembly->save = assemblyb->access != 1;
5751         assembly->domain = domain;
5752
5753         image = create_dynamic_mono_image (assembly, mono_string_to_utf8 (assemblyb->name), g_strdup ("RefEmit_YouForgotToDefineAModule"));
5754         image->initial_image = TRUE;
5755         assembly->assembly.aname.name = image->image.name;
5756         assembly->assembly.image = &image->image;
5757         if (assemblyb->pktoken && assemblyb->pktoken->max_length) {
5758                 /* -1 to correct for the trailing NULL byte */
5759                 if (assemblyb->pktoken->max_length != MONO_PUBLIC_KEY_TOKEN_LENGTH - 1) {
5760                         g_error ("Public key token length invalid for assembly %s: %i", assembly->assembly.aname.name, assemblyb->pktoken->max_length);
5761                 }
5762                 memcpy (&assembly->assembly.aname.public_key_token, mono_array_addr (assemblyb->pktoken, guint8, 0), assemblyb->pktoken->max_length);           
5763         }
5764
5765         mono_domain_assemblies_lock (domain);
5766         domain->domain_assemblies = g_slist_append (domain->domain_assemblies, assembly);
5767         mono_domain_assemblies_unlock (domain);
5768
5769         register_assembly (mono_object_domain (assemblyb), &assemblyb->assembly, &assembly->assembly);
5770         
5771         mono_profiler_assembly_loaded (&assembly->assembly, MONO_PROFILE_OK);
5772         
5773         mono_assembly_invoke_load_hook ((MonoAssembly*)assembly);
5774 }
5775
5776 #endif /* !DISABLE_REFLECTION_EMIT */
5777
5778 #ifndef DISABLE_REFLECTION_EMIT_SAVE
5779
5780 static int
5781 calc_section_size (MonoDynamicImage *assembly)
5782 {
5783         int nsections = 0;
5784
5785         /* alignment constraints */
5786         mono_image_add_stream_zero (&assembly->code, 4 - (assembly->code.index % 4));
5787         g_assert ((assembly->code.index % 4) == 0);
5788         assembly->meta_size += 3;
5789         assembly->meta_size &= ~3;
5790         mono_image_add_stream_zero (&assembly->resources, 4 - (assembly->resources.index % 4));
5791         g_assert ((assembly->resources.index % 4) == 0);
5792
5793         assembly->sections [MONO_SECTION_TEXT].size = assembly->meta_size + assembly->code.index + assembly->resources.index + assembly->strong_name_size;
5794         assembly->sections [MONO_SECTION_TEXT].attrs = SECT_FLAGS_HAS_CODE | SECT_FLAGS_MEM_EXECUTE | SECT_FLAGS_MEM_READ;
5795         nsections++;
5796
5797         if (assembly->win32_res) {
5798                 guint32 res_size = (assembly->win32_res_size + 3) & ~3;
5799
5800                 assembly->sections [MONO_SECTION_RSRC].size = res_size;
5801                 assembly->sections [MONO_SECTION_RSRC].attrs = SECT_FLAGS_HAS_INITIALIZED_DATA | SECT_FLAGS_MEM_READ;
5802                 nsections++;
5803         }
5804
5805         assembly->sections [MONO_SECTION_RELOC].size = 12;
5806         assembly->sections [MONO_SECTION_RELOC].attrs = SECT_FLAGS_MEM_READ | SECT_FLAGS_MEM_DISCARDABLE | SECT_FLAGS_HAS_INITIALIZED_DATA;
5807         nsections++;
5808
5809         return nsections;
5810 }
5811
5812 typedef struct {
5813         guint32 id;
5814         guint32 offset;
5815         GSList *children;
5816         MonoReflectionWin32Resource *win32_res; /* Only for leaf nodes */
5817 } ResTreeNode;
5818
5819 static int
5820 resource_tree_compare_by_id (gconstpointer a, gconstpointer b)
5821 {
5822         ResTreeNode *t1 = (ResTreeNode*)a;
5823         ResTreeNode *t2 = (ResTreeNode*)b;
5824
5825         return t1->id - t2->id;
5826 }
5827
5828 /*
5829  * resource_tree_create:
5830  *
5831  *  Organize the resources into a resource tree.
5832  */
5833 static ResTreeNode *
5834 resource_tree_create (MonoArray *win32_resources)
5835 {
5836         ResTreeNode *tree, *res_node, *type_node, *lang_node;
5837         GSList *l;
5838         int i;
5839
5840         tree = g_new0 (ResTreeNode, 1);
5841         
5842         for (i = 0; i < mono_array_length (win32_resources); ++i) {
5843                 MonoReflectionWin32Resource *win32_res =
5844                         (MonoReflectionWin32Resource*)mono_array_addr (win32_resources, MonoReflectionWin32Resource, i);
5845
5846                 /* Create node */
5847
5848                 /* FIXME: BUG: this stores managed references in unmanaged memory */
5849                 lang_node = g_new0 (ResTreeNode, 1);
5850                 lang_node->id = win32_res->lang_id;
5851                 lang_node->win32_res = win32_res;
5852
5853                 /* Create type node if neccesary */
5854                 type_node = NULL;
5855                 for (l = tree->children; l; l = l->next)
5856                         if (((ResTreeNode*)(l->data))->id == win32_res->res_type) {
5857                                 type_node = (ResTreeNode*)l->data;
5858                                 break;
5859                         }
5860
5861                 if (!type_node) {
5862                         type_node = g_new0 (ResTreeNode, 1);
5863                         type_node->id = win32_res->res_type;
5864
5865                         /* 
5866                          * The resource types have to be sorted otherwise
5867                          * Windows Explorer can't display the version information.
5868                          */
5869                         tree->children = g_slist_insert_sorted (tree->children, 
5870                                 type_node, resource_tree_compare_by_id);
5871                 }
5872
5873                 /* Create res node if neccesary */
5874                 res_node = NULL;
5875                 for (l = type_node->children; l; l = l->next)
5876                         if (((ResTreeNode*)(l->data))->id == win32_res->res_id) {
5877                                 res_node = (ResTreeNode*)l->data;
5878                                 break;
5879                         }
5880
5881                 if (!res_node) {
5882                         res_node = g_new0 (ResTreeNode, 1);
5883                         res_node->id = win32_res->res_id;
5884                         type_node->children = g_slist_append (type_node->children, res_node);
5885                 }
5886
5887                 res_node->children = g_slist_append (res_node->children, lang_node);
5888         }
5889
5890         return tree;
5891 }
5892
5893 /*
5894  * resource_tree_encode:
5895  * 
5896  *   Encode the resource tree into the format used in the PE file.
5897  */
5898 static void
5899 resource_tree_encode (ResTreeNode *node, char *begin, char *p, char **endbuf)
5900 {
5901         char *entries;
5902         MonoPEResourceDir dir;
5903         MonoPEResourceDirEntry dir_entry;
5904         MonoPEResourceDataEntry data_entry;
5905         GSList *l;
5906         guint32 res_id_entries;
5907
5908         /*
5909          * For the format of the resource directory, see the article
5910          * "An In-Depth Look into the Win32 Portable Executable File Format" by
5911          * Matt Pietrek
5912          */
5913
5914         memset (&dir, 0, sizeof (dir));
5915         memset (&dir_entry, 0, sizeof (dir_entry));
5916         memset (&data_entry, 0, sizeof (data_entry));
5917
5918         g_assert (sizeof (dir) == 16);
5919         g_assert (sizeof (dir_entry) == 8);
5920         g_assert (sizeof (data_entry) == 16);
5921
5922         node->offset = p - begin;
5923
5924         /* IMAGE_RESOURCE_DIRECTORY */
5925         res_id_entries = g_slist_length (node->children);
5926         dir.res_id_entries = GUINT16_TO_LE (res_id_entries);
5927
5928         memcpy (p, &dir, sizeof (dir));
5929         p += sizeof (dir);
5930
5931         /* Reserve space for entries */
5932         entries = p;
5933         p += sizeof (dir_entry) * res_id_entries;
5934
5935         /* Write children */
5936         for (l = node->children; l; l = l->next) {
5937                 ResTreeNode *child = (ResTreeNode*)l->data;
5938
5939                 if (child->win32_res) {
5940                         guint32 size;
5941
5942                         child->offset = p - begin;
5943
5944                         /* IMAGE_RESOURCE_DATA_ENTRY */
5945                         data_entry.rde_data_offset = GUINT32_TO_LE (p - begin + sizeof (data_entry));
5946                         size = mono_array_length (child->win32_res->res_data);
5947                         data_entry.rde_size = GUINT32_TO_LE (size);
5948
5949                         memcpy (p, &data_entry, sizeof (data_entry));
5950                         p += sizeof (data_entry);
5951
5952                         memcpy (p, mono_array_addr (child->win32_res->res_data, char, 0), size);
5953                         p += size;
5954                 } else {
5955                         resource_tree_encode (child, begin, p, &p);
5956                 }
5957         }
5958
5959         /* IMAGE_RESOURCE_ENTRY */
5960         for (l = node->children; l; l = l->next) {
5961                 ResTreeNode *child = (ResTreeNode*)l->data;
5962
5963                 MONO_PE_RES_DIR_ENTRY_SET_NAME (dir_entry, FALSE, child->id);
5964                 MONO_PE_RES_DIR_ENTRY_SET_DIR (dir_entry, !child->win32_res, child->offset);
5965
5966                 memcpy (entries, &dir_entry, sizeof (dir_entry));
5967                 entries += sizeof (dir_entry);
5968         }
5969
5970         *endbuf = p;
5971 }
5972
5973 static void
5974 resource_tree_free (ResTreeNode * node)
5975 {
5976         GSList * list;
5977         for (list = node->children; list; list = list->next)
5978                 resource_tree_free ((ResTreeNode*)list->data);
5979         g_slist_free(node->children);
5980         g_free (node);
5981 }
5982
5983 static void
5984 assembly_add_win32_resources (MonoDynamicImage *assembly, MonoReflectionAssemblyBuilder *assemblyb)
5985 {
5986         char *buf;
5987         char *p;
5988         guint32 size, i;
5989         MonoReflectionWin32Resource *win32_res;
5990         ResTreeNode *tree;
5991
5992         if (!assemblyb->win32_resources)
5993                 return;
5994
5995         /*
5996          * Resources are stored in a three level tree inside the PE file.
5997          * - level one contains a node for each type of resource
5998          * - level two contains a node for each resource
5999          * - level three contains a node for each instance of a resource for a
6000          *   specific language.
6001          */
6002
6003         tree = resource_tree_create (assemblyb->win32_resources);
6004
6005         /* Estimate the size of the encoded tree */
6006         size = 0;
6007         for (i = 0; i < mono_array_length (assemblyb->win32_resources); ++i) {
6008                 win32_res = (MonoReflectionWin32Resource*)mono_array_addr (assemblyb->win32_resources, MonoReflectionWin32Resource, i);
6009                 size += mono_array_length (win32_res->res_data);
6010         }
6011         /* Directory structure */
6012         size += mono_array_length (assemblyb->win32_resources) * 256;
6013         p = buf = (char *)g_malloc (size);
6014
6015         resource_tree_encode (tree, p, p, &p);
6016
6017         g_assert (p - buf <= size);
6018
6019         assembly->win32_res = (char *)g_malloc (p - buf);
6020         assembly->win32_res_size = p - buf;
6021         memcpy (assembly->win32_res, buf, p - buf);
6022
6023         g_free (buf);
6024         resource_tree_free (tree);
6025 }
6026
6027 static void
6028 fixup_resource_directory (char *res_section, char *p, guint32 rva)
6029 {
6030         MonoPEResourceDir *dir = (MonoPEResourceDir*)p;
6031         int i;
6032
6033         p += sizeof (MonoPEResourceDir);
6034         for (i = 0; i < GUINT16_FROM_LE (dir->res_named_entries) + GUINT16_FROM_LE (dir->res_id_entries); ++i) {
6035                 MonoPEResourceDirEntry *dir_entry = (MonoPEResourceDirEntry*)p;
6036                 char *child = res_section + MONO_PE_RES_DIR_ENTRY_DIR_OFFSET (*dir_entry);
6037                 if (MONO_PE_RES_DIR_ENTRY_IS_DIR (*dir_entry)) {
6038                         fixup_resource_directory (res_section, child, rva);
6039                 } else {
6040                         MonoPEResourceDataEntry *data_entry = (MonoPEResourceDataEntry*)child;
6041                         data_entry->rde_data_offset = GUINT32_TO_LE (GUINT32_FROM_LE (data_entry->rde_data_offset) + rva);
6042                 }
6043
6044                 p += sizeof (MonoPEResourceDirEntry);
6045         }
6046 }
6047
6048 static void
6049 checked_write_file (HANDLE f, gconstpointer buffer, guint32 numbytes)
6050 {
6051         guint32 dummy;
6052         if (!WriteFile (f, buffer, numbytes, &dummy, NULL))
6053                 g_error ("WriteFile returned %d\n", GetLastError ());
6054 }
6055
6056 /*
6057  * mono_image_create_pefile:
6058  * @mb: a module builder object
6059  * 
6060  * This function creates the PE-COFF header, the image sections, the CLI header  * etc. all the data is written in
6061  * assembly->pefile where it can be easily retrieved later in chunks.
6062  */
6063 gboolean
6064 mono_image_create_pefile (MonoReflectionModuleBuilder *mb, HANDLE file, MonoError *error)
6065 {
6066         MonoMSDOSHeader *msdos;
6067         MonoDotNetHeader *header;
6068         MonoSectionTable *section;
6069         MonoCLIHeader *cli_header;
6070         guint32 size, image_size, virtual_base, text_offset;
6071         guint32 header_start, section_start, file_offset, virtual_offset;
6072         MonoDynamicImage *assembly;
6073         MonoReflectionAssemblyBuilder *assemblyb;
6074         MonoDynamicStream pefile_stream = {0};
6075         MonoDynamicStream *pefile = &pefile_stream;
6076         int i, nsections;
6077         guint32 *rva, value;
6078         guchar *p;
6079         static const unsigned char msheader[] = {
6080                 0x4d, 0x5a, 0x90, 0x00, 0x03, 0x00, 0x00, 0x00,  0x04, 0x00, 0x00, 0x00, 0xff, 0xff, 0x00, 0x00,
6081                 0xb8, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,  0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
6082                 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
6083                 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,  0x00, 0x00, 0x00, 0x00, 0x80, 0x00, 0x00, 0x00,
6084                 0x0e, 0x1f, 0xba, 0x0e, 0x00, 0xb4, 0x09, 0xcd,  0x21, 0xb8, 0x01, 0x4c, 0xcd, 0x21, 0x54, 0x68,
6085                 0x69, 0x73, 0x20, 0x70, 0x72, 0x6f, 0x67, 0x72,  0x61, 0x6d, 0x20, 0x63, 0x61, 0x6e, 0x6e, 0x6f,
6086                 0x74, 0x20, 0x62, 0x65, 0x20, 0x72, 0x75, 0x6e,  0x20, 0x69, 0x6e, 0x20, 0x44, 0x4f, 0x53, 0x20,
6087                 0x6d, 0x6f, 0x64, 0x65, 0x2e, 0x0d, 0x0d, 0x0a,  0x24, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
6088         };
6089
6090         mono_error_init (error);
6091
6092         assemblyb = mb->assemblyb;
6093
6094         mono_image_basic_init (assemblyb);
6095         assembly = mb->dynamic_image;
6096
6097         assembly->pe_kind = assemblyb->pe_kind;
6098         assembly->machine = assemblyb->machine;
6099         ((MonoDynamicImage*)assemblyb->dynamic_assembly->assembly.image)->pe_kind = assemblyb->pe_kind;
6100         ((MonoDynamicImage*)assemblyb->dynamic_assembly->assembly.image)->machine = assemblyb->machine;
6101         
6102         if (!mono_image_build_metadata (mb, error))
6103                 return FALSE;
6104         
6105
6106         if (mb->is_main && assemblyb->resources) {
6107                 int len = mono_array_length (assemblyb->resources);
6108                 for (i = 0; i < len; ++i)
6109                         assembly_add_resource (mb, assembly, (MonoReflectionResource*)mono_array_addr (assemblyb->resources, MonoReflectionResource, i));
6110         }
6111
6112         if (mb->resources) {
6113                 int len = mono_array_length (mb->resources);
6114                 for (i = 0; i < len; ++i)
6115                         assembly_add_resource (mb, assembly, (MonoReflectionResource*)mono_array_addr (mb->resources, MonoReflectionResource, i));
6116         }
6117
6118         if (!build_compressed_metadata (assembly, error))
6119                 return FALSE;
6120
6121         if (mb->is_main)
6122                 assembly_add_win32_resources (assembly, assemblyb);
6123
6124         nsections = calc_section_size (assembly);
6125         
6126         /* The DOS header and stub */
6127         g_assert (sizeof (MonoMSDOSHeader) == sizeof (msheader));
6128         mono_image_add_stream_data (pefile, (char*)msheader, sizeof (msheader));
6129
6130         /* the dotnet header */
6131         header_start = mono_image_add_stream_zero (pefile, sizeof (MonoDotNetHeader));
6132
6133         /* the section tables */
6134         section_start = mono_image_add_stream_zero (pefile, sizeof (MonoSectionTable) * nsections);
6135
6136         file_offset = section_start + sizeof (MonoSectionTable) * nsections;
6137         virtual_offset = VIRT_ALIGN;
6138         image_size = 0;
6139
6140         for (i = 0; i < MONO_SECTION_MAX; ++i) {
6141                 if (!assembly->sections [i].size)
6142                         continue;
6143                 /* align offsets */
6144                 file_offset += FILE_ALIGN - 1;
6145                 file_offset &= ~(FILE_ALIGN - 1);
6146                 virtual_offset += VIRT_ALIGN - 1;
6147                 virtual_offset &= ~(VIRT_ALIGN - 1);
6148
6149                 assembly->sections [i].offset = file_offset;
6150                 assembly->sections [i].rva = virtual_offset;
6151
6152                 file_offset += assembly->sections [i].size;
6153                 virtual_offset += assembly->sections [i].size;
6154                 image_size += (assembly->sections [i].size + VIRT_ALIGN - 1) & ~(VIRT_ALIGN - 1);
6155         }
6156
6157         file_offset += FILE_ALIGN - 1;
6158         file_offset &= ~(FILE_ALIGN - 1);
6159
6160         image_size += section_start + sizeof (MonoSectionTable) * nsections;
6161
6162         /* back-patch info */
6163         msdos = (MonoMSDOSHeader*)pefile->data;
6164         msdos->pe_offset = GUINT32_FROM_LE (sizeof (MonoMSDOSHeader));
6165
6166         header = (MonoDotNetHeader*)(pefile->data + header_start);
6167         header->pesig [0] = 'P';
6168         header->pesig [1] = 'E';
6169         
6170         header->coff.coff_machine = GUINT16_FROM_LE (assemblyb->machine);
6171         header->coff.coff_sections = GUINT16_FROM_LE (nsections);
6172         header->coff.coff_time = GUINT32_FROM_LE (time (NULL));
6173         header->coff.coff_opt_header_size = GUINT16_FROM_LE (sizeof (MonoDotNetHeader) - sizeof (MonoCOFFHeader) - 4);
6174         if (assemblyb->pekind == 1) {
6175                 /* it's a dll */
6176                 header->coff.coff_attributes = GUINT16_FROM_LE (0x210e);
6177         } else {
6178                 /* it's an exe */
6179                 header->coff.coff_attributes = GUINT16_FROM_LE (0x010e);
6180         }
6181
6182         virtual_base = 0x400000; /* FIXME: 0x10000000 if a DLL */
6183
6184         header->pe.pe_magic = GUINT16_FROM_LE (0x10B);
6185         header->pe.pe_major = 6;
6186         header->pe.pe_minor = 0;
6187         size = assembly->sections [MONO_SECTION_TEXT].size;
6188         size += FILE_ALIGN - 1;
6189         size &= ~(FILE_ALIGN - 1);
6190         header->pe.pe_code_size = GUINT32_FROM_LE(size);
6191         size = assembly->sections [MONO_SECTION_RSRC].size;
6192         size += FILE_ALIGN - 1;
6193         size &= ~(FILE_ALIGN - 1);
6194         header->pe.pe_data_size = GUINT32_FROM_LE(size);
6195         g_assert (START_TEXT_RVA == assembly->sections [MONO_SECTION_TEXT].rva);
6196         header->pe.pe_rva_code_base = GUINT32_FROM_LE (assembly->sections [MONO_SECTION_TEXT].rva);
6197         header->pe.pe_rva_data_base = GUINT32_FROM_LE (assembly->sections [MONO_SECTION_RSRC].rva);
6198         /* pe_rva_entry_point always at the beginning of the text section */
6199         header->pe.pe_rva_entry_point = GUINT32_FROM_LE (assembly->sections [MONO_SECTION_TEXT].rva);
6200
6201         header->nt.pe_image_base = GUINT32_FROM_LE (virtual_base);
6202         header->nt.pe_section_align = GUINT32_FROM_LE (VIRT_ALIGN);
6203         header->nt.pe_file_alignment = GUINT32_FROM_LE (FILE_ALIGN);
6204         header->nt.pe_os_major = GUINT16_FROM_LE (4);
6205         header->nt.pe_os_minor = GUINT16_FROM_LE (0);
6206         header->nt.pe_subsys_major = GUINT16_FROM_LE (4);
6207         size = section_start;
6208         size += FILE_ALIGN - 1;
6209         size &= ~(FILE_ALIGN - 1);
6210         header->nt.pe_header_size = GUINT32_FROM_LE (size);
6211         size = image_size;
6212         size += VIRT_ALIGN - 1;
6213         size &= ~(VIRT_ALIGN - 1);
6214         header->nt.pe_image_size = GUINT32_FROM_LE (size);
6215
6216         /*
6217         // Translate the PEFileKind value to the value expected by the Windows loader
6218         */
6219         {
6220                 short kind;
6221
6222                 /*
6223                 // PEFileKinds.Dll == 1
6224                 // PEFileKinds.ConsoleApplication == 2
6225                 // PEFileKinds.WindowApplication == 3
6226                 //
6227                 // need to get:
6228                 //     IMAGE_SUBSYSTEM_WINDOWS_GUI 2 // Image runs in the Windows GUI subsystem.
6229                 //     IMAGE_SUBSYSTEM_WINDOWS_CUI 3 // Image runs in the Windows character subsystem.
6230                 */
6231                 if (assemblyb->pekind == 3)
6232                         kind = 2;
6233                 else
6234                         kind = 3;
6235                 
6236                 header->nt.pe_subsys_required = GUINT16_FROM_LE (kind);
6237         }    
6238         header->nt.pe_stack_reserve = GUINT32_FROM_LE (0x00100000);
6239         header->nt.pe_stack_commit = GUINT32_FROM_LE (0x00001000);
6240         header->nt.pe_heap_reserve = GUINT32_FROM_LE (0x00100000);
6241         header->nt.pe_heap_commit = GUINT32_FROM_LE (0x00001000);
6242         header->nt.pe_loader_flags = GUINT32_FROM_LE (0);
6243         header->nt.pe_data_dir_count = GUINT32_FROM_LE (16);
6244
6245         /* fill data directory entries */
6246
6247         header->datadir.pe_resource_table.size = GUINT32_FROM_LE (assembly->sections [MONO_SECTION_RSRC].size);
6248         header->datadir.pe_resource_table.rva = GUINT32_FROM_LE (assembly->sections [MONO_SECTION_RSRC].rva);
6249
6250         header->datadir.pe_reloc_table.size = GUINT32_FROM_LE (assembly->sections [MONO_SECTION_RELOC].size);
6251         header->datadir.pe_reloc_table.rva = GUINT32_FROM_LE (assembly->sections [MONO_SECTION_RELOC].rva);
6252
6253         header->datadir.pe_cli_header.size = GUINT32_FROM_LE (72);
6254         header->datadir.pe_cli_header.rva = GUINT32_FROM_LE (assembly->text_rva + assembly->cli_header_offset);
6255         header->datadir.pe_iat.size = GUINT32_FROM_LE (8);
6256         header->datadir.pe_iat.rva = GUINT32_FROM_LE (assembly->text_rva + assembly->iat_offset);
6257         /* patch entrypoint name */
6258         if (assemblyb->pekind == 1)
6259                 memcpy (assembly->code.data + assembly->imp_names_offset + 2, "_CorDllMain", 12);
6260         else
6261                 memcpy (assembly->code.data + assembly->imp_names_offset + 2, "_CorExeMain", 12);
6262         /* patch imported function RVA name */
6263         rva = (guint32*)(assembly->code.data + assembly->iat_offset);
6264         *rva = GUINT32_FROM_LE (assembly->text_rva + assembly->imp_names_offset);
6265
6266         /* the import table */
6267         header->datadir.pe_import_table.size = GUINT32_FROM_LE (79); /* FIXME: magic number? */
6268         header->datadir.pe_import_table.rva = GUINT32_FROM_LE (assembly->text_rva + assembly->idt_offset);
6269         /* patch imported dll RVA name and other entries in the dir */
6270         rva = (guint32*)(assembly->code.data + assembly->idt_offset + G_STRUCT_OFFSET (MonoIDT, name_rva));
6271         *rva = GUINT32_FROM_LE (assembly->text_rva + assembly->imp_names_offset + 14); /* 14 is hint+strlen+1 of func name */
6272         rva = (guint32*)(assembly->code.data + assembly->idt_offset + G_STRUCT_OFFSET (MonoIDT, import_address_table_rva));
6273         *rva = GUINT32_FROM_LE (assembly->text_rva + assembly->iat_offset);
6274         rva = (guint32*)(assembly->code.data + assembly->idt_offset + G_STRUCT_OFFSET (MonoIDT, import_lookup_table));
6275         *rva = GUINT32_FROM_LE (assembly->text_rva + assembly->ilt_offset);
6276
6277         p = (guchar*)(assembly->code.data + assembly->ilt_offset);
6278         value = (assembly->text_rva + assembly->imp_names_offset);
6279         *p++ = (value) & 0xff;
6280         *p++ = (value >> 8) & (0xff);
6281         *p++ = (value >> 16) & (0xff);
6282         *p++ = (value >> 24) & (0xff);
6283
6284         /* the CLI header info */
6285         cli_header = (MonoCLIHeader*)(assembly->code.data + assembly->cli_header_offset);
6286         cli_header->ch_size = GUINT32_FROM_LE (72);
6287         cli_header->ch_runtime_major = GUINT16_FROM_LE (2);
6288         cli_header->ch_runtime_minor = GUINT16_FROM_LE (5);
6289         cli_header->ch_flags = GUINT32_FROM_LE (assemblyb->pe_kind);
6290         if (assemblyb->entry_point) {
6291                 guint32 table_idx = 0;
6292                 if (!strcmp (assemblyb->entry_point->object.vtable->klass->name, "MethodBuilder")) {
6293                         MonoReflectionMethodBuilder *methodb = (MonoReflectionMethodBuilder*)assemblyb->entry_point;
6294                         table_idx = methodb->table_idx;
6295                 } else {
6296                         table_idx = GPOINTER_TO_UINT (g_hash_table_lookup (assembly->method_to_table_idx, assemblyb->entry_point->method));
6297                 }
6298                 cli_header->ch_entry_point = GUINT32_FROM_LE (table_idx | MONO_TOKEN_METHOD_DEF);
6299         } else {
6300                 cli_header->ch_entry_point = GUINT32_FROM_LE (0);
6301         }
6302         /* The embedded managed resources */
6303         text_offset = assembly->text_rva + assembly->code.index;
6304         cli_header->ch_resources.rva = GUINT32_FROM_LE (text_offset);
6305         cli_header->ch_resources.size = GUINT32_FROM_LE (assembly->resources.index);
6306         text_offset += assembly->resources.index;
6307         cli_header->ch_metadata.rva = GUINT32_FROM_LE (text_offset);
6308         cli_header->ch_metadata.size = GUINT32_FROM_LE (assembly->meta_size);
6309         text_offset += assembly->meta_size;
6310         if (assembly->strong_name_size) {
6311                 cli_header->ch_strong_name.rva = GUINT32_FROM_LE (text_offset);
6312                 cli_header->ch_strong_name.size = GUINT32_FROM_LE (assembly->strong_name_size);
6313                 text_offset += assembly->strong_name_size;
6314         }
6315
6316         /* write the section tables and section content */
6317         section = (MonoSectionTable*)(pefile->data + section_start);
6318         for (i = 0; i < MONO_SECTION_MAX; ++i) {
6319                 static const char section_names [][7] = {
6320                         ".text", ".rsrc", ".reloc"
6321                 };
6322                 if (!assembly->sections [i].size)
6323                         continue;
6324                 strcpy (section->st_name, section_names [i]);
6325                 /*g_print ("output section %s (%d), size: %d\n", section->st_name, i, assembly->sections [i].size);*/
6326                 section->st_virtual_address = GUINT32_FROM_LE (assembly->sections [i].rva);
6327                 section->st_virtual_size = GUINT32_FROM_LE (assembly->sections [i].size);
6328                 section->st_raw_data_size = GUINT32_FROM_LE (GUINT32_TO_LE (section->st_virtual_size) + (FILE_ALIGN - 1));
6329                 section->st_raw_data_size &= GUINT32_FROM_LE (~(FILE_ALIGN - 1));
6330                 section->st_raw_data_ptr = GUINT32_FROM_LE (assembly->sections [i].offset);
6331                 section->st_flags = GUINT32_FROM_LE (assembly->sections [i].attrs);
6332                 section ++;
6333         }
6334         
6335         checked_write_file (file, pefile->data, pefile->index);
6336         
6337         mono_dynamic_stream_reset (pefile);
6338         
6339         for (i = 0; i < MONO_SECTION_MAX; ++i) {
6340                 if (!assembly->sections [i].size)
6341                         continue;
6342                 
6343                 if (SetFilePointer (file, assembly->sections [i].offset, NULL, FILE_BEGIN) == INVALID_SET_FILE_POINTER)
6344                         g_error ("SetFilePointer returned %d\n", GetLastError ());
6345                 
6346                 switch (i) {
6347                 case MONO_SECTION_TEXT:
6348                         /* patch entry point */
6349                         p = (guchar*)(assembly->code.data + 2);
6350                         value = (virtual_base + assembly->text_rva + assembly->iat_offset);
6351                         *p++ = (value) & 0xff;
6352                         *p++ = (value >> 8) & 0xff;
6353                         *p++ = (value >> 16) & 0xff;
6354                         *p++ = (value >> 24) & 0xff;
6355                 
6356                         checked_write_file (file, assembly->code.data, assembly->code.index);
6357                         checked_write_file (file, assembly->resources.data, assembly->resources.index);
6358                         checked_write_file (file, assembly->image.raw_metadata, assembly->meta_size);
6359                         checked_write_file (file, assembly->strong_name, assembly->strong_name_size);
6360                                 
6361
6362                         g_free (assembly->image.raw_metadata);
6363                         break;
6364                 case MONO_SECTION_RELOC: {
6365                         struct {
6366                                 guint32 page_rva;
6367                                 guint32 block_size;
6368                                 guint16 type_and_offset;
6369                                 guint16 term;
6370                         } reloc;
6371                         
6372                         g_assert (sizeof (reloc) == 12);
6373                         
6374                         reloc.page_rva = GUINT32_FROM_LE (assembly->text_rva);
6375                         reloc.block_size = GUINT32_FROM_LE (12);
6376                         
6377                         /* 
6378                          * the entrypoint is always at the start of the text section 
6379                          * 3 is IMAGE_REL_BASED_HIGHLOW
6380                          * 2 is patch_size_rva - text_rva
6381                          */
6382                         reloc.type_and_offset = GUINT16_FROM_LE ((3 << 12) + (2));
6383                         reloc.term = 0;
6384                         
6385                         checked_write_file (file, &reloc, sizeof (reloc));
6386                         
6387                         break;
6388                 }
6389                 case MONO_SECTION_RSRC:
6390                         if (assembly->win32_res) {
6391
6392                                 /* Fixup the offsets in the IMAGE_RESOURCE_DATA_ENTRY structures */
6393                                 fixup_resource_directory (assembly->win32_res, assembly->win32_res, assembly->sections [i].rva);
6394                                 checked_write_file (file, assembly->win32_res, assembly->win32_res_size);
6395                         }
6396                         break;
6397                 default:
6398                         g_assert_not_reached ();
6399                 }
6400         }
6401         
6402         /* check that the file is properly padded */
6403         if (SetFilePointer (file, file_offset, NULL, FILE_BEGIN) == INVALID_SET_FILE_POINTER)
6404                 g_error ("SetFilePointer returned %d\n", GetLastError ());
6405         if (! SetEndOfFile (file))
6406                 g_error ("SetEndOfFile returned %d\n", GetLastError ());
6407         
6408         mono_dynamic_stream_reset (&assembly->code);
6409         mono_dynamic_stream_reset (&assembly->us);
6410         mono_dynamic_stream_reset (&assembly->blob);
6411         mono_dynamic_stream_reset (&assembly->guid);
6412         mono_dynamic_stream_reset (&assembly->sheap);
6413
6414         g_hash_table_foreach (assembly->blob_cache, (GHFunc)g_free, NULL);
6415         g_hash_table_destroy (assembly->blob_cache);
6416         assembly->blob_cache = NULL;
6417
6418         return TRUE;
6419 }
6420
6421 #else /* DISABLE_REFLECTION_EMIT_SAVE */
6422
6423 gboolean
6424 mono_image_create_pefile (MonoReflectionModuleBuilder *mb, HANDLE file, MonoError *error)
6425 {
6426         g_assert_not_reached ();
6427 }
6428
6429 #endif /* DISABLE_REFLECTION_EMIT_SAVE */
6430
6431 #ifndef DISABLE_REFLECTION_EMIT
6432
6433 MonoReflectionModule *
6434 mono_image_load_module_dynamic (MonoReflectionAssemblyBuilder *ab, MonoString *fileName)
6435 {
6436         MonoError error;
6437         MonoReflectionModule *result = NULL;
6438         char *name;
6439         MonoImage *image;
6440         MonoImageOpenStatus status;
6441         MonoDynamicAssembly *assembly;
6442         guint32 module_count;
6443         MonoImage **new_modules;
6444         gboolean *new_modules_loaded;
6445         
6446         name = mono_string_to_utf8 (fileName);
6447
6448         image = mono_image_open (name, &status);
6449         if (!image) {
6450                 MonoException *exc;
6451                 if (status == MONO_IMAGE_ERROR_ERRNO)
6452                         exc = mono_get_exception_file_not_found (fileName);
6453                 else
6454                         exc = mono_get_exception_bad_image_format (name);
6455                 g_free (name);
6456                 mono_raise_exception (exc);
6457         }
6458
6459         g_free (name);
6460
6461         assembly = ab->dynamic_assembly;
6462         image->assembly = (MonoAssembly*)assembly;
6463
6464         module_count = image->assembly->image->module_count;
6465         new_modules = g_new0 (MonoImage *, module_count + 1);
6466         new_modules_loaded = g_new0 (gboolean, module_count + 1);
6467
6468         if (image->assembly->image->modules)
6469                 memcpy (new_modules, image->assembly->image->modules, module_count * sizeof (MonoImage *));
6470         if (image->assembly->image->modules_loaded)
6471                 memcpy (new_modules_loaded, image->assembly->image->modules_loaded, module_count * sizeof (gboolean));
6472         new_modules [module_count] = image;
6473         new_modules_loaded [module_count] = TRUE;
6474         mono_image_addref (image);
6475
6476         g_free (image->assembly->image->modules);
6477         image->assembly->image->modules = new_modules;
6478         image->assembly->image->modules_loaded = new_modules_loaded;
6479         image->assembly->image->module_count ++;
6480
6481         mono_assembly_load_references (image, &status);
6482         if (status) {
6483                 mono_image_close (image);
6484                 mono_raise_exception (mono_get_exception_file_not_found (fileName));
6485         }
6486
6487         result = mono_module_get_object_checked (mono_domain_get (), image, &error);
6488         mono_error_raise_exception (&error); /* FIXME don't raise here */
6489         return result;
6490 }
6491
6492 #endif /* DISABLE_REFLECTION_EMIT */
6493
6494 /*
6495  * We need to return always the same object for MethodInfo, FieldInfo etc..
6496  * but we need to consider the reflected type.
6497  * type uses a different hash, since it uses custom hash/equal functions.
6498  */
6499
6500 typedef struct {
6501         gpointer item;
6502         MonoClass *refclass;
6503 } ReflectedEntry;
6504
6505 static gboolean
6506 reflected_equal (gconstpointer a, gconstpointer b) {
6507         const ReflectedEntry *ea = (const ReflectedEntry *)a;
6508         const ReflectedEntry *eb = (const ReflectedEntry *)b;
6509
6510         return (ea->item == eb->item) && (ea->refclass == eb->refclass);
6511 }
6512
6513 static guint
6514 reflected_hash (gconstpointer a) {
6515         const ReflectedEntry *ea = (const ReflectedEntry *)a;
6516         return mono_aligned_addr_hash (ea->item);
6517 }
6518
6519 #define CHECK_OBJECT(t,p,k)     \
6520         do {    \
6521                 t _obj; \
6522                 ReflectedEntry e;       \
6523                 e.item = (p);   \
6524                 e.refclass = (k);       \
6525                 mono_domain_lock (domain);      \
6526                 if (!domain->refobject_hash)    \
6527                         domain->refobject_hash = mono_g_hash_table_new_type (reflected_hash, reflected_equal, MONO_HASH_VALUE_GC, MONO_ROOT_SOURCE_DOMAIN, "domain reflection objects table");  \
6528                 if ((_obj = (t)mono_g_hash_table_lookup (domain->refobject_hash, &e))) {        \
6529                         mono_domain_unlock (domain);    \
6530                         return _obj;    \
6531                 }       \
6532         mono_domain_unlock (domain); \
6533         } while (0)
6534
6535 #ifdef HAVE_BOEHM_GC
6536 /* ReflectedEntry doesn't need to be GC tracked */
6537 #define ALLOC_REFENTRY g_new0 (ReflectedEntry, 1)
6538 #define FREE_REFENTRY(entry) g_free ((entry))
6539 #define REFENTRY_REQUIRES_CLEANUP
6540 #else
6541 #define ALLOC_REFENTRY (ReflectedEntry *)mono_mempool_alloc (domain->mp, sizeof (ReflectedEntry))
6542 /* FIXME: */
6543 #define FREE_REFENTRY(entry)
6544 #endif
6545
6546 #define CACHE_OBJECT(t,p,o,k)   \
6547         do {    \
6548                 t _obj; \
6549         ReflectedEntry pe; \
6550         pe.item = (p); \
6551         pe.refclass = (k); \
6552         mono_domain_lock (domain); \
6553                 if (!domain->refobject_hash)    \
6554                         domain->refobject_hash = mono_g_hash_table_new_type (reflected_hash, reflected_equal, MONO_HASH_VALUE_GC, MONO_ROOT_SOURCE_DOMAIN, "domain reflection objects table");  \
6555         _obj = (t)mono_g_hash_table_lookup (domain->refobject_hash, &pe); \
6556         if (!_obj) { \
6557                     ReflectedEntry *e = ALLOC_REFENTRY;         \
6558                     e->item = (p);      \
6559                     e->refclass = (k);  \
6560                     mono_g_hash_table_insert (domain->refobject_hash, e,o);     \
6561             _obj = o; \
6562         } \
6563                 mono_domain_unlock (domain);    \
6564         return _obj; \
6565         } while (0)
6566
6567 static void
6568 clear_cached_object (MonoDomain *domain, gpointer o, MonoClass *klass)
6569 {
6570         mono_domain_lock (domain);
6571         if (domain->refobject_hash) {
6572         ReflectedEntry pe;
6573                 gpointer orig_pe, orig_value;
6574
6575                 pe.item = o;
6576                 pe.refclass = klass;
6577                 if (mono_g_hash_table_lookup_extended (domain->refobject_hash, &pe, &orig_pe, &orig_value)) {
6578                         mono_g_hash_table_remove (domain->refobject_hash, &pe);
6579                         FREE_REFENTRY (orig_pe);
6580                 }
6581         }
6582         mono_domain_unlock (domain);
6583 }
6584
6585 #ifdef REFENTRY_REQUIRES_CLEANUP
6586 static void
6587 cleanup_refobject_hash (gpointer key, gpointer value, gpointer user_data)
6588 {
6589         FREE_REFENTRY (key);
6590 }
6591 #endif
6592
6593 void
6594 mono_reflection_cleanup_domain (MonoDomain *domain)
6595 {
6596         if (domain->refobject_hash) {
6597 /*let's avoid scanning the whole hashtable if not needed*/
6598 #ifdef REFENTRY_REQUIRES_CLEANUP
6599                 mono_g_hash_table_foreach (domain->refobject_hash, cleanup_refobject_hash, NULL);
6600 #endif
6601                 mono_g_hash_table_destroy (domain->refobject_hash);
6602                 domain->refobject_hash = NULL;
6603         }
6604 }
6605
6606 #ifndef DISABLE_REFLECTION_EMIT
6607 static gpointer
6608 register_assembly (MonoDomain *domain, MonoReflectionAssembly *res, MonoAssembly *assembly)
6609 {
6610         CACHE_OBJECT (MonoReflectionAssembly *, assembly, res, NULL);
6611 }
6612
6613 static gpointer
6614 register_module (MonoDomain *domain, MonoReflectionModuleBuilder *res, MonoDynamicImage *module)
6615 {
6616         CACHE_OBJECT (MonoReflectionModuleBuilder *, module, res, NULL);
6617 }
6618
6619 void
6620 mono_image_module_basic_init (MonoReflectionModuleBuilder *moduleb)
6621 {
6622         MonoDynamicImage *image = moduleb->dynamic_image;
6623         MonoReflectionAssemblyBuilder *ab = moduleb->assemblyb;
6624         if (!image) {
6625                 MonoError error;
6626                 int module_count;
6627                 MonoImage **new_modules;
6628                 MonoImage *ass;
6629                 char *name, *fqname;
6630                 /*
6631                  * FIXME: we already created an image in mono_image_basic_init (), but
6632                  * we don't know which module it belongs to, since that is only 
6633                  * determined at assembly save time.
6634                  */
6635                 /*image = (MonoDynamicImage*)ab->dynamic_assembly->assembly.image; */
6636                 name = mono_string_to_utf8 (ab->name);
6637                 fqname = mono_string_to_utf8_checked (moduleb->module.fqname, &error);
6638                 if (!mono_error_ok (&error)) {
6639                         g_free (name);
6640                         mono_error_raise_exception (&error);
6641                 }
6642                 image = create_dynamic_mono_image (ab->dynamic_assembly, name, fqname);
6643
6644                 moduleb->module.image = &image->image;
6645                 moduleb->dynamic_image = image;
6646                 register_module (mono_object_domain (moduleb), moduleb, image);
6647
6648                 /* register the module with the assembly */
6649                 ass = ab->dynamic_assembly->assembly.image;
6650                 module_count = ass->module_count;
6651                 new_modules = g_new0 (MonoImage *, module_count + 1);
6652
6653                 if (ass->modules)
6654                         memcpy (new_modules, ass->modules, module_count * sizeof (MonoImage *));
6655                 new_modules [module_count] = &image->image;
6656                 mono_image_addref (&image->image);
6657
6658                 g_free (ass->modules);
6659                 ass->modules = new_modules;
6660                 ass->module_count ++;
6661         }
6662 }
6663
6664 void
6665 mono_image_set_wrappers_type (MonoReflectionModuleBuilder *moduleb, MonoReflectionType *type)
6666 {
6667         MonoDynamicImage *image = moduleb->dynamic_image;
6668
6669         g_assert (type->type);
6670         image->wrappers_type = mono_class_from_mono_type (type->type);
6671 }
6672
6673 #endif
6674
6675 /*
6676  * mono_assembly_get_object:
6677  * @domain: an app domain
6678  * @assembly: an assembly
6679  *
6680  * Return an System.Reflection.Assembly object representing the MonoAssembly @assembly.
6681  */
6682 MonoReflectionAssembly*
6683 mono_assembly_get_object (MonoDomain *domain, MonoAssembly *assembly)
6684 {
6685         MonoError error;
6686         MonoReflectionAssembly *result;
6687         result = mono_assembly_get_object_checked (domain, assembly, &error);
6688         mono_error_cleanup (&error); /* FIXME new API that doesn't swallow the error */
6689         return result;
6690 }
6691 /*
6692  * mono_assembly_get_object_checked:
6693  * @domain: an app domain
6694  * @assembly: an assembly
6695  *
6696  * Return an System.Reflection.Assembly object representing the MonoAssembly @assembly.
6697  */
6698 MonoReflectionAssembly*
6699 mono_assembly_get_object_checked (MonoDomain *domain, MonoAssembly *assembly, MonoError *error)
6700 {
6701         MonoReflectionAssembly *res;
6702         
6703         mono_error_init (error);
6704
6705         CHECK_OBJECT (MonoReflectionAssembly *, assembly, NULL);
6706         res = (MonoReflectionAssembly *)mono_object_new_checked (domain, mono_class_get_mono_assembly_class (), error);
6707         if (!res)
6708                 return NULL;
6709         res->assembly = assembly;
6710
6711         CACHE_OBJECT (MonoReflectionAssembly *, assembly, res, NULL);
6712 }
6713
6714
6715
6716 MonoReflectionModule*   
6717 mono_module_get_object   (MonoDomain *domain, MonoImage *image)
6718 {
6719         MonoError error;
6720         MonoReflectionModule *result;
6721         result = mono_module_get_object_checked (domain, image, &error);
6722         mono_error_raise_exception (&error);
6723         return result;
6724 }
6725
6726 MonoReflectionModule*
6727 mono_module_get_object_checked (MonoDomain *domain, MonoImage *image, MonoError *error)
6728 {
6729         MonoReflectionModule *res;
6730         char* basename;
6731         
6732         mono_error_init (error);
6733         CHECK_OBJECT (MonoReflectionModule *, image, NULL);
6734         res = (MonoReflectionModule *)mono_object_new_checked (domain, mono_class_get_mono_module_class (), error);
6735         if (!res)
6736                 return NULL;
6737
6738         res->image = image;
6739         MonoReflectionAssembly *assm_obj = mono_assembly_get_object_checked (domain, image->assembly, error);
6740         if (!assm_obj)
6741                 return NULL;
6742         MONO_OBJECT_SETREF (res, assembly, assm_obj);
6743
6744         MONO_OBJECT_SETREF (res, fqname, mono_string_new (domain, image->name));
6745         basename = g_path_get_basename (image->name);
6746         MONO_OBJECT_SETREF (res, name, mono_string_new (domain, basename));
6747         MONO_OBJECT_SETREF (res, scopename, mono_string_new (domain, image->module_name));
6748         
6749         g_free (basename);
6750
6751         if (image->assembly->image == image) {
6752                 res->token = mono_metadata_make_token (MONO_TABLE_MODULE, 1);
6753         } else {
6754                 int i;
6755                 res->token = 0;
6756                 if (image->assembly->image->modules) {
6757                         for (i = 0; i < image->assembly->image->module_count; i++) {
6758                                 if (image->assembly->image->modules [i] == image)
6759                                         res->token = mono_metadata_make_token (MONO_TABLE_MODULEREF, i + 1);
6760                         }
6761                         g_assert (res->token);
6762                 }
6763         }
6764
6765         CACHE_OBJECT (MonoReflectionModule *, image, res, NULL);
6766 }
6767
6768 MonoReflectionModule*
6769 mono_module_file_get_object (MonoDomain *domain, MonoImage *image, int table_index)
6770 {
6771         MonoError error;
6772         MonoReflectionModule *result;
6773         result = mono_module_file_get_object_checked (domain, image, table_index, &error);
6774         mono_error_cleanup (&error); /* FIXME new API that doesn't swallow the error */
6775         return result;
6776 }
6777
6778 MonoReflectionModule*
6779 mono_module_file_get_object_checked (MonoDomain *domain, MonoImage *image, int table_index, MonoError *error)
6780 {
6781         MonoReflectionModule *res;
6782         MonoTableInfo *table;
6783         guint32 cols [MONO_FILE_SIZE];
6784         const char *name;
6785         guint32 i, name_idx;
6786         const char *val;
6787         
6788         mono_error_init (error);
6789
6790         res = (MonoReflectionModule *)mono_object_new_checked (domain, mono_class_get_mono_module_class (), error);
6791         if (!res)
6792                 return NULL;
6793
6794         table = &image->tables [MONO_TABLE_FILE];
6795         g_assert (table_index < table->rows);
6796         mono_metadata_decode_row (table, table_index, cols, MONO_FILE_SIZE);
6797
6798         res->image = NULL;
6799         MonoReflectionAssembly *assm_obj = mono_assembly_get_object_checked (domain, image->assembly, error);
6800         if (!assm_obj)
6801                 return NULL;
6802         MONO_OBJECT_SETREF (res, assembly, assm_obj);
6803         name = mono_metadata_string_heap (image, cols [MONO_FILE_NAME]);
6804
6805         /* Check whenever the row has a corresponding row in the moduleref table */
6806         table = &image->tables [MONO_TABLE_MODULEREF];
6807         for (i = 0; i < table->rows; ++i) {
6808                 name_idx = mono_metadata_decode_row_col (table, i, MONO_MODULEREF_NAME);
6809                 val = mono_metadata_string_heap (image, name_idx);
6810                 if (strcmp (val, name) == 0)
6811                         res->image = image->modules [i];
6812         }
6813
6814         MONO_OBJECT_SETREF (res, fqname, mono_string_new (domain, name));
6815         MONO_OBJECT_SETREF (res, name, mono_string_new (domain, name));
6816         MONO_OBJECT_SETREF (res, scopename, mono_string_new (domain, name));
6817         res->is_resource = cols [MONO_FILE_FLAGS] && FILE_CONTAINS_NO_METADATA;
6818         res->token = mono_metadata_make_token (MONO_TABLE_FILE, table_index + 1);
6819
6820         return res;
6821 }
6822
6823 static gboolean
6824 verify_safe_for_managed_space (MonoType *type)
6825 {
6826         switch (type->type) {
6827 #ifdef DEBUG_HARDER
6828         case MONO_TYPE_ARRAY:
6829                 return verify_safe_for_managed_space (&type->data.array->eklass->byval_arg);
6830         case MONO_TYPE_PTR:
6831                 return verify_safe_for_managed_space (type->data.type);
6832         case MONO_TYPE_SZARRAY:
6833                 return verify_safe_for_managed_space (&type->data.klass->byval_arg);
6834         case MONO_TYPE_GENERICINST: {
6835                 MonoGenericInst *inst = type->data.generic_class->inst;
6836                 int i;
6837                 if (!inst->is_open)
6838                         break;
6839                 for (i = 0; i < inst->type_argc; ++i)
6840                         if (!verify_safe_for_managed_space (inst->type_argv [i]))
6841                                 return FALSE;
6842                 return TRUE;
6843         }
6844 #endif
6845         case MONO_TYPE_VAR:
6846         case MONO_TYPE_MVAR:
6847                 return TRUE;
6848         default:
6849                 return TRUE;
6850         }
6851 }
6852
6853 static MonoType*
6854 mono_type_normalize (MonoType *type)
6855 {
6856         int i;
6857         MonoGenericClass *gclass;
6858         MonoGenericInst *ginst;
6859         MonoClass *gtd;
6860         MonoGenericContainer *gcontainer;
6861         MonoType **argv = NULL;
6862         gboolean is_denorm_gtd = TRUE, requires_rebind = FALSE;
6863
6864         if (type->type != MONO_TYPE_GENERICINST)
6865                 return type;
6866
6867         gclass = type->data.generic_class;
6868         ginst = gclass->context.class_inst;
6869         if (!ginst->is_open)
6870                 return type;
6871
6872         gtd = gclass->container_class;
6873         gcontainer = gtd->generic_container;
6874         argv = g_newa (MonoType*, ginst->type_argc);
6875
6876         for (i = 0; i < ginst->type_argc; ++i) {
6877                 MonoType *t = ginst->type_argv [i], *norm;
6878                 if (t->type != MONO_TYPE_VAR || t->data.generic_param->num != i || t->data.generic_param->owner != gcontainer)
6879                         is_denorm_gtd = FALSE;
6880                 norm = mono_type_normalize (t);
6881                 argv [i] = norm;
6882                 if (norm != t)
6883                         requires_rebind = TRUE;
6884         }
6885
6886         if (is_denorm_gtd)
6887                 return type->byref == gtd->byval_arg.byref ? &gtd->byval_arg : &gtd->this_arg;
6888
6889         if (requires_rebind) {
6890                 MonoClass *klass = mono_class_bind_generic_parameters (gtd, ginst->type_argc, argv, gclass->is_dynamic);
6891                 return type->byref == klass->byval_arg.byref ? &klass->byval_arg : &klass->this_arg;
6892         }
6893
6894         return type;
6895 }
6896 /*
6897  * mono_type_get_object:
6898  * @domain: an app domain
6899  * @type: a type
6900  *
6901  * Return an System.MonoType object representing the type @type.
6902  */
6903 MonoReflectionType*
6904 mono_type_get_object (MonoDomain *domain, MonoType *type)
6905 {
6906         MonoError error;
6907         MonoReflectionType *ret = mono_type_get_object_checked (domain, type, &error);
6908         mono_error_raise_exception (&error);
6909
6910         return ret;
6911 }
6912
6913 MonoReflectionType*
6914 mono_type_get_object_checked (MonoDomain *domain, MonoType *type, MonoError *error)
6915 {
6916         MonoType *norm_type;
6917         MonoReflectionType *res;
6918         MonoClass *klass;
6919
6920         mono_error_init (error);
6921
6922         klass = mono_class_from_mono_type (type);
6923
6924         /*we must avoid using @type as it might have come
6925          * from a mono_metadata_type_dup and the caller
6926          * expects that is can be freed.
6927          * Using the right type from 
6928          */
6929         type = klass->byval_arg.byref == type->byref ? &klass->byval_arg : &klass->this_arg;
6930
6931         /* void is very common */
6932         if (type->type == MONO_TYPE_VOID && domain->typeof_void)
6933                 return (MonoReflectionType*)domain->typeof_void;
6934
6935         /*
6936          * If the vtable of the given class was already created, we can use
6937          * the MonoType from there and avoid all locking and hash table lookups.
6938          * 
6939          * We cannot do this for TypeBuilders as mono_reflection_create_runtime_class expects
6940          * that the resulting object is different.   
6941          */
6942         if (type == &klass->byval_arg && !image_is_dynamic (klass->image)) {
6943                 MonoVTable *vtable = mono_class_try_get_vtable (domain, klass);
6944                 if (vtable && vtable->type)
6945                         return (MonoReflectionType *)vtable->type;
6946         }
6947
6948         mono_loader_lock (); /*FIXME mono_class_init and mono_class_vtable acquire it*/
6949         mono_domain_lock (domain);
6950         if (!domain->type_hash)
6951                 domain->type_hash = mono_g_hash_table_new_type ((GHashFunc)mono_metadata_type_hash, 
6952                                 (GCompareFunc)mono_metadata_type_equal, MONO_HASH_VALUE_GC, MONO_ROOT_SOURCE_DOMAIN, "domain reflection types table");
6953         if ((res = (MonoReflectionType *)mono_g_hash_table_lookup (domain->type_hash, type))) {
6954                 mono_domain_unlock (domain);
6955                 mono_loader_unlock ();
6956                 return res;
6957         }
6958
6959         /*Types must be normalized so a generic instance of the GTD get's the same inner type.
6960          * For example in: Foo<A,B>; Bar<A> : Foo<A, Bar<A>>
6961          * The second Bar will be encoded a generic instance of Bar with <A> as parameter.
6962          * On all other places, Bar<A> will be encoded as the GTD itself. This is an implementation
6963          * artifact of how generics are encoded and should be transparent to managed code so we
6964          * need to weed out this diference when retrieving managed System.Type objects.
6965          */
6966         norm_type = mono_type_normalize (type);
6967         if (norm_type != type) {
6968                 res = mono_type_get_object_checked (domain, norm_type, error);
6969                 if (!mono_error_ok (error))
6970                         return NULL;
6971                 mono_g_hash_table_insert (domain->type_hash, type, res);
6972                 mono_domain_unlock (domain);
6973                 mono_loader_unlock ();
6974                 return res;
6975         }
6976
6977         /* This MonoGenericClass hack is no longer necessary. Let's leave it here until we finish with the 2-stage type-builder setup.*/
6978         if ((type->type == MONO_TYPE_GENERICINST) && type->data.generic_class->is_dynamic && !type->data.generic_class->container_class->wastypebuilder)
6979                 g_assert (0);
6980
6981         if (!verify_safe_for_managed_space (type)) {
6982                 mono_domain_unlock (domain);
6983                 mono_loader_unlock ();
6984                 mono_error_set_generic_error (error, "System", "InvalidOperationException", "This type cannot be propagated to managed space");
6985                 return NULL;
6986         }
6987
6988         if (mono_class_get_ref_info (klass) && !klass->wastypebuilder) {
6989                 gboolean is_type_done = TRUE;
6990                 /* Generic parameters have reflection_info set but they are not finished together with their enclosing type.
6991                  * We must ensure that once a type is finished we don't return a GenericTypeParameterBuilder.
6992                  * We can't simply close the types as this will interfere with other parts of the generics machinery.
6993                 */
6994                 if (klass->byval_arg.type == MONO_TYPE_MVAR || klass->byval_arg.type == MONO_TYPE_VAR) {
6995                         MonoGenericParam *gparam = klass->byval_arg.data.generic_param;
6996
6997                         if (gparam->owner && gparam->owner->is_method) {
6998                                 MonoMethod *method = gparam->owner->owner.method;
6999                                 if (method && mono_class_get_generic_type_definition (method->klass)->wastypebuilder)
7000                                         is_type_done = FALSE;
7001                         } else if (gparam->owner && !gparam->owner->is_method) {
7002                                 MonoClass *klass = gparam->owner->owner.klass;
7003                                 if (klass && mono_class_get_generic_type_definition (klass)->wastypebuilder)
7004                                         is_type_done = FALSE;
7005                         }
7006                 } 
7007
7008                 /* g_assert_not_reached (); */
7009                 /* should this be considered an error condition? */
7010                 if (is_type_done && !type->byref) {
7011                         mono_domain_unlock (domain);
7012                         mono_loader_unlock ();
7013                         return (MonoReflectionType *)mono_class_get_ref_info (klass);
7014                 }
7015         }
7016         /* This is stored in vtables/JITted code so it has to be pinned */
7017         res = (MonoReflectionType *)mono_object_new_pinned (domain, mono_defaults.monotype_class, error);
7018         if (!mono_error_ok (error))
7019                 return NULL;
7020
7021         res->type = type;
7022         mono_g_hash_table_insert (domain->type_hash, type, res);
7023
7024         if (type->type == MONO_TYPE_VOID)
7025                 domain->typeof_void = (MonoObject*)res;
7026
7027         mono_domain_unlock (domain);
7028         mono_loader_unlock ();
7029         return res;
7030 }
7031
7032 /*
7033  * mono_method_get_object:
7034  * @domain: an app domain
7035  * @method: a method
7036  * @refclass: the reflected type (can be NULL)
7037  *
7038  * Return an System.Reflection.MonoMethod object representing the method @method.
7039  */
7040 MonoReflectionMethod*
7041 mono_method_get_object (MonoDomain *domain, MonoMethod *method, MonoClass *refclass)
7042 {
7043         MonoError error;
7044         MonoReflectionMethod *ret = NULL;
7045         ret = mono_method_get_object_checked (domain, method, refclass, &error);
7046         mono_error_raise_exception (&error);
7047         return ret;
7048 }
7049
7050 /*
7051  * mono_method_get_object_checked:
7052  * @domain: an app domain
7053  * @method: a method
7054  * @refclass: the reflected type (can be NULL)
7055  * @error: set on error.
7056  *
7057  * Return an System.Reflection.MonoMethod object representing the method @method.
7058  * Returns NULL and sets @error on error.
7059  */
7060 MonoReflectionMethod*
7061 mono_method_get_object_checked (MonoDomain *domain, MonoMethod *method, MonoClass *refclass, MonoError *error)
7062 {
7063         /*
7064          * We use the same C representation for methods and constructors, but the type 
7065          * name in C# is different.
7066          */
7067         MonoReflectionType *rt;
7068         MonoClass *klass;
7069         MonoReflectionMethod *ret;
7070
7071         mono_error_init (error);
7072
7073         if (method->is_inflated) {
7074                 MonoReflectionGenericMethod *gret;
7075
7076                 if (!refclass)
7077                         refclass = method->klass;
7078                 CHECK_OBJECT (MonoReflectionMethod *, method, refclass);
7079                 if ((*method->name == '.') && (!strcmp (method->name, ".ctor") || !strcmp (method->name, ".cctor"))) {
7080                         klass = mono_class_get_mono_generic_cmethod_class ();
7081                 } else {
7082                         klass = mono_class_get_mono_generic_method_class ();
7083                 }
7084                 gret = (MonoReflectionGenericMethod*)mono_object_new_checked (domain, klass, error);
7085                 if (!mono_error_ok (error))
7086                         goto leave;
7087                 gret->method.method = method;
7088
7089                 MONO_OBJECT_SETREF (gret, method.name, mono_string_new (domain, method->name));
7090
7091                 rt = mono_type_get_object_checked (domain, &refclass->byval_arg, error);
7092                 if (!mono_error_ok (error))
7093                     goto leave;
7094
7095                 MONO_OBJECT_SETREF (gret, method.reftype, rt);
7096
7097                 CACHE_OBJECT (MonoReflectionMethod *, method, (MonoReflectionMethod*)gret, refclass);
7098         }
7099
7100         if (!refclass)
7101                 refclass = method->klass;
7102
7103         CHECK_OBJECT (MonoReflectionMethod *, method, refclass);
7104         if (*method->name == '.' && (strcmp (method->name, ".ctor") == 0 || strcmp (method->name, ".cctor") == 0)) {
7105                 klass = mono_class_get_mono_cmethod_class ();
7106         }
7107         else {
7108                 klass = mono_class_get_mono_method_class ();
7109         }
7110         ret = (MonoReflectionMethod*)mono_object_new_checked (domain, klass, error);
7111         if (!mono_error_ok (error))
7112                 goto leave;
7113         ret->method = method;
7114
7115         rt = mono_type_get_object_checked (domain, &refclass->byval_arg, error);
7116         if (!mono_error_ok (error))
7117                 goto leave;
7118
7119         MONO_OBJECT_SETREF (ret, reftype, rt);
7120
7121         CACHE_OBJECT (MonoReflectionMethod *, method, ret, refclass);
7122
7123 leave:
7124         g_assert (!mono_error_ok (error));
7125         return NULL;
7126 }
7127
7128 /*
7129  * mono_method_clear_object:
7130  *
7131  *   Clear the cached reflection objects for the dynamic method METHOD.
7132  */
7133 void
7134 mono_method_clear_object (MonoDomain *domain, MonoMethod *method)
7135 {
7136         MonoClass *klass;
7137         g_assert (method_is_dynamic (method));
7138
7139         klass = method->klass;
7140         while (klass) {
7141                 clear_cached_object (domain, method, klass);
7142                 klass = klass->parent;
7143         }
7144         /* Added by mono_param_get_objects () */
7145         clear_cached_object (domain, &(method->signature), NULL);
7146         klass = method->klass;
7147         while (klass) {
7148                 clear_cached_object (domain, &(method->signature), klass);
7149                 klass = klass->parent;
7150         }
7151 }
7152
7153 /*
7154  * mono_field_get_object:
7155  * @domain: an app domain
7156  * @klass: a type
7157  * @field: a field
7158  *
7159  * Return an System.Reflection.MonoField object representing the field @field
7160  * in class @klass.
7161  */
7162 MonoReflectionField*
7163 mono_field_get_object (MonoDomain *domain, MonoClass *klass, MonoClassField *field)
7164 {
7165         MonoError error;
7166         MonoReflectionField *result;
7167         result = mono_field_get_object_checked (domain, klass, field, &error);
7168         mono_error_raise_exception (&error);
7169         return result;
7170 }
7171
7172 /*
7173  * mono_field_get_object_checked:
7174  * @domain: an app domain
7175  * @klass: a type
7176  * @field: a field
7177  * @error: set on error
7178  *
7179  * Return an System.Reflection.MonoField object representing the field @field
7180  * in class @klass. On error, returns NULL and sets @error.
7181  */
7182 MonoReflectionField*
7183 mono_field_get_object_checked (MonoDomain *domain, MonoClass *klass, MonoClassField *field, MonoError *error)
7184 {
7185         MonoReflectionType *rt;
7186         MonoReflectionField *res;
7187
7188         mono_error_init (error);
7189
7190         CHECK_OBJECT (MonoReflectionField *, field, klass);
7191         res = (MonoReflectionField *)mono_object_new_checked (domain, mono_class_get_mono_field_class (), error);
7192         if (!res)
7193                 return NULL;
7194         res->klass = klass;
7195         res->field = field;
7196         MONO_OBJECT_SETREF (res, name, mono_string_new (domain, mono_field_get_name (field)));
7197
7198         if (is_field_on_inst (field)) {
7199                 res->attrs = get_field_on_inst_generic_type (field)->attrs;
7200
7201                 rt = mono_type_get_object_checked (domain, field->type, error);
7202                 if (!mono_error_ok (error))
7203                         return NULL;
7204
7205                 MONO_OBJECT_SETREF (res, type, rt);
7206         } else {
7207                 if (field->type) {
7208                         rt = mono_type_get_object_checked (domain, field->type, error);
7209                         if (!mono_error_ok (error))
7210                                 return NULL;
7211
7212                         MONO_OBJECT_SETREF (res, type, rt);
7213                 }
7214                 res->attrs = mono_field_get_flags (field);
7215         }
7216         CACHE_OBJECT (MonoReflectionField *, field, res, klass);
7217 }
7218
7219 /*
7220  * mono_property_get_object:
7221  * @domain: an app domain
7222  * @klass: a type
7223  * @property: a property
7224  *
7225  * Return an System.Reflection.MonoProperty object representing the property @property
7226  * in class @klass.
7227  */
7228 MonoReflectionProperty*
7229 mono_property_get_object (MonoDomain *domain, MonoClass *klass, MonoProperty *property)
7230 {
7231         MonoError error;
7232         MonoReflectionProperty *result;
7233         result = mono_property_get_object_checked (domain, klass, property, &error);
7234         mono_error_raise_exception (&error);
7235         return result;
7236 }
7237
7238 /**
7239  * mono_property_get_object:
7240  * @domain: an app domain
7241  * @klass: a type
7242  * @property: a property
7243  * @error: set on error
7244  *
7245  * Return an System.Reflection.MonoProperty object representing the property @property
7246  * in class @klass.  On error returns NULL and sets @error.
7247  */
7248 MonoReflectionProperty*
7249 mono_property_get_object_checked (MonoDomain *domain, MonoClass *klass, MonoProperty *property, MonoError *error)
7250 {
7251         MonoReflectionProperty *res;
7252
7253         mono_error_init (error);
7254
7255         CHECK_OBJECT (MonoReflectionProperty *, property, klass);
7256         res = (MonoReflectionProperty *)mono_object_new_checked (domain, mono_class_get_mono_property_class (), error);
7257         if (!res)
7258                 return NULL;
7259         res->klass = klass;
7260         res->property = property;
7261         CACHE_OBJECT (MonoReflectionProperty *, property, res, klass);
7262 }
7263
7264 /*
7265  * mono_event_get_object:
7266  * @domain: an app domain
7267  * @klass: a type
7268  * @event: a event
7269  *
7270  * Return an System.Reflection.MonoEvent object representing the event @event
7271  * in class @klass.
7272  */
7273 MonoReflectionEvent*
7274 mono_event_get_object (MonoDomain *domain, MonoClass *klass, MonoEvent *event)
7275 {
7276         MonoError error;
7277         MonoReflectionEvent *result;
7278         result = mono_event_get_object_checked (domain, klass, event, &error);
7279         mono_error_raise_exception (&error);
7280         return result;
7281 }
7282
7283 /**
7284  * mono_event_get_object_checked:
7285  * @domain: an app domain
7286  * @klass: a type
7287  * @event: a event
7288  * @error: set on error
7289  *
7290  * Return an System.Reflection.MonoEvent object representing the event @event
7291  * in class @klass. On failure sets @error and returns NULL
7292  */
7293 MonoReflectionEvent*
7294 mono_event_get_object_checked (MonoDomain *domain, MonoClass *klass, MonoEvent *event, MonoError *error)
7295 {
7296         MonoReflectionEvent *res;
7297         MonoReflectionMonoEvent *mono_event;
7298
7299         CHECK_OBJECT (MonoReflectionEvent *, event, klass);
7300         mono_event = (MonoReflectionMonoEvent *)mono_object_new_checked (domain, mono_class_get_mono_event_class (), error);
7301         if (!mono_event)
7302                 return NULL;
7303         mono_event->klass = klass;
7304         mono_event->event = event;
7305         res = (MonoReflectionEvent*)mono_event;
7306         CACHE_OBJECT (MonoReflectionEvent *, event, res, klass);
7307 }
7308
7309 /**
7310  * mono_get_reflection_missing_object:
7311  * @domain: Domain where the object lives
7312  *
7313  * Returns the System.Reflection.Missing.Value singleton object
7314  * (of type System.Reflection.Missing).
7315  *
7316  * Used as the value for ParameterInfo.DefaultValue when Optional
7317  * is present
7318  */
7319 static MonoObject *
7320 mono_get_reflection_missing_object (MonoDomain *domain)
7321 {
7322         MonoObject *obj;
7323         static MonoClassField *missing_value_field = NULL;
7324         
7325         if (!missing_value_field) {
7326                 MonoClass *missing_klass;
7327                 missing_klass = mono_class_get_missing_class ();
7328                 mono_class_init (missing_klass);
7329                 missing_value_field = mono_class_get_field_from_name (missing_klass, "Value");
7330                 g_assert (missing_value_field);
7331         }
7332         obj = mono_field_get_value_object (domain, missing_value_field, NULL); 
7333         g_assert (obj);
7334         return obj;
7335 }
7336
7337 static MonoObject*
7338 get_dbnull (MonoDomain *domain, MonoObject **dbnull)
7339 {
7340         if (!*dbnull)
7341                 *dbnull = mono_get_dbnull_object (domain);
7342         return *dbnull;
7343 }
7344
7345 static MonoObject*
7346 get_reflection_missing (MonoDomain *domain, MonoObject **reflection_missing)
7347 {
7348         if (!*reflection_missing)
7349                 *reflection_missing = mono_get_reflection_missing_object (domain);
7350         return *reflection_missing;
7351 }
7352
7353 /*
7354  * mono_param_get_objects:
7355  * @domain: an app domain
7356  * @method: a method
7357  *
7358  * Return an System.Reflection.ParameterInfo array object representing the parameters
7359  * in the method @method.
7360  */
7361 MonoArray*
7362 mono_param_get_objects_internal (MonoDomain *domain, MonoMethod *method, MonoClass *refclass)
7363 {
7364         static MonoClass *System_Reflection_ParameterInfo;
7365         static MonoClass *System_Reflection_ParameterInfo_array;
7366         MonoError error;
7367         MonoArray *res = NULL;
7368         MonoReflectionMethod *member = NULL;
7369         MonoReflectionParameter *param = NULL;
7370         char **names = NULL, **blobs = NULL;
7371         guint32 *types = NULL;
7372         MonoType *type = NULL;
7373         MonoObject *dbnull = NULL;
7374         MonoObject *missing = NULL;
7375         MonoMarshalSpec **mspecs = NULL;
7376         MonoMethodSignature *sig = NULL;
7377         MonoVTable *pinfo_vtable;
7378         MonoReflectionType *rt;
7379         int i;
7380
7381         mono_error_init (&error);
7382         
7383         if (!System_Reflection_ParameterInfo_array) {
7384                 MonoClass *klass;
7385
7386                 klass = mono_class_get_mono_parameter_info_class ();
7387
7388                 mono_memory_barrier ();
7389                 System_Reflection_ParameterInfo = klass; 
7390
7391         
7392                 klass = mono_array_class_get (klass, 1);
7393                 mono_memory_barrier ();
7394                 System_Reflection_ParameterInfo_array = klass;
7395         }
7396
7397         sig = mono_method_signature_checked (method, &error);
7398         if (!mono_error_ok (&error))
7399                 goto leave;
7400
7401         if (!sig->param_count) {
7402                 res = mono_array_new_specific_checked (mono_class_vtable (domain, System_Reflection_ParameterInfo_array), 0, &error);
7403                 if (!res)
7404                         goto leave;
7405
7406                 return res;
7407         }
7408
7409         /* Note: the cache is based on the address of the signature into the method
7410          * since we already cache MethodInfos with the method as keys.
7411          */
7412         CHECK_OBJECT (MonoArray*, &(method->signature), refclass);
7413
7414         member = mono_method_get_object_checked (domain, method, refclass, &error);
7415         if (!member)
7416                 goto leave;
7417         names = g_new (char *, sig->param_count);
7418         mono_method_get_param_names (method, (const char **) names);
7419
7420         mspecs = g_new (MonoMarshalSpec*, sig->param_count + 1);
7421         mono_method_get_marshal_info (method, mspecs);
7422
7423         res = mono_array_new_specific_checked (mono_class_vtable (domain, System_Reflection_ParameterInfo_array), sig->param_count, &error);
7424         if (!res)
7425                 goto leave;
7426
7427         pinfo_vtable = mono_class_vtable (domain, System_Reflection_ParameterInfo);
7428         for (i = 0; i < sig->param_count; ++i) {
7429                 param = (MonoReflectionParameter *) mono_object_new_specific_checked (pinfo_vtable, &error);
7430                 if (!param)
7431                         goto leave;
7432
7433                 rt = mono_type_get_object_checked (domain, sig->params [i], &error);
7434                 if (!rt)
7435                         goto leave;
7436
7437                 MONO_OBJECT_SETREF (param, ClassImpl, rt);
7438
7439                 MONO_OBJECT_SETREF (param, MemberImpl, (MonoObject*)member);
7440
7441                 MONO_OBJECT_SETREF (param, NameImpl, mono_string_new (domain, names [i]));
7442
7443                 param->PositionImpl = i;
7444                 param->AttrsImpl = sig->params [i]->attrs;
7445
7446                 if (!(param->AttrsImpl & PARAM_ATTRIBUTE_HAS_DEFAULT)) {
7447                         if (param->AttrsImpl & PARAM_ATTRIBUTE_OPTIONAL)
7448                                 MONO_OBJECT_SETREF (param, DefaultValueImpl, get_reflection_missing (domain, &missing));
7449                         else
7450                                 MONO_OBJECT_SETREF (param, DefaultValueImpl, get_dbnull (domain, &dbnull));
7451                 } else {
7452
7453                         if (!blobs) {
7454                                 blobs = g_new0 (char *, sig->param_count);
7455                                 types = g_new0 (guint32, sig->param_count);
7456                                 get_default_param_value_blobs (method, blobs, types); 
7457                         }
7458
7459                         /* Build MonoType for the type from the Constant Table */
7460                         if (!type)
7461                                 type = g_new0 (MonoType, 1);
7462                         type->type = (MonoTypeEnum)types [i];
7463                         type->data.klass = NULL;
7464                         if (types [i] == MONO_TYPE_CLASS)
7465                                 type->data.klass = mono_defaults.object_class;
7466                         else if ((sig->params [i]->type == MONO_TYPE_VALUETYPE) && sig->params [i]->data.klass->enumtype) {
7467                                 /* For enums, types [i] contains the base type */
7468
7469                                         type->type = MONO_TYPE_VALUETYPE;
7470                                         type->data.klass = mono_class_from_mono_type (sig->params [i]);
7471                         } else
7472                                 type->data.klass = mono_class_from_mono_type (type);
7473
7474                         MONO_OBJECT_SETREF (param, DefaultValueImpl, mono_get_object_from_blob (domain, type, blobs [i]));
7475
7476                         /* Type in the Constant table is MONO_TYPE_CLASS for nulls */
7477                         if (types [i] != MONO_TYPE_CLASS && !param->DefaultValueImpl) {
7478                                 if (param->AttrsImpl & PARAM_ATTRIBUTE_OPTIONAL)
7479                                         MONO_OBJECT_SETREF (param, DefaultValueImpl, get_reflection_missing (domain, &missing));
7480                                 else
7481                                         MONO_OBJECT_SETREF (param, DefaultValueImpl, get_dbnull (domain, &dbnull));
7482                         }
7483                         
7484                 }
7485
7486                 if (mspecs [i + 1]) {
7487                         MonoReflectionMarshalAsAttribute* mobj;
7488                         mobj = mono_reflection_marshal_as_attribute_from_marshal_spec (domain, method->klass, mspecs [i + 1], &error);
7489                         if (!mobj)
7490                                 goto leave;
7491                         MONO_OBJECT_SETREF (param, MarshalAsImpl, (MonoObject*)mobj);
7492                 }
7493                 
7494                 mono_array_setref (res, i, param);
7495         }
7496
7497 leave:
7498         g_free (names);
7499         g_free (blobs);
7500         g_free (types);
7501         g_free (type);
7502
7503         if (sig) {
7504                 for (i = sig->param_count; i >= 0; i--) {
7505                         if (mspecs [i])
7506                                 mono_metadata_free_marshal_spec (mspecs [i]);
7507                 }
7508         }
7509         g_free (mspecs);
7510
7511         mono_error_raise_exception (&error); /* FIXME don't raise here */
7512         
7513         CACHE_OBJECT (MonoArray *, &(method->signature), res, refclass);
7514 }
7515
7516 MonoArray*
7517 mono_param_get_objects (MonoDomain *domain, MonoMethod *method)
7518 {
7519         return mono_param_get_objects_internal (domain, method, NULL);
7520 }
7521
7522 /*
7523  * mono_method_body_get_object:
7524  * @domain: an app domain
7525  * @method: a method
7526  *
7527  * Return an System.Reflection.MethodBody object representing the method @method.
7528  */
7529 MonoReflectionMethodBody*
7530 mono_method_body_get_object (MonoDomain *domain, MonoMethod *method)
7531 {
7532         MonoError error;
7533         MonoReflectionMethodBody *ret;
7534         MonoMethodHeader *header;
7535         MonoImage *image;
7536         MonoReflectionType *rt;
7537         guint32 method_rva, local_var_sig_token;
7538     char *ptr;
7539         unsigned char format, flags;
7540         int i;
7541
7542         /* for compatibility with .net */
7543     if (method_is_dynamic (method))
7544         mono_raise_exception (mono_get_exception_invalid_operation (NULL));
7545
7546         CHECK_OBJECT (MonoReflectionMethodBody *, method, NULL);
7547
7548         if ((method->flags & METHOD_ATTRIBUTE_PINVOKE_IMPL) ||
7549                 (method->flags & METHOD_ATTRIBUTE_ABSTRACT) ||
7550             (method->iflags & METHOD_IMPL_ATTRIBUTE_INTERNAL_CALL) ||
7551                 (method->klass->image->raw_data && method->klass->image->raw_data [1] != 'Z') ||
7552             (method->iflags & METHOD_IMPL_ATTRIBUTE_RUNTIME))
7553                 return NULL;
7554
7555         image = method->klass->image;
7556         header = mono_method_get_header_checked (method, &error);
7557         mono_error_raise_exception (&error); /* FIXME don't raise here */
7558
7559         if (!image_is_dynamic (image)) {
7560                 /* Obtain local vars signature token */
7561                 method_rva = mono_metadata_decode_row_col (&image->tables [MONO_TABLE_METHOD], mono_metadata_token_index (method->token) - 1, MONO_METHOD_RVA);
7562                 ptr = mono_image_rva_map (image, method_rva);
7563                 flags = *(const unsigned char *) ptr;
7564                 format = flags & METHOD_HEADER_FORMAT_MASK;
7565                 switch (format){
7566                 case METHOD_HEADER_TINY_FORMAT:
7567                         local_var_sig_token = 0;
7568                         break;
7569                 case METHOD_HEADER_FAT_FORMAT:
7570                         ptr += 2;
7571                         ptr += 2;
7572                         ptr += 4;
7573                         local_var_sig_token = read32 (ptr);
7574                         break;
7575                 default:
7576                         g_assert_not_reached ();
7577                 }
7578         } else
7579                 local_var_sig_token = 0; //FIXME
7580
7581         ret = (MonoReflectionMethodBody*)mono_object_new_checked (domain, mono_class_get_method_body_class (), &error);
7582         mono_error_raise_exception (&error); /* FIXME don't raise here */
7583
7584         ret->init_locals = header->init_locals;
7585         ret->max_stack = header->max_stack;
7586         ret->local_var_sig_token = local_var_sig_token;
7587         MONO_OBJECT_SETREF (ret, il, mono_array_new_cached (domain, mono_defaults.byte_class, header->code_size));
7588         memcpy (mono_array_addr (ret->il, guint8, 0), header->code, header->code_size);
7589
7590         /* Locals */
7591         MONO_OBJECT_SETREF (ret, locals, mono_array_new_cached (domain, mono_class_get_local_variable_info_class (), header->num_locals));
7592         for (i = 0; i < header->num_locals; ++i) {
7593                 MonoReflectionLocalVariableInfo *info = (MonoReflectionLocalVariableInfo*)mono_object_new_checked (domain, mono_class_get_local_variable_info_class (), &error);
7594                 mono_error_raise_exception (&error); /* FIXME don't raise here */
7595
7596                 rt = mono_type_get_object_checked (domain, header->locals [i], &error);
7597                 mono_error_raise_exception (&error); /* FIXME don't raise here */
7598
7599                 MONO_OBJECT_SETREF (info, local_type, rt);
7600
7601                 info->is_pinned = header->locals [i]->pinned;
7602                 info->local_index = i;
7603                 mono_array_setref (ret->locals, i, info);
7604         }
7605
7606         /* Exceptions */
7607         MONO_OBJECT_SETREF (ret, clauses, mono_array_new_cached (domain, mono_class_get_exception_handling_clause_class (), header->num_clauses));
7608         for (i = 0; i < header->num_clauses; ++i) {
7609                 MonoReflectionExceptionHandlingClause *info = (MonoReflectionExceptionHandlingClause*)mono_object_new_checked (domain, mono_class_get_exception_handling_clause_class (), &error);
7610                 mono_error_raise_exception (&error); /* FIXME don't raise here */
7611                 MonoExceptionClause *clause = &header->clauses [i];
7612
7613                 info->flags = clause->flags;
7614                 info->try_offset = clause->try_offset;
7615                 info->try_length = clause->try_len;
7616                 info->handler_offset = clause->handler_offset;
7617                 info->handler_length = clause->handler_len;
7618                 if (clause->flags == MONO_EXCEPTION_CLAUSE_FILTER)
7619                         info->filter_offset = clause->data.filter_offset;
7620                 else if (clause->data.catch_class) {
7621                         rt = mono_type_get_object_checked (mono_domain_get (), &clause->data.catch_class->byval_arg, &error);
7622                         mono_error_raise_exception (&error); /* FIXME don't raise here */
7623
7624                         MONO_OBJECT_SETREF (info, catch_type, rt);
7625                 }
7626
7627                 mono_array_setref (ret->clauses, i, info);
7628         }
7629
7630         mono_metadata_free_mh (header);
7631         CACHE_OBJECT (MonoReflectionMethodBody *, method, ret, NULL);
7632         return ret;
7633 }
7634
7635 /**
7636  * mono_get_dbnull_object:
7637  * @domain: Domain where the object lives
7638  *
7639  * Returns the System.DBNull.Value singleton object
7640  *
7641  * Used as the value for ParameterInfo.DefaultValue 
7642  */
7643 MonoObject *
7644 mono_get_dbnull_object (MonoDomain *domain)
7645 {
7646         MonoObject *obj;
7647         static MonoClassField *dbnull_value_field = NULL;
7648         
7649         if (!dbnull_value_field) {
7650                 MonoClass *dbnull_klass;
7651                 dbnull_klass = mono_class_get_dbnull_class ();
7652                 dbnull_value_field = mono_class_get_field_from_name (dbnull_klass, "Value");
7653                 g_assert (dbnull_value_field);
7654         }
7655         obj = mono_field_get_value_object (domain, dbnull_value_field, NULL); 
7656         g_assert (obj);
7657         return obj;
7658 }
7659
7660 static void
7661 get_default_param_value_blobs (MonoMethod *method, char **blobs, guint32 *types)
7662 {
7663         guint32 param_index, i, lastp, crow = 0;
7664         guint32 param_cols [MONO_PARAM_SIZE], const_cols [MONO_CONSTANT_SIZE];
7665         gint32 idx;
7666
7667         MonoClass *klass = method->klass;
7668         MonoImage *image = klass->image;
7669         MonoMethodSignature *methodsig = mono_method_signature (method);
7670
7671         MonoTableInfo *constt;
7672         MonoTableInfo *methodt;
7673         MonoTableInfo *paramt;
7674
7675         if (!methodsig->param_count)
7676                 return;
7677
7678         mono_class_init (klass);
7679
7680         if (image_is_dynamic (klass->image)) {
7681                 MonoReflectionMethodAux *aux;
7682                 if (method->is_inflated)
7683                         method = ((MonoMethodInflated*)method)->declaring;
7684                 aux = (MonoReflectionMethodAux *)g_hash_table_lookup (((MonoDynamicImage*)method->klass->image)->method_aux_hash, method);
7685                 if (aux && aux->param_defaults) {
7686                         memcpy (blobs, &(aux->param_defaults [1]), methodsig->param_count * sizeof (char*));
7687                         memcpy (types, &(aux->param_default_types [1]), methodsig->param_count * sizeof (guint32));
7688                 }
7689                 return;
7690         }
7691
7692         methodt = &klass->image->tables [MONO_TABLE_METHOD];
7693         paramt = &klass->image->tables [MONO_TABLE_PARAM];
7694         constt = &image->tables [MONO_TABLE_CONSTANT];
7695
7696         idx = mono_method_get_index (method) - 1;
7697         g_assert (idx != -1);
7698
7699         param_index = mono_metadata_decode_row_col (methodt, idx, MONO_METHOD_PARAMLIST);
7700         if (idx + 1 < methodt->rows)
7701                 lastp = mono_metadata_decode_row_col (methodt, idx + 1, MONO_METHOD_PARAMLIST);
7702         else
7703                 lastp = paramt->rows + 1;
7704
7705         for (i = param_index; i < lastp; ++i) {
7706                 guint32 paramseq;
7707
7708                 mono_metadata_decode_row (paramt, i - 1, param_cols, MONO_PARAM_SIZE);
7709                 paramseq = param_cols [MONO_PARAM_SEQUENCE];
7710
7711                 if (!(param_cols [MONO_PARAM_FLAGS] & PARAM_ATTRIBUTE_HAS_DEFAULT))
7712                         continue;
7713
7714                 crow = mono_metadata_get_constant_index (image, MONO_TOKEN_PARAM_DEF | i, crow + 1);
7715                 if (!crow) {
7716                         continue;
7717                 }
7718         
7719                 mono_metadata_decode_row (constt, crow - 1, const_cols, MONO_CONSTANT_SIZE);
7720                 blobs [paramseq - 1] = (char *)mono_metadata_blob_heap (image, const_cols [MONO_CONSTANT_VALUE]);
7721                 types [paramseq - 1] = const_cols [MONO_CONSTANT_TYPE];
7722         }
7723
7724         return;
7725 }
7726
7727 MonoObject *
7728 mono_get_object_from_blob (MonoDomain *domain, MonoType *type, const char *blob)
7729 {
7730         MonoError error;
7731         void *retval;
7732         MonoClass *klass;
7733         MonoObject *object;
7734         MonoType *basetype = type;
7735
7736         if (!blob)
7737                 return NULL;
7738         
7739         klass = mono_class_from_mono_type (type);
7740         if (klass->valuetype) {
7741                 object = mono_object_new_checked (domain, klass, &error);
7742                 mono_error_raise_exception (&error); /* FIXME don't raise here */
7743                 retval = ((gchar *) object + sizeof (MonoObject));
7744                 if (klass->enumtype)
7745                         basetype = mono_class_enum_basetype (klass);
7746         } else {
7747                 retval = &object;
7748         }
7749                         
7750         if (!mono_get_constant_value_from_blob (domain, basetype->type,  blob, retval))
7751                 return object;
7752         else
7753                 return NULL;
7754 }
7755
7756 static int
7757 assembly_name_to_aname (MonoAssemblyName *assembly, char *p) {
7758         int found_sep;
7759         char *s;
7760         gboolean quoted = FALSE;
7761
7762         memset (assembly, 0, sizeof (MonoAssemblyName));
7763         assembly->culture = "";
7764         memset (assembly->public_key_token, 0, MONO_PUBLIC_KEY_TOKEN_LENGTH);
7765
7766         if (*p == '"') {
7767                 quoted = TRUE;
7768                 p++;
7769         }
7770         assembly->name = p;
7771         while (*p && (isalnum (*p) || *p == '.' || *p == '-' || *p == '_' || *p == '$' || *p == '@' || g_ascii_isspace (*p)))
7772                 p++;
7773         if (quoted) {
7774                 if (*p != '"')
7775                         return 1;
7776                 *p = 0;
7777                 p++;
7778         }
7779         if (*p != ',')
7780                 return 1;
7781         *p = 0;
7782         /* Remove trailing whitespace */
7783         s = p - 1;
7784         while (*s && g_ascii_isspace (*s))
7785                 *s-- = 0;
7786         p ++;
7787         while (g_ascii_isspace (*p))
7788                 p++;
7789         while (*p) {
7790                 if (*p == 'V' && g_ascii_strncasecmp (p, "Version=", 8) == 0) {
7791                         p += 8;
7792                         assembly->major = strtoul (p, &s, 10);
7793                         if (s == p || *s != '.')
7794                                 return 1;
7795                         p = ++s;
7796                         assembly->minor = strtoul (p, &s, 10);
7797                         if (s == p || *s != '.')
7798                                 return 1;
7799                         p = ++s;
7800                         assembly->build = strtoul (p, &s, 10);
7801                         if (s == p || *s != '.')
7802                                 return 1;
7803                         p = ++s;
7804                         assembly->revision = strtoul (p, &s, 10);
7805                         if (s == p)
7806                                 return 1;
7807                         p = s;
7808                 } else if (*p == 'C' && g_ascii_strncasecmp (p, "Culture=", 8) == 0) {
7809                         p += 8;
7810                         if (g_ascii_strncasecmp (p, "neutral", 7) == 0) {
7811                                 assembly->culture = "";
7812                                 p += 7;
7813                         } else {
7814                                 assembly->culture = p;
7815                                 while (*p && *p != ',') {
7816                                         p++;
7817                                 }
7818                         }
7819                 } else if (*p == 'P' && g_ascii_strncasecmp (p, "PublicKeyToken=", 15) == 0) {
7820                         p += 15;
7821                         if (strncmp (p, "null", 4) == 0) {
7822                                 p += 4;
7823                         } else {
7824                                 int len;
7825                                 gchar *start = p;
7826                                 while (*p && *p != ',') {
7827                                         p++;
7828                                 }
7829                                 len = (p - start + 1);
7830                                 if (len > MONO_PUBLIC_KEY_TOKEN_LENGTH)
7831                                         len = MONO_PUBLIC_KEY_TOKEN_LENGTH;
7832                                 g_strlcpy ((char*)assembly->public_key_token, start, len);
7833                         }
7834                 } else {
7835                         while (*p && *p != ',')
7836                                 p++;
7837                 }
7838                 found_sep = 0;
7839                 while (g_ascii_isspace (*p) || *p == ',') {
7840                         *p++ = 0;
7841                         found_sep = 1;
7842                         continue;
7843                 }
7844                 /* failed */
7845                 if (!found_sep)
7846                         return 1;
7847         }
7848
7849         return 0;
7850 }
7851
7852 /*
7853  * mono_reflection_parse_type:
7854  * @name: type name
7855  *
7856  * Parse a type name as accepted by the GetType () method and output the info
7857  * extracted in the info structure.
7858  * the name param will be mangled, so, make a copy before passing it to this function.
7859  * The fields in info will be valid until the memory pointed to by name is valid.
7860  *
7861  * See also mono_type_get_name () below.
7862  *
7863  * Returns: 0 on parse error.
7864  */
7865 static int
7866 _mono_reflection_parse_type (char *name, char **endptr, gboolean is_recursed,
7867                              MonoTypeNameParse *info)
7868 {
7869         char *start, *p, *w, *last_point, *startn;
7870         int in_modifiers = 0;
7871         int isbyref = 0, rank = 0, isptr = 0;
7872
7873         start = p = w = name;
7874
7875         //FIXME could we just zero the whole struct? memset (&info, 0, sizeof (MonoTypeNameParse))
7876         memset (&info->assembly, 0, sizeof (MonoAssemblyName));
7877         info->name = info->name_space = NULL;
7878         info->nested = NULL;
7879         info->modifiers = NULL;
7880         info->type_arguments = NULL;
7881
7882         /* last_point separates the namespace from the name */
7883         last_point = NULL;
7884         /* Skips spaces */
7885         while (*p == ' ') p++, start++, w++, name++;
7886
7887         while (*p) {
7888                 switch (*p) {
7889                 case '+':
7890                         *p = 0; /* NULL terminate the name */
7891                         startn = p + 1;
7892                         info->nested = g_list_append (info->nested, startn);
7893                         /* we have parsed the nesting namespace + name */
7894                         if (info->name)
7895                                 break;
7896                         if (last_point) {
7897                                 info->name_space = start;
7898                                 *last_point = 0;
7899                                 info->name = last_point + 1;
7900                         } else {
7901                                 info->name_space = (char *)"";
7902                                 info->name = start;
7903                         }
7904                         break;
7905                 case '.':
7906                         last_point = p;
7907                         break;
7908                 case '\\':
7909                         ++p;
7910                         break;
7911                 case '&':
7912                 case '*':
7913                 case '[':
7914                 case ',':
7915                 case ']':
7916                         in_modifiers = 1;
7917                         break;
7918                 default:
7919                         break;
7920                 }
7921                 if (in_modifiers)
7922                         break;
7923                 // *w++ = *p++;
7924                 p++;
7925         }
7926         
7927         if (!info->name) {
7928                 if (last_point) {
7929                         info->name_space = start;
7930                         *last_point = 0;
7931                         info->name = last_point + 1;
7932                 } else {
7933                         info->name_space = (char *)"";
7934                         info->name = start;
7935                 }
7936         }
7937         while (*p) {
7938                 switch (*p) {
7939                 case '&':
7940                         if (isbyref) /* only one level allowed by the spec */
7941                                 return 0;
7942                         isbyref = 1;
7943                         isptr = 0;
7944                         info->modifiers = g_list_append (info->modifiers, GUINT_TO_POINTER (0));
7945                         *p++ = 0;
7946                         break;
7947                 case '*':
7948                         if (isbyref) /* pointer to ref not okay */
7949                                 return 0;
7950                         info->modifiers = g_list_append (info->modifiers, GUINT_TO_POINTER (-1));
7951                         isptr = 1;
7952                         *p++ = 0;
7953                         break;
7954                 case '[':
7955                         if (isbyref) /* array of ref and generic ref are not okay */
7956                                 return 0;
7957                         //Decide if it's an array of a generic argument list
7958                         *p++ = 0;
7959
7960                         if (!*p) //XXX test
7961                                 return 0;
7962                         if (*p  == ',' || *p == '*' || *p == ']') { //array
7963                                 isptr = 0;
7964                                 rank = 1;
7965                                 while (*p) {
7966                                         if (*p == ']')
7967                                                 break;
7968                                         if (*p == ',')
7969                                                 rank++;
7970                                         else if (*p == '*') /* '*' means unknown lower bound */
7971                                                 info->modifiers = g_list_append (info->modifiers, GUINT_TO_POINTER (-2));
7972                                         else
7973                                                 return 0;
7974                                         ++p;
7975                                 }
7976                                 if (*p++ != ']')
7977                                         return 0;
7978                                 info->modifiers = g_list_append (info->modifiers, GUINT_TO_POINTER (rank));
7979                         } else {
7980                                 if (rank || isptr) /* generic args after array spec or ptr*/ //XXX test
7981                                         return 0;
7982                                 isptr = 0;
7983                                 info->type_arguments = g_ptr_array_new ();
7984                                 while (*p) {
7985                                         MonoTypeNameParse *subinfo = g_new0 (MonoTypeNameParse, 1);
7986                                         gboolean fqname = FALSE;
7987
7988                                         g_ptr_array_add (info->type_arguments, subinfo);
7989
7990                                         while (*p == ' ') p++;
7991                                         if (*p == '[') {
7992                                                 p++;
7993                                                 fqname = TRUE;
7994                                         }
7995
7996                                         if (!_mono_reflection_parse_type (p, &p, TRUE, subinfo))
7997                                                 return 0;
7998
7999                                         /*MS is lenient on [] delimited parameters that aren't fqn - and F# uses them.*/
8000                                         if (fqname && (*p != ']')) {
8001                                                 char *aname;
8002
8003                                                 if (*p != ',')
8004                                                         return 0;
8005                                                 *p++ = 0;
8006
8007                                                 aname = p;
8008                                                 while (*p && (*p != ']'))
8009                                                         p++;
8010
8011                                                 if (*p != ']')
8012                                                         return 0;
8013
8014                                                 *p++ = 0;
8015                                                 while (*aname) {
8016                                                         if (g_ascii_isspace (*aname)) {
8017                                                                 ++aname;
8018                                                                 continue;
8019                                                         }
8020                                                         break;
8021                                                 }
8022                                                 if (!*aname ||
8023                                                     !assembly_name_to_aname (&subinfo->assembly, aname))
8024                                                         return 0;
8025                                         } else if (fqname && (*p == ']')) {
8026                                                 *p++ = 0;
8027                                         }
8028                                         if (*p == ']') {
8029                                                 *p++ = 0;
8030                                                 break;
8031                                         } else if (!*p) {
8032                                                 return 0;
8033                                         }
8034                                         *p++ = 0;
8035                                 }
8036                         }
8037                         break;
8038                 case ']':
8039                         if (is_recursed)
8040                                 goto end;
8041                         return 0;
8042                 case ',':
8043                         if (is_recursed)
8044                                 goto end;
8045                         *p++ = 0;
8046                         while (*p) {
8047                                 if (g_ascii_isspace (*p)) {
8048                                         ++p;
8049                                         continue;
8050                                 }
8051                                 break;
8052                         }
8053                         if (!*p)
8054                                 return 0; /* missing assembly name */
8055                         if (!assembly_name_to_aname (&info->assembly, p))
8056                                 return 0;
8057                         break;
8058                 default:
8059                         return 0;
8060                 }
8061                 if (info->assembly.name)
8062                         break;
8063         }
8064         // *w = 0; /* terminate class name */
8065  end:
8066         if (!info->name || !*info->name)
8067                 return 0;
8068         if (endptr)
8069                 *endptr = p;
8070         /* add other consistency checks */
8071         return 1;
8072 }
8073
8074
8075 /**
8076  * mono_identifier_unescape_type_name_chars:
8077  * @identifier: the display name of a mono type
8078  *
8079  * Returns:
8080  *  The name in internal form, that is without escaping backslashes.
8081  *
8082  *  The string is modified in place!
8083  */
8084 char*
8085 mono_identifier_unescape_type_name_chars(char* identifier)
8086 {
8087         char *w, *r;
8088         if (!identifier)
8089                 return NULL;
8090         for (w = r = identifier; *r != 0; r++)
8091         {
8092                 char c = *r;
8093                 if (c == '\\') {
8094                         r++;
8095                         if (*r == 0)
8096                                 break;
8097                         c = *r;
8098                 }
8099                 *w = c;
8100                 w++;
8101         }
8102         if (w != r)
8103                 *w = 0;
8104         return identifier;
8105 }
8106
8107 void
8108 mono_identifier_unescape_info (MonoTypeNameParse* info);
8109
8110 static void
8111 unescape_each_type_argument(void* data, void* user_data)
8112 {
8113         MonoTypeNameParse* info = (MonoTypeNameParse*)data;
8114         mono_identifier_unescape_info (info);
8115 }
8116
8117 static void
8118 unescape_each_nested_name (void* data, void* user_data)
8119 {
8120         char* nested_name = (char*) data;
8121         mono_identifier_unescape_type_name_chars(nested_name);
8122 }
8123
8124 /**
8125  * mono_identifier_unescape_info:
8126  *
8127  * @info: a parsed display form of an (optionally assembly qualified) full type name.
8128  *
8129  * Returns: nothing.
8130  *
8131  * Destructively updates the info by unescaping the identifiers that
8132  * comprise the type namespace, name, nested types (if any) and
8133  * generic type arguments (if any).
8134  *
8135  * The resulting info has the names in internal form.
8136  *
8137  */
8138 void
8139 mono_identifier_unescape_info (MonoTypeNameParse *info)
8140 {
8141         if (!info)
8142                 return;
8143         mono_identifier_unescape_type_name_chars(info->name_space);
8144         mono_identifier_unescape_type_name_chars(info->name);
8145         // but don't escape info->assembly
8146         if (info->type_arguments)
8147                 g_ptr_array_foreach(info->type_arguments, &unescape_each_type_argument, NULL);
8148         if (info->nested)
8149                 g_list_foreach(info->nested, &unescape_each_nested_name, NULL);
8150 }
8151
8152 int
8153 mono_reflection_parse_type (char *name, MonoTypeNameParse *info)
8154 {
8155         int ok = _mono_reflection_parse_type (name, NULL, FALSE, info);
8156         if (ok) {
8157                 mono_identifier_unescape_info (info);
8158         }
8159         return ok;
8160 }
8161
8162 static MonoType*
8163 _mono_reflection_get_type_from_info (MonoTypeNameParse *info, MonoImage *image, gboolean ignorecase)
8164 {
8165         gboolean type_resolve = FALSE;
8166         MonoType *type;
8167         MonoImage *rootimage = image;
8168
8169         if (info->assembly.name) {
8170                 MonoAssembly *assembly = mono_assembly_loaded (&info->assembly);
8171                 if (!assembly && image && image->assembly && mono_assembly_names_equal (&info->assembly, &image->assembly->aname))
8172                         /* 
8173                          * This could happen in the AOT compiler case when the search hook is not
8174                          * installed.
8175                          */
8176                         assembly = image->assembly;
8177                 if (!assembly) {
8178                         /* then we must load the assembly ourselve - see #60439 */
8179                         assembly = mono_assembly_load (&info->assembly, image->assembly->basedir, NULL);
8180                         if (!assembly)
8181                                 return NULL;
8182                 }
8183                 image = assembly->image;
8184         } else if (!image) {
8185                 image = mono_defaults.corlib;
8186         }
8187
8188         type = mono_reflection_get_type_with_rootimage (rootimage, image, info, ignorecase, &type_resolve);
8189         if (type == NULL && !info->assembly.name && image != mono_defaults.corlib) {
8190                 image = mono_defaults.corlib;
8191                 type = mono_reflection_get_type_with_rootimage (rootimage, image, info, ignorecase, &type_resolve);
8192         }
8193
8194         return type;
8195 }
8196
8197 /**
8198  * mono_reflection_get_type_internal:
8199  *
8200  * Returns: may return NULL on success, sets error on failure.
8201  */
8202 static MonoType*
8203 mono_reflection_get_type_internal (MonoImage *rootimage, MonoImage* image, MonoTypeNameParse *info, gboolean ignorecase, MonoError *error)
8204 {
8205         MonoClass *klass;
8206         GList *mod;
8207         int modval;
8208         gboolean bounded = FALSE;
8209         
8210         mono_error_init (error);
8211         if (!image)
8212                 image = mono_defaults.corlib;
8213
8214         if (!rootimage)
8215                 rootimage = mono_defaults.corlib;
8216
8217         if (ignorecase)
8218                 klass = mono_class_from_name_case_checked (image, info->name_space, info->name, error);
8219         else
8220                 klass = mono_class_from_name_checked (image, info->name_space, info->name, error);
8221
8222         if (!klass)
8223                 return NULL;
8224
8225         for (mod = info->nested; mod; mod = mod->next) {
8226                 gpointer iter = NULL;
8227                 MonoClass *parent;
8228
8229                 parent = klass;
8230                 mono_class_init (parent);
8231
8232                 while ((klass = mono_class_get_nested_types (parent, &iter))) {
8233                         char *lastp;
8234                         char *nested_name, *nested_nspace;
8235                         gboolean match = TRUE;
8236
8237                         lastp = strrchr ((const char *)mod->data, '.');
8238                         if (lastp) {
8239                                 /* Nested classes can have namespaces */
8240                                 int nspace_len;
8241
8242                                 nested_name = g_strdup (lastp + 1);
8243                                 nspace_len = lastp - (char*)mod->data;
8244                                 nested_nspace = (char *)g_malloc (nspace_len + 1);
8245                                 memcpy (nested_nspace, mod->data, nspace_len);
8246                                 nested_nspace [nspace_len] = '\0';
8247
8248                         } else {
8249                                 nested_name = (char *)mod->data;
8250                                 nested_nspace = NULL;
8251                         }
8252
8253                         if (nested_nspace) {
8254                                 if (ignorecase) {
8255                                         if (!(klass->name_space && mono_utf8_strcasecmp (klass->name_space, nested_nspace) == 0))
8256                                                 match = FALSE;
8257                                 } else {
8258                                         if (!(klass->name_space && strcmp (klass->name_space, nested_nspace) == 0))
8259                                                 match = FALSE;
8260                                 }
8261                         }
8262                         if (match) {
8263                                 if (ignorecase) {
8264                                         if (mono_utf8_strcasecmp (klass->name, nested_name) != 0)
8265                                                 match = FALSE;
8266                                 } else {
8267                                         if (strcmp (klass->name, nested_name) != 0)
8268                                                 match = FALSE;
8269                                 }
8270                         }
8271                         if (lastp) {
8272                                 g_free (nested_name);
8273                                 g_free (nested_nspace);
8274                         }
8275                         if (match)
8276                                 break;
8277                 }
8278
8279                 if (!klass)
8280                         break;
8281         }
8282         if (!klass)
8283                 return NULL;
8284
8285         if (info->type_arguments) {
8286                 MonoType **type_args = g_new0 (MonoType *, info->type_arguments->len);
8287                 MonoReflectionType *the_type;
8288                 MonoType *instance;
8289                 int i;
8290
8291                 for (i = 0; i < info->type_arguments->len; i++) {
8292                         MonoTypeNameParse *subinfo = (MonoTypeNameParse *)g_ptr_array_index (info->type_arguments, i);
8293
8294                         type_args [i] = _mono_reflection_get_type_from_info (subinfo, rootimage, ignorecase);
8295                         if (!type_args [i]) {
8296                                 g_free (type_args);
8297                                 return NULL;
8298                         }
8299                 }
8300
8301                 the_type = mono_type_get_object_checked (mono_domain_get (), &klass->byval_arg, error);
8302                 if (!the_type)
8303                         return NULL;
8304
8305                 instance = mono_reflection_bind_generic_parameters (
8306                         the_type, info->type_arguments->len, type_args);
8307
8308                 g_free (type_args);
8309                 if (!instance)
8310                         return NULL;
8311
8312                 klass = mono_class_from_mono_type (instance);
8313         }
8314
8315         for (mod = info->modifiers; mod; mod = mod->next) {
8316                 modval = GPOINTER_TO_UINT (mod->data);
8317                 if (!modval) { /* byref: must be last modifier */
8318                         return &klass->this_arg;
8319                 } else if (modval == -1) {
8320                         klass = mono_ptr_class_get (&klass->byval_arg);
8321                 } else if (modval == -2) {
8322                         bounded = TRUE;
8323                 } else { /* array rank */
8324                         klass = mono_bounded_array_class_get (klass, modval, bounded);
8325                 }
8326         }
8327
8328         return &klass->byval_arg;
8329 }
8330
8331 /*
8332  * mono_reflection_get_type:
8333  * @image: a metadata context
8334  * @info: type description structure
8335  * @ignorecase: flag for case-insensitive string compares
8336  * @type_resolve: whenever type resolve was already tried
8337  *
8338  * Build a MonoType from the type description in @info.
8339  * 
8340  */
8341
8342 MonoType*
8343 mono_reflection_get_type (MonoImage* image, MonoTypeNameParse *info, gboolean ignorecase, gboolean *type_resolve) {
8344         return mono_reflection_get_type_with_rootimage(image, image, info, ignorecase, type_resolve);
8345 }
8346
8347 static MonoType*
8348 mono_reflection_get_type_internal_dynamic (MonoImage *rootimage, MonoAssembly *assembly, MonoTypeNameParse *info, gboolean ignorecase, MonoError *error)
8349 {
8350         MonoReflectionAssemblyBuilder *abuilder;
8351         MonoType *type;
8352         int i;
8353
8354         mono_error_init (error);
8355         g_assert (assembly_is_dynamic (assembly));
8356         abuilder = (MonoReflectionAssemblyBuilder*)mono_assembly_get_object_checked (((MonoDynamicAssembly*)assembly)->domain, assembly, error);
8357         if (!abuilder)
8358                 return NULL;
8359
8360         /* Enumerate all modules */
8361
8362         type = NULL;
8363         if (abuilder->modules) {
8364                 for (i = 0; i < mono_array_length (abuilder->modules); ++i) {
8365                         MonoReflectionModuleBuilder *mb = mono_array_get (abuilder->modules, MonoReflectionModuleBuilder*, i);
8366                         type = mono_reflection_get_type_internal (rootimage, &mb->dynamic_image->image, info, ignorecase, error);
8367                         if (type)
8368                                 break;
8369                         if (!mono_error_ok (error))
8370                                 return NULL;
8371                 }
8372         }
8373
8374         if (!type && abuilder->loaded_modules) {
8375                 for (i = 0; i < mono_array_length (abuilder->loaded_modules); ++i) {
8376                         MonoReflectionModule *mod = mono_array_get (abuilder->loaded_modules, MonoReflectionModule*, i);
8377                         type = mono_reflection_get_type_internal (rootimage, mod->image, info, ignorecase, error);
8378                         if (type)
8379                                 break;
8380                         if (!mono_error_ok (error))
8381                                 return NULL;
8382                 }
8383         }
8384
8385         return type;
8386 }
8387         
8388 MonoType*
8389 mono_reflection_get_type_with_rootimage (MonoImage *rootimage, MonoImage* image, MonoTypeNameParse *info, gboolean ignorecase, gboolean *type_resolve)
8390 {
8391         MonoError error;
8392         MonoType *type;
8393         MonoReflectionAssembly *assembly;
8394         GString *fullName;
8395         GList *mod;
8396
8397         if (image && image_is_dynamic (image))
8398                 type = mono_reflection_get_type_internal_dynamic (rootimage, image->assembly, info, ignorecase, &error);
8399         else {
8400                 type = mono_reflection_get_type_internal (rootimage, image, info, ignorecase, &error);
8401         }
8402         if (!mono_error_ok (&error))
8403                 mono_error_raise_exception (&error); /* FIXME don't raise here */
8404
8405         if (type)
8406                 return type;
8407         if (!mono_domain_has_type_resolve (mono_domain_get ()))
8408                 return NULL;
8409
8410         if (type_resolve) {
8411                 if (*type_resolve) 
8412                         return NULL;
8413                 else
8414                         *type_resolve = TRUE;
8415         }
8416         
8417         /* Reconstruct the type name */
8418         fullName = g_string_new ("");
8419         if (info->name_space && (info->name_space [0] != '\0'))
8420                 g_string_printf (fullName, "%s.%s", info->name_space, info->name);
8421         else
8422                 g_string_printf (fullName, "%s", info->name);
8423         for (mod = info->nested; mod; mod = mod->next)
8424                 g_string_append_printf (fullName, "+%s", (char*)mod->data);
8425
8426         assembly = mono_domain_try_type_resolve_checked ( mono_domain_get (), fullName->str, NULL, &error);
8427         mono_error_raise_exception (&error); /* FIXME don't raise here */
8428
8429         if (assembly) {
8430                 if (assembly_is_dynamic (assembly->assembly))
8431                         type = mono_reflection_get_type_internal_dynamic (rootimage, assembly->assembly,
8432                                                                           info, ignorecase, &error);
8433                 else
8434                         type = mono_reflection_get_type_internal (rootimage, assembly->assembly->image, 
8435                                                                   info, ignorecase, &error);
8436         }
8437         g_string_free (fullName, TRUE);
8438         if (!mono_error_ok (&error))
8439                 mono_error_raise_exception (&error); /* FIXME don't raise here */
8440         return type;
8441 }
8442
8443 void
8444 mono_reflection_free_type_info (MonoTypeNameParse *info)
8445 {
8446         g_list_free (info->modifiers);
8447         g_list_free (info->nested);
8448
8449         if (info->type_arguments) {
8450                 int i;
8451
8452                 for (i = 0; i < info->type_arguments->len; i++) {
8453                         MonoTypeNameParse *subinfo = (MonoTypeNameParse *)g_ptr_array_index (info->type_arguments, i);
8454
8455                         mono_reflection_free_type_info (subinfo);
8456                         /*We free the subinfo since it is allocated by _mono_reflection_parse_type*/
8457                         g_free (subinfo);
8458                 }
8459
8460                 g_ptr_array_free (info->type_arguments, TRUE);
8461         }
8462 }
8463
8464 /*
8465  * mono_reflection_type_from_name:
8466  * @name: type name.
8467  * @image: a metadata context (can be NULL).
8468  *
8469  * Retrieves a MonoType from its @name. If the name is not fully qualified,
8470  * it defaults to get the type from @image or, if @image is NULL or loading
8471  * from it fails, uses corlib.
8472  * 
8473  */
8474 MonoType*
8475 mono_reflection_type_from_name (char *name, MonoImage *image)
8476 {
8477         MonoType *type = NULL;
8478         MonoTypeNameParse info;
8479         char *tmp;
8480
8481         /* Make a copy since parse_type modifies its argument */
8482         tmp = g_strdup (name);
8483         
8484         /*g_print ("requested type %s\n", str);*/
8485         if (mono_reflection_parse_type (tmp, &info)) {
8486                 type = _mono_reflection_get_type_from_info (&info, image, FALSE);
8487         }
8488
8489         g_free (tmp);
8490         mono_reflection_free_type_info (&info);
8491         return type;
8492 }
8493
8494 /*
8495  * mono_reflection_get_token:
8496  *
8497  *   Return the metadata token of OBJ which should be an object
8498  * representing a metadata element.
8499  */
8500 guint32
8501 mono_reflection_get_token (MonoObject *obj)
8502 {
8503         MonoClass *klass;
8504         guint32 token = 0;
8505
8506         klass = obj->vtable->klass;
8507
8508         if (strcmp (klass->name, "MethodBuilder") == 0) {
8509                 MonoReflectionMethodBuilder *mb = (MonoReflectionMethodBuilder *)obj;
8510
8511                 token = mb->table_idx | MONO_TOKEN_METHOD_DEF;
8512         } else if (strcmp (klass->name, "ConstructorBuilder") == 0) {
8513                 MonoReflectionCtorBuilder *mb = (MonoReflectionCtorBuilder *)obj;
8514
8515                 token = mb->table_idx | MONO_TOKEN_METHOD_DEF;
8516         } else if (strcmp (klass->name, "FieldBuilder") == 0) {
8517                 MonoReflectionFieldBuilder *fb = (MonoReflectionFieldBuilder *)obj;
8518
8519                 token = fb->table_idx | MONO_TOKEN_FIELD_DEF;
8520         } else if (strcmp (klass->name, "TypeBuilder") == 0) {
8521                 MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder *)obj;
8522                 token = tb->table_idx | MONO_TOKEN_TYPE_DEF;
8523         } else if (strcmp (klass->name, "MonoType") == 0) {
8524                 MonoType *type = mono_reflection_type_get_handle ((MonoReflectionType*)obj);
8525                 MonoClass *mc = mono_class_from_mono_type (type);
8526                 if (!mono_class_init (mc))
8527                         mono_raise_exception (mono_class_get_exception_for_failure (mc));
8528
8529                 token = mc->type_token;
8530         } else if (strcmp (klass->name, "MonoCMethod") == 0 ||
8531                    strcmp (klass->name, "MonoMethod") == 0 ||
8532                    strcmp (klass->name, "MonoGenericMethod") == 0 ||
8533                    strcmp (klass->name, "MonoGenericCMethod") == 0) {
8534                 MonoReflectionMethod *m = (MonoReflectionMethod *)obj;
8535                 if (m->method->is_inflated) {
8536                         MonoMethodInflated *inflated = (MonoMethodInflated *) m->method;
8537                         return inflated->declaring->token;
8538                 } else {
8539                         token = m->method->token;
8540                 }
8541         } else if (strcmp (klass->name, "MonoField") == 0) {
8542                 MonoReflectionField *f = (MonoReflectionField*)obj;
8543
8544                 if (is_field_on_inst (f->field)) {
8545                         MonoDynamicGenericClass *dgclass = (MonoDynamicGenericClass*)f->field->parent->generic_class;
8546
8547                         if (f->field >= dgclass->fields && f->field < dgclass->fields + dgclass->count_fields) {
8548                                 int field_index = f->field - dgclass->fields;
8549                                 MonoObject *obj;
8550
8551                                 g_assert (field_index >= 0 && field_index < dgclass->count_fields);
8552                                 obj = dgclass->field_objects [field_index];
8553                                 return mono_reflection_get_token (obj);
8554                         }
8555                 }
8556                 token = mono_class_get_field_token (f->field);
8557         } else if (strcmp (klass->name, "MonoProperty") == 0) {
8558                 MonoReflectionProperty *p = (MonoReflectionProperty*)obj;
8559
8560                 token = mono_class_get_property_token (p->property);
8561         } else if (strcmp (klass->name, "MonoEvent") == 0) {
8562                 MonoReflectionMonoEvent *p = (MonoReflectionMonoEvent*)obj;
8563
8564                 token = mono_class_get_event_token (p->event);
8565         } else if (strcmp (klass->name, "ParameterInfo") == 0 || strcmp (klass->name, "MonoParameterInfo") == 0) {
8566                 MonoReflectionParameter *p = (MonoReflectionParameter*)obj;
8567                 MonoClass *member_class = mono_object_class (p->MemberImpl);
8568                 g_assert (mono_class_is_reflection_method_or_constructor (member_class));
8569
8570                 token = mono_method_get_param_token (((MonoReflectionMethod*)p->MemberImpl)->method, p->PositionImpl);
8571         } else if (strcmp (klass->name, "Module") == 0 || strcmp (klass->name, "MonoModule") == 0) {
8572                 MonoReflectionModule *m = (MonoReflectionModule*)obj;
8573
8574                 token = m->token;
8575         } else if (strcmp (klass->name, "Assembly") == 0 || strcmp (klass->name, "MonoAssembly") == 0) {
8576                 token = mono_metadata_make_token (MONO_TABLE_ASSEMBLY, 1);
8577         } else {
8578                 gchar *msg = g_strdup_printf ("MetadataToken is not supported for type '%s.%s'", klass->name_space, klass->name);
8579                 MonoException *ex = mono_get_exception_not_implemented (msg);
8580                 g_free (msg);
8581                 mono_raise_exception (ex);
8582         }
8583
8584         return token;
8585 }
8586
8587 static MonoClass*
8588 load_cattr_enum_type (MonoImage *image, const char *p, const char **end, MonoError *error)
8589 {
8590         char *n;
8591         MonoType *t;
8592         int slen = mono_metadata_decode_value (p, &p);
8593
8594         mono_error_init (error);
8595
8596         n = (char *)g_memdup (p, slen + 1);
8597         n [slen] = 0;
8598         t = mono_reflection_type_from_name (n, image);
8599         if (!t) {
8600                 /* FIXME the error should come from mono_reflection_type_from_name as it will have type/assembly names split */
8601                 /* We don't free n, it's consumed by mono_error */
8602                 mono_error_set_type_load_name (error, n, NULL, "Could not load enum type %s while decoding custom attribute", n);
8603                 return NULL;
8604         }
8605         g_free (n);
8606         p += slen;
8607         *end = p;
8608         return mono_class_from_mono_type (t);
8609 }
8610
8611 static void*
8612 load_cattr_value (MonoImage *image, MonoType *t, const char *p, const char **end, MonoError *error)
8613 {
8614         int slen, type = t->type;
8615         MonoClass *tklass = t->data.klass;
8616
8617         mono_error_init (error);
8618
8619 handle_enum:
8620         switch (type) {
8621         case MONO_TYPE_U1:
8622         case MONO_TYPE_I1:
8623         case MONO_TYPE_BOOLEAN: {
8624                 MonoBoolean *bval = (MonoBoolean *)g_malloc (sizeof (MonoBoolean));
8625                 *bval = *p;
8626                 *end = p + 1;
8627                 return bval;
8628         }
8629         case MONO_TYPE_CHAR:
8630         case MONO_TYPE_U2:
8631         case MONO_TYPE_I2: {
8632                 guint16 *val = (guint16 *)g_malloc (sizeof (guint16));
8633                 *val = read16 (p);
8634                 *end = p + 2;
8635                 return val;
8636         }
8637 #if SIZEOF_VOID_P == 4
8638         case MONO_TYPE_U:
8639         case MONO_TYPE_I:
8640 #endif
8641         case MONO_TYPE_R4:
8642         case MONO_TYPE_U4:
8643         case MONO_TYPE_I4: {
8644                 guint32 *val = (guint32 *)g_malloc (sizeof (guint32));
8645                 *val = read32 (p);
8646                 *end = p + 4;
8647                 return val;
8648         }
8649 #if SIZEOF_VOID_P == 8
8650         case MONO_TYPE_U: /* error out instead? this should probably not happen */
8651         case MONO_TYPE_I:
8652 #endif
8653         case MONO_TYPE_U8:
8654         case MONO_TYPE_I8: {
8655                 guint64 *val = (guint64 *)g_malloc (sizeof (guint64));
8656                 *val = read64 (p);
8657                 *end = p + 8;
8658                 return val;
8659         }
8660         case MONO_TYPE_R8: {
8661                 double *val = (double *)g_malloc (sizeof (double));
8662                 readr8 (p, val);
8663                 *end = p + 8;
8664                 return val;
8665         }
8666         case MONO_TYPE_VALUETYPE:
8667                 if (t->data.klass->enumtype) {
8668                         type = mono_class_enum_basetype (t->data.klass)->type;
8669                         goto handle_enum;
8670                 } else {
8671                         MonoClass *k =  t->data.klass;
8672                         
8673                         if (mono_is_corlib_image (k->image) && strcmp (k->name_space, "System") == 0 && strcmp (k->name, "DateTime") == 0){
8674                                 guint64 *val = (guint64 *)g_malloc (sizeof (guint64));
8675                                 *val = read64 (p);
8676                                 *end = p + 8;
8677                                 return val;
8678                         }
8679                 }
8680                 g_error ("generic valutype %s not handled in custom attr value decoding", t->data.klass->name);
8681                 break;
8682                 
8683         case MONO_TYPE_STRING:
8684                 if (*p == (char)0xFF) {
8685                         *end = p + 1;
8686                         return NULL;
8687                 }
8688                 slen = mono_metadata_decode_value (p, &p);
8689                 *end = p + slen;
8690                 return mono_string_new_len (mono_domain_get (), p, slen);
8691         case MONO_TYPE_CLASS: {
8692                 MonoReflectionType *rt;
8693                 char *n;
8694                 MonoType *t;
8695                 if (*p == (char)0xFF) {
8696                         *end = p + 1;
8697                         return NULL;
8698                 }
8699 handle_type:
8700                 slen = mono_metadata_decode_value (p, &p);
8701                 n = (char *)g_memdup (p, slen + 1);
8702                 n [slen] = 0;
8703                 t = mono_reflection_type_from_name (n, image);
8704                 if (!t) {
8705                         /* FIXME the error should come from mono_reflection_type_from_name as it will have type/assembly names split */
8706                         /* We don't free n, it's consumed by mono_error */
8707                         mono_error_set_type_load_name (error, n, NULL, "Could not load type %s while decoding custom attribute", n);
8708                         return NULL;
8709                 }
8710                 g_free (n);
8711                 *end = p + slen;
8712
8713                 rt = mono_type_get_object_checked (mono_domain_get (), t, error);
8714                 if (!mono_error_ok (error))
8715                         return NULL;
8716
8717                 return rt;
8718         }
8719         case MONO_TYPE_OBJECT: {
8720                 char subt = *p++;
8721                 MonoObject *obj;
8722                 MonoClass *subc = NULL;
8723                 void *val;
8724
8725                 if (subt == 0x50) {
8726                         goto handle_type;
8727                 } else if (subt == 0x0E) {
8728                         type = MONO_TYPE_STRING;
8729                         goto handle_enum;
8730                 } else if (subt == 0x1D) {
8731                         MonoType simple_type = {{0}};
8732                         int etype = *p;
8733                         p ++;
8734
8735                         type = MONO_TYPE_SZARRAY;
8736                         if (etype == 0x50) {
8737                                 tklass = mono_defaults.systemtype_class;
8738                         } else if (etype == 0x55) {
8739                                 tklass = load_cattr_enum_type (image, p, &p, error);
8740                                 if (!mono_error_ok (error))
8741                                         return NULL;
8742                         } else {
8743                                 if (etype == 0x51)
8744                                         /* See Partition II, Appendix B3 */
8745                                         etype = MONO_TYPE_OBJECT;
8746                                 simple_type.type = (MonoTypeEnum)etype;
8747                                 tklass = mono_class_from_mono_type (&simple_type);
8748                         }
8749                         goto handle_enum;
8750                 } else if (subt == 0x55) {
8751                         char *n;
8752                         MonoType *t;
8753                         slen = mono_metadata_decode_value (p, &p);
8754                         n = (char *)g_memdup (p, slen + 1);
8755                         n [slen] = 0;
8756                         t = mono_reflection_type_from_name (n, image);
8757                         if (!t) {
8758                                 /* FIXME the error should come from mono_reflection_type_from_name as it will have type/assembly names split */
8759                                 /* We don't free n, it's consumed by mono_error */
8760                                 mono_error_set_type_load_name (error, n, NULL, "Could not load type %s while decoding custom attribute", n);
8761                                 return NULL;
8762                         }
8763                         g_free (n);
8764                         p += slen;
8765                         subc = mono_class_from_mono_type (t);
8766                 } else if (subt >= MONO_TYPE_BOOLEAN && subt <= MONO_TYPE_R8) {
8767                         MonoType simple_type = {{0}};
8768                         simple_type.type = (MonoTypeEnum)subt;
8769                         subc = mono_class_from_mono_type (&simple_type);
8770                 } else {
8771                         g_error ("Unknown type 0x%02x for object type encoding in custom attr", subt);
8772                 }
8773                 val = load_cattr_value (image, &subc->byval_arg, p, end, error);
8774                 obj = NULL;
8775                 if (mono_error_ok (error)) {
8776                         obj = mono_object_new_checked (mono_domain_get (), subc, error);
8777                         g_assert (!subc->has_references);
8778                         if (mono_error_ok (error))
8779                                 mono_gc_memmove_atomic ((char*)obj + sizeof (MonoObject), val, mono_class_value_size (subc, NULL));
8780                 }
8781
8782                 g_free (val);
8783                 return obj;
8784         }
8785         case MONO_TYPE_SZARRAY: {
8786                 MonoArray *arr;
8787                 guint32 i, alen, basetype;
8788                 alen = read32 (p);
8789                 p += 4;
8790                 if (alen == 0xffffffff) {
8791                         *end = p;
8792                         return NULL;
8793                 }
8794                 arr = mono_array_new (mono_domain_get(), tklass, alen);
8795                 basetype = tklass->byval_arg.type;
8796                 if (basetype == MONO_TYPE_VALUETYPE && tklass->enumtype)
8797                         basetype = mono_class_enum_basetype (tklass)->type;
8798                 switch (basetype)
8799                 {
8800                         case MONO_TYPE_U1:
8801                         case MONO_TYPE_I1:
8802                         case MONO_TYPE_BOOLEAN:
8803                                 for (i = 0; i < alen; i++) {
8804                                         MonoBoolean val = *p++;
8805                                         mono_array_set (arr, MonoBoolean, i, val);
8806                                 }
8807                                 break;
8808                         case MONO_TYPE_CHAR:
8809                         case MONO_TYPE_U2:
8810                         case MONO_TYPE_I2:
8811                                 for (i = 0; i < alen; i++) {
8812                                         guint16 val = read16 (p);
8813                                         mono_array_set (arr, guint16, i, val);
8814                                         p += 2;
8815                                 }
8816                                 break;
8817                         case MONO_TYPE_R4:
8818                         case MONO_TYPE_U4:
8819                         case MONO_TYPE_I4:
8820                                 for (i = 0; i < alen; i++) {
8821                                         guint32 val = read32 (p);
8822                                         mono_array_set (arr, guint32, i, val);
8823                                         p += 4;
8824                                 }
8825                                 break;
8826                         case MONO_TYPE_R8:
8827                                 for (i = 0; i < alen; i++) {
8828                                         double val;
8829                                         readr8 (p, &val);
8830                                         mono_array_set (arr, double, i, val);
8831                                         p += 8;
8832                                 }
8833                                 break;
8834                         case MONO_TYPE_U8:
8835                         case MONO_TYPE_I8:
8836                                 for (i = 0; i < alen; i++) {
8837                                         guint64 val = read64 (p);
8838                                         mono_array_set (arr, guint64, i, val);
8839                                         p += 8;
8840                                 }
8841                                 break;
8842                         case MONO_TYPE_CLASS:
8843                         case MONO_TYPE_OBJECT:
8844                         case MONO_TYPE_STRING:
8845                         case MONO_TYPE_SZARRAY:
8846                                 for (i = 0; i < alen; i++) {
8847                                         MonoObject *item = (MonoObject *)load_cattr_value (image, &tklass->byval_arg, p, &p, error);
8848                                         if (!mono_error_ok (error))
8849                                                 return NULL;
8850                                         mono_array_setref (arr, i, item);
8851                                 }
8852                                 break;
8853                         default:
8854                                 g_error ("Type 0x%02x not handled in custom attr array decoding", basetype);
8855                 }
8856                 *end=p;
8857                 return arr;
8858         }
8859         default:
8860                 g_error ("Type 0x%02x not handled in custom attr value decoding", type);
8861         }
8862         return NULL;
8863 }
8864
8865 static MonoObject*
8866 create_cattr_typed_arg (MonoType *t, MonoObject *val, MonoError *error)
8867 {
8868         static MonoMethod *ctor;
8869         MonoObject *retval;
8870         void *params [2], *unboxed;
8871
8872         mono_error_init (error);
8873
8874         if (!ctor)
8875                 ctor = mono_class_get_method_from_name (mono_class_get_custom_attribute_typed_argument_class (), ".ctor", 2);
8876         
8877         params [0] = mono_type_get_object_checked (mono_domain_get (), t, error);
8878         return_val_if_nok (error, NULL);
8879
8880         params [1] = val;
8881         retval = mono_object_new_checked (mono_domain_get (), mono_class_get_custom_attribute_typed_argument_class (), error);
8882         return_val_if_nok (error, NULL);
8883         unboxed = mono_object_unbox (retval);
8884
8885         mono_runtime_invoke_checked (ctor, unboxed, params, error);
8886         return_val_if_nok (error, NULL);
8887
8888         return retval;
8889 }
8890
8891 static MonoObject*
8892 create_cattr_named_arg (void *minfo, MonoObject *typedarg, MonoError *error)
8893 {
8894         static MonoMethod *ctor;
8895         MonoObject *retval;
8896         void *unboxed, *params [2];
8897
8898         mono_error_init (error);
8899
8900         if (!ctor)
8901                 ctor = mono_class_get_method_from_name (mono_class_get_custom_attribute_named_argument_class (), ".ctor", 2);
8902
8903         params [0] = minfo;
8904         params [1] = typedarg;
8905         retval = mono_object_new_checked (mono_domain_get (), mono_class_get_custom_attribute_named_argument_class (), error);
8906         return_val_if_nok (error, NULL);
8907
8908         unboxed = mono_object_unbox (retval);
8909
8910         mono_runtime_invoke_checked (ctor, unboxed, params, error);
8911         return_val_if_nok (error, NULL);
8912
8913         return retval;
8914 }
8915
8916 static gboolean
8917 type_is_reference (MonoType *type)
8918 {
8919         switch (type->type) {
8920         case MONO_TYPE_BOOLEAN:
8921         case MONO_TYPE_CHAR:
8922         case MONO_TYPE_U:
8923         case MONO_TYPE_I:
8924         case MONO_TYPE_U1:
8925         case MONO_TYPE_I1:
8926         case MONO_TYPE_U2:
8927         case MONO_TYPE_I2:
8928         case MONO_TYPE_U4:
8929         case MONO_TYPE_I4:
8930         case MONO_TYPE_U8:
8931         case MONO_TYPE_I8:
8932         case MONO_TYPE_R8:
8933         case MONO_TYPE_R4:
8934         case MONO_TYPE_VALUETYPE:
8935                 return FALSE;
8936         default:
8937                 return TRUE;
8938         }
8939 }
8940
8941 static void
8942 free_param_data (MonoMethodSignature *sig, void **params) {
8943         int i;
8944         for (i = 0; i < sig->param_count; ++i) {
8945                 if (!type_is_reference (sig->params [i]))
8946                         g_free (params [i]);
8947         }
8948 }
8949
8950 /*
8951  * Find the field index in the metadata FieldDef table.
8952  */
8953 static guint32
8954 find_field_index (MonoClass *klass, MonoClassField *field) {
8955         int i;
8956
8957         for (i = 0; i < klass->field.count; ++i) {
8958                 if (field == &klass->fields [i])
8959                         return klass->field.first + 1 + i;
8960         }
8961         return 0;
8962 }
8963
8964 /*
8965  * Find the property index in the metadata Property table.
8966  */
8967 static guint32
8968 find_property_index (MonoClass *klass, MonoProperty *property) {
8969         int i;
8970
8971         for (i = 0; i < klass->ext->property.count; ++i) {
8972                 if (property == &klass->ext->properties [i])
8973                         return klass->ext->property.first + 1 + i;
8974         }
8975         return 0;
8976 }
8977
8978 /*
8979  * Find the event index in the metadata Event table.
8980  */
8981 static guint32
8982 find_event_index (MonoClass *klass, MonoEvent *event) {
8983         int i;
8984
8985         for (i = 0; i < klass->ext->event.count; ++i) {
8986                 if (event == &klass->ext->events [i])
8987                         return klass->ext->event.first + 1 + i;
8988         }
8989         return 0;
8990 }
8991
8992 static MonoObject*
8993 create_custom_attr (MonoImage *image, MonoMethod *method, const guchar *data, guint32 len, MonoError *error)
8994 {
8995         const char *p = (const char*)data;
8996         const char *named;
8997         guint32 i, j, num_named;
8998         MonoObject *attr;
8999         void *params_buf [32];
9000         void **params = NULL;
9001         MonoMethodSignature *sig;
9002         MonoObject *exc = NULL;
9003
9004         mono_error_init (error);
9005
9006         mono_class_init (method->klass);
9007
9008         if (!mono_verifier_verify_cattr_content (image, method, data, len, NULL)) {
9009                 mono_error_set_generic_error (error, "System.Reflection", "CustomAttributeFormatException", "Binary format of the specified custom attribute was invalid.");
9010                 return NULL;
9011         }
9012
9013         if (len == 0) {
9014                 attr = mono_object_new_checked (mono_domain_get (), method->klass, error);
9015                 if (!mono_error_ok (error)) return NULL;
9016
9017                 mono_runtime_invoke_checked (method, attr, NULL, error);
9018                 if (!mono_error_ok (error))
9019                         return NULL;
9020
9021                 return attr;
9022         }
9023
9024         if (len < 2 || read16 (p) != 0x0001) /* Prolog */
9025                 return NULL;
9026
9027         /*g_print ("got attr %s\n", method->klass->name);*/
9028
9029         sig = mono_method_signature (method);
9030         if (sig->param_count < 32) {
9031                 params = params_buf;
9032                 memset (params, 0, sizeof (void*) * sig->param_count);
9033         } else {
9034                 /* Allocate using GC so it gets GC tracking */
9035                 params = (void **)mono_gc_alloc_fixed (sig->param_count * sizeof (void*), MONO_GC_DESCRIPTOR_NULL, MONO_ROOT_SOURCE_REFLECTION, "custom attribute parameters");
9036         }
9037
9038         /* skip prolog */
9039         p += 2;
9040         for (i = 0; i < mono_method_signature (method)->param_count; ++i) {
9041                 params [i] = load_cattr_value (image, mono_method_signature (method)->params [i], p, &p, error);
9042                 if (!mono_error_ok (error))
9043                         goto fail;
9044         }
9045
9046         named = p;
9047         attr = mono_object_new_checked (mono_domain_get (), method->klass, error);
9048         if (!mono_error_ok (error)) goto fail;
9049
9050         mono_runtime_try_invoke (method, attr, params, &exc, error);
9051         if (!mono_error_ok (error))
9052                 goto fail;
9053         if (exc)
9054                 goto fail;
9055
9056         num_named = read16 (named);
9057         named += 2;
9058         for (j = 0; j < num_named; j++) {
9059                 gint name_len;
9060                 char *name, named_type, data_type;
9061                 named_type = *named++;
9062                 data_type = *named++; /* type of data */
9063                 if (data_type == MONO_TYPE_SZARRAY)
9064                         data_type = *named++;
9065                 if (data_type == MONO_TYPE_ENUM) {
9066                         gint type_len;
9067                         char *type_name;
9068                         type_len = mono_metadata_decode_blob_size (named, &named);
9069                         type_name = (char *)g_malloc (type_len + 1);
9070                         memcpy (type_name, named, type_len);
9071                         type_name [type_len] = 0;
9072                         named += type_len;
9073                         /* FIXME: lookup the type and check type consistency */
9074                         g_free (type_name);
9075                 }
9076                 name_len = mono_metadata_decode_blob_size (named, &named);
9077                 name = (char *)g_malloc (name_len + 1);
9078                 memcpy (name, named, name_len);
9079                 name [name_len] = 0;
9080                 named += name_len;
9081                 if (named_type == 0x53) {
9082                         MonoClassField *field;
9083                         void *val;
9084
9085                         /* how this fail is a blackbox */
9086                         field = mono_class_get_field_from_name (mono_object_class (attr), name);
9087                         if (!field) {
9088                                 mono_error_set_generic_error (error, "System.Reflection", "CustomAttributeFormatException", "Could not find a field with name %s", name);
9089                                 g_free (name);
9090                                 goto fail;
9091                         }
9092
9093                         val = load_cattr_value (image, field->type, named, &named, error);
9094                         if (!mono_error_ok (error)) {
9095                                 g_free (name);
9096                                 if (!type_is_reference (field->type))
9097                                         g_free (val);
9098                                 goto fail;
9099                         }
9100
9101                         mono_field_set_value (attr, field, val);
9102                         if (!type_is_reference (field->type))
9103                                 g_free (val);
9104                 } else if (named_type == 0x54) {
9105                         MonoProperty *prop;
9106                         void *pparams [1];
9107                         MonoType *prop_type;
9108
9109                         prop = mono_class_get_property_from_name (mono_object_class (attr), name);
9110
9111                         if (!prop) {
9112                                 mono_error_set_generic_error (error, "System.Reflection", "CustomAttributeFormatException", "Could not find a property with name %s", name);
9113                                 g_free (name);
9114                                 goto fail;
9115                         }
9116
9117                         if (!prop->set) {
9118                                 mono_error_set_generic_error (error, "System.Reflection", "CustomAttributeFormatException", "Could not find the setter for %s", name);
9119                                 g_free (name);
9120                                 goto fail;
9121                         }
9122
9123                         /* can we have more that 1 arg in a custom attr named property? */
9124                         prop_type = prop->get? mono_method_signature (prop->get)->ret :
9125                              mono_method_signature (prop->set)->params [mono_method_signature (prop->set)->param_count - 1];
9126
9127                         pparams [0] = load_cattr_value (image, prop_type, named, &named, error);
9128                         if (!mono_error_ok (error)) {
9129                                 g_free (name);
9130                                 if (!type_is_reference (prop_type))
9131                                         g_free (pparams [0]);
9132                                 goto fail;
9133                         }
9134
9135
9136                         mono_property_set_value (prop, attr, pparams, NULL);
9137                         if (!type_is_reference (prop_type))
9138                                 g_free (pparams [0]);
9139                 }
9140                 g_free (name);
9141         }
9142
9143         free_param_data (method->signature, params);
9144         if (params != params_buf)
9145                 mono_gc_free_fixed (params);
9146
9147         return attr;
9148
9149 fail:
9150         free_param_data (method->signature, params);
9151         if (params != params_buf)
9152                 mono_gc_free_fixed (params);
9153         if (exc)
9154                 mono_raise_exception ((MonoException*)exc);
9155         return NULL;
9156 }
9157         
9158 /*
9159  * mono_reflection_create_custom_attr_data_args:
9160  *
9161  *   Create an array of typed and named arguments from the cattr blob given by DATA.
9162  * TYPED_ARGS and NAMED_ARGS will contain the objects representing the arguments,
9163  * NAMED_ARG_INFO will contain information about the named arguments.
9164  */
9165 void
9166 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)
9167 {
9168         MonoArray *typedargs, *namedargs;
9169         MonoClass *attrklass;
9170         MonoDomain *domain;
9171         const char *p = (const char*)data;
9172         const char *named;
9173         guint32 i, j, num_named;
9174         CattrNamedArg *arginfo = NULL;
9175
9176         *typed_args = NULL;
9177         *named_args = NULL;
9178         *named_arg_info = NULL;
9179
9180         mono_error_init (error);
9181
9182         if (!mono_verifier_verify_cattr_content (image, method, data, len, NULL)) {
9183                 mono_error_set_generic_error (error, "System.Reflection", "CustomAttributeFormatException", "Binary format of the specified custom attribute was invalid.");
9184                 return;
9185         }
9186
9187         mono_class_init (method->klass);
9188         
9189         domain = mono_domain_get ();
9190
9191         if (len < 2 || read16 (p) != 0x0001) /* Prolog */
9192                 return;
9193
9194         typedargs = mono_array_new (domain, mono_get_object_class (), mono_method_signature (method)->param_count);
9195         
9196         /* skip prolog */
9197         p += 2;
9198         for (i = 0; i < mono_method_signature (method)->param_count; ++i) {
9199                 MonoObject *obj;
9200                 void *val;
9201
9202                 val = load_cattr_value (image, mono_method_signature (method)->params [i], p, &p, error);
9203                 if (!mono_error_ok (error)) {
9204                         if (!type_is_reference (mono_method_signature (method)->params [i]))
9205                                 g_free (val);
9206                         return;
9207                 }
9208
9209                 obj = (MonoObject *)(type_is_reference (mono_method_signature (method)->params [i]) ?
9210                         val : mono_value_box (domain, mono_class_from_mono_type (mono_method_signature (method)->params [i]), val));
9211                 mono_array_setref (typedargs, i, obj);
9212
9213                 if (!type_is_reference (mono_method_signature (method)->params [i]))
9214                         g_free (val);
9215         }
9216
9217         named = p;
9218         num_named = read16 (named);
9219         namedargs = mono_array_new (domain, mono_get_object_class (), num_named);
9220         named += 2;
9221         attrklass = method->klass;
9222
9223         arginfo = g_new0 (CattrNamedArg, num_named);
9224         *named_arg_info = arginfo;
9225
9226         for (j = 0; j < num_named; j++) {
9227                 gint name_len;
9228                 char *name, named_type, data_type;
9229                 named_type = *named++;
9230                 data_type = *named++; /* type of data */
9231                 if (data_type == MONO_TYPE_SZARRAY)
9232                         data_type = *named++;
9233                 if (data_type == MONO_TYPE_ENUM) {
9234                         gint type_len;
9235                         char *type_name;
9236                         type_len = mono_metadata_decode_blob_size (named, &named);
9237                         if (ADDP_IS_GREATER_OR_OVF ((const guchar*)named, type_len, data + len))
9238                                 goto fail;
9239
9240                         type_name = (char *)g_malloc (type_len + 1);
9241                         memcpy (type_name, named, type_len);
9242                         type_name [type_len] = 0;
9243                         named += type_len;
9244                         /* FIXME: lookup the type and check type consistency */
9245                         g_free (type_name);
9246                 }
9247                 name_len = mono_metadata_decode_blob_size (named, &named);
9248                 if (ADDP_IS_GREATER_OR_OVF ((const guchar*)named, name_len, data + len))
9249                         goto fail;
9250                 name = (char *)g_malloc (name_len + 1);
9251                 memcpy (name, named, name_len);
9252                 name [name_len] = 0;
9253                 named += name_len;
9254                 if (named_type == 0x53) {
9255                         MonoObject *obj;
9256                         MonoClassField *field = mono_class_get_field_from_name (attrklass, name);
9257                         void *val;
9258
9259                         if (!field) {
9260                                 g_free (name);
9261                                 goto fail;
9262                         }
9263
9264                         arginfo [j].type = field->type;
9265                         arginfo [j].field = field;
9266
9267                         val = load_cattr_value (image, field->type, named, &named, error);
9268                         if (!mono_error_ok (error)) {
9269                                 if (!type_is_reference (field->type))
9270                                         g_free (val);
9271                                 g_free (name);
9272                                 return;
9273                         }
9274
9275                         obj = (MonoObject *)(type_is_reference (field->type) ? val : mono_value_box (domain, mono_class_from_mono_type (field->type), val));
9276                         mono_array_setref (namedargs, j, obj);
9277                         if (!type_is_reference (field->type))
9278                                 g_free (val);
9279                 } else if (named_type == 0x54) {
9280                         MonoObject *obj;
9281                         MonoType *prop_type;
9282                         MonoProperty *prop = mono_class_get_property_from_name (attrklass, name);
9283                         void *val;
9284
9285                         if (!prop || !prop->set) {
9286                                 g_free (name);
9287                                 goto fail;
9288                         }
9289
9290                         prop_type = prop->get? mono_method_signature (prop->get)->ret :
9291                              mono_method_signature (prop->set)->params [mono_method_signature (prop->set)->param_count - 1];
9292
9293                         arginfo [j].type = prop_type;
9294                         arginfo [j].prop = prop;
9295
9296                         val = load_cattr_value (image, prop_type, named, &named, error);
9297                         if (!mono_error_ok (error)) {
9298                                 if (!type_is_reference (prop_type))
9299                                         g_free (val);
9300                                 g_free (name);
9301                                 return;
9302                         }
9303
9304                         obj = (MonoObject *)(type_is_reference (prop_type) ? val : mono_value_box (domain, mono_class_from_mono_type (prop_type), val));
9305                         mono_array_setref (namedargs, j, obj);
9306                         if (!type_is_reference (prop_type))
9307                                 g_free (val);
9308                 }
9309                 g_free (name);
9310         }
9311
9312         *typed_args = typedargs;
9313         *named_args = namedargs;
9314         return;
9315 fail:
9316         mono_error_set_generic_error (error, "System.Reflection", "CustomAttributeFormatException", "Binary format of the specified custom attribute was invalid.");
9317         g_free (arginfo);
9318         *named_arg_info = NULL;
9319 }
9320
9321 void
9322 mono_reflection_resolve_custom_attribute_data (MonoReflectionMethod *ref_method, MonoReflectionAssembly *assembly, gpointer data, guint32 len, MonoArray **ctor_args, MonoArray **named_args)
9323 {
9324         MonoDomain *domain;
9325         MonoArray *typedargs, *namedargs;
9326         MonoImage *image;
9327         MonoMethod *method;
9328         CattrNamedArg *arginfo = NULL;
9329         MonoError error;
9330         int i;
9331
9332         mono_error_init (&error);
9333
9334         *ctor_args = NULL;
9335         *named_args = NULL;
9336
9337         if (len == 0)
9338                 return;
9339
9340         image = assembly->assembly->image;
9341         method = ref_method->method;
9342         domain = mono_object_domain (ref_method);
9343
9344         if (!mono_class_init (method->klass))
9345                 mono_raise_exception (mono_class_get_exception_for_failure (method->klass));
9346
9347         mono_reflection_create_custom_attr_data_args (image, method, (const guchar *)data, len, &typedargs, &namedargs, &arginfo, &error);
9348         if (!mono_error_ok (&error))
9349                 goto leave;
9350
9351         if (mono_loader_get_last_error ()) {
9352                 mono_error_set_from_loader_error (&error);
9353                 goto leave;
9354         }
9355
9356         if (!typedargs || !namedargs)
9357                 goto leave;
9358
9359         for (i = 0; i < mono_method_signature (method)->param_count; ++i) {
9360                 MonoObject *obj = mono_array_get (typedargs, MonoObject*, i);
9361                 MonoObject *typedarg;
9362
9363                 typedarg = create_cattr_typed_arg (mono_method_signature (method)->params [i], obj, &error);
9364                 if (!is_ok (&error))
9365                         goto leave;
9366                 mono_array_setref (typedargs, i, typedarg);
9367         }
9368
9369         for (i = 0; i < mono_array_length (namedargs); ++i) {
9370                 MonoObject *obj = mono_array_get (namedargs, MonoObject*, i);
9371                 MonoObject *typedarg, *namedarg, *minfo;
9372
9373                 if (arginfo [i].prop) {
9374                         minfo = (MonoObject*)mono_property_get_object_checked (domain, NULL, arginfo [i].prop, &error);
9375                         if (!minfo)
9376                                 goto leave;
9377                 } else {
9378                         minfo = (MonoObject*)mono_field_get_object_checked (domain, NULL, arginfo [i].field, &error);
9379                         if (!mono_error_ok (&error))
9380                                 goto leave;
9381                 }
9382
9383                 typedarg = create_cattr_typed_arg (arginfo [i].type, obj, &error);
9384                 if (!is_ok (&error))
9385                         goto leave;
9386                 namedarg = create_cattr_named_arg (minfo, typedarg, &error);
9387                 if (!is_ok (&error))
9388                         goto leave;
9389
9390                 mono_array_setref (namedargs, i, namedarg);
9391         }
9392
9393         *ctor_args = typedargs;
9394         *named_args = namedargs;
9395 leave:
9396         g_free (arginfo);
9397         mono_error_raise_exception (&error);
9398
9399 }
9400
9401 static MonoObject*
9402 create_custom_attr_data (MonoImage *image, MonoCustomAttrEntry *cattr, MonoError *error)
9403 {
9404         static MonoMethod *ctor;
9405
9406         MonoDomain *domain;
9407         MonoObject *attr;
9408         void *params [4];
9409
9410         mono_error_init (error);
9411
9412         g_assert (image->assembly);
9413
9414         if (!ctor)
9415                 ctor = mono_class_get_method_from_name (mono_defaults.customattribute_data_class, ".ctor", 4);
9416
9417         domain = mono_domain_get ();
9418         attr = mono_object_new_checked (domain, mono_defaults.customattribute_data_class, error);
9419         return_val_if_nok (error, NULL);
9420         params [0] = mono_method_get_object_checked (domain, cattr->ctor, NULL, error);
9421         return_val_if_nok (error, NULL);
9422         params [1] = mono_assembly_get_object_checked (domain, image->assembly, error);
9423         return_val_if_nok (error, NULL);
9424         params [2] = (gpointer)&cattr->data;
9425         params [3] = &cattr->data_size;
9426
9427         mono_runtime_invoke_checked (ctor, attr, params, error);
9428         return_val_if_nok (error, NULL);
9429         return attr;
9430 }
9431
9432 static MonoArray*
9433 mono_custom_attrs_construct_by_type (MonoCustomAttrInfo *cinfo, MonoClass *attr_klass, MonoError *error)
9434 {
9435         MonoArray *result;
9436         MonoObject *attr;
9437         int i, n;
9438
9439         mono_error_init (error);
9440
9441         n = 0;
9442         for (i = 0; i < cinfo->num_attrs; ++i) {
9443                 if (!attr_klass || mono_class_is_assignable_from (attr_klass, cinfo->attrs [i].ctor->klass))
9444                         n ++;
9445         }
9446
9447         result = mono_array_new_cached (mono_domain_get (), mono_defaults.attribute_class, n);
9448         n = 0;
9449         for (i = 0; i < cinfo->num_attrs; ++i) {
9450                 if (!cinfo->attrs [i].ctor) {
9451                         /* The cattr type is not finished yet */
9452                         /* We should include the type name but cinfo doesn't contain it */
9453                         mono_error_set_type_load_name (error, NULL, NULL, "");
9454                         return NULL;
9455                 }
9456                 if (!attr_klass || mono_class_is_assignable_from (attr_klass, cinfo->attrs [i].ctor->klass)) {
9457                         attr = create_custom_attr (cinfo->image, cinfo->attrs [i].ctor, cinfo->attrs [i].data, cinfo->attrs [i].data_size, error);
9458                         if (!mono_error_ok (error))
9459                                 return result;
9460                         mono_array_setref (result, n, attr);
9461                         n ++;
9462                 }
9463         }
9464         return result;
9465 }
9466
9467 MonoArray*
9468 mono_custom_attrs_construct (MonoCustomAttrInfo *cinfo)
9469 {
9470         MonoError error;
9471         MonoArray *result = mono_custom_attrs_construct_by_type (cinfo, NULL, &error);
9472         mono_error_assert_ok (&error); /*FIXME proper error handling*/
9473
9474         return result;
9475 }
9476
9477 static MonoArray*
9478 mono_custom_attrs_data_construct (MonoCustomAttrInfo *cinfo, MonoError *error)
9479 {
9480         MonoArray *result;
9481         MonoObject *attr;
9482         int i;
9483         
9484         mono_error_init (error);
9485         result = mono_array_new (mono_domain_get (), mono_defaults.customattribute_data_class, cinfo->num_attrs);
9486         for (i = 0; i < cinfo->num_attrs; ++i) {
9487                 attr = create_custom_attr_data (cinfo->image, &cinfo->attrs [i], error);
9488                 return_val_if_nok (error, NULL);
9489                 mono_array_setref (result, i, attr);
9490         }
9491         return result;
9492 }
9493
9494 /**
9495  * mono_custom_attrs_from_index:
9496  *
9497  * Returns: NULL if no attributes are found or if a loading error occurs.
9498  */
9499 MonoCustomAttrInfo*
9500 mono_custom_attrs_from_index (MonoImage *image, guint32 idx)
9501 {
9502         MonoError error;
9503         MonoCustomAttrInfo *result = mono_custom_attrs_from_index_checked (image, idx, &error);
9504         mono_error_cleanup (&error); /* FIXME a better public API that doesn't swallow the error. */
9505         return result;
9506 }
9507 /**
9508  * mono_custom_attrs_from_index_checked:
9509  *
9510  * Returns: NULL if no attributes are found.  On error returns NULL and sets @error.
9511  */
9512 MonoCustomAttrInfo*
9513 mono_custom_attrs_from_index_checked (MonoImage *image, guint32 idx, MonoError *error)
9514 {
9515         guint32 mtoken, i, len;
9516         guint32 cols [MONO_CUSTOM_ATTR_SIZE];
9517         MonoTableInfo *ca;
9518         MonoCustomAttrInfo *ainfo;
9519         GList *tmp, *list = NULL;
9520         const char *data;
9521         MonoCustomAttrEntry* attr;
9522
9523         mono_error_init (error);
9524
9525         ca = &image->tables [MONO_TABLE_CUSTOMATTRIBUTE];
9526
9527         i = mono_metadata_custom_attrs_from_index (image, idx);
9528         if (!i)
9529                 return NULL;
9530         i --;
9531         while (i < ca->rows) {
9532                 if (mono_metadata_decode_row_col (ca, i, MONO_CUSTOM_ATTR_PARENT) != idx)
9533                         break;
9534                 list = g_list_prepend (list, GUINT_TO_POINTER (i));
9535                 ++i;
9536         }
9537         len = g_list_length (list);
9538         if (!len)
9539                 return NULL;
9540         ainfo = (MonoCustomAttrInfo *)g_malloc0 (MONO_SIZEOF_CUSTOM_ATTR_INFO + sizeof (MonoCustomAttrEntry) * len);
9541         ainfo->num_attrs = len;
9542         ainfo->image = image;
9543         for (i = len, tmp = list; i != 0; --i, tmp = tmp->next) {
9544                 mono_metadata_decode_row (ca, GPOINTER_TO_UINT (tmp->data), cols, MONO_CUSTOM_ATTR_SIZE);
9545                 mtoken = cols [MONO_CUSTOM_ATTR_TYPE] >> MONO_CUSTOM_ATTR_TYPE_BITS;
9546                 switch (cols [MONO_CUSTOM_ATTR_TYPE] & MONO_CUSTOM_ATTR_TYPE_MASK) {
9547                 case MONO_CUSTOM_ATTR_TYPE_METHODDEF:
9548                         mtoken |= MONO_TOKEN_METHOD_DEF;
9549                         break;
9550                 case MONO_CUSTOM_ATTR_TYPE_MEMBERREF:
9551                         mtoken |= MONO_TOKEN_MEMBER_REF;
9552                         break;
9553                 default:
9554                         g_error ("Unknown table for custom attr type %08x", cols [MONO_CUSTOM_ATTR_TYPE]);
9555                         break;
9556                 }
9557                 attr = &ainfo->attrs [i - 1];
9558                 attr->ctor = mono_get_method_checked (image, mtoken, NULL, NULL, error);
9559                 if (!attr->ctor) {
9560                         g_warning ("Can't find custom attr constructor image: %s mtoken: 0x%08x due to %s", image->name, mtoken, mono_error_get_message (error));
9561                         g_list_free (list);
9562                         g_free (ainfo);
9563                         return NULL;
9564                 }
9565
9566                 if (!mono_verifier_verify_cattr_blob (image, cols [MONO_CUSTOM_ATTR_VALUE], NULL)) {
9567                         /*FIXME raising an exception here doesn't make any sense*/
9568                         g_warning ("Invalid custom attribute blob on image %s for index %x", image->name, idx);
9569                         g_list_free (list);
9570                         g_free (ainfo);
9571                         return NULL;
9572                 }
9573                 data = mono_metadata_blob_heap (image, cols [MONO_CUSTOM_ATTR_VALUE]);
9574                 attr->data_size = mono_metadata_decode_value (data, &data);
9575                 attr->data = (guchar*)data;
9576         }
9577         g_list_free (list);
9578
9579         return ainfo;
9580 }
9581
9582 MonoCustomAttrInfo*
9583 mono_custom_attrs_from_method (MonoMethod *method)
9584 {
9585         MonoError error;
9586         MonoCustomAttrInfo* result = mono_custom_attrs_from_method_checked  (method, &error);
9587         mono_error_cleanup (&error); /* FIXME want a better API that doesn't swallow the error */
9588         return result;
9589 }
9590
9591 MonoCustomAttrInfo*
9592 mono_custom_attrs_from_method_checked (MonoMethod *method, MonoError *error)
9593 {
9594         guint32 idx;
9595
9596         mono_error_init (error);
9597
9598         /*
9599          * An instantiated method has the same cattrs as the generic method definition.
9600          *
9601          * LAMESPEC: The .NET SRE throws an exception for instantiations of generic method builders
9602          *           Note that this stanza is not necessary for non-SRE types, but it's a micro-optimization
9603          */
9604         if (method->is_inflated)
9605                 method = ((MonoMethodInflated *) method)->declaring;
9606         
9607         if (method_is_dynamic (method) || image_is_dynamic (method->klass->image))
9608                 return lookup_custom_attr (method->klass->image, method);
9609
9610         if (!method->token)
9611                 /* Synthetic methods */
9612                 return NULL;
9613
9614         idx = mono_method_get_index (method);
9615         idx <<= MONO_CUSTOM_ATTR_BITS;
9616         idx |= MONO_CUSTOM_ATTR_METHODDEF;
9617         return mono_custom_attrs_from_index_checked (method->klass->image, idx, error);
9618 }
9619
9620 MonoCustomAttrInfo*
9621 mono_custom_attrs_from_class (MonoClass *klass)
9622 {
9623         MonoError error;
9624         MonoCustomAttrInfo *result = mono_custom_attrs_from_class_checked (klass, &error);
9625         mono_error_cleanup (&error); /* FIXME want a better API that doesn't swallow the error */
9626         return result;
9627 }
9628
9629 MonoCustomAttrInfo*
9630 mono_custom_attrs_from_class_checked (MonoClass *klass, MonoError *error)
9631 {
9632         guint32 idx;
9633
9634         mono_error_init (error);
9635
9636         if (klass->generic_class)
9637                 klass = klass->generic_class->container_class;
9638
9639         if (image_is_dynamic (klass->image))
9640                 return lookup_custom_attr (klass->image, klass);
9641
9642         if (klass->byval_arg.type == MONO_TYPE_VAR || klass->byval_arg.type == MONO_TYPE_MVAR) {
9643                 idx = mono_metadata_token_index (klass->sizes.generic_param_token);
9644                 idx <<= MONO_CUSTOM_ATTR_BITS;
9645                 idx |= MONO_CUSTOM_ATTR_GENERICPAR;
9646         } else {
9647                 idx = mono_metadata_token_index (klass->type_token);
9648                 idx <<= MONO_CUSTOM_ATTR_BITS;
9649                 idx |= MONO_CUSTOM_ATTR_TYPEDEF;
9650         }
9651         return mono_custom_attrs_from_index_checked (klass->image, idx, error);
9652 }
9653
9654 MonoCustomAttrInfo*
9655 mono_custom_attrs_from_assembly (MonoAssembly *assembly)
9656 {
9657         MonoError error;
9658         MonoCustomAttrInfo *result = mono_custom_attrs_from_assembly_checked (assembly, &error);
9659         mono_error_cleanup (&error); /* FIXME want a better API that doesn't swallow the error */
9660         return result;
9661 }
9662
9663 MonoCustomAttrInfo*
9664 mono_custom_attrs_from_assembly_checked (MonoAssembly *assembly, MonoError *error)
9665 {
9666         guint32 idx;
9667         
9668         mono_error_init (error);
9669
9670         if (image_is_dynamic (assembly->image))
9671                 return lookup_custom_attr (assembly->image, assembly);
9672         idx = 1; /* there is only one assembly */
9673         idx <<= MONO_CUSTOM_ATTR_BITS;
9674         idx |= MONO_CUSTOM_ATTR_ASSEMBLY;
9675         return mono_custom_attrs_from_index_checked (assembly->image, idx, error);
9676 }
9677
9678 static MonoCustomAttrInfo*
9679 mono_custom_attrs_from_module (MonoImage *image, MonoError *error)
9680 {
9681         guint32 idx;
9682         
9683         if (image_is_dynamic (image))
9684                 return lookup_custom_attr (image, image);
9685         idx = 1; /* there is only one module */
9686         idx <<= MONO_CUSTOM_ATTR_BITS;
9687         idx |= MONO_CUSTOM_ATTR_MODULE;
9688         return mono_custom_attrs_from_index_checked (image, idx, error);
9689 }
9690
9691 MonoCustomAttrInfo*
9692 mono_custom_attrs_from_property (MonoClass *klass, MonoProperty *property)
9693 {
9694         MonoError error;
9695         MonoCustomAttrInfo * result = mono_custom_attrs_from_property_checked (klass, property, &error);
9696         mono_error_cleanup (&error); /* FIXME want a better API that doesn't swallow the error */
9697         return result;
9698 }
9699
9700 MonoCustomAttrInfo*
9701 mono_custom_attrs_from_property_checked (MonoClass *klass, MonoProperty *property, MonoError *error)
9702 {
9703         guint32 idx;
9704         
9705         if (image_is_dynamic (klass->image)) {
9706                 property = mono_metadata_get_corresponding_property_from_generic_type_definition (property);
9707                 return lookup_custom_attr (klass->image, property);
9708         }
9709         idx = find_property_index (klass, property);
9710         idx <<= MONO_CUSTOM_ATTR_BITS;
9711         idx |= MONO_CUSTOM_ATTR_PROPERTY;
9712         return mono_custom_attrs_from_index_checked (klass->image, idx, error);
9713 }
9714
9715 MonoCustomAttrInfo*
9716 mono_custom_attrs_from_event (MonoClass *klass, MonoEvent *event)
9717 {
9718         MonoError error;
9719         MonoCustomAttrInfo * result = mono_custom_attrs_from_event_checked (klass, event, &error);
9720         mono_error_cleanup (&error); /* FIXME want a better API that doesn't swallow the error */
9721         return result;
9722 }
9723
9724 MonoCustomAttrInfo*
9725 mono_custom_attrs_from_event_checked (MonoClass *klass, MonoEvent *event, MonoError *error)
9726 {
9727         guint32 idx;
9728         
9729         if (image_is_dynamic (klass->image)) {
9730                 event = mono_metadata_get_corresponding_event_from_generic_type_definition (event);
9731                 return lookup_custom_attr (klass->image, event);
9732         }
9733         idx = find_event_index (klass, event);
9734         idx <<= MONO_CUSTOM_ATTR_BITS;
9735         idx |= MONO_CUSTOM_ATTR_EVENT;
9736         return mono_custom_attrs_from_index_checked (klass->image, idx, error);
9737 }
9738
9739 MonoCustomAttrInfo*
9740 mono_custom_attrs_from_field (MonoClass *klass, MonoClassField *field)
9741 {
9742         MonoError error;
9743         MonoCustomAttrInfo * result = mono_custom_attrs_from_field_checked (klass, field, &error);
9744         mono_error_cleanup (&error); /* FIXME want a better API that doesn't swallow the error */
9745         return result;
9746 }
9747
9748 MonoCustomAttrInfo*
9749 mono_custom_attrs_from_field_checked (MonoClass *klass, MonoClassField *field, MonoError *error)
9750 {
9751         guint32 idx;
9752         mono_error_init (error);
9753
9754         if (image_is_dynamic (klass->image)) {
9755                 field = mono_metadata_get_corresponding_field_from_generic_type_definition (field);
9756                 return lookup_custom_attr (klass->image, field);
9757         }
9758         idx = find_field_index (klass, field);
9759         idx <<= MONO_CUSTOM_ATTR_BITS;
9760         idx |= MONO_CUSTOM_ATTR_FIELDDEF;
9761         return mono_custom_attrs_from_index_checked (klass->image, idx, error);
9762 }
9763
9764 /**
9765  * mono_custom_attrs_from_param:
9766  * @method: handle to the method that we want to retrieve custom parameter information from
9767  * @param: parameter number, where zero represent the return value, and one is the first parameter in the method
9768  *
9769  * The result must be released with mono_custom_attrs_free().
9770  *
9771  * Returns: the custom attribute object for the specified parameter, or NULL if there are none.
9772  */
9773 MonoCustomAttrInfo*
9774 mono_custom_attrs_from_param (MonoMethod *method, guint32 param)
9775 {
9776         MonoError error;
9777         MonoCustomAttrInfo *result = mono_custom_attrs_from_param_checked (method, param, &error);
9778         mono_error_cleanup (&error); /* FIXME want a better API that doesn't swallow the error */
9779         return result;
9780 }
9781
9782 /**
9783  * mono_custom_attrs_from_param_checked:
9784  * @method: handle to the method that we want to retrieve custom parameter information from
9785  * @param: parameter number, where zero represent the return value, and one is the first parameter in the method
9786  * @error: set on error
9787  *
9788  * The result must be released with mono_custom_attrs_free().
9789  *
9790  * Returns: the custom attribute object for the specified parameter, or NULL if there are none.  On failure returns NULL and sets @error.
9791  */
9792 MonoCustomAttrInfo*
9793 mono_custom_attrs_from_param_checked (MonoMethod *method, guint32 param, MonoError *error)
9794 {
9795         MonoTableInfo *ca;
9796         guint32 i, idx, method_index;
9797         guint32 param_list, param_last, param_pos, found;
9798         MonoImage *image;
9799         MonoReflectionMethodAux *aux;
9800
9801         mono_error_init (error);
9802
9803         /*
9804          * An instantiated method has the same cattrs as the generic method definition.
9805          *
9806          * LAMESPEC: The .NET SRE throws an exception for instantiations of generic method builders
9807          *           Note that this stanza is not necessary for non-SRE types, but it's a micro-optimization
9808          */
9809         if (method->is_inflated)
9810                 method = ((MonoMethodInflated *) method)->declaring;
9811
9812         if (image_is_dynamic (method->klass->image)) {
9813                 MonoCustomAttrInfo *res, *ainfo;
9814                 int size;
9815
9816                 aux = (MonoReflectionMethodAux *)g_hash_table_lookup (((MonoDynamicImage*)method->klass->image)->method_aux_hash, method);
9817                 if (!aux || !aux->param_cattr)
9818                         return NULL;
9819
9820                 /* Need to copy since it will be freed later */
9821                 ainfo = aux->param_cattr [param];
9822                 if (!ainfo)
9823                         return NULL;
9824                 size = MONO_SIZEOF_CUSTOM_ATTR_INFO + sizeof (MonoCustomAttrEntry) * ainfo->num_attrs;
9825                 res = (MonoCustomAttrInfo *)g_malloc0 (size);
9826                 memcpy (res, ainfo, size);
9827                 return res;
9828         }
9829
9830         image = method->klass->image;
9831         method_index = mono_method_get_index (method);
9832         if (!method_index)
9833                 return NULL;
9834         ca = &image->tables [MONO_TABLE_METHOD];
9835
9836         param_list = mono_metadata_decode_row_col (ca, method_index - 1, MONO_METHOD_PARAMLIST);
9837         if (method_index == ca->rows) {
9838                 ca = &image->tables [MONO_TABLE_PARAM];
9839                 param_last = ca->rows + 1;
9840         } else {
9841                 param_last = mono_metadata_decode_row_col (ca, method_index, MONO_METHOD_PARAMLIST);
9842                 ca = &image->tables [MONO_TABLE_PARAM];
9843         }
9844         found = FALSE;
9845         for (i = param_list; i < param_last; ++i) {
9846                 param_pos = mono_metadata_decode_row_col (ca, i - 1, MONO_PARAM_SEQUENCE);
9847                 if (param_pos == param) {
9848                         found = TRUE;
9849                         break;
9850                 }
9851         }
9852         if (!found)
9853                 return NULL;
9854         idx = i;
9855         idx <<= MONO_CUSTOM_ATTR_BITS;
9856         idx |= MONO_CUSTOM_ATTR_PARAMDEF;
9857         return mono_custom_attrs_from_index_checked (image, idx, error);
9858 }
9859
9860 gboolean
9861 mono_custom_attrs_has_attr (MonoCustomAttrInfo *ainfo, MonoClass *attr_klass)
9862 {
9863         int i;
9864         MonoClass *klass;
9865         for (i = 0; i < ainfo->num_attrs; ++i) {
9866                 klass = ainfo->attrs [i].ctor->klass;
9867                 if (mono_class_has_parent (klass, attr_klass) || (MONO_CLASS_IS_INTERFACE (attr_klass) && mono_class_is_assignable_from (attr_klass, klass)))
9868                         return TRUE;
9869         }
9870         return FALSE;
9871 }
9872
9873 MonoObject*
9874 mono_custom_attrs_get_attr (MonoCustomAttrInfo *ainfo, MonoClass *attr_klass)
9875 {
9876         MonoError error;
9877         MonoObject *res = mono_custom_attrs_get_attr_checked (ainfo, attr_klass, &error);
9878         g_assert (mono_error_ok (&error)); /*FIXME proper error handling*/
9879         return res;
9880 }
9881
9882 MonoObject*
9883 mono_custom_attrs_get_attr_checked (MonoCustomAttrInfo *ainfo, MonoClass *attr_klass, MonoError *error)
9884 {
9885         int i, attr_index;
9886         MonoClass *klass;
9887         MonoArray *attrs;
9888
9889         mono_error_init (error);
9890
9891         attr_index = -1;
9892         for (i = 0; i < ainfo->num_attrs; ++i) {
9893                 klass = ainfo->attrs [i].ctor->klass;
9894                 if (mono_class_has_parent (klass, attr_klass)) {
9895                         attr_index = i;
9896                         break;
9897                 }
9898         }
9899         if (attr_index == -1)
9900                 return NULL;
9901
9902         attrs = mono_custom_attrs_construct_by_type (ainfo, NULL, error);
9903         if (!mono_error_ok (error))
9904                 return NULL;
9905         return mono_array_get (attrs, MonoObject*, attr_index);
9906 }
9907
9908 /*
9909  * mono_reflection_get_custom_attrs_info:
9910  * @obj: a reflection object handle
9911  *
9912  * Return the custom attribute info for attributes defined for the
9913  * reflection handle @obj. The objects.
9914  *
9915  * FIXME this function leaks like a sieve for SRE objects.
9916  */
9917 MonoCustomAttrInfo*
9918 mono_reflection_get_custom_attrs_info (MonoObject *obj)
9919 {
9920         MonoError error;
9921         MonoCustomAttrInfo *result = mono_reflection_get_custom_attrs_info_checked (obj, &error);
9922         mono_error_assert_ok (&error);
9923         return result;
9924 }
9925
9926 /**
9927  * mono_reflection_get_custom_attrs_info_checked:
9928  * @obj: a reflection object handle
9929  * @error: set on error
9930  *
9931  * Return the custom attribute info for attributes defined for the
9932  * reflection handle @obj. The objects.
9933  *
9934  * On failure returns NULL and sets @error.
9935  *
9936  * FIXME this function leaks like a sieve for SRE objects.
9937  */
9938 MonoCustomAttrInfo*
9939 mono_reflection_get_custom_attrs_info_checked (MonoObject *obj, MonoError *error)
9940 {
9941         MonoClass *klass;
9942         MonoCustomAttrInfo *cinfo = NULL;
9943         
9944         mono_error_init (error);
9945
9946         klass = obj->vtable->klass;
9947         if (klass == mono_defaults.monotype_class) {
9948                 MonoType *type = mono_reflection_type_get_handle ((MonoReflectionType *)obj);
9949                 klass = mono_class_from_mono_type (type);
9950                 /*We cannot mono_class_init the class from which we'll load the custom attributes since this must work with broken types.*/
9951                 cinfo = mono_custom_attrs_from_class_checked (klass, error);
9952                 return_val_if_nok (error, NULL);
9953         } else if (strcmp ("Assembly", klass->name) == 0 || strcmp ("MonoAssembly", klass->name) == 0) {
9954                 MonoReflectionAssembly *rassembly = (MonoReflectionAssembly*)obj;
9955                 cinfo = mono_custom_attrs_from_assembly_checked (rassembly->assembly, error);
9956                 return_val_if_nok (error, NULL);
9957         } else if (strcmp ("Module", klass->name) == 0 || strcmp ("MonoModule", klass->name) == 0) {
9958                 MonoReflectionModule *module = (MonoReflectionModule*)obj;
9959                 cinfo = mono_custom_attrs_from_module (module->image, error);
9960                 return_val_if_nok (error, NULL);
9961         } else if (strcmp ("MonoProperty", klass->name) == 0) {
9962                 MonoReflectionProperty *rprop = (MonoReflectionProperty*)obj;
9963                 cinfo = mono_custom_attrs_from_property_checked (rprop->property->parent, rprop->property, error);
9964                 return_val_if_nok (error, NULL);
9965         } else if (strcmp ("MonoEvent", klass->name) == 0) {
9966                 MonoReflectionMonoEvent *revent = (MonoReflectionMonoEvent*)obj;
9967                 cinfo = mono_custom_attrs_from_event_checked (revent->event->parent, revent->event, error);
9968                 return_val_if_nok (error, NULL);
9969         } else if (strcmp ("MonoField", klass->name) == 0) {
9970                 MonoReflectionField *rfield = (MonoReflectionField*)obj;
9971                 cinfo = mono_custom_attrs_from_field_checked (rfield->field->parent, rfield->field, error);
9972                 return_val_if_nok (error, NULL);
9973         } else if ((strcmp ("MonoMethod", klass->name) == 0) || (strcmp ("MonoCMethod", klass->name) == 0)) {
9974                 MonoReflectionMethod *rmethod = (MonoReflectionMethod*)obj;
9975                 cinfo = mono_custom_attrs_from_method_checked (rmethod->method, error);
9976                 return_val_if_nok (error, NULL);
9977         } else if ((strcmp ("MonoGenericMethod", klass->name) == 0) || (strcmp ("MonoGenericCMethod", klass->name) == 0)) {
9978                 MonoReflectionMethod *rmethod = (MonoReflectionMethod*)obj;
9979                 cinfo = mono_custom_attrs_from_method_checked (rmethod->method, error);
9980                 return_val_if_nok (error, NULL);
9981         } else if (strcmp ("ParameterInfo", klass->name) == 0 || strcmp ("MonoParameterInfo", klass->name) == 0) {
9982                 MonoReflectionParameter *param = (MonoReflectionParameter*)obj;
9983                 MonoClass *member_class = mono_object_class (param->MemberImpl);
9984                 if (mono_class_is_reflection_method_or_constructor (member_class)) {
9985                         MonoReflectionMethod *rmethod = (MonoReflectionMethod*)param->MemberImpl;
9986                         cinfo = mono_custom_attrs_from_param_checked (rmethod->method, param->PositionImpl + 1, error);
9987                         return_val_if_nok (error, NULL);
9988                 } else if (is_sr_mono_property (member_class)) {
9989                         MonoReflectionProperty *prop = (MonoReflectionProperty *)param->MemberImpl;
9990                         MonoMethod *method;
9991                         if (!(method = prop->property->get))
9992                                 method = prop->property->set;
9993                         g_assert (method);
9994
9995                         cinfo = mono_custom_attrs_from_param_checked (method, param->PositionImpl + 1, error);
9996                         return_val_if_nok (error, NULL);
9997                 } 
9998 #ifndef DISABLE_REFLECTION_EMIT
9999                 else if (is_sre_method_on_tb_inst (member_class)) {/*XXX This is a workaround for Compiler Context*/
10000                         MonoMethod *method = mono_reflection_method_on_tb_inst_get_handle ((MonoReflectionMethodOnTypeBuilderInst*)param->MemberImpl, error);
10001                         return_val_if_nok (error, NULL);
10002                         cinfo = mono_custom_attrs_from_param_checked (method, param->PositionImpl + 1, error);
10003                         return_val_if_nok (error, NULL);
10004                 } else if (is_sre_ctor_on_tb_inst (member_class)) { /*XX This is a workaround for Compiler Context*/
10005                         MonoReflectionCtorOnTypeBuilderInst *c = (MonoReflectionCtorOnTypeBuilderInst*)param->MemberImpl;
10006                         MonoMethod *method = NULL;
10007                         if (is_sre_ctor_builder (mono_object_class (c->cb)))
10008                                 method = ((MonoReflectionCtorBuilder *)c->cb)->mhandle;
10009                         else if (is_sr_mono_cmethod (mono_object_class (c->cb)))
10010                                 method = ((MonoReflectionMethod *)c->cb)->method;
10011                         else
10012                                 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));
10013
10014                         cinfo = mono_custom_attrs_from_param_checked (method, param->PositionImpl + 1, error);
10015                         return_val_if_nok (error, NULL);
10016                 } 
10017 #endif
10018                 else {
10019                         char *type_name = mono_type_get_full_name (member_class);
10020                         mono_error_set_generic_error (error, "System", "NotSupportedException",
10021                                                       "Custom attributes on a ParamInfo with member %s are not supported",
10022                                                       type_name);
10023                         g_free (type_name);
10024                         return NULL;
10025                 }
10026         } else if (strcmp ("AssemblyBuilder", klass->name) == 0) {
10027                 MonoReflectionAssemblyBuilder *assemblyb = (MonoReflectionAssemblyBuilder*)obj;
10028                 cinfo = mono_custom_attrs_from_builders (NULL, assemblyb->assembly.assembly->image, assemblyb->cattrs);
10029         } else if (strcmp ("TypeBuilder", klass->name) == 0) {
10030                 MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder*)obj;
10031                 cinfo = mono_custom_attrs_from_builders (NULL, &tb->module->dynamic_image->image, tb->cattrs);
10032         } else if (strcmp ("ModuleBuilder", klass->name) == 0) {
10033                 MonoReflectionModuleBuilder *mb = (MonoReflectionModuleBuilder*)obj;
10034                 cinfo = mono_custom_attrs_from_builders (NULL, &mb->dynamic_image->image, mb->cattrs);
10035         } else if (strcmp ("ConstructorBuilder", klass->name) == 0) {
10036                 MonoReflectionCtorBuilder *cb = (MonoReflectionCtorBuilder*)obj;
10037                 cinfo = mono_custom_attrs_from_builders (NULL, cb->mhandle->klass->image, cb->cattrs);
10038         } else if (strcmp ("MethodBuilder", klass->name) == 0) {
10039                 MonoReflectionMethodBuilder *mb = (MonoReflectionMethodBuilder*)obj;
10040                 cinfo = mono_custom_attrs_from_builders (NULL, mb->mhandle->klass->image, mb->cattrs);
10041         } else if (strcmp ("FieldBuilder", klass->name) == 0) {
10042                 MonoReflectionFieldBuilder *fb = (MonoReflectionFieldBuilder*)obj;
10043                 cinfo = mono_custom_attrs_from_builders (NULL, &((MonoReflectionTypeBuilder*)fb->typeb)->module->dynamic_image->image, fb->cattrs);
10044         } else if (strcmp ("MonoGenericClass", klass->name) == 0) {
10045                 MonoReflectionGenericClass *gclass = (MonoReflectionGenericClass*)obj;
10046                 cinfo = mono_reflection_get_custom_attrs_info_checked ((MonoObject*)gclass->generic_type, error);
10047                 return_val_if_nok (error, NULL);
10048         } else { /* handle other types here... */
10049                 g_error ("get custom attrs not yet supported for %s", klass->name);
10050         }
10051
10052         return cinfo;
10053 }
10054
10055 /*
10056  * mono_reflection_get_custom_attrs_by_type:
10057  * @obj: a reflection object handle
10058  *
10059  * Return an array with all the custom attributes defined of the
10060  * reflection handle @obj. If @attr_klass is non-NULL, only custom attributes 
10061  * of that type are returned. The objects are fully build. Return NULL if a loading error
10062  * occurs.
10063  */
10064 MonoArray*
10065 mono_reflection_get_custom_attrs_by_type (MonoObject *obj, MonoClass *attr_klass, MonoError *error)
10066 {
10067         MonoArray *result;
10068         MonoCustomAttrInfo *cinfo;
10069
10070         mono_error_init (error);
10071
10072         cinfo = mono_reflection_get_custom_attrs_info_checked (obj, error);
10073         return_val_if_nok (error, NULL);
10074         if (cinfo) {
10075                 result = mono_custom_attrs_construct_by_type (cinfo, attr_klass, error);
10076                 if (!result)
10077                         return NULL;
10078                 if (!cinfo->cached)
10079                         mono_custom_attrs_free (cinfo);
10080         } else {
10081                 mono_loader_assert_no_error ();
10082                 result = mono_array_new_cached (mono_domain_get (), mono_defaults.attribute_class, 0);
10083         }
10084
10085         return result;
10086 }
10087
10088 /*
10089  * mono_reflection_get_custom_attrs:
10090  * @obj: a reflection object handle
10091  *
10092  * Return an array with all the custom attributes defined of the
10093  * reflection handle @obj. The objects are fully build. Return NULL if a loading error
10094  * occurs.
10095  */
10096 MonoArray*
10097 mono_reflection_get_custom_attrs (MonoObject *obj)
10098 {
10099         MonoError error;
10100
10101         return mono_reflection_get_custom_attrs_by_type (obj, NULL, &error);
10102 }
10103
10104 /*
10105  * mono_reflection_get_custom_attrs_data:
10106  * @obj: a reflection obj handle
10107  *
10108  * Returns an array of System.Reflection.CustomAttributeData,
10109  * which include information about attributes reflected on
10110  * types loaded using the Reflection Only methods
10111  */
10112 MonoArray*
10113 mono_reflection_get_custom_attrs_data (MonoObject *obj)
10114 {
10115         MonoError error;
10116         MonoArray* result;
10117         result = mono_reflection_get_custom_attrs_data_checked (obj, &error);
10118         mono_error_cleanup (&error); /* FIXME new API that doesn't swallow the error */
10119         return result;
10120 }
10121
10122 /*
10123  * mono_reflection_get_custom_attrs_data_checked:
10124  * @obj: a reflection obj handle
10125  * @error: set on error
10126  *
10127  * Returns an array of System.Reflection.CustomAttributeData,
10128  * which include information about attributes reflected on
10129  * types loaded using the Reflection Only methods
10130  */
10131 MonoArray*
10132 mono_reflection_get_custom_attrs_data_checked (MonoObject *obj, MonoError *error)
10133 {
10134         MonoArray *result;
10135         MonoCustomAttrInfo *cinfo;
10136
10137         mono_error_init (error);
10138
10139         cinfo = mono_reflection_get_custom_attrs_info_checked (obj, error);
10140         return_val_if_nok (error, NULL);
10141         if (cinfo) {
10142                 result = mono_custom_attrs_data_construct (cinfo, error);
10143                 return_val_if_nok (error, NULL);
10144                 if (!cinfo->cached)
10145                         mono_custom_attrs_free (cinfo);
10146         } else
10147                 result = mono_array_new (mono_domain_get (), mono_defaults.customattribute_data_class, 0);
10148
10149         if (mono_loader_get_last_error ())
10150                 mono_error_set_from_loader_error (error);
10151
10152         return result;
10153 }
10154
10155 static MonoReflectionType*
10156 mono_reflection_type_get_underlying_system_type (MonoReflectionType* t, MonoError *error)
10157 {
10158         static MonoMethod *method_get_underlying_system_type = NULL;
10159         MonoReflectionType *rt;
10160         MonoMethod *usertype_method;
10161
10162         mono_error_init (error);
10163
10164         if (!method_get_underlying_system_type)
10165                 method_get_underlying_system_type = mono_class_get_method_from_name (mono_defaults.systemtype_class, "get_UnderlyingSystemType", 0);
10166
10167         usertype_method = mono_object_get_virtual_method ((MonoObject *) t, method_get_underlying_system_type);
10168
10169         rt = (MonoReflectionType *) mono_runtime_invoke_checked (usertype_method, t, NULL, error);
10170
10171         return rt;
10172 }
10173
10174
10175 static gboolean
10176 is_corlib_type (MonoClass *klass)
10177 {
10178         return klass->image == mono_defaults.corlib;
10179 }
10180
10181 #define check_corlib_type_cached(_class, _namespace, _name) do { \
10182         static MonoClass *cached_class; \
10183         if (cached_class) \
10184                 return cached_class == _class; \
10185         if (is_corlib_type (_class) && !strcmp (_name, _class->name) && !strcmp (_namespace, _class->name_space)) { \
10186                 cached_class = _class; \
10187                 return TRUE; \
10188         } \
10189         return FALSE; \
10190 } while (0) \
10191
10192
10193 #ifndef DISABLE_REFLECTION_EMIT
10194 static gboolean
10195 is_sre_array (MonoClass *klass)
10196 {
10197         check_corlib_type_cached (klass, "System.Reflection.Emit", "ArrayType");
10198 }
10199
10200 static gboolean
10201 is_sre_byref (MonoClass *klass)
10202 {
10203         check_corlib_type_cached (klass, "System.Reflection.Emit", "ByRefType");
10204 }
10205
10206 static gboolean
10207 is_sre_pointer (MonoClass *klass)
10208 {
10209         check_corlib_type_cached (klass, "System.Reflection.Emit", "PointerType");
10210 }
10211
10212 static gboolean
10213 is_sre_generic_instance (MonoClass *klass)
10214 {
10215         check_corlib_type_cached (klass, "System.Reflection", "MonoGenericClass");
10216 }
10217
10218 static gboolean
10219 is_sre_type_builder (MonoClass *klass)
10220 {
10221         check_corlib_type_cached (klass, "System.Reflection.Emit", "TypeBuilder");
10222 }
10223
10224 static gboolean
10225 is_sre_method_builder (MonoClass *klass)
10226 {
10227         check_corlib_type_cached (klass, "System.Reflection.Emit", "MethodBuilder");
10228 }
10229
10230 static gboolean
10231 is_sre_ctor_builder (MonoClass *klass)
10232 {
10233         check_corlib_type_cached (klass, "System.Reflection.Emit", "ConstructorBuilder");
10234 }
10235
10236 static gboolean
10237 is_sre_field_builder (MonoClass *klass)
10238 {
10239         check_corlib_type_cached (klass, "System.Reflection.Emit", "FieldBuilder");
10240 }
10241
10242 static gboolean
10243 is_sre_method_on_tb_inst (MonoClass *klass)
10244 {
10245         check_corlib_type_cached (klass, "System.Reflection.Emit", "MethodOnTypeBuilderInst");
10246 }
10247
10248 static gboolean
10249 is_sre_ctor_on_tb_inst (MonoClass *klass)
10250 {
10251         check_corlib_type_cached (klass, "System.Reflection.Emit", "ConstructorOnTypeBuilderInst");
10252 }
10253
10254 MonoType*
10255 mono_reflection_type_get_handle (MonoReflectionType* ref)
10256 {
10257         MonoError error;
10258         MonoClass *klass;
10259         if (!ref)
10260                 return NULL;
10261         if (ref->type)
10262                 return ref->type;
10263
10264         if (is_usertype (ref)) {
10265                 ref = mono_reflection_type_get_underlying_system_type (ref, &error);
10266                 mono_error_raise_exception (&error); /* FIXME don't raise here */
10267                 if (ref == NULL || is_usertype (ref))
10268                         return NULL;
10269                 if (ref->type)
10270                         return ref->type;
10271         }
10272
10273         klass = mono_object_class (ref);
10274
10275         if (is_sre_array (klass)) {
10276                 MonoType *res;
10277                 MonoReflectionArrayType *sre_array = (MonoReflectionArrayType*)ref;
10278                 MonoType *base = mono_reflection_type_get_handle (sre_array->element_type);
10279                 g_assert (base);
10280                 if (sre_array->rank == 0) //single dimentional array
10281                         res = &mono_array_class_get (mono_class_from_mono_type (base), 1)->byval_arg;
10282                 else
10283                         res = &mono_bounded_array_class_get (mono_class_from_mono_type (base), sre_array->rank, TRUE)->byval_arg;
10284                 sre_array->type.type = res;
10285                 return res;
10286         } else if (is_sre_byref (klass)) {
10287                 MonoType *res;
10288                 MonoReflectionDerivedType *sre_byref = (MonoReflectionDerivedType*)ref;
10289                 MonoType *base = mono_reflection_type_get_handle (sre_byref->element_type);
10290                 g_assert (base);
10291                 res = &mono_class_from_mono_type (base)->this_arg;
10292                 sre_byref->type.type = res;
10293                 return res;
10294         } else if (is_sre_pointer (klass)) {
10295                 MonoType *res;
10296                 MonoReflectionDerivedType *sre_pointer = (MonoReflectionDerivedType*)ref;
10297                 MonoType *base = mono_reflection_type_get_handle (sre_pointer->element_type);
10298                 g_assert (base);
10299                 res = &mono_ptr_class_get (base)->byval_arg;
10300                 sre_pointer->type.type = res;
10301                 return res;
10302         } else if (is_sre_generic_instance (klass)) {
10303                 MonoType *res, **types;
10304                 MonoReflectionGenericClass *gclass = (MonoReflectionGenericClass*)ref;
10305                 int i, count;
10306
10307                 count = mono_array_length (gclass->type_arguments);
10308                 types = g_new0 (MonoType*, count);
10309                 for (i = 0; i < count; ++i) {
10310                         MonoReflectionType *t = (MonoReflectionType *)mono_array_get (gclass->type_arguments, gpointer, i);
10311                         types [i] = mono_reflection_type_get_handle (t);
10312                         if (!types[i]) {
10313                                 g_free (types);
10314                                 return NULL;
10315                         }
10316                 }
10317
10318                 res = mono_reflection_bind_generic_parameters (gclass->generic_type, count, types);
10319                 g_free (types);
10320                 g_assert (res);
10321                 gclass->type.type = res;
10322                 return res;
10323         }
10324
10325         g_error ("Cannot handle corlib user type %s", mono_type_full_name (&mono_object_class(ref)->byval_arg));
10326         return NULL;
10327 }
10328
10329
10330
10331 void
10332 mono_reflection_create_unmanaged_type (MonoReflectionType *type)
10333 {
10334         mono_reflection_type_get_handle (type);
10335 }
10336
10337 void
10338 mono_reflection_register_with_runtime (MonoReflectionType *type)
10339 {
10340         MonoType *res = mono_reflection_type_get_handle (type);
10341         MonoDomain *domain = mono_object_domain ((MonoObject*)type);
10342         MonoClass *klass;
10343
10344         if (!res)
10345                 mono_raise_exception (mono_get_exception_argument (NULL, "Invalid generic instantiation, one or more arguments are not proper user types"));
10346
10347         klass = mono_class_from_mono_type (res);
10348
10349         mono_loader_lock (); /*same locking as mono_type_get_object_checked */
10350         mono_domain_lock (domain);
10351
10352         if (!image_is_dynamic (klass->image)) {
10353                 mono_class_setup_supertypes (klass);
10354         } else {
10355                 if (!domain->type_hash)
10356                         domain->type_hash = mono_g_hash_table_new_type ((GHashFunc)mono_metadata_type_hash, 
10357                                         (GCompareFunc)mono_metadata_type_equal, MONO_HASH_VALUE_GC, MONO_ROOT_SOURCE_DOMAIN, "domain reflection types table");
10358                 mono_g_hash_table_insert (domain->type_hash, res, type);
10359         }
10360         mono_domain_unlock (domain);
10361         mono_loader_unlock ();
10362 }
10363
10364 /**
10365  * LOCKING: Assumes the loader lock is held.
10366  */
10367 static MonoMethodSignature*
10368 parameters_to_signature (MonoImage *image, MonoArray *parameters) {
10369         MonoMethodSignature *sig;
10370         int count, i;
10371
10372         count = parameters? mono_array_length (parameters): 0;
10373
10374         sig = (MonoMethodSignature *)image_g_malloc0 (image, MONO_SIZEOF_METHOD_SIGNATURE + sizeof (MonoType*) * count);
10375         sig->param_count = count;
10376         sig->sentinelpos = -1; /* FIXME */
10377         for (i = 0; i < count; ++i)
10378                 sig->params [i] = mono_type_array_get_and_resolve (parameters, i);
10379         return sig;
10380 }
10381
10382 /**
10383  * LOCKING: Assumes the loader lock is held.
10384  */
10385 static MonoMethodSignature*
10386 ctor_builder_to_signature (MonoImage *image, MonoReflectionCtorBuilder *ctor) {
10387         MonoMethodSignature *sig;
10388
10389         sig = parameters_to_signature (image, ctor->parameters);
10390         sig->hasthis = ctor->attrs & METHOD_ATTRIBUTE_STATIC? 0: 1;
10391         sig->ret = &mono_defaults.void_class->byval_arg;
10392         return sig;
10393 }
10394
10395 /**
10396  * LOCKING: Assumes the loader lock is held.
10397  */
10398 static MonoMethodSignature*
10399 method_builder_to_signature (MonoImage *image, MonoReflectionMethodBuilder *method) {
10400         MonoMethodSignature *sig;
10401
10402         sig = parameters_to_signature (image, method->parameters);
10403         sig->hasthis = method->attrs & METHOD_ATTRIBUTE_STATIC? 0: 1;
10404         sig->ret = method->rtype? mono_reflection_type_get_handle ((MonoReflectionType*)method->rtype): &mono_defaults.void_class->byval_arg;
10405         sig->generic_param_count = method->generic_params ? mono_array_length (method->generic_params) : 0;
10406         return sig;
10407 }
10408
10409 static MonoMethodSignature*
10410 dynamic_method_to_signature (MonoReflectionDynamicMethod *method) {
10411         MonoMethodSignature *sig;
10412
10413         sig = parameters_to_signature (NULL, method->parameters);
10414         sig->hasthis = method->attrs & METHOD_ATTRIBUTE_STATIC? 0: 1;
10415         sig->ret = method->rtype? mono_reflection_type_get_handle (method->rtype): &mono_defaults.void_class->byval_arg;
10416         sig->generic_param_count = 0;
10417         return sig;
10418 }
10419
10420 static void
10421 get_prop_name_and_type (MonoObject *prop, char **name, MonoType **type)
10422 {
10423         MonoClass *klass = mono_object_class (prop);
10424         if (strcmp (klass->name, "PropertyBuilder") == 0) {
10425                 MonoReflectionPropertyBuilder *pb = (MonoReflectionPropertyBuilder *)prop;
10426                 *name = mono_string_to_utf8 (pb->name);
10427                 *type = mono_reflection_type_get_handle ((MonoReflectionType*)pb->type);
10428         } else {
10429                 MonoReflectionProperty *p = (MonoReflectionProperty *)prop;
10430                 *name = g_strdup (p->property->name);
10431                 if (p->property->get)
10432                         *type = mono_method_signature (p->property->get)->ret;
10433                 else
10434                         *type = mono_method_signature (p->property->set)->params [mono_method_signature (p->property->set)->param_count - 1];
10435         }
10436 }
10437
10438 static void
10439 get_field_name_and_type (MonoObject *field, char **name, MonoType **type)
10440 {
10441         MonoClass *klass = mono_object_class (field);
10442         if (strcmp (klass->name, "FieldBuilder") == 0) {
10443                 MonoReflectionFieldBuilder *fb = (MonoReflectionFieldBuilder *)field;
10444                 *name = mono_string_to_utf8 (fb->name);
10445                 *type = mono_reflection_type_get_handle ((MonoReflectionType*)fb->type);
10446         } else {
10447                 MonoReflectionField *f = (MonoReflectionField *)field;
10448                 *name = g_strdup (mono_field_get_name (f->field));
10449                 *type = f->field->type;
10450         }
10451 }
10452
10453 #else /* DISABLE_REFLECTION_EMIT */
10454
10455 void
10456 mono_reflection_register_with_runtime (MonoReflectionType *type)
10457 {
10458         /* This is empty */
10459 }
10460
10461 static gboolean
10462 is_sre_type_builder (MonoClass *klass)
10463 {
10464         return FALSE;
10465 }
10466
10467 static gboolean
10468 is_sre_generic_instance (MonoClass *klass)
10469 {
10470         return FALSE;
10471 }
10472
10473 static void
10474 init_type_builder_generics (MonoObject *type)
10475 {
10476 }
10477
10478 #endif /* !DISABLE_REFLECTION_EMIT */
10479
10480
10481 static gboolean
10482 is_sr_mono_field (MonoClass *klass)
10483 {
10484         check_corlib_type_cached (klass, "System.Reflection", "MonoField");
10485 }
10486
10487 static gboolean
10488 is_sr_mono_property (MonoClass *klass)
10489 {
10490         check_corlib_type_cached (klass, "System.Reflection", "MonoProperty");
10491 }
10492
10493 static gboolean
10494 is_sr_mono_method (MonoClass *klass)
10495 {
10496         check_corlib_type_cached (klass, "System.Reflection", "MonoMethod");
10497 }
10498
10499 static gboolean
10500 is_sr_mono_cmethod (MonoClass *klass)
10501 {
10502         check_corlib_type_cached (klass, "System.Reflection", "MonoCMethod");
10503 }
10504
10505 static gboolean
10506 is_sr_mono_generic_method (MonoClass *klass)
10507 {
10508         check_corlib_type_cached (klass, "System.Reflection", "MonoGenericMethod");
10509 }
10510
10511 static gboolean
10512 is_sr_mono_generic_cmethod (MonoClass *klass)
10513 {
10514         check_corlib_type_cached (klass, "System.Reflection", "MonoGenericCMethod");
10515 }
10516
10517 gboolean
10518 mono_class_is_reflection_method_or_constructor (MonoClass *klass)
10519 {
10520         return is_sr_mono_method (klass) || is_sr_mono_cmethod (klass) || is_sr_mono_generic_method (klass) || is_sr_mono_generic_cmethod (klass);
10521 }
10522
10523 static gboolean
10524 is_usertype (MonoReflectionType *ref)
10525 {
10526         MonoClass *klass = mono_object_class (ref);
10527         return klass->image != mono_defaults.corlib || strcmp ("TypeDelegator", klass->name) == 0;
10528 }
10529
10530 static MonoReflectionType*
10531 mono_reflection_type_resolve_user_types (MonoReflectionType *type, MonoError *error)
10532 {
10533         mono_error_init (error);
10534         if (!type || type->type)
10535                 return type;
10536
10537         if (is_usertype (type)) {
10538                 type = mono_reflection_type_get_underlying_system_type (type, error);
10539                 return_val_if_nok (error, NULL);
10540                 if (is_usertype (type)) {
10541                         mono_error_set_generic_error (error, "System", "NotSupportedException", "User defined subclasses of System.Type are not yet supported22");
10542                         return NULL;
10543                 }
10544         }
10545
10546         return type;
10547 }
10548 /*
10549  * Encode a value in a custom attribute stream of bytes.
10550  * The value to encode is either supplied as an object in argument val
10551  * (valuetypes are boxed), or as a pointer to the data in the
10552  * argument argval.
10553  * @type represents the type of the value
10554  * @buffer is the start of the buffer
10555  * @p the current position in the buffer
10556  * @buflen contains the size of the buffer and is used to return the new buffer size
10557  * if this needs to be realloced.
10558  * @retbuffer and @retp return the start and the position of the buffer
10559  */
10560 static void
10561 encode_cattr_value (MonoAssembly *assembly, char *buffer, char *p, char **retbuffer, char **retp, guint32 *buflen, MonoType *type, MonoObject *arg, char *argval)
10562 {
10563         MonoTypeEnum simple_type;
10564         
10565         if ((p-buffer) + 10 >= *buflen) {
10566                 char *newbuf;
10567                 *buflen *= 2;
10568                 newbuf = (char *)g_realloc (buffer, *buflen);
10569                 p = newbuf + (p-buffer);
10570                 buffer = newbuf;
10571         }
10572         if (!argval)
10573                 argval = ((char*)arg + sizeof (MonoObject));
10574         simple_type = type->type;
10575 handle_enum:
10576         switch (simple_type) {
10577         case MONO_TYPE_BOOLEAN:
10578         case MONO_TYPE_U1:
10579         case MONO_TYPE_I1:
10580                 *p++ = *argval;
10581                 break;
10582         case MONO_TYPE_CHAR:
10583         case MONO_TYPE_U2:
10584         case MONO_TYPE_I2:
10585                 swap_with_size (p, argval, 2, 1);
10586                 p += 2;
10587                 break;
10588         case MONO_TYPE_U4:
10589         case MONO_TYPE_I4:
10590         case MONO_TYPE_R4:
10591                 swap_with_size (p, argval, 4, 1);
10592                 p += 4;
10593                 break;
10594         case MONO_TYPE_R8:
10595                 swap_with_size (p, argval, 8, 1);
10596                 p += 8;
10597                 break;
10598         case MONO_TYPE_U8:
10599         case MONO_TYPE_I8:
10600                 swap_with_size (p, argval, 8, 1);
10601                 p += 8;
10602                 break;
10603         case MONO_TYPE_VALUETYPE:
10604                 if (type->data.klass->enumtype) {
10605                         simple_type = mono_class_enum_basetype (type->data.klass)->type;
10606                         goto handle_enum;
10607                 } else {
10608                         g_warning ("generic valutype %s not handled in custom attr value decoding", type->data.klass->name);
10609                 }
10610                 break;
10611         case MONO_TYPE_STRING: {
10612                 char *str;
10613                 guint32 slen;
10614                 if (!arg) {
10615                         *p++ = 0xFF;
10616                         break;
10617                 }
10618                 str = mono_string_to_utf8 ((MonoString*)arg);
10619                 slen = strlen (str);
10620                 if ((p-buffer) + 10 + slen >= *buflen) {
10621                         char *newbuf;
10622                         *buflen *= 2;
10623                         *buflen += slen;
10624                         newbuf = (char *)g_realloc (buffer, *buflen);
10625                         p = newbuf + (p-buffer);
10626                         buffer = newbuf;
10627                 }
10628                 mono_metadata_encode_value (slen, p, &p);
10629                 memcpy (p, str, slen);
10630                 p += slen;
10631                 g_free (str);
10632                 break;
10633         }
10634         case MONO_TYPE_CLASS: {
10635                 char *str;
10636                 guint32 slen;
10637                 if (!arg) {
10638                         *p++ = 0xFF;
10639                         break;
10640                 }
10641 handle_type:
10642                 str = type_get_qualified_name (mono_reflection_type_get_handle ((MonoReflectionType*)arg), NULL);
10643                 slen = strlen (str);
10644                 if ((p-buffer) + 10 + slen >= *buflen) {
10645                         char *newbuf;
10646                         *buflen *= 2;
10647                         *buflen += slen;
10648                         newbuf = (char *)g_realloc (buffer, *buflen);
10649                         p = newbuf + (p-buffer);
10650                         buffer = newbuf;
10651                 }
10652                 mono_metadata_encode_value (slen, p, &p);
10653                 memcpy (p, str, slen);
10654                 p += slen;
10655                 g_free (str);
10656                 break;
10657         }
10658         case MONO_TYPE_SZARRAY: {
10659                 int len, i;
10660                 MonoClass *eclass, *arg_eclass;
10661
10662                 if (!arg) {
10663                         *p++ = 0xff; *p++ = 0xff; *p++ = 0xff; *p++ = 0xff;
10664                         break;
10665                 }
10666                 len = mono_array_length ((MonoArray*)arg);
10667                 *p++ = len & 0xff;
10668                 *p++ = (len >> 8) & 0xff;
10669                 *p++ = (len >> 16) & 0xff;
10670                 *p++ = (len >> 24) & 0xff;
10671                 *retp = p;
10672                 *retbuffer = buffer;
10673                 eclass = type->data.klass;
10674                 arg_eclass = mono_object_class (arg)->element_class;
10675
10676                 if (!eclass) {
10677                         /* Happens when we are called from the MONO_TYPE_OBJECT case below */
10678                         eclass = mono_defaults.object_class;
10679                 }
10680                 if (eclass == mono_defaults.object_class && arg_eclass->valuetype) {
10681                         char *elptr = mono_array_addr ((MonoArray*)arg, char, 0);
10682                         int elsize = mono_class_array_element_size (arg_eclass);
10683                         for (i = 0; i < len; ++i) {
10684                                 encode_cattr_value (assembly, buffer, p, &buffer, &p, buflen, &arg_eclass->byval_arg, NULL, elptr);
10685                                 elptr += elsize;
10686                         }
10687                 } else if (eclass->valuetype && arg_eclass->valuetype) {
10688                         char *elptr = mono_array_addr ((MonoArray*)arg, char, 0);
10689                         int elsize = mono_class_array_element_size (eclass);
10690                         for (i = 0; i < len; ++i) {
10691                                 encode_cattr_value (assembly, buffer, p, &buffer, &p, buflen, &eclass->byval_arg, NULL, elptr);
10692                                 elptr += elsize;
10693                         }
10694                 } else {
10695                         for (i = 0; i < len; ++i) {
10696                                 encode_cattr_value (assembly, buffer, p, &buffer, &p, buflen, &eclass->byval_arg, mono_array_get ((MonoArray*)arg, MonoObject*, i), NULL);
10697                         }
10698                 }
10699                 break;
10700         }
10701         case MONO_TYPE_OBJECT: {
10702                 MonoClass *klass;
10703                 char *str;
10704                 guint32 slen;
10705
10706                 /*
10707                  * The parameter type is 'object' but the type of the actual
10708                  * argument is not. So we have to add type information to the blob
10709                  * too. This is completely undocumented in the spec.
10710                  */
10711
10712                 if (arg == NULL) {
10713                         *p++ = MONO_TYPE_STRING;        // It's same hack as MS uses
10714                         *p++ = 0xFF;
10715                         break;
10716                 }
10717                 
10718                 klass = mono_object_class (arg);
10719
10720                 if (mono_object_isinst (arg, mono_defaults.systemtype_class)) {
10721                         *p++ = 0x50;
10722                         goto handle_type;
10723                 } else if (klass->enumtype) {
10724                         *p++ = 0x55;
10725                 } else if (klass == mono_defaults.string_class) {
10726                         simple_type = MONO_TYPE_STRING;
10727                         *p++ = 0x0E;
10728                         goto handle_enum;
10729                 } else if (klass->rank == 1) {
10730                         *p++ = 0x1D;
10731                         if (klass->element_class->byval_arg.type == MONO_TYPE_OBJECT)
10732                                 /* See Partition II, Appendix B3 */
10733                                 *p++ = 0x51;
10734                         else
10735                                 *p++ = klass->element_class->byval_arg.type;
10736                         encode_cattr_value (assembly, buffer, p, &buffer, &p, buflen, &klass->byval_arg, arg, NULL);
10737                         break;
10738                 } else if (klass->byval_arg.type >= MONO_TYPE_BOOLEAN && klass->byval_arg.type <= MONO_TYPE_R8) {
10739                         *p++ = simple_type = klass->byval_arg.type;
10740                         goto handle_enum;
10741                 } else {
10742                         g_error ("unhandled type in custom attr");
10743                 }
10744                 str = type_get_qualified_name (mono_class_get_type(klass), NULL);
10745                 slen = strlen (str);
10746                 if ((p-buffer) + 10 + slen >= *buflen) {
10747                         char *newbuf;
10748                         *buflen *= 2;
10749                         *buflen += slen;
10750                         newbuf = (char *)g_realloc (buffer, *buflen);
10751                         p = newbuf + (p-buffer);
10752                         buffer = newbuf;
10753                 }
10754                 mono_metadata_encode_value (slen, p, &p);
10755                 memcpy (p, str, slen);
10756                 p += slen;
10757                 g_free (str);
10758                 simple_type = mono_class_enum_basetype (klass)->type;
10759                 goto handle_enum;
10760         }
10761         default:
10762                 g_error ("type 0x%02x not yet supported in custom attr encoder", simple_type);
10763         }
10764         *retp = p;
10765         *retbuffer = buffer;
10766 }
10767
10768 static void
10769 encode_field_or_prop_type (MonoType *type, char *p, char **retp)
10770 {
10771         if (type->type == MONO_TYPE_VALUETYPE && type->data.klass->enumtype) {
10772                 char *str = type_get_qualified_name (type, NULL);
10773                 int slen = strlen (str);
10774
10775                 *p++ = 0x55;
10776                 /*
10777                  * This seems to be optional...
10778                  * *p++ = 0x80;
10779                  */
10780                 mono_metadata_encode_value (slen, p, &p);
10781                 memcpy (p, str, slen);
10782                 p += slen;
10783                 g_free (str);
10784         } else if (type->type == MONO_TYPE_OBJECT) {
10785                 *p++ = 0x51;
10786         } else if (type->type == MONO_TYPE_CLASS) {
10787                 /* it should be a type: encode_cattr_value () has the check */
10788                 *p++ = 0x50;
10789         } else {
10790                 mono_metadata_encode_value (type->type, p, &p);
10791                 if (type->type == MONO_TYPE_SZARRAY)
10792                         /* See the examples in Partition VI, Annex B */
10793                         encode_field_or_prop_type (&type->data.klass->byval_arg, p, &p);
10794         }
10795
10796         *retp = p;
10797 }
10798
10799 #ifndef DISABLE_REFLECTION_EMIT
10800 static void
10801 encode_named_val (MonoReflectionAssembly *assembly, char *buffer, char *p, char **retbuffer, char **retp, guint32 *buflen, MonoType *type, char *name, MonoObject *value)
10802 {
10803         int len;
10804         /* Preallocate a large enough buffer */
10805         if (type->type == MONO_TYPE_VALUETYPE && type->data.klass->enumtype) {
10806                 char *str = type_get_qualified_name (type, NULL);
10807                 len = strlen (str);
10808                 g_free (str);
10809         } else if (type->type == MONO_TYPE_SZARRAY && type->data.klass->enumtype) {
10810                 char *str = type_get_qualified_name (&type->data.klass->byval_arg, NULL);
10811                 len = strlen (str);
10812                 g_free (str);
10813         } else {
10814                 len = 0;
10815         }
10816         len += strlen (name);
10817
10818         if ((p-buffer) + 20 + len >= *buflen) {
10819                 char *newbuf;
10820                 *buflen *= 2;
10821                 *buflen += len;
10822                 newbuf = (char *)g_realloc (buffer, *buflen);
10823                 p = newbuf + (p-buffer);
10824                 buffer = newbuf;
10825         }
10826
10827         encode_field_or_prop_type (type, p, &p);
10828
10829         len = strlen (name);
10830         mono_metadata_encode_value (len, p, &p);
10831         memcpy (p, name, len);
10832         p += len;
10833         encode_cattr_value (assembly->assembly, buffer, p, &buffer, &p, buflen, type, value, NULL);
10834         *retp = p;
10835         *retbuffer = buffer;
10836 }
10837
10838 /*
10839  * mono_reflection_get_custom_attrs_blob:
10840  * @ctor: custom attribute constructor
10841  * @ctorArgs: arguments o the constructor
10842  * @properties:
10843  * @propValues:
10844  * @fields:
10845  * @fieldValues:
10846  * 
10847  * Creates the blob of data that needs to be saved in the metadata and that represents
10848  * the custom attributed described by @ctor, @ctorArgs etc.
10849  * Returns: a Byte array representing the blob of data.
10850  */
10851 MonoArray*
10852 mono_reflection_get_custom_attrs_blob (MonoReflectionAssembly *assembly, MonoObject *ctor, MonoArray *ctorArgs, MonoArray *properties, MonoArray *propValues, MonoArray *fields, MonoArray* fieldValues) 
10853 {
10854         MonoArray *result;
10855         MonoMethodSignature *sig;
10856         MonoObject *arg;
10857         char *buffer, *p;
10858         guint32 buflen, i;
10859
10860         if (strcmp (ctor->vtable->klass->name, "MonoCMethod")) {
10861                 /* sig is freed later so allocate it in the heap */
10862                 sig = ctor_builder_to_signature (NULL, (MonoReflectionCtorBuilder*)ctor);
10863         } else {
10864                 sig = mono_method_signature (((MonoReflectionMethod*)ctor)->method);
10865         }
10866
10867         g_assert (mono_array_length (ctorArgs) == sig->param_count);
10868         buflen = 256;
10869         p = buffer = (char *)g_malloc (buflen);
10870         /* write the prolog */
10871         *p++ = 1;
10872         *p++ = 0;
10873         for (i = 0; i < sig->param_count; ++i) {
10874                 arg = mono_array_get (ctorArgs, MonoObject*, i);
10875                 encode_cattr_value (assembly->assembly, buffer, p, &buffer, &p, &buflen, sig->params [i], arg, NULL);
10876         }
10877         i = 0;
10878         if (properties)
10879                 i += mono_array_length (properties);
10880         if (fields)
10881                 i += mono_array_length (fields);
10882         *p++ = i & 0xff;
10883         *p++ = (i >> 8) & 0xff;
10884         if (properties) {
10885                 MonoObject *prop;
10886                 for (i = 0; i < mono_array_length (properties); ++i) {
10887                         MonoType *ptype;
10888                         char *pname;
10889
10890                         prop = (MonoObject *)mono_array_get (properties, gpointer, i);
10891                         get_prop_name_and_type (prop, &pname, &ptype);
10892                         *p++ = 0x54; /* PROPERTY signature */
10893                         encode_named_val (assembly, buffer, p, &buffer, &p, &buflen, ptype, pname, (MonoObject*)mono_array_get (propValues, gpointer, i));
10894                         g_free (pname);
10895                 }
10896         }
10897
10898         if (fields) {
10899                 MonoObject *field;
10900                 for (i = 0; i < mono_array_length (fields); ++i) {
10901                         MonoType *ftype;
10902                         char *fname;
10903
10904                         field = (MonoObject *)mono_array_get (fields, gpointer, i);
10905                         get_field_name_and_type (field, &fname, &ftype);
10906                         *p++ = 0x53; /* FIELD signature */
10907                         encode_named_val (assembly, buffer, p, &buffer, &p, &buflen, ftype, fname, (MonoObject*)mono_array_get (fieldValues, gpointer, i));
10908                         g_free (fname);
10909                 }
10910         }
10911
10912         g_assert (p - buffer <= buflen);
10913         buflen = p - buffer;
10914         result = mono_array_new (mono_domain_get (), mono_defaults.byte_class, buflen);
10915         p = mono_array_addr (result, char, 0);
10916         memcpy (p, buffer, buflen);
10917         g_free (buffer);
10918         if (strcmp (ctor->vtable->klass->name, "MonoCMethod"))
10919                 g_free (sig);
10920         return result;
10921 }
10922
10923 /*
10924  * mono_reflection_setup_internal_class:
10925  * @tb: a TypeBuilder object
10926  *
10927  * Creates a MonoClass that represents the TypeBuilder.
10928  * This is a trick that lets us simplify a lot of reflection code
10929  * (and will allow us to support Build and Run assemblies easier).
10930  */
10931 void
10932 mono_reflection_setup_internal_class (MonoReflectionTypeBuilder *tb)
10933 {
10934         MonoError error;
10935         MonoClass *klass, *parent;
10936
10937         RESOLVE_TYPE (tb->parent, &error);
10938         mono_error_raise_exception (&error); /* FIXME don't raise here */
10939
10940         mono_loader_lock ();
10941
10942         if (tb->parent) {
10943                 /* check so we can compile corlib correctly */
10944                 if (strcmp (mono_object_class (tb->parent)->name, "TypeBuilder") == 0) {
10945                         /* mono_class_setup_mono_type () guaranteess type->data.klass is valid */
10946                         parent = mono_reflection_type_get_handle ((MonoReflectionType*)tb->parent)->data.klass;
10947                 } else {
10948                         parent = mono_class_from_mono_type (mono_reflection_type_get_handle ((MonoReflectionType*)tb->parent));
10949                 }
10950         } else {
10951                 parent = NULL;
10952         }
10953         
10954         /* the type has already being created: it means we just have to change the parent */
10955         if (tb->type.type) {
10956                 klass = mono_class_from_mono_type (tb->type.type);
10957                 klass->parent = NULL;
10958                 /* fool mono_class_setup_parent */
10959                 klass->supertypes = NULL;
10960                 mono_class_setup_parent (klass, parent);
10961                 mono_class_setup_mono_type (klass);
10962                 mono_loader_unlock ();
10963                 return;
10964         }
10965
10966         klass = (MonoClass *)mono_image_alloc0 (&tb->module->dynamic_image->image, sizeof (MonoClass));
10967
10968         klass->image = &tb->module->dynamic_image->image;
10969
10970         klass->inited = 1; /* we lie to the runtime */
10971         klass->name = mono_string_to_utf8_image (klass->image, tb->name, &error);
10972         if (!mono_error_ok (&error))
10973                 goto failure;
10974         klass->name_space = mono_string_to_utf8_image (klass->image, tb->nspace, &error);
10975         if (!mono_error_ok (&error))
10976                 goto failure;
10977         klass->type_token = MONO_TOKEN_TYPE_DEF | tb->table_idx;
10978         klass->flags = tb->attrs;
10979         
10980         mono_profiler_class_event (klass, MONO_PROFILE_START_LOAD);
10981
10982         klass->element_class = klass;
10983
10984         if (mono_class_get_ref_info (klass) == NULL) {
10985
10986                 mono_class_set_ref_info (klass, tb);
10987
10988                 /* Put into cache so mono_class_get_checked () will find it.
10989                 Skip nested types as those should not be available on the global scope. */
10990                 if (!tb->nesting_type)
10991                         mono_image_add_to_name_cache (klass->image, klass->name_space, klass->name, tb->table_idx);
10992
10993                 /*
10994                 We must register all types as we cannot rely on the name_cache hashtable since we find the class
10995                 by performing a mono_class_get which does the full resolution.
10996
10997                 Working around this semantics would require us to write a lot of code for no clear advantage.
10998                 */
10999                 mono_image_append_class_to_reflection_info_set (klass);
11000         } else {
11001                 g_assert (mono_class_get_ref_info (klass) == tb);
11002         }
11003
11004         register_dyn_token (tb->module->dynamic_image, MONO_TOKEN_TYPE_DEF | tb->table_idx, (MonoObject*)tb);
11005
11006         if (parent != NULL) {
11007                 mono_class_setup_parent (klass, parent);
11008         } else if (strcmp (klass->name, "Object") == 0 && strcmp (klass->name_space, "System") == 0) {
11009                 const char *old_n = klass->name;
11010                 /* trick to get relative numbering right when compiling corlib */
11011                 klass->name = "BuildingObject";
11012                 mono_class_setup_parent (klass, mono_defaults.object_class);
11013                 klass->name = old_n;
11014         }
11015
11016         if ((!strcmp (klass->name, "ValueType") && !strcmp (klass->name_space, "System")) ||
11017                         (!strcmp (klass->name, "Object") && !strcmp (klass->name_space, "System")) ||
11018                         (!strcmp (klass->name, "Enum") && !strcmp (klass->name_space, "System"))) {
11019                 klass->instance_size = sizeof (MonoObject);
11020                 klass->size_inited = 1;
11021                 mono_class_setup_vtable_general (klass, NULL, 0, NULL);
11022         }
11023
11024         mono_class_setup_mono_type (klass);
11025
11026         mono_class_setup_supertypes (klass);
11027
11028         /*
11029          * FIXME: handle interfaces.
11030          */
11031
11032         tb->type.type = &klass->byval_arg;
11033
11034         if (tb->nesting_type) {
11035                 g_assert (tb->nesting_type->type);
11036                 klass->nested_in = mono_class_from_mono_type (mono_reflection_type_get_handle (tb->nesting_type));
11037         }
11038
11039         /*g_print ("setup %s as %s (%p)\n", klass->name, ((MonoObject*)tb)->vtable->klass->name, tb);*/
11040
11041         mono_profiler_class_loaded (klass, MONO_PROFILE_OK);
11042         
11043         mono_loader_unlock ();
11044         return;
11045
11046 failure:
11047         mono_loader_unlock ();
11048         mono_error_raise_exception (&error);
11049 }
11050
11051 /*
11052  * mono_reflection_setup_generic_class:
11053  * @tb: a TypeBuilder object
11054  *
11055  * Setup the generic class before adding the first generic parameter.
11056  */
11057 void
11058 mono_reflection_setup_generic_class (MonoReflectionTypeBuilder *tb)
11059 {
11060 }
11061
11062 /*
11063  * mono_reflection_create_generic_class:
11064  * @tb: a TypeBuilder object
11065  *
11066  * Creates the generic class after all generic parameters have been added.
11067  */
11068 void
11069 mono_reflection_create_generic_class (MonoReflectionTypeBuilder *tb)
11070 {
11071         MonoClass *klass;
11072         int count, i;
11073
11074         klass = mono_class_from_mono_type (tb->type.type);
11075
11076         count = tb->generic_params ? mono_array_length (tb->generic_params) : 0;
11077
11078         if (klass->generic_container || (count == 0))
11079                 return;
11080
11081         g_assert (tb->generic_container && (tb->generic_container->owner.klass == klass));
11082
11083         klass->generic_container = (MonoGenericContainer *)mono_image_alloc0 (klass->image, sizeof (MonoGenericContainer));
11084
11085         klass->generic_container->owner.klass = klass;
11086         klass->generic_container->type_argc = count;
11087         klass->generic_container->type_params = (MonoGenericParamFull *)mono_image_alloc0 (klass->image, sizeof (MonoGenericParamFull) * count);
11088
11089         klass->is_generic = 1;
11090
11091         for (i = 0; i < count; i++) {
11092                 MonoReflectionGenericParam *gparam = (MonoReflectionGenericParam *)mono_array_get (tb->generic_params, gpointer, i);
11093                 MonoGenericParamFull *param = (MonoGenericParamFull *) mono_reflection_type_get_handle ((MonoReflectionType*)gparam)->data.generic_param;
11094                 klass->generic_container->type_params [i] = *param;
11095                 /*Make sure we are a diferent type instance */
11096                 klass->generic_container->type_params [i].param.owner = klass->generic_container;
11097                 klass->generic_container->type_params [i].info.pklass = NULL;
11098                 klass->generic_container->type_params [i].info.flags = gparam->attrs;
11099
11100                 g_assert (klass->generic_container->type_params [i].param.owner);
11101         }
11102
11103         klass->generic_container->context.class_inst = mono_get_shared_generic_inst (klass->generic_container);
11104 }
11105
11106 /*
11107  * mono_reflection_create_internal_class:
11108  * @tb: a TypeBuilder object
11109  *
11110  * Actually create the MonoClass that is associated with the TypeBuilder.
11111  */
11112 void
11113 mono_reflection_create_internal_class (MonoReflectionTypeBuilder *tb)
11114 {
11115         MonoClass *klass;
11116
11117         klass = mono_class_from_mono_type (tb->type.type);
11118
11119         mono_loader_lock ();
11120         if (klass->enumtype && mono_class_enum_basetype (klass) == NULL) {
11121                 MonoReflectionFieldBuilder *fb;
11122                 MonoClass *ec;
11123                 MonoType *enum_basetype;
11124
11125                 g_assert (tb->fields != NULL);
11126                 g_assert (mono_array_length (tb->fields) >= 1);
11127
11128                 fb = mono_array_get (tb->fields, MonoReflectionFieldBuilder*, 0);
11129
11130                 if (!mono_type_is_valid_enum_basetype (mono_reflection_type_get_handle ((MonoReflectionType*)fb->type))) {
11131                         mono_loader_unlock ();
11132                         return;
11133                 }
11134
11135                 enum_basetype = mono_reflection_type_get_handle ((MonoReflectionType*)fb->type);
11136                 klass->element_class = mono_class_from_mono_type (enum_basetype);
11137                 if (!klass->element_class)
11138                         klass->element_class = mono_class_from_mono_type (enum_basetype);
11139
11140                 /*
11141                  * get the element_class from the current corlib.
11142                  */
11143                 ec = default_class_from_mono_type (enum_basetype);
11144                 klass->instance_size = ec->instance_size;
11145                 klass->size_inited = 1;
11146                 /* 
11147                  * this is almost safe to do with enums and it's needed to be able
11148                  * to create objects of the enum type (for use in SetConstant).
11149                  */
11150                 /* FIXME: Does this mean enums can't have method overrides ? */
11151                 mono_class_setup_vtable_general (klass, NULL, 0, NULL);
11152         }
11153         mono_loader_unlock ();
11154 }
11155
11156 static MonoMarshalSpec*
11157 mono_marshal_spec_from_builder (MonoImage *image, MonoAssembly *assembly,
11158                                                                 MonoReflectionMarshal *minfo)
11159 {
11160         MonoMarshalSpec *res;
11161
11162         res = image_g_new0 (image, MonoMarshalSpec, 1);
11163         res->native = (MonoMarshalNative)minfo->type;
11164
11165         switch (minfo->type) {
11166         case MONO_NATIVE_LPARRAY:
11167                 res->data.array_data.elem_type = (MonoMarshalNative)minfo->eltype;
11168                 if (minfo->has_size) {
11169                         res->data.array_data.param_num = minfo->param_num;
11170                         res->data.array_data.num_elem = minfo->count;
11171                         res->data.array_data.elem_mult = minfo->param_num == -1 ? 0 : 1;
11172                 }
11173                 else {
11174                         res->data.array_data.param_num = -1;
11175                         res->data.array_data.num_elem = -1;
11176                         res->data.array_data.elem_mult = -1;
11177                 }
11178                 break;
11179
11180         case MONO_NATIVE_BYVALTSTR:
11181         case MONO_NATIVE_BYVALARRAY:
11182                 res->data.array_data.num_elem = minfo->count;
11183                 break;
11184
11185         case MONO_NATIVE_CUSTOM:
11186                 if (minfo->marshaltyperef)
11187                         res->data.custom_data.custom_name =
11188                                 type_get_fully_qualified_name (mono_reflection_type_get_handle ((MonoReflectionType*)minfo->marshaltyperef));
11189                 if (minfo->mcookie)
11190                         res->data.custom_data.cookie = mono_string_to_utf8 (minfo->mcookie);
11191                 break;
11192
11193         default:
11194                 break;
11195         }
11196
11197         return res;
11198 }
11199 #endif /* !DISABLE_REFLECTION_EMIT */
11200
11201 MonoReflectionMarshalAsAttribute*
11202 mono_reflection_marshal_as_attribute_from_marshal_spec (MonoDomain *domain, MonoClass *klass,
11203                                                         MonoMarshalSpec *spec, MonoError *error)
11204 {
11205         MonoReflectionType *rt;
11206         MonoReflectionMarshalAsAttribute *minfo;
11207         MonoType *mtype;
11208
11209         mono_error_init (error);
11210         
11211         minfo = (MonoReflectionMarshalAsAttribute*)mono_object_new_checked (domain, mono_class_get_marshal_as_attribute_class (), error);
11212         if (!minfo)
11213                 return NULL;
11214         minfo->utype = spec->native;
11215
11216         switch (minfo->utype) {
11217         case MONO_NATIVE_LPARRAY:
11218                 minfo->array_subtype = spec->data.array_data.elem_type;
11219                 minfo->size_const = spec->data.array_data.num_elem;
11220                 if (spec->data.array_data.param_num != -1)
11221                         minfo->size_param_index = spec->data.array_data.param_num;
11222                 break;
11223
11224         case MONO_NATIVE_BYVALTSTR:
11225         case MONO_NATIVE_BYVALARRAY:
11226                 minfo->size_const = spec->data.array_data.num_elem;
11227                 break;
11228
11229         case MONO_NATIVE_CUSTOM:
11230                 if (spec->data.custom_data.custom_name) {
11231                         mtype = mono_reflection_type_from_name (spec->data.custom_data.custom_name, klass->image);
11232                         if (mtype) {
11233                                 rt = mono_type_get_object_checked (domain, mtype, error);
11234                                 if (!rt)
11235                                         return NULL;
11236
11237                                 MONO_OBJECT_SETREF (minfo, marshal_type_ref, rt);
11238                         }
11239
11240                         MONO_OBJECT_SETREF (minfo, marshal_type, mono_string_new (domain, spec->data.custom_data.custom_name));
11241                 }
11242                 if (spec->data.custom_data.cookie)
11243                         MONO_OBJECT_SETREF (minfo, marshal_cookie, mono_string_new (domain, spec->data.custom_data.cookie));
11244                 break;
11245
11246         default:
11247                 break;
11248         }
11249
11250         return minfo;
11251 }
11252
11253 #ifndef DISABLE_REFLECTION_EMIT
11254 static MonoMethod*
11255 reflection_methodbuilder_to_mono_method (MonoClass *klass,
11256                                          ReflectionMethodBuilder *rmb,
11257                                          MonoMethodSignature *sig)
11258 {
11259         MonoError error;
11260         MonoMethod *m;
11261         MonoMethodWrapper *wrapperm;
11262         MonoMarshalSpec **specs;
11263         MonoReflectionMethodAux *method_aux;
11264         MonoImage *image;
11265         gboolean dynamic;
11266         int i;
11267
11268         mono_error_init (&error);
11269         /*
11270          * Methods created using a MethodBuilder should have their memory allocated
11271          * inside the image mempool, while dynamic methods should have their memory
11272          * malloc'd.
11273          */
11274         dynamic = rmb->refs != NULL;
11275         image = dynamic ? NULL : klass->image;
11276
11277         if (!dynamic)
11278                 g_assert (!klass->generic_class);
11279
11280         mono_loader_lock ();
11281
11282         if ((rmb->attrs & METHOD_ATTRIBUTE_PINVOKE_IMPL) ||
11283                         (rmb->iattrs & METHOD_IMPL_ATTRIBUTE_INTERNAL_CALL))
11284                 m = (MonoMethod *)image_g_new0 (image, MonoMethodPInvoke, 1);
11285         else
11286                 m = (MonoMethod *)image_g_new0 (image, MonoMethodWrapper, 1);
11287
11288         wrapperm = (MonoMethodWrapper*)m;
11289
11290         m->dynamic = dynamic;
11291         m->slot = -1;
11292         m->flags = rmb->attrs;
11293         m->iflags = rmb->iattrs;
11294         m->name = mono_string_to_utf8_image_ignore (image, rmb->name);
11295         m->klass = klass;
11296         m->signature = sig;
11297         m->sre_method = TRUE;
11298         m->skip_visibility = rmb->skip_visibility;
11299         if (rmb->table_idx)
11300                 m->token = MONO_TOKEN_METHOD_DEF | (*rmb->table_idx);
11301
11302         if (m->iflags & METHOD_IMPL_ATTRIBUTE_INTERNAL_CALL) {
11303                 if (klass == mono_defaults.string_class && !strcmp (m->name, ".ctor"))
11304                         m->string_ctor = 1;
11305
11306                 m->signature->pinvoke = 1;
11307         } else if (m->flags & METHOD_ATTRIBUTE_PINVOKE_IMPL) {
11308                 m->signature->pinvoke = 1;
11309
11310                 method_aux = image_g_new0 (image, MonoReflectionMethodAux, 1);
11311
11312                 method_aux->dllentry = rmb->dllentry ? mono_string_to_utf8_image (image, rmb->dllentry, &error) : image_strdup (image, m->name);
11313                 g_assert (mono_error_ok (&error));
11314                 method_aux->dll = mono_string_to_utf8_image (image, rmb->dll, &error);
11315                 g_assert (mono_error_ok (&error));
11316                 
11317                 ((MonoMethodPInvoke*)m)->piflags = (rmb->native_cc << 8) | (rmb->charset ? (rmb->charset - 1) * 2 : 0) | rmb->extra_flags;
11318
11319                 if (image_is_dynamic (klass->image))
11320                         g_hash_table_insert (((MonoDynamicImage*)klass->image)->method_aux_hash, m, method_aux);
11321
11322                 mono_loader_unlock ();
11323
11324                 return m;
11325         } else if (!(m->flags & METHOD_ATTRIBUTE_ABSTRACT) &&
11326                            !(m->iflags & METHOD_IMPL_ATTRIBUTE_RUNTIME)) {
11327                 MonoMethodHeader *header;
11328                 guint32 code_size;
11329                 gint32 max_stack, i;
11330                 gint32 num_locals = 0;
11331                 gint32 num_clauses = 0;
11332                 guint8 *code;
11333
11334                 if (rmb->ilgen) {
11335                         code = mono_array_addr (rmb->ilgen->code, guint8, 0);
11336                         code_size = rmb->ilgen->code_len;
11337                         max_stack = rmb->ilgen->max_stack;
11338                         num_locals = rmb->ilgen->locals ? mono_array_length (rmb->ilgen->locals) : 0;
11339                         if (rmb->ilgen->ex_handlers)
11340                                 num_clauses = method_count_clauses (rmb->ilgen);
11341                 } else {
11342                         if (rmb->code) {
11343                                 code = mono_array_addr (rmb->code, guint8, 0);
11344                                 code_size = mono_array_length (rmb->code);
11345                                 /* we probably need to run a verifier on the code... */
11346                                 max_stack = 8; 
11347                         }
11348                         else {
11349                                 code = NULL;
11350                                 code_size = 0;
11351                                 max_stack = 8;
11352                         }
11353                 }
11354
11355                 header = (MonoMethodHeader *)image_g_malloc0 (image, MONO_SIZEOF_METHOD_HEADER + num_locals * sizeof (MonoType*));
11356                 header->code_size = code_size;
11357                 header->code = (const unsigned char *)image_g_malloc (image, code_size);
11358                 memcpy ((char*)header->code, code, code_size);
11359                 header->max_stack = max_stack;
11360                 header->init_locals = rmb->init_locals;
11361                 header->num_locals = num_locals;
11362
11363                 for (i = 0; i < num_locals; ++i) {
11364                         MonoReflectionLocalBuilder *lb = 
11365                                 mono_array_get (rmb->ilgen->locals, MonoReflectionLocalBuilder*, i);
11366
11367                         header->locals [i] = image_g_new0 (image, MonoType, 1);
11368                         memcpy (header->locals [i], mono_reflection_type_get_handle ((MonoReflectionType*)lb->type), MONO_SIZEOF_TYPE);
11369                 }
11370
11371                 header->num_clauses = num_clauses;
11372                 if (num_clauses) {
11373                         header->clauses = method_encode_clauses (image, (MonoDynamicImage*)klass->image,
11374                                  rmb->ilgen, num_clauses);
11375                 }
11376
11377                 wrapperm->header = header;
11378         }
11379
11380         if (rmb->generic_params) {
11381                 int count = mono_array_length (rmb->generic_params);
11382                 MonoGenericContainer *container = rmb->generic_container;
11383
11384                 g_assert (container);
11385
11386                 container->type_argc = count;
11387                 container->type_params = image_g_new0 (image, MonoGenericParamFull, count);
11388                 container->owner.method = m;
11389                 container->is_anonymous = FALSE; // Method is now known, container is no longer anonymous
11390
11391                 m->is_generic = TRUE;
11392                 mono_method_set_generic_container (m, container);
11393
11394                 for (i = 0; i < count; i++) {
11395                         MonoReflectionGenericParam *gp =
11396                                 mono_array_get (rmb->generic_params, MonoReflectionGenericParam*, i);
11397                         MonoGenericParamFull *param = (MonoGenericParamFull *) mono_reflection_type_get_handle ((MonoReflectionType*)gp)->data.generic_param;
11398                         container->type_params [i] = *param;
11399                 }
11400
11401                 /*
11402                  * The method signature might have pointers to generic parameters that belong to other methods.
11403                  * This is a valid SRE case, but the resulting method signature must be encoded using the proper
11404                  * generic parameters.
11405                  */
11406                 for (i = 0; i < m->signature->param_count; ++i) {
11407                         MonoType *t = m->signature->params [i];
11408                         if (t->type == MONO_TYPE_MVAR) {
11409                                 MonoGenericParam *gparam =  t->data.generic_param;
11410                                 if (gparam->num < count) {
11411                                         m->signature->params [i] = mono_metadata_type_dup (image, m->signature->params [i]);
11412                                         m->signature->params [i]->data.generic_param = mono_generic_container_get_param (container, gparam->num);
11413                                 }
11414
11415                         }
11416                 }
11417
11418                 if (klass->generic_container) {
11419                         container->parent = klass->generic_container;
11420                         container->context.class_inst = klass->generic_container->context.class_inst;
11421                 }
11422                 container->context.method_inst = mono_get_shared_generic_inst (container);
11423         }
11424
11425         if (rmb->refs) {
11426                 MonoMethodWrapper *mw = (MonoMethodWrapper*)m;
11427                 int i;
11428                 void **data;
11429
11430                 m->wrapper_type = MONO_WRAPPER_DYNAMIC_METHOD;
11431
11432                 mw->method_data = data = image_g_new (image, gpointer, rmb->nrefs + 1);
11433                 data [0] = GUINT_TO_POINTER (rmb->nrefs);
11434                 for (i = 0; i < rmb->nrefs; ++i)
11435                         data [i + 1] = rmb->refs [i];
11436         }
11437
11438         method_aux = NULL;
11439
11440         /* Parameter info */
11441         if (rmb->pinfo) {
11442                 if (!method_aux)
11443                         method_aux = image_g_new0 (image, MonoReflectionMethodAux, 1);
11444                 method_aux->param_names = image_g_new0 (image, char *, mono_method_signature (m)->param_count + 1);
11445                 for (i = 0; i <= m->signature->param_count; ++i) {
11446                         MonoReflectionParamBuilder *pb;
11447                         if ((pb = mono_array_get (rmb->pinfo, MonoReflectionParamBuilder*, i))) {
11448                                 if ((i > 0) && (pb->attrs)) {
11449                                         /* Make a copy since it might point to a shared type structure */
11450                                         m->signature->params [i - 1] = mono_metadata_type_dup (klass->image, m->signature->params [i - 1]);
11451                                         m->signature->params [i - 1]->attrs = pb->attrs;
11452                                 }
11453
11454                                 if (pb->attrs & PARAM_ATTRIBUTE_HAS_DEFAULT) {
11455                                         MonoDynamicImage *assembly;
11456                                         guint32 idx, len;
11457                                         MonoTypeEnum def_type;
11458                                         char *p;
11459                                         const char *p2;
11460
11461                                         if (!method_aux->param_defaults) {
11462                                                 method_aux->param_defaults = image_g_new0 (image, guint8*, m->signature->param_count + 1);
11463                                                 method_aux->param_default_types = image_g_new0 (image, guint32, m->signature->param_count + 1);
11464                                         }
11465                                         assembly = (MonoDynamicImage*)klass->image;
11466                                         idx = encode_constant (assembly, pb->def_value, &def_type);
11467                                         /* Copy the data from the blob since it might get realloc-ed */
11468                                         p = assembly->blob.data + idx;
11469                                         len = mono_metadata_decode_blob_size (p, &p2);
11470                                         len += p2 - p;
11471                                         method_aux->param_defaults [i] = (uint8_t *)image_g_malloc (image, len);
11472                                         method_aux->param_default_types [i] = def_type;
11473                                         memcpy ((gpointer)method_aux->param_defaults [i], p, len);
11474                                 }
11475
11476                                 if (pb->name) {
11477                                         method_aux->param_names [i] = mono_string_to_utf8_image (image, pb->name, &error);
11478                                         g_assert (mono_error_ok (&error));
11479                                 }
11480                                 if (pb->cattrs) {
11481                                         if (!method_aux->param_cattr)
11482                                                 method_aux->param_cattr = image_g_new0 (image, MonoCustomAttrInfo*, m->signature->param_count + 1);
11483                                         method_aux->param_cattr [i] = mono_custom_attrs_from_builders (image, klass->image, pb->cattrs);
11484                                 }
11485                         }
11486                 }
11487         }
11488
11489         /* Parameter marshalling */
11490         specs = NULL;
11491         if (rmb->pinfo)         
11492                 for (i = 0; i < mono_array_length (rmb->pinfo); ++i) {
11493                         MonoReflectionParamBuilder *pb;
11494                         if ((pb = mono_array_get (rmb->pinfo, MonoReflectionParamBuilder*, i))) {
11495                                 if (pb->marshal_info) {
11496                                         if (specs == NULL)
11497                                                 specs = image_g_new0 (image, MonoMarshalSpec*, sig->param_count + 1);
11498                                         specs [pb->position] = 
11499                                                 mono_marshal_spec_from_builder (image, klass->image->assembly, pb->marshal_info);
11500                                 }
11501                         }
11502                 }
11503         if (specs != NULL) {
11504                 if (!method_aux)
11505                         method_aux = image_g_new0 (image, MonoReflectionMethodAux, 1);
11506                 method_aux->param_marshall = specs;
11507         }
11508
11509         if (image_is_dynamic (klass->image) && method_aux)
11510                 g_hash_table_insert (((MonoDynamicImage*)klass->image)->method_aux_hash, m, method_aux);
11511
11512         mono_loader_unlock ();
11513
11514         return m;
11515 }       
11516
11517 static MonoMethod*
11518 ctorbuilder_to_mono_method (MonoClass *klass, MonoReflectionCtorBuilder* mb, MonoError *error)
11519 {
11520         ReflectionMethodBuilder rmb;
11521         MonoMethodSignature *sig;
11522
11523         mono_loader_lock ();
11524         sig = ctor_builder_to_signature (klass->image, mb);
11525         mono_loader_unlock ();
11526
11527         if (!reflection_methodbuilder_from_ctor_builder (&rmb, mb, error))
11528                 return NULL;
11529
11530         mb->mhandle = reflection_methodbuilder_to_mono_method (klass, &rmb, sig);
11531         mono_save_custom_attrs (klass->image, mb->mhandle, mb->cattrs);
11532
11533         /* If we are in a generic class, we might be called multiple times from inflate_method */
11534         if (!((MonoDynamicImage*)(MonoDynamicImage*)klass->image)->save && !klass->generic_container) {
11535                 /* ilgen is no longer needed */
11536                 mb->ilgen = NULL;
11537         }
11538
11539         return mb->mhandle;
11540 }
11541
11542 static MonoMethod*
11543 methodbuilder_to_mono_method (MonoClass *klass, MonoReflectionMethodBuilder* mb, MonoError *error)
11544 {
11545         ReflectionMethodBuilder rmb;
11546         MonoMethodSignature *sig;
11547
11548         mono_error_init (error);
11549
11550         mono_loader_lock ();
11551         sig = method_builder_to_signature (klass->image, mb);
11552         mono_loader_unlock ();
11553
11554         if (!reflection_methodbuilder_from_method_builder (&rmb, mb, error))
11555                 return NULL;
11556
11557         mb->mhandle = reflection_methodbuilder_to_mono_method (klass, &rmb, sig);
11558         mono_save_custom_attrs (klass->image, mb->mhandle, mb->cattrs);
11559
11560         /* If we are in a generic class, we might be called multiple times from inflate_method */
11561         if (!((MonoDynamicImage*)(MonoDynamicImage*)klass->image)->save && !klass->generic_container) {
11562                 /* ilgen is no longer needed */
11563                 mb->ilgen = NULL;
11564         }
11565         return mb->mhandle;
11566 }
11567
11568 static MonoClassField*
11569 fieldbuilder_to_mono_class_field (MonoClass *klass, MonoReflectionFieldBuilder* fb)
11570 {
11571         MonoClassField *field;
11572         MonoType *custom;
11573         MonoError error;
11574
11575         field = g_new0 (MonoClassField, 1);
11576
11577         field->name = mono_string_to_utf8_image (klass->image, fb->name, &error);
11578         g_assert (mono_error_ok (&error));
11579         if (fb->attrs || fb->modreq || fb->modopt) {
11580                 field->type = mono_metadata_type_dup (NULL, mono_reflection_type_get_handle ((MonoReflectionType*)fb->type));
11581                 field->type->attrs = fb->attrs;
11582
11583                 g_assert (image_is_dynamic (klass->image));
11584                 custom = add_custom_modifiers ((MonoDynamicImage*)klass->image, field->type, fb->modreq, fb->modopt);
11585                 g_free (field->type);
11586                 field->type = mono_metadata_type_dup (klass->image, custom);
11587                 g_free (custom);
11588         } else {
11589                 field->type = mono_reflection_type_get_handle ((MonoReflectionType*)fb->type);
11590         }
11591         if (fb->offset != -1)
11592                 field->offset = fb->offset;
11593         field->parent = klass;
11594         mono_save_custom_attrs (klass->image, field, fb->cattrs);
11595
11596         // FIXME: Can't store fb->def_value/RVA, is it needed for field_on_insts ?
11597
11598         return field;
11599 }
11600 #endif
11601
11602 MonoType*
11603 mono_reflection_bind_generic_parameters (MonoReflectionType *type, int type_argc, MonoType **types)
11604 {
11605         MonoClass *klass;
11606         MonoReflectionTypeBuilder *tb = NULL;
11607         gboolean is_dynamic = FALSE;
11608         MonoClass *geninst;
11609
11610         mono_loader_lock ();
11611
11612         if (is_sre_type_builder (mono_object_class (type))) {
11613                 tb = (MonoReflectionTypeBuilder *) type;
11614
11615                 is_dynamic = TRUE;
11616         } else if (is_sre_generic_instance (mono_object_class (type))) {
11617                 MonoReflectionGenericClass *rgi = (MonoReflectionGenericClass *) type;
11618                 MonoReflectionType *gtd = rgi->generic_type;
11619
11620                 if (is_sre_type_builder (mono_object_class (gtd))) {
11621                         tb = (MonoReflectionTypeBuilder *)gtd;
11622                         is_dynamic = TRUE;
11623                 }
11624         }
11625
11626         /* FIXME: fix the CreateGenericParameters protocol to avoid the two stage setup of TypeBuilders */
11627         if (tb && tb->generic_container)
11628                 mono_reflection_create_generic_class (tb);
11629
11630         klass = mono_class_from_mono_type (mono_reflection_type_get_handle (type));
11631         if (!klass->generic_container) {
11632                 mono_loader_unlock ();
11633                 return NULL;
11634         }
11635
11636         if (klass->wastypebuilder) {
11637                 tb = (MonoReflectionTypeBuilder *) mono_class_get_ref_info (klass);
11638
11639                 is_dynamic = TRUE;
11640         }
11641
11642         mono_loader_unlock ();
11643
11644         geninst = mono_class_bind_generic_parameters (klass, type_argc, types, is_dynamic);
11645
11646         return &geninst->byval_arg;
11647 }
11648
11649 MonoClass*
11650 mono_class_bind_generic_parameters (MonoClass *klass, int type_argc, MonoType **types, gboolean is_dynamic)
11651 {
11652         MonoGenericClass *gclass;
11653         MonoGenericInst *inst;
11654
11655         g_assert (klass->generic_container);
11656
11657         inst = mono_metadata_get_generic_inst (type_argc, types);
11658         gclass = mono_metadata_lookup_generic_class (klass, inst, is_dynamic);
11659
11660         return mono_generic_class_get_class (gclass);
11661 }
11662
11663 MonoReflectionMethod*
11664 mono_reflection_bind_generic_method_parameters (MonoReflectionMethod *rmethod, MonoArray *types)
11665 {
11666         MonoError error;
11667         MonoClass *klass;
11668         MonoMethod *method, *inflated;
11669         MonoMethodInflated *imethod;
11670         MonoGenericContext tmp_context;
11671         MonoGenericInst *ginst;
11672         MonoType **type_argv;
11673         int count, i;
11674
11675         /*FIXME but this no longer should happen*/
11676         if (!strcmp (rmethod->object.vtable->klass->name, "MethodBuilder")) {
11677 #ifndef DISABLE_REFLECTION_EMIT
11678                 MonoReflectionMethodBuilder *mb = NULL;
11679                 MonoReflectionTypeBuilder *tb;
11680                 MonoClass *klass;
11681
11682                 mb = (MonoReflectionMethodBuilder *) rmethod;
11683                 tb = (MonoReflectionTypeBuilder *) mb->type;
11684                 klass = mono_class_from_mono_type (mono_reflection_type_get_handle ((MonoReflectionType*)tb));
11685
11686                 method = methodbuilder_to_mono_method (klass, mb, &error);
11687                 if (!method)
11688                         mono_error_raise_exception (&error); /* FIXME don't raise here */
11689 #else
11690                 g_assert_not_reached ();
11691                 method = NULL;
11692 #endif
11693         } else {
11694                 method = rmethod->method;
11695         }
11696
11697         klass = method->klass;
11698
11699         if (method->is_inflated)
11700                 method = ((MonoMethodInflated *) method)->declaring;
11701
11702         count = mono_method_signature (method)->generic_param_count;
11703         if (count != mono_array_length (types))
11704                 return NULL;
11705
11706         type_argv = g_new0 (MonoType *, count);
11707         for (i = 0; i < count; i++) {
11708                 MonoReflectionType *garg = (MonoReflectionType *)mono_array_get (types, gpointer, i);
11709                 type_argv [i] = mono_reflection_type_get_handle (garg);
11710         }
11711         ginst = mono_metadata_get_generic_inst (count, type_argv);
11712         g_free (type_argv);
11713
11714         tmp_context.class_inst = klass->generic_class ? klass->generic_class->context.class_inst : NULL;
11715         tmp_context.method_inst = ginst;
11716
11717         inflated = mono_class_inflate_generic_method_checked (method, &tmp_context, &error);
11718         g_assert (mono_error_ok (&error)); /* FIXME don't swallow the error */
11719         imethod = (MonoMethodInflated *) inflated;
11720
11721         /*FIXME but I think this is no longer necessary*/
11722         if (image_is_dynamic (method->klass->image)) {
11723                 MonoDynamicImage *image = (MonoDynamicImage*)method->klass->image;
11724                 /*
11725                  * This table maps metadata structures representing inflated methods/fields
11726                  * to the reflection objects representing their generic definitions.
11727                  */
11728                 mono_image_lock ((MonoImage*)image);
11729                 mono_g_hash_table_insert (image->generic_def_objects, imethod, rmethod);
11730                 mono_image_unlock ((MonoImage*)image);
11731         }
11732
11733         if (!mono_verifier_is_method_valid_generic_instantiation (inflated))
11734                 mono_raise_exception (mono_get_exception_argument ("typeArguments", "Invalid generic arguments"));
11735         
11736         MonoReflectionMethod *ret = mono_method_get_object_checked (mono_object_domain (rmethod), inflated, NULL, &error);
11737         mono_error_raise_exception (&error); /* FIXME don't raise here */
11738         return ret;
11739 }
11740
11741 #ifndef DISABLE_REFLECTION_EMIT
11742
11743 static MonoMethod *
11744 inflate_mono_method (MonoClass *klass, MonoMethod *method, MonoObject *obj)
11745 {
11746         MonoMethodInflated *imethod;
11747         MonoGenericContext *context;
11748         int i;
11749
11750         /*
11751          * With generic code sharing the klass might not be inflated.
11752          * This can happen because classes inflated with their own
11753          * type arguments are "normalized" to the uninflated class.
11754          */
11755         if (!klass->generic_class)
11756                 return method;
11757
11758         context = mono_class_get_context (klass);
11759
11760         if (klass->method.count && klass->methods) {
11761                 /* Find the already created inflated method */
11762                 for (i = 0; i < klass->method.count; ++i) {
11763                         g_assert (klass->methods [i]->is_inflated);
11764                         if (((MonoMethodInflated*)klass->methods [i])->declaring == method)
11765                                 break;
11766                 }
11767                 g_assert (i < klass->method.count);
11768                 imethod = (MonoMethodInflated*)klass->methods [i];
11769         } else {
11770                 MonoError error;
11771                 imethod = (MonoMethodInflated *) mono_class_inflate_generic_method_full_checked (method, klass, context, &error);
11772                 mono_error_assert_ok (&error);
11773         }
11774
11775         if (method->is_generic && image_is_dynamic (method->klass->image)) {
11776                 MonoDynamicImage *image = (MonoDynamicImage*)method->klass->image;
11777
11778                 mono_image_lock ((MonoImage*)image);
11779                 mono_g_hash_table_insert (image->generic_def_objects, imethod, obj);
11780                 mono_image_unlock ((MonoImage*)image);
11781         }
11782         return (MonoMethod *) imethod;
11783 }
11784
11785 static MonoMethod *
11786 inflate_method (MonoReflectionType *type, MonoObject *obj, MonoError *error)
11787 {
11788         MonoMethod *method;
11789         MonoClass *gklass;
11790
11791         mono_error_init (error);
11792
11793         MonoClass *type_class = mono_object_class (type);
11794
11795         if (is_sre_generic_instance (type_class)) {
11796                 MonoReflectionGenericClass *mgc = (MonoReflectionGenericClass*)type;
11797                 gklass = mono_class_from_mono_type (mono_reflection_type_get_handle ((MonoReflectionType*)mgc->generic_type));
11798         } else if (is_sre_type_builder (type_class)) {
11799                 gklass = mono_class_from_mono_type (mono_reflection_type_get_handle (type));
11800         } else if (type->type) {
11801                 gklass = mono_class_from_mono_type (type->type);
11802                 gklass = mono_class_get_generic_type_definition (gklass);
11803         } else {
11804                 g_error ("Can't handle type %s", mono_type_get_full_name (mono_object_class (type)));
11805         }
11806
11807         if (!strcmp (obj->vtable->klass->name, "MethodBuilder"))
11808                 if (((MonoReflectionMethodBuilder*)obj)->mhandle)
11809                         method = ((MonoReflectionMethodBuilder*)obj)->mhandle;
11810                 else {
11811                         method = methodbuilder_to_mono_method (gklass, (MonoReflectionMethodBuilder *) obj, error);
11812                         if (!method)
11813                                 return NULL;
11814                 }
11815         else if (!strcmp (obj->vtable->klass->name, "ConstructorBuilder")) {
11816                 method = ctorbuilder_to_mono_method (gklass, (MonoReflectionCtorBuilder *) obj, error);
11817                 if (!method)
11818                         return NULL;
11819         } else if (!strcmp (obj->vtable->klass->name, "MonoMethod") || !strcmp (obj->vtable->klass->name, "MonoCMethod"))
11820                 method = ((MonoReflectionMethod *) obj)->method;
11821         else {
11822                 method = NULL; /* prevent compiler warning */
11823                 g_error ("can't handle type %s", obj->vtable->klass->name);
11824         }
11825
11826         return inflate_mono_method (mono_class_from_mono_type (mono_reflection_type_get_handle ((MonoReflectionType*)type)), method, obj);
11827 }
11828
11829 /*TODO avoid saving custom attrs for generic classes as it's enough to have them on the generic type definition.*/
11830 void
11831 mono_reflection_generic_class_initialize (MonoReflectionGenericClass *type, MonoArray *fields)
11832 {
11833         MonoGenericClass *gclass;
11834         MonoDynamicGenericClass *dgclass;
11835         MonoClass *klass, *gklass;
11836         MonoType *gtype;
11837         int i;
11838
11839         gtype = mono_reflection_type_get_handle ((MonoReflectionType*)type);
11840         klass = mono_class_from_mono_type (gtype);
11841         g_assert (gtype->type == MONO_TYPE_GENERICINST);
11842         gclass = gtype->data.generic_class;
11843
11844         if (!gclass->is_dynamic)
11845                 return;
11846
11847         dgclass = (MonoDynamicGenericClass *) gclass;
11848
11849         if (dgclass->initialized)
11850                 return;
11851
11852         gklass = gclass->container_class;
11853         mono_class_init (gklass);
11854
11855         dgclass->count_fields = fields ? mono_array_length (fields) : 0;
11856
11857         dgclass->fields = mono_image_set_new0 (gclass->owner, MonoClassField, dgclass->count_fields);
11858         dgclass->field_objects = mono_image_set_new0 (gclass->owner, MonoObject*, dgclass->count_fields);
11859         dgclass->field_generic_types = mono_image_set_new0 (gclass->owner, MonoType*, dgclass->count_fields);
11860
11861         for (i = 0; i < dgclass->count_fields; i++) {
11862                 MonoError error;
11863                 MonoObject *obj = (MonoObject *)mono_array_get (fields, gpointer, i);
11864                 MonoClassField *field, *inflated_field = NULL;
11865
11866                 if (!strcmp (obj->vtable->klass->name, "FieldBuilder"))
11867                         inflated_field = field = fieldbuilder_to_mono_class_field (klass, (MonoReflectionFieldBuilder *) obj);
11868                 else if (!strcmp (obj->vtable->klass->name, "MonoField"))
11869                         field = ((MonoReflectionField *) obj)->field;
11870                 else {
11871                         field = NULL; /* prevent compiler warning */
11872                         g_assert_not_reached ();
11873                 }
11874
11875                 dgclass->fields [i] = *field;
11876                 dgclass->fields [i].parent = klass;
11877                 dgclass->fields [i].type = mono_class_inflate_generic_type_checked (
11878                         field->type, mono_generic_class_get_context ((MonoGenericClass *) dgclass), &error);
11879                 mono_error_assert_ok (&error); /* FIXME don't swallow the error */
11880                 dgclass->field_generic_types [i] = field->type;
11881                 MONO_GC_REGISTER_ROOT_IF_MOVING (dgclass->field_objects [i], MONO_ROOT_SOURCE_REFLECTION, "dynamic generic class field object");
11882                 dgclass->field_objects [i] = obj;
11883
11884                 if (inflated_field) {
11885                         g_free (inflated_field);
11886                 } else {
11887                         dgclass->fields [i].name = mono_image_set_strdup (gclass->owner, dgclass->fields [i].name);
11888                 }
11889         }
11890
11891         dgclass->initialized = TRUE;
11892 }
11893
11894 void
11895 mono_reflection_free_dynamic_generic_class (MonoGenericClass *gclass)
11896 {
11897         MonoDynamicGenericClass *dgclass;
11898         int i;
11899
11900         g_assert (gclass->is_dynamic);
11901
11902         dgclass = (MonoDynamicGenericClass *)gclass;
11903
11904         for (i = 0; i < dgclass->count_fields; ++i) {
11905                 MonoClassField *field = dgclass->fields + i;
11906                 mono_metadata_free_type (field->type);
11907                 MONO_GC_UNREGISTER_ROOT_IF_MOVING (dgclass->field_objects [i]);
11908         }
11909 }
11910
11911 static void
11912 fix_partial_generic_class (MonoClass *klass)
11913 {
11914         MonoClass *gklass = klass->generic_class->container_class;
11915         MonoDynamicGenericClass *dgclass;
11916         int i;
11917
11918         if (klass->wastypebuilder)
11919                 return;
11920
11921         dgclass = (MonoDynamicGenericClass *)  klass->generic_class;
11922         if (klass->parent != gklass->parent) {
11923                 MonoError error;
11924                 MonoType *parent_type = mono_class_inflate_generic_type_checked (&gklass->parent->byval_arg, &klass->generic_class->context, &error);
11925                 if (mono_error_ok (&error)) {
11926                         MonoClass *parent = mono_class_from_mono_type (parent_type);
11927                         mono_metadata_free_type (parent_type);
11928                         if (parent != klass->parent) {
11929                                 /*fool mono_class_setup_parent*/
11930                                 klass->supertypes = NULL;
11931                                 mono_class_setup_parent (klass, parent);
11932                         }
11933                 } else {
11934                         mono_class_set_failure (klass, MONO_EXCEPTION_TYPE_LOAD, NULL);
11935                         mono_error_cleanup (&error);
11936                         if (gklass->wastypebuilder)
11937                                 klass->wastypebuilder = TRUE;
11938                         return;
11939                 }
11940         }
11941
11942         if (!dgclass->initialized)
11943                 return;
11944
11945         if (klass->method.count != gklass->method.count) {
11946                 klass->method.count = gklass->method.count;
11947                 klass->methods = (MonoMethod **)mono_image_alloc (klass->image, sizeof (MonoMethod*) * (klass->method.count + 1));
11948
11949                 for (i = 0; i < klass->method.count; i++) {
11950                         MonoError error;
11951                         klass->methods [i] = mono_class_inflate_generic_method_full_checked (
11952                                 gklass->methods [i], klass, mono_class_get_context (klass), &error);
11953                         g_assert (mono_error_ok (&error)); /* FIXME don't swallow the error */
11954                 }
11955         }
11956
11957         if (klass->interface_count && klass->interface_count != gklass->interface_count) {
11958                 klass->interface_count = gklass->interface_count;
11959                 klass->interfaces = (MonoClass **)mono_image_alloc (klass->image, sizeof (MonoClass*) * gklass->interface_count);
11960                 klass->interfaces_packed = NULL; /*make setup_interface_offsets happy*/
11961
11962                 for (i = 0; i < gklass->interface_count; ++i) {
11963                         MonoError error;
11964                         MonoType *iface_type = mono_class_inflate_generic_type_checked (&gklass->interfaces [i]->byval_arg, mono_class_get_context (klass), &error);
11965                         mono_error_raise_exception (&error); /* FIXME don't raise here */
11966
11967                         klass->interfaces [i] = mono_class_from_mono_type (iface_type);
11968                         mono_metadata_free_type (iface_type);
11969
11970                         ensure_runtime_vtable (klass->interfaces [i], &error);
11971                         mono_error_raise_exception (&error); /* FIXME don't raise here */
11972                 }
11973                 klass->interfaces_inited = 1;
11974         }
11975
11976         if (klass->field.count != gklass->field.count) {
11977                 klass->field.count = gklass->field.count;
11978                 klass->fields = image_g_new0 (klass->image, MonoClassField, klass->field.count);
11979
11980                 for (i = 0; i < klass->field.count; i++) {
11981                         MonoError error;
11982                         klass->fields [i] = gklass->fields [i];
11983                         klass->fields [i].parent = klass;
11984                         klass->fields [i].type = mono_class_inflate_generic_type_checked (gklass->fields [i].type, mono_class_get_context (klass), &error);
11985                         mono_error_raise_exception (&error); /* FIXME don't raise here */
11986                 }
11987         }
11988
11989         /*We can only finish with this klass once it's parent has as well*/
11990         if (gklass->wastypebuilder)
11991                 klass->wastypebuilder = TRUE;
11992         return;
11993 }
11994
11995 /**
11996  * ensure_generic_class_runtime_vtable:
11997  * @klass a generic class
11998  * @error set on error
11999  *
12000  * Ensures that the generic container of @klass has a vtable and
12001  * returns TRUE on success.  On error returns FALSE and sets @error.
12002  */
12003 static gboolean
12004 ensure_generic_class_runtime_vtable (MonoClass *klass, MonoError *error)
12005 {
12006         MonoClass *gklass = klass->generic_class->container_class;
12007
12008         mono_error_init (error);
12009
12010         if (!ensure_runtime_vtable (gklass, error))
12011                 return FALSE;
12012
12013         fix_partial_generic_class (klass);
12014
12015         return TRUE;
12016 }
12017
12018 /**
12019  * ensure_runtime_vtable:
12020  * @klass the class
12021  * @error set on error
12022  *
12023  * Ensures that @klass has a vtable and returns TRUE on success. On
12024  * error returns FALSE and sets @error.
12025  */
12026 static gboolean
12027 ensure_runtime_vtable (MonoClass *klass, MonoError *error)
12028 {
12029         MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder *)mono_class_get_ref_info (klass);
12030         int i, num, j;
12031
12032         mono_error_init (error);
12033
12034         if (!image_is_dynamic (klass->image) || (!tb && !klass->generic_class) || klass->wastypebuilder)
12035                 return TRUE;
12036         if (klass->parent)
12037                 if (!ensure_runtime_vtable (klass->parent, error))
12038                         return FALSE;
12039
12040         if (tb) {
12041                 num = tb->ctors? mono_array_length (tb->ctors): 0;
12042                 num += tb->num_methods;
12043                 klass->method.count = num;
12044                 klass->methods = (MonoMethod **)mono_image_alloc (klass->image, sizeof (MonoMethod*) * num);
12045                 num = tb->ctors? mono_array_length (tb->ctors): 0;
12046                 for (i = 0; i < num; ++i) {
12047                         MonoMethod *ctor = ctorbuilder_to_mono_method (klass, mono_array_get (tb->ctors, MonoReflectionCtorBuilder*, i), error);
12048                         if (!ctor)
12049                                 return FALSE;
12050                         klass->methods [i] = ctor;
12051                 }
12052                 num = tb->num_methods;
12053                 j = i;
12054                 for (i = 0; i < num; ++i) {
12055                         MonoMethod *meth = methodbuilder_to_mono_method (klass, mono_array_get (tb->methods, MonoReflectionMethodBuilder*, i), error);
12056                         if (!meth)
12057                                 return FALSE;
12058                         klass->methods [j++] = meth;
12059                 }
12060         
12061                 if (tb->interfaces) {
12062                         klass->interface_count = mono_array_length (tb->interfaces);
12063                         klass->interfaces = (MonoClass **)mono_image_alloc (klass->image, sizeof (MonoClass*) * klass->interface_count);
12064                         for (i = 0; i < klass->interface_count; ++i) {
12065                                 MonoType *iface = mono_type_array_get_and_resolve (tb->interfaces, i);
12066                                 klass->interfaces [i] = mono_class_from_mono_type (iface);
12067                                 if (!ensure_runtime_vtable (klass->interfaces [i], error))
12068                                         return FALSE;
12069                         }
12070                         klass->interfaces_inited = 1;
12071                 }
12072         } else if (klass->generic_class){
12073                 if (!ensure_generic_class_runtime_vtable (klass, error))
12074                         return FALSE;
12075         }
12076
12077         if (klass->flags & TYPE_ATTRIBUTE_INTERFACE) {
12078                 int slot_num = 0;
12079                 for (i = 0; i < klass->method.count; ++i) {
12080                         MonoMethod *im = klass->methods [i];
12081                         if (!(im->flags & METHOD_ATTRIBUTE_STATIC))
12082                                 im->slot = slot_num++;
12083                 }
12084                 
12085                 klass->interfaces_packed = NULL; /*make setup_interface_offsets happy*/
12086                 mono_class_setup_interface_offsets (klass);
12087                 mono_class_setup_interface_id (klass);
12088         }
12089
12090         /*
12091          * The generic vtable is needed even if image->run is not set since some
12092          * runtime code like ves_icall_Type_GetMethodsByName depends on 
12093          * method->slot being defined.
12094          */
12095
12096         /* 
12097          * tb->methods could not be freed since it is used for determining 
12098          * overrides during dynamic vtable construction.
12099          */
12100
12101         return TRUE;
12102 }
12103
12104 static MonoMethod*
12105 mono_reflection_method_get_handle (MonoObject *method)
12106 {
12107         MonoError error;
12108         MonoClass *klass = mono_object_class (method);
12109         if (is_sr_mono_method (klass) || is_sr_mono_generic_method (klass)) {
12110                 MonoReflectionMethod *sr_method = (MonoReflectionMethod*)method;
12111                 return sr_method->method;
12112         }
12113         if (is_sre_method_builder (klass)) {
12114                 MonoReflectionMethodBuilder *mb = (MonoReflectionMethodBuilder*)method;
12115                 return mb->mhandle;
12116         }
12117         if (is_sre_method_on_tb_inst (klass)) {
12118                 MonoReflectionMethodOnTypeBuilderInst *m = (MonoReflectionMethodOnTypeBuilderInst*)method;
12119                 MonoMethod *result;
12120                 /*FIXME move this to a proper method and unify with resolve_object*/
12121                 if (m->method_args) {
12122                         result = mono_reflection_method_on_tb_inst_get_handle (m, &error);
12123                         mono_error_raise_exception (&error); /* FIXME don't raise here */
12124                 } else {
12125                         MonoType *type = mono_reflection_type_get_handle ((MonoReflectionType*)m->inst);
12126                         MonoClass *inflated_klass = mono_class_from_mono_type (type);
12127                         MonoMethod *mono_method;
12128
12129                         if (is_sre_method_builder (mono_object_class (m->mb)))
12130                                 mono_method = ((MonoReflectionMethodBuilder *)m->mb)->mhandle;
12131                         else if (is_sr_mono_method (mono_object_class (m->mb)))
12132                                 mono_method = ((MonoReflectionMethod *)m->mb)->method;
12133                         else
12134                                 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)));
12135
12136                         result = inflate_mono_method (inflated_klass, mono_method, (MonoObject*)m->mb);
12137                 }
12138                 return result;
12139         }
12140
12141         g_error ("Can't handle methods of type %s:%s", klass->name_space, klass->name);
12142         return NULL;
12143 }
12144
12145 void
12146 mono_reflection_get_dynamic_overrides (MonoClass *klass, MonoMethod ***overrides, int *num_overrides)
12147 {
12148         MonoReflectionTypeBuilder *tb;
12149         int i, j, onum;
12150         MonoReflectionMethod *m;
12151
12152         *overrides = NULL;
12153         *num_overrides = 0;
12154
12155         g_assert (image_is_dynamic (klass->image));
12156
12157         if (!mono_class_get_ref_info (klass))
12158                 return;
12159
12160         g_assert (strcmp (((MonoObject*)mono_class_get_ref_info (klass))->vtable->klass->name, "TypeBuilder") == 0);
12161
12162         tb = (MonoReflectionTypeBuilder*)mono_class_get_ref_info (klass);
12163
12164         onum = 0;
12165         if (tb->methods) {
12166                 for (i = 0; i < tb->num_methods; ++i) {
12167                         MonoReflectionMethodBuilder *mb = 
12168                                 mono_array_get (tb->methods, MonoReflectionMethodBuilder*, i);
12169                         if (mb->override_methods)
12170                                 onum += mono_array_length (mb->override_methods);
12171                 }
12172         }
12173
12174         if (onum) {
12175                 *overrides = g_new0 (MonoMethod*, onum * 2);
12176
12177                 onum = 0;
12178                 for (i = 0; i < tb->num_methods; ++i) {
12179                         MonoReflectionMethodBuilder *mb = 
12180                                 mono_array_get (tb->methods, MonoReflectionMethodBuilder*, i);
12181                         if (mb->override_methods) {
12182                                 for (j = 0; j < mono_array_length (mb->override_methods); ++j) {
12183                                         m = mono_array_get (mb->override_methods, MonoReflectionMethod*, j);
12184
12185                                         (*overrides) [onum * 2] = mono_reflection_method_get_handle ((MonoObject*)m);
12186                                         (*overrides) [onum * 2 + 1] = mb->mhandle;
12187
12188                                         g_assert (mb->mhandle);
12189
12190                                         onum ++;
12191                                 }
12192                         }
12193                 }
12194         }
12195
12196         *num_overrides = onum;
12197 }
12198
12199 static void
12200 typebuilder_setup_fields (MonoClass *klass, MonoError *error)
12201 {
12202         MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder *)mono_class_get_ref_info (klass);
12203         MonoReflectionFieldBuilder *fb;
12204         MonoClassField *field;
12205         MonoImage *image = klass->image;
12206         const char *p, *p2;
12207         int i;
12208         guint32 len, idx, real_size = 0;
12209
12210         klass->field.count = tb->num_fields;
12211         klass->field.first = 0;
12212
12213         mono_error_init (error);
12214
12215         if (tb->class_size) {
12216                 if ((tb->packing_size & 0xffffff00) != 0) {
12217                         char *err_msg = g_strdup_printf ("Could not load struct '%s' with packing size %d >= 256", klass->name, tb->packing_size);
12218                         mono_class_set_failure (klass, MONO_EXCEPTION_TYPE_LOAD, err_msg);
12219                         return;
12220                 }
12221                 klass->packing_size = tb->packing_size;
12222                 real_size = klass->instance_size + tb->class_size;
12223         }
12224
12225         if (!klass->field.count) {
12226                 klass->instance_size = MAX (klass->instance_size, real_size);
12227                 return;
12228         }
12229         
12230         klass->fields = image_g_new0 (image, MonoClassField, klass->field.count);
12231         mono_class_alloc_ext (klass);
12232         klass->ext->field_def_values = image_g_new0 (image, MonoFieldDefaultValue, klass->field.count);
12233         /*
12234         This is, guess what, a hack.
12235         The issue is that the runtime doesn't know how to setup the fields of a typebuider and crash.
12236         On the static path no field class is resolved, only types are built. This is the right thing to do
12237         but we suck.
12238         Setting size_inited is harmless because we're doing the same job as mono_class_setup_fields anyway.
12239         */
12240         klass->size_inited = 1;
12241
12242         for (i = 0; i < klass->field.count; ++i) {
12243                 MonoArray *rva_data;
12244                 fb = (MonoReflectionFieldBuilder *)mono_array_get (tb->fields, gpointer, i);
12245                 field = &klass->fields [i];
12246                 field->name = mono_string_to_utf8_image (image, fb->name, error);
12247                 if (!mono_error_ok (error))
12248                         return;
12249                 if (fb->attrs) {
12250                         field->type = mono_metadata_type_dup (klass->image, mono_reflection_type_get_handle ((MonoReflectionType*)fb->type));
12251                         field->type->attrs = fb->attrs;
12252                 } else {
12253                         field->type = mono_reflection_type_get_handle ((MonoReflectionType*)fb->type);
12254                 }
12255
12256                 if ((fb->attrs & FIELD_ATTRIBUTE_HAS_FIELD_RVA) && (rva_data = fb->rva_data)) {
12257                         char *base = mono_array_addr (rva_data, char, 0);
12258                         size_t size = mono_array_length (rva_data);
12259                         char *data = (char *)mono_image_alloc (klass->image, size);
12260                         memcpy (data, base, size);
12261                         klass->ext->field_def_values [i].data = data;
12262                 }
12263                 if (fb->offset != -1)
12264                         field->offset = fb->offset;
12265                 field->parent = klass;
12266                 fb->handle = field;
12267                 mono_save_custom_attrs (klass->image, field, fb->cattrs);
12268
12269                 if (klass->enumtype && !(field->type->attrs & FIELD_ATTRIBUTE_STATIC)) {
12270                         klass->cast_class = klass->element_class = mono_class_from_mono_type (field->type);
12271                 }
12272                 if (fb->def_value) {
12273                         MonoDynamicImage *assembly = (MonoDynamicImage*)klass->image;
12274                         field->type->attrs |= FIELD_ATTRIBUTE_HAS_DEFAULT;
12275                         idx = encode_constant (assembly, fb->def_value, &klass->ext->field_def_values [i].def_type);
12276                         /* Copy the data from the blob since it might get realloc-ed */
12277                         p = assembly->blob.data + idx;
12278                         len = mono_metadata_decode_blob_size (p, &p2);
12279                         len += p2 - p;
12280                         klass->ext->field_def_values [i].data = (const char *)mono_image_alloc (image, len);
12281                         memcpy ((gpointer)klass->ext->field_def_values [i].data, p, len);
12282                 }
12283         }
12284
12285         klass->instance_size = MAX (klass->instance_size, real_size);
12286         mono_class_layout_fields (klass);
12287 }
12288
12289 static void
12290 typebuilder_setup_properties (MonoClass *klass, MonoError *error)
12291 {
12292         MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder *)mono_class_get_ref_info (klass);
12293         MonoReflectionPropertyBuilder *pb;
12294         MonoImage *image = klass->image;
12295         MonoProperty *properties;
12296         int i;
12297
12298         mono_error_init (error);
12299
12300         if (!klass->ext)
12301                 klass->ext = image_g_new0 (image, MonoClassExt, 1);
12302
12303         klass->ext->property.count = tb->properties ? mono_array_length (tb->properties) : 0;
12304         klass->ext->property.first = 0;
12305
12306         properties = image_g_new0 (image, MonoProperty, klass->ext->property.count);
12307         klass->ext->properties = properties;
12308         for (i = 0; i < klass->ext->property.count; ++i) {
12309                 pb = mono_array_get (tb->properties, MonoReflectionPropertyBuilder*, i);
12310                 properties [i].parent = klass;
12311                 properties [i].attrs = pb->attrs;
12312                 properties [i].name = mono_string_to_utf8_image (image, pb->name, error);
12313                 if (!mono_error_ok (error))
12314                         return;
12315                 if (pb->get_method)
12316                         properties [i].get = pb->get_method->mhandle;
12317                 if (pb->set_method)
12318                         properties [i].set = pb->set_method->mhandle;
12319
12320                 mono_save_custom_attrs (klass->image, &properties [i], pb->cattrs);
12321                 if (pb->def_value) {
12322                         guint32 len, idx;
12323                         const char *p, *p2;
12324                         MonoDynamicImage *assembly = (MonoDynamicImage*)klass->image;
12325                         if (!klass->ext->prop_def_values)
12326                                 klass->ext->prop_def_values = image_g_new0 (image, MonoFieldDefaultValue, klass->ext->property.count);
12327                         properties [i].attrs |= PROPERTY_ATTRIBUTE_HAS_DEFAULT;
12328                         idx = encode_constant (assembly, pb->def_value, &klass->ext->prop_def_values [i].def_type);
12329                         /* Copy the data from the blob since it might get realloc-ed */
12330                         p = assembly->blob.data + idx;
12331                         len = mono_metadata_decode_blob_size (p, &p2);
12332                         len += p2 - p;
12333                         klass->ext->prop_def_values [i].data = (const char *)mono_image_alloc (image, len);
12334                         memcpy ((gpointer)klass->ext->prop_def_values [i].data, p, len);
12335                 }
12336         }
12337 }
12338
12339 MonoReflectionEvent *
12340 mono_reflection_event_builder_get_event_info (MonoReflectionTypeBuilder *tb, MonoReflectionEventBuilder *eb)
12341 {
12342         MonoError error;
12343         MonoEvent *event = g_new0 (MonoEvent, 1);
12344         MonoClass *klass;
12345
12346         klass = mono_class_from_mono_type (mono_reflection_type_get_handle ((MonoReflectionType*)tb));
12347
12348         event->parent = klass;
12349         event->attrs = eb->attrs;
12350         event->name = mono_string_to_utf8 (eb->name);
12351         if (eb->add_method)
12352                 event->add = eb->add_method->mhandle;
12353         if (eb->remove_method)
12354                 event->remove = eb->remove_method->mhandle;
12355         if (eb->raise_method)
12356                 event->raise = eb->raise_method->mhandle;
12357
12358 #ifndef MONO_SMALL_CONFIG
12359         if (eb->other_methods) {
12360                 int j;
12361                 event->other = g_new0 (MonoMethod*, mono_array_length (eb->other_methods) + 1);
12362                 for (j = 0; j < mono_array_length (eb->other_methods); ++j) {
12363                         MonoReflectionMethodBuilder *mb = 
12364                                 mono_array_get (eb->other_methods,
12365                                                 MonoReflectionMethodBuilder*, j);
12366                         event->other [j] = mb->mhandle;
12367                 }
12368         }
12369 #endif
12370
12371         MonoReflectionEvent *ev_obj = mono_event_get_object_checked (mono_object_domain (tb), klass, event, &error);
12372         mono_error_raise_exception (&error); /* FIXME don't raise here */
12373         return ev_obj;
12374 }
12375
12376 static void
12377 typebuilder_setup_events (MonoClass *klass, MonoError *error)
12378 {
12379         MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder *)mono_class_get_ref_info (klass);
12380         MonoReflectionEventBuilder *eb;
12381         MonoImage *image = klass->image;
12382         MonoEvent *events;
12383         int i;
12384
12385         mono_error_init (error);
12386
12387         if (!klass->ext)
12388                 klass->ext = image_g_new0 (image, MonoClassExt, 1);
12389
12390         klass->ext->event.count = tb->events ? mono_array_length (tb->events) : 0;
12391         klass->ext->event.first = 0;
12392
12393         events = image_g_new0 (image, MonoEvent, klass->ext->event.count);
12394         klass->ext->events = events;
12395         for (i = 0; i < klass->ext->event.count; ++i) {
12396                 eb = mono_array_get (tb->events, MonoReflectionEventBuilder*, i);
12397                 events [i].parent = klass;
12398                 events [i].attrs = eb->attrs;
12399                 events [i].name = mono_string_to_utf8_image (image, eb->name, error);
12400                 if (!mono_error_ok (error))
12401                         return;
12402                 if (eb->add_method)
12403                         events [i].add = eb->add_method->mhandle;
12404                 if (eb->remove_method)
12405                         events [i].remove = eb->remove_method->mhandle;
12406                 if (eb->raise_method)
12407                         events [i].raise = eb->raise_method->mhandle;
12408
12409 #ifndef MONO_SMALL_CONFIG
12410                 if (eb->other_methods) {
12411                         int j;
12412                         events [i].other = image_g_new0 (image, MonoMethod*, mono_array_length (eb->other_methods) + 1);
12413                         for (j = 0; j < mono_array_length (eb->other_methods); ++j) {
12414                                 MonoReflectionMethodBuilder *mb = 
12415                                         mono_array_get (eb->other_methods,
12416                                                                         MonoReflectionMethodBuilder*, j);
12417                                 events [i].other [j] = mb->mhandle;
12418                         }
12419                 }
12420 #endif
12421                 mono_save_custom_attrs (klass->image, &events [i], eb->cattrs);
12422         }
12423 }
12424
12425 static gboolean
12426 remove_instantiations_of_and_ensure_contents (gpointer key,
12427                                                   gpointer value,
12428                                                   gpointer user_data)
12429 {
12430         MonoType *type = (MonoType*)key;
12431         MonoClass *klass = (MonoClass*)user_data;
12432
12433         if ((type->type == MONO_TYPE_GENERICINST) && (type->data.generic_class->container_class == klass)) {
12434                 fix_partial_generic_class (mono_class_from_mono_type (type)); //Ensure it's safe to use it.
12435                 return TRUE;
12436         } else
12437                 return FALSE;
12438 }
12439
12440 static void
12441 check_array_for_usertypes (MonoArray *arr, MonoError *error)
12442 {
12443         mono_error_init (error);
12444         int i;
12445
12446         if (!arr)
12447                 return;
12448
12449         for (i = 0; i < mono_array_length (arr); ++i) {
12450                 RESOLVE_ARRAY_TYPE_ELEMENT (arr, i, error);
12451                 if (!mono_error_ok (error))
12452                         break;
12453         }
12454 }
12455
12456 MonoReflectionType*
12457 mono_reflection_create_runtime_class (MonoReflectionTypeBuilder *tb)
12458 {
12459         MonoError error;
12460         MonoClass *klass;
12461         MonoDomain* domain;
12462         MonoReflectionType* res;
12463         int i, j;
12464
12465         domain = mono_object_domain (tb);
12466         klass = mono_class_from_mono_type (tb->type.type);
12467
12468         /*
12469          * Check for user defined Type subclasses.
12470          */
12471         RESOLVE_TYPE (tb->parent, &error);
12472         mono_error_raise_exception (&error); /* FIXME don't raise here */
12473         check_array_for_usertypes (tb->interfaces, &error);
12474         mono_error_raise_exception (&error); /*FIXME don't raise here */
12475         if (tb->fields) {
12476                 for (i = 0; i < mono_array_length (tb->fields); ++i) {
12477                         MonoReflectionFieldBuilder *fb = (MonoReflectionFieldBuilder *)mono_array_get (tb->fields, gpointer, i);
12478                         if (fb) {
12479                                 RESOLVE_TYPE (fb->type, &error);
12480                                 mono_error_raise_exception (&error); /* FIXME don't raise here */
12481                                 check_array_for_usertypes (fb->modreq, &error);
12482                                 mono_error_raise_exception (&error); /*FIXME don't raise here */
12483                                 check_array_for_usertypes (fb->modopt, &error);
12484                                 mono_error_raise_exception (&error); /*FIXME don't raise here */
12485                                 if (fb->marshal_info && fb->marshal_info->marshaltyperef) {
12486                                         RESOLVE_TYPE (fb->marshal_info->marshaltyperef, &error);
12487                                         mono_error_raise_exception (&error); /* FIXME don't raise here */
12488                                 }
12489                         }
12490                 }
12491         }
12492         if (tb->methods) {
12493                 for (i = 0; i < mono_array_length (tb->methods); ++i) {
12494                         MonoReflectionMethodBuilder *mb = (MonoReflectionMethodBuilder *)mono_array_get (tb->methods, gpointer, i);
12495                         if (mb) {
12496                                 RESOLVE_TYPE (mb->rtype, &error);
12497                                 mono_error_raise_exception (&error); /* FIXME don't raise here */
12498                                 check_array_for_usertypes (mb->return_modreq, &error);
12499                                 mono_error_raise_exception (&error); /*FIXME don't raise here */
12500                                 check_array_for_usertypes (mb->return_modopt, &error);
12501                                 mono_error_raise_exception (&error); /*FIXME don't raise here */
12502                                 check_array_for_usertypes (mb->parameters, &error);
12503                                 mono_error_raise_exception (&error); /*FIXME don't raise here */
12504                                 if (mb->param_modreq)
12505                                         for (j = 0; j < mono_array_length (mb->param_modreq); ++j) {
12506                                                 check_array_for_usertypes (mono_array_get (mb->param_modreq, MonoArray*, j), &error);
12507                                                 mono_error_raise_exception (&error); /*FIXME don't raise here */
12508                                         }
12509                                 if (mb->param_modopt)
12510                                         for (j = 0; j < mono_array_length (mb->param_modopt); ++j) {
12511                                                 check_array_for_usertypes (mono_array_get (mb->param_modopt, MonoArray*, j), &error);
12512                                                 mono_error_raise_exception (&error); /*FIXME don't raise here */
12513                                         }
12514                         }
12515                 }
12516         }
12517         if (tb->ctors) {
12518                 for (i = 0; i < mono_array_length (tb->ctors); ++i) {
12519                         MonoReflectionCtorBuilder *mb = (MonoReflectionCtorBuilder *)mono_array_get (tb->ctors, gpointer, i);
12520                         if (mb) {
12521                                 check_array_for_usertypes (mb->parameters, &error);
12522                                 mono_error_raise_exception (&error); /*FIXME don't raise here */
12523                                 if (mb->param_modreq)
12524                                         for (j = 0; j < mono_array_length (mb->param_modreq); ++j) {
12525                                                 check_array_for_usertypes (mono_array_get (mb->param_modreq, MonoArray*, j), &error);
12526                                                 mono_error_raise_exception (&error); /*FIXME don't raise here */
12527                                         }
12528                                 if (mb->param_modopt)
12529                                         for (j = 0; j < mono_array_length (mb->param_modopt); ++j) {
12530                                                 check_array_for_usertypes (mono_array_get (mb->param_modopt, MonoArray*, j), &error);
12531                                                 mono_error_raise_exception (&error); /*FIXME don't raise here */
12532                                         }
12533                         }
12534                 }
12535         }
12536
12537         mono_save_custom_attrs (klass->image, klass, tb->cattrs);
12538
12539         /* 
12540          * we need to lock the domain because the lock will be taken inside
12541          * So, we need to keep the locking order correct.
12542          */
12543         mono_loader_lock ();
12544         mono_domain_lock (domain);
12545         if (klass->wastypebuilder) {
12546                 mono_domain_unlock (domain);
12547                 mono_loader_unlock ();
12548
12549                 res = mono_type_get_object_checked (mono_object_domain (tb), &klass->byval_arg, &error);
12550                 mono_error_raise_exception (&error); /* FIXME don't raise here */
12551
12552                 return res;
12553         }
12554         /*
12555          * Fields to set in klass:
12556          * the various flags: delegate/unicode/contextbound etc.
12557          */
12558         klass->flags = tb->attrs;
12559         klass->has_cctor = 1;
12560         klass->has_finalize = 1;
12561         klass->has_finalize_inited = 1;
12562
12563         mono_class_setup_parent (klass, klass->parent);
12564         /* fool mono_class_setup_supertypes */
12565         klass->supertypes = NULL;
12566         mono_class_setup_supertypes (klass);
12567         mono_class_setup_mono_type (klass);
12568
12569 #if 0
12570         if (!((MonoDynamicImage*)klass->image)->run) {
12571                 if (klass->generic_container) {
12572                         /* FIXME: The code below can't handle generic classes */
12573                         klass->wastypebuilder = TRUE;
12574                         mono_loader_unlock ();
12575                         mono_domain_unlock (domain);
12576
12577                         res = mono_type_get_object_checked (mono_object_domain (tb), &klass->byval_arg, &error);
12578                         mono_error_raise_exception (&error); /* FIXME don't raise here */
12579
12580                         return res;
12581                 }
12582         }
12583 #endif
12584
12585         /* enums are done right away */
12586         if (!klass->enumtype)
12587                 if (!ensure_runtime_vtable (klass, &error))
12588                         goto failure;
12589
12590         if (tb->subtypes) {
12591                 for (i = 0; i < mono_array_length (tb->subtypes); ++i) {
12592                         MonoReflectionTypeBuilder *subtb = mono_array_get (tb->subtypes, MonoReflectionTypeBuilder*, i);
12593                         mono_class_alloc_ext (klass);
12594                         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)));
12595                 }
12596         }
12597
12598         klass->nested_classes_inited = TRUE;
12599
12600         /* fields and object layout */
12601         if (klass->parent) {
12602                 if (!klass->parent->size_inited)
12603                         mono_class_init (klass->parent);
12604                 klass->instance_size = klass->parent->instance_size;
12605                 klass->sizes.class_size = 0;
12606                 klass->min_align = klass->parent->min_align;
12607                 /* if the type has no fields we won't call the field_setup
12608                  * routine which sets up klass->has_references.
12609                  */
12610                 klass->has_references |= klass->parent->has_references;
12611         } else {
12612                 klass->instance_size = sizeof (MonoObject);
12613                 klass->min_align = 1;
12614         }
12615
12616         /* FIXME: handle packing_size and instance_size */
12617         typebuilder_setup_fields (klass, &error);
12618         if (!mono_error_ok (&error))
12619                 goto failure;
12620         typebuilder_setup_properties (klass, &error);
12621         if (!mono_error_ok (&error))
12622                 goto failure;
12623
12624         typebuilder_setup_events (klass, &error);
12625         if (!mono_error_ok (&error))
12626                 goto failure;
12627
12628         klass->wastypebuilder = TRUE;
12629
12630         /* 
12631          * If we are a generic TypeBuilder, there might be instantiations in the type cache
12632          * which have type System.Reflection.MonoGenericClass, but after the type is created, 
12633          * we want to return normal System.MonoType objects, so clear these out from the cache.
12634          *
12635          * Together with this we must ensure the contents of all instances to match the created type.
12636          */
12637         if (domain->type_hash && klass->generic_container)
12638                 mono_g_hash_table_foreach_remove (domain->type_hash, remove_instantiations_of_and_ensure_contents, klass);
12639
12640         mono_domain_unlock (domain);
12641         mono_loader_unlock ();
12642
12643         if (klass->enumtype && !mono_class_is_valid_enum (klass)) {
12644                 mono_class_set_failure (klass, MONO_EXCEPTION_TYPE_LOAD, NULL);
12645                 mono_raise_exception (mono_get_exception_type_load (tb->name, NULL));
12646         }
12647
12648         res = mono_type_get_object_checked (mono_object_domain (tb), &klass->byval_arg, &error);
12649         mono_error_raise_exception (&error); /* FIXME don't raise here */
12650
12651         g_assert (res != (MonoReflectionType*)tb);
12652
12653         return res;
12654
12655 failure:
12656         mono_class_set_failure (klass, MONO_EXCEPTION_TYPE_LOAD, NULL);
12657         klass->wastypebuilder = TRUE;
12658         mono_domain_unlock (domain);
12659         mono_loader_unlock ();
12660         mono_error_raise_exception (&error);
12661         return NULL;
12662 }
12663
12664 void
12665 mono_reflection_initialize_generic_parameter (MonoReflectionGenericParam *gparam)
12666 {
12667         MonoGenericParamFull *param;
12668         MonoImage *image;
12669         MonoClass *pklass;
12670         MonoError error;
12671
12672         image = &gparam->tbuilder->module->dynamic_image->image;
12673
12674         param = mono_image_new0 (image, MonoGenericParamFull, 1);
12675
12676         param->info.name = mono_string_to_utf8_image (image, gparam->name, &error);
12677         g_assert (mono_error_ok (&error));
12678         param->param.num = gparam->index;
12679
12680         if (gparam->mbuilder) {
12681                 if (!gparam->mbuilder->generic_container) {
12682                         MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder *)gparam->mbuilder->type;
12683                         MonoClass *klass = mono_class_from_mono_type (mono_reflection_type_get_handle ((MonoReflectionType*)tb));
12684                         gparam->mbuilder->generic_container = (MonoGenericContainer *)mono_image_alloc0 (klass->image, sizeof (MonoGenericContainer));
12685                         gparam->mbuilder->generic_container->is_method = TRUE;
12686                         /* 
12687                          * Cannot set owner.method, since the MonoMethod is not created yet.
12688                          * Set the image field instead, so type_in_image () works.
12689                          */
12690                         gparam->mbuilder->generic_container->is_anonymous = TRUE;
12691                         gparam->mbuilder->generic_container->owner.image = klass->image;
12692                 }
12693                 param->param.owner = gparam->mbuilder->generic_container;
12694         } else if (gparam->tbuilder) {
12695                 if (!gparam->tbuilder->generic_container) {
12696                         MonoClass *klass = mono_class_from_mono_type (mono_reflection_type_get_handle ((MonoReflectionType*)gparam->tbuilder));
12697                         gparam->tbuilder->generic_container = (MonoGenericContainer *)mono_image_alloc0 (klass->image, sizeof (MonoGenericContainer));
12698                         gparam->tbuilder->generic_container->owner.klass = klass;
12699                 }
12700                 param->param.owner = gparam->tbuilder->generic_container;
12701         }
12702
12703         pklass = mono_class_from_generic_parameter_internal ((MonoGenericParam *) param);
12704
12705         gparam->type.type = &pklass->byval_arg;
12706
12707         mono_class_set_ref_info (pklass, gparam);
12708         mono_image_append_class_to_reflection_info_set (pklass);
12709 }
12710
12711 MonoArray *
12712 mono_reflection_sighelper_get_signature_local (MonoReflectionSigHelper *sig)
12713 {
12714         MonoError error;
12715         MonoReflectionModuleBuilder *module = sig->module;
12716         MonoDynamicImage *assembly = module != NULL ? module->dynamic_image : NULL;
12717         guint32 na = sig->arguments ? mono_array_length (sig->arguments) : 0;
12718         guint32 buflen, i;
12719         MonoArray *result;
12720         SigBuffer buf;
12721
12722         check_array_for_usertypes (sig->arguments, &error);
12723         mono_error_raise_exception (&error); /* FIXME: don't raise here */
12724
12725         sigbuffer_init (&buf, 32);
12726
12727         sigbuffer_add_value (&buf, 0x07);
12728         sigbuffer_add_value (&buf, na);
12729         if (assembly != NULL){
12730                 for (i = 0; i < na; ++i) {
12731                         MonoReflectionType *type = mono_array_get (sig->arguments, MonoReflectionType*, i);
12732                         encode_reflection_type (assembly, type, &buf);
12733                 }
12734         }
12735
12736         buflen = buf.p - buf.buf;
12737         result = mono_array_new (mono_domain_get (), mono_defaults.byte_class, buflen);
12738         memcpy (mono_array_addr (result, char, 0), buf.buf, buflen);
12739         sigbuffer_free (&buf);
12740
12741         return result;
12742 }
12743
12744 MonoArray *
12745 mono_reflection_sighelper_get_signature_field (MonoReflectionSigHelper *sig)
12746 {
12747         MonoError error;
12748         MonoDynamicImage *assembly = sig->module->dynamic_image;
12749         guint32 na = sig->arguments ? mono_array_length (sig->arguments) : 0;
12750         guint32 buflen, i;
12751         MonoArray *result;
12752         SigBuffer buf;
12753
12754         check_array_for_usertypes (sig->arguments, &error);
12755         mono_error_raise_exception (&error); /* FIXME: don't raise here */
12756
12757         sigbuffer_init (&buf, 32);
12758
12759         sigbuffer_add_value (&buf, 0x06);
12760         for (i = 0; i < na; ++i) {
12761                 MonoReflectionType *type = mono_array_get (sig->arguments, MonoReflectionType*, i);
12762                 encode_reflection_type (assembly, type, &buf);
12763         }
12764
12765         buflen = buf.p - buf.buf;
12766         result = mono_array_new (mono_domain_get (), mono_defaults.byte_class, buflen);
12767         memcpy (mono_array_addr (result, char, 0), buf.buf, buflen);
12768         sigbuffer_free (&buf);
12769
12770         return result;
12771 }
12772
12773 typedef struct {
12774         MonoMethod *handle;
12775         MonoDomain *domain;
12776 } DynamicMethodReleaseData;
12777
12778 /*
12779  * The runtime automatically clean up those after finalization.
12780 */      
12781 static MonoReferenceQueue *dynamic_method_queue;
12782
12783 static void
12784 free_dynamic_method (void *dynamic_method)
12785 {
12786         DynamicMethodReleaseData *data = (DynamicMethodReleaseData *)dynamic_method;
12787         MonoDomain *domain = data->domain;
12788         MonoMethod *method = data->handle;
12789         guint32 dis_link;
12790
12791         mono_domain_lock (domain);
12792         dis_link = (guint32)(size_t)g_hash_table_lookup (domain->method_to_dyn_method, method);
12793         g_hash_table_remove (domain->method_to_dyn_method, method);
12794         mono_domain_unlock (domain);
12795         g_assert (dis_link);
12796         mono_gchandle_free (dis_link);
12797
12798         mono_runtime_free_method (domain, method);
12799         g_free (data);
12800 }
12801
12802 void 
12803 mono_reflection_create_dynamic_method (MonoReflectionDynamicMethod *mb)
12804 {
12805         MonoReferenceQueue *queue;
12806         MonoMethod *handle;
12807         DynamicMethodReleaseData *release_data;
12808         ReflectionMethodBuilder rmb;
12809         MonoMethodSignature *sig;
12810         MonoClass *klass;
12811         MonoDomain *domain;
12812         GSList *l;
12813         int i;
12814
12815         if (mono_runtime_is_shutting_down ())
12816                 mono_raise_exception (mono_get_exception_invalid_operation (""));
12817
12818         if (!(queue = dynamic_method_queue)) {
12819                 mono_loader_lock ();
12820                 if (!(queue = dynamic_method_queue))
12821                         queue = dynamic_method_queue = mono_gc_reference_queue_new (free_dynamic_method);
12822                 mono_loader_unlock ();
12823         }
12824
12825         sig = dynamic_method_to_signature (mb);
12826
12827         reflection_methodbuilder_from_dynamic_method (&rmb, mb);
12828
12829         /*
12830          * Resolve references.
12831          */
12832         /* 
12833          * Every second entry in the refs array is reserved for storing handle_class,
12834          * which is needed by the ldtoken implementation in the JIT.
12835          */
12836         rmb.nrefs = mb->nrefs;
12837         rmb.refs = g_new0 (gpointer, mb->nrefs + 1);
12838         for (i = 0; i < mb->nrefs; i += 2) {
12839                 MonoClass *handle_class;
12840                 gpointer ref;
12841                 MonoObject *obj = mono_array_get (mb->refs, MonoObject*, i);
12842
12843                 if (strcmp (obj->vtable->klass->name, "DynamicMethod") == 0) {
12844                         MonoReflectionDynamicMethod *method = (MonoReflectionDynamicMethod*)obj;
12845                         /*
12846                          * The referenced DynamicMethod should already be created by the managed
12847                          * code, except in the case of circular references. In that case, we store
12848                          * method in the refs array, and fix it up later when the referenced 
12849                          * DynamicMethod is created.
12850                          */
12851                         if (method->mhandle) {
12852                                 ref = method->mhandle;
12853                         } else {
12854                                 /* FIXME: GC object stored in unmanaged memory */
12855                                 ref = method;
12856
12857                                 /* FIXME: GC object stored in unmanaged memory */
12858                                 method->referenced_by = g_slist_append (method->referenced_by, mb);
12859                         }
12860                         handle_class = mono_defaults.methodhandle_class;
12861                 } else {
12862                         MonoException *ex = NULL;
12863                         ref = resolve_object (mb->module->image, obj, &handle_class, NULL);
12864                         if (!ref)
12865                                 ex = mono_get_exception_type_load (NULL, NULL);
12866                         else if (mono_security_core_clr_enabled ())
12867                                 ex = mono_security_core_clr_ensure_dynamic_method_resolved_object (ref, handle_class);
12868
12869                         if (ex) {
12870                                 g_free (rmb.refs);
12871                                 mono_raise_exception (ex);
12872                                 return;
12873                         }
12874                 }
12875
12876                 rmb.refs [i] = ref; /* FIXME: GC object stored in unmanaged memory (change also resolve_object() signature) */
12877                 rmb.refs [i + 1] = handle_class;
12878         }               
12879
12880         klass = mb->owner ? mono_class_from_mono_type (mono_reflection_type_get_handle ((MonoReflectionType*)mb->owner)) : mono_defaults.object_class;
12881
12882         mb->mhandle = handle = reflection_methodbuilder_to_mono_method (klass, &rmb, sig);
12883         release_data = g_new (DynamicMethodReleaseData, 1);
12884         release_data->handle = handle;
12885         release_data->domain = mono_object_get_domain ((MonoObject*)mb);
12886         if (!mono_gc_reference_queue_add (queue, (MonoObject*)mb, release_data))
12887                 g_free (release_data);
12888
12889         /* Fix up refs entries pointing at us */
12890         for (l = mb->referenced_by; l; l = l->next) {
12891                 MonoReflectionDynamicMethod *method = (MonoReflectionDynamicMethod*)l->data;
12892                 MonoMethodWrapper *wrapper = (MonoMethodWrapper*)method->mhandle;
12893                 gpointer *data;
12894                 
12895                 g_assert (method->mhandle);
12896
12897                 data = (gpointer*)wrapper->method_data;
12898                 for (i = 0; i < GPOINTER_TO_UINT (data [0]); i += 2) {
12899                         if ((data [i + 1] == mb) && (data [i + 1 + 1] == mono_defaults.methodhandle_class))
12900                                 data [i + 1] = mb->mhandle;
12901                 }
12902         }
12903         g_slist_free (mb->referenced_by);
12904
12905         g_free (rmb.refs);
12906
12907         /* ilgen is no longer needed */
12908         mb->ilgen = NULL;
12909
12910         domain = mono_domain_get ();
12911         mono_domain_lock (domain);
12912         if (!domain->method_to_dyn_method)
12913                 domain->method_to_dyn_method = g_hash_table_new (NULL, NULL);
12914         g_hash_table_insert (domain->method_to_dyn_method, handle, (gpointer)(size_t)mono_gchandle_new_weakref ((MonoObject *)mb, TRUE));
12915         mono_domain_unlock (domain);
12916 }
12917
12918 #endif /* DISABLE_REFLECTION_EMIT */
12919
12920 /**
12921  * 
12922  * mono_reflection_is_valid_dynamic_token:
12923  * 
12924  * Returns TRUE if token is valid.
12925  * 
12926  */
12927 gboolean
12928 mono_reflection_is_valid_dynamic_token (MonoDynamicImage *image, guint32 token)
12929 {
12930         return lookup_dyn_token (image, token) != NULL;
12931 }
12932
12933 MonoMethodSignature *
12934 mono_reflection_lookup_signature (MonoImage *image, MonoMethod *method, guint32 token, MonoError *error)
12935 {
12936         MonoMethodSignature *sig;
12937         g_assert (image_is_dynamic (image));
12938
12939         mono_error_init (error);
12940
12941         sig = (MonoMethodSignature *)g_hash_table_lookup (((MonoDynamicImage*)image)->vararg_aux_hash, GUINT_TO_POINTER (token));
12942         if (sig)
12943                 return sig;
12944
12945         return mono_method_signature_checked (method, error);
12946 }
12947
12948 #ifndef DISABLE_REFLECTION_EMIT
12949
12950 /**
12951  * mono_reflection_lookup_dynamic_token:
12952  *
12953  * Finish the Builder object pointed to by TOKEN and return the corresponding
12954  * runtime structure. If HANDLE_CLASS is not NULL, it is set to the class required by 
12955  * mono_ldtoken. If valid_token is TRUE, assert if it is not found in the token->object
12956  * mapping table.
12957  *
12958  * LOCKING: Take the loader lock
12959  */
12960 gpointer
12961 mono_reflection_lookup_dynamic_token (MonoImage *image, guint32 token, gboolean valid_token, MonoClass **handle_class, MonoGenericContext *context)
12962 {
12963         MonoDynamicImage *assembly = (MonoDynamicImage*)image;
12964         MonoObject *obj;
12965         MonoClass *klass;
12966
12967         obj = lookup_dyn_token (assembly, token);
12968         if (!obj) {
12969                 if (valid_token)
12970                         g_error ("Could not find required dynamic token 0x%08x", token);
12971                 else
12972                         return NULL;
12973         }
12974
12975         if (!handle_class)
12976                 handle_class = &klass;
12977         return resolve_object (image, obj, handle_class, context);
12978 }
12979
12980 /*
12981  * ensure_complete_type:
12982  *
12983  *   Ensure that KLASS is completed if it is a dynamic type, or references
12984  * dynamic types.
12985  */
12986 static void
12987 ensure_complete_type (MonoClass *klass)
12988 {
12989         MonoError error;
12990
12991         if (image_is_dynamic (klass->image) && !klass->wastypebuilder && mono_class_get_ref_info (klass)) {
12992                 MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder *)mono_class_get_ref_info (klass);
12993
12994                 mono_domain_try_type_resolve_checked (mono_domain_get (), NULL, (MonoObject*)tb, &error);
12995                 mono_error_raise_exception (&error); /* FIXME don't raise here */
12996
12997                 // Asserting here could break a lot of code
12998                 //g_assert (klass->wastypebuilder);
12999         }
13000
13001         if (klass->generic_class) {
13002                 MonoGenericInst *inst = klass->generic_class->context.class_inst;
13003                 int i;
13004
13005                 for (i = 0; i < inst->type_argc; ++i) {
13006                         ensure_complete_type (mono_class_from_mono_type (inst->type_argv [i]));
13007                 }
13008         }
13009 }
13010
13011 static gpointer
13012 resolve_object (MonoImage *image, MonoObject *obj, MonoClass **handle_class, MonoGenericContext *context)
13013 {
13014         MonoError error;
13015         gpointer result = NULL;
13016
13017         if (strcmp (obj->vtable->klass->name, "String") == 0) {
13018                 result = mono_string_intern_checked ((MonoString*)obj, &error);
13019                 mono_error_raise_exception (&error); /* FIXME don't raise here */
13020                 *handle_class = mono_defaults.string_class;
13021                 g_assert (result);
13022         } else if (strcmp (obj->vtable->klass->name, "MonoType") == 0) {
13023                 MonoType *type = mono_reflection_type_get_handle ((MonoReflectionType*)obj);
13024                 MonoClass *mc = mono_class_from_mono_type (type);
13025                 if (!mono_class_init (mc))
13026                         mono_raise_exception (mono_class_get_exception_for_failure (mc));
13027
13028                 if (context) {
13029                         MonoType *inflated = mono_class_inflate_generic_type_checked (type, context, &error);
13030                         mono_error_raise_exception (&error); /* FIXME don't raise here */
13031
13032                         result = mono_class_from_mono_type (inflated);
13033                         mono_metadata_free_type (inflated);
13034                 } else {
13035                         result = mono_class_from_mono_type (type);
13036                 }
13037                 *handle_class = mono_defaults.typehandle_class;
13038                 g_assert (result);
13039         } else if (strcmp (obj->vtable->klass->name, "MonoMethod") == 0 ||
13040                    strcmp (obj->vtable->klass->name, "MonoCMethod") == 0 ||
13041                    strcmp (obj->vtable->klass->name, "MonoGenericCMethod") == 0 ||
13042                    strcmp (obj->vtable->klass->name, "MonoGenericMethod") == 0) {
13043                 result = ((MonoReflectionMethod*)obj)->method;
13044                 if (context) {
13045                         MonoError error;
13046                         result = mono_class_inflate_generic_method_checked ((MonoMethod *)result, context, &error);
13047                         g_assert (mono_error_ok (&error)); /* FIXME don't swallow the error */
13048                 }
13049                 *handle_class = mono_defaults.methodhandle_class;
13050                 g_assert (result);
13051         } else if (strcmp (obj->vtable->klass->name, "MethodBuilder") == 0) {
13052                 MonoReflectionMethodBuilder *mb = (MonoReflectionMethodBuilder*)obj;
13053                 result = mb->mhandle;
13054                 if (!result) {
13055                         /* Type is not yet created */
13056                         MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder*)mb->type;
13057
13058                         mono_domain_try_type_resolve_checked (mono_domain_get (), NULL, (MonoObject*)tb, &error);
13059                         mono_error_raise_exception (&error); /* FIXME don't raise here */
13060
13061                         /*
13062                          * Hopefully this has been filled in by calling CreateType() on the
13063                          * TypeBuilder.
13064                          */
13065                         /*
13066                          * TODO: This won't work if the application finishes another 
13067                          * TypeBuilder instance instead of this one.
13068                          */
13069                         result = mb->mhandle;
13070                 }
13071                 if (context) {
13072                         MonoError error;
13073                         result = mono_class_inflate_generic_method_checked ((MonoMethod *)result, context, &error);
13074                         g_assert (mono_error_ok (&error)); /* FIXME don't swallow the error */
13075                 }
13076                 *handle_class = mono_defaults.methodhandle_class;
13077         } else if (strcmp (obj->vtable->klass->name, "ConstructorBuilder") == 0) {
13078                 MonoReflectionCtorBuilder *cb = (MonoReflectionCtorBuilder*)obj;
13079
13080                 result = cb->mhandle;
13081                 if (!result) {
13082                         MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder*)cb->type;
13083
13084                         mono_domain_try_type_resolve_checked (mono_domain_get (), NULL, (MonoObject*)tb, &error);
13085                         mono_error_raise_exception (&error); /* FIXME don't raise here */
13086                         result = cb->mhandle;
13087                 }
13088                 if (context) {
13089                         MonoError error;
13090                         result = mono_class_inflate_generic_method_checked ((MonoMethod *)result, context, &error);
13091                         g_assert (mono_error_ok (&error)); /* FIXME don't swallow the error */
13092                 }
13093                 *handle_class = mono_defaults.methodhandle_class;
13094         } else if (strcmp (obj->vtable->klass->name, "MonoField") == 0) {
13095                 MonoClassField *field = ((MonoReflectionField*)obj)->field;
13096
13097                 ensure_complete_type (field->parent);
13098                 if (context) {
13099                         MonoType *inflated = mono_class_inflate_generic_type_checked (&field->parent->byval_arg, context, &error);
13100                         mono_error_raise_exception (&error); /* FIXME don't raise here */
13101
13102                         MonoClass *klass = mono_class_from_mono_type (inflated);
13103                         MonoClassField *inflated_field;
13104                         gpointer iter = NULL;
13105                         mono_metadata_free_type (inflated);
13106                         while ((inflated_field = mono_class_get_fields (klass, &iter))) {
13107                                 if (!strcmp (field->name, inflated_field->name))
13108                                         break;
13109                         }
13110                         g_assert (inflated_field && !strcmp (field->name, inflated_field->name));
13111                         result = inflated_field;
13112                 } else {
13113                         result = field;
13114                 }
13115                 *handle_class = mono_defaults.fieldhandle_class;
13116                 g_assert (result);
13117         } else if (strcmp (obj->vtable->klass->name, "FieldBuilder") == 0) {
13118                 MonoReflectionFieldBuilder *fb = (MonoReflectionFieldBuilder*)obj;
13119                 result = fb->handle;
13120
13121                 if (!result) {
13122                         MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder*)fb->typeb;
13123
13124                         mono_domain_try_type_resolve_checked (mono_domain_get (), NULL, (MonoObject*)tb, &error);
13125                         mono_error_raise_exception (&error); /* FIXME don't raise here */
13126                         result = fb->handle;
13127                 }
13128
13129                 if (fb->handle && fb->handle->parent->generic_container) {
13130                         MonoClass *klass = fb->handle->parent;
13131                         MonoType *type = mono_class_inflate_generic_type_checked (&klass->byval_arg, context, &error);
13132                         mono_error_raise_exception (&error); /* FIXME don't raise here */
13133
13134                         MonoClass *inflated = mono_class_from_mono_type (type);
13135
13136                         result = mono_class_get_field_from_name (inflated, mono_field_get_name (fb->handle));
13137                         g_assert (result);
13138                         mono_metadata_free_type (type);
13139                 }
13140                 *handle_class = mono_defaults.fieldhandle_class;
13141         } else if (strcmp (obj->vtable->klass->name, "TypeBuilder") == 0) {
13142                 MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder*)obj;
13143                 MonoType *type = mono_reflection_type_get_handle ((MonoReflectionType*)tb); 
13144                 MonoClass *klass;
13145
13146                 klass = type->data.klass;
13147                 if (klass->wastypebuilder) {
13148                         /* Already created */
13149                         result = klass;
13150                 }
13151                 else {
13152                         mono_domain_try_type_resolve_checked (mono_domain_get (), NULL, (MonoObject*)tb, &error);
13153                         mono_error_raise_exception (&error); /* FIXME don't raise here */
13154                         result = type->data.klass;
13155                         g_assert (result);
13156                 }
13157                 *handle_class = mono_defaults.typehandle_class;
13158         } else if (strcmp (obj->vtable->klass->name, "SignatureHelper") == 0) {
13159                 MonoReflectionSigHelper *helper = (MonoReflectionSigHelper*)obj;
13160                 MonoMethodSignature *sig;
13161                 int nargs, i;
13162
13163                 if (helper->arguments)
13164                         nargs = mono_array_length (helper->arguments);
13165                 else
13166                         nargs = 0;
13167
13168                 sig = mono_metadata_signature_alloc (image, nargs);
13169                 sig->explicit_this = helper->call_conv & 64 ? 1 : 0;
13170                 sig->hasthis = helper->call_conv & 32 ? 1 : 0;
13171
13172                 if (helper->unmanaged_call_conv) { /* unmanaged */
13173                         sig->call_convention = helper->unmanaged_call_conv - 1;
13174                         sig->pinvoke = TRUE;
13175                 } else if (helper->call_conv & 0x02) {
13176                         sig->call_convention = MONO_CALL_VARARG;
13177                 } else {
13178                         sig->call_convention = MONO_CALL_DEFAULT;
13179                 }
13180
13181                 sig->param_count = nargs;
13182                 /* TODO: Copy type ? */
13183                 sig->ret = helper->return_type->type;
13184                 for (i = 0; i < nargs; ++i)
13185                         sig->params [i] = mono_type_array_get_and_resolve (helper->arguments, i);
13186
13187                 result = sig;
13188                 *handle_class = NULL;
13189         } else if (strcmp (obj->vtable->klass->name, "DynamicMethod") == 0) {
13190                 MonoReflectionDynamicMethod *method = (MonoReflectionDynamicMethod*)obj;
13191                 /* Already created by the managed code */
13192                 g_assert (method->mhandle);
13193                 result = method->mhandle;
13194                 *handle_class = mono_defaults.methodhandle_class;
13195         } else if (strcmp (obj->vtable->klass->name, "GenericTypeParameterBuilder") == 0) {
13196                 MonoType *type = mono_reflection_type_get_handle ((MonoReflectionType*)obj);
13197                 type = mono_class_inflate_generic_type_checked (type, context, &error);
13198                 mono_error_raise_exception (&error); /* FIXME don't raise here */
13199
13200                 result = mono_class_from_mono_type (type);
13201                 *handle_class = mono_defaults.typehandle_class;
13202                 g_assert (result);
13203                 mono_metadata_free_type (type);
13204         } else if (strcmp (obj->vtable->klass->name, "MonoGenericClass") == 0) {
13205                 MonoType *type = mono_reflection_type_get_handle ((MonoReflectionType*)obj);
13206                 type = mono_class_inflate_generic_type_checked (type, context, &error);
13207                 mono_error_raise_exception (&error); /* FIXME don't raise here */
13208
13209                 result = mono_class_from_mono_type (type);
13210                 *handle_class = mono_defaults.typehandle_class;
13211                 g_assert (result);
13212                 mono_metadata_free_type (type);
13213         } else if (strcmp (obj->vtable->klass->name, "FieldOnTypeBuilderInst") == 0) {
13214                 MonoReflectionFieldOnTypeBuilderInst *f = (MonoReflectionFieldOnTypeBuilderInst*)obj;
13215                 MonoClass *inflated;
13216                 MonoType *type;
13217                 MonoClassField *field;
13218
13219                 if (is_sre_field_builder (mono_object_class (f->fb)))
13220                         field = ((MonoReflectionFieldBuilder*)f->fb)->handle;
13221                 else if (is_sr_mono_field (mono_object_class (f->fb)))
13222                         field = ((MonoReflectionField*)f->fb)->field;
13223                 else
13224                         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)));
13225
13226                 type = mono_class_inflate_generic_type_checked (mono_reflection_type_get_handle ((MonoReflectionType*)f->inst), context, &error);
13227                 mono_error_raise_exception (&error); /* FIXME don't raise here */
13228
13229                 inflated = mono_class_from_mono_type (type);
13230
13231                 result = field = mono_class_get_field_from_name (inflated, mono_field_get_name (field));
13232                 ensure_complete_type (field->parent);
13233                 g_assert (result);
13234                 mono_metadata_free_type (type);
13235                 *handle_class = mono_defaults.fieldhandle_class;
13236         } else if (strcmp (obj->vtable->klass->name, "ConstructorOnTypeBuilderInst") == 0) {
13237                 MonoReflectionCtorOnTypeBuilderInst *c = (MonoReflectionCtorOnTypeBuilderInst*)obj;
13238                 MonoType *type = mono_class_inflate_generic_type_checked (mono_reflection_type_get_handle ((MonoReflectionType*)c->inst), context, &error);
13239                 mono_error_raise_exception (&error); /* FIXME don't raise here */
13240
13241                 MonoClass *inflated_klass = mono_class_from_mono_type (type);
13242                 MonoMethod *method;
13243
13244                 if (is_sre_ctor_builder (mono_object_class (c->cb)))
13245                         method = ((MonoReflectionCtorBuilder *)c->cb)->mhandle;
13246                 else if (is_sr_mono_cmethod (mono_object_class (c->cb)))
13247                         method = ((MonoReflectionMethod *)c->cb)->method;
13248                 else
13249                         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)));
13250
13251                 result = inflate_mono_method (inflated_klass, method, (MonoObject*)c->cb);
13252                 *handle_class = mono_defaults.methodhandle_class;
13253                 mono_metadata_free_type (type);
13254         } else if (strcmp (obj->vtable->klass->name, "MethodOnTypeBuilderInst") == 0) {
13255                 MonoReflectionMethodOnTypeBuilderInst *m = (MonoReflectionMethodOnTypeBuilderInst*)obj;
13256                 if (m->method_args) {
13257                         result = mono_reflection_method_on_tb_inst_get_handle (m, &error);
13258                         mono_error_raise_exception (&error); /* FIXME don't raise here */
13259                         if (context) {
13260                                 result = mono_class_inflate_generic_method_checked ((MonoMethod *)result, context, &error);
13261                                 mono_error_assert_ok (&error);
13262                         }
13263                 } else {
13264                         MonoType *type = mono_class_inflate_generic_type_checked (mono_reflection_type_get_handle ((MonoReflectionType*)m->inst), context, &error);
13265                         mono_error_raise_exception (&error); /* FIXME don't raise here */
13266
13267                         MonoClass *inflated_klass = mono_class_from_mono_type (type);
13268                         MonoMethod *method;
13269
13270                         if (is_sre_method_builder (mono_object_class (m->mb)))
13271                                 method = ((MonoReflectionMethodBuilder *)m->mb)->mhandle;
13272                         else if (is_sr_mono_method (mono_object_class (m->mb)))
13273                                 method = ((MonoReflectionMethod *)m->mb)->method;
13274                         else
13275                                 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)));
13276
13277                         result = inflate_mono_method (inflated_klass, method, (MonoObject*)m->mb);
13278                         mono_metadata_free_type (type);
13279                 }
13280                 *handle_class = mono_defaults.methodhandle_class;
13281         } else if (strcmp (obj->vtable->klass->name, "MonoArrayMethod") == 0) {
13282                 MonoReflectionArrayMethod *m = (MonoReflectionArrayMethod*)obj;
13283                 MonoType *mtype;
13284                 MonoClass *klass;
13285                 MonoMethod *method;
13286                 gpointer iter;
13287                 char *name;
13288
13289                 mtype = mono_reflection_type_get_handle (m->parent);
13290                 klass = mono_class_from_mono_type (mtype);
13291
13292                 /* Find the method */
13293
13294                 name = mono_string_to_utf8 (m->name);
13295                 iter = NULL;
13296                 while ((method = mono_class_get_methods (klass, &iter))) {
13297                         if (!strcmp (method->name, name))
13298                                 break;
13299                 }
13300                 g_free (name);
13301
13302                 // FIXME:
13303                 g_assert (method);
13304                 // FIXME: Check parameters/return value etc. match
13305
13306                 result = method;
13307                 *handle_class = mono_defaults.methodhandle_class;
13308         } else if (is_sre_array (mono_object_get_class(obj)) ||
13309                                 is_sre_byref (mono_object_get_class(obj)) ||
13310                                 is_sre_pointer (mono_object_get_class(obj))) {
13311                 MonoReflectionType *ref_type = (MonoReflectionType *)obj;
13312                 MonoType *type = mono_reflection_type_get_handle (ref_type);
13313
13314                 if (context) {
13315                         MonoType *inflated = mono_class_inflate_generic_type_checked (type, context, &error);
13316                         mono_error_raise_exception (&error); /* FIXME don't raise here */
13317
13318                         result = mono_class_from_mono_type (inflated);
13319                         mono_metadata_free_type (inflated);
13320                 } else {
13321                         result = mono_class_from_mono_type (type);
13322                 }
13323                 *handle_class = mono_defaults.typehandle_class;
13324         } else {
13325                 g_print ("%s\n", obj->vtable->klass->name);
13326                 g_assert_not_reached ();
13327         }
13328         return result;
13329 }
13330
13331 #else /* DISABLE_REFLECTION_EMIT */
13332
13333 MonoArray*
13334 mono_reflection_get_custom_attrs_blob (MonoReflectionAssembly *assembly, MonoObject *ctor, MonoArray *ctorArgs, MonoArray *properties, MonoArray *propValues, MonoArray *fields, MonoArray* fieldValues) 
13335 {
13336         g_assert_not_reached ();
13337         return NULL;
13338 }
13339
13340 void
13341 mono_reflection_setup_internal_class (MonoReflectionTypeBuilder *tb)
13342 {
13343         g_assert_not_reached ();
13344 }
13345
13346 void
13347 mono_reflection_setup_generic_class (MonoReflectionTypeBuilder *tb)
13348 {
13349         g_assert_not_reached ();
13350 }
13351
13352 void
13353 mono_reflection_create_generic_class (MonoReflectionTypeBuilder *tb)
13354 {
13355         g_assert_not_reached ();
13356 }
13357
13358 void
13359 mono_reflection_create_internal_class (MonoReflectionTypeBuilder *tb)
13360 {
13361         g_assert_not_reached ();
13362 }
13363
13364 void
13365 mono_image_basic_init (MonoReflectionAssemblyBuilder *assemblyb)
13366 {
13367         g_error ("This mono runtime was configured with --enable-minimal=reflection_emit, so System.Reflection.Emit is not supported.");
13368 }
13369
13370 void
13371 mono_image_module_basic_init (MonoReflectionModuleBuilder *moduleb)
13372 {
13373         g_assert_not_reached ();
13374 }
13375
13376 void
13377 mono_image_set_wrappers_type (MonoReflectionModuleBuilder *moduleb, MonoReflectionType *type)
13378 {
13379         g_assert_not_reached ();
13380 }
13381
13382 MonoReflectionModule *
13383 mono_image_load_module_dynamic (MonoReflectionAssemblyBuilder *ab, MonoString *fileName)
13384 {
13385         g_assert_not_reached ();
13386         return NULL;
13387 }
13388
13389 guint32
13390 mono_image_insert_string (MonoReflectionModuleBuilder *module, MonoString *str)
13391 {
13392         g_assert_not_reached ();
13393         return 0;
13394 }
13395
13396 guint32
13397 mono_image_create_method_token (MonoDynamicImage *assembly, MonoObject *obj, MonoArray *opt_param_types, MonoError *error)
13398 {
13399         g_assert_not_reached ();
13400         return 0;
13401 }
13402
13403 guint32
13404 mono_image_create_token (MonoDynamicImage *assembly, MonoObject *obj, 
13405                          gboolean create_open_instance, gboolean register_token, MonoError *error)
13406 {
13407         g_assert_not_reached ();
13408         return 0;
13409 }
13410
13411 void
13412 mono_image_register_token (MonoDynamicImage *assembly, guint32 token, MonoObject *obj)
13413 {
13414 }
13415
13416 void
13417 mono_reflection_generic_class_initialize (MonoReflectionGenericClass *type, MonoArray *fields)
13418 {
13419         g_assert_not_reached ();
13420 }
13421
13422 void
13423 mono_reflection_get_dynamic_overrides (MonoClass *klass, MonoMethod ***overrides, int *num_overrides)
13424 {
13425         *overrides = NULL;
13426         *num_overrides = 0;
13427 }
13428
13429 MonoReflectionEvent *
13430 mono_reflection_event_builder_get_event_info (MonoReflectionTypeBuilder *tb, MonoReflectionEventBuilder *eb)
13431 {
13432         g_assert_not_reached ();
13433         return NULL;
13434 }
13435
13436 MonoReflectionType*
13437 mono_reflection_create_runtime_class (MonoReflectionTypeBuilder *tb)
13438 {
13439         g_assert_not_reached ();
13440         return NULL;
13441 }
13442
13443 void
13444 mono_reflection_initialize_generic_parameter (MonoReflectionGenericParam *gparam)
13445 {
13446         g_assert_not_reached ();
13447 }
13448
13449 MonoArray *
13450 mono_reflection_sighelper_get_signature_local (MonoReflectionSigHelper *sig)
13451 {
13452         g_assert_not_reached ();
13453         return NULL;
13454 }
13455
13456 MonoArray *
13457 mono_reflection_sighelper_get_signature_field (MonoReflectionSigHelper *sig)
13458 {
13459         g_assert_not_reached ();
13460         return NULL;
13461 }
13462
13463 void 
13464 mono_reflection_create_dynamic_method (MonoReflectionDynamicMethod *mb)
13465 {
13466 }
13467
13468 gpointer
13469 mono_reflection_lookup_dynamic_token (MonoImage *image, guint32 token, gboolean valid_token, MonoClass **handle_class, MonoGenericContext *context)
13470 {
13471         return NULL;
13472 }
13473
13474 MonoType*
13475 mono_reflection_type_get_handle (MonoReflectionType* ref)
13476 {
13477         if (!ref)
13478                 return NULL;
13479         return ref->type;
13480 }
13481
13482 void
13483 mono_reflection_free_dynamic_generic_class (MonoGenericClass *gclass)
13484 {
13485         g_assert_not_reached ();
13486 }
13487
13488 #endif /* DISABLE_REFLECTION_EMIT */
13489
13490 /* SECURITY_ACTION_* are defined in mono/metadata/tabledefs.h */
13491 const static guint32 declsec_flags_map[] = {
13492         0x00000000,                                     /* empty */
13493         MONO_DECLSEC_FLAG_REQUEST,                      /* SECURITY_ACTION_REQUEST                      (x01) */
13494         MONO_DECLSEC_FLAG_DEMAND,                       /* SECURITY_ACTION_DEMAND                       (x02) */
13495         MONO_DECLSEC_FLAG_ASSERT,                       /* SECURITY_ACTION_ASSERT                       (x03) */
13496         MONO_DECLSEC_FLAG_DENY,                         /* SECURITY_ACTION_DENY                         (x04) */
13497         MONO_DECLSEC_FLAG_PERMITONLY,                   /* SECURITY_ACTION_PERMITONLY                   (x05) */
13498         MONO_DECLSEC_FLAG_LINKDEMAND,                   /* SECURITY_ACTION_LINKDEMAND                   (x06) */
13499         MONO_DECLSEC_FLAG_INHERITANCEDEMAND,            /* SECURITY_ACTION_INHERITANCEDEMAND            (x07) */
13500         MONO_DECLSEC_FLAG_REQUEST_MINIMUM,              /* SECURITY_ACTION_REQUEST_MINIMUM              (x08) */
13501         MONO_DECLSEC_FLAG_REQUEST_OPTIONAL,             /* SECURITY_ACTION_REQUEST_OPTIONAL             (x09) */
13502         MONO_DECLSEC_FLAG_REQUEST_REFUSE,               /* SECURITY_ACTION_REQUEST_REFUSE               (x0A) */
13503         MONO_DECLSEC_FLAG_PREJIT_GRANT,                 /* SECURITY_ACTION_PREJIT_GRANT                 (x0B) */
13504         MONO_DECLSEC_FLAG_PREJIT_DENY,                  /* SECURITY_ACTION_PREJIT_DENY                  (x0C) */
13505         MONO_DECLSEC_FLAG_NONCAS_DEMAND,                /* SECURITY_ACTION_NONCAS_DEMAND                (x0D) */
13506         MONO_DECLSEC_FLAG_NONCAS_LINKDEMAND,            /* SECURITY_ACTION_NONCAS_LINKDEMAND            (x0E) */
13507         MONO_DECLSEC_FLAG_NONCAS_INHERITANCEDEMAND,     /* SECURITY_ACTION_NONCAS_INHERITANCEDEMAND     (x0F) */
13508         MONO_DECLSEC_FLAG_LINKDEMAND_CHOICE,            /* SECURITY_ACTION_LINKDEMAND_CHOICE            (x10) */
13509         MONO_DECLSEC_FLAG_INHERITANCEDEMAND_CHOICE,     /* SECURITY_ACTION_INHERITANCEDEMAND_CHOICE     (x11) */
13510         MONO_DECLSEC_FLAG_DEMAND_CHOICE,                /* SECURITY_ACTION_DEMAND_CHOICE                (x12) */
13511 };
13512
13513 /*
13514  * Returns flags that includes all available security action associated to the handle.
13515  * @token: metadata token (either for a class or a method)
13516  * @image: image where resides the metadata.
13517  */
13518 static guint32
13519 mono_declsec_get_flags (MonoImage *image, guint32 token)
13520 {
13521         int index = mono_metadata_declsec_from_index (image, token);
13522         MonoTableInfo *t = &image->tables [MONO_TABLE_DECLSECURITY];
13523         guint32 result = 0;
13524         guint32 action;
13525         int i;
13526
13527         /* HasSecurity can be present for other, not specially encoded, attributes,
13528            e.g. SuppressUnmanagedCodeSecurityAttribute */
13529         if (index < 0)
13530                 return 0;
13531
13532         for (i = index; i < t->rows; i++) {
13533                 guint32 cols [MONO_DECL_SECURITY_SIZE];
13534
13535                 mono_metadata_decode_row (t, i, cols, MONO_DECL_SECURITY_SIZE);
13536                 if (cols [MONO_DECL_SECURITY_PARENT] != token)
13537                         break;
13538
13539                 action = cols [MONO_DECL_SECURITY_ACTION];
13540                 if ((action >= MONO_DECLSEC_ACTION_MIN) && (action <= MONO_DECLSEC_ACTION_MAX)) {
13541                         result |= declsec_flags_map [action];
13542                 } else {
13543                         g_assert_not_reached ();
13544                 }
13545         }
13546         return result;
13547 }
13548
13549 /*
13550  * Get the security actions (in the form of flags) associated with the specified method.
13551  *
13552  * @method: The method for which we want the declarative security flags.
13553  * Return the declarative security flags for the method (only).
13554  *
13555  * Note: To keep MonoMethod size down we do not cache the declarative security flags
13556  *       (except for the stack modifiers which are kept in the MonoJitInfo structure)
13557  */
13558 guint32
13559 mono_declsec_flags_from_method (MonoMethod *method)
13560 {
13561         if (method->flags & METHOD_ATTRIBUTE_HAS_SECURITY) {
13562                 /* FIXME: No cache (for the moment) */
13563                 guint32 idx = mono_method_get_index (method);
13564                 idx <<= MONO_HAS_DECL_SECURITY_BITS;
13565                 idx |= MONO_HAS_DECL_SECURITY_METHODDEF;
13566                 return mono_declsec_get_flags (method->klass->image, idx);
13567         }
13568         return 0;
13569 }
13570
13571 /*
13572  * Get the security actions (in the form of flags) associated with the specified class.
13573  *
13574  * @klass: The class for which we want the declarative security flags.
13575  * Return the declarative security flags for the class.
13576  *
13577  * Note: We cache the flags inside the MonoClass structure as this will get 
13578  *       called very often (at least for each method).
13579  */
13580 guint32
13581 mono_declsec_flags_from_class (MonoClass *klass)
13582 {
13583         if (klass->flags & TYPE_ATTRIBUTE_HAS_SECURITY) {
13584                 if (!klass->ext || !klass->ext->declsec_flags) {
13585                         guint32 idx;
13586
13587                         idx = mono_metadata_token_index (klass->type_token);
13588                         idx <<= MONO_HAS_DECL_SECURITY_BITS;
13589                         idx |= MONO_HAS_DECL_SECURITY_TYPEDEF;
13590                         mono_loader_lock ();
13591                         mono_class_alloc_ext (klass);
13592                         mono_loader_unlock ();
13593                         /* we cache the flags on classes */
13594                         klass->ext->declsec_flags = mono_declsec_get_flags (klass->image, idx);
13595                 }
13596                 return klass->ext->declsec_flags;
13597         }
13598         return 0;
13599 }
13600
13601 /*
13602  * Get the security actions (in the form of flags) associated with the specified assembly.
13603  *
13604  * @assembly: The assembly for which we want the declarative security flags.
13605  * Return the declarative security flags for the assembly.
13606  */
13607 guint32
13608 mono_declsec_flags_from_assembly (MonoAssembly *assembly)
13609 {
13610         guint32 idx = 1; /* there is only one assembly */
13611         idx <<= MONO_HAS_DECL_SECURITY_BITS;
13612         idx |= MONO_HAS_DECL_SECURITY_ASSEMBLY;
13613         return mono_declsec_get_flags (assembly->image, idx);
13614 }
13615
13616
13617 /*
13618  * Fill actions for the specific index (which may either be an encoded class token or
13619  * an encoded method token) from the metadata image.
13620  * Returns TRUE if some actions requiring code generation are present, FALSE otherwise.
13621  */
13622 static MonoBoolean
13623 fill_actions_from_index (MonoImage *image, guint32 token, MonoDeclSecurityActions* actions,
13624         guint32 id_std, guint32 id_noncas, guint32 id_choice)
13625 {
13626         MonoBoolean result = FALSE;
13627         MonoTableInfo *t;
13628         guint32 cols [MONO_DECL_SECURITY_SIZE];
13629         int index = mono_metadata_declsec_from_index (image, token);
13630         int i;
13631
13632         t  = &image->tables [MONO_TABLE_DECLSECURITY];
13633         for (i = index; i < t->rows; i++) {
13634                 mono_metadata_decode_row (t, i, cols, MONO_DECL_SECURITY_SIZE);
13635
13636                 if (cols [MONO_DECL_SECURITY_PARENT] != token)
13637                         return result;
13638
13639                 /* if present only replace (class) permissions with method permissions */
13640                 /* if empty accept either class or method permissions */
13641                 if (cols [MONO_DECL_SECURITY_ACTION] == id_std) {
13642                         if (!actions->demand.blob) {
13643                                 const char *blob = mono_metadata_blob_heap (image, cols [MONO_DECL_SECURITY_PERMISSIONSET]);
13644                                 actions->demand.index = cols [MONO_DECL_SECURITY_PERMISSIONSET];
13645                                 actions->demand.blob = (char*) (blob + 2);
13646                                 actions->demand.size = mono_metadata_decode_blob_size (blob, &blob);
13647                                 result = TRUE;
13648                         }
13649                 } else if (cols [MONO_DECL_SECURITY_ACTION] == id_noncas) {
13650                         if (!actions->noncasdemand.blob) {
13651                                 const char *blob = mono_metadata_blob_heap (image, cols [MONO_DECL_SECURITY_PERMISSIONSET]);
13652                                 actions->noncasdemand.index = cols [MONO_DECL_SECURITY_PERMISSIONSET];
13653                                 actions->noncasdemand.blob = (char*) (blob + 2);
13654                                 actions->noncasdemand.size = mono_metadata_decode_blob_size (blob, &blob);
13655                                 result = TRUE;
13656                         }
13657                 } else if (cols [MONO_DECL_SECURITY_ACTION] == id_choice) {
13658                         if (!actions->demandchoice.blob) {
13659                                 const char *blob = mono_metadata_blob_heap (image, cols [MONO_DECL_SECURITY_PERMISSIONSET]);
13660                                 actions->demandchoice.index = cols [MONO_DECL_SECURITY_PERMISSIONSET];
13661                                 actions->demandchoice.blob = (char*) (blob + 2);
13662                                 actions->demandchoice.size = mono_metadata_decode_blob_size (blob, &blob);
13663                                 result = TRUE;
13664                         }
13665                 }
13666         }
13667
13668         return result;
13669 }
13670
13671 static MonoBoolean
13672 mono_declsec_get_class_demands_params (MonoClass *klass, MonoDeclSecurityActions* demands, 
13673         guint32 id_std, guint32 id_noncas, guint32 id_choice)
13674 {
13675         guint32 idx = mono_metadata_token_index (klass->type_token);
13676         idx <<= MONO_HAS_DECL_SECURITY_BITS;
13677         idx |= MONO_HAS_DECL_SECURITY_TYPEDEF;
13678         return fill_actions_from_index (klass->image, idx, demands, id_std, id_noncas, id_choice);
13679 }
13680
13681 static MonoBoolean
13682 mono_declsec_get_method_demands_params (MonoMethod *method, MonoDeclSecurityActions* demands, 
13683         guint32 id_std, guint32 id_noncas, guint32 id_choice)
13684 {
13685         guint32 idx = mono_method_get_index (method);
13686         idx <<= MONO_HAS_DECL_SECURITY_BITS;
13687         idx |= MONO_HAS_DECL_SECURITY_METHODDEF;
13688         return fill_actions_from_index (method->klass->image, idx, demands, id_std, id_noncas, id_choice);
13689 }
13690
13691 /*
13692  * Collect all actions (that requires to generate code in mini) assigned for
13693  * the specified method.
13694  * Note: Don't use the content of actions if the function return FALSE.
13695  */
13696 MonoBoolean
13697 mono_declsec_get_demands (MonoMethod *method, MonoDeclSecurityActions* demands)
13698 {
13699         guint32 mask = MONO_DECLSEC_FLAG_DEMAND | MONO_DECLSEC_FLAG_NONCAS_DEMAND | 
13700                 MONO_DECLSEC_FLAG_DEMAND_CHOICE;
13701         MonoBoolean result = FALSE;
13702         guint32 flags;
13703
13704         /* quick exit if no declarative security is present in the metadata */
13705         if (!method->klass->image->tables [MONO_TABLE_DECLSECURITY].rows)
13706                 return FALSE;
13707
13708         /* we want the original as the wrapper is "free" of the security informations */
13709         if (method->wrapper_type == MONO_WRAPPER_MANAGED_TO_NATIVE || method->wrapper_type == MONO_WRAPPER_MANAGED_TO_MANAGED) {
13710                 method = mono_marshal_method_from_wrapper (method);
13711                 if (!method)
13712                         return FALSE;
13713         }
13714
13715         /* First we look for method-level attributes */
13716         if (method->flags & METHOD_ATTRIBUTE_HAS_SECURITY) {
13717                 mono_class_init (method->klass);
13718                 memset (demands, 0, sizeof (MonoDeclSecurityActions));
13719
13720                 result = mono_declsec_get_method_demands_params (method, demands, 
13721                         SECURITY_ACTION_DEMAND, SECURITY_ACTION_NONCASDEMAND, SECURITY_ACTION_DEMANDCHOICE);
13722         }
13723
13724         /* Here we use (or create) the class declarative cache to look for demands */
13725         flags = mono_declsec_flags_from_class (method->klass);
13726         if (flags & mask) {
13727                 if (!result) {
13728                         mono_class_init (method->klass);
13729                         memset (demands, 0, sizeof (MonoDeclSecurityActions));
13730                 }
13731                 result |= mono_declsec_get_class_demands_params (method->klass, demands, 
13732                         SECURITY_ACTION_DEMAND, SECURITY_ACTION_NONCASDEMAND, SECURITY_ACTION_DEMANDCHOICE);
13733         }
13734
13735         /* The boolean return value is used as a shortcut in case nothing needs to
13736            be generated (e.g. LinkDemand[Choice] and InheritanceDemand[Choice]) */
13737         return result;
13738 }
13739
13740
13741 /*
13742  * Collect all Link actions: LinkDemand, NonCasLinkDemand and LinkDemandChoice (2.0).
13743  *
13744  * Note: Don't use the content of actions if the function return FALSE.
13745  */
13746 MonoBoolean
13747 mono_declsec_get_linkdemands (MonoMethod *method, MonoDeclSecurityActions* klass, MonoDeclSecurityActions *cmethod)
13748 {
13749         MonoBoolean result = FALSE;
13750         guint32 flags;
13751
13752         /* quick exit if no declarative security is present in the metadata */
13753         if (!method->klass->image->tables [MONO_TABLE_DECLSECURITY].rows)
13754                 return FALSE;
13755
13756         /* we want the original as the wrapper is "free" of the security informations */
13757         if (method->wrapper_type == MONO_WRAPPER_MANAGED_TO_NATIVE || method->wrapper_type == MONO_WRAPPER_MANAGED_TO_MANAGED) {
13758                 method = mono_marshal_method_from_wrapper (method);
13759                 if (!method)
13760                         return FALSE;
13761         }
13762
13763         /* results are independant - zeroize both */
13764         memset (cmethod, 0, sizeof (MonoDeclSecurityActions));
13765         memset (klass, 0, sizeof (MonoDeclSecurityActions));
13766
13767         /* First we look for method-level attributes */
13768         if (method->flags & METHOD_ATTRIBUTE_HAS_SECURITY) {
13769                 mono_class_init (method->klass);
13770
13771                 result = mono_declsec_get_method_demands_params (method, cmethod, 
13772                         SECURITY_ACTION_LINKDEMAND, SECURITY_ACTION_NONCASLINKDEMAND, SECURITY_ACTION_LINKDEMANDCHOICE);
13773         }
13774
13775         /* Here we use (or create) the class declarative cache to look for demands */
13776         flags = mono_declsec_flags_from_class (method->klass);
13777         if (flags & (MONO_DECLSEC_FLAG_LINKDEMAND | MONO_DECLSEC_FLAG_NONCAS_LINKDEMAND | MONO_DECLSEC_FLAG_LINKDEMAND_CHOICE)) {
13778                 mono_class_init (method->klass);
13779
13780                 result |= mono_declsec_get_class_demands_params (method->klass, klass, 
13781                         SECURITY_ACTION_LINKDEMAND, SECURITY_ACTION_NONCASLINKDEMAND, SECURITY_ACTION_LINKDEMANDCHOICE);
13782         }
13783
13784         return result;
13785 }
13786
13787 /*
13788  * Collect all Inherit actions: InheritanceDemand, NonCasInheritanceDemand and InheritanceDemandChoice (2.0).
13789  *
13790  * @klass       The inherited class - this is the class that provides the security check (attributes)
13791  * @demans      
13792  * return TRUE if inheritance demands (any kind) are present, FALSE otherwise.
13793  * 
13794  * Note: Don't use the content of actions if the function return FALSE.
13795  */
13796 MonoBoolean
13797 mono_declsec_get_inheritdemands_class (MonoClass *klass, MonoDeclSecurityActions* demands)
13798 {
13799         MonoBoolean result = FALSE;
13800         guint32 flags;
13801
13802         /* quick exit if no declarative security is present in the metadata */
13803         if (!klass->image->tables [MONO_TABLE_DECLSECURITY].rows)
13804                 return FALSE;
13805
13806         /* Here we use (or create) the class declarative cache to look for demands */
13807         flags = mono_declsec_flags_from_class (klass);
13808         if (flags & (MONO_DECLSEC_FLAG_INHERITANCEDEMAND | MONO_DECLSEC_FLAG_NONCAS_INHERITANCEDEMAND | MONO_DECLSEC_FLAG_INHERITANCEDEMAND_CHOICE)) {
13809                 mono_class_init (klass);
13810                 memset (demands, 0, sizeof (MonoDeclSecurityActions));
13811
13812                 result |= mono_declsec_get_class_demands_params (klass, demands, 
13813                         SECURITY_ACTION_INHERITDEMAND, SECURITY_ACTION_NONCASINHERITANCE, SECURITY_ACTION_INHERITDEMANDCHOICE);
13814         }
13815
13816         return result;
13817 }
13818
13819 /*
13820  * Collect all Inherit actions: InheritanceDemand, NonCasInheritanceDemand and InheritanceDemandChoice (2.0).
13821  *
13822  * Note: Don't use the content of actions if the function return FALSE.
13823  */
13824 MonoBoolean
13825 mono_declsec_get_inheritdemands_method (MonoMethod *method, MonoDeclSecurityActions* demands)
13826 {
13827         /* quick exit if no declarative security is present in the metadata */
13828         if (!method->klass->image->tables [MONO_TABLE_DECLSECURITY].rows)
13829                 return FALSE;
13830
13831         /* we want the original as the wrapper is "free" of the security informations */
13832         if (method->wrapper_type == MONO_WRAPPER_MANAGED_TO_NATIVE || method->wrapper_type == MONO_WRAPPER_MANAGED_TO_MANAGED) {
13833                 method = mono_marshal_method_from_wrapper (method);
13834                 if (!method)
13835                         return FALSE;
13836         }
13837
13838         if (method->flags & METHOD_ATTRIBUTE_HAS_SECURITY) {
13839                 mono_class_init (method->klass);
13840                 memset (demands, 0, sizeof (MonoDeclSecurityActions));
13841
13842                 return mono_declsec_get_method_demands_params (method, demands, 
13843                         SECURITY_ACTION_INHERITDEMAND, SECURITY_ACTION_NONCASINHERITANCE, SECURITY_ACTION_INHERITDEMANDCHOICE);
13844         }
13845         return FALSE;
13846 }
13847
13848
13849 static MonoBoolean
13850 get_declsec_action (MonoImage *image, guint32 token, guint32 action, MonoDeclSecurityEntry *entry)
13851 {
13852         guint32 cols [MONO_DECL_SECURITY_SIZE];
13853         MonoTableInfo *t;
13854         int i;
13855
13856         int index = mono_metadata_declsec_from_index (image, token);
13857         if (index == -1)
13858                 return FALSE;
13859
13860         t =  &image->tables [MONO_TABLE_DECLSECURITY];
13861         for (i = index; i < t->rows; i++) {
13862                 mono_metadata_decode_row (t, i, cols, MONO_DECL_SECURITY_SIZE);
13863
13864                 /* shortcut - index are ordered */
13865                 if (token != cols [MONO_DECL_SECURITY_PARENT])
13866                         return FALSE;
13867
13868                 if (cols [MONO_DECL_SECURITY_ACTION] == action) {
13869                         const char *metadata = mono_metadata_blob_heap (image, cols [MONO_DECL_SECURITY_PERMISSIONSET]);
13870                         entry->blob = (char*) (metadata + 2);
13871                         entry->size = mono_metadata_decode_blob_size (metadata, &metadata);
13872                         return TRUE;
13873                 }
13874         }
13875
13876         return FALSE;
13877 }
13878
13879 MonoBoolean
13880 mono_declsec_get_method_action (MonoMethod *method, guint32 action, MonoDeclSecurityEntry *entry)
13881 {
13882         if (method->flags & METHOD_ATTRIBUTE_HAS_SECURITY) {
13883                 guint32 idx = mono_method_get_index (method);
13884                 idx <<= MONO_HAS_DECL_SECURITY_BITS;
13885                 idx |= MONO_HAS_DECL_SECURITY_METHODDEF;
13886                 return get_declsec_action (method->klass->image, idx, action, entry);
13887         }
13888         return FALSE;
13889 }
13890
13891 MonoBoolean
13892 mono_declsec_get_class_action (MonoClass *klass, guint32 action, MonoDeclSecurityEntry *entry)
13893 {
13894         /* use cache */
13895         guint32 flags = mono_declsec_flags_from_class (klass);
13896         if (declsec_flags_map [action] & flags) {
13897                 guint32 idx = mono_metadata_token_index (klass->type_token);
13898                 idx <<= MONO_HAS_DECL_SECURITY_BITS;
13899                 idx |= MONO_HAS_DECL_SECURITY_TYPEDEF;
13900                 return get_declsec_action (klass->image, idx, action, entry);
13901         }
13902         return FALSE;
13903 }
13904
13905 MonoBoolean
13906 mono_declsec_get_assembly_action (MonoAssembly *assembly, guint32 action, MonoDeclSecurityEntry *entry)
13907 {
13908         guint32 idx = 1; /* there is only one assembly */
13909         idx <<= MONO_HAS_DECL_SECURITY_BITS;
13910         idx |= MONO_HAS_DECL_SECURITY_ASSEMBLY;
13911
13912         return get_declsec_action (assembly->image, idx, action, entry);
13913 }
13914
13915 gboolean
13916 mono_reflection_call_is_assignable_to (MonoClass *klass, MonoClass *oklass)
13917 {
13918         MonoError error;
13919         MonoObject *res, *exc;
13920         void *params [1];
13921         static MonoMethod *method = NULL;
13922
13923         if (method == NULL) {
13924                 method = mono_class_get_method_from_name (mono_class_get_type_builder_class (), "IsAssignableTo", 1);
13925                 g_assert (method);
13926         }
13927
13928         /* 
13929          * The result of mono_type_get_object_checked () might be a System.MonoType but we
13930          * need a TypeBuilder so use mono_class_get_ref_info (klass).
13931          */
13932         g_assert (mono_class_get_ref_info (klass));
13933         g_assert (!strcmp (((MonoObject*)(mono_class_get_ref_info (klass)))->vtable->klass->name, "TypeBuilder"));
13934
13935         params [0] = mono_type_get_object_checked (mono_domain_get (), &oklass->byval_arg, &error);
13936         mono_error_raise_exception (&error); /* FIXME don't raise here */
13937
13938         res = mono_runtime_try_invoke (method, (MonoObject*)(mono_class_get_ref_info (klass)), params, &exc, &error);
13939
13940         if (exc || !mono_error_ok (&error)) {
13941                 mono_error_cleanup (&error);
13942                 return FALSE;
13943         } else
13944                 return *(MonoBoolean*)mono_object_unbox (res);
13945 }
13946
13947 /**
13948  * mono_reflection_type_get_type:
13949  * @reftype: the System.Type object
13950  *
13951  * Returns the MonoType* associated with the C# System.Type object @reftype.
13952  */
13953 MonoType*
13954 mono_reflection_type_get_type (MonoReflectionType *reftype)
13955 {
13956         g_assert (reftype);
13957
13958         return mono_reflection_type_get_handle (reftype);
13959 }
13960
13961 /**
13962  * mono_reflection_assembly_get_assembly:
13963  * @refassembly: the System.Reflection.Assembly object
13964  *
13965  * Returns the MonoAssembly* associated with the C# System.Reflection.Assembly object @refassembly.
13966  */
13967 MonoAssembly*
13968 mono_reflection_assembly_get_assembly (MonoReflectionAssembly *refassembly)
13969 {
13970         g_assert (refassembly);
13971
13972         return refassembly->assembly;
13973 }
13974