[reflection] Use MonoError in mono_reflection_get_type_with_rootimage
[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, MonoError *error);
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, MonoError *error)
8164 {
8165         gboolean type_resolve = FALSE;
8166         MonoType *type;
8167         MonoImage *rootimage = image;
8168
8169         mono_error_init (error);
8170
8171         if (info->assembly.name) {
8172                 MonoAssembly *assembly = mono_assembly_loaded (&info->assembly);
8173                 if (!assembly && image && image->assembly && mono_assembly_names_equal (&info->assembly, &image->assembly->aname))
8174                         /* 
8175                          * This could happen in the AOT compiler case when the search hook is not
8176                          * installed.
8177                          */
8178                         assembly = image->assembly;
8179                 if (!assembly) {
8180                         /* then we must load the assembly ourselve - see #60439 */
8181                         assembly = mono_assembly_load (&info->assembly, image->assembly->basedir, NULL);
8182                         if (!assembly)
8183                                 return NULL;
8184                 }
8185                 image = assembly->image;
8186         } else if (!image) {
8187                 image = mono_defaults.corlib;
8188         }
8189
8190         type = mono_reflection_get_type_with_rootimage (rootimage, image, info, ignorecase, &type_resolve, error);
8191         if (type == NULL && !info->assembly.name && image != mono_defaults.corlib) {
8192                 mono_error_cleanup (error);
8193                 image = mono_defaults.corlib;
8194                 type = mono_reflection_get_type_with_rootimage (rootimage, image, info, ignorecase, &type_resolve, error);
8195         }
8196
8197         return type;
8198 }
8199
8200 /**
8201  * mono_reflection_get_type_internal:
8202  *
8203  * Returns: may return NULL on success, sets error on failure.
8204  */
8205 static MonoType*
8206 mono_reflection_get_type_internal (MonoImage *rootimage, MonoImage* image, MonoTypeNameParse *info, gboolean ignorecase, MonoError *error)
8207 {
8208         MonoClass *klass;
8209         GList *mod;
8210         int modval;
8211         gboolean bounded = FALSE;
8212         
8213         mono_error_init (error);
8214         if (!image)
8215                 image = mono_defaults.corlib;
8216
8217         if (!rootimage)
8218                 rootimage = mono_defaults.corlib;
8219
8220         if (ignorecase)
8221                 klass = mono_class_from_name_case_checked (image, info->name_space, info->name, error);
8222         else
8223                 klass = mono_class_from_name_checked (image, info->name_space, info->name, error);
8224
8225         if (!klass)
8226                 return NULL;
8227
8228         for (mod = info->nested; mod; mod = mod->next) {
8229                 gpointer iter = NULL;
8230                 MonoClass *parent;
8231
8232                 parent = klass;
8233                 mono_class_init (parent);
8234
8235                 while ((klass = mono_class_get_nested_types (parent, &iter))) {
8236                         char *lastp;
8237                         char *nested_name, *nested_nspace;
8238                         gboolean match = TRUE;
8239
8240                         lastp = strrchr ((const char *)mod->data, '.');
8241                         if (lastp) {
8242                                 /* Nested classes can have namespaces */
8243                                 int nspace_len;
8244
8245                                 nested_name = g_strdup (lastp + 1);
8246                                 nspace_len = lastp - (char*)mod->data;
8247                                 nested_nspace = (char *)g_malloc (nspace_len + 1);
8248                                 memcpy (nested_nspace, mod->data, nspace_len);
8249                                 nested_nspace [nspace_len] = '\0';
8250
8251                         } else {
8252                                 nested_name = (char *)mod->data;
8253                                 nested_nspace = NULL;
8254                         }
8255
8256                         if (nested_nspace) {
8257                                 if (ignorecase) {
8258                                         if (!(klass->name_space && mono_utf8_strcasecmp (klass->name_space, nested_nspace) == 0))
8259                                                 match = FALSE;
8260                                 } else {
8261                                         if (!(klass->name_space && strcmp (klass->name_space, nested_nspace) == 0))
8262                                                 match = FALSE;
8263                                 }
8264                         }
8265                         if (match) {
8266                                 if (ignorecase) {
8267                                         if (mono_utf8_strcasecmp (klass->name, nested_name) != 0)
8268                                                 match = FALSE;
8269                                 } else {
8270                                         if (strcmp (klass->name, nested_name) != 0)
8271                                                 match = FALSE;
8272                                 }
8273                         }
8274                         if (lastp) {
8275                                 g_free (nested_name);
8276                                 g_free (nested_nspace);
8277                         }
8278                         if (match)
8279                                 break;
8280                 }
8281
8282                 if (!klass)
8283                         break;
8284         }
8285         if (!klass)
8286                 return NULL;
8287
8288         if (info->type_arguments) {
8289                 MonoType **type_args = g_new0 (MonoType *, info->type_arguments->len);
8290                 MonoReflectionType *the_type;
8291                 MonoType *instance;
8292                 int i;
8293
8294                 for (i = 0; i < info->type_arguments->len; i++) {
8295                         MonoTypeNameParse *subinfo = (MonoTypeNameParse *)g_ptr_array_index (info->type_arguments, i);
8296
8297                         type_args [i] = _mono_reflection_get_type_from_info (subinfo, rootimage, ignorecase, error);
8298                         if (!type_args [i]) {
8299                                 g_free (type_args);
8300                                 return NULL;
8301                         }
8302                 }
8303
8304                 the_type = mono_type_get_object_checked (mono_domain_get (), &klass->byval_arg, error);
8305                 if (!the_type)
8306                         return NULL;
8307
8308                 instance = mono_reflection_bind_generic_parameters (
8309                         the_type, info->type_arguments->len, type_args);
8310
8311                 g_free (type_args);
8312                 if (!instance)
8313                         return NULL;
8314
8315                 klass = mono_class_from_mono_type (instance);
8316         }
8317
8318         for (mod = info->modifiers; mod; mod = mod->next) {
8319                 modval = GPOINTER_TO_UINT (mod->data);
8320                 if (!modval) { /* byref: must be last modifier */
8321                         return &klass->this_arg;
8322                 } else if (modval == -1) {
8323                         klass = mono_ptr_class_get (&klass->byval_arg);
8324                 } else if (modval == -2) {
8325                         bounded = TRUE;
8326                 } else { /* array rank */
8327                         klass = mono_bounded_array_class_get (klass, modval, bounded);
8328                 }
8329         }
8330
8331         return &klass->byval_arg;
8332 }
8333
8334 /*
8335  * mono_reflection_get_type:
8336  * @image: a metadata context
8337  * @info: type description structure
8338  * @ignorecase: flag for case-insensitive string compares
8339  * @type_resolve: whenever type resolve was already tried
8340  *
8341  * Build a MonoType from the type description in @info.
8342  * 
8343  */
8344
8345 MonoType*
8346 mono_reflection_get_type (MonoImage* image, MonoTypeNameParse *info, gboolean ignorecase, gboolean *type_resolve) {
8347         MonoError error;
8348         MonoType *result = mono_reflection_get_type_with_rootimage(image, image, info, ignorecase, type_resolve, &error);
8349         mono_error_raise_exception (&error); /* FIXME don't raise here */
8350         return result;
8351 }
8352
8353 static MonoType*
8354 mono_reflection_get_type_internal_dynamic (MonoImage *rootimage, MonoAssembly *assembly, MonoTypeNameParse *info, gboolean ignorecase, MonoError *error)
8355 {
8356         MonoReflectionAssemblyBuilder *abuilder;
8357         MonoType *type;
8358         int i;
8359
8360         mono_error_init (error);
8361         g_assert (assembly_is_dynamic (assembly));
8362         abuilder = (MonoReflectionAssemblyBuilder*)mono_assembly_get_object_checked (((MonoDynamicAssembly*)assembly)->domain, assembly, error);
8363         if (!abuilder)
8364                 return NULL;
8365
8366         /* Enumerate all modules */
8367
8368         type = NULL;
8369         if (abuilder->modules) {
8370                 for (i = 0; i < mono_array_length (abuilder->modules); ++i) {
8371                         MonoReflectionModuleBuilder *mb = mono_array_get (abuilder->modules, MonoReflectionModuleBuilder*, i);
8372                         type = mono_reflection_get_type_internal (rootimage, &mb->dynamic_image->image, info, ignorecase, error);
8373                         if (type)
8374                                 break;
8375                         if (!mono_error_ok (error))
8376                                 return NULL;
8377                 }
8378         }
8379
8380         if (!type && abuilder->loaded_modules) {
8381                 for (i = 0; i < mono_array_length (abuilder->loaded_modules); ++i) {
8382                         MonoReflectionModule *mod = mono_array_get (abuilder->loaded_modules, MonoReflectionModule*, i);
8383                         type = mono_reflection_get_type_internal (rootimage, mod->image, info, ignorecase, error);
8384                         if (type)
8385                                 break;
8386                         if (!mono_error_ok (error))
8387                                 return NULL;
8388                 }
8389         }
8390
8391         return type;
8392 }
8393         
8394 MonoType*
8395 mono_reflection_get_type_with_rootimage (MonoImage *rootimage, MonoImage* image, MonoTypeNameParse *info, gboolean ignorecase, gboolean *type_resolve, MonoError *error)
8396 {
8397         MonoType *type;
8398         MonoReflectionAssembly *assembly;
8399         GString *fullName;
8400         GList *mod;
8401
8402         mono_error_init (error);
8403
8404         if (image && image_is_dynamic (image))
8405                 type = mono_reflection_get_type_internal_dynamic (rootimage, image->assembly, info, ignorecase, error);
8406         else {
8407                 type = mono_reflection_get_type_internal (rootimage, image, info, ignorecase, error);
8408         }
8409         return_val_if_nok (error, NULL);
8410
8411         if (type)
8412                 return type;
8413         if (!mono_domain_has_type_resolve (mono_domain_get ()))
8414                 return NULL;
8415
8416         if (type_resolve) {
8417                 if (*type_resolve) 
8418                         return NULL;
8419                 else
8420                         *type_resolve = TRUE;
8421         }
8422         
8423         /* Reconstruct the type name */
8424         fullName = g_string_new ("");
8425         if (info->name_space && (info->name_space [0] != '\0'))
8426                 g_string_printf (fullName, "%s.%s", info->name_space, info->name);
8427         else
8428                 g_string_printf (fullName, "%s", info->name);
8429         for (mod = info->nested; mod; mod = mod->next)
8430                 g_string_append_printf (fullName, "+%s", (char*)mod->data);
8431
8432         assembly = mono_domain_try_type_resolve_checked ( mono_domain_get (), fullName->str, NULL, error);
8433         if (!is_ok (error)) {
8434                 g_string_free (fullName, TRUE);
8435                 return NULL;
8436         }
8437
8438         if (assembly) {
8439                 if (assembly_is_dynamic (assembly->assembly))
8440                         type = mono_reflection_get_type_internal_dynamic (rootimage, assembly->assembly,
8441                                                                           info, ignorecase, error);
8442                 else
8443                         type = mono_reflection_get_type_internal (rootimage, assembly->assembly->image, 
8444                                                                   info, ignorecase, error);
8445         }
8446         g_string_free (fullName, TRUE);
8447         return_val_if_nok (error, NULL);
8448         return type;
8449 }
8450
8451 void
8452 mono_reflection_free_type_info (MonoTypeNameParse *info)
8453 {
8454         g_list_free (info->modifiers);
8455         g_list_free (info->nested);
8456
8457         if (info->type_arguments) {
8458                 int i;
8459
8460                 for (i = 0; i < info->type_arguments->len; i++) {
8461                         MonoTypeNameParse *subinfo = (MonoTypeNameParse *)g_ptr_array_index (info->type_arguments, i);
8462
8463                         mono_reflection_free_type_info (subinfo);
8464                         /*We free the subinfo since it is allocated by _mono_reflection_parse_type*/
8465                         g_free (subinfo);
8466                 }
8467
8468                 g_ptr_array_free (info->type_arguments, TRUE);
8469         }
8470 }
8471
8472 /*
8473  * mono_reflection_type_from_name:
8474  * @name: type name.
8475  * @image: a metadata context (can be NULL).
8476  *
8477  * Retrieves a MonoType from its @name. If the name is not fully qualified,
8478  * it defaults to get the type from @image or, if @image is NULL or loading
8479  * from it fails, uses corlib.
8480  * 
8481  */
8482 MonoType*
8483 mono_reflection_type_from_name (char *name, MonoImage *image)
8484 {
8485         MonoError error;
8486         MonoType *type = NULL;
8487         MonoTypeNameParse info;
8488         char *tmp;
8489
8490         /* Make a copy since parse_type modifies its argument */
8491         tmp = g_strdup (name);
8492         
8493         /*g_print ("requested type %s\n", str);*/
8494         if (mono_reflection_parse_type (tmp, &info)) {
8495                 type = _mono_reflection_get_type_from_info (&info, image, FALSE, &error);
8496                 if (!is_ok (&error)) {
8497                         g_free (tmp);
8498                         mono_reflection_free_type_info (&info);
8499                         mono_error_raise_exception (&error); /* FIXME don't raise here */
8500                 }
8501         }
8502
8503         g_free (tmp);
8504         mono_reflection_free_type_info (&info);
8505         return type;
8506 }
8507
8508 /*
8509  * mono_reflection_get_token:
8510  *
8511  *   Return the metadata token of OBJ which should be an object
8512  * representing a metadata element.
8513  */
8514 guint32
8515 mono_reflection_get_token (MonoObject *obj)
8516 {
8517         MonoClass *klass;
8518         guint32 token = 0;
8519
8520         klass = obj->vtable->klass;
8521
8522         if (strcmp (klass->name, "MethodBuilder") == 0) {
8523                 MonoReflectionMethodBuilder *mb = (MonoReflectionMethodBuilder *)obj;
8524
8525                 token = mb->table_idx | MONO_TOKEN_METHOD_DEF;
8526         } else if (strcmp (klass->name, "ConstructorBuilder") == 0) {
8527                 MonoReflectionCtorBuilder *mb = (MonoReflectionCtorBuilder *)obj;
8528
8529                 token = mb->table_idx | MONO_TOKEN_METHOD_DEF;
8530         } else if (strcmp (klass->name, "FieldBuilder") == 0) {
8531                 MonoReflectionFieldBuilder *fb = (MonoReflectionFieldBuilder *)obj;
8532
8533                 token = fb->table_idx | MONO_TOKEN_FIELD_DEF;
8534         } else if (strcmp (klass->name, "TypeBuilder") == 0) {
8535                 MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder *)obj;
8536                 token = tb->table_idx | MONO_TOKEN_TYPE_DEF;
8537         } else if (strcmp (klass->name, "MonoType") == 0) {
8538                 MonoType *type = mono_reflection_type_get_handle ((MonoReflectionType*)obj);
8539                 MonoClass *mc = mono_class_from_mono_type (type);
8540                 if (!mono_class_init (mc))
8541                         mono_raise_exception (mono_class_get_exception_for_failure (mc));
8542
8543                 token = mc->type_token;
8544         } else if (strcmp (klass->name, "MonoCMethod") == 0 ||
8545                    strcmp (klass->name, "MonoMethod") == 0 ||
8546                    strcmp (klass->name, "MonoGenericMethod") == 0 ||
8547                    strcmp (klass->name, "MonoGenericCMethod") == 0) {
8548                 MonoReflectionMethod *m = (MonoReflectionMethod *)obj;
8549                 if (m->method->is_inflated) {
8550                         MonoMethodInflated *inflated = (MonoMethodInflated *) m->method;
8551                         return inflated->declaring->token;
8552                 } else {
8553                         token = m->method->token;
8554                 }
8555         } else if (strcmp (klass->name, "MonoField") == 0) {
8556                 MonoReflectionField *f = (MonoReflectionField*)obj;
8557
8558                 if (is_field_on_inst (f->field)) {
8559                         MonoDynamicGenericClass *dgclass = (MonoDynamicGenericClass*)f->field->parent->generic_class;
8560
8561                         if (f->field >= dgclass->fields && f->field < dgclass->fields + dgclass->count_fields) {
8562                                 int field_index = f->field - dgclass->fields;
8563                                 MonoObject *obj;
8564
8565                                 g_assert (field_index >= 0 && field_index < dgclass->count_fields);
8566                                 obj = dgclass->field_objects [field_index];
8567                                 return mono_reflection_get_token (obj);
8568                         }
8569                 }
8570                 token = mono_class_get_field_token (f->field);
8571         } else if (strcmp (klass->name, "MonoProperty") == 0) {
8572                 MonoReflectionProperty *p = (MonoReflectionProperty*)obj;
8573
8574                 token = mono_class_get_property_token (p->property);
8575         } else if (strcmp (klass->name, "MonoEvent") == 0) {
8576                 MonoReflectionMonoEvent *p = (MonoReflectionMonoEvent*)obj;
8577
8578                 token = mono_class_get_event_token (p->event);
8579         } else if (strcmp (klass->name, "ParameterInfo") == 0 || strcmp (klass->name, "MonoParameterInfo") == 0) {
8580                 MonoReflectionParameter *p = (MonoReflectionParameter*)obj;
8581                 MonoClass *member_class = mono_object_class (p->MemberImpl);
8582                 g_assert (mono_class_is_reflection_method_or_constructor (member_class));
8583
8584                 token = mono_method_get_param_token (((MonoReflectionMethod*)p->MemberImpl)->method, p->PositionImpl);
8585         } else if (strcmp (klass->name, "Module") == 0 || strcmp (klass->name, "MonoModule") == 0) {
8586                 MonoReflectionModule *m = (MonoReflectionModule*)obj;
8587
8588                 token = m->token;
8589         } else if (strcmp (klass->name, "Assembly") == 0 || strcmp (klass->name, "MonoAssembly") == 0) {
8590                 token = mono_metadata_make_token (MONO_TABLE_ASSEMBLY, 1);
8591         } else {
8592                 gchar *msg = g_strdup_printf ("MetadataToken is not supported for type '%s.%s'", klass->name_space, klass->name);
8593                 MonoException *ex = mono_get_exception_not_implemented (msg);
8594                 g_free (msg);
8595                 mono_raise_exception (ex);
8596         }
8597
8598         return token;
8599 }
8600
8601 static MonoClass*
8602 load_cattr_enum_type (MonoImage *image, const char *p, const char **end, MonoError *error)
8603 {
8604         char *n;
8605         MonoType *t;
8606         int slen = mono_metadata_decode_value (p, &p);
8607
8608         mono_error_init (error);
8609
8610         n = (char *)g_memdup (p, slen + 1);
8611         n [slen] = 0;
8612         t = mono_reflection_type_from_name (n, image);
8613         if (!t) {
8614                 /* FIXME the error should come from mono_reflection_type_from_name as it will have type/assembly names split */
8615                 /* We don't free n, it's consumed by mono_error */
8616                 mono_error_set_type_load_name (error, n, NULL, "Could not load enum type %s while decoding custom attribute", n);
8617                 return NULL;
8618         }
8619         g_free (n);
8620         p += slen;
8621         *end = p;
8622         return mono_class_from_mono_type (t);
8623 }
8624
8625 static void*
8626 load_cattr_value (MonoImage *image, MonoType *t, const char *p, const char **end, MonoError *error)
8627 {
8628         int slen, type = t->type;
8629         MonoClass *tklass = t->data.klass;
8630
8631         mono_error_init (error);
8632
8633 handle_enum:
8634         switch (type) {
8635         case MONO_TYPE_U1:
8636         case MONO_TYPE_I1:
8637         case MONO_TYPE_BOOLEAN: {
8638                 MonoBoolean *bval = (MonoBoolean *)g_malloc (sizeof (MonoBoolean));
8639                 *bval = *p;
8640                 *end = p + 1;
8641                 return bval;
8642         }
8643         case MONO_TYPE_CHAR:
8644         case MONO_TYPE_U2:
8645         case MONO_TYPE_I2: {
8646                 guint16 *val = (guint16 *)g_malloc (sizeof (guint16));
8647                 *val = read16 (p);
8648                 *end = p + 2;
8649                 return val;
8650         }
8651 #if SIZEOF_VOID_P == 4
8652         case MONO_TYPE_U:
8653         case MONO_TYPE_I:
8654 #endif
8655         case MONO_TYPE_R4:
8656         case MONO_TYPE_U4:
8657         case MONO_TYPE_I4: {
8658                 guint32 *val = (guint32 *)g_malloc (sizeof (guint32));
8659                 *val = read32 (p);
8660                 *end = p + 4;
8661                 return val;
8662         }
8663 #if SIZEOF_VOID_P == 8
8664         case MONO_TYPE_U: /* error out instead? this should probably not happen */
8665         case MONO_TYPE_I:
8666 #endif
8667         case MONO_TYPE_U8:
8668         case MONO_TYPE_I8: {
8669                 guint64 *val = (guint64 *)g_malloc (sizeof (guint64));
8670                 *val = read64 (p);
8671                 *end = p + 8;
8672                 return val;
8673         }
8674         case MONO_TYPE_R8: {
8675                 double *val = (double *)g_malloc (sizeof (double));
8676                 readr8 (p, val);
8677                 *end = p + 8;
8678                 return val;
8679         }
8680         case MONO_TYPE_VALUETYPE:
8681                 if (t->data.klass->enumtype) {
8682                         type = mono_class_enum_basetype (t->data.klass)->type;
8683                         goto handle_enum;
8684                 } else {
8685                         MonoClass *k =  t->data.klass;
8686                         
8687                         if (mono_is_corlib_image (k->image) && strcmp (k->name_space, "System") == 0 && strcmp (k->name, "DateTime") == 0){
8688                                 guint64 *val = (guint64 *)g_malloc (sizeof (guint64));
8689                                 *val = read64 (p);
8690                                 *end = p + 8;
8691                                 return val;
8692                         }
8693                 }
8694                 g_error ("generic valutype %s not handled in custom attr value decoding", t->data.klass->name);
8695                 break;
8696                 
8697         case MONO_TYPE_STRING:
8698                 if (*p == (char)0xFF) {
8699                         *end = p + 1;
8700                         return NULL;
8701                 }
8702                 slen = mono_metadata_decode_value (p, &p);
8703                 *end = p + slen;
8704                 return mono_string_new_len (mono_domain_get (), p, slen);
8705         case MONO_TYPE_CLASS: {
8706                 MonoReflectionType *rt;
8707                 char *n;
8708                 MonoType *t;
8709                 if (*p == (char)0xFF) {
8710                         *end = p + 1;
8711                         return NULL;
8712                 }
8713 handle_type:
8714                 slen = mono_metadata_decode_value (p, &p);
8715                 n = (char *)g_memdup (p, slen + 1);
8716                 n [slen] = 0;
8717                 t = mono_reflection_type_from_name (n, image);
8718                 if (!t) {
8719                         /* FIXME the error should come from mono_reflection_type_from_name as it will have type/assembly names split */
8720                         /* We don't free n, it's consumed by mono_error */
8721                         mono_error_set_type_load_name (error, n, NULL, "Could not load type %s while decoding custom attribute", n);
8722                         return NULL;
8723                 }
8724                 g_free (n);
8725                 *end = p + slen;
8726
8727                 rt = mono_type_get_object_checked (mono_domain_get (), t, error);
8728                 if (!mono_error_ok (error))
8729                         return NULL;
8730
8731                 return rt;
8732         }
8733         case MONO_TYPE_OBJECT: {
8734                 char subt = *p++;
8735                 MonoObject *obj;
8736                 MonoClass *subc = NULL;
8737                 void *val;
8738
8739                 if (subt == 0x50) {
8740                         goto handle_type;
8741                 } else if (subt == 0x0E) {
8742                         type = MONO_TYPE_STRING;
8743                         goto handle_enum;
8744                 } else if (subt == 0x1D) {
8745                         MonoType simple_type = {{0}};
8746                         int etype = *p;
8747                         p ++;
8748
8749                         type = MONO_TYPE_SZARRAY;
8750                         if (etype == 0x50) {
8751                                 tklass = mono_defaults.systemtype_class;
8752                         } else if (etype == 0x55) {
8753                                 tklass = load_cattr_enum_type (image, p, &p, error);
8754                                 if (!mono_error_ok (error))
8755                                         return NULL;
8756                         } else {
8757                                 if (etype == 0x51)
8758                                         /* See Partition II, Appendix B3 */
8759                                         etype = MONO_TYPE_OBJECT;
8760                                 simple_type.type = (MonoTypeEnum)etype;
8761                                 tklass = mono_class_from_mono_type (&simple_type);
8762                         }
8763                         goto handle_enum;
8764                 } else if (subt == 0x55) {
8765                         char *n;
8766                         MonoType *t;
8767                         slen = mono_metadata_decode_value (p, &p);
8768                         n = (char *)g_memdup (p, slen + 1);
8769                         n [slen] = 0;
8770                         t = mono_reflection_type_from_name (n, image);
8771                         if (!t) {
8772                                 /* FIXME the error should come from mono_reflection_type_from_name as it will have type/assembly names split */
8773                                 /* We don't free n, it's consumed by mono_error */
8774                                 mono_error_set_type_load_name (error, n, NULL, "Could not load type %s while decoding custom attribute", n);
8775                                 return NULL;
8776                         }
8777                         g_free (n);
8778                         p += slen;
8779                         subc = mono_class_from_mono_type (t);
8780                 } else if (subt >= MONO_TYPE_BOOLEAN && subt <= MONO_TYPE_R8) {
8781                         MonoType simple_type = {{0}};
8782                         simple_type.type = (MonoTypeEnum)subt;
8783                         subc = mono_class_from_mono_type (&simple_type);
8784                 } else {
8785                         g_error ("Unknown type 0x%02x for object type encoding in custom attr", subt);
8786                 }
8787                 val = load_cattr_value (image, &subc->byval_arg, p, end, error);
8788                 obj = NULL;
8789                 if (mono_error_ok (error)) {
8790                         obj = mono_object_new_checked (mono_domain_get (), subc, error);
8791                         g_assert (!subc->has_references);
8792                         if (mono_error_ok (error))
8793                                 mono_gc_memmove_atomic ((char*)obj + sizeof (MonoObject), val, mono_class_value_size (subc, NULL));
8794                 }
8795
8796                 g_free (val);
8797                 return obj;
8798         }
8799         case MONO_TYPE_SZARRAY: {
8800                 MonoArray *arr;
8801                 guint32 i, alen, basetype;
8802                 alen = read32 (p);
8803                 p += 4;
8804                 if (alen == 0xffffffff) {
8805                         *end = p;
8806                         return NULL;
8807                 }
8808                 arr = mono_array_new (mono_domain_get(), tklass, alen);
8809                 basetype = tklass->byval_arg.type;
8810                 if (basetype == MONO_TYPE_VALUETYPE && tklass->enumtype)
8811                         basetype = mono_class_enum_basetype (tklass)->type;
8812                 switch (basetype)
8813                 {
8814                         case MONO_TYPE_U1:
8815                         case MONO_TYPE_I1:
8816                         case MONO_TYPE_BOOLEAN:
8817                                 for (i = 0; i < alen; i++) {
8818                                         MonoBoolean val = *p++;
8819                                         mono_array_set (arr, MonoBoolean, i, val);
8820                                 }
8821                                 break;
8822                         case MONO_TYPE_CHAR:
8823                         case MONO_TYPE_U2:
8824                         case MONO_TYPE_I2:
8825                                 for (i = 0; i < alen; i++) {
8826                                         guint16 val = read16 (p);
8827                                         mono_array_set (arr, guint16, i, val);
8828                                         p += 2;
8829                                 }
8830                                 break;
8831                         case MONO_TYPE_R4:
8832                         case MONO_TYPE_U4:
8833                         case MONO_TYPE_I4:
8834                                 for (i = 0; i < alen; i++) {
8835                                         guint32 val = read32 (p);
8836                                         mono_array_set (arr, guint32, i, val);
8837                                         p += 4;
8838                                 }
8839                                 break;
8840                         case MONO_TYPE_R8:
8841                                 for (i = 0; i < alen; i++) {
8842                                         double val;
8843                                         readr8 (p, &val);
8844                                         mono_array_set (arr, double, i, val);
8845                                         p += 8;
8846                                 }
8847                                 break;
8848                         case MONO_TYPE_U8:
8849                         case MONO_TYPE_I8:
8850                                 for (i = 0; i < alen; i++) {
8851                                         guint64 val = read64 (p);
8852                                         mono_array_set (arr, guint64, i, val);
8853                                         p += 8;
8854                                 }
8855                                 break;
8856                         case MONO_TYPE_CLASS:
8857                         case MONO_TYPE_OBJECT:
8858                         case MONO_TYPE_STRING:
8859                         case MONO_TYPE_SZARRAY:
8860                                 for (i = 0; i < alen; i++) {
8861                                         MonoObject *item = (MonoObject *)load_cattr_value (image, &tklass->byval_arg, p, &p, error);
8862                                         if (!mono_error_ok (error))
8863                                                 return NULL;
8864                                         mono_array_setref (arr, i, item);
8865                                 }
8866                                 break;
8867                         default:
8868                                 g_error ("Type 0x%02x not handled in custom attr array decoding", basetype);
8869                 }
8870                 *end=p;
8871                 return arr;
8872         }
8873         default:
8874                 g_error ("Type 0x%02x not handled in custom attr value decoding", type);
8875         }
8876         return NULL;
8877 }
8878
8879 static MonoObject*
8880 create_cattr_typed_arg (MonoType *t, MonoObject *val, MonoError *error)
8881 {
8882         static MonoMethod *ctor;
8883         MonoObject *retval;
8884         void *params [2], *unboxed;
8885
8886         mono_error_init (error);
8887
8888         if (!ctor)
8889                 ctor = mono_class_get_method_from_name (mono_class_get_custom_attribute_typed_argument_class (), ".ctor", 2);
8890         
8891         params [0] = mono_type_get_object_checked (mono_domain_get (), t, error);
8892         return_val_if_nok (error, NULL);
8893
8894         params [1] = val;
8895         retval = mono_object_new_checked (mono_domain_get (), mono_class_get_custom_attribute_typed_argument_class (), error);
8896         return_val_if_nok (error, NULL);
8897         unboxed = mono_object_unbox (retval);
8898
8899         mono_runtime_invoke_checked (ctor, unboxed, params, error);
8900         return_val_if_nok (error, NULL);
8901
8902         return retval;
8903 }
8904
8905 static MonoObject*
8906 create_cattr_named_arg (void *minfo, MonoObject *typedarg, MonoError *error)
8907 {
8908         static MonoMethod *ctor;
8909         MonoObject *retval;
8910         void *unboxed, *params [2];
8911
8912         mono_error_init (error);
8913
8914         if (!ctor)
8915                 ctor = mono_class_get_method_from_name (mono_class_get_custom_attribute_named_argument_class (), ".ctor", 2);
8916
8917         params [0] = minfo;
8918         params [1] = typedarg;
8919         retval = mono_object_new_checked (mono_domain_get (), mono_class_get_custom_attribute_named_argument_class (), error);
8920         return_val_if_nok (error, NULL);
8921
8922         unboxed = mono_object_unbox (retval);
8923
8924         mono_runtime_invoke_checked (ctor, unboxed, params, error);
8925         return_val_if_nok (error, NULL);
8926
8927         return retval;
8928 }
8929
8930 static gboolean
8931 type_is_reference (MonoType *type)
8932 {
8933         switch (type->type) {
8934         case MONO_TYPE_BOOLEAN:
8935         case MONO_TYPE_CHAR:
8936         case MONO_TYPE_U:
8937         case MONO_TYPE_I:
8938         case MONO_TYPE_U1:
8939         case MONO_TYPE_I1:
8940         case MONO_TYPE_U2:
8941         case MONO_TYPE_I2:
8942         case MONO_TYPE_U4:
8943         case MONO_TYPE_I4:
8944         case MONO_TYPE_U8:
8945         case MONO_TYPE_I8:
8946         case MONO_TYPE_R8:
8947         case MONO_TYPE_R4:
8948         case MONO_TYPE_VALUETYPE:
8949                 return FALSE;
8950         default:
8951                 return TRUE;
8952         }
8953 }
8954
8955 static void
8956 free_param_data (MonoMethodSignature *sig, void **params) {
8957         int i;
8958         for (i = 0; i < sig->param_count; ++i) {
8959                 if (!type_is_reference (sig->params [i]))
8960                         g_free (params [i]);
8961         }
8962 }
8963
8964 /*
8965  * Find the field index in the metadata FieldDef table.
8966  */
8967 static guint32
8968 find_field_index (MonoClass *klass, MonoClassField *field) {
8969         int i;
8970
8971         for (i = 0; i < klass->field.count; ++i) {
8972                 if (field == &klass->fields [i])
8973                         return klass->field.first + 1 + i;
8974         }
8975         return 0;
8976 }
8977
8978 /*
8979  * Find the property index in the metadata Property table.
8980  */
8981 static guint32
8982 find_property_index (MonoClass *klass, MonoProperty *property) {
8983         int i;
8984
8985         for (i = 0; i < klass->ext->property.count; ++i) {
8986                 if (property == &klass->ext->properties [i])
8987                         return klass->ext->property.first + 1 + i;
8988         }
8989         return 0;
8990 }
8991
8992 /*
8993  * Find the event index in the metadata Event table.
8994  */
8995 static guint32
8996 find_event_index (MonoClass *klass, MonoEvent *event) {
8997         int i;
8998
8999         for (i = 0; i < klass->ext->event.count; ++i) {
9000                 if (event == &klass->ext->events [i])
9001                         return klass->ext->event.first + 1 + i;
9002         }
9003         return 0;
9004 }
9005
9006 static MonoObject*
9007 create_custom_attr (MonoImage *image, MonoMethod *method, const guchar *data, guint32 len, MonoError *error)
9008 {
9009         const char *p = (const char*)data;
9010         const char *named;
9011         guint32 i, j, num_named;
9012         MonoObject *attr;
9013         void *params_buf [32];
9014         void **params = NULL;
9015         MonoMethodSignature *sig;
9016         MonoObject *exc = NULL;
9017
9018         mono_error_init (error);
9019
9020         mono_class_init (method->klass);
9021
9022         if (!mono_verifier_verify_cattr_content (image, method, data, len, NULL)) {
9023                 mono_error_set_generic_error (error, "System.Reflection", "CustomAttributeFormatException", "Binary format of the specified custom attribute was invalid.");
9024                 return NULL;
9025         }
9026
9027         if (len == 0) {
9028                 attr = mono_object_new_checked (mono_domain_get (), method->klass, error);
9029                 if (!mono_error_ok (error)) return NULL;
9030
9031                 mono_runtime_invoke_checked (method, attr, NULL, error);
9032                 if (!mono_error_ok (error))
9033                         return NULL;
9034
9035                 return attr;
9036         }
9037
9038         if (len < 2 || read16 (p) != 0x0001) /* Prolog */
9039                 return NULL;
9040
9041         /*g_print ("got attr %s\n", method->klass->name);*/
9042
9043         sig = mono_method_signature (method);
9044         if (sig->param_count < 32) {
9045                 params = params_buf;
9046                 memset (params, 0, sizeof (void*) * sig->param_count);
9047         } else {
9048                 /* Allocate using GC so it gets GC tracking */
9049                 params = (void **)mono_gc_alloc_fixed (sig->param_count * sizeof (void*), MONO_GC_DESCRIPTOR_NULL, MONO_ROOT_SOURCE_REFLECTION, "custom attribute parameters");
9050         }
9051
9052         /* skip prolog */
9053         p += 2;
9054         for (i = 0; i < mono_method_signature (method)->param_count; ++i) {
9055                 params [i] = load_cattr_value (image, mono_method_signature (method)->params [i], p, &p, error);
9056                 if (!mono_error_ok (error))
9057                         goto fail;
9058         }
9059
9060         named = p;
9061         attr = mono_object_new_checked (mono_domain_get (), method->klass, error);
9062         if (!mono_error_ok (error)) goto fail;
9063
9064         mono_runtime_try_invoke (method, attr, params, &exc, error);
9065         if (!mono_error_ok (error))
9066                 goto fail;
9067         if (exc)
9068                 goto fail;
9069
9070         num_named = read16 (named);
9071         named += 2;
9072         for (j = 0; j < num_named; j++) {
9073                 gint name_len;
9074                 char *name, named_type, data_type;
9075                 named_type = *named++;
9076                 data_type = *named++; /* type of data */
9077                 if (data_type == MONO_TYPE_SZARRAY)
9078                         data_type = *named++;
9079                 if (data_type == MONO_TYPE_ENUM) {
9080                         gint type_len;
9081                         char *type_name;
9082                         type_len = mono_metadata_decode_blob_size (named, &named);
9083                         type_name = (char *)g_malloc (type_len + 1);
9084                         memcpy (type_name, named, type_len);
9085                         type_name [type_len] = 0;
9086                         named += type_len;
9087                         /* FIXME: lookup the type and check type consistency */
9088                         g_free (type_name);
9089                 }
9090                 name_len = mono_metadata_decode_blob_size (named, &named);
9091                 name = (char *)g_malloc (name_len + 1);
9092                 memcpy (name, named, name_len);
9093                 name [name_len] = 0;
9094                 named += name_len;
9095                 if (named_type == 0x53) {
9096                         MonoClassField *field;
9097                         void *val;
9098
9099                         /* how this fail is a blackbox */
9100                         field = mono_class_get_field_from_name (mono_object_class (attr), name);
9101                         if (!field) {
9102                                 mono_error_set_generic_error (error, "System.Reflection", "CustomAttributeFormatException", "Could not find a field with name %s", name);
9103                                 g_free (name);
9104                                 goto fail;
9105                         }
9106
9107                         val = load_cattr_value (image, field->type, named, &named, error);
9108                         if (!mono_error_ok (error)) {
9109                                 g_free (name);
9110                                 if (!type_is_reference (field->type))
9111                                         g_free (val);
9112                                 goto fail;
9113                         }
9114
9115                         mono_field_set_value (attr, field, val);
9116                         if (!type_is_reference (field->type))
9117                                 g_free (val);
9118                 } else if (named_type == 0x54) {
9119                         MonoProperty *prop;
9120                         void *pparams [1];
9121                         MonoType *prop_type;
9122
9123                         prop = mono_class_get_property_from_name (mono_object_class (attr), name);
9124
9125                         if (!prop) {
9126                                 mono_error_set_generic_error (error, "System.Reflection", "CustomAttributeFormatException", "Could not find a property with name %s", name);
9127                                 g_free (name);
9128                                 goto fail;
9129                         }
9130
9131                         if (!prop->set) {
9132                                 mono_error_set_generic_error (error, "System.Reflection", "CustomAttributeFormatException", "Could not find the setter for %s", name);
9133                                 g_free (name);
9134                                 goto fail;
9135                         }
9136
9137                         /* can we have more that 1 arg in a custom attr named property? */
9138                         prop_type = prop->get? mono_method_signature (prop->get)->ret :
9139                              mono_method_signature (prop->set)->params [mono_method_signature (prop->set)->param_count - 1];
9140
9141                         pparams [0] = load_cattr_value (image, prop_type, named, &named, error);
9142                         if (!mono_error_ok (error)) {
9143                                 g_free (name);
9144                                 if (!type_is_reference (prop_type))
9145                                         g_free (pparams [0]);
9146                                 goto fail;
9147                         }
9148
9149
9150                         mono_property_set_value (prop, attr, pparams, NULL);
9151                         if (!type_is_reference (prop_type))
9152                                 g_free (pparams [0]);
9153                 }
9154                 g_free (name);
9155         }
9156
9157         free_param_data (method->signature, params);
9158         if (params != params_buf)
9159                 mono_gc_free_fixed (params);
9160
9161         return attr;
9162
9163 fail:
9164         free_param_data (method->signature, params);
9165         if (params != params_buf)
9166                 mono_gc_free_fixed (params);
9167         if (exc)
9168                 mono_raise_exception ((MonoException*)exc);
9169         return NULL;
9170 }
9171         
9172 /*
9173  * mono_reflection_create_custom_attr_data_args:
9174  *
9175  *   Create an array of typed and named arguments from the cattr blob given by DATA.
9176  * TYPED_ARGS and NAMED_ARGS will contain the objects representing the arguments,
9177  * NAMED_ARG_INFO will contain information about the named arguments.
9178  */
9179 void
9180 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)
9181 {
9182         MonoArray *typedargs, *namedargs;
9183         MonoClass *attrklass;
9184         MonoDomain *domain;
9185         const char *p = (const char*)data;
9186         const char *named;
9187         guint32 i, j, num_named;
9188         CattrNamedArg *arginfo = NULL;
9189
9190         *typed_args = NULL;
9191         *named_args = NULL;
9192         *named_arg_info = NULL;
9193
9194         mono_error_init (error);
9195
9196         if (!mono_verifier_verify_cattr_content (image, method, data, len, NULL)) {
9197                 mono_error_set_generic_error (error, "System.Reflection", "CustomAttributeFormatException", "Binary format of the specified custom attribute was invalid.");
9198                 return;
9199         }
9200
9201         mono_class_init (method->klass);
9202         
9203         domain = mono_domain_get ();
9204
9205         if (len < 2 || read16 (p) != 0x0001) /* Prolog */
9206                 return;
9207
9208         typedargs = mono_array_new (domain, mono_get_object_class (), mono_method_signature (method)->param_count);
9209         
9210         /* skip prolog */
9211         p += 2;
9212         for (i = 0; i < mono_method_signature (method)->param_count; ++i) {
9213                 MonoObject *obj;
9214                 void *val;
9215
9216                 val = load_cattr_value (image, mono_method_signature (method)->params [i], p, &p, error);
9217                 if (!mono_error_ok (error)) {
9218                         if (!type_is_reference (mono_method_signature (method)->params [i]))
9219                                 g_free (val);
9220                         return;
9221                 }
9222
9223                 obj = (MonoObject *)(type_is_reference (mono_method_signature (method)->params [i]) ?
9224                         val : mono_value_box (domain, mono_class_from_mono_type (mono_method_signature (method)->params [i]), val));
9225                 mono_array_setref (typedargs, i, obj);
9226
9227                 if (!type_is_reference (mono_method_signature (method)->params [i]))
9228                         g_free (val);
9229         }
9230
9231         named = p;
9232         num_named = read16 (named);
9233         namedargs = mono_array_new (domain, mono_get_object_class (), num_named);
9234         named += 2;
9235         attrklass = method->klass;
9236
9237         arginfo = g_new0 (CattrNamedArg, num_named);
9238         *named_arg_info = arginfo;
9239
9240         for (j = 0; j < num_named; j++) {
9241                 gint name_len;
9242                 char *name, named_type, data_type;
9243                 named_type = *named++;
9244                 data_type = *named++; /* type of data */
9245                 if (data_type == MONO_TYPE_SZARRAY)
9246                         data_type = *named++;
9247                 if (data_type == MONO_TYPE_ENUM) {
9248                         gint type_len;
9249                         char *type_name;
9250                         type_len = mono_metadata_decode_blob_size (named, &named);
9251                         if (ADDP_IS_GREATER_OR_OVF ((const guchar*)named, type_len, data + len))
9252                                 goto fail;
9253
9254                         type_name = (char *)g_malloc (type_len + 1);
9255                         memcpy (type_name, named, type_len);
9256                         type_name [type_len] = 0;
9257                         named += type_len;
9258                         /* FIXME: lookup the type and check type consistency */
9259                         g_free (type_name);
9260                 }
9261                 name_len = mono_metadata_decode_blob_size (named, &named);
9262                 if (ADDP_IS_GREATER_OR_OVF ((const guchar*)named, name_len, data + len))
9263                         goto fail;
9264                 name = (char *)g_malloc (name_len + 1);
9265                 memcpy (name, named, name_len);
9266                 name [name_len] = 0;
9267                 named += name_len;
9268                 if (named_type == 0x53) {
9269                         MonoObject *obj;
9270                         MonoClassField *field = mono_class_get_field_from_name (attrklass, name);
9271                         void *val;
9272
9273                         if (!field) {
9274                                 g_free (name);
9275                                 goto fail;
9276                         }
9277
9278                         arginfo [j].type = field->type;
9279                         arginfo [j].field = field;
9280
9281                         val = load_cattr_value (image, field->type, named, &named, error);
9282                         if (!mono_error_ok (error)) {
9283                                 if (!type_is_reference (field->type))
9284                                         g_free (val);
9285                                 g_free (name);
9286                                 return;
9287                         }
9288
9289                         obj = (MonoObject *)(type_is_reference (field->type) ? val : mono_value_box (domain, mono_class_from_mono_type (field->type), val));
9290                         mono_array_setref (namedargs, j, obj);
9291                         if (!type_is_reference (field->type))
9292                                 g_free (val);
9293                 } else if (named_type == 0x54) {
9294                         MonoObject *obj;
9295                         MonoType *prop_type;
9296                         MonoProperty *prop = mono_class_get_property_from_name (attrklass, name);
9297                         void *val;
9298
9299                         if (!prop || !prop->set) {
9300                                 g_free (name);
9301                                 goto fail;
9302                         }
9303
9304                         prop_type = prop->get? mono_method_signature (prop->get)->ret :
9305                              mono_method_signature (prop->set)->params [mono_method_signature (prop->set)->param_count - 1];
9306
9307                         arginfo [j].type = prop_type;
9308                         arginfo [j].prop = prop;
9309
9310                         val = load_cattr_value (image, prop_type, named, &named, error);
9311                         if (!mono_error_ok (error)) {
9312                                 if (!type_is_reference (prop_type))
9313                                         g_free (val);
9314                                 g_free (name);
9315                                 return;
9316                         }
9317
9318                         obj = (MonoObject *)(type_is_reference (prop_type) ? val : mono_value_box (domain, mono_class_from_mono_type (prop_type), val));
9319                         mono_array_setref (namedargs, j, obj);
9320                         if (!type_is_reference (prop_type))
9321                                 g_free (val);
9322                 }
9323                 g_free (name);
9324         }
9325
9326         *typed_args = typedargs;
9327         *named_args = namedargs;
9328         return;
9329 fail:
9330         mono_error_set_generic_error (error, "System.Reflection", "CustomAttributeFormatException", "Binary format of the specified custom attribute was invalid.");
9331         g_free (arginfo);
9332         *named_arg_info = NULL;
9333 }
9334
9335 void
9336 mono_reflection_resolve_custom_attribute_data (MonoReflectionMethod *ref_method, MonoReflectionAssembly *assembly, gpointer data, guint32 len, MonoArray **ctor_args, MonoArray **named_args)
9337 {
9338         MonoDomain *domain;
9339         MonoArray *typedargs, *namedargs;
9340         MonoImage *image;
9341         MonoMethod *method;
9342         CattrNamedArg *arginfo = NULL;
9343         MonoError error;
9344         int i;
9345
9346         mono_error_init (&error);
9347
9348         *ctor_args = NULL;
9349         *named_args = NULL;
9350
9351         if (len == 0)
9352                 return;
9353
9354         image = assembly->assembly->image;
9355         method = ref_method->method;
9356         domain = mono_object_domain (ref_method);
9357
9358         if (!mono_class_init (method->klass))
9359                 mono_raise_exception (mono_class_get_exception_for_failure (method->klass));
9360
9361         mono_reflection_create_custom_attr_data_args (image, method, (const guchar *)data, len, &typedargs, &namedargs, &arginfo, &error);
9362         if (!mono_error_ok (&error))
9363                 goto leave;
9364
9365         if (mono_loader_get_last_error ()) {
9366                 mono_error_set_from_loader_error (&error);
9367                 goto leave;
9368         }
9369
9370         if (!typedargs || !namedargs)
9371                 goto leave;
9372
9373         for (i = 0; i < mono_method_signature (method)->param_count; ++i) {
9374                 MonoObject *obj = mono_array_get (typedargs, MonoObject*, i);
9375                 MonoObject *typedarg;
9376
9377                 typedarg = create_cattr_typed_arg (mono_method_signature (method)->params [i], obj, &error);
9378                 if (!is_ok (&error))
9379                         goto leave;
9380                 mono_array_setref (typedargs, i, typedarg);
9381         }
9382
9383         for (i = 0; i < mono_array_length (namedargs); ++i) {
9384                 MonoObject *obj = mono_array_get (namedargs, MonoObject*, i);
9385                 MonoObject *typedarg, *namedarg, *minfo;
9386
9387                 if (arginfo [i].prop) {
9388                         minfo = (MonoObject*)mono_property_get_object_checked (domain, NULL, arginfo [i].prop, &error);
9389                         if (!minfo)
9390                                 goto leave;
9391                 } else {
9392                         minfo = (MonoObject*)mono_field_get_object_checked (domain, NULL, arginfo [i].field, &error);
9393                         if (!mono_error_ok (&error))
9394                                 goto leave;
9395                 }
9396
9397                 typedarg = create_cattr_typed_arg (arginfo [i].type, obj, &error);
9398                 if (!is_ok (&error))
9399                         goto leave;
9400                 namedarg = create_cattr_named_arg (minfo, typedarg, &error);
9401                 if (!is_ok (&error))
9402                         goto leave;
9403
9404                 mono_array_setref (namedargs, i, namedarg);
9405         }
9406
9407         *ctor_args = typedargs;
9408         *named_args = namedargs;
9409 leave:
9410         g_free (arginfo);
9411         mono_error_raise_exception (&error);
9412
9413 }
9414
9415 static MonoObject*
9416 create_custom_attr_data (MonoImage *image, MonoCustomAttrEntry *cattr, MonoError *error)
9417 {
9418         static MonoMethod *ctor;
9419
9420         MonoDomain *domain;
9421         MonoObject *attr;
9422         void *params [4];
9423
9424         mono_error_init (error);
9425
9426         g_assert (image->assembly);
9427
9428         if (!ctor)
9429                 ctor = mono_class_get_method_from_name (mono_defaults.customattribute_data_class, ".ctor", 4);
9430
9431         domain = mono_domain_get ();
9432         attr = mono_object_new_checked (domain, mono_defaults.customattribute_data_class, error);
9433         return_val_if_nok (error, NULL);
9434         params [0] = mono_method_get_object_checked (domain, cattr->ctor, NULL, error);
9435         return_val_if_nok (error, NULL);
9436         params [1] = mono_assembly_get_object_checked (domain, image->assembly, error);
9437         return_val_if_nok (error, NULL);
9438         params [2] = (gpointer)&cattr->data;
9439         params [3] = &cattr->data_size;
9440
9441         mono_runtime_invoke_checked (ctor, attr, params, error);
9442         return_val_if_nok (error, NULL);
9443         return attr;
9444 }
9445
9446 static MonoArray*
9447 mono_custom_attrs_construct_by_type (MonoCustomAttrInfo *cinfo, MonoClass *attr_klass, MonoError *error)
9448 {
9449         MonoArray *result;
9450         MonoObject *attr;
9451         int i, n;
9452
9453         mono_error_init (error);
9454
9455         n = 0;
9456         for (i = 0; i < cinfo->num_attrs; ++i) {
9457                 if (!attr_klass || mono_class_is_assignable_from (attr_klass, cinfo->attrs [i].ctor->klass))
9458                         n ++;
9459         }
9460
9461         result = mono_array_new_cached (mono_domain_get (), mono_defaults.attribute_class, n);
9462         n = 0;
9463         for (i = 0; i < cinfo->num_attrs; ++i) {
9464                 if (!cinfo->attrs [i].ctor) {
9465                         /* The cattr type is not finished yet */
9466                         /* We should include the type name but cinfo doesn't contain it */
9467                         mono_error_set_type_load_name (error, NULL, NULL, "");
9468                         return NULL;
9469                 }
9470                 if (!attr_klass || mono_class_is_assignable_from (attr_klass, cinfo->attrs [i].ctor->klass)) {
9471                         attr = create_custom_attr (cinfo->image, cinfo->attrs [i].ctor, cinfo->attrs [i].data, cinfo->attrs [i].data_size, error);
9472                         if (!mono_error_ok (error))
9473                                 return result;
9474                         mono_array_setref (result, n, attr);
9475                         n ++;
9476                 }
9477         }
9478         return result;
9479 }
9480
9481 MonoArray*
9482 mono_custom_attrs_construct (MonoCustomAttrInfo *cinfo)
9483 {
9484         MonoError error;
9485         MonoArray *result = mono_custom_attrs_construct_by_type (cinfo, NULL, &error);
9486         mono_error_assert_ok (&error); /*FIXME proper error handling*/
9487
9488         return result;
9489 }
9490
9491 static MonoArray*
9492 mono_custom_attrs_data_construct (MonoCustomAttrInfo *cinfo, MonoError *error)
9493 {
9494         MonoArray *result;
9495         MonoObject *attr;
9496         int i;
9497         
9498         mono_error_init (error);
9499         result = mono_array_new (mono_domain_get (), mono_defaults.customattribute_data_class, cinfo->num_attrs);
9500         for (i = 0; i < cinfo->num_attrs; ++i) {
9501                 attr = create_custom_attr_data (cinfo->image, &cinfo->attrs [i], error);
9502                 return_val_if_nok (error, NULL);
9503                 mono_array_setref (result, i, attr);
9504         }
9505         return result;
9506 }
9507
9508 /**
9509  * mono_custom_attrs_from_index:
9510  *
9511  * Returns: NULL if no attributes are found or if a loading error occurs.
9512  */
9513 MonoCustomAttrInfo*
9514 mono_custom_attrs_from_index (MonoImage *image, guint32 idx)
9515 {
9516         MonoError error;
9517         MonoCustomAttrInfo *result = mono_custom_attrs_from_index_checked (image, idx, &error);
9518         mono_error_cleanup (&error); /* FIXME a better public API that doesn't swallow the error. */
9519         return result;
9520 }
9521 /**
9522  * mono_custom_attrs_from_index_checked:
9523  *
9524  * Returns: NULL if no attributes are found.  On error returns NULL and sets @error.
9525  */
9526 MonoCustomAttrInfo*
9527 mono_custom_attrs_from_index_checked (MonoImage *image, guint32 idx, MonoError *error)
9528 {
9529         guint32 mtoken, i, len;
9530         guint32 cols [MONO_CUSTOM_ATTR_SIZE];
9531         MonoTableInfo *ca;
9532         MonoCustomAttrInfo *ainfo;
9533         GList *tmp, *list = NULL;
9534         const char *data;
9535         MonoCustomAttrEntry* attr;
9536
9537         mono_error_init (error);
9538
9539         ca = &image->tables [MONO_TABLE_CUSTOMATTRIBUTE];
9540
9541         i = mono_metadata_custom_attrs_from_index (image, idx);
9542         if (!i)
9543                 return NULL;
9544         i --;
9545         while (i < ca->rows) {
9546                 if (mono_metadata_decode_row_col (ca, i, MONO_CUSTOM_ATTR_PARENT) != idx)
9547                         break;
9548                 list = g_list_prepend (list, GUINT_TO_POINTER (i));
9549                 ++i;
9550         }
9551         len = g_list_length (list);
9552         if (!len)
9553                 return NULL;
9554         ainfo = (MonoCustomAttrInfo *)g_malloc0 (MONO_SIZEOF_CUSTOM_ATTR_INFO + sizeof (MonoCustomAttrEntry) * len);
9555         ainfo->num_attrs = len;
9556         ainfo->image = image;
9557         for (i = len, tmp = list; i != 0; --i, tmp = tmp->next) {
9558                 mono_metadata_decode_row (ca, GPOINTER_TO_UINT (tmp->data), cols, MONO_CUSTOM_ATTR_SIZE);
9559                 mtoken = cols [MONO_CUSTOM_ATTR_TYPE] >> MONO_CUSTOM_ATTR_TYPE_BITS;
9560                 switch (cols [MONO_CUSTOM_ATTR_TYPE] & MONO_CUSTOM_ATTR_TYPE_MASK) {
9561                 case MONO_CUSTOM_ATTR_TYPE_METHODDEF:
9562                         mtoken |= MONO_TOKEN_METHOD_DEF;
9563                         break;
9564                 case MONO_CUSTOM_ATTR_TYPE_MEMBERREF:
9565                         mtoken |= MONO_TOKEN_MEMBER_REF;
9566                         break;
9567                 default:
9568                         g_error ("Unknown table for custom attr type %08x", cols [MONO_CUSTOM_ATTR_TYPE]);
9569                         break;
9570                 }
9571                 attr = &ainfo->attrs [i - 1];
9572                 attr->ctor = mono_get_method_checked (image, mtoken, NULL, NULL, error);
9573                 if (!attr->ctor) {
9574                         g_warning ("Can't find custom attr constructor image: %s mtoken: 0x%08x due to %s", image->name, mtoken, mono_error_get_message (error));
9575                         g_list_free (list);
9576                         g_free (ainfo);
9577                         return NULL;
9578                 }
9579
9580                 if (!mono_verifier_verify_cattr_blob (image, cols [MONO_CUSTOM_ATTR_VALUE], NULL)) {
9581                         /*FIXME raising an exception here doesn't make any sense*/
9582                         g_warning ("Invalid custom attribute blob on image %s for index %x", image->name, idx);
9583                         g_list_free (list);
9584                         g_free (ainfo);
9585                         return NULL;
9586                 }
9587                 data = mono_metadata_blob_heap (image, cols [MONO_CUSTOM_ATTR_VALUE]);
9588                 attr->data_size = mono_metadata_decode_value (data, &data);
9589                 attr->data = (guchar*)data;
9590         }
9591         g_list_free (list);
9592
9593         return ainfo;
9594 }
9595
9596 MonoCustomAttrInfo*
9597 mono_custom_attrs_from_method (MonoMethod *method)
9598 {
9599         MonoError error;
9600         MonoCustomAttrInfo* result = mono_custom_attrs_from_method_checked  (method, &error);
9601         mono_error_cleanup (&error); /* FIXME want a better API that doesn't swallow the error */
9602         return result;
9603 }
9604
9605 MonoCustomAttrInfo*
9606 mono_custom_attrs_from_method_checked (MonoMethod *method, MonoError *error)
9607 {
9608         guint32 idx;
9609
9610         mono_error_init (error);
9611
9612         /*
9613          * An instantiated method has the same cattrs as the generic method definition.
9614          *
9615          * LAMESPEC: The .NET SRE throws an exception for instantiations of generic method builders
9616          *           Note that this stanza is not necessary for non-SRE types, but it's a micro-optimization
9617          */
9618         if (method->is_inflated)
9619                 method = ((MonoMethodInflated *) method)->declaring;
9620         
9621         if (method_is_dynamic (method) || image_is_dynamic (method->klass->image))
9622                 return lookup_custom_attr (method->klass->image, method);
9623
9624         if (!method->token)
9625                 /* Synthetic methods */
9626                 return NULL;
9627
9628         idx = mono_method_get_index (method);
9629         idx <<= MONO_CUSTOM_ATTR_BITS;
9630         idx |= MONO_CUSTOM_ATTR_METHODDEF;
9631         return mono_custom_attrs_from_index_checked (method->klass->image, idx, error);
9632 }
9633
9634 MonoCustomAttrInfo*
9635 mono_custom_attrs_from_class (MonoClass *klass)
9636 {
9637         MonoError error;
9638         MonoCustomAttrInfo *result = mono_custom_attrs_from_class_checked (klass, &error);
9639         mono_error_cleanup (&error); /* FIXME want a better API that doesn't swallow the error */
9640         return result;
9641 }
9642
9643 MonoCustomAttrInfo*
9644 mono_custom_attrs_from_class_checked (MonoClass *klass, MonoError *error)
9645 {
9646         guint32 idx;
9647
9648         mono_error_init (error);
9649
9650         if (klass->generic_class)
9651                 klass = klass->generic_class->container_class;
9652
9653         if (image_is_dynamic (klass->image))
9654                 return lookup_custom_attr (klass->image, klass);
9655
9656         if (klass->byval_arg.type == MONO_TYPE_VAR || klass->byval_arg.type == MONO_TYPE_MVAR) {
9657                 idx = mono_metadata_token_index (klass->sizes.generic_param_token);
9658                 idx <<= MONO_CUSTOM_ATTR_BITS;
9659                 idx |= MONO_CUSTOM_ATTR_GENERICPAR;
9660         } else {
9661                 idx = mono_metadata_token_index (klass->type_token);
9662                 idx <<= MONO_CUSTOM_ATTR_BITS;
9663                 idx |= MONO_CUSTOM_ATTR_TYPEDEF;
9664         }
9665         return mono_custom_attrs_from_index_checked (klass->image, idx, error);
9666 }
9667
9668 MonoCustomAttrInfo*
9669 mono_custom_attrs_from_assembly (MonoAssembly *assembly)
9670 {
9671         MonoError error;
9672         MonoCustomAttrInfo *result = mono_custom_attrs_from_assembly_checked (assembly, &error);
9673         mono_error_cleanup (&error); /* FIXME want a better API that doesn't swallow the error */
9674         return result;
9675 }
9676
9677 MonoCustomAttrInfo*
9678 mono_custom_attrs_from_assembly_checked (MonoAssembly *assembly, MonoError *error)
9679 {
9680         guint32 idx;
9681         
9682         mono_error_init (error);
9683
9684         if (image_is_dynamic (assembly->image))
9685                 return lookup_custom_attr (assembly->image, assembly);
9686         idx = 1; /* there is only one assembly */
9687         idx <<= MONO_CUSTOM_ATTR_BITS;
9688         idx |= MONO_CUSTOM_ATTR_ASSEMBLY;
9689         return mono_custom_attrs_from_index_checked (assembly->image, idx, error);
9690 }
9691
9692 static MonoCustomAttrInfo*
9693 mono_custom_attrs_from_module (MonoImage *image, MonoError *error)
9694 {
9695         guint32 idx;
9696         
9697         if (image_is_dynamic (image))
9698                 return lookup_custom_attr (image, image);
9699         idx = 1; /* there is only one module */
9700         idx <<= MONO_CUSTOM_ATTR_BITS;
9701         idx |= MONO_CUSTOM_ATTR_MODULE;
9702         return mono_custom_attrs_from_index_checked (image, idx, error);
9703 }
9704
9705 MonoCustomAttrInfo*
9706 mono_custom_attrs_from_property (MonoClass *klass, MonoProperty *property)
9707 {
9708         MonoError error;
9709         MonoCustomAttrInfo * result = mono_custom_attrs_from_property_checked (klass, property, &error);
9710         mono_error_cleanup (&error); /* FIXME want a better API that doesn't swallow the error */
9711         return result;
9712 }
9713
9714 MonoCustomAttrInfo*
9715 mono_custom_attrs_from_property_checked (MonoClass *klass, MonoProperty *property, MonoError *error)
9716 {
9717         guint32 idx;
9718         
9719         if (image_is_dynamic (klass->image)) {
9720                 property = mono_metadata_get_corresponding_property_from_generic_type_definition (property);
9721                 return lookup_custom_attr (klass->image, property);
9722         }
9723         idx = find_property_index (klass, property);
9724         idx <<= MONO_CUSTOM_ATTR_BITS;
9725         idx |= MONO_CUSTOM_ATTR_PROPERTY;
9726         return mono_custom_attrs_from_index_checked (klass->image, idx, error);
9727 }
9728
9729 MonoCustomAttrInfo*
9730 mono_custom_attrs_from_event (MonoClass *klass, MonoEvent *event)
9731 {
9732         MonoError error;
9733         MonoCustomAttrInfo * result = mono_custom_attrs_from_event_checked (klass, event, &error);
9734         mono_error_cleanup (&error); /* FIXME want a better API that doesn't swallow the error */
9735         return result;
9736 }
9737
9738 MonoCustomAttrInfo*
9739 mono_custom_attrs_from_event_checked (MonoClass *klass, MonoEvent *event, MonoError *error)
9740 {
9741         guint32 idx;
9742         
9743         if (image_is_dynamic (klass->image)) {
9744                 event = mono_metadata_get_corresponding_event_from_generic_type_definition (event);
9745                 return lookup_custom_attr (klass->image, event);
9746         }
9747         idx = find_event_index (klass, event);
9748         idx <<= MONO_CUSTOM_ATTR_BITS;
9749         idx |= MONO_CUSTOM_ATTR_EVENT;
9750         return mono_custom_attrs_from_index_checked (klass->image, idx, error);
9751 }
9752
9753 MonoCustomAttrInfo*
9754 mono_custom_attrs_from_field (MonoClass *klass, MonoClassField *field)
9755 {
9756         MonoError error;
9757         MonoCustomAttrInfo * result = mono_custom_attrs_from_field_checked (klass, field, &error);
9758         mono_error_cleanup (&error); /* FIXME want a better API that doesn't swallow the error */
9759         return result;
9760 }
9761
9762 MonoCustomAttrInfo*
9763 mono_custom_attrs_from_field_checked (MonoClass *klass, MonoClassField *field, MonoError *error)
9764 {
9765         guint32 idx;
9766         mono_error_init (error);
9767
9768         if (image_is_dynamic (klass->image)) {
9769                 field = mono_metadata_get_corresponding_field_from_generic_type_definition (field);
9770                 return lookup_custom_attr (klass->image, field);
9771         }
9772         idx = find_field_index (klass, field);
9773         idx <<= MONO_CUSTOM_ATTR_BITS;
9774         idx |= MONO_CUSTOM_ATTR_FIELDDEF;
9775         return mono_custom_attrs_from_index_checked (klass->image, idx, error);
9776 }
9777
9778 /**
9779  * mono_custom_attrs_from_param:
9780  * @method: handle to the method that we want to retrieve custom parameter information from
9781  * @param: parameter number, where zero represent the return value, and one is the first parameter in the method
9782  *
9783  * The result must be released with mono_custom_attrs_free().
9784  *
9785  * Returns: the custom attribute object for the specified parameter, or NULL if there are none.
9786  */
9787 MonoCustomAttrInfo*
9788 mono_custom_attrs_from_param (MonoMethod *method, guint32 param)
9789 {
9790         MonoError error;
9791         MonoCustomAttrInfo *result = mono_custom_attrs_from_param_checked (method, param, &error);
9792         mono_error_cleanup (&error); /* FIXME want a better API that doesn't swallow the error */
9793         return result;
9794 }
9795
9796 /**
9797  * mono_custom_attrs_from_param_checked:
9798  * @method: handle to the method that we want to retrieve custom parameter information from
9799  * @param: parameter number, where zero represent the return value, and one is the first parameter in the method
9800  * @error: set on error
9801  *
9802  * The result must be released with mono_custom_attrs_free().
9803  *
9804  * Returns: the custom attribute object for the specified parameter, or NULL if there are none.  On failure returns NULL and sets @error.
9805  */
9806 MonoCustomAttrInfo*
9807 mono_custom_attrs_from_param_checked (MonoMethod *method, guint32 param, MonoError *error)
9808 {
9809         MonoTableInfo *ca;
9810         guint32 i, idx, method_index;
9811         guint32 param_list, param_last, param_pos, found;
9812         MonoImage *image;
9813         MonoReflectionMethodAux *aux;
9814
9815         mono_error_init (error);
9816
9817         /*
9818          * An instantiated method has the same cattrs as the generic method definition.
9819          *
9820          * LAMESPEC: The .NET SRE throws an exception for instantiations of generic method builders
9821          *           Note that this stanza is not necessary for non-SRE types, but it's a micro-optimization
9822          */
9823         if (method->is_inflated)
9824                 method = ((MonoMethodInflated *) method)->declaring;
9825
9826         if (image_is_dynamic (method->klass->image)) {
9827                 MonoCustomAttrInfo *res, *ainfo;
9828                 int size;
9829
9830                 aux = (MonoReflectionMethodAux *)g_hash_table_lookup (((MonoDynamicImage*)method->klass->image)->method_aux_hash, method);
9831                 if (!aux || !aux->param_cattr)
9832                         return NULL;
9833
9834                 /* Need to copy since it will be freed later */
9835                 ainfo = aux->param_cattr [param];
9836                 if (!ainfo)
9837                         return NULL;
9838                 size = MONO_SIZEOF_CUSTOM_ATTR_INFO + sizeof (MonoCustomAttrEntry) * ainfo->num_attrs;
9839                 res = (MonoCustomAttrInfo *)g_malloc0 (size);
9840                 memcpy (res, ainfo, size);
9841                 return res;
9842         }
9843
9844         image = method->klass->image;
9845         method_index = mono_method_get_index (method);
9846         if (!method_index)
9847                 return NULL;
9848         ca = &image->tables [MONO_TABLE_METHOD];
9849
9850         param_list = mono_metadata_decode_row_col (ca, method_index - 1, MONO_METHOD_PARAMLIST);
9851         if (method_index == ca->rows) {
9852                 ca = &image->tables [MONO_TABLE_PARAM];
9853                 param_last = ca->rows + 1;
9854         } else {
9855                 param_last = mono_metadata_decode_row_col (ca, method_index, MONO_METHOD_PARAMLIST);
9856                 ca = &image->tables [MONO_TABLE_PARAM];
9857         }
9858         found = FALSE;
9859         for (i = param_list; i < param_last; ++i) {
9860                 param_pos = mono_metadata_decode_row_col (ca, i - 1, MONO_PARAM_SEQUENCE);
9861                 if (param_pos == param) {
9862                         found = TRUE;
9863                         break;
9864                 }
9865         }
9866         if (!found)
9867                 return NULL;
9868         idx = i;
9869         idx <<= MONO_CUSTOM_ATTR_BITS;
9870         idx |= MONO_CUSTOM_ATTR_PARAMDEF;
9871         return mono_custom_attrs_from_index_checked (image, idx, error);
9872 }
9873
9874 gboolean
9875 mono_custom_attrs_has_attr (MonoCustomAttrInfo *ainfo, MonoClass *attr_klass)
9876 {
9877         int i;
9878         MonoClass *klass;
9879         for (i = 0; i < ainfo->num_attrs; ++i) {
9880                 klass = ainfo->attrs [i].ctor->klass;
9881                 if (mono_class_has_parent (klass, attr_klass) || (MONO_CLASS_IS_INTERFACE (attr_klass) && mono_class_is_assignable_from (attr_klass, klass)))
9882                         return TRUE;
9883         }
9884         return FALSE;
9885 }
9886
9887 MonoObject*
9888 mono_custom_attrs_get_attr (MonoCustomAttrInfo *ainfo, MonoClass *attr_klass)
9889 {
9890         MonoError error;
9891         MonoObject *res = mono_custom_attrs_get_attr_checked (ainfo, attr_klass, &error);
9892         g_assert (mono_error_ok (&error)); /*FIXME proper error handling*/
9893         return res;
9894 }
9895
9896 MonoObject*
9897 mono_custom_attrs_get_attr_checked (MonoCustomAttrInfo *ainfo, MonoClass *attr_klass, MonoError *error)
9898 {
9899         int i, attr_index;
9900         MonoClass *klass;
9901         MonoArray *attrs;
9902
9903         mono_error_init (error);
9904
9905         attr_index = -1;
9906         for (i = 0; i < ainfo->num_attrs; ++i) {
9907                 klass = ainfo->attrs [i].ctor->klass;
9908                 if (mono_class_has_parent (klass, attr_klass)) {
9909                         attr_index = i;
9910                         break;
9911                 }
9912         }
9913         if (attr_index == -1)
9914                 return NULL;
9915
9916         attrs = mono_custom_attrs_construct_by_type (ainfo, NULL, error);
9917         if (!mono_error_ok (error))
9918                 return NULL;
9919         return mono_array_get (attrs, MonoObject*, attr_index);
9920 }
9921
9922 /*
9923  * mono_reflection_get_custom_attrs_info:
9924  * @obj: a reflection object handle
9925  *
9926  * Return the custom attribute info for attributes defined for the
9927  * reflection handle @obj. The objects.
9928  *
9929  * FIXME this function leaks like a sieve for SRE objects.
9930  */
9931 MonoCustomAttrInfo*
9932 mono_reflection_get_custom_attrs_info (MonoObject *obj)
9933 {
9934         MonoError error;
9935         MonoCustomAttrInfo *result = mono_reflection_get_custom_attrs_info_checked (obj, &error);
9936         mono_error_assert_ok (&error);
9937         return result;
9938 }
9939
9940 /**
9941  * mono_reflection_get_custom_attrs_info_checked:
9942  * @obj: a reflection object handle
9943  * @error: set on error
9944  *
9945  * Return the custom attribute info for attributes defined for the
9946  * reflection handle @obj. The objects.
9947  *
9948  * On failure returns NULL and sets @error.
9949  *
9950  * FIXME this function leaks like a sieve for SRE objects.
9951  */
9952 MonoCustomAttrInfo*
9953 mono_reflection_get_custom_attrs_info_checked (MonoObject *obj, MonoError *error)
9954 {
9955         MonoClass *klass;
9956         MonoCustomAttrInfo *cinfo = NULL;
9957         
9958         mono_error_init (error);
9959
9960         klass = obj->vtable->klass;
9961         if (klass == mono_defaults.monotype_class) {
9962                 MonoType *type = mono_reflection_type_get_handle ((MonoReflectionType *)obj);
9963                 klass = mono_class_from_mono_type (type);
9964                 /*We cannot mono_class_init the class from which we'll load the custom attributes since this must work with broken types.*/
9965                 cinfo = mono_custom_attrs_from_class_checked (klass, error);
9966                 return_val_if_nok (error, NULL);
9967         } else if (strcmp ("Assembly", klass->name) == 0 || strcmp ("MonoAssembly", klass->name) == 0) {
9968                 MonoReflectionAssembly *rassembly = (MonoReflectionAssembly*)obj;
9969                 cinfo = mono_custom_attrs_from_assembly_checked (rassembly->assembly, error);
9970                 return_val_if_nok (error, NULL);
9971         } else if (strcmp ("Module", klass->name) == 0 || strcmp ("MonoModule", klass->name) == 0) {
9972                 MonoReflectionModule *module = (MonoReflectionModule*)obj;
9973                 cinfo = mono_custom_attrs_from_module (module->image, error);
9974                 return_val_if_nok (error, NULL);
9975         } else if (strcmp ("MonoProperty", klass->name) == 0) {
9976                 MonoReflectionProperty *rprop = (MonoReflectionProperty*)obj;
9977                 cinfo = mono_custom_attrs_from_property_checked (rprop->property->parent, rprop->property, error);
9978                 return_val_if_nok (error, NULL);
9979         } else if (strcmp ("MonoEvent", klass->name) == 0) {
9980                 MonoReflectionMonoEvent *revent = (MonoReflectionMonoEvent*)obj;
9981                 cinfo = mono_custom_attrs_from_event_checked (revent->event->parent, revent->event, error);
9982                 return_val_if_nok (error, NULL);
9983         } else if (strcmp ("MonoField", klass->name) == 0) {
9984                 MonoReflectionField *rfield = (MonoReflectionField*)obj;
9985                 cinfo = mono_custom_attrs_from_field_checked (rfield->field->parent, rfield->field, error);
9986                 return_val_if_nok (error, NULL);
9987         } else if ((strcmp ("MonoMethod", klass->name) == 0) || (strcmp ("MonoCMethod", klass->name) == 0)) {
9988                 MonoReflectionMethod *rmethod = (MonoReflectionMethod*)obj;
9989                 cinfo = mono_custom_attrs_from_method_checked (rmethod->method, error);
9990                 return_val_if_nok (error, NULL);
9991         } else if ((strcmp ("MonoGenericMethod", klass->name) == 0) || (strcmp ("MonoGenericCMethod", klass->name) == 0)) {
9992                 MonoReflectionMethod *rmethod = (MonoReflectionMethod*)obj;
9993                 cinfo = mono_custom_attrs_from_method_checked (rmethod->method, error);
9994                 return_val_if_nok (error, NULL);
9995         } else if (strcmp ("ParameterInfo", klass->name) == 0 || strcmp ("MonoParameterInfo", klass->name) == 0) {
9996                 MonoReflectionParameter *param = (MonoReflectionParameter*)obj;
9997                 MonoClass *member_class = mono_object_class (param->MemberImpl);
9998                 if (mono_class_is_reflection_method_or_constructor (member_class)) {
9999                         MonoReflectionMethod *rmethod = (MonoReflectionMethod*)param->MemberImpl;
10000                         cinfo = mono_custom_attrs_from_param_checked (rmethod->method, param->PositionImpl + 1, error);
10001                         return_val_if_nok (error, NULL);
10002                 } else if (is_sr_mono_property (member_class)) {
10003                         MonoReflectionProperty *prop = (MonoReflectionProperty *)param->MemberImpl;
10004                         MonoMethod *method;
10005                         if (!(method = prop->property->get))
10006                                 method = prop->property->set;
10007                         g_assert (method);
10008
10009                         cinfo = mono_custom_attrs_from_param_checked (method, param->PositionImpl + 1, error);
10010                         return_val_if_nok (error, NULL);
10011                 } 
10012 #ifndef DISABLE_REFLECTION_EMIT
10013                 else if (is_sre_method_on_tb_inst (member_class)) {/*XXX This is a workaround for Compiler Context*/
10014                         MonoMethod *method = mono_reflection_method_on_tb_inst_get_handle ((MonoReflectionMethodOnTypeBuilderInst*)param->MemberImpl, error);
10015                         return_val_if_nok (error, NULL);
10016                         cinfo = mono_custom_attrs_from_param_checked (method, param->PositionImpl + 1, error);
10017                         return_val_if_nok (error, NULL);
10018                 } else if (is_sre_ctor_on_tb_inst (member_class)) { /*XX This is a workaround for Compiler Context*/
10019                         MonoReflectionCtorOnTypeBuilderInst *c = (MonoReflectionCtorOnTypeBuilderInst*)param->MemberImpl;
10020                         MonoMethod *method = NULL;
10021                         if (is_sre_ctor_builder (mono_object_class (c->cb)))
10022                                 method = ((MonoReflectionCtorBuilder *)c->cb)->mhandle;
10023                         else if (is_sr_mono_cmethod (mono_object_class (c->cb)))
10024                                 method = ((MonoReflectionMethod *)c->cb)->method;
10025                         else
10026                                 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));
10027
10028                         cinfo = mono_custom_attrs_from_param_checked (method, param->PositionImpl + 1, error);
10029                         return_val_if_nok (error, NULL);
10030                 } 
10031 #endif
10032                 else {
10033                         char *type_name = mono_type_get_full_name (member_class);
10034                         mono_error_set_generic_error (error, "System", "NotSupportedException",
10035                                                       "Custom attributes on a ParamInfo with member %s are not supported",
10036                                                       type_name);
10037                         g_free (type_name);
10038                         return NULL;
10039                 }
10040         } else if (strcmp ("AssemblyBuilder", klass->name) == 0) {
10041                 MonoReflectionAssemblyBuilder *assemblyb = (MonoReflectionAssemblyBuilder*)obj;
10042                 cinfo = mono_custom_attrs_from_builders (NULL, assemblyb->assembly.assembly->image, assemblyb->cattrs);
10043         } else if (strcmp ("TypeBuilder", klass->name) == 0) {
10044                 MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder*)obj;
10045                 cinfo = mono_custom_attrs_from_builders (NULL, &tb->module->dynamic_image->image, tb->cattrs);
10046         } else if (strcmp ("ModuleBuilder", klass->name) == 0) {
10047                 MonoReflectionModuleBuilder *mb = (MonoReflectionModuleBuilder*)obj;
10048                 cinfo = mono_custom_attrs_from_builders (NULL, &mb->dynamic_image->image, mb->cattrs);
10049         } else if (strcmp ("ConstructorBuilder", klass->name) == 0) {
10050                 MonoReflectionCtorBuilder *cb = (MonoReflectionCtorBuilder*)obj;
10051                 cinfo = mono_custom_attrs_from_builders (NULL, cb->mhandle->klass->image, cb->cattrs);
10052         } else if (strcmp ("MethodBuilder", klass->name) == 0) {
10053                 MonoReflectionMethodBuilder *mb = (MonoReflectionMethodBuilder*)obj;
10054                 cinfo = mono_custom_attrs_from_builders (NULL, mb->mhandle->klass->image, mb->cattrs);
10055         } else if (strcmp ("FieldBuilder", klass->name) == 0) {
10056                 MonoReflectionFieldBuilder *fb = (MonoReflectionFieldBuilder*)obj;
10057                 cinfo = mono_custom_attrs_from_builders (NULL, &((MonoReflectionTypeBuilder*)fb->typeb)->module->dynamic_image->image, fb->cattrs);
10058         } else if (strcmp ("MonoGenericClass", klass->name) == 0) {
10059                 MonoReflectionGenericClass *gclass = (MonoReflectionGenericClass*)obj;
10060                 cinfo = mono_reflection_get_custom_attrs_info_checked ((MonoObject*)gclass->generic_type, error);
10061                 return_val_if_nok (error, NULL);
10062         } else { /* handle other types here... */
10063                 g_error ("get custom attrs not yet supported for %s", klass->name);
10064         }
10065
10066         return cinfo;
10067 }
10068
10069 /*
10070  * mono_reflection_get_custom_attrs_by_type:
10071  * @obj: a reflection object handle
10072  *
10073  * Return an array with all the custom attributes defined of the
10074  * reflection handle @obj. If @attr_klass is non-NULL, only custom attributes 
10075  * of that type are returned. The objects are fully build. Return NULL if a loading error
10076  * occurs.
10077  */
10078 MonoArray*
10079 mono_reflection_get_custom_attrs_by_type (MonoObject *obj, MonoClass *attr_klass, MonoError *error)
10080 {
10081         MonoArray *result;
10082         MonoCustomAttrInfo *cinfo;
10083
10084         mono_error_init (error);
10085
10086         cinfo = mono_reflection_get_custom_attrs_info_checked (obj, error);
10087         return_val_if_nok (error, NULL);
10088         if (cinfo) {
10089                 result = mono_custom_attrs_construct_by_type (cinfo, attr_klass, error);
10090                 if (!result)
10091                         return NULL;
10092                 if (!cinfo->cached)
10093                         mono_custom_attrs_free (cinfo);
10094         } else {
10095                 mono_loader_assert_no_error ();
10096                 result = mono_array_new_cached (mono_domain_get (), mono_defaults.attribute_class, 0);
10097         }
10098
10099         return result;
10100 }
10101
10102 /*
10103  * mono_reflection_get_custom_attrs:
10104  * @obj: a reflection object handle
10105  *
10106  * Return an array with all the custom attributes defined of the
10107  * reflection handle @obj. The objects are fully build. Return NULL if a loading error
10108  * occurs.
10109  */
10110 MonoArray*
10111 mono_reflection_get_custom_attrs (MonoObject *obj)
10112 {
10113         MonoError error;
10114
10115         return mono_reflection_get_custom_attrs_by_type (obj, NULL, &error);
10116 }
10117
10118 /*
10119  * mono_reflection_get_custom_attrs_data:
10120  * @obj: a reflection obj handle
10121  *
10122  * Returns an array of System.Reflection.CustomAttributeData,
10123  * which include information about attributes reflected on
10124  * types loaded using the Reflection Only methods
10125  */
10126 MonoArray*
10127 mono_reflection_get_custom_attrs_data (MonoObject *obj)
10128 {
10129         MonoError error;
10130         MonoArray* result;
10131         result = mono_reflection_get_custom_attrs_data_checked (obj, &error);
10132         mono_error_cleanup (&error); /* FIXME new API that doesn't swallow the error */
10133         return result;
10134 }
10135
10136 /*
10137  * mono_reflection_get_custom_attrs_data_checked:
10138  * @obj: a reflection obj handle
10139  * @error: set on error
10140  *
10141  * Returns an array of System.Reflection.CustomAttributeData,
10142  * which include information about attributes reflected on
10143  * types loaded using the Reflection Only methods
10144  */
10145 MonoArray*
10146 mono_reflection_get_custom_attrs_data_checked (MonoObject *obj, MonoError *error)
10147 {
10148         MonoArray *result;
10149         MonoCustomAttrInfo *cinfo;
10150
10151         mono_error_init (error);
10152
10153         cinfo = mono_reflection_get_custom_attrs_info_checked (obj, error);
10154         return_val_if_nok (error, NULL);
10155         if (cinfo) {
10156                 result = mono_custom_attrs_data_construct (cinfo, error);
10157                 return_val_if_nok (error, NULL);
10158                 if (!cinfo->cached)
10159                         mono_custom_attrs_free (cinfo);
10160         } else
10161                 result = mono_array_new (mono_domain_get (), mono_defaults.customattribute_data_class, 0);
10162
10163         if (mono_loader_get_last_error ())
10164                 mono_error_set_from_loader_error (error);
10165
10166         return result;
10167 }
10168
10169 static MonoReflectionType*
10170 mono_reflection_type_get_underlying_system_type (MonoReflectionType* t, MonoError *error)
10171 {
10172         static MonoMethod *method_get_underlying_system_type = NULL;
10173         MonoReflectionType *rt;
10174         MonoMethod *usertype_method;
10175
10176         mono_error_init (error);
10177
10178         if (!method_get_underlying_system_type)
10179                 method_get_underlying_system_type = mono_class_get_method_from_name (mono_defaults.systemtype_class, "get_UnderlyingSystemType", 0);
10180
10181         usertype_method = mono_object_get_virtual_method ((MonoObject *) t, method_get_underlying_system_type);
10182
10183         rt = (MonoReflectionType *) mono_runtime_invoke_checked (usertype_method, t, NULL, error);
10184
10185         return rt;
10186 }
10187
10188
10189 static gboolean
10190 is_corlib_type (MonoClass *klass)
10191 {
10192         return klass->image == mono_defaults.corlib;
10193 }
10194
10195 #define check_corlib_type_cached(_class, _namespace, _name) do { \
10196         static MonoClass *cached_class; \
10197         if (cached_class) \
10198                 return cached_class == _class; \
10199         if (is_corlib_type (_class) && !strcmp (_name, _class->name) && !strcmp (_namespace, _class->name_space)) { \
10200                 cached_class = _class; \
10201                 return TRUE; \
10202         } \
10203         return FALSE; \
10204 } while (0) \
10205
10206
10207 #ifndef DISABLE_REFLECTION_EMIT
10208 static gboolean
10209 is_sre_array (MonoClass *klass)
10210 {
10211         check_corlib_type_cached (klass, "System.Reflection.Emit", "ArrayType");
10212 }
10213
10214 static gboolean
10215 is_sre_byref (MonoClass *klass)
10216 {
10217         check_corlib_type_cached (klass, "System.Reflection.Emit", "ByRefType");
10218 }
10219
10220 static gboolean
10221 is_sre_pointer (MonoClass *klass)
10222 {
10223         check_corlib_type_cached (klass, "System.Reflection.Emit", "PointerType");
10224 }
10225
10226 static gboolean
10227 is_sre_generic_instance (MonoClass *klass)
10228 {
10229         check_corlib_type_cached (klass, "System.Reflection", "MonoGenericClass");
10230 }
10231
10232 static gboolean
10233 is_sre_type_builder (MonoClass *klass)
10234 {
10235         check_corlib_type_cached (klass, "System.Reflection.Emit", "TypeBuilder");
10236 }
10237
10238 static gboolean
10239 is_sre_method_builder (MonoClass *klass)
10240 {
10241         check_corlib_type_cached (klass, "System.Reflection.Emit", "MethodBuilder");
10242 }
10243
10244 static gboolean
10245 is_sre_ctor_builder (MonoClass *klass)
10246 {
10247         check_corlib_type_cached (klass, "System.Reflection.Emit", "ConstructorBuilder");
10248 }
10249
10250 static gboolean
10251 is_sre_field_builder (MonoClass *klass)
10252 {
10253         check_corlib_type_cached (klass, "System.Reflection.Emit", "FieldBuilder");
10254 }
10255
10256 static gboolean
10257 is_sre_method_on_tb_inst (MonoClass *klass)
10258 {
10259         check_corlib_type_cached (klass, "System.Reflection.Emit", "MethodOnTypeBuilderInst");
10260 }
10261
10262 static gboolean
10263 is_sre_ctor_on_tb_inst (MonoClass *klass)
10264 {
10265         check_corlib_type_cached (klass, "System.Reflection.Emit", "ConstructorOnTypeBuilderInst");
10266 }
10267
10268 MonoType*
10269 mono_reflection_type_get_handle (MonoReflectionType* ref)
10270 {
10271         MonoError error;
10272         MonoClass *klass;
10273         if (!ref)
10274                 return NULL;
10275         if (ref->type)
10276                 return ref->type;
10277
10278         if (is_usertype (ref)) {
10279                 ref = mono_reflection_type_get_underlying_system_type (ref, &error);
10280                 mono_error_raise_exception (&error); /* FIXME don't raise here */
10281                 if (ref == NULL || is_usertype (ref))
10282                         return NULL;
10283                 if (ref->type)
10284                         return ref->type;
10285         }
10286
10287         klass = mono_object_class (ref);
10288
10289         if (is_sre_array (klass)) {
10290                 MonoType *res;
10291                 MonoReflectionArrayType *sre_array = (MonoReflectionArrayType*)ref;
10292                 MonoType *base = mono_reflection_type_get_handle (sre_array->element_type);
10293                 g_assert (base);
10294                 if (sre_array->rank == 0) //single dimentional array
10295                         res = &mono_array_class_get (mono_class_from_mono_type (base), 1)->byval_arg;
10296                 else
10297                         res = &mono_bounded_array_class_get (mono_class_from_mono_type (base), sre_array->rank, TRUE)->byval_arg;
10298                 sre_array->type.type = res;
10299                 return res;
10300         } else if (is_sre_byref (klass)) {
10301                 MonoType *res;
10302                 MonoReflectionDerivedType *sre_byref = (MonoReflectionDerivedType*)ref;
10303                 MonoType *base = mono_reflection_type_get_handle (sre_byref->element_type);
10304                 g_assert (base);
10305                 res = &mono_class_from_mono_type (base)->this_arg;
10306                 sre_byref->type.type = res;
10307                 return res;
10308         } else if (is_sre_pointer (klass)) {
10309                 MonoType *res;
10310                 MonoReflectionDerivedType *sre_pointer = (MonoReflectionDerivedType*)ref;
10311                 MonoType *base = mono_reflection_type_get_handle (sre_pointer->element_type);
10312                 g_assert (base);
10313                 res = &mono_ptr_class_get (base)->byval_arg;
10314                 sre_pointer->type.type = res;
10315                 return res;
10316         } else if (is_sre_generic_instance (klass)) {
10317                 MonoType *res, **types;
10318                 MonoReflectionGenericClass *gclass = (MonoReflectionGenericClass*)ref;
10319                 int i, count;
10320
10321                 count = mono_array_length (gclass->type_arguments);
10322                 types = g_new0 (MonoType*, count);
10323                 for (i = 0; i < count; ++i) {
10324                         MonoReflectionType *t = (MonoReflectionType *)mono_array_get (gclass->type_arguments, gpointer, i);
10325                         types [i] = mono_reflection_type_get_handle (t);
10326                         if (!types[i]) {
10327                                 g_free (types);
10328                                 return NULL;
10329                         }
10330                 }
10331
10332                 res = mono_reflection_bind_generic_parameters (gclass->generic_type, count, types);
10333                 g_free (types);
10334                 g_assert (res);
10335                 gclass->type.type = res;
10336                 return res;
10337         }
10338
10339         g_error ("Cannot handle corlib user type %s", mono_type_full_name (&mono_object_class(ref)->byval_arg));
10340         return NULL;
10341 }
10342
10343
10344
10345 void
10346 mono_reflection_create_unmanaged_type (MonoReflectionType *type)
10347 {
10348         mono_reflection_type_get_handle (type);
10349 }
10350
10351 void
10352 mono_reflection_register_with_runtime (MonoReflectionType *type)
10353 {
10354         MonoType *res = mono_reflection_type_get_handle (type);
10355         MonoDomain *domain = mono_object_domain ((MonoObject*)type);
10356         MonoClass *klass;
10357
10358         if (!res)
10359                 mono_raise_exception (mono_get_exception_argument (NULL, "Invalid generic instantiation, one or more arguments are not proper user types"));
10360
10361         klass = mono_class_from_mono_type (res);
10362
10363         mono_loader_lock (); /*same locking as mono_type_get_object_checked */
10364         mono_domain_lock (domain);
10365
10366         if (!image_is_dynamic (klass->image)) {
10367                 mono_class_setup_supertypes (klass);
10368         } else {
10369                 if (!domain->type_hash)
10370                         domain->type_hash = mono_g_hash_table_new_type ((GHashFunc)mono_metadata_type_hash, 
10371                                         (GCompareFunc)mono_metadata_type_equal, MONO_HASH_VALUE_GC, MONO_ROOT_SOURCE_DOMAIN, "domain reflection types table");
10372                 mono_g_hash_table_insert (domain->type_hash, res, type);
10373         }
10374         mono_domain_unlock (domain);
10375         mono_loader_unlock ();
10376 }
10377
10378 /**
10379  * LOCKING: Assumes the loader lock is held.
10380  */
10381 static MonoMethodSignature*
10382 parameters_to_signature (MonoImage *image, MonoArray *parameters) {
10383         MonoMethodSignature *sig;
10384         int count, i;
10385
10386         count = parameters? mono_array_length (parameters): 0;
10387
10388         sig = (MonoMethodSignature *)image_g_malloc0 (image, MONO_SIZEOF_METHOD_SIGNATURE + sizeof (MonoType*) * count);
10389         sig->param_count = count;
10390         sig->sentinelpos = -1; /* FIXME */
10391         for (i = 0; i < count; ++i)
10392                 sig->params [i] = mono_type_array_get_and_resolve (parameters, i);
10393         return sig;
10394 }
10395
10396 /**
10397  * LOCKING: Assumes the loader lock is held.
10398  */
10399 static MonoMethodSignature*
10400 ctor_builder_to_signature (MonoImage *image, MonoReflectionCtorBuilder *ctor) {
10401         MonoMethodSignature *sig;
10402
10403         sig = parameters_to_signature (image, ctor->parameters);
10404         sig->hasthis = ctor->attrs & METHOD_ATTRIBUTE_STATIC? 0: 1;
10405         sig->ret = &mono_defaults.void_class->byval_arg;
10406         return sig;
10407 }
10408
10409 /**
10410  * LOCKING: Assumes the loader lock is held.
10411  */
10412 static MonoMethodSignature*
10413 method_builder_to_signature (MonoImage *image, MonoReflectionMethodBuilder *method) {
10414         MonoMethodSignature *sig;
10415
10416         sig = parameters_to_signature (image, method->parameters);
10417         sig->hasthis = method->attrs & METHOD_ATTRIBUTE_STATIC? 0: 1;
10418         sig->ret = method->rtype? mono_reflection_type_get_handle ((MonoReflectionType*)method->rtype): &mono_defaults.void_class->byval_arg;
10419         sig->generic_param_count = method->generic_params ? mono_array_length (method->generic_params) : 0;
10420         return sig;
10421 }
10422
10423 static MonoMethodSignature*
10424 dynamic_method_to_signature (MonoReflectionDynamicMethod *method) {
10425         MonoMethodSignature *sig;
10426
10427         sig = parameters_to_signature (NULL, method->parameters);
10428         sig->hasthis = method->attrs & METHOD_ATTRIBUTE_STATIC? 0: 1;
10429         sig->ret = method->rtype? mono_reflection_type_get_handle (method->rtype): &mono_defaults.void_class->byval_arg;
10430         sig->generic_param_count = 0;
10431         return sig;
10432 }
10433
10434 static void
10435 get_prop_name_and_type (MonoObject *prop, char **name, MonoType **type)
10436 {
10437         MonoClass *klass = mono_object_class (prop);
10438         if (strcmp (klass->name, "PropertyBuilder") == 0) {
10439                 MonoReflectionPropertyBuilder *pb = (MonoReflectionPropertyBuilder *)prop;
10440                 *name = mono_string_to_utf8 (pb->name);
10441                 *type = mono_reflection_type_get_handle ((MonoReflectionType*)pb->type);
10442         } else {
10443                 MonoReflectionProperty *p = (MonoReflectionProperty *)prop;
10444                 *name = g_strdup (p->property->name);
10445                 if (p->property->get)
10446                         *type = mono_method_signature (p->property->get)->ret;
10447                 else
10448                         *type = mono_method_signature (p->property->set)->params [mono_method_signature (p->property->set)->param_count - 1];
10449         }
10450 }
10451
10452 static void
10453 get_field_name_and_type (MonoObject *field, char **name, MonoType **type)
10454 {
10455         MonoClass *klass = mono_object_class (field);
10456         if (strcmp (klass->name, "FieldBuilder") == 0) {
10457                 MonoReflectionFieldBuilder *fb = (MonoReflectionFieldBuilder *)field;
10458                 *name = mono_string_to_utf8 (fb->name);
10459                 *type = mono_reflection_type_get_handle ((MonoReflectionType*)fb->type);
10460         } else {
10461                 MonoReflectionField *f = (MonoReflectionField *)field;
10462                 *name = g_strdup (mono_field_get_name (f->field));
10463                 *type = f->field->type;
10464         }
10465 }
10466
10467 #else /* DISABLE_REFLECTION_EMIT */
10468
10469 void
10470 mono_reflection_register_with_runtime (MonoReflectionType *type)
10471 {
10472         /* This is empty */
10473 }
10474
10475 static gboolean
10476 is_sre_type_builder (MonoClass *klass)
10477 {
10478         return FALSE;
10479 }
10480
10481 static gboolean
10482 is_sre_generic_instance (MonoClass *klass)
10483 {
10484         return FALSE;
10485 }
10486
10487 static void
10488 init_type_builder_generics (MonoObject *type)
10489 {
10490 }
10491
10492 #endif /* !DISABLE_REFLECTION_EMIT */
10493
10494
10495 static gboolean
10496 is_sr_mono_field (MonoClass *klass)
10497 {
10498         check_corlib_type_cached (klass, "System.Reflection", "MonoField");
10499 }
10500
10501 static gboolean
10502 is_sr_mono_property (MonoClass *klass)
10503 {
10504         check_corlib_type_cached (klass, "System.Reflection", "MonoProperty");
10505 }
10506
10507 static gboolean
10508 is_sr_mono_method (MonoClass *klass)
10509 {
10510         check_corlib_type_cached (klass, "System.Reflection", "MonoMethod");
10511 }
10512
10513 static gboolean
10514 is_sr_mono_cmethod (MonoClass *klass)
10515 {
10516         check_corlib_type_cached (klass, "System.Reflection", "MonoCMethod");
10517 }
10518
10519 static gboolean
10520 is_sr_mono_generic_method (MonoClass *klass)
10521 {
10522         check_corlib_type_cached (klass, "System.Reflection", "MonoGenericMethod");
10523 }
10524
10525 static gboolean
10526 is_sr_mono_generic_cmethod (MonoClass *klass)
10527 {
10528         check_corlib_type_cached (klass, "System.Reflection", "MonoGenericCMethod");
10529 }
10530
10531 gboolean
10532 mono_class_is_reflection_method_or_constructor (MonoClass *klass)
10533 {
10534         return is_sr_mono_method (klass) || is_sr_mono_cmethod (klass) || is_sr_mono_generic_method (klass) || is_sr_mono_generic_cmethod (klass);
10535 }
10536
10537 static gboolean
10538 is_usertype (MonoReflectionType *ref)
10539 {
10540         MonoClass *klass = mono_object_class (ref);
10541         return klass->image != mono_defaults.corlib || strcmp ("TypeDelegator", klass->name) == 0;
10542 }
10543
10544 static MonoReflectionType*
10545 mono_reflection_type_resolve_user_types (MonoReflectionType *type, MonoError *error)
10546 {
10547         mono_error_init (error);
10548         if (!type || type->type)
10549                 return type;
10550
10551         if (is_usertype (type)) {
10552                 type = mono_reflection_type_get_underlying_system_type (type, error);
10553                 return_val_if_nok (error, NULL);
10554                 if (is_usertype (type)) {
10555                         mono_error_set_generic_error (error, "System", "NotSupportedException", "User defined subclasses of System.Type are not yet supported22");
10556                         return NULL;
10557                 }
10558         }
10559
10560         return type;
10561 }
10562 /*
10563  * Encode a value in a custom attribute stream of bytes.
10564  * The value to encode is either supplied as an object in argument val
10565  * (valuetypes are boxed), or as a pointer to the data in the
10566  * argument argval.
10567  * @type represents the type of the value
10568  * @buffer is the start of the buffer
10569  * @p the current position in the buffer
10570  * @buflen contains the size of the buffer and is used to return the new buffer size
10571  * if this needs to be realloced.
10572  * @retbuffer and @retp return the start and the position of the buffer
10573  */
10574 static void
10575 encode_cattr_value (MonoAssembly *assembly, char *buffer, char *p, char **retbuffer, char **retp, guint32 *buflen, MonoType *type, MonoObject *arg, char *argval)
10576 {
10577         MonoTypeEnum simple_type;
10578         
10579         if ((p-buffer) + 10 >= *buflen) {
10580                 char *newbuf;
10581                 *buflen *= 2;
10582                 newbuf = (char *)g_realloc (buffer, *buflen);
10583                 p = newbuf + (p-buffer);
10584                 buffer = newbuf;
10585         }
10586         if (!argval)
10587                 argval = ((char*)arg + sizeof (MonoObject));
10588         simple_type = type->type;
10589 handle_enum:
10590         switch (simple_type) {
10591         case MONO_TYPE_BOOLEAN:
10592         case MONO_TYPE_U1:
10593         case MONO_TYPE_I1:
10594                 *p++ = *argval;
10595                 break;
10596         case MONO_TYPE_CHAR:
10597         case MONO_TYPE_U2:
10598         case MONO_TYPE_I2:
10599                 swap_with_size (p, argval, 2, 1);
10600                 p += 2;
10601                 break;
10602         case MONO_TYPE_U4:
10603         case MONO_TYPE_I4:
10604         case MONO_TYPE_R4:
10605                 swap_with_size (p, argval, 4, 1);
10606                 p += 4;
10607                 break;
10608         case MONO_TYPE_R8:
10609                 swap_with_size (p, argval, 8, 1);
10610                 p += 8;
10611                 break;
10612         case MONO_TYPE_U8:
10613         case MONO_TYPE_I8:
10614                 swap_with_size (p, argval, 8, 1);
10615                 p += 8;
10616                 break;
10617         case MONO_TYPE_VALUETYPE:
10618                 if (type->data.klass->enumtype) {
10619                         simple_type = mono_class_enum_basetype (type->data.klass)->type;
10620                         goto handle_enum;
10621                 } else {
10622                         g_warning ("generic valutype %s not handled in custom attr value decoding", type->data.klass->name);
10623                 }
10624                 break;
10625         case MONO_TYPE_STRING: {
10626                 char *str;
10627                 guint32 slen;
10628                 if (!arg) {
10629                         *p++ = 0xFF;
10630                         break;
10631                 }
10632                 str = mono_string_to_utf8 ((MonoString*)arg);
10633                 slen = strlen (str);
10634                 if ((p-buffer) + 10 + slen >= *buflen) {
10635                         char *newbuf;
10636                         *buflen *= 2;
10637                         *buflen += slen;
10638                         newbuf = (char *)g_realloc (buffer, *buflen);
10639                         p = newbuf + (p-buffer);
10640                         buffer = newbuf;
10641                 }
10642                 mono_metadata_encode_value (slen, p, &p);
10643                 memcpy (p, str, slen);
10644                 p += slen;
10645                 g_free (str);
10646                 break;
10647         }
10648         case MONO_TYPE_CLASS: {
10649                 char *str;
10650                 guint32 slen;
10651                 if (!arg) {
10652                         *p++ = 0xFF;
10653                         break;
10654                 }
10655 handle_type:
10656                 str = type_get_qualified_name (mono_reflection_type_get_handle ((MonoReflectionType*)arg), NULL);
10657                 slen = strlen (str);
10658                 if ((p-buffer) + 10 + slen >= *buflen) {
10659                         char *newbuf;
10660                         *buflen *= 2;
10661                         *buflen += slen;
10662                         newbuf = (char *)g_realloc (buffer, *buflen);
10663                         p = newbuf + (p-buffer);
10664                         buffer = newbuf;
10665                 }
10666                 mono_metadata_encode_value (slen, p, &p);
10667                 memcpy (p, str, slen);
10668                 p += slen;
10669                 g_free (str);
10670                 break;
10671         }
10672         case MONO_TYPE_SZARRAY: {
10673                 int len, i;
10674                 MonoClass *eclass, *arg_eclass;
10675
10676                 if (!arg) {
10677                         *p++ = 0xff; *p++ = 0xff; *p++ = 0xff; *p++ = 0xff;
10678                         break;
10679                 }
10680                 len = mono_array_length ((MonoArray*)arg);
10681                 *p++ = len & 0xff;
10682                 *p++ = (len >> 8) & 0xff;
10683                 *p++ = (len >> 16) & 0xff;
10684                 *p++ = (len >> 24) & 0xff;
10685                 *retp = p;
10686                 *retbuffer = buffer;
10687                 eclass = type->data.klass;
10688                 arg_eclass = mono_object_class (arg)->element_class;
10689
10690                 if (!eclass) {
10691                         /* Happens when we are called from the MONO_TYPE_OBJECT case below */
10692                         eclass = mono_defaults.object_class;
10693                 }
10694                 if (eclass == mono_defaults.object_class && arg_eclass->valuetype) {
10695                         char *elptr = mono_array_addr ((MonoArray*)arg, char, 0);
10696                         int elsize = mono_class_array_element_size (arg_eclass);
10697                         for (i = 0; i < len; ++i) {
10698                                 encode_cattr_value (assembly, buffer, p, &buffer, &p, buflen, &arg_eclass->byval_arg, NULL, elptr);
10699                                 elptr += elsize;
10700                         }
10701                 } else if (eclass->valuetype && arg_eclass->valuetype) {
10702                         char *elptr = mono_array_addr ((MonoArray*)arg, char, 0);
10703                         int elsize = mono_class_array_element_size (eclass);
10704                         for (i = 0; i < len; ++i) {
10705                                 encode_cattr_value (assembly, buffer, p, &buffer, &p, buflen, &eclass->byval_arg, NULL, elptr);
10706                                 elptr += elsize;
10707                         }
10708                 } else {
10709                         for (i = 0; i < len; ++i) {
10710                                 encode_cattr_value (assembly, buffer, p, &buffer, &p, buflen, &eclass->byval_arg, mono_array_get ((MonoArray*)arg, MonoObject*, i), NULL);
10711                         }
10712                 }
10713                 break;
10714         }
10715         case MONO_TYPE_OBJECT: {
10716                 MonoClass *klass;
10717                 char *str;
10718                 guint32 slen;
10719
10720                 /*
10721                  * The parameter type is 'object' but the type of the actual
10722                  * argument is not. So we have to add type information to the blob
10723                  * too. This is completely undocumented in the spec.
10724                  */
10725
10726                 if (arg == NULL) {
10727                         *p++ = MONO_TYPE_STRING;        // It's same hack as MS uses
10728                         *p++ = 0xFF;
10729                         break;
10730                 }
10731                 
10732                 klass = mono_object_class (arg);
10733
10734                 if (mono_object_isinst (arg, mono_defaults.systemtype_class)) {
10735                         *p++ = 0x50;
10736                         goto handle_type;
10737                 } else if (klass->enumtype) {
10738                         *p++ = 0x55;
10739                 } else if (klass == mono_defaults.string_class) {
10740                         simple_type = MONO_TYPE_STRING;
10741                         *p++ = 0x0E;
10742                         goto handle_enum;
10743                 } else if (klass->rank == 1) {
10744                         *p++ = 0x1D;
10745                         if (klass->element_class->byval_arg.type == MONO_TYPE_OBJECT)
10746                                 /* See Partition II, Appendix B3 */
10747                                 *p++ = 0x51;
10748                         else
10749                                 *p++ = klass->element_class->byval_arg.type;
10750                         encode_cattr_value (assembly, buffer, p, &buffer, &p, buflen, &klass->byval_arg, arg, NULL);
10751                         break;
10752                 } else if (klass->byval_arg.type >= MONO_TYPE_BOOLEAN && klass->byval_arg.type <= MONO_TYPE_R8) {
10753                         *p++ = simple_type = klass->byval_arg.type;
10754                         goto handle_enum;
10755                 } else {
10756                         g_error ("unhandled type in custom attr");
10757                 }
10758                 str = type_get_qualified_name (mono_class_get_type(klass), NULL);
10759                 slen = strlen (str);
10760                 if ((p-buffer) + 10 + slen >= *buflen) {
10761                         char *newbuf;
10762                         *buflen *= 2;
10763                         *buflen += slen;
10764                         newbuf = (char *)g_realloc (buffer, *buflen);
10765                         p = newbuf + (p-buffer);
10766                         buffer = newbuf;
10767                 }
10768                 mono_metadata_encode_value (slen, p, &p);
10769                 memcpy (p, str, slen);
10770                 p += slen;
10771                 g_free (str);
10772                 simple_type = mono_class_enum_basetype (klass)->type;
10773                 goto handle_enum;
10774         }
10775         default:
10776                 g_error ("type 0x%02x not yet supported in custom attr encoder", simple_type);
10777         }
10778         *retp = p;
10779         *retbuffer = buffer;
10780 }
10781
10782 static void
10783 encode_field_or_prop_type (MonoType *type, char *p, char **retp)
10784 {
10785         if (type->type == MONO_TYPE_VALUETYPE && type->data.klass->enumtype) {
10786                 char *str = type_get_qualified_name (type, NULL);
10787                 int slen = strlen (str);
10788
10789                 *p++ = 0x55;
10790                 /*
10791                  * This seems to be optional...
10792                  * *p++ = 0x80;
10793                  */
10794                 mono_metadata_encode_value (slen, p, &p);
10795                 memcpy (p, str, slen);
10796                 p += slen;
10797                 g_free (str);
10798         } else if (type->type == MONO_TYPE_OBJECT) {
10799                 *p++ = 0x51;
10800         } else if (type->type == MONO_TYPE_CLASS) {
10801                 /* it should be a type: encode_cattr_value () has the check */
10802                 *p++ = 0x50;
10803         } else {
10804                 mono_metadata_encode_value (type->type, p, &p);
10805                 if (type->type == MONO_TYPE_SZARRAY)
10806                         /* See the examples in Partition VI, Annex B */
10807                         encode_field_or_prop_type (&type->data.klass->byval_arg, p, &p);
10808         }
10809
10810         *retp = p;
10811 }
10812
10813 #ifndef DISABLE_REFLECTION_EMIT
10814 static void
10815 encode_named_val (MonoReflectionAssembly *assembly, char *buffer, char *p, char **retbuffer, char **retp, guint32 *buflen, MonoType *type, char *name, MonoObject *value)
10816 {
10817         int len;
10818         /* Preallocate a large enough buffer */
10819         if (type->type == MONO_TYPE_VALUETYPE && type->data.klass->enumtype) {
10820                 char *str = type_get_qualified_name (type, NULL);
10821                 len = strlen (str);
10822                 g_free (str);
10823         } else if (type->type == MONO_TYPE_SZARRAY && type->data.klass->enumtype) {
10824                 char *str = type_get_qualified_name (&type->data.klass->byval_arg, NULL);
10825                 len = strlen (str);
10826                 g_free (str);
10827         } else {
10828                 len = 0;
10829         }
10830         len += strlen (name);
10831
10832         if ((p-buffer) + 20 + len >= *buflen) {
10833                 char *newbuf;
10834                 *buflen *= 2;
10835                 *buflen += len;
10836                 newbuf = (char *)g_realloc (buffer, *buflen);
10837                 p = newbuf + (p-buffer);
10838                 buffer = newbuf;
10839         }
10840
10841         encode_field_or_prop_type (type, p, &p);
10842
10843         len = strlen (name);
10844         mono_metadata_encode_value (len, p, &p);
10845         memcpy (p, name, len);
10846         p += len;
10847         encode_cattr_value (assembly->assembly, buffer, p, &buffer, &p, buflen, type, value, NULL);
10848         *retp = p;
10849         *retbuffer = buffer;
10850 }
10851
10852 /*
10853  * mono_reflection_get_custom_attrs_blob:
10854  * @ctor: custom attribute constructor
10855  * @ctorArgs: arguments o the constructor
10856  * @properties:
10857  * @propValues:
10858  * @fields:
10859  * @fieldValues:
10860  * 
10861  * Creates the blob of data that needs to be saved in the metadata and that represents
10862  * the custom attributed described by @ctor, @ctorArgs etc.
10863  * Returns: a Byte array representing the blob of data.
10864  */
10865 MonoArray*
10866 mono_reflection_get_custom_attrs_blob (MonoReflectionAssembly *assembly, MonoObject *ctor, MonoArray *ctorArgs, MonoArray *properties, MonoArray *propValues, MonoArray *fields, MonoArray* fieldValues) 
10867 {
10868         MonoArray *result;
10869         MonoMethodSignature *sig;
10870         MonoObject *arg;
10871         char *buffer, *p;
10872         guint32 buflen, i;
10873
10874         if (strcmp (ctor->vtable->klass->name, "MonoCMethod")) {
10875                 /* sig is freed later so allocate it in the heap */
10876                 sig = ctor_builder_to_signature (NULL, (MonoReflectionCtorBuilder*)ctor);
10877         } else {
10878                 sig = mono_method_signature (((MonoReflectionMethod*)ctor)->method);
10879         }
10880
10881         g_assert (mono_array_length (ctorArgs) == sig->param_count);
10882         buflen = 256;
10883         p = buffer = (char *)g_malloc (buflen);
10884         /* write the prolog */
10885         *p++ = 1;
10886         *p++ = 0;
10887         for (i = 0; i < sig->param_count; ++i) {
10888                 arg = mono_array_get (ctorArgs, MonoObject*, i);
10889                 encode_cattr_value (assembly->assembly, buffer, p, &buffer, &p, &buflen, sig->params [i], arg, NULL);
10890         }
10891         i = 0;
10892         if (properties)
10893                 i += mono_array_length (properties);
10894         if (fields)
10895                 i += mono_array_length (fields);
10896         *p++ = i & 0xff;
10897         *p++ = (i >> 8) & 0xff;
10898         if (properties) {
10899                 MonoObject *prop;
10900                 for (i = 0; i < mono_array_length (properties); ++i) {
10901                         MonoType *ptype;
10902                         char *pname;
10903
10904                         prop = (MonoObject *)mono_array_get (properties, gpointer, i);
10905                         get_prop_name_and_type (prop, &pname, &ptype);
10906                         *p++ = 0x54; /* PROPERTY signature */
10907                         encode_named_val (assembly, buffer, p, &buffer, &p, &buflen, ptype, pname, (MonoObject*)mono_array_get (propValues, gpointer, i));
10908                         g_free (pname);
10909                 }
10910         }
10911
10912         if (fields) {
10913                 MonoObject *field;
10914                 for (i = 0; i < mono_array_length (fields); ++i) {
10915                         MonoType *ftype;
10916                         char *fname;
10917
10918                         field = (MonoObject *)mono_array_get (fields, gpointer, i);
10919                         get_field_name_and_type (field, &fname, &ftype);
10920                         *p++ = 0x53; /* FIELD signature */
10921                         encode_named_val (assembly, buffer, p, &buffer, &p, &buflen, ftype, fname, (MonoObject*)mono_array_get (fieldValues, gpointer, i));
10922                         g_free (fname);
10923                 }
10924         }
10925
10926         g_assert (p - buffer <= buflen);
10927         buflen = p - buffer;
10928         result = mono_array_new (mono_domain_get (), mono_defaults.byte_class, buflen);
10929         p = mono_array_addr (result, char, 0);
10930         memcpy (p, buffer, buflen);
10931         g_free (buffer);
10932         if (strcmp (ctor->vtable->klass->name, "MonoCMethod"))
10933                 g_free (sig);
10934         return result;
10935 }
10936
10937 /*
10938  * mono_reflection_setup_internal_class:
10939  * @tb: a TypeBuilder object
10940  *
10941  * Creates a MonoClass that represents the TypeBuilder.
10942  * This is a trick that lets us simplify a lot of reflection code
10943  * (and will allow us to support Build and Run assemblies easier).
10944  */
10945 void
10946 mono_reflection_setup_internal_class (MonoReflectionTypeBuilder *tb)
10947 {
10948         MonoError error;
10949         MonoClass *klass, *parent;
10950
10951         RESOLVE_TYPE (tb->parent, &error);
10952         mono_error_raise_exception (&error); /* FIXME don't raise here */
10953
10954         mono_loader_lock ();
10955
10956         if (tb->parent) {
10957                 /* check so we can compile corlib correctly */
10958                 if (strcmp (mono_object_class (tb->parent)->name, "TypeBuilder") == 0) {
10959                         /* mono_class_setup_mono_type () guaranteess type->data.klass is valid */
10960                         parent = mono_reflection_type_get_handle ((MonoReflectionType*)tb->parent)->data.klass;
10961                 } else {
10962                         parent = mono_class_from_mono_type (mono_reflection_type_get_handle ((MonoReflectionType*)tb->parent));
10963                 }
10964         } else {
10965                 parent = NULL;
10966         }
10967         
10968         /* the type has already being created: it means we just have to change the parent */
10969         if (tb->type.type) {
10970                 klass = mono_class_from_mono_type (tb->type.type);
10971                 klass->parent = NULL;
10972                 /* fool mono_class_setup_parent */
10973                 klass->supertypes = NULL;
10974                 mono_class_setup_parent (klass, parent);
10975                 mono_class_setup_mono_type (klass);
10976                 mono_loader_unlock ();
10977                 return;
10978         }
10979
10980         klass = (MonoClass *)mono_image_alloc0 (&tb->module->dynamic_image->image, sizeof (MonoClass));
10981
10982         klass->image = &tb->module->dynamic_image->image;
10983
10984         klass->inited = 1; /* we lie to the runtime */
10985         klass->name = mono_string_to_utf8_image (klass->image, tb->name, &error);
10986         if (!mono_error_ok (&error))
10987                 goto failure;
10988         klass->name_space = mono_string_to_utf8_image (klass->image, tb->nspace, &error);
10989         if (!mono_error_ok (&error))
10990                 goto failure;
10991         klass->type_token = MONO_TOKEN_TYPE_DEF | tb->table_idx;
10992         klass->flags = tb->attrs;
10993         
10994         mono_profiler_class_event (klass, MONO_PROFILE_START_LOAD);
10995
10996         klass->element_class = klass;
10997
10998         if (mono_class_get_ref_info (klass) == NULL) {
10999
11000                 mono_class_set_ref_info (klass, tb);
11001
11002                 /* Put into cache so mono_class_get_checked () will find it.
11003                 Skip nested types as those should not be available on the global scope. */
11004                 if (!tb->nesting_type)
11005                         mono_image_add_to_name_cache (klass->image, klass->name_space, klass->name, tb->table_idx);
11006
11007                 /*
11008                 We must register all types as we cannot rely on the name_cache hashtable since we find the class
11009                 by performing a mono_class_get which does the full resolution.
11010
11011                 Working around this semantics would require us to write a lot of code for no clear advantage.
11012                 */
11013                 mono_image_append_class_to_reflection_info_set (klass);
11014         } else {
11015                 g_assert (mono_class_get_ref_info (klass) == tb);
11016         }
11017
11018         register_dyn_token (tb->module->dynamic_image, MONO_TOKEN_TYPE_DEF | tb->table_idx, (MonoObject*)tb);
11019
11020         if (parent != NULL) {
11021                 mono_class_setup_parent (klass, parent);
11022         } else if (strcmp (klass->name, "Object") == 0 && strcmp (klass->name_space, "System") == 0) {
11023                 const char *old_n = klass->name;
11024                 /* trick to get relative numbering right when compiling corlib */
11025                 klass->name = "BuildingObject";
11026                 mono_class_setup_parent (klass, mono_defaults.object_class);
11027                 klass->name = old_n;
11028         }
11029
11030         if ((!strcmp (klass->name, "ValueType") && !strcmp (klass->name_space, "System")) ||
11031                         (!strcmp (klass->name, "Object") && !strcmp (klass->name_space, "System")) ||
11032                         (!strcmp (klass->name, "Enum") && !strcmp (klass->name_space, "System"))) {
11033                 klass->instance_size = sizeof (MonoObject);
11034                 klass->size_inited = 1;
11035                 mono_class_setup_vtable_general (klass, NULL, 0, NULL);
11036         }
11037
11038         mono_class_setup_mono_type (klass);
11039
11040         mono_class_setup_supertypes (klass);
11041
11042         /*
11043          * FIXME: handle interfaces.
11044          */
11045
11046         tb->type.type = &klass->byval_arg;
11047
11048         if (tb->nesting_type) {
11049                 g_assert (tb->nesting_type->type);
11050                 klass->nested_in = mono_class_from_mono_type (mono_reflection_type_get_handle (tb->nesting_type));
11051         }
11052
11053         /*g_print ("setup %s as %s (%p)\n", klass->name, ((MonoObject*)tb)->vtable->klass->name, tb);*/
11054
11055         mono_profiler_class_loaded (klass, MONO_PROFILE_OK);
11056         
11057         mono_loader_unlock ();
11058         return;
11059
11060 failure:
11061         mono_loader_unlock ();
11062         mono_error_raise_exception (&error);
11063 }
11064
11065 /*
11066  * mono_reflection_setup_generic_class:
11067  * @tb: a TypeBuilder object
11068  *
11069  * Setup the generic class before adding the first generic parameter.
11070  */
11071 void
11072 mono_reflection_setup_generic_class (MonoReflectionTypeBuilder *tb)
11073 {
11074 }
11075
11076 /*
11077  * mono_reflection_create_generic_class:
11078  * @tb: a TypeBuilder object
11079  *
11080  * Creates the generic class after all generic parameters have been added.
11081  */
11082 void
11083 mono_reflection_create_generic_class (MonoReflectionTypeBuilder *tb)
11084 {
11085         MonoClass *klass;
11086         int count, i;
11087
11088         klass = mono_class_from_mono_type (tb->type.type);
11089
11090         count = tb->generic_params ? mono_array_length (tb->generic_params) : 0;
11091
11092         if (klass->generic_container || (count == 0))
11093                 return;
11094
11095         g_assert (tb->generic_container && (tb->generic_container->owner.klass == klass));
11096
11097         klass->generic_container = (MonoGenericContainer *)mono_image_alloc0 (klass->image, sizeof (MonoGenericContainer));
11098
11099         klass->generic_container->owner.klass = klass;
11100         klass->generic_container->type_argc = count;
11101         klass->generic_container->type_params = (MonoGenericParamFull *)mono_image_alloc0 (klass->image, sizeof (MonoGenericParamFull) * count);
11102
11103         klass->is_generic = 1;
11104
11105         for (i = 0; i < count; i++) {
11106                 MonoReflectionGenericParam *gparam = (MonoReflectionGenericParam *)mono_array_get (tb->generic_params, gpointer, i);
11107                 MonoGenericParamFull *param = (MonoGenericParamFull *) mono_reflection_type_get_handle ((MonoReflectionType*)gparam)->data.generic_param;
11108                 klass->generic_container->type_params [i] = *param;
11109                 /*Make sure we are a diferent type instance */
11110                 klass->generic_container->type_params [i].param.owner = klass->generic_container;
11111                 klass->generic_container->type_params [i].info.pklass = NULL;
11112                 klass->generic_container->type_params [i].info.flags = gparam->attrs;
11113
11114                 g_assert (klass->generic_container->type_params [i].param.owner);
11115         }
11116
11117         klass->generic_container->context.class_inst = mono_get_shared_generic_inst (klass->generic_container);
11118 }
11119
11120 /*
11121  * mono_reflection_create_internal_class:
11122  * @tb: a TypeBuilder object
11123  *
11124  * Actually create the MonoClass that is associated with the TypeBuilder.
11125  */
11126 void
11127 mono_reflection_create_internal_class (MonoReflectionTypeBuilder *tb)
11128 {
11129         MonoClass *klass;
11130
11131         klass = mono_class_from_mono_type (tb->type.type);
11132
11133         mono_loader_lock ();
11134         if (klass->enumtype && mono_class_enum_basetype (klass) == NULL) {
11135                 MonoReflectionFieldBuilder *fb;
11136                 MonoClass *ec;
11137                 MonoType *enum_basetype;
11138
11139                 g_assert (tb->fields != NULL);
11140                 g_assert (mono_array_length (tb->fields) >= 1);
11141
11142                 fb = mono_array_get (tb->fields, MonoReflectionFieldBuilder*, 0);
11143
11144                 if (!mono_type_is_valid_enum_basetype (mono_reflection_type_get_handle ((MonoReflectionType*)fb->type))) {
11145                         mono_loader_unlock ();
11146                         return;
11147                 }
11148
11149                 enum_basetype = mono_reflection_type_get_handle ((MonoReflectionType*)fb->type);
11150                 klass->element_class = mono_class_from_mono_type (enum_basetype);
11151                 if (!klass->element_class)
11152                         klass->element_class = mono_class_from_mono_type (enum_basetype);
11153
11154                 /*
11155                  * get the element_class from the current corlib.
11156                  */
11157                 ec = default_class_from_mono_type (enum_basetype);
11158                 klass->instance_size = ec->instance_size;
11159                 klass->size_inited = 1;
11160                 /* 
11161                  * this is almost safe to do with enums and it's needed to be able
11162                  * to create objects of the enum type (for use in SetConstant).
11163                  */
11164                 /* FIXME: Does this mean enums can't have method overrides ? */
11165                 mono_class_setup_vtable_general (klass, NULL, 0, NULL);
11166         }
11167         mono_loader_unlock ();
11168 }
11169
11170 static MonoMarshalSpec*
11171 mono_marshal_spec_from_builder (MonoImage *image, MonoAssembly *assembly,
11172                                                                 MonoReflectionMarshal *minfo)
11173 {
11174         MonoMarshalSpec *res;
11175
11176         res = image_g_new0 (image, MonoMarshalSpec, 1);
11177         res->native = (MonoMarshalNative)minfo->type;
11178
11179         switch (minfo->type) {
11180         case MONO_NATIVE_LPARRAY:
11181                 res->data.array_data.elem_type = (MonoMarshalNative)minfo->eltype;
11182                 if (minfo->has_size) {
11183                         res->data.array_data.param_num = minfo->param_num;
11184                         res->data.array_data.num_elem = minfo->count;
11185                         res->data.array_data.elem_mult = minfo->param_num == -1 ? 0 : 1;
11186                 }
11187                 else {
11188                         res->data.array_data.param_num = -1;
11189                         res->data.array_data.num_elem = -1;
11190                         res->data.array_data.elem_mult = -1;
11191                 }
11192                 break;
11193
11194         case MONO_NATIVE_BYVALTSTR:
11195         case MONO_NATIVE_BYVALARRAY:
11196                 res->data.array_data.num_elem = minfo->count;
11197                 break;
11198
11199         case MONO_NATIVE_CUSTOM:
11200                 if (minfo->marshaltyperef)
11201                         res->data.custom_data.custom_name =
11202                                 type_get_fully_qualified_name (mono_reflection_type_get_handle ((MonoReflectionType*)minfo->marshaltyperef));
11203                 if (minfo->mcookie)
11204                         res->data.custom_data.cookie = mono_string_to_utf8 (minfo->mcookie);
11205                 break;
11206
11207         default:
11208                 break;
11209         }
11210
11211         return res;
11212 }
11213 #endif /* !DISABLE_REFLECTION_EMIT */
11214
11215 MonoReflectionMarshalAsAttribute*
11216 mono_reflection_marshal_as_attribute_from_marshal_spec (MonoDomain *domain, MonoClass *klass,
11217                                                         MonoMarshalSpec *spec, MonoError *error)
11218 {
11219         MonoReflectionType *rt;
11220         MonoReflectionMarshalAsAttribute *minfo;
11221         MonoType *mtype;
11222
11223         mono_error_init (error);
11224         
11225         minfo = (MonoReflectionMarshalAsAttribute*)mono_object_new_checked (domain, mono_class_get_marshal_as_attribute_class (), error);
11226         if (!minfo)
11227                 return NULL;
11228         minfo->utype = spec->native;
11229
11230         switch (minfo->utype) {
11231         case MONO_NATIVE_LPARRAY:
11232                 minfo->array_subtype = spec->data.array_data.elem_type;
11233                 minfo->size_const = spec->data.array_data.num_elem;
11234                 if (spec->data.array_data.param_num != -1)
11235                         minfo->size_param_index = spec->data.array_data.param_num;
11236                 break;
11237
11238         case MONO_NATIVE_BYVALTSTR:
11239         case MONO_NATIVE_BYVALARRAY:
11240                 minfo->size_const = spec->data.array_data.num_elem;
11241                 break;
11242
11243         case MONO_NATIVE_CUSTOM:
11244                 if (spec->data.custom_data.custom_name) {
11245                         mtype = mono_reflection_type_from_name (spec->data.custom_data.custom_name, klass->image);
11246                         if (mtype) {
11247                                 rt = mono_type_get_object_checked (domain, mtype, error);
11248                                 if (!rt)
11249                                         return NULL;
11250
11251                                 MONO_OBJECT_SETREF (minfo, marshal_type_ref, rt);
11252                         }
11253
11254                         MONO_OBJECT_SETREF (minfo, marshal_type, mono_string_new (domain, spec->data.custom_data.custom_name));
11255                 }
11256                 if (spec->data.custom_data.cookie)
11257                         MONO_OBJECT_SETREF (minfo, marshal_cookie, mono_string_new (domain, spec->data.custom_data.cookie));
11258                 break;
11259
11260         default:
11261                 break;
11262         }
11263
11264         return minfo;
11265 }
11266
11267 #ifndef DISABLE_REFLECTION_EMIT
11268 static MonoMethod*
11269 reflection_methodbuilder_to_mono_method (MonoClass *klass,
11270                                          ReflectionMethodBuilder *rmb,
11271                                          MonoMethodSignature *sig)
11272 {
11273         MonoError error;
11274         MonoMethod *m;
11275         MonoMethodWrapper *wrapperm;
11276         MonoMarshalSpec **specs;
11277         MonoReflectionMethodAux *method_aux;
11278         MonoImage *image;
11279         gboolean dynamic;
11280         int i;
11281
11282         mono_error_init (&error);
11283         /*
11284          * Methods created using a MethodBuilder should have their memory allocated
11285          * inside the image mempool, while dynamic methods should have their memory
11286          * malloc'd.
11287          */
11288         dynamic = rmb->refs != NULL;
11289         image = dynamic ? NULL : klass->image;
11290
11291         if (!dynamic)
11292                 g_assert (!klass->generic_class);
11293
11294         mono_loader_lock ();
11295
11296         if ((rmb->attrs & METHOD_ATTRIBUTE_PINVOKE_IMPL) ||
11297                         (rmb->iattrs & METHOD_IMPL_ATTRIBUTE_INTERNAL_CALL))
11298                 m = (MonoMethod *)image_g_new0 (image, MonoMethodPInvoke, 1);
11299         else
11300                 m = (MonoMethod *)image_g_new0 (image, MonoMethodWrapper, 1);
11301
11302         wrapperm = (MonoMethodWrapper*)m;
11303
11304         m->dynamic = dynamic;
11305         m->slot = -1;
11306         m->flags = rmb->attrs;
11307         m->iflags = rmb->iattrs;
11308         m->name = mono_string_to_utf8_image_ignore (image, rmb->name);
11309         m->klass = klass;
11310         m->signature = sig;
11311         m->sre_method = TRUE;
11312         m->skip_visibility = rmb->skip_visibility;
11313         if (rmb->table_idx)
11314                 m->token = MONO_TOKEN_METHOD_DEF | (*rmb->table_idx);
11315
11316         if (m->iflags & METHOD_IMPL_ATTRIBUTE_INTERNAL_CALL) {
11317                 if (klass == mono_defaults.string_class && !strcmp (m->name, ".ctor"))
11318                         m->string_ctor = 1;
11319
11320                 m->signature->pinvoke = 1;
11321         } else if (m->flags & METHOD_ATTRIBUTE_PINVOKE_IMPL) {
11322                 m->signature->pinvoke = 1;
11323
11324                 method_aux = image_g_new0 (image, MonoReflectionMethodAux, 1);
11325
11326                 method_aux->dllentry = rmb->dllentry ? mono_string_to_utf8_image (image, rmb->dllentry, &error) : image_strdup (image, m->name);
11327                 g_assert (mono_error_ok (&error));
11328                 method_aux->dll = mono_string_to_utf8_image (image, rmb->dll, &error);
11329                 g_assert (mono_error_ok (&error));
11330                 
11331                 ((MonoMethodPInvoke*)m)->piflags = (rmb->native_cc << 8) | (rmb->charset ? (rmb->charset - 1) * 2 : 0) | rmb->extra_flags;
11332
11333                 if (image_is_dynamic (klass->image))
11334                         g_hash_table_insert (((MonoDynamicImage*)klass->image)->method_aux_hash, m, method_aux);
11335
11336                 mono_loader_unlock ();
11337
11338                 return m;
11339         } else if (!(m->flags & METHOD_ATTRIBUTE_ABSTRACT) &&
11340                            !(m->iflags & METHOD_IMPL_ATTRIBUTE_RUNTIME)) {
11341                 MonoMethodHeader *header;
11342                 guint32 code_size;
11343                 gint32 max_stack, i;
11344                 gint32 num_locals = 0;
11345                 gint32 num_clauses = 0;
11346                 guint8 *code;
11347
11348                 if (rmb->ilgen) {
11349                         code = mono_array_addr (rmb->ilgen->code, guint8, 0);
11350                         code_size = rmb->ilgen->code_len;
11351                         max_stack = rmb->ilgen->max_stack;
11352                         num_locals = rmb->ilgen->locals ? mono_array_length (rmb->ilgen->locals) : 0;
11353                         if (rmb->ilgen->ex_handlers)
11354                                 num_clauses = method_count_clauses (rmb->ilgen);
11355                 } else {
11356                         if (rmb->code) {
11357                                 code = mono_array_addr (rmb->code, guint8, 0);
11358                                 code_size = mono_array_length (rmb->code);
11359                                 /* we probably need to run a verifier on the code... */
11360                                 max_stack = 8; 
11361                         }
11362                         else {
11363                                 code = NULL;
11364                                 code_size = 0;
11365                                 max_stack = 8;
11366                         }
11367                 }
11368
11369                 header = (MonoMethodHeader *)image_g_malloc0 (image, MONO_SIZEOF_METHOD_HEADER + num_locals * sizeof (MonoType*));
11370                 header->code_size = code_size;
11371                 header->code = (const unsigned char *)image_g_malloc (image, code_size);
11372                 memcpy ((char*)header->code, code, code_size);
11373                 header->max_stack = max_stack;
11374                 header->init_locals = rmb->init_locals;
11375                 header->num_locals = num_locals;
11376
11377                 for (i = 0; i < num_locals; ++i) {
11378                         MonoReflectionLocalBuilder *lb = 
11379                                 mono_array_get (rmb->ilgen->locals, MonoReflectionLocalBuilder*, i);
11380
11381                         header->locals [i] = image_g_new0 (image, MonoType, 1);
11382                         memcpy (header->locals [i], mono_reflection_type_get_handle ((MonoReflectionType*)lb->type), MONO_SIZEOF_TYPE);
11383                 }
11384
11385                 header->num_clauses = num_clauses;
11386                 if (num_clauses) {
11387                         header->clauses = method_encode_clauses (image, (MonoDynamicImage*)klass->image,
11388                                  rmb->ilgen, num_clauses);
11389                 }
11390
11391                 wrapperm->header = header;
11392         }
11393
11394         if (rmb->generic_params) {
11395                 int count = mono_array_length (rmb->generic_params);
11396                 MonoGenericContainer *container = rmb->generic_container;
11397
11398                 g_assert (container);
11399
11400                 container->type_argc = count;
11401                 container->type_params = image_g_new0 (image, MonoGenericParamFull, count);
11402                 container->owner.method = m;
11403                 container->is_anonymous = FALSE; // Method is now known, container is no longer anonymous
11404
11405                 m->is_generic = TRUE;
11406                 mono_method_set_generic_container (m, container);
11407
11408                 for (i = 0; i < count; i++) {
11409                         MonoReflectionGenericParam *gp =
11410                                 mono_array_get (rmb->generic_params, MonoReflectionGenericParam*, i);
11411                         MonoGenericParamFull *param = (MonoGenericParamFull *) mono_reflection_type_get_handle ((MonoReflectionType*)gp)->data.generic_param;
11412                         container->type_params [i] = *param;
11413                 }
11414
11415                 /*
11416                  * The method signature might have pointers to generic parameters that belong to other methods.
11417                  * This is a valid SRE case, but the resulting method signature must be encoded using the proper
11418                  * generic parameters.
11419                  */
11420                 for (i = 0; i < m->signature->param_count; ++i) {
11421                         MonoType *t = m->signature->params [i];
11422                         if (t->type == MONO_TYPE_MVAR) {
11423                                 MonoGenericParam *gparam =  t->data.generic_param;
11424                                 if (gparam->num < count) {
11425                                         m->signature->params [i] = mono_metadata_type_dup (image, m->signature->params [i]);
11426                                         m->signature->params [i]->data.generic_param = mono_generic_container_get_param (container, gparam->num);
11427                                 }
11428
11429                         }
11430                 }
11431
11432                 if (klass->generic_container) {
11433                         container->parent = klass->generic_container;
11434                         container->context.class_inst = klass->generic_container->context.class_inst;
11435                 }
11436                 container->context.method_inst = mono_get_shared_generic_inst (container);
11437         }
11438
11439         if (rmb->refs) {
11440                 MonoMethodWrapper *mw = (MonoMethodWrapper*)m;
11441                 int i;
11442                 void **data;
11443
11444                 m->wrapper_type = MONO_WRAPPER_DYNAMIC_METHOD;
11445
11446                 mw->method_data = data = image_g_new (image, gpointer, rmb->nrefs + 1);
11447                 data [0] = GUINT_TO_POINTER (rmb->nrefs);
11448                 for (i = 0; i < rmb->nrefs; ++i)
11449                         data [i + 1] = rmb->refs [i];
11450         }
11451
11452         method_aux = NULL;
11453
11454         /* Parameter info */
11455         if (rmb->pinfo) {
11456                 if (!method_aux)
11457                         method_aux = image_g_new0 (image, MonoReflectionMethodAux, 1);
11458                 method_aux->param_names = image_g_new0 (image, char *, mono_method_signature (m)->param_count + 1);
11459                 for (i = 0; i <= m->signature->param_count; ++i) {
11460                         MonoReflectionParamBuilder *pb;
11461                         if ((pb = mono_array_get (rmb->pinfo, MonoReflectionParamBuilder*, i))) {
11462                                 if ((i > 0) && (pb->attrs)) {
11463                                         /* Make a copy since it might point to a shared type structure */
11464                                         m->signature->params [i - 1] = mono_metadata_type_dup (klass->image, m->signature->params [i - 1]);
11465                                         m->signature->params [i - 1]->attrs = pb->attrs;
11466                                 }
11467
11468                                 if (pb->attrs & PARAM_ATTRIBUTE_HAS_DEFAULT) {
11469                                         MonoDynamicImage *assembly;
11470                                         guint32 idx, len;
11471                                         MonoTypeEnum def_type;
11472                                         char *p;
11473                                         const char *p2;
11474
11475                                         if (!method_aux->param_defaults) {
11476                                                 method_aux->param_defaults = image_g_new0 (image, guint8*, m->signature->param_count + 1);
11477                                                 method_aux->param_default_types = image_g_new0 (image, guint32, m->signature->param_count + 1);
11478                                         }
11479                                         assembly = (MonoDynamicImage*)klass->image;
11480                                         idx = encode_constant (assembly, pb->def_value, &def_type);
11481                                         /* Copy the data from the blob since it might get realloc-ed */
11482                                         p = assembly->blob.data + idx;
11483                                         len = mono_metadata_decode_blob_size (p, &p2);
11484                                         len += p2 - p;
11485                                         method_aux->param_defaults [i] = (uint8_t *)image_g_malloc (image, len);
11486                                         method_aux->param_default_types [i] = def_type;
11487                                         memcpy ((gpointer)method_aux->param_defaults [i], p, len);
11488                                 }
11489
11490                                 if (pb->name) {
11491                                         method_aux->param_names [i] = mono_string_to_utf8_image (image, pb->name, &error);
11492                                         g_assert (mono_error_ok (&error));
11493                                 }
11494                                 if (pb->cattrs) {
11495                                         if (!method_aux->param_cattr)
11496                                                 method_aux->param_cattr = image_g_new0 (image, MonoCustomAttrInfo*, m->signature->param_count + 1);
11497                                         method_aux->param_cattr [i] = mono_custom_attrs_from_builders (image, klass->image, pb->cattrs);
11498                                 }
11499                         }
11500                 }
11501         }
11502
11503         /* Parameter marshalling */
11504         specs = NULL;
11505         if (rmb->pinfo)         
11506                 for (i = 0; i < mono_array_length (rmb->pinfo); ++i) {
11507                         MonoReflectionParamBuilder *pb;
11508                         if ((pb = mono_array_get (rmb->pinfo, MonoReflectionParamBuilder*, i))) {
11509                                 if (pb->marshal_info) {
11510                                         if (specs == NULL)
11511                                                 specs = image_g_new0 (image, MonoMarshalSpec*, sig->param_count + 1);
11512                                         specs [pb->position] = 
11513                                                 mono_marshal_spec_from_builder (image, klass->image->assembly, pb->marshal_info);
11514                                 }
11515                         }
11516                 }
11517         if (specs != NULL) {
11518                 if (!method_aux)
11519                         method_aux = image_g_new0 (image, MonoReflectionMethodAux, 1);
11520                 method_aux->param_marshall = specs;
11521         }
11522
11523         if (image_is_dynamic (klass->image) && method_aux)
11524                 g_hash_table_insert (((MonoDynamicImage*)klass->image)->method_aux_hash, m, method_aux);
11525
11526         mono_loader_unlock ();
11527
11528         return m;
11529 }       
11530
11531 static MonoMethod*
11532 ctorbuilder_to_mono_method (MonoClass *klass, MonoReflectionCtorBuilder* mb, MonoError *error)
11533 {
11534         ReflectionMethodBuilder rmb;
11535         MonoMethodSignature *sig;
11536
11537         mono_loader_lock ();
11538         sig = ctor_builder_to_signature (klass->image, mb);
11539         mono_loader_unlock ();
11540
11541         if (!reflection_methodbuilder_from_ctor_builder (&rmb, mb, error))
11542                 return NULL;
11543
11544         mb->mhandle = reflection_methodbuilder_to_mono_method (klass, &rmb, sig);
11545         mono_save_custom_attrs (klass->image, mb->mhandle, mb->cattrs);
11546
11547         /* If we are in a generic class, we might be called multiple times from inflate_method */
11548         if (!((MonoDynamicImage*)(MonoDynamicImage*)klass->image)->save && !klass->generic_container) {
11549                 /* ilgen is no longer needed */
11550                 mb->ilgen = NULL;
11551         }
11552
11553         return mb->mhandle;
11554 }
11555
11556 static MonoMethod*
11557 methodbuilder_to_mono_method (MonoClass *klass, MonoReflectionMethodBuilder* mb, MonoError *error)
11558 {
11559         ReflectionMethodBuilder rmb;
11560         MonoMethodSignature *sig;
11561
11562         mono_error_init (error);
11563
11564         mono_loader_lock ();
11565         sig = method_builder_to_signature (klass->image, mb);
11566         mono_loader_unlock ();
11567
11568         if (!reflection_methodbuilder_from_method_builder (&rmb, mb, error))
11569                 return NULL;
11570
11571         mb->mhandle = reflection_methodbuilder_to_mono_method (klass, &rmb, sig);
11572         mono_save_custom_attrs (klass->image, mb->mhandle, mb->cattrs);
11573
11574         /* If we are in a generic class, we might be called multiple times from inflate_method */
11575         if (!((MonoDynamicImage*)(MonoDynamicImage*)klass->image)->save && !klass->generic_container) {
11576                 /* ilgen is no longer needed */
11577                 mb->ilgen = NULL;
11578         }
11579         return mb->mhandle;
11580 }
11581
11582 static MonoClassField*
11583 fieldbuilder_to_mono_class_field (MonoClass *klass, MonoReflectionFieldBuilder* fb)
11584 {
11585         MonoClassField *field;
11586         MonoType *custom;
11587         MonoError error;
11588
11589         field = g_new0 (MonoClassField, 1);
11590
11591         field->name = mono_string_to_utf8_image (klass->image, fb->name, &error);
11592         g_assert (mono_error_ok (&error));
11593         if (fb->attrs || fb->modreq || fb->modopt) {
11594                 field->type = mono_metadata_type_dup (NULL, mono_reflection_type_get_handle ((MonoReflectionType*)fb->type));
11595                 field->type->attrs = fb->attrs;
11596
11597                 g_assert (image_is_dynamic (klass->image));
11598                 custom = add_custom_modifiers ((MonoDynamicImage*)klass->image, field->type, fb->modreq, fb->modopt);
11599                 g_free (field->type);
11600                 field->type = mono_metadata_type_dup (klass->image, custom);
11601                 g_free (custom);
11602         } else {
11603                 field->type = mono_reflection_type_get_handle ((MonoReflectionType*)fb->type);
11604         }
11605         if (fb->offset != -1)
11606                 field->offset = fb->offset;
11607         field->parent = klass;
11608         mono_save_custom_attrs (klass->image, field, fb->cattrs);
11609
11610         // FIXME: Can't store fb->def_value/RVA, is it needed for field_on_insts ?
11611
11612         return field;
11613 }
11614 #endif
11615
11616 MonoType*
11617 mono_reflection_bind_generic_parameters (MonoReflectionType *type, int type_argc, MonoType **types)
11618 {
11619         MonoClass *klass;
11620         MonoReflectionTypeBuilder *tb = NULL;
11621         gboolean is_dynamic = FALSE;
11622         MonoClass *geninst;
11623
11624         mono_loader_lock ();
11625
11626         if (is_sre_type_builder (mono_object_class (type))) {
11627                 tb = (MonoReflectionTypeBuilder *) type;
11628
11629                 is_dynamic = TRUE;
11630         } else if (is_sre_generic_instance (mono_object_class (type))) {
11631                 MonoReflectionGenericClass *rgi = (MonoReflectionGenericClass *) type;
11632                 MonoReflectionType *gtd = rgi->generic_type;
11633
11634                 if (is_sre_type_builder (mono_object_class (gtd))) {
11635                         tb = (MonoReflectionTypeBuilder *)gtd;
11636                         is_dynamic = TRUE;
11637                 }
11638         }
11639
11640         /* FIXME: fix the CreateGenericParameters protocol to avoid the two stage setup of TypeBuilders */
11641         if (tb && tb->generic_container)
11642                 mono_reflection_create_generic_class (tb);
11643
11644         klass = mono_class_from_mono_type (mono_reflection_type_get_handle (type));
11645         if (!klass->generic_container) {
11646                 mono_loader_unlock ();
11647                 return NULL;
11648         }
11649
11650         if (klass->wastypebuilder) {
11651                 tb = (MonoReflectionTypeBuilder *) mono_class_get_ref_info (klass);
11652
11653                 is_dynamic = TRUE;
11654         }
11655
11656         mono_loader_unlock ();
11657
11658         geninst = mono_class_bind_generic_parameters (klass, type_argc, types, is_dynamic);
11659
11660         return &geninst->byval_arg;
11661 }
11662
11663 MonoClass*
11664 mono_class_bind_generic_parameters (MonoClass *klass, int type_argc, MonoType **types, gboolean is_dynamic)
11665 {
11666         MonoGenericClass *gclass;
11667         MonoGenericInst *inst;
11668
11669         g_assert (klass->generic_container);
11670
11671         inst = mono_metadata_get_generic_inst (type_argc, types);
11672         gclass = mono_metadata_lookup_generic_class (klass, inst, is_dynamic);
11673
11674         return mono_generic_class_get_class (gclass);
11675 }
11676
11677 MonoReflectionMethod*
11678 mono_reflection_bind_generic_method_parameters (MonoReflectionMethod *rmethod, MonoArray *types)
11679 {
11680         MonoError error;
11681         MonoClass *klass;
11682         MonoMethod *method, *inflated;
11683         MonoMethodInflated *imethod;
11684         MonoGenericContext tmp_context;
11685         MonoGenericInst *ginst;
11686         MonoType **type_argv;
11687         int count, i;
11688
11689         /*FIXME but this no longer should happen*/
11690         if (!strcmp (rmethod->object.vtable->klass->name, "MethodBuilder")) {
11691 #ifndef DISABLE_REFLECTION_EMIT
11692                 MonoReflectionMethodBuilder *mb = NULL;
11693                 MonoReflectionTypeBuilder *tb;
11694                 MonoClass *klass;
11695
11696                 mb = (MonoReflectionMethodBuilder *) rmethod;
11697                 tb = (MonoReflectionTypeBuilder *) mb->type;
11698                 klass = mono_class_from_mono_type (mono_reflection_type_get_handle ((MonoReflectionType*)tb));
11699
11700                 method = methodbuilder_to_mono_method (klass, mb, &error);
11701                 if (!method)
11702                         mono_error_raise_exception (&error); /* FIXME don't raise here */
11703 #else
11704                 g_assert_not_reached ();
11705                 method = NULL;
11706 #endif
11707         } else {
11708                 method = rmethod->method;
11709         }
11710
11711         klass = method->klass;
11712
11713         if (method->is_inflated)
11714                 method = ((MonoMethodInflated *) method)->declaring;
11715
11716         count = mono_method_signature (method)->generic_param_count;
11717         if (count != mono_array_length (types))
11718                 return NULL;
11719
11720         type_argv = g_new0 (MonoType *, count);
11721         for (i = 0; i < count; i++) {
11722                 MonoReflectionType *garg = (MonoReflectionType *)mono_array_get (types, gpointer, i);
11723                 type_argv [i] = mono_reflection_type_get_handle (garg);
11724         }
11725         ginst = mono_metadata_get_generic_inst (count, type_argv);
11726         g_free (type_argv);
11727
11728         tmp_context.class_inst = klass->generic_class ? klass->generic_class->context.class_inst : NULL;
11729         tmp_context.method_inst = ginst;
11730
11731         inflated = mono_class_inflate_generic_method_checked (method, &tmp_context, &error);
11732         g_assert (mono_error_ok (&error)); /* FIXME don't swallow the error */
11733         imethod = (MonoMethodInflated *) inflated;
11734
11735         /*FIXME but I think this is no longer necessary*/
11736         if (image_is_dynamic (method->klass->image)) {
11737                 MonoDynamicImage *image = (MonoDynamicImage*)method->klass->image;
11738                 /*
11739                  * This table maps metadata structures representing inflated methods/fields
11740                  * to the reflection objects representing their generic definitions.
11741                  */
11742                 mono_image_lock ((MonoImage*)image);
11743                 mono_g_hash_table_insert (image->generic_def_objects, imethod, rmethod);
11744                 mono_image_unlock ((MonoImage*)image);
11745         }
11746
11747         if (!mono_verifier_is_method_valid_generic_instantiation (inflated))
11748                 mono_raise_exception (mono_get_exception_argument ("typeArguments", "Invalid generic arguments"));
11749         
11750         MonoReflectionMethod *ret = mono_method_get_object_checked (mono_object_domain (rmethod), inflated, NULL, &error);
11751         mono_error_raise_exception (&error); /* FIXME don't raise here */
11752         return ret;
11753 }
11754
11755 #ifndef DISABLE_REFLECTION_EMIT
11756
11757 static MonoMethod *
11758 inflate_mono_method (MonoClass *klass, MonoMethod *method, MonoObject *obj)
11759 {
11760         MonoMethodInflated *imethod;
11761         MonoGenericContext *context;
11762         int i;
11763
11764         /*
11765          * With generic code sharing the klass might not be inflated.
11766          * This can happen because classes inflated with their own
11767          * type arguments are "normalized" to the uninflated class.
11768          */
11769         if (!klass->generic_class)
11770                 return method;
11771
11772         context = mono_class_get_context (klass);
11773
11774         if (klass->method.count && klass->methods) {
11775                 /* Find the already created inflated method */
11776                 for (i = 0; i < klass->method.count; ++i) {
11777                         g_assert (klass->methods [i]->is_inflated);
11778                         if (((MonoMethodInflated*)klass->methods [i])->declaring == method)
11779                                 break;
11780                 }
11781                 g_assert (i < klass->method.count);
11782                 imethod = (MonoMethodInflated*)klass->methods [i];
11783         } else {
11784                 MonoError error;
11785                 imethod = (MonoMethodInflated *) mono_class_inflate_generic_method_full_checked (method, klass, context, &error);
11786                 mono_error_assert_ok (&error);
11787         }
11788
11789         if (method->is_generic && image_is_dynamic (method->klass->image)) {
11790                 MonoDynamicImage *image = (MonoDynamicImage*)method->klass->image;
11791
11792                 mono_image_lock ((MonoImage*)image);
11793                 mono_g_hash_table_insert (image->generic_def_objects, imethod, obj);
11794                 mono_image_unlock ((MonoImage*)image);
11795         }
11796         return (MonoMethod *) imethod;
11797 }
11798
11799 static MonoMethod *
11800 inflate_method (MonoReflectionType *type, MonoObject *obj, MonoError *error)
11801 {
11802         MonoMethod *method;
11803         MonoClass *gklass;
11804
11805         mono_error_init (error);
11806
11807         MonoClass *type_class = mono_object_class (type);
11808
11809         if (is_sre_generic_instance (type_class)) {
11810                 MonoReflectionGenericClass *mgc = (MonoReflectionGenericClass*)type;
11811                 gklass = mono_class_from_mono_type (mono_reflection_type_get_handle ((MonoReflectionType*)mgc->generic_type));
11812         } else if (is_sre_type_builder (type_class)) {
11813                 gklass = mono_class_from_mono_type (mono_reflection_type_get_handle (type));
11814         } else if (type->type) {
11815                 gklass = mono_class_from_mono_type (type->type);
11816                 gklass = mono_class_get_generic_type_definition (gklass);
11817         } else {
11818                 g_error ("Can't handle type %s", mono_type_get_full_name (mono_object_class (type)));
11819         }
11820
11821         if (!strcmp (obj->vtable->klass->name, "MethodBuilder"))
11822                 if (((MonoReflectionMethodBuilder*)obj)->mhandle)
11823                         method = ((MonoReflectionMethodBuilder*)obj)->mhandle;
11824                 else {
11825                         method = methodbuilder_to_mono_method (gklass, (MonoReflectionMethodBuilder *) obj, error);
11826                         if (!method)
11827                                 return NULL;
11828                 }
11829         else if (!strcmp (obj->vtable->klass->name, "ConstructorBuilder")) {
11830                 method = ctorbuilder_to_mono_method (gklass, (MonoReflectionCtorBuilder *) obj, error);
11831                 if (!method)
11832                         return NULL;
11833         } else if (!strcmp (obj->vtable->klass->name, "MonoMethod") || !strcmp (obj->vtable->klass->name, "MonoCMethod"))
11834                 method = ((MonoReflectionMethod *) obj)->method;
11835         else {
11836                 method = NULL; /* prevent compiler warning */
11837                 g_error ("can't handle type %s", obj->vtable->klass->name);
11838         }
11839
11840         return inflate_mono_method (mono_class_from_mono_type (mono_reflection_type_get_handle ((MonoReflectionType*)type)), method, obj);
11841 }
11842
11843 /*TODO avoid saving custom attrs for generic classes as it's enough to have them on the generic type definition.*/
11844 void
11845 mono_reflection_generic_class_initialize (MonoReflectionGenericClass *type, MonoArray *fields)
11846 {
11847         MonoGenericClass *gclass;
11848         MonoDynamicGenericClass *dgclass;
11849         MonoClass *klass, *gklass;
11850         MonoType *gtype;
11851         int i;
11852
11853         gtype = mono_reflection_type_get_handle ((MonoReflectionType*)type);
11854         klass = mono_class_from_mono_type (gtype);
11855         g_assert (gtype->type == MONO_TYPE_GENERICINST);
11856         gclass = gtype->data.generic_class;
11857
11858         if (!gclass->is_dynamic)
11859                 return;
11860
11861         dgclass = (MonoDynamicGenericClass *) gclass;
11862
11863         if (dgclass->initialized)
11864                 return;
11865
11866         gklass = gclass->container_class;
11867         mono_class_init (gklass);
11868
11869         dgclass->count_fields = fields ? mono_array_length (fields) : 0;
11870
11871         dgclass->fields = mono_image_set_new0 (gclass->owner, MonoClassField, dgclass->count_fields);
11872         dgclass->field_objects = mono_image_set_new0 (gclass->owner, MonoObject*, dgclass->count_fields);
11873         dgclass->field_generic_types = mono_image_set_new0 (gclass->owner, MonoType*, dgclass->count_fields);
11874
11875         for (i = 0; i < dgclass->count_fields; i++) {
11876                 MonoError error;
11877                 MonoObject *obj = (MonoObject *)mono_array_get (fields, gpointer, i);
11878                 MonoClassField *field, *inflated_field = NULL;
11879
11880                 if (!strcmp (obj->vtable->klass->name, "FieldBuilder"))
11881                         inflated_field = field = fieldbuilder_to_mono_class_field (klass, (MonoReflectionFieldBuilder *) obj);
11882                 else if (!strcmp (obj->vtable->klass->name, "MonoField"))
11883                         field = ((MonoReflectionField *) obj)->field;
11884                 else {
11885                         field = NULL; /* prevent compiler warning */
11886                         g_assert_not_reached ();
11887                 }
11888
11889                 dgclass->fields [i] = *field;
11890                 dgclass->fields [i].parent = klass;
11891                 dgclass->fields [i].type = mono_class_inflate_generic_type_checked (
11892                         field->type, mono_generic_class_get_context ((MonoGenericClass *) dgclass), &error);
11893                 mono_error_assert_ok (&error); /* FIXME don't swallow the error */
11894                 dgclass->field_generic_types [i] = field->type;
11895                 MONO_GC_REGISTER_ROOT_IF_MOVING (dgclass->field_objects [i], MONO_ROOT_SOURCE_REFLECTION, "dynamic generic class field object");
11896                 dgclass->field_objects [i] = obj;
11897
11898                 if (inflated_field) {
11899                         g_free (inflated_field);
11900                 } else {
11901                         dgclass->fields [i].name = mono_image_set_strdup (gclass->owner, dgclass->fields [i].name);
11902                 }
11903         }
11904
11905         dgclass->initialized = TRUE;
11906 }
11907
11908 void
11909 mono_reflection_free_dynamic_generic_class (MonoGenericClass *gclass)
11910 {
11911         MonoDynamicGenericClass *dgclass;
11912         int i;
11913
11914         g_assert (gclass->is_dynamic);
11915
11916         dgclass = (MonoDynamicGenericClass *)gclass;
11917
11918         for (i = 0; i < dgclass->count_fields; ++i) {
11919                 MonoClassField *field = dgclass->fields + i;
11920                 mono_metadata_free_type (field->type);
11921                 MONO_GC_UNREGISTER_ROOT_IF_MOVING (dgclass->field_objects [i]);
11922         }
11923 }
11924
11925 static void
11926 fix_partial_generic_class (MonoClass *klass)
11927 {
11928         MonoClass *gklass = klass->generic_class->container_class;
11929         MonoDynamicGenericClass *dgclass;
11930         int i;
11931
11932         if (klass->wastypebuilder)
11933                 return;
11934
11935         dgclass = (MonoDynamicGenericClass *)  klass->generic_class;
11936         if (klass->parent != gklass->parent) {
11937                 MonoError error;
11938                 MonoType *parent_type = mono_class_inflate_generic_type_checked (&gklass->parent->byval_arg, &klass->generic_class->context, &error);
11939                 if (mono_error_ok (&error)) {
11940                         MonoClass *parent = mono_class_from_mono_type (parent_type);
11941                         mono_metadata_free_type (parent_type);
11942                         if (parent != klass->parent) {
11943                                 /*fool mono_class_setup_parent*/
11944                                 klass->supertypes = NULL;
11945                                 mono_class_setup_parent (klass, parent);
11946                         }
11947                 } else {
11948                         mono_class_set_failure (klass, MONO_EXCEPTION_TYPE_LOAD, NULL);
11949                         mono_error_cleanup (&error);
11950                         if (gklass->wastypebuilder)
11951                                 klass->wastypebuilder = TRUE;
11952                         return;
11953                 }
11954         }
11955
11956         if (!dgclass->initialized)
11957                 return;
11958
11959         if (klass->method.count != gklass->method.count) {
11960                 klass->method.count = gklass->method.count;
11961                 klass->methods = (MonoMethod **)mono_image_alloc (klass->image, sizeof (MonoMethod*) * (klass->method.count + 1));
11962
11963                 for (i = 0; i < klass->method.count; i++) {
11964                         MonoError error;
11965                         klass->methods [i] = mono_class_inflate_generic_method_full_checked (
11966                                 gklass->methods [i], klass, mono_class_get_context (klass), &error);
11967                         g_assert (mono_error_ok (&error)); /* FIXME don't swallow the error */
11968                 }
11969         }
11970
11971         if (klass->interface_count && klass->interface_count != gklass->interface_count) {
11972                 klass->interface_count = gklass->interface_count;
11973                 klass->interfaces = (MonoClass **)mono_image_alloc (klass->image, sizeof (MonoClass*) * gklass->interface_count);
11974                 klass->interfaces_packed = NULL; /*make setup_interface_offsets happy*/
11975
11976                 for (i = 0; i < gklass->interface_count; ++i) {
11977                         MonoError error;
11978                         MonoType *iface_type = mono_class_inflate_generic_type_checked (&gklass->interfaces [i]->byval_arg, mono_class_get_context (klass), &error);
11979                         mono_error_raise_exception (&error); /* FIXME don't raise here */
11980
11981                         klass->interfaces [i] = mono_class_from_mono_type (iface_type);
11982                         mono_metadata_free_type (iface_type);
11983
11984                         ensure_runtime_vtable (klass->interfaces [i], &error);
11985                         mono_error_raise_exception (&error); /* FIXME don't raise here */
11986                 }
11987                 klass->interfaces_inited = 1;
11988         }
11989
11990         if (klass->field.count != gklass->field.count) {
11991                 klass->field.count = gklass->field.count;
11992                 klass->fields = image_g_new0 (klass->image, MonoClassField, klass->field.count);
11993
11994                 for (i = 0; i < klass->field.count; i++) {
11995                         MonoError error;
11996                         klass->fields [i] = gklass->fields [i];
11997                         klass->fields [i].parent = klass;
11998                         klass->fields [i].type = mono_class_inflate_generic_type_checked (gklass->fields [i].type, mono_class_get_context (klass), &error);
11999                         mono_error_raise_exception (&error); /* FIXME don't raise here */
12000                 }
12001         }
12002
12003         /*We can only finish with this klass once it's parent has as well*/
12004         if (gklass->wastypebuilder)
12005                 klass->wastypebuilder = TRUE;
12006         return;
12007 }
12008
12009 /**
12010  * ensure_generic_class_runtime_vtable:
12011  * @klass a generic class
12012  * @error set on error
12013  *
12014  * Ensures that the generic container of @klass has a vtable and
12015  * returns TRUE on success.  On error returns FALSE and sets @error.
12016  */
12017 static gboolean
12018 ensure_generic_class_runtime_vtable (MonoClass *klass, MonoError *error)
12019 {
12020         MonoClass *gklass = klass->generic_class->container_class;
12021
12022         mono_error_init (error);
12023
12024         if (!ensure_runtime_vtable (gklass, error))
12025                 return FALSE;
12026
12027         fix_partial_generic_class (klass);
12028
12029         return TRUE;
12030 }
12031
12032 /**
12033  * ensure_runtime_vtable:
12034  * @klass the class
12035  * @error set on error
12036  *
12037  * Ensures that @klass has a vtable and returns TRUE on success. On
12038  * error returns FALSE and sets @error.
12039  */
12040 static gboolean
12041 ensure_runtime_vtable (MonoClass *klass, MonoError *error)
12042 {
12043         MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder *)mono_class_get_ref_info (klass);
12044         int i, num, j;
12045
12046         mono_error_init (error);
12047
12048         if (!image_is_dynamic (klass->image) || (!tb && !klass->generic_class) || klass->wastypebuilder)
12049                 return TRUE;
12050         if (klass->parent)
12051                 if (!ensure_runtime_vtable (klass->parent, error))
12052                         return FALSE;
12053
12054         if (tb) {
12055                 num = tb->ctors? mono_array_length (tb->ctors): 0;
12056                 num += tb->num_methods;
12057                 klass->method.count = num;
12058                 klass->methods = (MonoMethod **)mono_image_alloc (klass->image, sizeof (MonoMethod*) * num);
12059                 num = tb->ctors? mono_array_length (tb->ctors): 0;
12060                 for (i = 0; i < num; ++i) {
12061                         MonoMethod *ctor = ctorbuilder_to_mono_method (klass, mono_array_get (tb->ctors, MonoReflectionCtorBuilder*, i), error);
12062                         if (!ctor)
12063                                 return FALSE;
12064                         klass->methods [i] = ctor;
12065                 }
12066                 num = tb->num_methods;
12067                 j = i;
12068                 for (i = 0; i < num; ++i) {
12069                         MonoMethod *meth = methodbuilder_to_mono_method (klass, mono_array_get (tb->methods, MonoReflectionMethodBuilder*, i), error);
12070                         if (!meth)
12071                                 return FALSE;
12072                         klass->methods [j++] = meth;
12073                 }
12074         
12075                 if (tb->interfaces) {
12076                         klass->interface_count = mono_array_length (tb->interfaces);
12077                         klass->interfaces = (MonoClass **)mono_image_alloc (klass->image, sizeof (MonoClass*) * klass->interface_count);
12078                         for (i = 0; i < klass->interface_count; ++i) {
12079                                 MonoType *iface = mono_type_array_get_and_resolve (tb->interfaces, i);
12080                                 klass->interfaces [i] = mono_class_from_mono_type (iface);
12081                                 if (!ensure_runtime_vtable (klass->interfaces [i], error))
12082                                         return FALSE;
12083                         }
12084                         klass->interfaces_inited = 1;
12085                 }
12086         } else if (klass->generic_class){
12087                 if (!ensure_generic_class_runtime_vtable (klass, error))
12088                         return FALSE;
12089         }
12090
12091         if (klass->flags & TYPE_ATTRIBUTE_INTERFACE) {
12092                 int slot_num = 0;
12093                 for (i = 0; i < klass->method.count; ++i) {
12094                         MonoMethod *im = klass->methods [i];
12095                         if (!(im->flags & METHOD_ATTRIBUTE_STATIC))
12096                                 im->slot = slot_num++;
12097                 }
12098                 
12099                 klass->interfaces_packed = NULL; /*make setup_interface_offsets happy*/
12100                 mono_class_setup_interface_offsets (klass);
12101                 mono_class_setup_interface_id (klass);
12102         }
12103
12104         /*
12105          * The generic vtable is needed even if image->run is not set since some
12106          * runtime code like ves_icall_Type_GetMethodsByName depends on 
12107          * method->slot being defined.
12108          */
12109
12110         /* 
12111          * tb->methods could not be freed since it is used for determining 
12112          * overrides during dynamic vtable construction.
12113          */
12114
12115         return TRUE;
12116 }
12117
12118 static MonoMethod*
12119 mono_reflection_method_get_handle (MonoObject *method)
12120 {
12121         MonoError error;
12122         MonoClass *klass = mono_object_class (method);
12123         if (is_sr_mono_method (klass) || is_sr_mono_generic_method (klass)) {
12124                 MonoReflectionMethod *sr_method = (MonoReflectionMethod*)method;
12125                 return sr_method->method;
12126         }
12127         if (is_sre_method_builder (klass)) {
12128                 MonoReflectionMethodBuilder *mb = (MonoReflectionMethodBuilder*)method;
12129                 return mb->mhandle;
12130         }
12131         if (is_sre_method_on_tb_inst (klass)) {
12132                 MonoReflectionMethodOnTypeBuilderInst *m = (MonoReflectionMethodOnTypeBuilderInst*)method;
12133                 MonoMethod *result;
12134                 /*FIXME move this to a proper method and unify with resolve_object*/
12135                 if (m->method_args) {
12136                         result = mono_reflection_method_on_tb_inst_get_handle (m, &error);
12137                         mono_error_raise_exception (&error); /* FIXME don't raise here */
12138                 } else {
12139                         MonoType *type = mono_reflection_type_get_handle ((MonoReflectionType*)m->inst);
12140                         MonoClass *inflated_klass = mono_class_from_mono_type (type);
12141                         MonoMethod *mono_method;
12142
12143                         if (is_sre_method_builder (mono_object_class (m->mb)))
12144                                 mono_method = ((MonoReflectionMethodBuilder *)m->mb)->mhandle;
12145                         else if (is_sr_mono_method (mono_object_class (m->mb)))
12146                                 mono_method = ((MonoReflectionMethod *)m->mb)->method;
12147                         else
12148                                 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)));
12149
12150                         result = inflate_mono_method (inflated_klass, mono_method, (MonoObject*)m->mb);
12151                 }
12152                 return result;
12153         }
12154
12155         g_error ("Can't handle methods of type %s:%s", klass->name_space, klass->name);
12156         return NULL;
12157 }
12158
12159 void
12160 mono_reflection_get_dynamic_overrides (MonoClass *klass, MonoMethod ***overrides, int *num_overrides)
12161 {
12162         MonoReflectionTypeBuilder *tb;
12163         int i, j, onum;
12164         MonoReflectionMethod *m;
12165
12166         *overrides = NULL;
12167         *num_overrides = 0;
12168
12169         g_assert (image_is_dynamic (klass->image));
12170
12171         if (!mono_class_get_ref_info (klass))
12172                 return;
12173
12174         g_assert (strcmp (((MonoObject*)mono_class_get_ref_info (klass))->vtable->klass->name, "TypeBuilder") == 0);
12175
12176         tb = (MonoReflectionTypeBuilder*)mono_class_get_ref_info (klass);
12177
12178         onum = 0;
12179         if (tb->methods) {
12180                 for (i = 0; i < tb->num_methods; ++i) {
12181                         MonoReflectionMethodBuilder *mb = 
12182                                 mono_array_get (tb->methods, MonoReflectionMethodBuilder*, i);
12183                         if (mb->override_methods)
12184                                 onum += mono_array_length (mb->override_methods);
12185                 }
12186         }
12187
12188         if (onum) {
12189                 *overrides = g_new0 (MonoMethod*, onum * 2);
12190
12191                 onum = 0;
12192                 for (i = 0; i < tb->num_methods; ++i) {
12193                         MonoReflectionMethodBuilder *mb = 
12194                                 mono_array_get (tb->methods, MonoReflectionMethodBuilder*, i);
12195                         if (mb->override_methods) {
12196                                 for (j = 0; j < mono_array_length (mb->override_methods); ++j) {
12197                                         m = mono_array_get (mb->override_methods, MonoReflectionMethod*, j);
12198
12199                                         (*overrides) [onum * 2] = mono_reflection_method_get_handle ((MonoObject*)m);
12200                                         (*overrides) [onum * 2 + 1] = mb->mhandle;
12201
12202                                         g_assert (mb->mhandle);
12203
12204                                         onum ++;
12205                                 }
12206                         }
12207                 }
12208         }
12209
12210         *num_overrides = onum;
12211 }
12212
12213 static void
12214 typebuilder_setup_fields (MonoClass *klass, MonoError *error)
12215 {
12216         MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder *)mono_class_get_ref_info (klass);
12217         MonoReflectionFieldBuilder *fb;
12218         MonoClassField *field;
12219         MonoImage *image = klass->image;
12220         const char *p, *p2;
12221         int i;
12222         guint32 len, idx, real_size = 0;
12223
12224         klass->field.count = tb->num_fields;
12225         klass->field.first = 0;
12226
12227         mono_error_init (error);
12228
12229         if (tb->class_size) {
12230                 if ((tb->packing_size & 0xffffff00) != 0) {
12231                         char *err_msg = g_strdup_printf ("Could not load struct '%s' with packing size %d >= 256", klass->name, tb->packing_size);
12232                         mono_class_set_failure (klass, MONO_EXCEPTION_TYPE_LOAD, err_msg);
12233                         return;
12234                 }
12235                 klass->packing_size = tb->packing_size;
12236                 real_size = klass->instance_size + tb->class_size;
12237         }
12238
12239         if (!klass->field.count) {
12240                 klass->instance_size = MAX (klass->instance_size, real_size);
12241                 return;
12242         }
12243         
12244         klass->fields = image_g_new0 (image, MonoClassField, klass->field.count);
12245         mono_class_alloc_ext (klass);
12246         klass->ext->field_def_values = image_g_new0 (image, MonoFieldDefaultValue, klass->field.count);
12247         /*
12248         This is, guess what, a hack.
12249         The issue is that the runtime doesn't know how to setup the fields of a typebuider and crash.
12250         On the static path no field class is resolved, only types are built. This is the right thing to do
12251         but we suck.
12252         Setting size_inited is harmless because we're doing the same job as mono_class_setup_fields anyway.
12253         */
12254         klass->size_inited = 1;
12255
12256         for (i = 0; i < klass->field.count; ++i) {
12257                 MonoArray *rva_data;
12258                 fb = (MonoReflectionFieldBuilder *)mono_array_get (tb->fields, gpointer, i);
12259                 field = &klass->fields [i];
12260                 field->name = mono_string_to_utf8_image (image, fb->name, error);
12261                 if (!mono_error_ok (error))
12262                         return;
12263                 if (fb->attrs) {
12264                         field->type = mono_metadata_type_dup (klass->image, mono_reflection_type_get_handle ((MonoReflectionType*)fb->type));
12265                         field->type->attrs = fb->attrs;
12266                 } else {
12267                         field->type = mono_reflection_type_get_handle ((MonoReflectionType*)fb->type);
12268                 }
12269
12270                 if ((fb->attrs & FIELD_ATTRIBUTE_HAS_FIELD_RVA) && (rva_data = fb->rva_data)) {
12271                         char *base = mono_array_addr (rva_data, char, 0);
12272                         size_t size = mono_array_length (rva_data);
12273                         char *data = (char *)mono_image_alloc (klass->image, size);
12274                         memcpy (data, base, size);
12275                         klass->ext->field_def_values [i].data = data;
12276                 }
12277                 if (fb->offset != -1)
12278                         field->offset = fb->offset;
12279                 field->parent = klass;
12280                 fb->handle = field;
12281                 mono_save_custom_attrs (klass->image, field, fb->cattrs);
12282
12283                 if (klass->enumtype && !(field->type->attrs & FIELD_ATTRIBUTE_STATIC)) {
12284                         klass->cast_class = klass->element_class = mono_class_from_mono_type (field->type);
12285                 }
12286                 if (fb->def_value) {
12287                         MonoDynamicImage *assembly = (MonoDynamicImage*)klass->image;
12288                         field->type->attrs |= FIELD_ATTRIBUTE_HAS_DEFAULT;
12289                         idx = encode_constant (assembly, fb->def_value, &klass->ext->field_def_values [i].def_type);
12290                         /* Copy the data from the blob since it might get realloc-ed */
12291                         p = assembly->blob.data + idx;
12292                         len = mono_metadata_decode_blob_size (p, &p2);
12293                         len += p2 - p;
12294                         klass->ext->field_def_values [i].data = (const char *)mono_image_alloc (image, len);
12295                         memcpy ((gpointer)klass->ext->field_def_values [i].data, p, len);
12296                 }
12297         }
12298
12299         klass->instance_size = MAX (klass->instance_size, real_size);
12300         mono_class_layout_fields (klass);
12301 }
12302
12303 static void
12304 typebuilder_setup_properties (MonoClass *klass, MonoError *error)
12305 {
12306         MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder *)mono_class_get_ref_info (klass);
12307         MonoReflectionPropertyBuilder *pb;
12308         MonoImage *image = klass->image;
12309         MonoProperty *properties;
12310         int i;
12311
12312         mono_error_init (error);
12313
12314         if (!klass->ext)
12315                 klass->ext = image_g_new0 (image, MonoClassExt, 1);
12316
12317         klass->ext->property.count = tb->properties ? mono_array_length (tb->properties) : 0;
12318         klass->ext->property.first = 0;
12319
12320         properties = image_g_new0 (image, MonoProperty, klass->ext->property.count);
12321         klass->ext->properties = properties;
12322         for (i = 0; i < klass->ext->property.count; ++i) {
12323                 pb = mono_array_get (tb->properties, MonoReflectionPropertyBuilder*, i);
12324                 properties [i].parent = klass;
12325                 properties [i].attrs = pb->attrs;
12326                 properties [i].name = mono_string_to_utf8_image (image, pb->name, error);
12327                 if (!mono_error_ok (error))
12328                         return;
12329                 if (pb->get_method)
12330                         properties [i].get = pb->get_method->mhandle;
12331                 if (pb->set_method)
12332                         properties [i].set = pb->set_method->mhandle;
12333
12334                 mono_save_custom_attrs (klass->image, &properties [i], pb->cattrs);
12335                 if (pb->def_value) {
12336                         guint32 len, idx;
12337                         const char *p, *p2;
12338                         MonoDynamicImage *assembly = (MonoDynamicImage*)klass->image;
12339                         if (!klass->ext->prop_def_values)
12340                                 klass->ext->prop_def_values = image_g_new0 (image, MonoFieldDefaultValue, klass->ext->property.count);
12341                         properties [i].attrs |= PROPERTY_ATTRIBUTE_HAS_DEFAULT;
12342                         idx = encode_constant (assembly, pb->def_value, &klass->ext->prop_def_values [i].def_type);
12343                         /* Copy the data from the blob since it might get realloc-ed */
12344                         p = assembly->blob.data + idx;
12345                         len = mono_metadata_decode_blob_size (p, &p2);
12346                         len += p2 - p;
12347                         klass->ext->prop_def_values [i].data = (const char *)mono_image_alloc (image, len);
12348                         memcpy ((gpointer)klass->ext->prop_def_values [i].data, p, len);
12349                 }
12350         }
12351 }
12352
12353 MonoReflectionEvent *
12354 mono_reflection_event_builder_get_event_info (MonoReflectionTypeBuilder *tb, MonoReflectionEventBuilder *eb)
12355 {
12356         MonoError error;
12357         MonoEvent *event = g_new0 (MonoEvent, 1);
12358         MonoClass *klass;
12359
12360         klass = mono_class_from_mono_type (mono_reflection_type_get_handle ((MonoReflectionType*)tb));
12361
12362         event->parent = klass;
12363         event->attrs = eb->attrs;
12364         event->name = mono_string_to_utf8 (eb->name);
12365         if (eb->add_method)
12366                 event->add = eb->add_method->mhandle;
12367         if (eb->remove_method)
12368                 event->remove = eb->remove_method->mhandle;
12369         if (eb->raise_method)
12370                 event->raise = eb->raise_method->mhandle;
12371
12372 #ifndef MONO_SMALL_CONFIG
12373         if (eb->other_methods) {
12374                 int j;
12375                 event->other = g_new0 (MonoMethod*, mono_array_length (eb->other_methods) + 1);
12376                 for (j = 0; j < mono_array_length (eb->other_methods); ++j) {
12377                         MonoReflectionMethodBuilder *mb = 
12378                                 mono_array_get (eb->other_methods,
12379                                                 MonoReflectionMethodBuilder*, j);
12380                         event->other [j] = mb->mhandle;
12381                 }
12382         }
12383 #endif
12384
12385         MonoReflectionEvent *ev_obj = mono_event_get_object_checked (mono_object_domain (tb), klass, event, &error);
12386         mono_error_raise_exception (&error); /* FIXME don't raise here */
12387         return ev_obj;
12388 }
12389
12390 static void
12391 typebuilder_setup_events (MonoClass *klass, MonoError *error)
12392 {
12393         MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder *)mono_class_get_ref_info (klass);
12394         MonoReflectionEventBuilder *eb;
12395         MonoImage *image = klass->image;
12396         MonoEvent *events;
12397         int i;
12398
12399         mono_error_init (error);
12400
12401         if (!klass->ext)
12402                 klass->ext = image_g_new0 (image, MonoClassExt, 1);
12403
12404         klass->ext->event.count = tb->events ? mono_array_length (tb->events) : 0;
12405         klass->ext->event.first = 0;
12406
12407         events = image_g_new0 (image, MonoEvent, klass->ext->event.count);
12408         klass->ext->events = events;
12409         for (i = 0; i < klass->ext->event.count; ++i) {
12410                 eb = mono_array_get (tb->events, MonoReflectionEventBuilder*, i);
12411                 events [i].parent = klass;
12412                 events [i].attrs = eb->attrs;
12413                 events [i].name = mono_string_to_utf8_image (image, eb->name, error);
12414                 if (!mono_error_ok (error))
12415                         return;
12416                 if (eb->add_method)
12417                         events [i].add = eb->add_method->mhandle;
12418                 if (eb->remove_method)
12419                         events [i].remove = eb->remove_method->mhandle;
12420                 if (eb->raise_method)
12421                         events [i].raise = eb->raise_method->mhandle;
12422
12423 #ifndef MONO_SMALL_CONFIG
12424                 if (eb->other_methods) {
12425                         int j;
12426                         events [i].other = image_g_new0 (image, MonoMethod*, mono_array_length (eb->other_methods) + 1);
12427                         for (j = 0; j < mono_array_length (eb->other_methods); ++j) {
12428                                 MonoReflectionMethodBuilder *mb = 
12429                                         mono_array_get (eb->other_methods,
12430                                                                         MonoReflectionMethodBuilder*, j);
12431                                 events [i].other [j] = mb->mhandle;
12432                         }
12433                 }
12434 #endif
12435                 mono_save_custom_attrs (klass->image, &events [i], eb->cattrs);
12436         }
12437 }
12438
12439 static gboolean
12440 remove_instantiations_of_and_ensure_contents (gpointer key,
12441                                                   gpointer value,
12442                                                   gpointer user_data)
12443 {
12444         MonoType *type = (MonoType*)key;
12445         MonoClass *klass = (MonoClass*)user_data;
12446
12447         if ((type->type == MONO_TYPE_GENERICINST) && (type->data.generic_class->container_class == klass)) {
12448                 fix_partial_generic_class (mono_class_from_mono_type (type)); //Ensure it's safe to use it.
12449                 return TRUE;
12450         } else
12451                 return FALSE;
12452 }
12453
12454 static void
12455 check_array_for_usertypes (MonoArray *arr, MonoError *error)
12456 {
12457         mono_error_init (error);
12458         int i;
12459
12460         if (!arr)
12461                 return;
12462
12463         for (i = 0; i < mono_array_length (arr); ++i) {
12464                 RESOLVE_ARRAY_TYPE_ELEMENT (arr, i, error);
12465                 if (!mono_error_ok (error))
12466                         break;
12467         }
12468 }
12469
12470 MonoReflectionType*
12471 mono_reflection_create_runtime_class (MonoReflectionTypeBuilder *tb)
12472 {
12473         MonoError error;
12474         MonoClass *klass;
12475         MonoDomain* domain;
12476         MonoReflectionType* res;
12477         int i, j;
12478
12479         domain = mono_object_domain (tb);
12480         klass = mono_class_from_mono_type (tb->type.type);
12481
12482         /*
12483          * Check for user defined Type subclasses.
12484          */
12485         RESOLVE_TYPE (tb->parent, &error);
12486         mono_error_raise_exception (&error); /* FIXME don't raise here */
12487         check_array_for_usertypes (tb->interfaces, &error);
12488         mono_error_raise_exception (&error); /*FIXME don't raise here */
12489         if (tb->fields) {
12490                 for (i = 0; i < mono_array_length (tb->fields); ++i) {
12491                         MonoReflectionFieldBuilder *fb = (MonoReflectionFieldBuilder *)mono_array_get (tb->fields, gpointer, i);
12492                         if (fb) {
12493                                 RESOLVE_TYPE (fb->type, &error);
12494                                 mono_error_raise_exception (&error); /* FIXME don't raise here */
12495                                 check_array_for_usertypes (fb->modreq, &error);
12496                                 mono_error_raise_exception (&error); /*FIXME don't raise here */
12497                                 check_array_for_usertypes (fb->modopt, &error);
12498                                 mono_error_raise_exception (&error); /*FIXME don't raise here */
12499                                 if (fb->marshal_info && fb->marshal_info->marshaltyperef) {
12500                                         RESOLVE_TYPE (fb->marshal_info->marshaltyperef, &error);
12501                                         mono_error_raise_exception (&error); /* FIXME don't raise here */
12502                                 }
12503                         }
12504                 }
12505         }
12506         if (tb->methods) {
12507                 for (i = 0; i < mono_array_length (tb->methods); ++i) {
12508                         MonoReflectionMethodBuilder *mb = (MonoReflectionMethodBuilder *)mono_array_get (tb->methods, gpointer, i);
12509                         if (mb) {
12510                                 RESOLVE_TYPE (mb->rtype, &error);
12511                                 mono_error_raise_exception (&error); /* FIXME don't raise here */
12512                                 check_array_for_usertypes (mb->return_modreq, &error);
12513                                 mono_error_raise_exception (&error); /*FIXME don't raise here */
12514                                 check_array_for_usertypes (mb->return_modopt, &error);
12515                                 mono_error_raise_exception (&error); /*FIXME don't raise here */
12516                                 check_array_for_usertypes (mb->parameters, &error);
12517                                 mono_error_raise_exception (&error); /*FIXME don't raise here */
12518                                 if (mb->param_modreq)
12519                                         for (j = 0; j < mono_array_length (mb->param_modreq); ++j) {
12520                                                 check_array_for_usertypes (mono_array_get (mb->param_modreq, MonoArray*, j), &error);
12521                                                 mono_error_raise_exception (&error); /*FIXME don't raise here */
12522                                         }
12523                                 if (mb->param_modopt)
12524                                         for (j = 0; j < mono_array_length (mb->param_modopt); ++j) {
12525                                                 check_array_for_usertypes (mono_array_get (mb->param_modopt, MonoArray*, j), &error);
12526                                                 mono_error_raise_exception (&error); /*FIXME don't raise here */
12527                                         }
12528                         }
12529                 }
12530         }
12531         if (tb->ctors) {
12532                 for (i = 0; i < mono_array_length (tb->ctors); ++i) {
12533                         MonoReflectionCtorBuilder *mb = (MonoReflectionCtorBuilder *)mono_array_get (tb->ctors, gpointer, i);
12534                         if (mb) {
12535                                 check_array_for_usertypes (mb->parameters, &error);
12536                                 mono_error_raise_exception (&error); /*FIXME don't raise here */
12537                                 if (mb->param_modreq)
12538                                         for (j = 0; j < mono_array_length (mb->param_modreq); ++j) {
12539                                                 check_array_for_usertypes (mono_array_get (mb->param_modreq, MonoArray*, j), &error);
12540                                                 mono_error_raise_exception (&error); /*FIXME don't raise here */
12541                                         }
12542                                 if (mb->param_modopt)
12543                                         for (j = 0; j < mono_array_length (mb->param_modopt); ++j) {
12544                                                 check_array_for_usertypes (mono_array_get (mb->param_modopt, MonoArray*, j), &error);
12545                                                 mono_error_raise_exception (&error); /*FIXME don't raise here */
12546                                         }
12547                         }
12548                 }
12549         }
12550
12551         mono_save_custom_attrs (klass->image, klass, tb->cattrs);
12552
12553         /* 
12554          * we need to lock the domain because the lock will be taken inside
12555          * So, we need to keep the locking order correct.
12556          */
12557         mono_loader_lock ();
12558         mono_domain_lock (domain);
12559         if (klass->wastypebuilder) {
12560                 mono_domain_unlock (domain);
12561                 mono_loader_unlock ();
12562
12563                 res = mono_type_get_object_checked (mono_object_domain (tb), &klass->byval_arg, &error);
12564                 mono_error_raise_exception (&error); /* FIXME don't raise here */
12565
12566                 return res;
12567         }
12568         /*
12569          * Fields to set in klass:
12570          * the various flags: delegate/unicode/contextbound etc.
12571          */
12572         klass->flags = tb->attrs;
12573         klass->has_cctor = 1;
12574         klass->has_finalize = 1;
12575         klass->has_finalize_inited = 1;
12576
12577         mono_class_setup_parent (klass, klass->parent);
12578         /* fool mono_class_setup_supertypes */
12579         klass->supertypes = NULL;
12580         mono_class_setup_supertypes (klass);
12581         mono_class_setup_mono_type (klass);
12582
12583 #if 0
12584         if (!((MonoDynamicImage*)klass->image)->run) {
12585                 if (klass->generic_container) {
12586                         /* FIXME: The code below can't handle generic classes */
12587                         klass->wastypebuilder = TRUE;
12588                         mono_loader_unlock ();
12589                         mono_domain_unlock (domain);
12590
12591                         res = mono_type_get_object_checked (mono_object_domain (tb), &klass->byval_arg, &error);
12592                         mono_error_raise_exception (&error); /* FIXME don't raise here */
12593
12594                         return res;
12595                 }
12596         }
12597 #endif
12598
12599         /* enums are done right away */
12600         if (!klass->enumtype)
12601                 if (!ensure_runtime_vtable (klass, &error))
12602                         goto failure;
12603
12604         if (tb->subtypes) {
12605                 for (i = 0; i < mono_array_length (tb->subtypes); ++i) {
12606                         MonoReflectionTypeBuilder *subtb = mono_array_get (tb->subtypes, MonoReflectionTypeBuilder*, i);
12607                         mono_class_alloc_ext (klass);
12608                         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)));
12609                 }
12610         }
12611
12612         klass->nested_classes_inited = TRUE;
12613
12614         /* fields and object layout */
12615         if (klass->parent) {
12616                 if (!klass->parent->size_inited)
12617                         mono_class_init (klass->parent);
12618                 klass->instance_size = klass->parent->instance_size;
12619                 klass->sizes.class_size = 0;
12620                 klass->min_align = klass->parent->min_align;
12621                 /* if the type has no fields we won't call the field_setup
12622                  * routine which sets up klass->has_references.
12623                  */
12624                 klass->has_references |= klass->parent->has_references;
12625         } else {
12626                 klass->instance_size = sizeof (MonoObject);
12627                 klass->min_align = 1;
12628         }
12629
12630         /* FIXME: handle packing_size and instance_size */
12631         typebuilder_setup_fields (klass, &error);
12632         if (!mono_error_ok (&error))
12633                 goto failure;
12634         typebuilder_setup_properties (klass, &error);
12635         if (!mono_error_ok (&error))
12636                 goto failure;
12637
12638         typebuilder_setup_events (klass, &error);
12639         if (!mono_error_ok (&error))
12640                 goto failure;
12641
12642         klass->wastypebuilder = TRUE;
12643
12644         /* 
12645          * If we are a generic TypeBuilder, there might be instantiations in the type cache
12646          * which have type System.Reflection.MonoGenericClass, but after the type is created, 
12647          * we want to return normal System.MonoType objects, so clear these out from the cache.
12648          *
12649          * Together with this we must ensure the contents of all instances to match the created type.
12650          */
12651         if (domain->type_hash && klass->generic_container)
12652                 mono_g_hash_table_foreach_remove (domain->type_hash, remove_instantiations_of_and_ensure_contents, klass);
12653
12654         mono_domain_unlock (domain);
12655         mono_loader_unlock ();
12656
12657         if (klass->enumtype && !mono_class_is_valid_enum (klass)) {
12658                 mono_class_set_failure (klass, MONO_EXCEPTION_TYPE_LOAD, NULL);
12659                 mono_raise_exception (mono_get_exception_type_load (tb->name, NULL));
12660         }
12661
12662         res = mono_type_get_object_checked (mono_object_domain (tb), &klass->byval_arg, &error);
12663         mono_error_raise_exception (&error); /* FIXME don't raise here */
12664
12665         g_assert (res != (MonoReflectionType*)tb);
12666
12667         return res;
12668
12669 failure:
12670         mono_class_set_failure (klass, MONO_EXCEPTION_TYPE_LOAD, NULL);
12671         klass->wastypebuilder = TRUE;
12672         mono_domain_unlock (domain);
12673         mono_loader_unlock ();
12674         mono_error_raise_exception (&error);
12675         return NULL;
12676 }
12677
12678 void
12679 mono_reflection_initialize_generic_parameter (MonoReflectionGenericParam *gparam)
12680 {
12681         MonoGenericParamFull *param;
12682         MonoImage *image;
12683         MonoClass *pklass;
12684         MonoError error;
12685
12686         image = &gparam->tbuilder->module->dynamic_image->image;
12687
12688         param = mono_image_new0 (image, MonoGenericParamFull, 1);
12689
12690         param->info.name = mono_string_to_utf8_image (image, gparam->name, &error);
12691         g_assert (mono_error_ok (&error));
12692         param->param.num = gparam->index;
12693
12694         if (gparam->mbuilder) {
12695                 if (!gparam->mbuilder->generic_container) {
12696                         MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder *)gparam->mbuilder->type;
12697                         MonoClass *klass = mono_class_from_mono_type (mono_reflection_type_get_handle ((MonoReflectionType*)tb));
12698                         gparam->mbuilder->generic_container = (MonoGenericContainer *)mono_image_alloc0 (klass->image, sizeof (MonoGenericContainer));
12699                         gparam->mbuilder->generic_container->is_method = TRUE;
12700                         /* 
12701                          * Cannot set owner.method, since the MonoMethod is not created yet.
12702                          * Set the image field instead, so type_in_image () works.
12703                          */
12704                         gparam->mbuilder->generic_container->is_anonymous = TRUE;
12705                         gparam->mbuilder->generic_container->owner.image = klass->image;
12706                 }
12707                 param->param.owner = gparam->mbuilder->generic_container;
12708         } else if (gparam->tbuilder) {
12709                 if (!gparam->tbuilder->generic_container) {
12710                         MonoClass *klass = mono_class_from_mono_type (mono_reflection_type_get_handle ((MonoReflectionType*)gparam->tbuilder));
12711                         gparam->tbuilder->generic_container = (MonoGenericContainer *)mono_image_alloc0 (klass->image, sizeof (MonoGenericContainer));
12712                         gparam->tbuilder->generic_container->owner.klass = klass;
12713                 }
12714                 param->param.owner = gparam->tbuilder->generic_container;
12715         }
12716
12717         pklass = mono_class_from_generic_parameter_internal ((MonoGenericParam *) param);
12718
12719         gparam->type.type = &pklass->byval_arg;
12720
12721         mono_class_set_ref_info (pklass, gparam);
12722         mono_image_append_class_to_reflection_info_set (pklass);
12723 }
12724
12725 MonoArray *
12726 mono_reflection_sighelper_get_signature_local (MonoReflectionSigHelper *sig)
12727 {
12728         MonoError error;
12729         MonoReflectionModuleBuilder *module = sig->module;
12730         MonoDynamicImage *assembly = module != NULL ? module->dynamic_image : NULL;
12731         guint32 na = sig->arguments ? mono_array_length (sig->arguments) : 0;
12732         guint32 buflen, i;
12733         MonoArray *result;
12734         SigBuffer buf;
12735
12736         check_array_for_usertypes (sig->arguments, &error);
12737         mono_error_raise_exception (&error); /* FIXME: don't raise here */
12738
12739         sigbuffer_init (&buf, 32);
12740
12741         sigbuffer_add_value (&buf, 0x07);
12742         sigbuffer_add_value (&buf, na);
12743         if (assembly != NULL){
12744                 for (i = 0; i < na; ++i) {
12745                         MonoReflectionType *type = mono_array_get (sig->arguments, MonoReflectionType*, i);
12746                         encode_reflection_type (assembly, type, &buf);
12747                 }
12748         }
12749
12750         buflen = buf.p - buf.buf;
12751         result = mono_array_new (mono_domain_get (), mono_defaults.byte_class, buflen);
12752         memcpy (mono_array_addr (result, char, 0), buf.buf, buflen);
12753         sigbuffer_free (&buf);
12754
12755         return result;
12756 }
12757
12758 MonoArray *
12759 mono_reflection_sighelper_get_signature_field (MonoReflectionSigHelper *sig)
12760 {
12761         MonoError error;
12762         MonoDynamicImage *assembly = sig->module->dynamic_image;
12763         guint32 na = sig->arguments ? mono_array_length (sig->arguments) : 0;
12764         guint32 buflen, i;
12765         MonoArray *result;
12766         SigBuffer buf;
12767
12768         check_array_for_usertypes (sig->arguments, &error);
12769         mono_error_raise_exception (&error); /* FIXME: don't raise here */
12770
12771         sigbuffer_init (&buf, 32);
12772
12773         sigbuffer_add_value (&buf, 0x06);
12774         for (i = 0; i < na; ++i) {
12775                 MonoReflectionType *type = mono_array_get (sig->arguments, MonoReflectionType*, i);
12776                 encode_reflection_type (assembly, type, &buf);
12777         }
12778
12779         buflen = buf.p - buf.buf;
12780         result = mono_array_new (mono_domain_get (), mono_defaults.byte_class, buflen);
12781         memcpy (mono_array_addr (result, char, 0), buf.buf, buflen);
12782         sigbuffer_free (&buf);
12783
12784         return result;
12785 }
12786
12787 typedef struct {
12788         MonoMethod *handle;
12789         MonoDomain *domain;
12790 } DynamicMethodReleaseData;
12791
12792 /*
12793  * The runtime automatically clean up those after finalization.
12794 */      
12795 static MonoReferenceQueue *dynamic_method_queue;
12796
12797 static void
12798 free_dynamic_method (void *dynamic_method)
12799 {
12800         DynamicMethodReleaseData *data = (DynamicMethodReleaseData *)dynamic_method;
12801         MonoDomain *domain = data->domain;
12802         MonoMethod *method = data->handle;
12803         guint32 dis_link;
12804
12805         mono_domain_lock (domain);
12806         dis_link = (guint32)(size_t)g_hash_table_lookup (domain->method_to_dyn_method, method);
12807         g_hash_table_remove (domain->method_to_dyn_method, method);
12808         mono_domain_unlock (domain);
12809         g_assert (dis_link);
12810         mono_gchandle_free (dis_link);
12811
12812         mono_runtime_free_method (domain, method);
12813         g_free (data);
12814 }
12815
12816 void 
12817 mono_reflection_create_dynamic_method (MonoReflectionDynamicMethod *mb)
12818 {
12819         MonoReferenceQueue *queue;
12820         MonoMethod *handle;
12821         DynamicMethodReleaseData *release_data;
12822         ReflectionMethodBuilder rmb;
12823         MonoMethodSignature *sig;
12824         MonoClass *klass;
12825         MonoDomain *domain;
12826         GSList *l;
12827         int i;
12828
12829         if (mono_runtime_is_shutting_down ())
12830                 mono_raise_exception (mono_get_exception_invalid_operation (""));
12831
12832         if (!(queue = dynamic_method_queue)) {
12833                 mono_loader_lock ();
12834                 if (!(queue = dynamic_method_queue))
12835                         queue = dynamic_method_queue = mono_gc_reference_queue_new (free_dynamic_method);
12836                 mono_loader_unlock ();
12837         }
12838
12839         sig = dynamic_method_to_signature (mb);
12840
12841         reflection_methodbuilder_from_dynamic_method (&rmb, mb);
12842
12843         /*
12844          * Resolve references.
12845          */
12846         /* 
12847          * Every second entry in the refs array is reserved for storing handle_class,
12848          * which is needed by the ldtoken implementation in the JIT.
12849          */
12850         rmb.nrefs = mb->nrefs;
12851         rmb.refs = g_new0 (gpointer, mb->nrefs + 1);
12852         for (i = 0; i < mb->nrefs; i += 2) {
12853                 MonoClass *handle_class;
12854                 gpointer ref;
12855                 MonoObject *obj = mono_array_get (mb->refs, MonoObject*, i);
12856
12857                 if (strcmp (obj->vtable->klass->name, "DynamicMethod") == 0) {
12858                         MonoReflectionDynamicMethod *method = (MonoReflectionDynamicMethod*)obj;
12859                         /*
12860                          * The referenced DynamicMethod should already be created by the managed
12861                          * code, except in the case of circular references. In that case, we store
12862                          * method in the refs array, and fix it up later when the referenced 
12863                          * DynamicMethod is created.
12864                          */
12865                         if (method->mhandle) {
12866                                 ref = method->mhandle;
12867                         } else {
12868                                 /* FIXME: GC object stored in unmanaged memory */
12869                                 ref = method;
12870
12871                                 /* FIXME: GC object stored in unmanaged memory */
12872                                 method->referenced_by = g_slist_append (method->referenced_by, mb);
12873                         }
12874                         handle_class = mono_defaults.methodhandle_class;
12875                 } else {
12876                         MonoException *ex = NULL;
12877                         ref = resolve_object (mb->module->image, obj, &handle_class, NULL);
12878                         if (!ref)
12879                                 ex = mono_get_exception_type_load (NULL, NULL);
12880                         else if (mono_security_core_clr_enabled ())
12881                                 ex = mono_security_core_clr_ensure_dynamic_method_resolved_object (ref, handle_class);
12882
12883                         if (ex) {
12884                                 g_free (rmb.refs);
12885                                 mono_raise_exception (ex);
12886                                 return;
12887                         }
12888                 }
12889
12890                 rmb.refs [i] = ref; /* FIXME: GC object stored in unmanaged memory (change also resolve_object() signature) */
12891                 rmb.refs [i + 1] = handle_class;
12892         }               
12893
12894         klass = mb->owner ? mono_class_from_mono_type (mono_reflection_type_get_handle ((MonoReflectionType*)mb->owner)) : mono_defaults.object_class;
12895
12896         mb->mhandle = handle = reflection_methodbuilder_to_mono_method (klass, &rmb, sig);
12897         release_data = g_new (DynamicMethodReleaseData, 1);
12898         release_data->handle = handle;
12899         release_data->domain = mono_object_get_domain ((MonoObject*)mb);
12900         if (!mono_gc_reference_queue_add (queue, (MonoObject*)mb, release_data))
12901                 g_free (release_data);
12902
12903         /* Fix up refs entries pointing at us */
12904         for (l = mb->referenced_by; l; l = l->next) {
12905                 MonoReflectionDynamicMethod *method = (MonoReflectionDynamicMethod*)l->data;
12906                 MonoMethodWrapper *wrapper = (MonoMethodWrapper*)method->mhandle;
12907                 gpointer *data;
12908                 
12909                 g_assert (method->mhandle);
12910
12911                 data = (gpointer*)wrapper->method_data;
12912                 for (i = 0; i < GPOINTER_TO_UINT (data [0]); i += 2) {
12913                         if ((data [i + 1] == mb) && (data [i + 1 + 1] == mono_defaults.methodhandle_class))
12914                                 data [i + 1] = mb->mhandle;
12915                 }
12916         }
12917         g_slist_free (mb->referenced_by);
12918
12919         g_free (rmb.refs);
12920
12921         /* ilgen is no longer needed */
12922         mb->ilgen = NULL;
12923
12924         domain = mono_domain_get ();
12925         mono_domain_lock (domain);
12926         if (!domain->method_to_dyn_method)
12927                 domain->method_to_dyn_method = g_hash_table_new (NULL, NULL);
12928         g_hash_table_insert (domain->method_to_dyn_method, handle, (gpointer)(size_t)mono_gchandle_new_weakref ((MonoObject *)mb, TRUE));
12929         mono_domain_unlock (domain);
12930 }
12931
12932 #endif /* DISABLE_REFLECTION_EMIT */
12933
12934 /**
12935  * 
12936  * mono_reflection_is_valid_dynamic_token:
12937  * 
12938  * Returns TRUE if token is valid.
12939  * 
12940  */
12941 gboolean
12942 mono_reflection_is_valid_dynamic_token (MonoDynamicImage *image, guint32 token)
12943 {
12944         return lookup_dyn_token (image, token) != NULL;
12945 }
12946
12947 MonoMethodSignature *
12948 mono_reflection_lookup_signature (MonoImage *image, MonoMethod *method, guint32 token, MonoError *error)
12949 {
12950         MonoMethodSignature *sig;
12951         g_assert (image_is_dynamic (image));
12952
12953         mono_error_init (error);
12954
12955         sig = (MonoMethodSignature *)g_hash_table_lookup (((MonoDynamicImage*)image)->vararg_aux_hash, GUINT_TO_POINTER (token));
12956         if (sig)
12957                 return sig;
12958
12959         return mono_method_signature_checked (method, error);
12960 }
12961
12962 #ifndef DISABLE_REFLECTION_EMIT
12963
12964 /**
12965  * mono_reflection_lookup_dynamic_token:
12966  *
12967  * Finish the Builder object pointed to by TOKEN and return the corresponding
12968  * runtime structure. If HANDLE_CLASS is not NULL, it is set to the class required by 
12969  * mono_ldtoken. If valid_token is TRUE, assert if it is not found in the token->object
12970  * mapping table.
12971  *
12972  * LOCKING: Take the loader lock
12973  */
12974 gpointer
12975 mono_reflection_lookup_dynamic_token (MonoImage *image, guint32 token, gboolean valid_token, MonoClass **handle_class, MonoGenericContext *context)
12976 {
12977         MonoDynamicImage *assembly = (MonoDynamicImage*)image;
12978         MonoObject *obj;
12979         MonoClass *klass;
12980
12981         obj = lookup_dyn_token (assembly, token);
12982         if (!obj) {
12983                 if (valid_token)
12984                         g_error ("Could not find required dynamic token 0x%08x", token);
12985                 else
12986                         return NULL;
12987         }
12988
12989         if (!handle_class)
12990                 handle_class = &klass;
12991         return resolve_object (image, obj, handle_class, context);
12992 }
12993
12994 /*
12995  * ensure_complete_type:
12996  *
12997  *   Ensure that KLASS is completed if it is a dynamic type, or references
12998  * dynamic types.
12999  */
13000 static void
13001 ensure_complete_type (MonoClass *klass)
13002 {
13003         MonoError error;
13004
13005         if (image_is_dynamic (klass->image) && !klass->wastypebuilder && mono_class_get_ref_info (klass)) {
13006                 MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder *)mono_class_get_ref_info (klass);
13007
13008                 mono_domain_try_type_resolve_checked (mono_domain_get (), NULL, (MonoObject*)tb, &error);
13009                 mono_error_raise_exception (&error); /* FIXME don't raise here */
13010
13011                 // Asserting here could break a lot of code
13012                 //g_assert (klass->wastypebuilder);
13013         }
13014
13015         if (klass->generic_class) {
13016                 MonoGenericInst *inst = klass->generic_class->context.class_inst;
13017                 int i;
13018
13019                 for (i = 0; i < inst->type_argc; ++i) {
13020                         ensure_complete_type (mono_class_from_mono_type (inst->type_argv [i]));
13021                 }
13022         }
13023 }
13024
13025 static gpointer
13026 resolve_object (MonoImage *image, MonoObject *obj, MonoClass **handle_class, MonoGenericContext *context)
13027 {
13028         MonoError error;
13029         gpointer result = NULL;
13030
13031         if (strcmp (obj->vtable->klass->name, "String") == 0) {
13032                 result = mono_string_intern_checked ((MonoString*)obj, &error);
13033                 mono_error_raise_exception (&error); /* FIXME don't raise here */
13034                 *handle_class = mono_defaults.string_class;
13035                 g_assert (result);
13036         } else if (strcmp (obj->vtable->klass->name, "MonoType") == 0) {
13037                 MonoType *type = mono_reflection_type_get_handle ((MonoReflectionType*)obj);
13038                 MonoClass *mc = mono_class_from_mono_type (type);
13039                 if (!mono_class_init (mc))
13040                         mono_raise_exception (mono_class_get_exception_for_failure (mc));
13041
13042                 if (context) {
13043                         MonoType *inflated = mono_class_inflate_generic_type_checked (type, context, &error);
13044                         mono_error_raise_exception (&error); /* FIXME don't raise here */
13045
13046                         result = mono_class_from_mono_type (inflated);
13047                         mono_metadata_free_type (inflated);
13048                 } else {
13049                         result = mono_class_from_mono_type (type);
13050                 }
13051                 *handle_class = mono_defaults.typehandle_class;
13052                 g_assert (result);
13053         } else if (strcmp (obj->vtable->klass->name, "MonoMethod") == 0 ||
13054                    strcmp (obj->vtable->klass->name, "MonoCMethod") == 0 ||
13055                    strcmp (obj->vtable->klass->name, "MonoGenericCMethod") == 0 ||
13056                    strcmp (obj->vtable->klass->name, "MonoGenericMethod") == 0) {
13057                 result = ((MonoReflectionMethod*)obj)->method;
13058                 if (context) {
13059                         MonoError error;
13060                         result = mono_class_inflate_generic_method_checked ((MonoMethod *)result, context, &error);
13061                         g_assert (mono_error_ok (&error)); /* FIXME don't swallow the error */
13062                 }
13063                 *handle_class = mono_defaults.methodhandle_class;
13064                 g_assert (result);
13065         } else if (strcmp (obj->vtable->klass->name, "MethodBuilder") == 0) {
13066                 MonoReflectionMethodBuilder *mb = (MonoReflectionMethodBuilder*)obj;
13067                 result = mb->mhandle;
13068                 if (!result) {
13069                         /* Type is not yet created */
13070                         MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder*)mb->type;
13071
13072                         mono_domain_try_type_resolve_checked (mono_domain_get (), NULL, (MonoObject*)tb, &error);
13073                         mono_error_raise_exception (&error); /* FIXME don't raise here */
13074
13075                         /*
13076                          * Hopefully this has been filled in by calling CreateType() on the
13077                          * TypeBuilder.
13078                          */
13079                         /*
13080                          * TODO: This won't work if the application finishes another 
13081                          * TypeBuilder instance instead of this one.
13082                          */
13083                         result = mb->mhandle;
13084                 }
13085                 if (context) {
13086                         MonoError error;
13087                         result = mono_class_inflate_generic_method_checked ((MonoMethod *)result, context, &error);
13088                         g_assert (mono_error_ok (&error)); /* FIXME don't swallow the error */
13089                 }
13090                 *handle_class = mono_defaults.methodhandle_class;
13091         } else if (strcmp (obj->vtable->klass->name, "ConstructorBuilder") == 0) {
13092                 MonoReflectionCtorBuilder *cb = (MonoReflectionCtorBuilder*)obj;
13093
13094                 result = cb->mhandle;
13095                 if (!result) {
13096                         MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder*)cb->type;
13097
13098                         mono_domain_try_type_resolve_checked (mono_domain_get (), NULL, (MonoObject*)tb, &error);
13099                         mono_error_raise_exception (&error); /* FIXME don't raise here */
13100                         result = cb->mhandle;
13101                 }
13102                 if (context) {
13103                         MonoError error;
13104                         result = mono_class_inflate_generic_method_checked ((MonoMethod *)result, context, &error);
13105                         g_assert (mono_error_ok (&error)); /* FIXME don't swallow the error */
13106                 }
13107                 *handle_class = mono_defaults.methodhandle_class;
13108         } else if (strcmp (obj->vtable->klass->name, "MonoField") == 0) {
13109                 MonoClassField *field = ((MonoReflectionField*)obj)->field;
13110
13111                 ensure_complete_type (field->parent);
13112                 if (context) {
13113                         MonoType *inflated = mono_class_inflate_generic_type_checked (&field->parent->byval_arg, context, &error);
13114                         mono_error_raise_exception (&error); /* FIXME don't raise here */
13115
13116                         MonoClass *klass = mono_class_from_mono_type (inflated);
13117                         MonoClassField *inflated_field;
13118                         gpointer iter = NULL;
13119                         mono_metadata_free_type (inflated);
13120                         while ((inflated_field = mono_class_get_fields (klass, &iter))) {
13121                                 if (!strcmp (field->name, inflated_field->name))
13122                                         break;
13123                         }
13124                         g_assert (inflated_field && !strcmp (field->name, inflated_field->name));
13125                         result = inflated_field;
13126                 } else {
13127                         result = field;
13128                 }
13129                 *handle_class = mono_defaults.fieldhandle_class;
13130                 g_assert (result);
13131         } else if (strcmp (obj->vtable->klass->name, "FieldBuilder") == 0) {
13132                 MonoReflectionFieldBuilder *fb = (MonoReflectionFieldBuilder*)obj;
13133                 result = fb->handle;
13134
13135                 if (!result) {
13136                         MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder*)fb->typeb;
13137
13138                         mono_domain_try_type_resolve_checked (mono_domain_get (), NULL, (MonoObject*)tb, &error);
13139                         mono_error_raise_exception (&error); /* FIXME don't raise here */
13140                         result = fb->handle;
13141                 }
13142
13143                 if (fb->handle && fb->handle->parent->generic_container) {
13144                         MonoClass *klass = fb->handle->parent;
13145                         MonoType *type = mono_class_inflate_generic_type_checked (&klass->byval_arg, context, &error);
13146                         mono_error_raise_exception (&error); /* FIXME don't raise here */
13147
13148                         MonoClass *inflated = mono_class_from_mono_type (type);
13149
13150                         result = mono_class_get_field_from_name (inflated, mono_field_get_name (fb->handle));
13151                         g_assert (result);
13152                         mono_metadata_free_type (type);
13153                 }
13154                 *handle_class = mono_defaults.fieldhandle_class;
13155         } else if (strcmp (obj->vtable->klass->name, "TypeBuilder") == 0) {
13156                 MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder*)obj;
13157                 MonoType *type = mono_reflection_type_get_handle ((MonoReflectionType*)tb); 
13158                 MonoClass *klass;
13159
13160                 klass = type->data.klass;
13161                 if (klass->wastypebuilder) {
13162                         /* Already created */
13163                         result = klass;
13164                 }
13165                 else {
13166                         mono_domain_try_type_resolve_checked (mono_domain_get (), NULL, (MonoObject*)tb, &error);
13167                         mono_error_raise_exception (&error); /* FIXME don't raise here */
13168                         result = type->data.klass;
13169                         g_assert (result);
13170                 }
13171                 *handle_class = mono_defaults.typehandle_class;
13172         } else if (strcmp (obj->vtable->klass->name, "SignatureHelper") == 0) {
13173                 MonoReflectionSigHelper *helper = (MonoReflectionSigHelper*)obj;
13174                 MonoMethodSignature *sig;
13175                 int nargs, i;
13176
13177                 if (helper->arguments)
13178                         nargs = mono_array_length (helper->arguments);
13179                 else
13180                         nargs = 0;
13181
13182                 sig = mono_metadata_signature_alloc (image, nargs);
13183                 sig->explicit_this = helper->call_conv & 64 ? 1 : 0;
13184                 sig->hasthis = helper->call_conv & 32 ? 1 : 0;
13185
13186                 if (helper->unmanaged_call_conv) { /* unmanaged */
13187                         sig->call_convention = helper->unmanaged_call_conv - 1;
13188                         sig->pinvoke = TRUE;
13189                 } else if (helper->call_conv & 0x02) {
13190                         sig->call_convention = MONO_CALL_VARARG;
13191                 } else {
13192                         sig->call_convention = MONO_CALL_DEFAULT;
13193                 }
13194
13195                 sig->param_count = nargs;
13196                 /* TODO: Copy type ? */
13197                 sig->ret = helper->return_type->type;
13198                 for (i = 0; i < nargs; ++i)
13199                         sig->params [i] = mono_type_array_get_and_resolve (helper->arguments, i);
13200
13201                 result = sig;
13202                 *handle_class = NULL;
13203         } else if (strcmp (obj->vtable->klass->name, "DynamicMethod") == 0) {
13204                 MonoReflectionDynamicMethod *method = (MonoReflectionDynamicMethod*)obj;
13205                 /* Already created by the managed code */
13206                 g_assert (method->mhandle);
13207                 result = method->mhandle;
13208                 *handle_class = mono_defaults.methodhandle_class;
13209         } else if (strcmp (obj->vtable->klass->name, "GenericTypeParameterBuilder") == 0) {
13210                 MonoType *type = mono_reflection_type_get_handle ((MonoReflectionType*)obj);
13211                 type = mono_class_inflate_generic_type_checked (type, context, &error);
13212                 mono_error_raise_exception (&error); /* FIXME don't raise here */
13213
13214                 result = mono_class_from_mono_type (type);
13215                 *handle_class = mono_defaults.typehandle_class;
13216                 g_assert (result);
13217                 mono_metadata_free_type (type);
13218         } else if (strcmp (obj->vtable->klass->name, "MonoGenericClass") == 0) {
13219                 MonoType *type = mono_reflection_type_get_handle ((MonoReflectionType*)obj);
13220                 type = mono_class_inflate_generic_type_checked (type, context, &error);
13221                 mono_error_raise_exception (&error); /* FIXME don't raise here */
13222
13223                 result = mono_class_from_mono_type (type);
13224                 *handle_class = mono_defaults.typehandle_class;
13225                 g_assert (result);
13226                 mono_metadata_free_type (type);
13227         } else if (strcmp (obj->vtable->klass->name, "FieldOnTypeBuilderInst") == 0) {
13228                 MonoReflectionFieldOnTypeBuilderInst *f = (MonoReflectionFieldOnTypeBuilderInst*)obj;
13229                 MonoClass *inflated;
13230                 MonoType *type;
13231                 MonoClassField *field;
13232
13233                 if (is_sre_field_builder (mono_object_class (f->fb)))
13234                         field = ((MonoReflectionFieldBuilder*)f->fb)->handle;
13235                 else if (is_sr_mono_field (mono_object_class (f->fb)))
13236                         field = ((MonoReflectionField*)f->fb)->field;
13237                 else
13238                         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)));
13239
13240                 type = mono_class_inflate_generic_type_checked (mono_reflection_type_get_handle ((MonoReflectionType*)f->inst), context, &error);
13241                 mono_error_raise_exception (&error); /* FIXME don't raise here */
13242
13243                 inflated = mono_class_from_mono_type (type);
13244
13245                 result = field = mono_class_get_field_from_name (inflated, mono_field_get_name (field));
13246                 ensure_complete_type (field->parent);
13247                 g_assert (result);
13248                 mono_metadata_free_type (type);
13249                 *handle_class = mono_defaults.fieldhandle_class;
13250         } else if (strcmp (obj->vtable->klass->name, "ConstructorOnTypeBuilderInst") == 0) {
13251                 MonoReflectionCtorOnTypeBuilderInst *c = (MonoReflectionCtorOnTypeBuilderInst*)obj;
13252                 MonoType *type = mono_class_inflate_generic_type_checked (mono_reflection_type_get_handle ((MonoReflectionType*)c->inst), context, &error);
13253                 mono_error_raise_exception (&error); /* FIXME don't raise here */
13254
13255                 MonoClass *inflated_klass = mono_class_from_mono_type (type);
13256                 MonoMethod *method;
13257
13258                 if (is_sre_ctor_builder (mono_object_class (c->cb)))
13259                         method = ((MonoReflectionCtorBuilder *)c->cb)->mhandle;
13260                 else if (is_sr_mono_cmethod (mono_object_class (c->cb)))
13261                         method = ((MonoReflectionMethod *)c->cb)->method;
13262                 else
13263                         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)));
13264
13265                 result = inflate_mono_method (inflated_klass, method, (MonoObject*)c->cb);
13266                 *handle_class = mono_defaults.methodhandle_class;
13267                 mono_metadata_free_type (type);
13268         } else if (strcmp (obj->vtable->klass->name, "MethodOnTypeBuilderInst") == 0) {
13269                 MonoReflectionMethodOnTypeBuilderInst *m = (MonoReflectionMethodOnTypeBuilderInst*)obj;
13270                 if (m->method_args) {
13271                         result = mono_reflection_method_on_tb_inst_get_handle (m, &error);
13272                         mono_error_raise_exception (&error); /* FIXME don't raise here */
13273                         if (context) {
13274                                 result = mono_class_inflate_generic_method_checked ((MonoMethod *)result, context, &error);
13275                                 mono_error_assert_ok (&error);
13276                         }
13277                 } else {
13278                         MonoType *type = mono_class_inflate_generic_type_checked (mono_reflection_type_get_handle ((MonoReflectionType*)m->inst), context, &error);
13279                         mono_error_raise_exception (&error); /* FIXME don't raise here */
13280
13281                         MonoClass *inflated_klass = mono_class_from_mono_type (type);
13282                         MonoMethod *method;
13283
13284                         if (is_sre_method_builder (mono_object_class (m->mb)))
13285                                 method = ((MonoReflectionMethodBuilder *)m->mb)->mhandle;
13286                         else if (is_sr_mono_method (mono_object_class (m->mb)))
13287                                 method = ((MonoReflectionMethod *)m->mb)->method;
13288                         else
13289                                 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)));
13290
13291                         result = inflate_mono_method (inflated_klass, method, (MonoObject*)m->mb);
13292                         mono_metadata_free_type (type);
13293                 }
13294                 *handle_class = mono_defaults.methodhandle_class;
13295         } else if (strcmp (obj->vtable->klass->name, "MonoArrayMethod") == 0) {
13296                 MonoReflectionArrayMethod *m = (MonoReflectionArrayMethod*)obj;
13297                 MonoType *mtype;
13298                 MonoClass *klass;
13299                 MonoMethod *method;
13300                 gpointer iter;
13301                 char *name;
13302
13303                 mtype = mono_reflection_type_get_handle (m->parent);
13304                 klass = mono_class_from_mono_type (mtype);
13305
13306                 /* Find the method */
13307
13308                 name = mono_string_to_utf8 (m->name);
13309                 iter = NULL;
13310                 while ((method = mono_class_get_methods (klass, &iter))) {
13311                         if (!strcmp (method->name, name))
13312                                 break;
13313                 }
13314                 g_free (name);
13315
13316                 // FIXME:
13317                 g_assert (method);
13318                 // FIXME: Check parameters/return value etc. match
13319
13320                 result = method;
13321                 *handle_class = mono_defaults.methodhandle_class;
13322         } else if (is_sre_array (mono_object_get_class(obj)) ||
13323                                 is_sre_byref (mono_object_get_class(obj)) ||
13324                                 is_sre_pointer (mono_object_get_class(obj))) {
13325                 MonoReflectionType *ref_type = (MonoReflectionType *)obj;
13326                 MonoType *type = mono_reflection_type_get_handle (ref_type);
13327
13328                 if (context) {
13329                         MonoType *inflated = mono_class_inflate_generic_type_checked (type, context, &error);
13330                         mono_error_raise_exception (&error); /* FIXME don't raise here */
13331
13332                         result = mono_class_from_mono_type (inflated);
13333                         mono_metadata_free_type (inflated);
13334                 } else {
13335                         result = mono_class_from_mono_type (type);
13336                 }
13337                 *handle_class = mono_defaults.typehandle_class;
13338         } else {
13339                 g_print ("%s\n", obj->vtable->klass->name);
13340                 g_assert_not_reached ();
13341         }
13342         return result;
13343 }
13344
13345 #else /* DISABLE_REFLECTION_EMIT */
13346
13347 MonoArray*
13348 mono_reflection_get_custom_attrs_blob (MonoReflectionAssembly *assembly, MonoObject *ctor, MonoArray *ctorArgs, MonoArray *properties, MonoArray *propValues, MonoArray *fields, MonoArray* fieldValues) 
13349 {
13350         g_assert_not_reached ();
13351         return NULL;
13352 }
13353
13354 void
13355 mono_reflection_setup_internal_class (MonoReflectionTypeBuilder *tb)
13356 {
13357         g_assert_not_reached ();
13358 }
13359
13360 void
13361 mono_reflection_setup_generic_class (MonoReflectionTypeBuilder *tb)
13362 {
13363         g_assert_not_reached ();
13364 }
13365
13366 void
13367 mono_reflection_create_generic_class (MonoReflectionTypeBuilder *tb)
13368 {
13369         g_assert_not_reached ();
13370 }
13371
13372 void
13373 mono_reflection_create_internal_class (MonoReflectionTypeBuilder *tb)
13374 {
13375         g_assert_not_reached ();
13376 }
13377
13378 void
13379 mono_image_basic_init (MonoReflectionAssemblyBuilder *assemblyb)
13380 {
13381         g_error ("This mono runtime was configured with --enable-minimal=reflection_emit, so System.Reflection.Emit is not supported.");
13382 }
13383
13384 void
13385 mono_image_module_basic_init (MonoReflectionModuleBuilder *moduleb)
13386 {
13387         g_assert_not_reached ();
13388 }
13389
13390 void
13391 mono_image_set_wrappers_type (MonoReflectionModuleBuilder *moduleb, MonoReflectionType *type)
13392 {
13393         g_assert_not_reached ();
13394 }
13395
13396 MonoReflectionModule *
13397 mono_image_load_module_dynamic (MonoReflectionAssemblyBuilder *ab, MonoString *fileName)
13398 {
13399         g_assert_not_reached ();
13400         return NULL;
13401 }
13402
13403 guint32
13404 mono_image_insert_string (MonoReflectionModuleBuilder *module, MonoString *str)
13405 {
13406         g_assert_not_reached ();
13407         return 0;
13408 }
13409
13410 guint32
13411 mono_image_create_method_token (MonoDynamicImage *assembly, MonoObject *obj, MonoArray *opt_param_types, MonoError *error)
13412 {
13413         g_assert_not_reached ();
13414         return 0;
13415 }
13416
13417 guint32
13418 mono_image_create_token (MonoDynamicImage *assembly, MonoObject *obj, 
13419                          gboolean create_open_instance, gboolean register_token, MonoError *error)
13420 {
13421         g_assert_not_reached ();
13422         return 0;
13423 }
13424
13425 void
13426 mono_image_register_token (MonoDynamicImage *assembly, guint32 token, MonoObject *obj)
13427 {
13428 }
13429
13430 void
13431 mono_reflection_generic_class_initialize (MonoReflectionGenericClass *type, MonoArray *fields)
13432 {
13433         g_assert_not_reached ();
13434 }
13435
13436 void
13437 mono_reflection_get_dynamic_overrides (MonoClass *klass, MonoMethod ***overrides, int *num_overrides)
13438 {
13439         *overrides = NULL;
13440         *num_overrides = 0;
13441 }
13442
13443 MonoReflectionEvent *
13444 mono_reflection_event_builder_get_event_info (MonoReflectionTypeBuilder *tb, MonoReflectionEventBuilder *eb)
13445 {
13446         g_assert_not_reached ();
13447         return NULL;
13448 }
13449
13450 MonoReflectionType*
13451 mono_reflection_create_runtime_class (MonoReflectionTypeBuilder *tb)
13452 {
13453         g_assert_not_reached ();
13454         return NULL;
13455 }
13456
13457 void
13458 mono_reflection_initialize_generic_parameter (MonoReflectionGenericParam *gparam)
13459 {
13460         g_assert_not_reached ();
13461 }
13462
13463 MonoArray *
13464 mono_reflection_sighelper_get_signature_local (MonoReflectionSigHelper *sig)
13465 {
13466         g_assert_not_reached ();
13467         return NULL;
13468 }
13469
13470 MonoArray *
13471 mono_reflection_sighelper_get_signature_field (MonoReflectionSigHelper *sig)
13472 {
13473         g_assert_not_reached ();
13474         return NULL;
13475 }
13476
13477 void 
13478 mono_reflection_create_dynamic_method (MonoReflectionDynamicMethod *mb)
13479 {
13480 }
13481
13482 gpointer
13483 mono_reflection_lookup_dynamic_token (MonoImage *image, guint32 token, gboolean valid_token, MonoClass **handle_class, MonoGenericContext *context)
13484 {
13485         return NULL;
13486 }
13487
13488 MonoType*
13489 mono_reflection_type_get_handle (MonoReflectionType* ref)
13490 {
13491         if (!ref)
13492                 return NULL;
13493         return ref->type;
13494 }
13495
13496 void
13497 mono_reflection_free_dynamic_generic_class (MonoGenericClass *gclass)
13498 {
13499         g_assert_not_reached ();
13500 }
13501
13502 #endif /* DISABLE_REFLECTION_EMIT */
13503
13504 /* SECURITY_ACTION_* are defined in mono/metadata/tabledefs.h */
13505 const static guint32 declsec_flags_map[] = {
13506         0x00000000,                                     /* empty */
13507         MONO_DECLSEC_FLAG_REQUEST,                      /* SECURITY_ACTION_REQUEST                      (x01) */
13508         MONO_DECLSEC_FLAG_DEMAND,                       /* SECURITY_ACTION_DEMAND                       (x02) */
13509         MONO_DECLSEC_FLAG_ASSERT,                       /* SECURITY_ACTION_ASSERT                       (x03) */
13510         MONO_DECLSEC_FLAG_DENY,                         /* SECURITY_ACTION_DENY                         (x04) */
13511         MONO_DECLSEC_FLAG_PERMITONLY,                   /* SECURITY_ACTION_PERMITONLY                   (x05) */
13512         MONO_DECLSEC_FLAG_LINKDEMAND,                   /* SECURITY_ACTION_LINKDEMAND                   (x06) */
13513         MONO_DECLSEC_FLAG_INHERITANCEDEMAND,            /* SECURITY_ACTION_INHERITANCEDEMAND            (x07) */
13514         MONO_DECLSEC_FLAG_REQUEST_MINIMUM,              /* SECURITY_ACTION_REQUEST_MINIMUM              (x08) */
13515         MONO_DECLSEC_FLAG_REQUEST_OPTIONAL,             /* SECURITY_ACTION_REQUEST_OPTIONAL             (x09) */
13516         MONO_DECLSEC_FLAG_REQUEST_REFUSE,               /* SECURITY_ACTION_REQUEST_REFUSE               (x0A) */
13517         MONO_DECLSEC_FLAG_PREJIT_GRANT,                 /* SECURITY_ACTION_PREJIT_GRANT                 (x0B) */
13518         MONO_DECLSEC_FLAG_PREJIT_DENY,                  /* SECURITY_ACTION_PREJIT_DENY                  (x0C) */
13519         MONO_DECLSEC_FLAG_NONCAS_DEMAND,                /* SECURITY_ACTION_NONCAS_DEMAND                (x0D) */
13520         MONO_DECLSEC_FLAG_NONCAS_LINKDEMAND,            /* SECURITY_ACTION_NONCAS_LINKDEMAND            (x0E) */
13521         MONO_DECLSEC_FLAG_NONCAS_INHERITANCEDEMAND,     /* SECURITY_ACTION_NONCAS_INHERITANCEDEMAND     (x0F) */
13522         MONO_DECLSEC_FLAG_LINKDEMAND_CHOICE,            /* SECURITY_ACTION_LINKDEMAND_CHOICE            (x10) */
13523         MONO_DECLSEC_FLAG_INHERITANCEDEMAND_CHOICE,     /* SECURITY_ACTION_INHERITANCEDEMAND_CHOICE     (x11) */
13524         MONO_DECLSEC_FLAG_DEMAND_CHOICE,                /* SECURITY_ACTION_DEMAND_CHOICE                (x12) */
13525 };
13526
13527 /*
13528  * Returns flags that includes all available security action associated to the handle.
13529  * @token: metadata token (either for a class or a method)
13530  * @image: image where resides the metadata.
13531  */
13532 static guint32
13533 mono_declsec_get_flags (MonoImage *image, guint32 token)
13534 {
13535         int index = mono_metadata_declsec_from_index (image, token);
13536         MonoTableInfo *t = &image->tables [MONO_TABLE_DECLSECURITY];
13537         guint32 result = 0;
13538         guint32 action;
13539         int i;
13540
13541         /* HasSecurity can be present for other, not specially encoded, attributes,
13542            e.g. SuppressUnmanagedCodeSecurityAttribute */
13543         if (index < 0)
13544                 return 0;
13545
13546         for (i = index; i < t->rows; i++) {
13547                 guint32 cols [MONO_DECL_SECURITY_SIZE];
13548
13549                 mono_metadata_decode_row (t, i, cols, MONO_DECL_SECURITY_SIZE);
13550                 if (cols [MONO_DECL_SECURITY_PARENT] != token)
13551                         break;
13552
13553                 action = cols [MONO_DECL_SECURITY_ACTION];
13554                 if ((action >= MONO_DECLSEC_ACTION_MIN) && (action <= MONO_DECLSEC_ACTION_MAX)) {
13555                         result |= declsec_flags_map [action];
13556                 } else {
13557                         g_assert_not_reached ();
13558                 }
13559         }
13560         return result;
13561 }
13562
13563 /*
13564  * Get the security actions (in the form of flags) associated with the specified method.
13565  *
13566  * @method: The method for which we want the declarative security flags.
13567  * Return the declarative security flags for the method (only).
13568  *
13569  * Note: To keep MonoMethod size down we do not cache the declarative security flags
13570  *       (except for the stack modifiers which are kept in the MonoJitInfo structure)
13571  */
13572 guint32
13573 mono_declsec_flags_from_method (MonoMethod *method)
13574 {
13575         if (method->flags & METHOD_ATTRIBUTE_HAS_SECURITY) {
13576                 /* FIXME: No cache (for the moment) */
13577                 guint32 idx = mono_method_get_index (method);
13578                 idx <<= MONO_HAS_DECL_SECURITY_BITS;
13579                 idx |= MONO_HAS_DECL_SECURITY_METHODDEF;
13580                 return mono_declsec_get_flags (method->klass->image, idx);
13581         }
13582         return 0;
13583 }
13584
13585 /*
13586  * Get the security actions (in the form of flags) associated with the specified class.
13587  *
13588  * @klass: The class for which we want the declarative security flags.
13589  * Return the declarative security flags for the class.
13590  *
13591  * Note: We cache the flags inside the MonoClass structure as this will get 
13592  *       called very often (at least for each method).
13593  */
13594 guint32
13595 mono_declsec_flags_from_class (MonoClass *klass)
13596 {
13597         if (klass->flags & TYPE_ATTRIBUTE_HAS_SECURITY) {
13598                 if (!klass->ext || !klass->ext->declsec_flags) {
13599                         guint32 idx;
13600
13601                         idx = mono_metadata_token_index (klass->type_token);
13602                         idx <<= MONO_HAS_DECL_SECURITY_BITS;
13603                         idx |= MONO_HAS_DECL_SECURITY_TYPEDEF;
13604                         mono_loader_lock ();
13605                         mono_class_alloc_ext (klass);
13606                         mono_loader_unlock ();
13607                         /* we cache the flags on classes */
13608                         klass->ext->declsec_flags = mono_declsec_get_flags (klass->image, idx);
13609                 }
13610                 return klass->ext->declsec_flags;
13611         }
13612         return 0;
13613 }
13614
13615 /*
13616  * Get the security actions (in the form of flags) associated with the specified assembly.
13617  *
13618  * @assembly: The assembly for which we want the declarative security flags.
13619  * Return the declarative security flags for the assembly.
13620  */
13621 guint32
13622 mono_declsec_flags_from_assembly (MonoAssembly *assembly)
13623 {
13624         guint32 idx = 1; /* there is only one assembly */
13625         idx <<= MONO_HAS_DECL_SECURITY_BITS;
13626         idx |= MONO_HAS_DECL_SECURITY_ASSEMBLY;
13627         return mono_declsec_get_flags (assembly->image, idx);
13628 }
13629
13630
13631 /*
13632  * Fill actions for the specific index (which may either be an encoded class token or
13633  * an encoded method token) from the metadata image.
13634  * Returns TRUE if some actions requiring code generation are present, FALSE otherwise.
13635  */
13636 static MonoBoolean
13637 fill_actions_from_index (MonoImage *image, guint32 token, MonoDeclSecurityActions* actions,
13638         guint32 id_std, guint32 id_noncas, guint32 id_choice)
13639 {
13640         MonoBoolean result = FALSE;
13641         MonoTableInfo *t;
13642         guint32 cols [MONO_DECL_SECURITY_SIZE];
13643         int index = mono_metadata_declsec_from_index (image, token);
13644         int i;
13645
13646         t  = &image->tables [MONO_TABLE_DECLSECURITY];
13647         for (i = index; i < t->rows; i++) {
13648                 mono_metadata_decode_row (t, i, cols, MONO_DECL_SECURITY_SIZE);
13649
13650                 if (cols [MONO_DECL_SECURITY_PARENT] != token)
13651                         return result;
13652
13653                 /* if present only replace (class) permissions with method permissions */
13654                 /* if empty accept either class or method permissions */
13655                 if (cols [MONO_DECL_SECURITY_ACTION] == id_std) {
13656                         if (!actions->demand.blob) {
13657                                 const char *blob = mono_metadata_blob_heap (image, cols [MONO_DECL_SECURITY_PERMISSIONSET]);
13658                                 actions->demand.index = cols [MONO_DECL_SECURITY_PERMISSIONSET];
13659                                 actions->demand.blob = (char*) (blob + 2);
13660                                 actions->demand.size = mono_metadata_decode_blob_size (blob, &blob);
13661                                 result = TRUE;
13662                         }
13663                 } else if (cols [MONO_DECL_SECURITY_ACTION] == id_noncas) {
13664                         if (!actions->noncasdemand.blob) {
13665                                 const char *blob = mono_metadata_blob_heap (image, cols [MONO_DECL_SECURITY_PERMISSIONSET]);
13666                                 actions->noncasdemand.index = cols [MONO_DECL_SECURITY_PERMISSIONSET];
13667                                 actions->noncasdemand.blob = (char*) (blob + 2);
13668                                 actions->noncasdemand.size = mono_metadata_decode_blob_size (blob, &blob);
13669                                 result = TRUE;
13670                         }
13671                 } else if (cols [MONO_DECL_SECURITY_ACTION] == id_choice) {
13672                         if (!actions->demandchoice.blob) {
13673                                 const char *blob = mono_metadata_blob_heap (image, cols [MONO_DECL_SECURITY_PERMISSIONSET]);
13674                                 actions->demandchoice.index = cols [MONO_DECL_SECURITY_PERMISSIONSET];
13675                                 actions->demandchoice.blob = (char*) (blob + 2);
13676                                 actions->demandchoice.size = mono_metadata_decode_blob_size (blob, &blob);
13677                                 result = TRUE;
13678                         }
13679                 }
13680         }
13681
13682         return result;
13683 }
13684
13685 static MonoBoolean
13686 mono_declsec_get_class_demands_params (MonoClass *klass, MonoDeclSecurityActions* demands, 
13687         guint32 id_std, guint32 id_noncas, guint32 id_choice)
13688 {
13689         guint32 idx = mono_metadata_token_index (klass->type_token);
13690         idx <<= MONO_HAS_DECL_SECURITY_BITS;
13691         idx |= MONO_HAS_DECL_SECURITY_TYPEDEF;
13692         return fill_actions_from_index (klass->image, idx, demands, id_std, id_noncas, id_choice);
13693 }
13694
13695 static MonoBoolean
13696 mono_declsec_get_method_demands_params (MonoMethod *method, MonoDeclSecurityActions* demands, 
13697         guint32 id_std, guint32 id_noncas, guint32 id_choice)
13698 {
13699         guint32 idx = mono_method_get_index (method);
13700         idx <<= MONO_HAS_DECL_SECURITY_BITS;
13701         idx |= MONO_HAS_DECL_SECURITY_METHODDEF;
13702         return fill_actions_from_index (method->klass->image, idx, demands, id_std, id_noncas, id_choice);
13703 }
13704
13705 /*
13706  * Collect all actions (that requires to generate code in mini) assigned for
13707  * the specified method.
13708  * Note: Don't use the content of actions if the function return FALSE.
13709  */
13710 MonoBoolean
13711 mono_declsec_get_demands (MonoMethod *method, MonoDeclSecurityActions* demands)
13712 {
13713         guint32 mask = MONO_DECLSEC_FLAG_DEMAND | MONO_DECLSEC_FLAG_NONCAS_DEMAND | 
13714                 MONO_DECLSEC_FLAG_DEMAND_CHOICE;
13715         MonoBoolean result = FALSE;
13716         guint32 flags;
13717
13718         /* quick exit if no declarative security is present in the metadata */
13719         if (!method->klass->image->tables [MONO_TABLE_DECLSECURITY].rows)
13720                 return FALSE;
13721
13722         /* we want the original as the wrapper is "free" of the security informations */
13723         if (method->wrapper_type == MONO_WRAPPER_MANAGED_TO_NATIVE || method->wrapper_type == MONO_WRAPPER_MANAGED_TO_MANAGED) {
13724                 method = mono_marshal_method_from_wrapper (method);
13725                 if (!method)
13726                         return FALSE;
13727         }
13728
13729         /* First we look for method-level attributes */
13730         if (method->flags & METHOD_ATTRIBUTE_HAS_SECURITY) {
13731                 mono_class_init (method->klass);
13732                 memset (demands, 0, sizeof (MonoDeclSecurityActions));
13733
13734                 result = mono_declsec_get_method_demands_params (method, demands, 
13735                         SECURITY_ACTION_DEMAND, SECURITY_ACTION_NONCASDEMAND, SECURITY_ACTION_DEMANDCHOICE);
13736         }
13737
13738         /* Here we use (or create) the class declarative cache to look for demands */
13739         flags = mono_declsec_flags_from_class (method->klass);
13740         if (flags & mask) {
13741                 if (!result) {
13742                         mono_class_init (method->klass);
13743                         memset (demands, 0, sizeof (MonoDeclSecurityActions));
13744                 }
13745                 result |= mono_declsec_get_class_demands_params (method->klass, demands, 
13746                         SECURITY_ACTION_DEMAND, SECURITY_ACTION_NONCASDEMAND, SECURITY_ACTION_DEMANDCHOICE);
13747         }
13748
13749         /* The boolean return value is used as a shortcut in case nothing needs to
13750            be generated (e.g. LinkDemand[Choice] and InheritanceDemand[Choice]) */
13751         return result;
13752 }
13753
13754
13755 /*
13756  * Collect all Link actions: LinkDemand, NonCasLinkDemand and LinkDemandChoice (2.0).
13757  *
13758  * Note: Don't use the content of actions if the function return FALSE.
13759  */
13760 MonoBoolean
13761 mono_declsec_get_linkdemands (MonoMethod *method, MonoDeclSecurityActions* klass, MonoDeclSecurityActions *cmethod)
13762 {
13763         MonoBoolean result = FALSE;
13764         guint32 flags;
13765
13766         /* quick exit if no declarative security is present in the metadata */
13767         if (!method->klass->image->tables [MONO_TABLE_DECLSECURITY].rows)
13768                 return FALSE;
13769
13770         /* we want the original as the wrapper is "free" of the security informations */
13771         if (method->wrapper_type == MONO_WRAPPER_MANAGED_TO_NATIVE || method->wrapper_type == MONO_WRAPPER_MANAGED_TO_MANAGED) {
13772                 method = mono_marshal_method_from_wrapper (method);
13773                 if (!method)
13774                         return FALSE;
13775         }
13776
13777         /* results are independant - zeroize both */
13778         memset (cmethod, 0, sizeof (MonoDeclSecurityActions));
13779         memset (klass, 0, sizeof (MonoDeclSecurityActions));
13780
13781         /* First we look for method-level attributes */
13782         if (method->flags & METHOD_ATTRIBUTE_HAS_SECURITY) {
13783                 mono_class_init (method->klass);
13784
13785                 result = mono_declsec_get_method_demands_params (method, cmethod, 
13786                         SECURITY_ACTION_LINKDEMAND, SECURITY_ACTION_NONCASLINKDEMAND, SECURITY_ACTION_LINKDEMANDCHOICE);
13787         }
13788
13789         /* Here we use (or create) the class declarative cache to look for demands */
13790         flags = mono_declsec_flags_from_class (method->klass);
13791         if (flags & (MONO_DECLSEC_FLAG_LINKDEMAND | MONO_DECLSEC_FLAG_NONCAS_LINKDEMAND | MONO_DECLSEC_FLAG_LINKDEMAND_CHOICE)) {
13792                 mono_class_init (method->klass);
13793
13794                 result |= mono_declsec_get_class_demands_params (method->klass, klass, 
13795                         SECURITY_ACTION_LINKDEMAND, SECURITY_ACTION_NONCASLINKDEMAND, SECURITY_ACTION_LINKDEMANDCHOICE);
13796         }
13797
13798         return result;
13799 }
13800
13801 /*
13802  * Collect all Inherit actions: InheritanceDemand, NonCasInheritanceDemand and InheritanceDemandChoice (2.0).
13803  *
13804  * @klass       The inherited class - this is the class that provides the security check (attributes)
13805  * @demans      
13806  * return TRUE if inheritance demands (any kind) are present, FALSE otherwise.
13807  * 
13808  * Note: Don't use the content of actions if the function return FALSE.
13809  */
13810 MonoBoolean
13811 mono_declsec_get_inheritdemands_class (MonoClass *klass, MonoDeclSecurityActions* demands)
13812 {
13813         MonoBoolean result = FALSE;
13814         guint32 flags;
13815
13816         /* quick exit if no declarative security is present in the metadata */
13817         if (!klass->image->tables [MONO_TABLE_DECLSECURITY].rows)
13818                 return FALSE;
13819
13820         /* Here we use (or create) the class declarative cache to look for demands */
13821         flags = mono_declsec_flags_from_class (klass);
13822         if (flags & (MONO_DECLSEC_FLAG_INHERITANCEDEMAND | MONO_DECLSEC_FLAG_NONCAS_INHERITANCEDEMAND | MONO_DECLSEC_FLAG_INHERITANCEDEMAND_CHOICE)) {
13823                 mono_class_init (klass);
13824                 memset (demands, 0, sizeof (MonoDeclSecurityActions));
13825
13826                 result |= mono_declsec_get_class_demands_params (klass, demands, 
13827                         SECURITY_ACTION_INHERITDEMAND, SECURITY_ACTION_NONCASINHERITANCE, SECURITY_ACTION_INHERITDEMANDCHOICE);
13828         }
13829
13830         return result;
13831 }
13832
13833 /*
13834  * Collect all Inherit actions: InheritanceDemand, NonCasInheritanceDemand and InheritanceDemandChoice (2.0).
13835  *
13836  * Note: Don't use the content of actions if the function return FALSE.
13837  */
13838 MonoBoolean
13839 mono_declsec_get_inheritdemands_method (MonoMethod *method, MonoDeclSecurityActions* demands)
13840 {
13841         /* quick exit if no declarative security is present in the metadata */
13842         if (!method->klass->image->tables [MONO_TABLE_DECLSECURITY].rows)
13843                 return FALSE;
13844
13845         /* we want the original as the wrapper is "free" of the security informations */
13846         if (method->wrapper_type == MONO_WRAPPER_MANAGED_TO_NATIVE || method->wrapper_type == MONO_WRAPPER_MANAGED_TO_MANAGED) {
13847                 method = mono_marshal_method_from_wrapper (method);
13848                 if (!method)
13849                         return FALSE;
13850         }
13851
13852         if (method->flags & METHOD_ATTRIBUTE_HAS_SECURITY) {
13853                 mono_class_init (method->klass);
13854                 memset (demands, 0, sizeof (MonoDeclSecurityActions));
13855
13856                 return mono_declsec_get_method_demands_params (method, demands, 
13857                         SECURITY_ACTION_INHERITDEMAND, SECURITY_ACTION_NONCASINHERITANCE, SECURITY_ACTION_INHERITDEMANDCHOICE);
13858         }
13859         return FALSE;
13860 }
13861
13862
13863 static MonoBoolean
13864 get_declsec_action (MonoImage *image, guint32 token, guint32 action, MonoDeclSecurityEntry *entry)
13865 {
13866         guint32 cols [MONO_DECL_SECURITY_SIZE];
13867         MonoTableInfo *t;
13868         int i;
13869
13870         int index = mono_metadata_declsec_from_index (image, token);
13871         if (index == -1)
13872                 return FALSE;
13873
13874         t =  &image->tables [MONO_TABLE_DECLSECURITY];
13875         for (i = index; i < t->rows; i++) {
13876                 mono_metadata_decode_row (t, i, cols, MONO_DECL_SECURITY_SIZE);
13877
13878                 /* shortcut - index are ordered */
13879                 if (token != cols [MONO_DECL_SECURITY_PARENT])
13880                         return FALSE;
13881
13882                 if (cols [MONO_DECL_SECURITY_ACTION] == action) {
13883                         const char *metadata = mono_metadata_blob_heap (image, cols [MONO_DECL_SECURITY_PERMISSIONSET]);
13884                         entry->blob = (char*) (metadata + 2);
13885                         entry->size = mono_metadata_decode_blob_size (metadata, &metadata);
13886                         return TRUE;
13887                 }
13888         }
13889
13890         return FALSE;
13891 }
13892
13893 MonoBoolean
13894 mono_declsec_get_method_action (MonoMethod *method, guint32 action, MonoDeclSecurityEntry *entry)
13895 {
13896         if (method->flags & METHOD_ATTRIBUTE_HAS_SECURITY) {
13897                 guint32 idx = mono_method_get_index (method);
13898                 idx <<= MONO_HAS_DECL_SECURITY_BITS;
13899                 idx |= MONO_HAS_DECL_SECURITY_METHODDEF;
13900                 return get_declsec_action (method->klass->image, idx, action, entry);
13901         }
13902         return FALSE;
13903 }
13904
13905 MonoBoolean
13906 mono_declsec_get_class_action (MonoClass *klass, guint32 action, MonoDeclSecurityEntry *entry)
13907 {
13908         /* use cache */
13909         guint32 flags = mono_declsec_flags_from_class (klass);
13910         if (declsec_flags_map [action] & flags) {
13911                 guint32 idx = mono_metadata_token_index (klass->type_token);
13912                 idx <<= MONO_HAS_DECL_SECURITY_BITS;
13913                 idx |= MONO_HAS_DECL_SECURITY_TYPEDEF;
13914                 return get_declsec_action (klass->image, idx, action, entry);
13915         }
13916         return FALSE;
13917 }
13918
13919 MonoBoolean
13920 mono_declsec_get_assembly_action (MonoAssembly *assembly, guint32 action, MonoDeclSecurityEntry *entry)
13921 {
13922         guint32 idx = 1; /* there is only one assembly */
13923         idx <<= MONO_HAS_DECL_SECURITY_BITS;
13924         idx |= MONO_HAS_DECL_SECURITY_ASSEMBLY;
13925
13926         return get_declsec_action (assembly->image, idx, action, entry);
13927 }
13928
13929 gboolean
13930 mono_reflection_call_is_assignable_to (MonoClass *klass, MonoClass *oklass)
13931 {
13932         MonoError error;
13933         MonoObject *res, *exc;
13934         void *params [1];
13935         static MonoMethod *method = NULL;
13936
13937         if (method == NULL) {
13938                 method = mono_class_get_method_from_name (mono_class_get_type_builder_class (), "IsAssignableTo", 1);
13939                 g_assert (method);
13940         }
13941
13942         /* 
13943          * The result of mono_type_get_object_checked () might be a System.MonoType but we
13944          * need a TypeBuilder so use mono_class_get_ref_info (klass).
13945          */
13946         g_assert (mono_class_get_ref_info (klass));
13947         g_assert (!strcmp (((MonoObject*)(mono_class_get_ref_info (klass)))->vtable->klass->name, "TypeBuilder"));
13948
13949         params [0] = mono_type_get_object_checked (mono_domain_get (), &oklass->byval_arg, &error);
13950         mono_error_raise_exception (&error); /* FIXME don't raise here */
13951
13952         res = mono_runtime_try_invoke (method, (MonoObject*)(mono_class_get_ref_info (klass)), params, &exc, &error);
13953
13954         if (exc || !mono_error_ok (&error)) {
13955                 mono_error_cleanup (&error);
13956                 return FALSE;
13957         } else
13958                 return *(MonoBoolean*)mono_object_unbox (res);
13959 }
13960
13961 /**
13962  * mono_reflection_type_get_type:
13963  * @reftype: the System.Type object
13964  *
13965  * Returns the MonoType* associated with the C# System.Type object @reftype.
13966  */
13967 MonoType*
13968 mono_reflection_type_get_type (MonoReflectionType *reftype)
13969 {
13970         g_assert (reftype);
13971
13972         return mono_reflection_type_get_handle (reftype);
13973 }
13974
13975 /**
13976  * mono_reflection_assembly_get_assembly:
13977  * @refassembly: the System.Reflection.Assembly object
13978  *
13979  * Returns the MonoAssembly* associated with the C# System.Reflection.Assembly object @refassembly.
13980  */
13981 MonoAssembly*
13982 mono_reflection_assembly_get_assembly (MonoReflectionAssembly *refassembly)
13983 {
13984         g_assert (refassembly);
13985
13986         return refassembly->assembly;
13987 }
13988